From cd0477e8e397f0f4b14140a81e21778f660e8efc Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Wed, 23 Sep 2009 15:15:35 +0200 Subject: [PATCH 001/104] WL#5105, ptr_cmp optimised on Solaris, more efficient to use memcmp on Solaris than native impl. --- mysys/ptr_cmp.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/mysys/ptr_cmp.c b/mysys/ptr_cmp.c index 24ab6a1ea9c..9f053f0b3b4 100644 --- a/mysys/ptr_cmp.c +++ b/mysys/ptr_cmp.c @@ -22,16 +22,39 @@ #include "mysys_priv.h" #include +#ifdef UNIV_SOLARIS +/* + * On Solaris, memcmp() is normally faster than the unrolled ptr_compare_N + * functions, as memcmp() is usually a platform-specific implementation + * written in assembler, provided in /usr/lib/libc/libc_hwcap*.so.1. + * This implementation is also usually faster than the built-in memcmp + * supplied by GCC, so it is recommended to build with "-fno-builtin-memcmp" + * in CFLAGS if building with GCC on Solaris. + */ + +#include + +static int native_compare(size_t *length, unsigned char **a, unsigned char **b) +{ + return memcmp(*a, *b, *length); +} + +#else /* UNIV_SOLARIS */ + static int ptr_compare(size_t *compare_length, uchar **a, uchar **b); static int ptr_compare_0(size_t *compare_length, uchar **a, uchar **b); static int ptr_compare_1(size_t *compare_length, uchar **a, uchar **b); static int ptr_compare_2(size_t *compare_length, uchar **a, uchar **b); static int ptr_compare_3(size_t *compare_length, uchar **a, uchar **b); +#endif /* UNIV_SOLARIS */ /* Get a pointer to a optimal byte-compare function for a given size */ qsort2_cmp get_ptr_compare (size_t size) { +#ifdef UNIV_SOLARIS + return (qsort2_cmp) native_compare; +#else if (size < 4) return (qsort2_cmp) ptr_compare; switch (size & 3) { @@ -41,6 +64,7 @@ qsort2_cmp get_ptr_compare (size_t size) case 3: return (qsort2_cmp) ptr_compare_3; } return 0; /* Impossible */ +#endif /* UNIV_SOLARIS */ } From 6e4f01fa8b9adce822a9b40a7b4453ece6bf5fb7 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Fri, 9 Oct 2009 14:21:29 +0200 Subject: [PATCH 002/104] Moved atomics from 6.0 codebase to prepare for using atomic increments in places where LOCK_thread_count previously was used --- include/atomic/gcc_builtins.h | 10 +- include/atomic/generic-msvc.h | 116 ++++++++++++++ include/atomic/nolock.h | 49 +++--- include/atomic/solaris.h | 8 +- include/atomic/x86-gcc.h | 35 ++-- include/atomic/x86-msvc.h | 96 ----------- include/my_atomic.h | 289 +++++++++++++++++++++++++--------- 7 files changed, 394 insertions(+), 209 deletions(-) create mode 100644 include/atomic/generic-msvc.h delete mode 100644 include/atomic/x86-msvc.h diff --git a/include/atomic/gcc_builtins.h b/include/atomic/gcc_builtins.h index 509701b30a5..100ff80cacd 100644 --- a/include/atomic/gcc_builtins.h +++ b/include/atomic/gcc_builtins.h @@ -1,3 +1,6 @@ +#ifndef ATOMIC_GCC_BUILTINS_INCLUDED +#define ATOMIC_GCC_BUILTINS_INCLUDED + /* Copyright (C) 2008 MySQL AB This program is free software; you can redistribute it and/or modify @@ -15,7 +18,7 @@ #define make_atomic_add_body(S) \ v= __sync_fetch_and_add(a, v); -#define make_atomic_swap_body(S) \ +#define make_atomic_fas_body(S) \ v= __sync_lock_test_and_set(a, v); #define make_atomic_cas_body(S) \ int ## S sav; \ @@ -25,9 +28,14 @@ #ifdef MY_ATOMIC_MODE_DUMMY #define make_atomic_load_body(S) ret= *a #define make_atomic_store_body(S) *a= v +#define MY_ATOMIC_MODE "gcc-builtins-up" + #else +#define MY_ATOMIC_MODE "gcc-builtins-smp" #define make_atomic_load_body(S) \ ret= __sync_fetch_and_or(a, 0); #define make_atomic_store_body(S) \ (void) __sync_lock_test_and_set(a, v); #endif + +#endif /* ATOMIC_GCC_BUILTINS_INCLUDED */ diff --git a/include/atomic/generic-msvc.h b/include/atomic/generic-msvc.h new file mode 100644 index 00000000000..f1e1b0e88c9 --- /dev/null +++ b/include/atomic/generic-msvc.h @@ -0,0 +1,116 @@ +/* Copyright (C) 2006-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef _atomic_h_cleanup_ +#define _atomic_h_cleanup_ "atomic/generic-msvc.h" + +/* + We don't implement anything specific for MY_ATOMIC_MODE_DUMMY, always use + intrinsics. + 8 and 16-bit atomics are not implemented, but it can be done if necessary. +*/ +#undef MY_ATOMIC_HAS_8_16 + +/* + x86 compilers (both VS2003 or VS2005) never use instrinsics, but generate + function calls to kernel32 instead, even in the optimized build. + We force intrinsics as described in MSDN documentation for + _InterlockedCompareExchange. +*/ +#ifdef _M_IX86 + +#if (_MSC_VER >= 1500) +#include +#else +C_MODE_START +/*Visual Studio 2003 and earlier do not have prototypes for atomic intrinsics*/ +LONG _InterlockedExchange (LONG volatile *Target,LONG Value); +LONG _InterlockedCompareExchange (LONG volatile *Target, LONG Value, LONG Comp); +LONG _InterlockedExchangeAdd (LONG volatile *Addend, LONG Value); +C_MODE_END + +#pragma intrinsic(_InterlockedExchangeAdd) +#pragma intrinsic(_InterlockedCompareExchange) +#pragma intrinsic(_InterlockedExchange) +#endif + +#define InterlockedExchange _InterlockedExchange +#define InterlockedExchangeAdd _InterlockedExchangeAdd +#define InterlockedCompareExchange _InterlockedCompareExchange +/* + No need to do something special for InterlockedCompareExchangePointer + as it is a #define to InterlockedCompareExchange. The same applies to + InterlockedExchangePointer. +*/ +#endif /*_M_IX86*/ + +#define MY_ATOMIC_MODE "msvc-intrinsics" +#define IL_EXCHG_ADD32(X,Y) InterlockedExchangeAdd((volatile LONG *)(X),(Y)) +#define IL_COMP_EXCHG32(X,Y,Z) InterlockedCompareExchange((volatile LONG *)(X),(Y),(Z)) +#define IL_COMP_EXCHGptr InterlockedCompareExchangePointer +#define IL_EXCHG32(X,Y) InterlockedExchange((volatile LONG *)(X),(Y)) +#define IL_EXCHGptr InterlockedExchangePointer +#define make_atomic_add_body(S) \ + v= IL_EXCHG_ADD ## S (a, v) +#define make_atomic_cas_body(S) \ + int ## S initial_cmp= *cmp; \ + int ## S initial_a= IL_COMP_EXCHG ## S (a, set, initial_cmp); \ + if (!(ret= (initial_a == initial_cmp))) *cmp= initial_a; +#define make_atomic_swap_body(S) \ + v= IL_EXCHG ## S (a, v) +#define make_atomic_load_body(S) \ + ret= 0; /* avoid compiler warning */ \ + ret= IL_COMP_EXCHG ## S (a, ret, ret); + +/* + my_yield_processor (equivalent of x86 PAUSE instruction) should be used + to improve performance on hyperthreaded CPUs. Intel recommends to use it in + spin loops also on non-HT machines to reduce power consumption (see e.g + http://softwarecommunity.intel.com/articles/eng/2004.htm) + + Running benchmarks for spinlocks implemented with InterlockedCompareExchange + and YieldProcessor shows that much better performance is achieved by calling + YieldProcessor in a loop - that is, yielding longer. On Intel boxes setting + loop count in the range 200-300 brought best results. + */ +#ifndef YIELD_LOOPS +#define YIELD_LOOPS 200 +#endif + +static __inline int my_yield_processor() +{ + int i; + for(i=0; i Date: Fri, 9 Oct 2009 14:22:22 +0200 Subject: [PATCH 003/104] A minor change to MySQL's hash where calculation of hash can be done separately to avoid doing it under contended mutex locks --- include/hash.h | 9 +++++++++ mysys/hash.c | 29 +++++++++++++++++++++++++++-- sql/sql_base.cc | 9 +++++++-- 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/include/hash.h b/include/hash.h index 629b404e8a7..b6fc365ab76 100644 --- a/include/hash.h +++ b/include/hash.h @@ -45,6 +45,7 @@ extern "C" { #define hash_element my_hash_element #define hash_search my_hash_search #define hash_first my_hash_first +#define hash_first_from_hash_value my_hash_first_from_hash_value #define hash_next my_hash_next #define hash_insert my_hash_insert #define hash_delete my_hash_delete @@ -94,8 +95,16 @@ void my_hash_free(HASH *tree); void my_hash_reset(HASH *hash); uchar *my_hash_element(HASH *hash, ulong idx); uchar *my_hash_search(const HASH *info, const uchar *key, size_t length); +uchar *my_hash_search_using_hash_value(const HASH *info, uint hash_value, + const uchar *key, size_t length); +uint my_calc_hash(const HASH *info, const uchar *key, size_t length); uchar *my_hash_first(const HASH *info, const uchar *key, size_t length, HASH_SEARCH_STATE *state); +uchar *my_hash_first_from_hash_value(const HASH *info, + uint hash_value, + const uchar *key, + size_t length, + HASH_SEARCH_STATE *state); uchar *my_hash_next(const HASH *info, const uchar *key, size_t length, HASH_SEARCH_STATE *state); my_bool my_hash_insert(HASH *info, const uchar *data); diff --git a/mysys/hash.c b/mysys/hash.c index 63933abb085..367ac8713dd 100644 --- a/mysys/hash.c +++ b/mysys/hash.c @@ -214,6 +214,20 @@ uchar* my_hash_search(const HASH *hash, const uchar *key, size_t length) return my_hash_first(hash, key, length, &state); } +uchar* my_hash_search_using_hash_value(const HASH *hash, + uint hash_value, + const uchar *key, + size_t length) +{ + HASH_SEARCH_STATE state; + return my_hash_first_from_hash_value(hash, hash_value, + key, length, &state); +} + +uint my_calc_hash(const HASH *hash, const uchar *key, size_t length) +{ + return calc_hash(hash, key, length ? length : hash->key_length); +} /* Search after a record based on a key @@ -223,15 +237,26 @@ uchar* my_hash_search(const HASH *hash, const uchar *key, size_t length) uchar* my_hash_first(const HASH *hash, const uchar *key, size_t length, HASH_SEARCH_STATE *current_record) +{ + return my_hash_first_from_hash_value(hash, + calc_hash(hash, key, length ? length : hash->key_length), + key, length, current_record); +} + +uchar* my_hash_first_from_hash_value(const HASH *hash, + uint hash_value, + const uchar *key, + size_t length, + HASH_SEARCH_STATE *current_record) { HASH_LINK *pos; uint flag,idx; - DBUG_ENTER("my_hash_first"); + DBUG_ENTER("my_hash_first_from_hash_value"); flag=1; if (hash->records) { - idx= my_hash_mask(calc_hash(hash, key, length ? length : hash->key_length), + idx= my_hash_mask(hash_value, hash->blength, hash->records); do { diff --git a/sql/sql_base.cc b/sql/sql_base.cc index b81070000b3..064d277e0b4 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2513,6 +2513,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, char key[MAX_DBKEY_LENGTH]; uint key_length; char *alias= table_list->alias; + uint hash_value; HASH_SEARCH_STATE state; DBUG_ENTER("open_table"); @@ -2702,6 +2703,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, on disk. */ + hash_value= my_calc_hash(&open_cache, (uchar*) key, key_length); VOID(pthread_mutex_lock(&LOCK_open)); /* @@ -2744,8 +2746,11 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, an implicit "pending locks queue" - see wait_for_locked_table_names for details. */ - for (table= (TABLE*) hash_first(&open_cache, (uchar*) key, key_length, - &state); + for (table= (TABLE*) hash_first_from_hash_value(&open_cache, + hash_value, + (uchar*) key, + key_length, + &state); table && table->in_use ; table= (TABLE*) hash_next(&open_cache, (uchar*) key, key_length, &state)) From c4ce446f1925ecefdec6afac69416a8d80868091 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Mon, 12 Oct 2009 11:00:39 +0200 Subject: [PATCH 004/104] Backported my_atomic from 6.0-codebase and added support for 64-bit atomics to enable removal of LOCK_thread_count from every query, removed LOCK_thread_count from use in dispatch_command and close of query which is used in every query, now uses atomic increments/decrements instead --- include/Makefile.am | 2 +- include/atomic/rwlock.h | 31 ++++-- include/atomic/x86-gcc.h | 32 +++++- include/my_atomic.h | 12 ++- include/my_global.h | 2 + sql/event_scheduler.cc | 17 ++- sql/log_event.cc | 12 +-- sql/mysql_priv.h | 45 +++++++- sql/mysqld.cc | 6 +- sql/sp_head.cc | 4 +- sql/sql_parse.cc | 57 +++++----- unittest/mysys/my_atomic-t.c | 192 +++++++++++++++------------------- unittest/mysys/thr_template.c | 92 ++++++++++++++++ 13 files changed, 337 insertions(+), 167 deletions(-) create mode 100644 unittest/mysys/thr_template.c diff --git a/include/Makefile.am b/include/Makefile.am index dd6f53f7ca2..d698b1323b8 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -38,7 +38,7 @@ noinst_HEADERS = config-win.h config-netware.h my_bit.h \ thr_lock.h t_ctype.h violite.h my_md5.h base64.h \ my_handler.h my_time.h \ my_vle.h my_user.h my_atomic.h atomic/nolock.h \ - atomic/rwlock.h atomic/x86-gcc.h atomic/x86-msvc.h \ + atomic/rwlock.h atomic/x86-gcc.h atomic/generic-msvc.h \ atomic/solaris.h \ atomic/gcc_builtins.h my_libwrap.h my_stacktrace.h diff --git a/include/atomic/rwlock.h b/include/atomic/rwlock.h index 18b77e93d80..29e22fcb3d5 100644 --- a/include/atomic/rwlock.h +++ b/include/atomic/rwlock.h @@ -1,3 +1,6 @@ +#ifndef ATOMIC_RWLOCK_INCLUDED +#define ATOMIC_RWLOCK_INCLUDED + /* Copyright (C) 2006 MySQL AB This program is free software; you can redistribute it and/or modify @@ -13,7 +16,8 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -typedef struct {pthread_rwlock_t rw;} my_atomic_rwlock_t; +typedef struct {pthread_mutex_t rw;} my_atomic_rwlock_t; +#define MY_ATOMIC_MODE_RWLOCKS 1 #ifdef MY_ATOMIC_MODE_DUMMY /* @@ -31,18 +35,27 @@ typedef struct {pthread_rwlock_t rw;} my_atomic_rwlock_t; #define my_atomic_rwlock_wrunlock(name) #define MY_ATOMIC_MODE "dummy (non-atomic)" #else -#define my_atomic_rwlock_destroy(name) pthread_rwlock_destroy(& (name)->rw) -#define my_atomic_rwlock_init(name) pthread_rwlock_init(& (name)->rw, 0) -#define my_atomic_rwlock_rdlock(name) pthread_rwlock_rdlock(& (name)->rw) -#define my_atomic_rwlock_wrlock(name) pthread_rwlock_wrlock(& (name)->rw) -#define my_atomic_rwlock_rdunlock(name) pthread_rwlock_unlock(& (name)->rw) -#define my_atomic_rwlock_wrunlock(name) pthread_rwlock_unlock(& (name)->rw) -#define MY_ATOMIC_MODE "rwlocks" +/* + we're using read-write lock macros but map them to mutex locks, and they're + faster. Still, having semantically rich API we can change the + underlying implementation, if necessary. +*/ +#define my_atomic_rwlock_destroy(name) pthread_mutex_destroy(& (name)->rw) +#define my_atomic_rwlock_init(name) pthread_mutex_init(& (name)->rw, 0) +#define my_atomic_rwlock_rdlock(name) pthread_mutex_lock(& (name)->rw) +#define my_atomic_rwlock_wrlock(name) pthread_mutex_lock(& (name)->rw) +#define my_atomic_rwlock_rdunlock(name) pthread_mutex_unlock(& (name)->rw) +#define my_atomic_rwlock_wrunlock(name) pthread_mutex_unlock(& (name)->rw) +#define MY_ATOMIC_MODE "mutex" +#ifndef MY_ATOMIC_MODE_RWLOCKS +#define MY_ATOMIC_MODE_RWLOCKS 1 +#endif #endif #define make_atomic_add_body(S) int ## S sav; sav= *a; *a+= v; v=sav; -#define make_atomic_swap_body(S) int ## S sav; sav= *a; *a= v; v=sav; +#define make_atomic_fas_body(S) int ## S sav; sav= *a; *a= v; v=sav; #define make_atomic_cas_body(S) if ((ret= (*a == *cmp))) *a= set; else *cmp=*a; #define make_atomic_load_body(S) ret= *a; #define make_atomic_store_body(S) *a= v; +#endif /* ATOMIC_RWLOCK_INCLUDED */ diff --git a/include/atomic/x86-gcc.h b/include/atomic/x86-gcc.h index c11483b4083..ba7e7eb572f 100644 --- a/include/atomic/x86-gcc.h +++ b/include/atomic/x86-gcc.h @@ -42,15 +42,37 @@ #endif #ifndef MY_ATOMIC_NO_XADD -#define make_atomic_add_body(S) \ - asm volatile (LOCK_prefix "; xadd %0, %1;" : "+r" (v) , "+m" (*a)) +#define make_atomic_add_body(S) make_atomic_add_body ## S +#define make_atomic_cas_body(S) make_atomic_cas_body ## S #endif -#define make_atomic_fas_body(S) \ - asm volatile ("xchg %0, %1;" : "+q" (v) , "+m" (*a)) -#define make_atomic_cas_body(S) \ + +#define make_atomic_add_body32 \ + asm volatile (LOCK_prefix "; xadd %0, %1;" : "+r" (v) , "+m" (*a)) + +#define make_atomic_cas_body32 \ asm volatile (LOCK_prefix "; cmpxchg %3, %0; setz %2;" \ : "+m" (*a), "+a" (*cmp), "=q" (ret): "r" (set)) +#define make_atomic_cas_bodyptr make_atomic_cas_body32 + +#ifndef __x86_64__ +#define make_atomic_add_body64 make_atomic_add_body32 +#define make_atomic_cas_body64 make_atomic_cas_body32 +#else +#define make_atomic_add_body64 \ + int64 tmp=*a; \ + while (!my_atomic_cas64(a, &tmp, tmp+v)); \ + v=tmp; +#define make_atomic_cas_body64 \ + int32 ebx=(set & 0xFFFFFFFF), ecx=(set >> 32); \ + asm volatile (LOCK_prefix "; cmpxchg8b %0; setz %2;" \ + : "+m" (*a), "+A" (*cmp), "=q" (ret) \ + :"b" (ebx), "c" (ecx)) +#endif + +#define make_atomic_fas_body(S) \ + asm volatile ("xchg %0, %1;" : "+r" (v) , "+m" (*a)) + #ifdef MY_ATOMIC_MODE_DUMMY #define make_atomic_load_body(S) ret=*a #define make_atomic_store_body(S) *a=v diff --git a/include/my_atomic.h b/include/my_atomic.h index f62d3e32b42..4170e45fe8c 100644 --- a/include/my_atomic.h +++ b/include/my_atomic.h @@ -37,7 +37,7 @@ my_atomic_store#(&var, what) store 'what' in *var - '#' is substituted by a size suffix - 8, 16, 32, or ptr + '#' is substituted by a size suffix - 8, 16, 32, 64, or ptr (e.g. my_atomic_add8, my_atomic_fas32, my_atomic_casptr). NOTE This operations are not always atomic, so they always must be @@ -129,6 +129,7 @@ make_transparent_unions(8) make_transparent_unions(16) make_transparent_unions(32) +make_transparent_unions(64) make_transparent_unions(ptr) #undef uintptr #undef make_transparent_unions @@ -140,10 +141,12 @@ make_transparent_unions(ptr) #define U_8 int8 #define U_16 int16 #define U_32 int32 +#define U_64 int64 #define U_ptr intptr #define Uv_8 int8 #define Uv_16 int16 #define Uv_32 int32 +#define Uv_64 int64 #define Uv_ptr intptr #define U_a volatile *a #define U_cmp *cmp @@ -217,6 +220,7 @@ make_atomic_cas(8) make_atomic_cas(16) #endif make_atomic_cas(32) +make_atomic_cas(64) make_atomic_cas(ptr) #ifdef MY_ATOMIC_HAS_8_16 @@ -224,12 +228,14 @@ make_atomic_add(8) make_atomic_add(16) #endif make_atomic_add(32) +make_atomic_add(64) #ifdef MY_ATOMIC_HAS_8_16 make_atomic_load(8) make_atomic_load(16) #endif make_atomic_load(32) +make_atomic_load(64) make_atomic_load(ptr) #ifdef MY_ATOMIC_HAS_8_16 @@ -237,6 +243,7 @@ make_atomic_fas(8) make_atomic_fas(16) #endif make_atomic_fas(32) +make_atomic_fas(64) make_atomic_fas(ptr) #ifdef MY_ATOMIC_HAS_8_16 @@ -244,6 +251,7 @@ make_atomic_store(8) make_atomic_store(16) #endif make_atomic_store(32) +make_atomic_store(64) make_atomic_store(ptr) #ifdef _atomic_h_cleanup_ @@ -254,10 +262,12 @@ make_atomic_store(ptr) #undef U_8 #undef U_16 #undef U_32 +#undef U_64 #undef U_ptr #undef Uv_8 #undef Uv_16 #undef Uv_32 +#undef Uv_64 #undef Uv_ptr #undef a #undef cmp diff --git a/include/my_global.h b/include/my_global.h index 4ad851e9e5d..25d3a9e461b 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -832,6 +832,8 @@ typedef SOCKET_SIZE_TYPE size_socket; #endif #endif /* defined (HAVE_LONG_LONG) && !defined(ULONGLONG_MAX)*/ +#define INT_MIN64 (~0x7FFFFFFFFFFFFFFFLL) +#define INT_MAX64 0x7FFFFFFFFFFFFFFFLL #define INT_MIN32 (~0x7FFFFFFFL) #define INT_MAX32 0x7FFFFFFFL #define UINT_MAX32 0xFFFFFFFFL diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc index 8c0025f9ed4..9c825078370 100644 --- a/sql/event_scheduler.cc +++ b/sql/event_scheduler.cc @@ -132,9 +132,10 @@ post_init_event_thread(THD *thd) pthread_mutex_lock(&LOCK_thread_count); threads.append(thd); thread_count++; - thread_running++; pthread_mutex_unlock(&LOCK_thread_count); - + my_atomic_rwlock_wrlock(&global_query_id_lock); + inc_thread_running(); + my_atomic_rwlock_wrunlock(&global_query_id_lock); return FALSE; } @@ -156,10 +157,12 @@ deinit_event_thread(THD *thd) DBUG_PRINT("exit", ("Event thread finishing")); pthread_mutex_lock(&LOCK_thread_count); thread_count--; - thread_running--; delete thd; pthread_cond_broadcast(&COND_thread_count); pthread_mutex_unlock(&LOCK_thread_count); + my_atomic_rwlock_wrlock(&global_query_id_lock); + dec_thread_running(); + my_atomic_rwlock_wrunlock(&global_query_id_lock); } @@ -417,10 +420,12 @@ Event_scheduler::start() net_end(&new_thd->net); pthread_mutex_lock(&LOCK_thread_count); thread_count--; - thread_running--; delete new_thd; pthread_cond_broadcast(&COND_thread_count); pthread_mutex_unlock(&LOCK_thread_count); + my_atomic_rwlock_wrlock(&global_query_id_lock); + dec_thread_running(); + my_atomic_rwlock_wrunlock(&global_query_id_lock); } end: UNLOCK_DATA(); @@ -550,10 +555,12 @@ error: net_end(&new_thd->net); pthread_mutex_lock(&LOCK_thread_count); thread_count--; - thread_running--; delete new_thd; pthread_cond_broadcast(&COND_thread_count); pthread_mutex_unlock(&LOCK_thread_count); + my_atomic_rwlock_wrlock(&global_query_id_lock); + dec_thread_running(); + my_atomic_rwlock_wrunlock(&global_query_id_lock); } delete event_name; DBUG_RETURN(TRUE); diff --git a/sql/log_event.cc b/sql/log_event.cc index e7cbbaba38e..5b286d94c0b 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -3026,9 +3026,9 @@ int Query_log_event::do_apply_event(Relay_log_info const *rli, { thd->set_time((time_t)when); thd->set_query((char*)query_arg, q_len_arg); - VOID(pthread_mutex_lock(&LOCK_thread_count)); + my_atomic_rwlock_wrlock(&global_query_id_lock); thd->query_id = next_query_id(); - VOID(pthread_mutex_unlock(&LOCK_thread_count)); + my_atomic_rwlock_wrunlock(&global_query_id_lock); thd->variables.pseudo_thread_id= thread_id; // for temp tables DBUG_PRINT("query",("%s",thd->query)); @@ -4504,9 +4504,9 @@ int Load_log_event::do_apply_event(NET* net, Relay_log_info const *rli, if (rpl_filter->db_ok(thd->db)) { thd->set_time((time_t)when); - VOID(pthread_mutex_lock(&LOCK_thread_count)); + my_atomic_rwlock_wrlock(&global_query_id_lock); thd->query_id = next_query_id(); - VOID(pthread_mutex_unlock(&LOCK_thread_count)); + my_atomic_rwlock_wrunlock(&global_query_id_lock); /* Initing thd->row_count is not necessary in theory as this variable has no influence in the case of the slave SQL thread (it is used to generate a @@ -8025,9 +8025,9 @@ int Table_map_log_event::do_apply_event(Relay_log_info const *rli) DBUG_ASSERT(rli->sql_thd == thd); /* Step the query id to mark what columns that are actually used. */ - pthread_mutex_lock(&LOCK_thread_count); + my_atomic_rwlock_wrlock(&global_query_id_lock); thd->query_id= next_query_id(); - pthread_mutex_unlock(&LOCK_thread_count); + my_atomic_rwlock_wrunlock(&global_query_id_lock); if (!(memory= my_multi_malloc(MYF(MY_WME), &table_list, (uint) sizeof(RPL_TABLE_LIST), diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index cd1a31f0fab..ff6d3578406 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -43,6 +43,7 @@ #include "sql_array.h" #include "sql_plugin.h" #include "scheduler.h" +#include class Parser_state; @@ -75,11 +76,49 @@ typedef ulong nesting_map; /* Used for flags of nesting constructs */ typedef ulonglong nested_join_map; /* query_id */ -typedef ulonglong query_id_t; +typedef int64 query_id_t; extern query_id_t global_query_id; +extern int32 thread_running; +extern my_atomic_rwlock_t global_query_id_lock; /* increment query_id and return it. */ -inline query_id_t next_query_id() { return global_query_id++; } +inline query_id_t next_query_id() +{ + query_id_t id; + id= my_atomic_add64(&global_query_id, 1); + return (id+1); +} + +inline query_id_t get_query_id() +{ + query_id_t id; + id= my_atomic_load64(&global_query_id); + return id; +} + +inline int32 +inc_thread_running() +{ + int32 num_thread_running; + num_thread_running= my_atomic_add32(&thread_running, 1); + return (num_thread_running+1); +} + +inline int32 +dec_thread_running() +{ + int32 num_thread_running; + num_thread_running= my_atomic_add32(&thread_running, -1); + return (num_thread_running-1); +} + +inline int32 +get_thread_running() +{ + int32 num_thread_running; + num_thread_running= my_atomic_load32(&thread_running); + return num_thread_running; +} /* useful constants */ extern MYSQL_PLUGIN_IMPORT const key_map key_map_empty; @@ -1994,7 +2033,7 @@ extern bool opt_ignore_builtin_innodb; extern my_bool opt_character_set_client_handshake; extern bool volatile abort_loop, shutdown_in_progress; extern bool in_bootstrap; -extern uint volatile thread_count, thread_running, global_read_lock; +extern uint volatile thread_count, global_read_lock; extern uint connection_count; extern my_bool opt_sql_bin_update, opt_safe_user_create, opt_no_mix_types; extern my_bool opt_safe_show_db, opt_local_infile, opt_myisam_use_mmap; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 5dad29a1ab7..1389f0b32f4 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -523,7 +523,8 @@ uint mysqld_port_timeout; uint delay_key_write_options, protocol_version; uint lower_case_table_names; uint tc_heuristic_recover= 0; -uint volatile thread_count, thread_running; +uint volatile thread_count; +int32 thread_running; ulonglong thd_startup_options; ulong back_log, connect_timeout, concurrency, server_id; ulong table_cache_size, table_def_size; @@ -539,6 +540,7 @@ ulonglong max_binlog_cache_size=0; ulong query_cache_size=0; ulong refresh_version; /* Increments on each reload */ query_id_t global_query_id; +my_atomic_rwlock_t global_query_id_lock; ulong aborted_threads, aborted_connects; ulong delayed_insert_timeout, delayed_insert_limit, delayed_queue_size; ulong delayed_insert_threads, delayed_insert_writes, delayed_rows_in_use; @@ -1349,6 +1351,7 @@ void clean_up(bool print_message) DBUG_PRINT("quit", ("Error messages freed")); /* Tell main we are ready */ logger.cleanup_end(); + my_atomic_rwlock_destroy(&global_query_id_lock); (void) pthread_mutex_lock(&LOCK_thread_count); DBUG_PRINT("quit", ("got thread count lock")); ready_to_exit=1; @@ -7730,6 +7733,7 @@ static int mysql_init_variables(void) what_to_log= ~ (1L << (uint) COM_TIME); refresh_version= 1L; /* Increments on each reload */ global_query_id= thread_id= 1L; + my_atomic_rwlock_init(&global_query_id_lock); strmov(server_version, MYSQL_SERVER_VERSION); myisam_recover_options_str= sql_mode_str= "OFF"; myisam_stats_method_str= "nulls_unequal"; diff --git a/sql/sp_head.cc b/sql/sp_head.cc index aed19b76011..83f886a2fdb 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -2702,9 +2702,9 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp, */ thd->lex= m_lex; - VOID(pthread_mutex_lock(&LOCK_thread_count)); + my_atomic_rwlock_wrlock(&global_query_id_lock); thd->query_id= next_query_id(); - VOID(pthread_mutex_unlock(&LOCK_thread_count)); + my_atomic_rwlock_wrunlock(&global_query_id_lock); if (thd->prelocked_mode == NON_PRELOCKED) { diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index a09fed98d65..b0dcc9aff13 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -505,7 +505,9 @@ pthread_handler_t handle_bootstrap(void *arg) We don't need to obtain LOCK_thread_count here because in bootstrap mode we have only one thread. */ + my_atomic_rwlock_wrlock(&global_query_id_lock); thd->query_id=next_query_id(); + my_atomic_rwlock_wrunlock(&global_query_id_lock); thd->set_time(); mysql_parse(thd, thd->query, length, & found_semicolon); close_thread_tables(thd); // Free tables @@ -971,29 +973,30 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thd->enable_slow_log= TRUE; thd->lex->sql_command= SQLCOM_END; /* to avoid confusing VIEW detectors */ thd->set_time(); - VOID(pthread_mutex_lock(&LOCK_thread_count)); - thd->query_id= global_query_id; - - switch( command ) { - /* Ignore these statements. */ - case COM_STATISTICS: - case COM_PING: - break; - /* Only increase id on these statements but don't count them. */ - case COM_STMT_PREPARE: - case COM_STMT_CLOSE: - case COM_STMT_RESET: - next_query_id(); - break; - /* Increase id and count all other statements. */ - default: - statistic_increment(thd->status_var.questions, &LOCK_status); - next_query_id(); + my_atomic_rwlock_wrlock(&global_query_id_lock); + { + query_id_t query_id; + switch( command ) { + /* Ignore these statements. */ + case COM_STATISTICS: + case COM_PING: + query_id= get_query_id(); + break; + /* Only increase id on these statements but don't count them. */ + case COM_STMT_PREPARE: + case COM_STMT_CLOSE: + case COM_STMT_RESET: + query_id= next_query_id() - 1; + break; + /* Increase id and count all other statements. */ + default: + statistic_increment(thd->status_var.questions, &LOCK_status); + query_id= next_query_id() - 1; + } + thd->query_id= query_id; } - - thread_running++; - /* TODO: set thd->lex->sql_command to SQLCOM_END here */ - VOID(pthread_mutex_unlock(&LOCK_thread_count)); + inc_thread_running(); + my_atomic_rwlock_wrunlock(&global_query_id_lock); /** Clear the set of flags that are expected to be cleared at the @@ -1259,15 +1262,15 @@ bool dispatch_command(enum enum_server_command command, THD *thd, (char *) thd->security_ctx->host_or_ip); thd->set_query(beginning_of_next_stmt, length); - VOID(pthread_mutex_lock(&LOCK_thread_count)); /* Count each statement from the client. */ statistic_increment(thd->status_var.questions, &LOCK_status); + my_atomic_rwlock_wrlock(&global_query_id_lock); thd->query_id= next_query_id(); + my_atomic_rwlock_wrunlock(&global_query_id_lock); thd->set_time(); /* Reset the query start time. */ /* TODO: set thd->lex->sql_command to SQLCOM_END here */ - VOID(pthread_mutex_unlock(&LOCK_thread_count)); mysql_parse(thd, beginning_of_next_stmt, length, &end_of_stmt); } @@ -1610,9 +1613,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thd_proc_info(thd, "cleaning up"); thd->set_query(NULL, 0); thd->command=COM_SLEEP; - VOID(pthread_mutex_lock(&LOCK_thread_count)); // For process list - thread_running--; - VOID(pthread_mutex_unlock(&LOCK_thread_count)); + my_atomic_rwlock_wrlock(&global_query_id_lock); + dec_thread_running(); + my_atomic_rwlock_wrunlock(&global_query_id_lock); thd_proc_info(thd, 0); thd->packet.shrink(thd->variables.net_buffer_length); // Reclaim some memory free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC)); diff --git a/unittest/mysys/my_atomic-t.c b/unittest/mysys/my_atomic-t.c index f2bcd360508..9853d3cf964 100644 --- a/unittest/mysys/my_atomic-t.c +++ b/unittest/mysys/my_atomic-t.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 MySQL AB +/* Copyright (C) 2006-2008 MySQL AB, 2008 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -13,10 +13,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include -#include -#include -#include +#include "thr_template.c" /* at least gcc 3.4.5 and 3.4.6 (but not 3.2.3) on RHEL */ #if __GNUC__ == 3 && __GNUC_MINOR__ == 4 @@ -25,181 +22,162 @@ #define GCC_BUG_WORKAROUND #endif -int32 a32,b32,c32; +volatile uint32 b32; +volatile int32 c32; my_atomic_rwlock_t rwl; -pthread_attr_t thr_attr; -pthread_mutex_t mutex; -pthread_cond_t cond; -int N; - /* add and sub a random number in a loop. Must get 0 at the end */ -pthread_handler_t test_atomic_add_handler(void *arg) +pthread_handler_t test_atomic_add(void *arg) { - int m=*(int *)arg; + int m= (*(int *)arg)/2; GCC_BUG_WORKAROUND int32 x; - for (x=((int)((long)(&m))); m ; m--) + for (x= ((int)(intptr)(&m)); m ; m--) { - x=x*m+0x87654321; + x= (x*m+0x87654321) & INT_MAX32; my_atomic_rwlock_wrlock(&rwl); - my_atomic_add32(&a32, x); + my_atomic_add32(&bad, x); my_atomic_rwlock_wrunlock(&rwl); my_atomic_rwlock_wrlock(&rwl); - my_atomic_add32(&a32, -x); + my_atomic_add32(&bad, -x); my_atomic_rwlock_wrunlock(&rwl); } pthread_mutex_lock(&mutex); - N--; - if (!N) pthread_cond_signal(&cond); + if (!--running_threads) pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex); return 0; } +volatile int64 a64; +/* add and sub a random number in a loop. Must get 0 at the end */ +pthread_handler_t test_atomic_add64(void *arg) +{ + int m= (*(int *)arg)/2; + GCC_BUG_WORKAROUND int64 x; + for (x= ((int64)(intptr)(&m)); m ; m--) + { + x= (x*m+0xfdecba987654321LL) & INT_MAX64; + my_atomic_rwlock_wrlock(&rwl); + my_atomic_add64(&a64, x); + my_atomic_rwlock_wrunlock(&rwl); + + my_atomic_rwlock_wrlock(&rwl); + my_atomic_add64(&a64, -x); + my_atomic_rwlock_wrunlock(&rwl); + } + pthread_mutex_lock(&mutex); + if (!--running_threads) + { + bad= (a64 != 0); + pthread_cond_signal(&cond); + } + pthread_mutex_unlock(&mutex); + return 0; +} + + /* 1. generate thread number 0..N-1 from b32 - 2. add it to a32 + 2. add it to bad 3. swap thread numbers in c32 4. (optionally) one more swap to avoid 0 as a result - 5. subtract result from a32 - must get 0 in a32 at the end + 5. subtract result from bad + must get 0 in bad at the end */ -pthread_handler_t test_atomic_swap_handler(void *arg) +pthread_handler_t test_atomic_fas(void *arg) { - int m=*(int *)arg; - int32 x; + int m= *(int *)arg; + int32 x; my_atomic_rwlock_wrlock(&rwl); - x=my_atomic_add32(&b32, 1); + x= my_atomic_add32(&b32, 1); my_atomic_rwlock_wrunlock(&rwl); my_atomic_rwlock_wrlock(&rwl); - my_atomic_add32(&a32, x); + my_atomic_add32(&bad, x); my_atomic_rwlock_wrunlock(&rwl); for (; m ; m--) { my_atomic_rwlock_wrlock(&rwl); - x=my_atomic_swap32(&c32, x); + x= my_atomic_fas32(&c32, x); my_atomic_rwlock_wrunlock(&rwl); } if (!x) { my_atomic_rwlock_wrlock(&rwl); - x=my_atomic_swap32(&c32, x); + x= my_atomic_fas32(&c32, x); my_atomic_rwlock_wrunlock(&rwl); } my_atomic_rwlock_wrlock(&rwl); - my_atomic_add32(&a32, -x); + my_atomic_add32(&bad, -x); my_atomic_rwlock_wrunlock(&rwl); pthread_mutex_lock(&mutex); - N--; - if (!N) pthread_cond_signal(&cond); + if (!--running_threads) pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex); return 0; } /* - same as test_atomic_add_handler, but my_atomic_add32 is emulated with - (slower) my_atomic_cas32 + same as test_atomic_add, but my_atomic_add32 is emulated with + my_atomic_cas32 - notice that the slowdown is proportional to the + number of CPUs */ -pthread_handler_t test_atomic_cas_handler(void *arg) +pthread_handler_t test_atomic_cas(void *arg) { - int m=*(int *)arg, ok; - GCC_BUG_WORKAROUND int32 x,y; - for (x=((int)((long)(&m))); m ; m--) + int m= (*(int *)arg)/2, ok= 0; + GCC_BUG_WORKAROUND int32 x, y; + for (x= ((int)(intptr)(&m)); m ; m--) { my_atomic_rwlock_wrlock(&rwl); - y=my_atomic_load32(&a32); + y= my_atomic_load32(&bad); my_atomic_rwlock_wrunlock(&rwl); - - x=x*m+0x87654321; + x= (x*m+0x87654321) & INT_MAX32; do { my_atomic_rwlock_wrlock(&rwl); - ok=my_atomic_cas32(&a32, &y, y+x); + ok= my_atomic_cas32(&bad, &y, (uint32)y+x); my_atomic_rwlock_wrunlock(&rwl); - } while (!ok); + } while (!ok) ; do { my_atomic_rwlock_wrlock(&rwl); - ok=my_atomic_cas32(&a32, &y, y-x); + ok= my_atomic_cas32(&bad, &y, y-x); my_atomic_rwlock_wrunlock(&rwl); - } while (!ok); + } while (!ok) ; } pthread_mutex_lock(&mutex); - N--; - if (!N) pthread_cond_signal(&cond); + if (!--running_threads) pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex); return 0; } -void test_atomic(const char *test, pthread_handler handler, int n, int m) + +void do_tests() { - pthread_t t; - ulonglong now=my_getsystime(); + plan(6); - a32= 0; - b32= 0; - c32= 0; + bad= my_atomic_initialize(); + ok(!bad, "my_atomic_initialize() returned %d", bad); - diag("Testing %s with %d threads, %d iterations... ", test, n, m); - for (N=n ; n ; n--) - { - if (pthread_create(&t, &thr_attr, handler, &m) != 0) - { - diag("Could not create thread"); - a32= 1; - goto err; - } - } - - pthread_mutex_lock(&mutex); - while (N) - pthread_cond_wait(&cond, &mutex); - pthread_mutex_unlock(&mutex); - now=my_getsystime()-now; -err: - ok(a32 == 0, "tested %s in %g secs", test, ((double)now)/1e7); -} - -int main() -{ - int err; - MY_INIT("my_atomic-t.c"); - - diag("N CPUs: %d", my_getncpus()); - err= my_atomic_initialize(); - - plan(4); - ok(err == 0, "my_atomic_initialize() returned %d", err); - - pthread_attr_init(&thr_attr); - pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED); - pthread_mutex_init(&mutex, 0); - pthread_cond_init(&cond, 0); my_atomic_rwlock_init(&rwl); -#ifdef HPUX11 -#define CYCLES 1000 -#else -#define CYCLES 10000 -#endif -#define THREADS 100 - test_atomic("my_atomic_add32", test_atomic_add_handler, THREADS, CYCLES); - test_atomic("my_atomic_swap32", test_atomic_swap_handler, THREADS, CYCLES); - test_atomic("my_atomic_cas32", test_atomic_cas_handler, THREADS, CYCLES); - /* - workaround until we know why it crashes randomly on some machine - (BUG#22320). - */ - sleep(2); + b32= c32= 0; + test_concurrently("my_atomic_add32", test_atomic_add, THREADS, CYCLES); + b32= c32= 0; + test_concurrently("my_atomic_fas32", test_atomic_fas, THREADS, CYCLES); + b32= c32= 0; + test_concurrently("my_atomic_cas32", test_atomic_cas, THREADS, CYCLES); + + { + int64 b=0x1000200030004000LL; + a64=0; + my_atomic_add64(&a64, b); + ok(a64==b, "add64"); + } + a64=0; + test_concurrently("my_atomic_add64", test_atomic_add64, THREADS, CYCLES); - pthread_mutex_destroy(&mutex); - pthread_cond_destroy(&cond); - pthread_attr_destroy(&thr_attr); my_atomic_rwlock_destroy(&rwl); - return exit_status(); } - diff --git a/unittest/mysys/thr_template.c b/unittest/mysys/thr_template.c new file mode 100644 index 00000000000..1ac03e474fd --- /dev/null +++ b/unittest/mysys/thr_template.c @@ -0,0 +1,92 @@ +/* Copyright (C) 2006-2008 MySQL AB, 2008 Sun Microsystems, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include +#include +#include +#include + +volatile uint32 bad; +pthread_attr_t thr_attr; +pthread_mutex_t mutex; +pthread_cond_t cond; +uint running_threads; + +void do_tests(); + +void test_concurrently(const char *test, pthread_handler handler, int n, int m) +{ + pthread_t t; + ulonglong now= my_getsystime(); + + bad= 0; + + diag("Testing %s with %d threads, %d iterations... ", test, n, m); + for (running_threads= n ; n ; n--) + { + if (pthread_create(&t, &thr_attr, handler, &m) != 0) + { + diag("Could not create thread"); + abort(); + } + } + pthread_mutex_lock(&mutex); + while (running_threads) + pthread_cond_wait(&cond, &mutex); + pthread_mutex_unlock(&mutex); + + now= my_getsystime()-now; + ok(!bad, "tested %s in %g secs (%d)", test, ((double)now)/1e7, bad); +} + +int main(int argc __attribute__((unused)), char **argv) +{ + MY_INIT("thd_template"); + + if (argv[1] && *argv[1]) + DBUG_SET_INITIAL(argv[1]); + + pthread_mutex_init(&mutex, 0); + pthread_cond_init(&cond, 0); + pthread_attr_init(&thr_attr); + pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED); + +#ifdef MY_ATOMIC_MODE_RWLOCKS +#if defined(HPUX11) || defined(__POWERPC__) /* showed to be very slow (scheduler-related) */ +#define CYCLES 300 +#else +#define CYCLES 3000 +#endif +#else +#define CYCLES 3000 +#endif +#define THREADS 30 + + diag("N CPUs: %d, atomic ops: %s", my_getncpus(), MY_ATOMIC_MODE); + + do_tests(); + + /* + workaround until we know why it crashes randomly on some machine + (BUG#22320). + */ + sleep(2); + pthread_mutex_destroy(&mutex); + pthread_cond_destroy(&cond); + pthread_attr_destroy(&thr_attr); + my_end(0); + return exit_status(); +} + From 018b63c55cb10cbb2c79a0ca8f9e9c677285becb Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Thu, 15 Oct 2009 15:03:43 +0200 Subject: [PATCH 005/104] Bug fixes to my_atomic infrastructure --- unittest/mysys/Makefile.am | 2 ++ 1 file changed, 2 insertions(+) diff --git a/unittest/mysys/Makefile.am b/unittest/mysys/Makefile.am index be91ef31c9d..118643bb061 100644 --- a/unittest/mysys/Makefile.am +++ b/unittest/mysys/Makefile.am @@ -16,6 +16,8 @@ AM_CPPFLAGS = @ZLIB_INCLUDES@ -I$(top_builddir)/include AM_CPPFLAGS += -I$(top_srcdir)/include -I$(top_srcdir)/unittest/mytap +noinst_HEADERS = thr_template.c + LDADD = $(top_builddir)/unittest/mytap/libmytap.a \ $(top_builddir)/mysys/libmysys.a \ $(top_builddir)/dbug/libdbug.a \ From c8df6e8d4b8e7d006cd53393ba14fbd141244c6c Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Mon, 9 Nov 2009 17:36:13 +0000 Subject: [PATCH 006/104] BUG#48357: SHOW BINLOG EVENTS: Wrong offset or I/O error In function log_event.cc:Query_log_event::write, there was a cast that was triggering undefined behavior. The offending cast is the following: write_str_with_code_and_len((char **)(&start), catalog, catalog_len, Q_CATALOG_NZ_CODE); This results in calling write_str_with_code_and_len with first argument pointing to a (char **) while "start" is itself a pointer to uchar (uchar *). Inside write_str_with_..., the content of start is then be updated: (*dst)+= len; The instruction above would cause the (*dst) pointer (ie, the "start" argument, from the caller point of view, and which actually points to uchar instead of pointing to char) to be updated so that it would increment catalog_len. However, this seems to break strict-aliasing rules ultimately causing the increment and assignment to behave unexpectedly. We fix this by removing the cast and by making the types match. --- sql/log_event.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sql/log_event.cc b/sql/log_event.cc index 2cb253c9c56..9a3c6537b9e 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -2138,8 +2138,8 @@ void Query_log_event::pack_info(Protocol *protocol) /** Utility function for the next method (Query_log_event::write()) . */ -static void write_str_with_code_and_len(char **dst, const char *src, - int len, uint code) +static void write_str_with_code_and_len(uchar **dst, const char *src, + uint len, uint code) { /* only 1 byte to store the length of catalog, so it should not @@ -2234,7 +2234,7 @@ bool Query_log_event::write(IO_CACHE* file) } if (catalog_len) // i.e. this var is inited (false for 4.0 events) { - write_str_with_code_and_len((char **)(&start), + write_str_with_code_and_len(&start, catalog, catalog_len, Q_CATALOG_NZ_CODE); /* In 5.0.x where x<4 masters we used to store the end zero here. This was @@ -2272,7 +2272,7 @@ bool Query_log_event::write(IO_CACHE* file) { /* In the TZ sys table, column Name is of length 64 so this should be ok */ DBUG_ASSERT(time_zone_len <= MAX_TIME_ZONE_NAME_LENGTH); - write_str_with_code_and_len((char **)(&start), + write_str_with_code_and_len(&start, time_zone_str, time_zone_len, Q_TIME_ZONE_CODE); } if (lc_time_names_number) From 1edf7e71fe4646cb3dac948d0ab2df10fd296a3d Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Tue, 10 Nov 2009 15:09:44 +0100 Subject: [PATCH 007/104] Review comments for LOCK_open patch --- include/hash.h | 10 ++++++---- mysys/hash.c | 26 ++++++++++++++++---------- sql/sql_base.cc | 12 ++++++------ 3 files changed, 28 insertions(+), 20 deletions(-) diff --git a/include/hash.h b/include/hash.h index b6fc365ab76..80408f75f4d 100644 --- a/include/hash.h +++ b/include/hash.h @@ -45,7 +45,6 @@ extern "C" { #define hash_element my_hash_element #define hash_search my_hash_search #define hash_first my_hash_first -#define hash_first_from_hash_value my_hash_first_from_hash_value #define hash_next my_hash_next #define hash_insert my_hash_insert #define hash_delete my_hash_delete @@ -65,6 +64,7 @@ extern "C" { /* flags for hash_init */ #define HASH_UNIQUE 1 /* hash_insert fails on duplicate key */ +typedef uint my_hash_value_type; typedef uchar *(*my_hash_get_key)(const uchar *,size_t*,my_bool); typedef void (*my_hash_free_key)(void *); @@ -95,13 +95,15 @@ void my_hash_free(HASH *tree); void my_hash_reset(HASH *hash); uchar *my_hash_element(HASH *hash, ulong idx); uchar *my_hash_search(const HASH *info, const uchar *key, size_t length); -uchar *my_hash_search_using_hash_value(const HASH *info, uint hash_value, +uchar *my_hash_search_using_hash_value(const HASH *info, + my_hash_value_type hash_value, const uchar *key, size_t length); -uint my_calc_hash(const HASH *info, const uchar *key, size_t length); +my_hash_value_type my_calc_hash(const HASH *info, + const uchar *key, size_t length); uchar *my_hash_first(const HASH *info, const uchar *key, size_t length, HASH_SEARCH_STATE *state); uchar *my_hash_first_from_hash_value(const HASH *info, - uint hash_value, + my_hash_value_type hash_value, const uchar *key, size_t length, HASH_SEARCH_STATE *state); diff --git a/mysys/hash.c b/mysys/hash.c index 367ac8713dd..ae754e5bd93 100644 --- a/mysys/hash.c +++ b/mysys/hash.c @@ -33,16 +33,18 @@ typedef struct st_hash_info { uchar *data; /* data for current entry */ } HASH_LINK; -static uint my_hash_mask(size_t hashnr, size_t buffmax, size_t maxlength); +static uint my_hash_mask(my_hash_value_type hashnr, + size_t buffmax, size_t maxlength); static void movelink(HASH_LINK *array,uint pos,uint next_link,uint newlink); static int hashcmp(const HASH *hash, HASH_LINK *pos, const uchar *key, size_t length); -static uint calc_hash(const HASH *hash, const uchar *key, size_t length) +static my_hash_value_type calc_hash(const HASH *hash, + const uchar *key, size_t length) { ulong nr1=1, nr2=4; hash->charset->coll->hash_sort(hash->charset,(uchar*) key,length,&nr1,&nr2); - return nr1; + return (my_hash_value_type)nr1; } /** @@ -179,7 +181,8 @@ my_hash_key(const HASH *hash, const uchar *record, size_t *length, /* Calculate pos according to keys */ -static uint my_hash_mask(size_t hashnr, size_t buffmax, size_t maxlength) +static uint my_hash_mask(my_hash_value_type hashnr, size_t buffmax, + size_t maxlength) { if ((hashnr & (buffmax-1)) < maxlength) return (hashnr & (buffmax-1)); return (hashnr & ((buffmax >> 1) -1)); @@ -200,7 +203,7 @@ static #if !defined(__USLC__) && !defined(__sgi) inline #endif -unsigned int rec_hashnr(HASH *hash,const uchar *record) +my_hash_value_type rec_hashnr(HASH *hash,const uchar *record) { size_t length; uchar *key= (uchar*) my_hash_key(hash, record, &length, 0); @@ -215,7 +218,7 @@ uchar* my_hash_search(const HASH *hash, const uchar *key, size_t length) } uchar* my_hash_search_using_hash_value(const HASH *hash, - uint hash_value, + my_hash_value_type hash_value, const uchar *key, size_t length) { @@ -224,7 +227,8 @@ uchar* my_hash_search_using_hash_value(const HASH *hash, key, length, &state); } -uint my_calc_hash(const HASH *hash, const uchar *key, size_t length) +my_hash_value_type my_calc_hash(const HASH *hash, + const uchar *key, size_t length) { return calc_hash(hash, key, length ? length : hash->key_length); } @@ -244,7 +248,7 @@ uchar* my_hash_first(const HASH *hash, const uchar *key, size_t length, } uchar* my_hash_first_from_hash_value(const HASH *hash, - uint hash_value, + my_hash_value_type hash_value, const uchar *key, size_t length, HASH_SEARCH_STATE *current_record) @@ -356,7 +360,8 @@ static int hashcmp(const HASH *hash, HASH_LINK *pos, const uchar *key, my_bool my_hash_insert(HASH *info, const uchar *record) { int flag; - size_t idx,halfbuff,hash_nr,first_index; + size_t idx,halfbuff,first_index; + my_hash_value_type hash_nr; uchar *ptr_to_rec,*ptr_to_rec2; HASH_LINK *data,*empty,*gpos,*gpos2,*pos; @@ -497,7 +502,8 @@ my_bool my_hash_insert(HASH *info, const uchar *record) my_bool my_hash_delete(HASH *hash, uchar *record) { - uint blength,pos2,pos_hashnr,lastpos_hashnr,idx,empty_index; + uint blength,pos2,idx,empty_index; + my_hash_value_type pos_hashnr, lastpos_hashnr; HASH_LINK *data,*lastpos,*gpos,*pos,*pos3,*empty; DBUG_ENTER("my_hash_delete"); if (!hash->records) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 064d277e0b4..9116d89ceed 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2513,7 +2513,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, char key[MAX_DBKEY_LENGTH]; uint key_length; char *alias= table_list->alias; - uint hash_value; + my_hash_value_type hash_value; HASH_SEARCH_STATE state; DBUG_ENTER("open_table"); @@ -2746,11 +2746,11 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, an implicit "pending locks queue" - see wait_for_locked_table_names for details. */ - for (table= (TABLE*) hash_first_from_hash_value(&open_cache, - hash_value, - (uchar*) key, - key_length, - &state); + for (table= (TABLE*) my_hash_first_from_hash_value(&open_cache, + hash_value, + (uchar*) key, + key_length, + &state); table && table->in_use ; table= (TABLE*) hash_next(&open_cache, (uchar*) key, key_length, &state)) From a31ed000eae3af23481d4e6517ef20a66fe125c7 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Thu, 12 Nov 2009 12:17:31 +0100 Subject: [PATCH 008/104] WL#4949, Remove use of LOCK_alarm by instead using SO_SNDTIME0/SO_RCVTIME0 --- configure.in | 67 +++++++++++++++++++++++++++++++++++++++++++++++-- sql/net_serv.cc | 2 ++ 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 9fe5c741a03..227f7844037 100644 --- a/configure.in +++ b/configure.in @@ -859,10 +859,73 @@ AC_CHECK_DECLS(MHA_MAPSIZE_VA, #include ] ) - - fi +dnl Use of ALARMs to wakeup on timeout on sockets +dnl +dnl This feature makes use of a mutex and is a scalability hog we +dnl try to avoid using. However we need support for SO_SNDTIMEO and +dnl SO_RCVTIMEO socket options for this to work. So we will check +dnl if this feature is supported by a simple AC_RUN_IFELSE macro. However +dnl on some OS's there is support for setting those variables but +dnl they are silently ignored. For those OS's we will not attempt +dnl o use SO_SNDTIMEO and SO_RCVTIMEO even if it is said to work. +dnl See Bug#29093 for the problem with SO_SND/RCVTIMEO on HP/UX. +dnl To use alarm is simple, simply avoid setting anything. + + +AC_CACHE_CHECK([whether SO_SNDTIMEO and SO_RCVTIMEO work], + [mysql_cv_socket_timeout], + [AC_RUN_IFELSE( + [AC_LANG_PROGRAM([[ + #include + #include + #include + ]],[[ + int fd = socket(AF_INET, SOCK_STREAM, 0); + struct timeval tv; + int ret= 0; + tv.tv_sec= 2; + tv.tv_usec= 0; + ret|= setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); + ret|= setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); + return !!ret; + ]])], + [mysql_cv_socket_timeout=yes], + [mysql_cv_socket_timeout=no], + [mysql_cv_socket_timeout=no + AC_MSG_WARN([Socket timeout options disabled due to cross-compiling])]) + ]) + +use_alarm=yes + +if test "$mysql_cv_socket_timeout" = yes; then + case $SYSTEM_TYPE in + dnl We trust the result from the following systems + *solaris*) use_alarm=no ;; + *freebsd*) use_alarm=no ;; + *darwin*) use_alarm=no ;; + *) + dnl We trust the result from Linux also + if test "$TARGET_LINUX" = "true"; then + use_alarm=no + fi + dnl We trust no one else for the moment + dnl (Windows is hardcoded to not use alarms) + ;; + esac +fi + +AC_ARG_WITH(alarm, + AS_HELP_STRING([--with-alarm], [Use alarm to implement socket timeout.]), + [use_alarm=$withval], []) + +AC_MSG_CHECKING(whether to use alarms to implement socket timeout) +if test "$use_alarm" = no ; then + AC_DEFINE([NO_ALARM], [1], [No need to use alarm for socket timeout]) +fi +AC_MSG_RESULT($use_alarm) + #-------------------------------------------------------------------- # Check for TCP wrapper support #-------------------------------------------------------------------- diff --git a/sql/net_serv.cc b/sql/net_serv.cc index 5cf3597c638..d54ff1d2779 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -71,8 +71,10 @@ #if defined(__WIN__) || !defined(MYSQL_SERVER) /* The following is because alarms doesn't work on windows. */ +#ifndef NO_ALARM #define NO_ALARM #endif +#endif #ifndef NO_ALARM #include "my_pthread.h" From 41a125474facfe7d6403a737fa32e491e2b44c3d Mon Sep 17 00:00:00 2001 From: Andrei Elkin Date: Thu, 12 Nov 2009 17:10:19 +0200 Subject: [PATCH 009/104] Bug #47210 first execution of "start slave until" stops too early Until-pos guarding did not distiguish the master originated events from ones that the slave can introduce to the relay log e.g Rotate to the next relay log at slave restarting. The local Rotate's coordinate are incomparable with the Until-master-pos. That led to the unexpectable stop this bug describes. Fixed with to avoid Until-master-pos comparison for a local slave's event. Notice that if --replicate-same-server is true such event is treated as coming from the master side. --- mysql-test/r/rpl_until.result | 28 +++++++++++++++ mysql-test/t/rpl_until.test | 65 ++++++++++++++++++++++++++++++++++- sql/slave.cc | 14 ++++---- sql/slave.h | 2 +- 4 files changed, 101 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/rpl_until.result b/mysql-test/r/rpl_until.result index 60b956785ba..3dac55ec5c1 100644 --- a/mysql-test/r/rpl_until.result +++ b/mysql-test/r/rpl_until.result @@ -194,3 +194,31 @@ start slave sql_thread; start slave until master_log_file='master-bin.000001', master_log_pos=776; Warnings: Note 1254 Slave is already running +include/stop_slave.inc +drop table if exists t1; +reset slave; +change master to master_host='127.0.0.1',master_port=MASTER_PORT, master_user='root'; +drop table if exists t1; +reset master; +create table t1 (a int primary key auto_increment); +start slave; +include/stop_slave.inc +master and slave are in sync now +select 0 as zero; +zero +0 +insert into t1 set a=null; +insert into t1 set a=null; +select count(*) as two from t1; +two +2 +start slave until master_log_file='master-bin.000001', master_log_pos= UNTIL_POS;; +slave stopped at the prescribed position +select 0 as zero; +zero +0 +select count(*) as one from t1; +one +1 +drop table t1; +start slave; diff --git a/mysql-test/t/rpl_until.test b/mysql-test/t/rpl_until.test index c404ea7e58b..abd78b6a005 100644 --- a/mysql-test/t/rpl_until.test +++ b/mysql-test/t/rpl_until.test @@ -84,4 +84,67 @@ start slave until relay_log_file='slave-relay-bin.000002', master_log_pos=561; start slave sql_thread; start slave until master_log_file='master-bin.000001', master_log_pos=776; -# End of 4.1 tests +# +# bug#47210 first execution of "start slave until" stops too early +# +# testing that a slave rotate event that is caused by stopping the slave +# does not intervene anymore in UNTIL condition. +# + +connection slave; +source include/stop_slave.inc; +--disable_warnings +drop table if exists t1; +--enable_warnings +reset slave; +--replace_result $MASTER_MYPORT MASTER_PORT +eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root'; + +connection master; +--disable_warnings +drop table if exists t1; +--enable_warnings +reset master; +create table t1 (a int primary key auto_increment); +save_master_pos; +let $master_pos= query_get_value(SHOW MASTER STATUS, Position, 1); + +connection slave; +start slave; +sync_with_master; + +# at this point slave will close the relay log stamping it with its own +# Rotate log event. This event won't be examined on matter of the master +# UNTIL pos anymore. +source include/stop_slave.inc; +let $slave_exec_pos= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1); + +--echo master and slave are in sync now +let $diff_pos= `select $master_pos - $slave_exec_pos`; +eval select $diff_pos as zero; + +connection master; +insert into t1 set a=null; +let $until_pos= query_get_value(SHOW MASTER STATUS, Position, 1); +insert into t1 set a=null; +select count(*) as two from t1; + +connection slave; +--replace_result $until_pos UNTIL_POS; +eval start slave until master_log_file='master-bin.000001', master_log_pos= $until_pos; +source include/wait_for_slave_sql_to_stop.inc; +let $slave_exec_pos= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1); +--echo slave stopped at the prescribed position +let $diff_pos= `select $until_pos - $slave_exec_pos`; +eval select $diff_pos as zero; +select count(*) as one from t1; + + +connection master; +drop table t1; + +connection slave; +start slave; +sync_with_master; + +# End of tests diff --git a/sql/slave.cc b/sql/slave.cc index dd29a3f45c9..87bd7e2be8c 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -3223,7 +3223,7 @@ int check_expected_error(THD* thd, RELAY_LOG_INFO* rli, int expected_error) false - condition not met */ -bool st_relay_log_info::is_until_satisfied(my_off_t master_beg_pos) +bool st_relay_log_info::is_until_satisfied(THD *thd, Log_event *ev) { const char *log_name; ulonglong log_pos; @@ -3232,8 +3232,12 @@ bool st_relay_log_info::is_until_satisfied(my_off_t master_beg_pos) if (until_condition == UNTIL_MASTER_POS) { + if (ev && ev->server_id == (uint32) ::server_id && !replicate_same_server_id) + return FALSE; log_name= group_master_log_name; - log_pos= master_beg_pos; + log_pos= (!ev)? group_master_log_pos : + ((thd->options & OPTION_BEGIN || !ev->log_pos) ? + group_master_log_pos : ev->log_pos - ev->data_written); } else { /* until_condition == UNTIL_RELAY_POS */ @@ -3333,9 +3337,7 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) hits the UNTIL barrier. */ if (rli->until_condition != RELAY_LOG_INFO::UNTIL_NONE && - rli->is_until_satisfied((thd->options & OPTION_BEGIN || !ev->log_pos) ? - rli->group_master_log_pos : - ev->log_pos - ev->data_written)) + rli->is_until_satisfied(thd, ev)) { char buf[22]; sql_print_information("Slave SQL thread stopped because it reached its" @@ -4065,7 +4067,7 @@ Slave SQL thread aborted. Can't execute init_slave query"); */ pthread_mutex_lock(&rli->data_lock); if (rli->until_condition != RELAY_LOG_INFO::UNTIL_NONE && - rli->is_until_satisfied(rli->group_master_log_pos)) + rli->is_until_satisfied(thd, NULL)) { char buf[22]; sql_print_information("Slave SQL thread stopped because it reached its" diff --git a/sql/slave.h b/sql/slave.h index 5ae596f1eb5..78627214eef 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -348,7 +348,7 @@ typedef struct st_relay_log_info void close_temporary_tables(); /* Check if UNTIL condition is satisfied. See slave.cc for more. */ - bool is_until_satisfied(my_off_t master_beg_pos); + bool is_until_satisfied(THD *thd, Log_event *ev); inline ulonglong until_pos() { return ((until_condition == UNTIL_MASTER_POS) ? group_master_log_pos : From 31d01ce3014242fb375087dc82b600678decfef0 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Fri, 20 Nov 2009 16:43:21 +0100 Subject: [PATCH 010/104] WL#5138, review fixes --- sql/event_scheduler.cc | 18 +++++++++--------- sql/mysql_priv.h | 4 ++-- sql/mysqld.cc | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc index 880bccdd67e..411be5a9d20 100644 --- a/sql/event_scheduler.cc +++ b/sql/event_scheduler.cc @@ -158,12 +158,12 @@ deinit_event_thread(THD *thd) DBUG_PRINT("exit", ("Event thread finishing")); pthread_mutex_lock(&LOCK_thread_count); thread_count--; - delete thd; - pthread_cond_broadcast(&COND_thread_count); - pthread_mutex_unlock(&LOCK_thread_count); my_atomic_rwlock_wrlock(&global_query_id_lock); dec_thread_running(); my_atomic_rwlock_wrunlock(&global_query_id_lock); + delete thd; + pthread_cond_broadcast(&COND_thread_count); + pthread_mutex_unlock(&LOCK_thread_count); } @@ -421,12 +421,12 @@ Event_scheduler::start() net_end(&new_thd->net); pthread_mutex_lock(&LOCK_thread_count); thread_count--; - delete new_thd; - pthread_cond_broadcast(&COND_thread_count); - pthread_mutex_unlock(&LOCK_thread_count); my_atomic_rwlock_wrlock(&global_query_id_lock); dec_thread_running(); my_atomic_rwlock_wrunlock(&global_query_id_lock); + delete new_thd; + pthread_cond_broadcast(&COND_thread_count); + pthread_mutex_unlock(&LOCK_thread_count); } end: UNLOCK_DATA(); @@ -556,12 +556,12 @@ error: net_end(&new_thd->net); pthread_mutex_lock(&LOCK_thread_count); thread_count--; - delete new_thd; - pthread_cond_broadcast(&COND_thread_count); - pthread_mutex_unlock(&LOCK_thread_count); my_atomic_rwlock_wrlock(&global_query_id_lock); dec_thread_running(); my_atomic_rwlock_wrunlock(&global_query_id_lock); + delete new_thd; + pthread_cond_broadcast(&COND_thread_count); + pthread_mutex_unlock(&LOCK_thread_count); } delete event_name; DBUG_RETURN(TRUE); diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 0caf3197fb8..b816f692320 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -86,9 +86,9 @@ typedef ulong nesting_map; /* Used for flags of nesting constructs */ typedef ulonglong nested_join_map; /* query_id */ -typedef int64 query_id_t; +typedef uint64 query_id_t; extern query_id_t global_query_id; -extern int32 thread_running; +extern uint32 thread_running; extern my_atomic_rwlock_t global_query_id_lock; /* increment query_id and return it. */ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index ddc6d53e019..253ed36ce31 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -532,7 +532,7 @@ uint delay_key_write_options, protocol_version; uint lower_case_table_names; uint tc_heuristic_recover= 0; uint volatile thread_count; -int32 thread_running; +uint32 thread_running; ulonglong thd_startup_options; ulong back_log, connect_timeout, concurrency, server_id; ulong table_cache_size, table_def_size; From 3566f21b08f49ece56280d8fbaeb53259ae22a43 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Fri, 20 Nov 2009 18:42:15 +0100 Subject: [PATCH 011/104] WL#5138, reverted some review fixes --- sql/mysql_priv.h | 4 ++-- sql/mysqld.cc | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index b816f692320..0caf3197fb8 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -86,9 +86,9 @@ typedef ulong nesting_map; /* Used for flags of nesting constructs */ typedef ulonglong nested_join_map; /* query_id */ -typedef uint64 query_id_t; +typedef int64 query_id_t; extern query_id_t global_query_id; -extern uint32 thread_running; +extern int32 thread_running; extern my_atomic_rwlock_t global_query_id_lock; /* increment query_id and return it. */ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 253ed36ce31..ddc6d53e019 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -532,7 +532,7 @@ uint delay_key_write_options, protocol_version; uint lower_case_table_names; uint tc_heuristic_recover= 0; uint volatile thread_count; -uint32 thread_running; +int32 thread_running; ulonglong thd_startup_options; ulong back_log, connect_timeout, concurrency, server_id; ulong table_cache_size, table_def_size; From 6e02272abb2789766180c9b1dc4a906337368d78 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Fri, 20 Nov 2009 20:01:43 +0100 Subject: [PATCH 012/104] WL#5105, review fix --- mysys/ptr_cmp.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mysys/ptr_cmp.c b/mysys/ptr_cmp.c index 9f053f0b3b4..2005e3eb2b7 100644 --- a/mysys/ptr_cmp.c +++ b/mysys/ptr_cmp.c @@ -22,7 +22,7 @@ #include "mysys_priv.h" #include -#ifdef UNIV_SOLARIS +#ifdef TARGET_OS_SOLARIS /* * On Solaris, memcmp() is normally faster than the unrolled ptr_compare_N * functions, as memcmp() is usually a platform-specific implementation @@ -39,20 +39,20 @@ static int native_compare(size_t *length, unsigned char **a, unsigned char **b) return memcmp(*a, *b, *length); } -#else /* UNIV_SOLARIS */ +#else /* TARGET_OS_SOLARIS */ static int ptr_compare(size_t *compare_length, uchar **a, uchar **b); static int ptr_compare_0(size_t *compare_length, uchar **a, uchar **b); static int ptr_compare_1(size_t *compare_length, uchar **a, uchar **b); static int ptr_compare_2(size_t *compare_length, uchar **a, uchar **b); static int ptr_compare_3(size_t *compare_length, uchar **a, uchar **b); -#endif /* UNIV_SOLARIS */ +#endif /* TARGET_OS_SOLARIS */ /* Get a pointer to a optimal byte-compare function for a given size */ qsort2_cmp get_ptr_compare (size_t size) { -#ifdef UNIV_SOLARIS +#ifdef TARGET_OS_SOLARIS return (qsort2_cmp) native_compare; #else if (size < 4) @@ -64,7 +64,7 @@ qsort2_cmp get_ptr_compare (size_t size) case 3: return (qsort2_cmp) ptr_compare_3; } return 0; /* Impossible */ -#endif /* UNIV_SOLARIS */ +#endif /* TARGET_OS_SOLARIS */ } From 9d625dca13ff09beee30138e9f6ddb038435faa4 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Mon, 23 Nov 2009 17:57:21 +0100 Subject: [PATCH 013/104] WL#5138, fixed review comments --- sql/event_scheduler.cc | 10 +--------- sql/log_event.cc | 6 ------ sql/mysql_priv.h | 11 +++++++++++ sql/mysqld.cc | 3 +++ sql/sp_head.cc | 2 -- sql/sql_parse.cc | 8 -------- 6 files changed, 15 insertions(+), 25 deletions(-) diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc index 411be5a9d20..69e5f30ad31 100644 --- a/sql/event_scheduler.cc +++ b/sql/event_scheduler.cc @@ -133,10 +133,8 @@ post_init_event_thread(THD *thd) pthread_mutex_lock(&LOCK_thread_count); threads.append(thd); thread_count++; - pthread_mutex_unlock(&LOCK_thread_count); - my_atomic_rwlock_wrlock(&global_query_id_lock); inc_thread_running(); - my_atomic_rwlock_wrunlock(&global_query_id_lock); + pthread_mutex_unlock(&LOCK_thread_count); return FALSE; } @@ -158,9 +156,7 @@ deinit_event_thread(THD *thd) DBUG_PRINT("exit", ("Event thread finishing")); pthread_mutex_lock(&LOCK_thread_count); thread_count--; - my_atomic_rwlock_wrlock(&global_query_id_lock); dec_thread_running(); - my_atomic_rwlock_wrunlock(&global_query_id_lock); delete thd; pthread_cond_broadcast(&COND_thread_count); pthread_mutex_unlock(&LOCK_thread_count); @@ -421,9 +417,7 @@ Event_scheduler::start() net_end(&new_thd->net); pthread_mutex_lock(&LOCK_thread_count); thread_count--; - my_atomic_rwlock_wrlock(&global_query_id_lock); dec_thread_running(); - my_atomic_rwlock_wrunlock(&global_query_id_lock); delete new_thd; pthread_cond_broadcast(&COND_thread_count); pthread_mutex_unlock(&LOCK_thread_count); @@ -556,9 +550,7 @@ error: net_end(&new_thd->net); pthread_mutex_lock(&LOCK_thread_count); thread_count--; - my_atomic_rwlock_wrlock(&global_query_id_lock); dec_thread_running(); - my_atomic_rwlock_wrunlock(&global_query_id_lock); delete new_thd; pthread_cond_broadcast(&COND_thread_count); pthread_mutex_unlock(&LOCK_thread_count); diff --git a/sql/log_event.cc b/sql/log_event.cc index 31908a818be..58ed5aa6a60 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -3056,9 +3056,7 @@ int Query_log_event::do_apply_event(Relay_log_info const *rli, { thd->set_time((time_t)when); thd->set_query((char*)query_arg, q_len_arg); - my_atomic_rwlock_wrlock(&global_query_id_lock); thd->query_id = next_query_id(); - my_atomic_rwlock_wrunlock(&global_query_id_lock); thd->variables.pseudo_thread_id= thread_id; // for temp tables DBUG_PRINT("query",("%s", thd->query())); @@ -4581,9 +4579,7 @@ int Load_log_event::do_apply_event(NET* net, Relay_log_info const *rli, if (rpl_filter->db_ok(thd->db)) { thd->set_time((time_t)when); - my_atomic_rwlock_wrlock(&global_query_id_lock); thd->query_id = next_query_id(); - my_atomic_rwlock_wrunlock(&global_query_id_lock); thd->warning_info->opt_clear_warning_info(thd->query_id); TABLE_LIST tables; @@ -8072,9 +8068,7 @@ int Table_map_log_event::do_apply_event(Relay_log_info const *rli) DBUG_ASSERT(rli->sql_thd == thd); /* Step the query id to mark what columns that are actually used. */ - my_atomic_rwlock_wrlock(&global_query_id_lock); thd->query_id= next_query_id(); - my_atomic_rwlock_wrunlock(&global_query_id_lock); if (!(memory= my_multi_malloc(MYF(MY_WME), &table_list, (uint) sizeof(RPL_TABLE_LIST), diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 0caf3197fb8..ec6aa274e49 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -90,19 +90,24 @@ typedef int64 query_id_t; extern query_id_t global_query_id; extern int32 thread_running; extern my_atomic_rwlock_t global_query_id_lock; +extern my_atomic_rwlock_t thread_running_lock; /* increment query_id and return it. */ inline query_id_t next_query_id() { query_id_t id; + my_atomic_rwlock_wrlock(&global_query_id_lock); id= my_atomic_add64(&global_query_id, 1); + my_atomic_rwlock_wrunlock(&global_query_id_lock); return (id+1); } inline query_id_t get_query_id() { query_id_t id; + my_atomic_rwlock_wrlock(&global_query_id_lock); id= my_atomic_load64(&global_query_id); + my_atomic_rwlock_wrunlock(&global_query_id_lock); return id; } @@ -110,7 +115,9 @@ inline int32 inc_thread_running() { int32 num_thread_running; + my_atomic_rwlock_wrlock(&thread_running_lock); num_thread_running= my_atomic_add32(&thread_running, 1); + my_atomic_rwlock_wrunlock(&thread_running_lock); return (num_thread_running+1); } @@ -118,7 +125,9 @@ inline int32 dec_thread_running() { int32 num_thread_running; + my_atomic_rwlock_wrlock(&thread_running_lock); num_thread_running= my_atomic_add32(&thread_running, -1); + my_atomic_rwlock_wrunlock(&thread_running_lock); return (num_thread_running-1); } @@ -126,7 +135,9 @@ inline int32 get_thread_running() { int32 num_thread_running; + my_atomic_rwlock_wrlock(&thread_running_lock); num_thread_running= my_atomic_load32(&thread_running); + my_atomic_rwlock_wrunlock(&thread_running_lock); return num_thread_running; } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index ddc6d53e019..e841f869b95 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -549,6 +549,7 @@ ulong query_cache_size=0; ulong refresh_version; /* Increments on each reload */ query_id_t global_query_id; my_atomic_rwlock_t global_query_id_lock; +my_atomic_rwlock_t thread_running_lock; ulong aborted_threads, aborted_connects; ulong delayed_insert_timeout, delayed_insert_limit, delayed_queue_size; ulong delayed_insert_threads, delayed_insert_writes, delayed_rows_in_use; @@ -1383,6 +1384,7 @@ void clean_up(bool print_message) /* Tell main we are ready */ logger.cleanup_end(); my_atomic_rwlock_destroy(&global_query_id_lock); + my_atomic_rwlock_destroy(&thread_running_lock); (void) pthread_mutex_lock(&LOCK_thread_count); DBUG_PRINT("quit", ("got thread count lock")); ready_to_exit=1; @@ -7799,6 +7801,7 @@ static int mysql_init_variables(void) refresh_version= 1L; /* Increments on each reload */ global_query_id= thread_id= 1L; my_atomic_rwlock_init(&global_query_id_lock); + my_atomic_rwlock_init(&thread_running_lock); strmov(server_version, MYSQL_SERVER_VERSION); myisam_recover_options_str= sql_mode_str= "OFF"; myisam_stats_method_str= "nulls_unequal"; diff --git a/sql/sp_head.cc b/sql/sp_head.cc index d0453c08a00..705fd2f702b 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -2736,9 +2736,7 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp, */ thd->lex= m_lex; - my_atomic_rwlock_wrlock(&global_query_id_lock); thd->query_id= next_query_id(); - my_atomic_rwlock_wrunlock(&global_query_id_lock); if (thd->prelocked_mode == NON_PRELOCKED) { diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 7b5df421785..83a54d1a59f 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -495,9 +495,7 @@ static void handle_bootstrap_impl(THD *thd) We don't need to obtain LOCK_thread_count here because in bootstrap mode we have only one thread. */ - my_atomic_rwlock_wrlock(&global_query_id_lock); thd->query_id=next_query_id(); - my_atomic_rwlock_wrunlock(&global_query_id_lock); thd->set_time(); mysql_parse(thd, thd->query(), length, & found_semicolon); close_thread_tables(thd); // Free tables @@ -991,7 +989,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thd->enable_slow_log= TRUE; thd->lex->sql_command= SQLCOM_END; /* to avoid confusing VIEW detectors */ thd->set_time(); - my_atomic_rwlock_wrlock(&global_query_id_lock); { query_id_t query_id; switch( command ) { @@ -1014,7 +1011,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thd->query_id= query_id; } inc_thread_running(); - my_atomic_rwlock_wrunlock(&global_query_id_lock); /** Clear the set of flags that are expected to be cleared at the @@ -1284,9 +1280,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, Count each statement from the client. */ statistic_increment(thd->status_var.questions, &LOCK_status); - my_atomic_rwlock_wrlock(&global_query_id_lock); thd->query_id= next_query_id(); - my_atomic_rwlock_wrunlock(&global_query_id_lock); thd->set_time(); /* Reset the query start time. */ /* TODO: set thd->lex->sql_command to SQLCOM_END here */ mysql_parse(thd, beginning_of_next_stmt, length, &end_of_stmt); @@ -1604,9 +1598,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thd_proc_info(thd, "cleaning up"); thd->set_query(NULL, 0); thd->command=COM_SLEEP; - my_atomic_rwlock_wrlock(&global_query_id_lock); dec_thread_running(); - my_atomic_rwlock_wrunlock(&global_query_id_lock); thd_proc_info(thd, 0); thd->packet.shrink(thd->variables.net_buffer_length); // Reclaim some memory free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC)); From 4fd771cedcf9d55477dba81fad3f41e2da074f1c Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Tue, 24 Nov 2009 14:28:38 +0100 Subject: [PATCH 014/104] WL#5138, Fixed according to code review comments from Davi --- sql/log_event.cc | 5 ++--- sql/sp_head.cc | 4 ++-- sql/sql_class.cc | 20 ++++++++++++++++++++ sql/sql_class.h | 5 ++++- sql/sql_cursor.cc | 2 +- sql/sql_parse.cc | 8 +++----- 6 files changed, 32 insertions(+), 12 deletions(-) diff --git a/sql/log_event.cc b/sql/log_event.cc index 58ed5aa6a60..608f4d25cf4 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -3055,8 +3055,7 @@ int Query_log_event::do_apply_event(Relay_log_info const *rli, rpl_filter->db_ok(thd->db)) { thd->set_time((time_t)when); - thd->set_query((char*)query_arg, q_len_arg); - thd->query_id = next_query_id(); + thd->set_query_and_id((char*)query_arg, q_len_arg, next_query_id()); thd->variables.pseudo_thread_id= thread_id; // for temp tables DBUG_PRINT("query",("%s", thd->query())); @@ -8068,7 +8067,7 @@ int Table_map_log_event::do_apply_event(Relay_log_info const *rli) DBUG_ASSERT(rli->sql_thd == thd); /* Step the query id to mark what columns that are actually used. */ - thd->query_id= next_query_id(); + thd->set_query_id(next_query_id()); if (!(memory= my_multi_malloc(MYF(MY_WME), &table_list, (uint) sizeof(RPL_TABLE_LIST), diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 705fd2f702b..dae4a03c7f5 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1338,7 +1338,7 @@ sp_head::execute(THD *thd) /* To avoid wiping out thd->change_list on old_change_list destruction */ old_change_list.empty(); thd->lex= old_lex; - thd->query_id= old_query_id; + thd->set_query_id(old_query_id); DBUG_ASSERT(!thd->derived_tables); thd->derived_tables= old_derived_tables; thd->variables.sql_mode= save_sql_mode; @@ -2736,7 +2736,7 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp, */ thd->lex= m_lex; - thd->query_id= next_query_id(); + thd->set_query_id(next_query_id()); if (thd->prelocked_mode == NON_PRELOCKED) { diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 60aed4ce53b..d8fb64878aa 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -3273,6 +3273,26 @@ void THD::set_query(char *query_arg, uint32 query_length_arg) pthread_mutex_unlock(&LOCK_thd_data); } +/** Assign a new value to thd->query and thd->query_id. */ + +void THD::set_query_and_id(char *query_arg, uint32 query_length_arg, + query_id_t new_query_id) +{ + pthread_mutex_lock(&LOCK_thd_data); + set_query_inner(query_arg, query_length_arg); + query_id= new_query_id; + pthread_mutex_unlock(&LOCK_thd_data); +} + +/** Assign a new value to thd->query_id. */ + +void THD::set_query_id(query_id_t new_query_id) +{ + pthread_mutex_lock(&LOCK_thd_data); + query_id= new_query_id; + pthread_mutex_unlock(&LOCK_thd_data); +} + /** Mark transaction to rollback and mark error as fatal to a sub-statement. diff --git a/sql/sql_class.h b/sql/sql_class.h index 2dd45997ee1..79e87a5ca3d 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2324,10 +2324,13 @@ public: virtual void set_statement(Statement *stmt); /** - Assign a new value to thd->query. + Assign a new value to thd->query and thd->query_id. Protected with LOCK_thd_data mutex. */ void set_query(char *query_arg, uint32 query_length_arg); + void set_query_and_id(char *query_arg, uint32 query_length_arg, + query_id_t new_query_id); + void set_query_id(query_id_t new_query_id); private: /** The current internal error handler for this thread, or NULL. */ Internal_error_handler *m_internal_handler; diff --git a/sql/sql_cursor.cc b/sql/sql_cursor.cc index ffc3fafe55f..533b47e61da 100644 --- a/sql/sql_cursor.cc +++ b/sql/sql_cursor.cc @@ -438,7 +438,7 @@ Sensitive_cursor::fetch(ulong num_rows) thd->derived_tables= derived_tables; thd->open_tables= open_tables; thd->lock= lock; - thd->query_id= query_id; + thd->set_query_id(query_id); thd->change_list= change_list; /* save references to memory allocated during fetch */ thd->set_n_backup_active_arena(this, &backup_arena); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 83a54d1a59f..f2b9d613e3a 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -484,7 +484,7 @@ static void handle_bootstrap_impl(THD *thd) query= (char *) thd->memdup_w_gap(buff, length + 1, thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE); - thd->set_query(query, length); + thd->set_query_and_id(query, length, next_query_id()); DBUG_PRINT("query",("%-.4096s",thd->query())); #if defined(ENABLED_PROFILING) thd->profiling.start_new_query(); @@ -495,7 +495,6 @@ static void handle_bootstrap_impl(THD *thd) We don't need to obtain LOCK_thread_count here because in bootstrap mode we have only one thread. */ - thd->query_id=next_query_id(); thd->set_time(); mysql_parse(thd, thd->query(), length, & found_semicolon); close_thread_tables(thd); // Free tables @@ -1008,7 +1007,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, statistic_increment(thd->status_var.questions, &LOCK_status); query_id= next_query_id() - 1; } - thd->query_id= query_id; + thd->set_query_id(query_id); } inc_thread_running(); @@ -1275,12 +1274,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thd->security_ctx->priv_user, (char *) thd->security_ctx->host_or_ip); - thd->set_query(beginning_of_next_stmt, length); + thd->set_query_and_id(beginning_of_next_stmt, length, next_query_id()); /* Count each statement from the client. */ statistic_increment(thd->status_var.questions, &LOCK_status); - thd->query_id= next_query_id(); thd->set_time(); /* Reset the query start time. */ /* TODO: set thd->lex->sql_command to SQLCOM_END here */ mysql_parse(thd, beginning_of_next_stmt, length, &end_of_stmt); From 2390a0cd0351514d12644fbe1955a2ea75b0997b Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Tue, 24 Nov 2009 20:04:02 +0000 Subject: [PATCH 015/104] BUG#48340: rpl_cross_version: Found warnings/errors in server log file! Valgrind reports a conditional jump that depends on uninitialized data while doing a LOAD DATA and for this test case only. This test case, tests that loading data from a 4.0 or 4.1 instance into a 5.1 instance is working. As such it handles old binary log with a different set of events than currently 5.1 codebase uses. See the following reference for details: http://forge.mysql.com/wiki/MySQL_Internals_Binary_Log#LOAD_DATA_INFILE_Events Problem: The server is handling an Execute_load_log_event, which results in reading a Load_log_event from the binary log and applying it. When applying the Load_log_event, some variable setup is done and then mysql_load is called. Late in mysql_load execution, if not in row mode logging, the event is binlogged write_execute_load_query_log_event. In write_execute_load_query_log_event, thd->lex->local_file is inspected. The problem is that it has not been set before in the execution stack. This causes valgrind to report the warning. Fix: We fix this by initializing thd->lex->local_file to be the same as the value of Load_log_event::local_fname, when lex_start is called inside Load_log_event::do_apply_event. --- sql/log_event.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/log_event.cc b/sql/log_event.cc index 2cb253c9c56..73580636b7b 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -4510,6 +4510,7 @@ int Load_log_event::do_apply_event(NET* net, Relay_log_info const *rli, as the present method does not call mysql_parse(). */ lex_start(thd); + thd->lex->local_file= local_fname; mysql_reset_thd_for_next_command(thd); if (!use_rli_only_for_errors) From 8b77e90380f1807716889ebadf3761832d6e8750 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Thu, 26 Nov 2009 13:48:21 +0100 Subject: [PATCH 016/104] Fixed kill_alarm test and got it working --- configure.in | 1 + mysql-test/r/kill_alarm.result | 10 ++++++++++ mysql-test/t/kill_alarm.test | 13 +++++++++++++ 3 files changed, 24 insertions(+) create mode 100644 mysql-test/r/kill_alarm.result create mode 100644 mysql-test/t/kill_alarm.test diff --git a/configure.in b/configure.in index 783b4444a28..890fc333cee 100644 --- a/configure.in +++ b/configure.in @@ -923,6 +923,7 @@ AC_ARG_WITH(alarm, AC_MSG_CHECKING(whether to use alarms to implement socket timeout) if test "$use_alarm" = no ; then AC_DEFINE([NO_ALARM], [1], [No need to use alarm for socket timeout]) + AC_DEFINE([SIGNAL_WITH_VIO_CLOSE], [1], [Need to use vio close for kill connection]) fi AC_MSG_RESULT($use_alarm) diff --git a/mysql-test/r/kill_alarm.result b/mysql-test/r/kill_alarm.result new file mode 100644 index 00000000000..27636f55c97 --- /dev/null +++ b/mysql-test/r/kill_alarm.result @@ -0,0 +1,10 @@ +show processlist; +Id User Host db Command Time State Info +2 root localhost test Sleep 0 NULL +3 root localhost test Sleep 0 NULL +4 root localhost test Query 0 NULL show processlist +kill connection 3; +show processlist; +Id User Host db Command Time State Info +2 root localhost test Sleep 4 NULL +4 root localhost test Query 0 NULL show processlist diff --git a/mysql-test/t/kill_alarm.test b/mysql-test/t/kill_alarm.test new file mode 100644 index 00000000000..c08eb3dcf83 --- /dev/null +++ b/mysql-test/t/kill_alarm.test @@ -0,0 +1,13 @@ +-- source include/not_embedded.inc + +connect (con1, localhost, root,,); +connect (con2, localhost, root,,); + +connection con1; +let $ID=`select connection_id()`; + +connection con2; +show processlist; +eval kill connection $ID; +--sleep 4 +show processlist; From 9553b61769dbb317eb6efb8c2e43c28a5d6e04eb Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Thu, 26 Nov 2009 13:58:59 +0100 Subject: [PATCH 017/104] Removed extra test case after review comment --- mysql-test/r/kill_alarm.result | 10 ---------- mysql-test/t/kill_alarm.test | 13 ------------- 2 files changed, 23 deletions(-) delete mode 100644 mysql-test/r/kill_alarm.result delete mode 100644 mysql-test/t/kill_alarm.test diff --git a/mysql-test/r/kill_alarm.result b/mysql-test/r/kill_alarm.result deleted file mode 100644 index 27636f55c97..00000000000 --- a/mysql-test/r/kill_alarm.result +++ /dev/null @@ -1,10 +0,0 @@ -show processlist; -Id User Host db Command Time State Info -2 root localhost test Sleep 0 NULL -3 root localhost test Sleep 0 NULL -4 root localhost test Query 0 NULL show processlist -kill connection 3; -show processlist; -Id User Host db Command Time State Info -2 root localhost test Sleep 4 NULL -4 root localhost test Query 0 NULL show processlist diff --git a/mysql-test/t/kill_alarm.test b/mysql-test/t/kill_alarm.test deleted file mode 100644 index c08eb3dcf83..00000000000 --- a/mysql-test/t/kill_alarm.test +++ /dev/null @@ -1,13 +0,0 @@ --- source include/not_embedded.inc - -connect (con1, localhost, root,,); -connect (con2, localhost, root,,); - -connection con1; -let $ID=`select connection_id()`; - -connection con2; -show processlist; -eval kill connection $ID; ---sleep 4 -show processlist; From 1db3a684e2bf16e2ca8537cac9ff21d47bcd9c67 Mon Sep 17 00:00:00 2001 From: Evgeny Potemkin Date: Tue, 1 Dec 2009 21:28:45 +0300 Subject: [PATCH 018/104] Bug#48508: Crash on prepared statement re-execution. Actually there is two different bugs. The first one caused crash on queries with WHERE condition over views containing WHERE condition. A wrong check for prepared statement phase led to items for view fields being allocated in the execution memory and freed at the end of execution. Thus the optimized WHERE condition refers to unallocated memory on the second execution and server crashed. The second one caused by the Item_cond::compile function not saving changes it made to the item tree. Thus on the next execution changes weren't reverted and server crashed on dereferencing of unallocated space. The new helper function called is_stmt_prepare_or_first_stmt_execute is added to the Query_arena class. The find_field_in_view function now uses is_stmt_prepare_or_first_stmt_execute() to check whether newly created view items should be freed at the end of the query execution. The Item_cond::compile function now saves changes it makes to item tree. --- mysql-test/r/ps.result | 23 +++++++++++++++++++++++ mysql-test/t/ps.test | 21 +++++++++++++++++++++ sql/item_cmpfunc.cc | 2 +- sql/sql_base.cc | 3 ++- sql/sql_class.h | 2 ++ 5 files changed, 49 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 43c50998e20..e7894388494 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -1891,4 +1891,27 @@ execute stmt using @arg; ? -12345.5432100000 deallocate prepare stmt; +# +# Bug#48508: Crash on prepared statement re-execution. +# +create table t1(b int); +insert into t1 values (0); +create view v1 AS select 1 as a from t1 where b; +prepare stmt from "select * from v1 where a"; +execute stmt; +a +execute stmt; +a +drop table t1; +drop view v1; +create table t1(a bigint); +create table t2(b tinyint); +insert into t2 values (null); +prepare stmt from "select 1 from t1 join t2 on a xor b where b > 1 and a =1"; +execute stmt; +1 +execute stmt; +1 +drop table t1,t2; +# End of 5.0 tests. diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index d9e593fd76f..6134efb5c5c 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -1973,4 +1973,25 @@ select @arg; execute stmt using @arg; deallocate prepare stmt; +--echo # +--echo # Bug#48508: Crash on prepared statement re-execution. +--echo # +create table t1(b int); +insert into t1 values (0); +create view v1 AS select 1 as a from t1 where b; +prepare stmt from "select * from v1 where a"; +execute stmt; +execute stmt; +drop table t1; +drop view v1; + +create table t1(a bigint); +create table t2(b tinyint); +insert into t2 values (null); +prepare stmt from "select 1 from t1 join t2 on a xor b where b > 1 and a =1"; +execute stmt; +execute stmt; +drop table t1,t2; +--echo # + --echo End of 5.0 tests. diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 8c655cdc369..d03c68b3560 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -3907,7 +3907,7 @@ Item *Item_cond::compile(Item_analyzer analyzer, byte **arg_p, byte *arg_v= *arg_p; Item *new_item= item->compile(analyzer, &arg_v, transformer, arg_t); if (new_item && new_item != item) - li.replace(new_item); + current_thd->change_item_tree(li.ref(), new_item); } return Item_func::transform(transformer, arg_t); } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 178c3e12e23..88d1e8879d1 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -3481,7 +3481,8 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list, if (!my_strcasecmp(system_charset_info, field_it.name(), name)) { // in PS use own arena or data will be freed after prepare - if (register_tree_change && thd->stmt_arena->is_stmt_prepare_or_first_sp_execute()) + if (register_tree_change && + thd->stmt_arena->is_stmt_prepare_or_first_stmt_execute()) arena= thd->activate_stmt_arena_if_needed(&backup); /* create_item() may, or may not create a new Item, depending on diff --git a/sql/sql_class.h b/sql/sql_class.h index b41a5d5c6b7..ac058bca4f9 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -759,6 +759,8 @@ public: { return state == INITIALIZED_FOR_SP; } inline bool is_stmt_prepare_or_first_sp_execute() const { return (int)state < (int)PREPARED; } + inline bool is_stmt_prepare_or_first_stmt_execute() const + { return (int)state <= (int)PREPARED; } inline bool is_first_stmt_execute() const { return state == PREPARED; } inline bool is_stmt_execute() const { return state == PREPARED || state == EXECUTED; } From f81700aa4ead8af29ec34870eefa61abfab12bee Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Wed, 2 Dec 2009 15:17:08 +0400 Subject: [PATCH 019/104] Bug#48766 SHOW CREATE FUNCTION returns extra data in return clause Problem: SHOW CREATE FUNCTION and SELECT DTD_IDENTIFIER FROM I_S.ROUTINES returned wrong values in case of ENUM return data type and UCS2 character set. Fix: the string to collect returned data type was incorrectly set to "binary" character set, therefore UCS2 values where returned with extra '\0' characters. Setting string character set to creation_ctx->get_client_cs() in sp_find_routine(), and to system_charset_info in sp_create_routine fixes the problem. Adding tests: - the original test with Latin letters - an extra test with non-Latin letters --- mysql-test/r/sp-ucs2.result | 26 ++++++++++++++++++++++++++ mysql-test/t/sp-ucs2.test | 29 +++++++++++++++++++++++++++++ sql/sp.cc | 2 ++ 3 files changed, 57 insertions(+) diff --git a/mysql-test/r/sp-ucs2.result b/mysql-test/r/sp-ucs2.result index ce6be5b0a65..1c266e38d97 100644 --- a/mysql-test/r/sp-ucs2.result +++ b/mysql-test/r/sp-ucs2.result @@ -12,3 +12,29 @@ a foo string drop function bug17615| drop table t3| +SET NAMES utf8; +DROP FUNCTION IF EXISTS bug48766; +CREATE FUNCTION bug48766 () +RETURNS ENUM( 'w' ) CHARACTER SET ucs2 +RETURN 0; +SHOW CREATE FUNCTION bug48766; +Function sql_mode Create Function character_set_client collation_connection Database Collation +bug48766 CREATE DEFINER=`root`@`localhost` FUNCTION `bug48766`() RETURNS enum('w') CHARSET ucs2 +RETURN 0 utf8 utf8_general_ci latin1_swedish_ci +SELECT DTD_IDENTIFIER FROM INFORMATION_SCHEMA.ROUTINES +WHERE ROUTINE_NAME='bug48766'; +DTD_IDENTIFIER +enum('w') CHARSET ucs2 +DROP FUNCTION bug48766; +CREATE FUNCTION bug48766 () +RETURNS ENUM('а','б','в','г') CHARACTER SET ucs2 +RETURN 0; +SHOW CREATE FUNCTION bug48766; +Function sql_mode Create Function character_set_client collation_connection Database Collation +bug48766 CREATE DEFINER=`root`@`localhost` FUNCTION `bug48766`() RETURNS enum('а','б','в','г') CHARSET ucs2 +RETURN 0 utf8 utf8_general_ci latin1_swedish_ci +SELECT DTD_IDENTIFIER FROM INFORMATION_SCHEMA.ROUTINES +WHERE ROUTINE_NAME='bug48766'; +DTD_IDENTIFIER +enum('а','б','в','г') CHARSET ucs2 +DROP FUNCTION bug48766; diff --git a/mysql-test/t/sp-ucs2.test b/mysql-test/t/sp-ucs2.test index 7dd88b04871..7d6b62dfea0 100644 --- a/mysql-test/t/sp-ucs2.test +++ b/mysql-test/t/sp-ucs2.test @@ -26,3 +26,32 @@ drop table t3| delimiter ;| + +# +# Bug#48766 SHOW CREATE FUNCTION returns extra data in return clause +# +SET NAMES utf8; +--disable_warnings +DROP FUNCTION IF EXISTS bug48766; +--enable_warnings +# +# Test that Latin letters are not prepended with extra '\0'. +# +CREATE FUNCTION bug48766 () + RETURNS ENUM( 'w' ) CHARACTER SET ucs2 + RETURN 0; +SHOW CREATE FUNCTION bug48766; +SELECT DTD_IDENTIFIER FROM INFORMATION_SCHEMA.ROUTINES +WHERE ROUTINE_NAME='bug48766'; +DROP FUNCTION bug48766; +# +# Test non-Latin characters +# +CREATE FUNCTION bug48766 () + RETURNS ENUM('а','б','в','г') CHARACTER SET ucs2 + RETURN 0; +SHOW CREATE FUNCTION bug48766; +SELECT DTD_IDENTIFIER FROM INFORMATION_SCHEMA.ROUTINES +WHERE ROUTINE_NAME='bug48766'; + +DROP FUNCTION bug48766; diff --git a/sql/sp.cc b/sql/sp.cc index d3c5dfb96d0..6fad1d70ffd 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -900,6 +900,7 @@ sp_create_routine(THD *thd, int type, sp_head *sp) DBUG_PRINT("enter", ("type: %d name: %.*s",type, (int) sp->m_name.length, sp->m_name.str)); String retstr(64); + retstr.set_charset(system_charset_info); DBUG_ASSERT(type == TYPE_ENUM_PROCEDURE || type == TYPE_ENUM_FUNCTION); @@ -1403,6 +1404,7 @@ sp_find_routine(THD *thd, int type, sp_name *name, sp_cache **cp, 64 -- size of "returns" column of mysql.proc. */ String retstr(64); + retstr.set_charset(sp->get_creation_ctx()->get_client_cs()); DBUG_PRINT("info", ("found: 0x%lx", (ulong)sp)); if (sp->m_first_free_instance) From 3707a74e6e97a86531d2284e8e3106b30c2297b2 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Thu, 3 Dec 2009 13:22:34 +0400 Subject: [PATCH 020/104] Bug#44131 Binary-mode "order by" returns records in incorrect order for UTF-8 strings Problem: Item_char_typecast reported wrong max_length when casting to BINARY, which lead, in particular, in wrong "ORDER BY BINARY(char_column)" results. Fix: making Item_char_typecast report correct max_length. @ mysql-test/r/ctype_utf16.result Fixing old incorrect test result. @ mysql-test/r/ctype_utf32.result Fixing old incorrect test result. @ mysql-test/r/ctype_utf8.result Adding new test @ mysql-test/t/ctype_utf8.test Adding new test @ sql/item_timefunc.cc Making Item_char_typecast report correct max_length when cast is done to BINARY. --- mysql-test/r/ctype_utf8.result | 18 ++++++++++++++++++ mysql-test/t/ctype_utf8.test | 10 ++++++++++ sql/item_timefunc.cc | 6 +++--- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 6f4ae965ca0..4c21e66a39c 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -1848,6 +1848,24 @@ select hex(_utf8 B'001111111111'); ERROR HY000: Invalid utf8 character string: 'FF' select (_utf8 X'616263FF'); ERROR HY000: Invalid utf8 character string: 'FF' +# +# Bug#44131 Binary-mode "order by" returns records in incorrect order for UTF-8 strings +# +CREATE TABLE t1 (id int not null primary key, name varchar(10)) character set utf8; +INSERT INTO t1 VALUES +(2,'一二三01'),(3,'一二三09'),(4,'一二三02'),(5,'一二三08'), +(6,'一二三11'),(7,'一二三91'),(8,'一二三21'),(9,'一二三81'); +SELECT * FROM t1 ORDER BY BINARY(name); +id name +2 一二三01 +4 一二三02 +5 一二三08 +3 一二三09 +6 一二三11 +8 一二三21 +9 一二三81 +7 一二三91 +DROP TABLE t1; CREATE TABLE t1 (a INT NOT NULL, b INT NOT NULL); INSERT INTO t1 VALUES (70000, 1092), (70001, 1085), (70002, 1065); SELECT CONVERT(a, CHAR), CONVERT(b, CHAR) FROM t1 GROUP BY b; diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index f0c769251cf..23c83310886 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -1440,6 +1440,16 @@ select hex(_utf8 B'001111111111'); --error ER_INVALID_CHARACTER_STRING select (_utf8 X'616263FF'); +--echo # +--echo # Bug#44131 Binary-mode "order by" returns records in incorrect order for UTF-8 strings +--echo # +CREATE TABLE t1 (id int not null primary key, name varchar(10)) character set utf8; +INSERT INTO t1 VALUES +(2,'一二三01'),(3,'一二三09'),(4,'一二三02'),(5,'一二三08'), +(6,'一二三11'),(7,'一二三91'),(8,'一二三21'),(9,'一二三81'); +SELECT * FROM t1 ORDER BY BINARY(name); +DROP TABLE t1; + # # Bug #36772: When using UTF8, CONVERT with GROUP BY returns truncated results # diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index b293145cc27..ded4d28ca29 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -2554,9 +2554,9 @@ void Item_char_typecast::fix_length_and_dec() from_cs != &my_charset_bin && cast_cs != &my_charset_bin); collation.set(cast_cs, DERIVATION_IMPLICIT); - char_length= (cast_length >= 0) ? - cast_length : - args[0]->max_length / args[0]->collation.collation->mbmaxlen; + char_length= (cast_length >= 0) ? cast_length : + args[0]->max_length / + (cast_cs == &my_charset_bin ? 1 : args[0]->collation.collation->mbmaxlen); max_length= char_length * cast_cs->mbmaxlen; } From 1457d7b3679956e5d97a34e58a7b0ff5dffcec85 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Thu, 3 Dec 2009 14:07:46 +0200 Subject: [PATCH 021/104] Bug #48985: show create table crashes if previous access to the table was killed When checking for an error after removing the special view error handler the code was not taking into account that open_tables() may fail because of the current statement being killed. Added a check for thd->killed. Added a client program to test it. --- mysql-test/r/show_check.result | 6 ++++++ mysql-test/t/show_check.test | 22 ++++++++++++++++++++++ sql/sql_show.cc | 2 +- 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index e6550bee954..ec0a70ff581 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -1454,4 +1454,10 @@ GRANT PROCESS ON *.* TO test_u@localhost; SHOW ENGINE MYISAM MUTEX; SHOW ENGINE MYISAM STATUS; DROP USER test_u@localhost; +# +# Bug #48985: show create table crashes if previous access to the table +# was killed +# +SHOW CREATE TABLE non_existent; +ERROR 70100: Query execution was interrupted End of 5.1 tests diff --git a/mysql-test/t/show_check.test b/mysql-test/t/show_check.test index 0ce807ae73e..d46261f38d2 100644 --- a/mysql-test/t/show_check.test +++ b/mysql-test/t/show_check.test @@ -1207,6 +1207,28 @@ connection default; DROP USER test_u@localhost; +--echo # +--echo # Bug #48985: show create table crashes if previous access to the table +--echo # was killed +--echo # + +connect(con1,localhost,root,,); +CONNECTION con1; +LET $ID= `SELECT connection_id()`; + +CONNECTION default; +--disable_query_log +eval KILL QUERY $ID; +--enable_query_log + +CONNECTION con1; +--error ER_QUERY_INTERRUPTED +SHOW CREATE TABLE non_existent; + +CONNECTION default; +DISCONNECT con1; + + --echo End of 5.1 tests # Wait till all disconnects are completed diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 2c1f360104b..e55000c0f65 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -719,7 +719,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) thd->push_internal_handler(&view_error_suppressor); bool error= open_normal_and_derived_tables(thd, table_list, 0); thd->pop_internal_handler(); - if (error && thd->main_da.is_error()) + if (error && (thd->killed || thd->main_da.is_error())) DBUG_RETURN(TRUE); } From dd46365a0bf752766a71ffc871dcedd29ff02200 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Thu, 3 Dec 2009 13:31:56 +0100 Subject: [PATCH 022/104] Bug#49369: No testcase for key caches on partitions The original test case was lost when merging WL#4571. Added the testcase. --- mysql-test/include/check_key_reads.inc | 6 + mysql-test/include/check_key_req.inc | 9 + mysql-test/r/partition_key_cache.result | 420 ++++++++++++++++++++++++ mysql-test/t/partition_key_cache.test | 252 ++++++++++++++ 4 files changed, 687 insertions(+) create mode 100644 mysql-test/include/check_key_reads.inc create mode 100644 mysql-test/include/check_key_req.inc create mode 100644 mysql-test/r/partition_key_cache.result create mode 100644 mysql-test/t/partition_key_cache.test diff --git a/mysql-test/include/check_key_reads.inc b/mysql-test/include/check_key_reads.inc new file mode 100644 index 00000000000..cfb754bccd4 --- /dev/null +++ b/mysql-test/include/check_key_reads.inc @@ -0,0 +1,6 @@ +# include file for checking if variable key_reads is zero +let $key_reads= query_get_value(SHOW STATUS LIKE 'key_reads',Value,1); +--disable_query_log +eval SELECT IF($key_reads = 0, "Yes!", "No!") as 'Zero key reads?'; +FLUSH STATUS; +--enable_query_log diff --git a/mysql-test/include/check_key_req.inc b/mysql-test/include/check_key_req.inc new file mode 100644 index 00000000000..92a81f09d91 --- /dev/null +++ b/mysql-test/include/check_key_req.inc @@ -0,0 +1,9 @@ +# include file for checking if variable key_reads = key_read_requests +let $key_reads= query_get_value(SHOW STATUS LIKE 'key_reads',Value,1); +let $key_r_req= query_get_value(SHOW STATUS LIKE 'key_read_requests',Value,1); +let $key_writes= query_get_value(SHOW STATUS LIKE 'key_writes',Value,1); +let $key_w_req= query_get_value(SHOW STATUS LIKE 'key_write_requests',Value,1); +--disable_query_log +eval SELECT IF($key_reads = $key_r_req, "reads == requests", "reads != requests") as 'reads vs requests'; +eval SELECT IF($key_writes = $key_w_req, "writes == requests", "writes != requests") as 'writes vs requests'; +--enable_query_log diff --git a/mysql-test/r/partition_key_cache.result b/mysql-test/r/partition_key_cache.result new file mode 100644 index 00000000000..c09f277840b --- /dev/null +++ b/mysql-test/r/partition_key_cache.result @@ -0,0 +1,420 @@ +DROP TABLE IF EXISTS t1, t2, v, x; +# Actual test of key caches +# Verifing that reads/writes use the key cache correctly +SELECT @org_key_cache_buffer_size:= @@global.default.key_buffer_size; +@org_key_cache_buffer_size:= @@global.default.key_buffer_size +1048576 +# Minimize default key cache (almost disabled). +SET @@global.default.key_buffer_size = 1; +Warnings: +Warning 1292 Truncated incorrect key_buffer_size value: '1' +SELECT @@global.default.key_buffer_size; +@@global.default.key_buffer_size +36 +CREATE TABLE t1 ( +a INT, +b INT, +c INT NOT NULL, +PRIMARY KEY (a), +KEY `inx_b` (b)) +PARTITION BY RANGE (a) +SUBPARTITION BY HASH (a) +(PARTITION p0 VALUES LESS THAN (1167602410) +(SUBPARTITION sp0, +SUBPARTITION sp1), +PARTITION p1 VALUES LESS THAN MAXVALUE +(SUBPARTITION sp2, +SUBPARTITION sp3)); +CREATE TABLE t2 ( +a INT, +b INT, +c INT NOT NULL, +PRIMARY KEY (a), +KEY `inx_b` (b)); +FLUSH TABLES; +FLUSH STATUS; +SET @a:=1167602400; +CREATE VIEW v AS SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4; +CREATE VIEW x AS SELECT 1 FROM v,v a,v b; +FLUSH STATUS; +INSERT t1 SELECT @a, @a * (1 - ((@a % 2) * 2)) , 1167612400 - (@a:=@a+1) FROM x, x y; +reads vs requests +reads == requests +writes vs requests +writes == requests +# row distribution: +SELECT PARTITION_NAME, SUBPARTITION_NAME, TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_SCHEMA='test' and TABLE_NAME='t1'; +PARTITION_NAME SUBPARTITION_NAME TABLE_ROWS +p0 sp0 5 +p0 sp1 5 +p1 sp2 2043 +p1 sp3 2043 +DROP VIEW x; +DROP VIEW v; +FLUSH TABLES; +FLUSH STATUS; +SELECT COUNT(b) FROM t1 WHERE b >= 0; +COUNT(b) +2048 +Zero key reads? +No! +INSERT t2 SELECT a,b,c FROM t1; +reads vs requests +reads == requests +writes vs requests +writes == requests +FLUSH STATUS; +SELECT COUNT(b) FROM t2 WHERE b >= 0; +COUNT(b) +2048 +Zero key reads? +No! +FLUSH TABLES; +# Setting the default key cache to 1M +SET GLOBAL key_buffer_size = 1024*1024; +FLUSH STATUS; +# All these have to read the indexes +LOAD INDEX INTO CACHE t1 PARTITION (p1); +Table Op Msg_type Msg_text +test.t1 preload_keys status OK +Zero key reads? +No! +SELECT COUNT(b) FROM t1 WHERE b >= 0; +COUNT(b) +2048 +Zero key reads? +No! +SELECT COUNT(b) FROM t2 WHERE b >= 0; +COUNT(b) +2048 +Zero key reads? +No! +# All these should be able to use the key cache +SELECT COUNT(b) FROM t1 WHERE b >= 0; +COUNT(b) +2048 +Zero key reads? +Yes! +SELECT COUNT(b) FROM t2 WHERE b >= 0; +COUNT(b) +2048 +Zero key reads? +Yes! +FLUSH TABLES; +LOAD INDEX INTO CACHE t1 PARTITION (p1,p0); +Table Op Msg_type Msg_text +test.t1 preload_keys status OK +Zero key reads? +No! +# should not be zero +SELECT COUNT(b) FROM t1 WHERE b >= 0; +COUNT(b) +2048 +Zero key reads? +Yes! +LOAD INDEX INTO CACHE t2; +Table Op Msg_type Msg_text +test.t2 preload_keys status OK +Zero key reads? +No! +# should not be zero +SELECT COUNT(b) FROM t2 WHERE b >= 0; +COUNT(b) +2048 +Zero key reads? +Yes! +FLUSH TABLES; +LOAD INDEX INTO CACHE t1 PARTITION (p1,p0) IGNORE LEAVES; +Table Op Msg_type Msg_text +test.t1 preload_keys status OK +Zero key reads? +No! +# should not be zero +SELECT COUNT(b) FROM t1 WHERE b >= 0; +COUNT(b) +2048 +Zero key reads? +No! +LOAD INDEX INTO CACHE t2 IGNORE LEAVES; +Table Op Msg_type Msg_text +test.t2 preload_keys status OK +Zero key reads? +No! +# should not be zero +SELECT COUNT(b) FROM t2 WHERE b >= 0; +COUNT(b) +2048 +Zero key reads? +No! +TRUNCATE TABLE t2; +INSERT t2 SELECT a,b,c FROM t1; +reads vs requests +reads != requests +writes vs requests +writes != requests +DROP TABLE t1,t2; +SET GLOBAL hot_cache.key_buffer_size = 1024*1024; +SET GLOBAL warm_cache.key_buffer_size = 1024*1024; +SET @@global.cold_cache.key_buffer_size = 1024*1024; +SELECT @@global.default.key_buffer_size a, @@global.default.key_cache_block_size b, @@global.default.key_cache_age_threshold c, @@global.default.key_cache_division_limit d; +a b c d +1048576 1024 300 100 +SELECT @@global.hot_cache.key_buffer_size a, @@global.hot_cache.key_cache_block_size b, @@global.hot_cache.key_cache_age_threshold c, @@global.hot_cache.key_cache_division_limit d; +a b c d +1048576 1024 300 100 +SELECT @@global.warm_cache.key_buffer_size a, @@global.warm_cache.key_cache_block_size b, @@global.warm_cache.key_cache_age_threshold c, @@global.warm_cache.key_cache_division_limit d; +a b c d +1048576 1024 300 100 +SELECT @@global.cold_cache.key_buffer_size a, @@global.cold_cache.key_cache_block_size b, @@global.cold_cache.key_cache_age_threshold c, @@global.cold_cache.key_cache_division_limit d; +a b c d +1048576 1024 300 100 +CREATE TABLE t1 ( +a INT, +b VARCHAR(257), +c INT NOT NULL, +PRIMARY KEY (a), +KEY `inx_b` (b), +KEY `inx_c`(c)) +PARTITION BY RANGE (a) +SUBPARTITION BY HASH (a) +(PARTITION p0 VALUES LESS THAN (10) +(SUBPARTITION sp0, +SUBPARTITION sp1), +PARTITION p1 VALUES LESS THAN MAXVALUE +(SUBPARTITION sp2, +SUBPARTITION sp3)); +CREATE TABLE t2 ( +a INT, +b VARCHAR(257), +c INT NOT NULL, +PRIMARY KEY (a), +KEY `inx_b` (b), +KEY `inx_c`(c)); +SET @a:=1167602400; +CREATE VIEW v AS SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4; +CREATE VIEW x AS SELECT 1 FROM v,v a,v b; +INSERT t1 SELECT @a, CONCAT('X_', @a, ' MySQL'), 1167612400 - (@a:=@a+1) FROM x, x a; +DROP VIEW x; +DROP VIEW v; +INSERT t2 SELECT a, b, c FROM t1; +SELECT COUNT(*) FROM t1; +COUNT(*) +4096 +SELECT COUNT(*) FROM t2; +COUNT(*) +4096 +FLUSH TABLES; +# Restrict partitioned commands to partitioned tables only +CACHE INDEX t2 PARTITION (p0) KEY (`inx_b`) IN hot_cache; +ERROR HY000: Partition management on a not partitioned table is not possible +CACHE INDEX t2 PARTITION (p0,`p1`) INDEX (`PRIMARY`) IN hot_cache; +ERROR HY000: Partition management on a not partitioned table is not possible +CACHE INDEX t2 PARTITION (`p1`) INDEX (`PRIMARY`,`inx_b`) IN hot_cache; +ERROR HY000: Partition management on a not partitioned table is not possible +CACHE INDEX t2 PARTITION (ALL) KEY (`inx_b`,`PRIMARY`) IN hot_cache; +ERROR HY000: Partition management on a not partitioned table is not possible +# Basic key cache testing +# The manual correctly says: "The syntax of CACHE INDEX enables you to +# specify that only particular indexes from a table should be assigned +# to the cache. The current implementation assigns all the table's +# indexes to the cache, so there is no reason to specify anything +# other than the table name." +# So the most of the test only tests the syntax +CACHE INDEX t2 INDEX (`inx_b`) IN hot_cache; +Table Op Msg_type Msg_text +test.t2 assign_to_keycache status OK +CACHE INDEX t2 KEY (`PRIMARY`) IN warm_cache; +Table Op Msg_type Msg_text +test.t2 assign_to_keycache status OK +CACHE INDEX t2 KEY (`PRIMARY`,`inx_b`) IN cold_cache; +Table Op Msg_type Msg_text +test.t2 assign_to_keycache status OK +CACHE INDEX t2 INDEX (inx_b,`PRIMARY`) IN default; +Table Op Msg_type Msg_text +test.t2 assign_to_keycache status OK +CACHE INDEX t1 PARTITION (p0) KEY (`inx_b`) IN cold_cache; +Table Op Msg_type Msg_text +test.t1 assign_to_keycache status OK +CACHE INDEX t1 PARTITIONS (p0) KEY (`inx_b`) IN cold_cache; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'PARTITIONS (p0) KEY (`inx_b`) IN cold_cache' at line 1 +# only one table at a time if specifying partitions +CACHE INDEX t1,t2 PARTITION (p0) KEY (`inx_b`) IN cold_cache; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'PARTITION (p0) KEY (`inx_b`) IN cold_cache' at line 1 +CACHE INDEX t1 PARTITION (`p0`,p1) INDEX (`PRIMARY`) IN warm_cache; +Table Op Msg_type Msg_text +test.t1 assign_to_keycache status OK +CACHE INDEX t1 PARTITION (`p1`) INDEX (`PRIMARY`,inx_b) IN hot_cache; +Table Op Msg_type Msg_text +test.t1 assign_to_keycache status OK +CACHE INDEX t1 PARTITION (ALL) KEY (`inx_b`,`PRIMARY`) IN default; +Table Op Msg_type Msg_text +test.t1 assign_to_keycache status OK +CACHE INDEX t1 PARTITION (ALL) IN hot_cache; +Table Op Msg_type Msg_text +test.t1 assign_to_keycache status OK +CACHE INDEX t1 INDEX (`inx_b`) IN default; +Table Op Msg_type Msg_text +test.t1 assign_to_keycache status OK +CACHE INDEX t1 KEY (`PRIMARY`) IN hot_cache; +Table Op Msg_type Msg_text +test.t1 assign_to_keycache status OK +CACHE INDEX t1 KEY (`PRIMARY`,`inx_b`) IN warm_cache; +Table Op Msg_type Msg_text +test.t1 assign_to_keycache status OK +CACHE INDEX t1 INDEX (`inx_b`,`PRIMARY`) IN cold_cache; +Table Op Msg_type Msg_text +test.t1 assign_to_keycache status OK +CACHE INDEX t1 IN hot_cache; +Table Op Msg_type Msg_text +test.t1 assign_to_keycache status OK +# Test of non existent key cache: +CACHE INDEX t1 IN non_existent_key_cache; +ERROR HY000: Unknown key cache 'non_existent_key_cache' +# Basic testing of LOAD INDEX +LOAD INDEX INTO CACHE t2; +Table Op Msg_type Msg_text +test.t2 preload_keys status OK +# PRIMARY and secondary keys have different block sizes +LOAD INDEX INTO CACHE t2 ignore leaves; +Table Op Msg_type Msg_text +test.t2 preload_keys error Indexes use different block sizes +test.t2 preload_keys status Operation failed +# Must have INDEX or KEY before the index list +LOAD INDEX INTO CACHE t2 (`PRIMARY`); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '(`PRIMARY`)' at line 1 +# Test of IGNORE LEAVES +LOAD INDEX INTO CACHE t2 INDEX (`PRIMARY`); +Table Op Msg_type Msg_text +test.t2 preload_keys status OK +LOAD INDEX INTO CACHE t2 KEY (`PRIMARY`,`inx_b`) IGNORE LEAVES; +Table Op Msg_type Msg_text +test.t2 preload_keys error Indexes use different block sizes +test.t2 preload_keys status Operation failed +CACHE INDEX t2 IN warm_cache; +Table Op Msg_type Msg_text +test.t2 assign_to_keycache status OK +CACHE INDEX t1 IN cold_cache; +Table Op Msg_type Msg_text +test.t1 assign_to_keycache status OK +LOAD INDEX INTO CACHE t2 KEY (`PRIMARY`) IGNORE LEAVES; +Table Op Msg_type Msg_text +test.t2 preload_keys error Indexes use different block sizes +test.t2 preload_keys status Operation failed +CACHE INDEX t2 INDEX (`inx_b`, `inx_c`) IN hot_cache; +Table Op Msg_type Msg_text +test.t2 assign_to_keycache status OK +LOAD INDEX INTO CACHE t2 KEY (`inx_b`, `inx_c`) IGNORE LEAVES; +Table Op Msg_type Msg_text +test.t2 preload_keys error Indexes use different block sizes +test.t2 preload_keys status Operation failed +CACHE INDEX t2 IN warm_cache; +Table Op Msg_type Msg_text +test.t2 assign_to_keycache status OK +CACHE INDEX t2 INDEX (`PRIMARY`, `inx_c`) IN hot_cache; +Table Op Msg_type Msg_text +test.t2 assign_to_keycache status OK +LOAD INDEX INTO CACHE t2 KEY (`PRIMARY`,`inx_c`) IGNORE LEAVES; +Table Op Msg_type Msg_text +test.t2 preload_keys error Indexes use different block sizes +test.t2 preload_keys status Operation failed +CACHE INDEX t2 INDEX (`inx_b`,`PRIMARY`) IN default; +Table Op Msg_type Msg_text +test.t2 assign_to_keycache status OK +LOAD INDEX INTO CACHE t2 KEY (`PRIMARY`,`inx_b`); +Table Op Msg_type Msg_text +test.t2 preload_keys status OK +CACHE INDEX t2 IN default; +Table Op Msg_type Msg_text +test.t2 assign_to_keycache status OK +LOAD INDEX INTO CACHE t2 IGNORE LEAVES; +Table Op Msg_type Msg_text +test.t2 preload_keys error Indexes use different block sizes +test.t2 preload_keys status Operation failed +LOAD INDEX INTO CACHE t2 PARTITION (p1) INDEX (`PRIMARY`); +ERROR HY000: Partition management on a not partitioned table is not possible +LOAD INDEX INTO CACHE t1, t2; +Table Op Msg_type Msg_text +test.t1 preload_keys status OK +test.t2 preload_keys status OK +# only one table at a time if specifying partitions +LOAD INDEX INTO CACHE t1 PARTITION (p0), t2; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ' t2' at line 1 +LOAD INDEX INTO CACHE t1 IGNORE LEAVES; +Table Op Msg_type Msg_text +test.t1 preload_keys error Indexes use different block sizes +test.t1 preload_keys error Subpartition sp2 returned error +test.t1 preload_keys status Operation failed +LOAD INDEX INTO CACHE t1 INDEX (`PRIMARY`); +Table Op Msg_type Msg_text +test.t1 preload_keys status OK +LOAD INDEX INTO CACHE t1 INDEX (`PRIMARY`,`inx_b`) IGNORE LEAVES; +Table Op Msg_type Msg_text +test.t1 preload_keys error Indexes use different block sizes +test.t1 preload_keys error Subpartition sp2 returned error +test.t1 preload_keys status Operation failed +LOAD INDEX INTO CACHE t1 INDEX (`inx_b`) IGNORE LEAVES; +Table Op Msg_type Msg_text +test.t1 preload_keys error Indexes use different block sizes +test.t1 preload_keys error Subpartition sp2 returned error +test.t1 preload_keys status Operation failed +LOAD INDEX INTO CACHE t1 INDEX (`PRIMARY`) IGNORE LEAVES; +Table Op Msg_type Msg_text +test.t1 preload_keys error Indexes use different block sizes +test.t1 preload_keys error Subpartition sp2 returned error +test.t1 preload_keys status Operation failed +LOAD INDEX INTO CACHE t1 INDEX (`PRIMARY`,`inx_b`); +Table Op Msg_type Msg_text +test.t1 preload_keys status OK +LOAD INDEX INTO CACHE t1 PARTITION (p1) INDEX (`PRIMARY`); +Table Op Msg_type Msg_text +test.t1 preload_keys status OK +LOAD INDEX INTO CACHE t1 PARTITION (`p1`,p0) KEY (`PRIMARY`) IGNORE LEAVES; +Table Op Msg_type Msg_text +test.t1 preload_keys error Indexes use different block sizes +test.t1 preload_keys error Subpartition sp2 returned error +test.t1 preload_keys status Operation failed +LOAD INDEX INTO CACHE t1 PARTITION (ALL); +Table Op Msg_type Msg_text +test.t1 preload_keys status OK +LOAD INDEX INTO CACHE t1 PARTITIONS ALL; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'PARTITIONS ALL' at line 1 +LOAD INDEX INTO CACHE t1 PARTITION (p1,`p0`) IGNORE LEAVES; +Table Op Msg_type Msg_text +test.t1 preload_keys error Indexes use different block sizes +test.t1 preload_keys error Subpartition sp2 returned error +test.t1 preload_keys status Operation failed +DROP INDEX `inx_b` on t1; +DROP INDEX `inx_b` on t2; +CACHE INDEX t2 PARTITION (p0) KEY (`inx_b`) IN hot_cache; +ERROR HY000: Partition management on a not partitioned table is not possible +CACHE INDEX t2 INDEX (`inx_b`) IN hot_cache; +Table Op Msg_type Msg_text +test.t2 assign_to_keycache Error Key 'inx_b' doesn't exist in table 't2' +test.t2 assign_to_keycache status Operation failed +CACHE INDEX t1 PARTITION (p0) KEY (`inx_b`) IN hot_cache; +Table Op Msg_type Msg_text +test.t1 assign_to_keycache error Subpartition sp0 returned error +test.t1 assign_to_keycache Error Key 'inx_b' doesn't exist in table 't1' +test.t1 assign_to_keycache status Operation failed +CACHE INDEX t1 INDEX (`inx_b`) IN hot_cache; +Table Op Msg_type Msg_text +test.t1 assign_to_keycache error Subpartition sp0 returned error +test.t1 assign_to_keycache Error Key 'inx_b' doesn't exist in table 't1' +test.t1 assign_to_keycache status Operation failed +DROP TABLE t1,t2; +SET GLOBAL hot_cache.key_buffer_size = 0; +SET GLOBAL warm_cache.key_buffer_size = 0; +SET @@global.cold_cache.key_buffer_size = 0; +SELECT @@global.default.key_buffer_size a, @@global.default.key_cache_block_size b, @@global.default.key_cache_age_threshold c, @@global.default.key_cache_division_limit d; +a b c d +1048576 1024 300 100 +SELECT @@global.hot_cache.key_buffer_size a, @@global.hot_cache.key_cache_block_size b, @@global.hot_cache.key_cache_age_threshold c, @@global.hot_cache.key_cache_division_limit d; +a b c d +0 1024 300 100 +SELECT @@global.warm_cache.key_buffer_size a, @@global.warm_cache.key_cache_block_size b, @@global.warm_cache.key_cache_age_threshold c, @@global.warm_cache.key_cache_division_limit d; +a b c d +0 1024 300 100 +SELECT @@global.cold_cache.key_buffer_size a, @@global.cold_cache.key_cache_block_size b, @@global.cold_cache.key_cache_age_threshold c, @@global.cold_cache.key_cache_division_limit d; +a b c d +0 1024 300 100 +SET @@global.default.key_buffer_size = @org_key_cache_buffer_size; diff --git a/mysql-test/t/partition_key_cache.test b/mysql-test/t/partition_key_cache.test new file mode 100644 index 00000000000..34f3d4de19c --- /dev/null +++ b/mysql-test/t/partition_key_cache.test @@ -0,0 +1,252 @@ +# Test of key cache with partitions +--source include/have_partition.inc + +--disable_warnings +DROP TABLE IF EXISTS t1, t2, v, x; +--enable_warnings + +--echo # Actual test of key caches +--echo # Verifing that reads/writes use the key cache correctly +SELECT @org_key_cache_buffer_size:= @@global.default.key_buffer_size; +--echo # Minimize default key cache (almost disabled). +SET @@global.default.key_buffer_size = 1; +SELECT @@global.default.key_buffer_size; +CREATE TABLE t1 ( + a INT, + b INT, + c INT NOT NULL, + PRIMARY KEY (a), + KEY `inx_b` (b)) +PARTITION BY RANGE (a) +SUBPARTITION BY HASH (a) +(PARTITION p0 VALUES LESS THAN (1167602410) + (SUBPARTITION sp0, + SUBPARTITION sp1), + PARTITION p1 VALUES LESS THAN MAXVALUE + (SUBPARTITION sp2, + SUBPARTITION sp3)); +CREATE TABLE t2 ( + a INT, + b INT, + c INT NOT NULL, + PRIMARY KEY (a), + KEY `inx_b` (b)); +FLUSH TABLES; +FLUSH STATUS; + +# Genereate 4096 rows. Idea from: +# http://datacharmer.blogspot.com/2007/12/data-from-nothing-solution-to-pop-quiz.html +SET @a:=1167602400; +CREATE VIEW v AS SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4; +CREATE VIEW x AS SELECT 1 FROM v,v a,v b; +# due to I_S performance, this was substituted with include files which +# uses SHOW STATUS +#DELIMITER |; +#CREATE PROCEDURE was_zero_reads() +#BEGIN +# SELECT IF(VARIABLE_VALUE = 0,"Yes!","No!") as 'Was zero reads?' +# FROM INFORMATION_SCHEMA.SESSION_STATUS +# WHERE VARIABLE_NAME = 'KEY_READS'; +# FLUSH STATUS; +#END| +#DELIMITER ;| + +FLUSH STATUS; +INSERT t1 SELECT @a, @a * (1 - ((@a % 2) * 2)) , 1167612400 - (@a:=@a+1) FROM x, x y; +--source include/check_key_req.inc +--echo # row distribution: +SELECT PARTITION_NAME, SUBPARTITION_NAME, TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_SCHEMA='test' and TABLE_NAME='t1'; +DROP VIEW x; +DROP VIEW v; +FLUSH TABLES; +FLUSH STATUS; +SELECT COUNT(b) FROM t1 WHERE b >= 0; +--source include/check_key_reads.inc +INSERT t2 SELECT a,b,c FROM t1; +--source include/check_key_req.inc +FLUSH STATUS; +SELECT COUNT(b) FROM t2 WHERE b >= 0; +--source include/check_key_reads.inc +FLUSH TABLES; +--echo # Setting the default key cache to 1M +SET GLOBAL key_buffer_size = 1024*1024; +FLUSH STATUS; +--echo # All these have to read the indexes +LOAD INDEX INTO CACHE t1 PARTITION (p1); +--source include/check_key_reads.inc +SELECT COUNT(b) FROM t1 WHERE b >= 0; +--source include/check_key_reads.inc +SELECT COUNT(b) FROM t2 WHERE b >= 0; +--source include/check_key_reads.inc +--echo # All these should be able to use the key cache +SELECT COUNT(b) FROM t1 WHERE b >= 0; +--source include/check_key_reads.inc +SELECT COUNT(b) FROM t2 WHERE b >= 0; +--source include/check_key_reads.inc +FLUSH TABLES; +LOAD INDEX INTO CACHE t1 PARTITION (p1,p0); +--source include/check_key_reads.inc +--echo # should not be zero +SELECT COUNT(b) FROM t1 WHERE b >= 0; +--source include/check_key_reads.inc +LOAD INDEX INTO CACHE t2; +--source include/check_key_reads.inc +--echo # should not be zero +SELECT COUNT(b) FROM t2 WHERE b >= 0; +--source include/check_key_reads.inc +FLUSH TABLES; +LOAD INDEX INTO CACHE t1 PARTITION (p1,p0) IGNORE LEAVES; +--source include/check_key_reads.inc +--echo # should not be zero +SELECT COUNT(b) FROM t1 WHERE b >= 0; +--source include/check_key_reads.inc +LOAD INDEX INTO CACHE t2 IGNORE LEAVES; +--source include/check_key_reads.inc +--echo # should not be zero +SELECT COUNT(b) FROM t2 WHERE b >= 0; +--source include/check_key_reads.inc +TRUNCATE TABLE t2; +INSERT t2 SELECT a,b,c FROM t1; +--source include/check_key_req.inc +DROP TABLE t1,t2; + +SET GLOBAL hot_cache.key_buffer_size = 1024*1024; +SET GLOBAL warm_cache.key_buffer_size = 1024*1024; +SET @@global.cold_cache.key_buffer_size = 1024*1024; +SELECT @@global.default.key_buffer_size a, @@global.default.key_cache_block_size b, @@global.default.key_cache_age_threshold c, @@global.default.key_cache_division_limit d; +SELECT @@global.hot_cache.key_buffer_size a, @@global.hot_cache.key_cache_block_size b, @@global.hot_cache.key_cache_age_threshold c, @@global.hot_cache.key_cache_division_limit d; +SELECT @@global.warm_cache.key_buffer_size a, @@global.warm_cache.key_cache_block_size b, @@global.warm_cache.key_cache_age_threshold c, @@global.warm_cache.key_cache_division_limit d; +SELECT @@global.cold_cache.key_buffer_size a, @@global.cold_cache.key_cache_block_size b, @@global.cold_cache.key_cache_age_threshold c, @@global.cold_cache.key_cache_division_limit d; +CREATE TABLE t1 ( + a INT, + b VARCHAR(257), + c INT NOT NULL, + PRIMARY KEY (a), + KEY `inx_b` (b), + KEY `inx_c`(c)) +PARTITION BY RANGE (a) +SUBPARTITION BY HASH (a) +(PARTITION p0 VALUES LESS THAN (10) + (SUBPARTITION sp0, + SUBPARTITION sp1), + PARTITION p1 VALUES LESS THAN MAXVALUE + (SUBPARTITION sp2, + SUBPARTITION sp3)); +CREATE TABLE t2 ( + a INT, + b VARCHAR(257), + c INT NOT NULL, + PRIMARY KEY (a), + KEY `inx_b` (b), + KEY `inx_c`(c)); +SET @a:=1167602400; +# Genereate 4096 rows. Idea from: +# http://datacharmer.blogspot.com/2007/12/data-from-nothing-solution-to-pop-quiz.html +CREATE VIEW v AS SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4; +CREATE VIEW x AS SELECT 1 FROM v,v a,v b; +INSERT t1 SELECT @a, CONCAT('X_', @a, ' MySQL'), 1167612400 - (@a:=@a+1) FROM x, x a; +DROP VIEW x; +DROP VIEW v; +INSERT t2 SELECT a, b, c FROM t1; +SELECT COUNT(*) FROM t1; +SELECT COUNT(*) FROM t2; +FLUSH TABLES; + +--echo # Restrict partitioned commands to partitioned tables only +--error ER_PARTITION_MGMT_ON_NONPARTITIONED +CACHE INDEX t2 PARTITION (p0) KEY (`inx_b`) IN hot_cache; +--error ER_PARTITION_MGMT_ON_NONPARTITIONED +CACHE INDEX t2 PARTITION (p0,`p1`) INDEX (`PRIMARY`) IN hot_cache; +--error ER_PARTITION_MGMT_ON_NONPARTITIONED +CACHE INDEX t2 PARTITION (`p1`) INDEX (`PRIMARY`,`inx_b`) IN hot_cache; +--error ER_PARTITION_MGMT_ON_NONPARTITIONED +CACHE INDEX t2 PARTITION (ALL) KEY (`inx_b`,`PRIMARY`) IN hot_cache; +--echo # Basic key cache testing +--echo # The manual correctly says: "The syntax of CACHE INDEX enables you to +--echo # specify that only particular indexes from a table should be assigned +--echo # to the cache. The current implementation assigns all the table's +--echo # indexes to the cache, so there is no reason to specify anything +--echo # other than the table name." +--echo # So the most of the test only tests the syntax +CACHE INDEX t2 INDEX (`inx_b`) IN hot_cache; +CACHE INDEX t2 KEY (`PRIMARY`) IN warm_cache; +CACHE INDEX t2 KEY (`PRIMARY`,`inx_b`) IN cold_cache; +CACHE INDEX t2 INDEX (inx_b,`PRIMARY`) IN default; +CACHE INDEX t1 PARTITION (p0) KEY (`inx_b`) IN cold_cache; +--error ER_PARSE_ERROR +CACHE INDEX t1 PARTITIONS (p0) KEY (`inx_b`) IN cold_cache; +--echo # only one table at a time if specifying partitions +--error ER_PARSE_ERROR +CACHE INDEX t1,t2 PARTITION (p0) KEY (`inx_b`) IN cold_cache; +CACHE INDEX t1 PARTITION (`p0`,p1) INDEX (`PRIMARY`) IN warm_cache; +CACHE INDEX t1 PARTITION (`p1`) INDEX (`PRIMARY`,inx_b) IN hot_cache; +CACHE INDEX t1 PARTITION (ALL) KEY (`inx_b`,`PRIMARY`) IN default; +CACHE INDEX t1 PARTITION (ALL) IN hot_cache; +CACHE INDEX t1 INDEX (`inx_b`) IN default; +CACHE INDEX t1 KEY (`PRIMARY`) IN hot_cache; +CACHE INDEX t1 KEY (`PRIMARY`,`inx_b`) IN warm_cache; +CACHE INDEX t1 INDEX (`inx_b`,`PRIMARY`) IN cold_cache; +CACHE INDEX t1 IN hot_cache; +--echo # Test of non existent key cache: +--error ER_UNKNOWN_KEY_CACHE +CACHE INDEX t1 IN non_existent_key_cache; +--echo # Basic testing of LOAD INDEX +LOAD INDEX INTO CACHE t2; +--echo # PRIMARY and secondary keys have different block sizes +LOAD INDEX INTO CACHE t2 ignore leaves; +--echo # Must have INDEX or KEY before the index list +--error ER_PARSE_ERROR +LOAD INDEX INTO CACHE t2 (`PRIMARY`); + +--echo # Test of IGNORE LEAVES +LOAD INDEX INTO CACHE t2 INDEX (`PRIMARY`); +LOAD INDEX INTO CACHE t2 KEY (`PRIMARY`,`inx_b`) IGNORE LEAVES; +CACHE INDEX t2 IN warm_cache; +CACHE INDEX t1 IN cold_cache; +LOAD INDEX INTO CACHE t2 KEY (`PRIMARY`) IGNORE LEAVES; +CACHE INDEX t2 INDEX (`inx_b`, `inx_c`) IN hot_cache; +LOAD INDEX INTO CACHE t2 KEY (`inx_b`, `inx_c`) IGNORE LEAVES; +CACHE INDEX t2 IN warm_cache; +CACHE INDEX t2 INDEX (`PRIMARY`, `inx_c`) IN hot_cache; +LOAD INDEX INTO CACHE t2 KEY (`PRIMARY`,`inx_c`) IGNORE LEAVES; +CACHE INDEX t2 INDEX (`inx_b`,`PRIMARY`) IN default; +LOAD INDEX INTO CACHE t2 KEY (`PRIMARY`,`inx_b`); +CACHE INDEX t2 IN default; +LOAD INDEX INTO CACHE t2 IGNORE LEAVES; + +--error ER_PARTITION_MGMT_ON_NONPARTITIONED +LOAD INDEX INTO CACHE t2 PARTITION (p1) INDEX (`PRIMARY`); +LOAD INDEX INTO CACHE t1, t2; +--echo # only one table at a time if specifying partitions +--error ER_PARSE_ERROR +LOAD INDEX INTO CACHE t1 PARTITION (p0), t2; +LOAD INDEX INTO CACHE t1 IGNORE LEAVES; +LOAD INDEX INTO CACHE t1 INDEX (`PRIMARY`); +LOAD INDEX INTO CACHE t1 INDEX (`PRIMARY`,`inx_b`) IGNORE LEAVES; +LOAD INDEX INTO CACHE t1 INDEX (`inx_b`) IGNORE LEAVES; +LOAD INDEX INTO CACHE t1 INDEX (`PRIMARY`) IGNORE LEAVES; +LOAD INDEX INTO CACHE t1 INDEX (`PRIMARY`,`inx_b`); +LOAD INDEX INTO CACHE t1 PARTITION (p1) INDEX (`PRIMARY`); +LOAD INDEX INTO CACHE t1 PARTITION (`p1`,p0) KEY (`PRIMARY`) IGNORE LEAVES; +LOAD INDEX INTO CACHE t1 PARTITION (ALL); +--error ER_PARSE_ERROR +LOAD INDEX INTO CACHE t1 PARTITIONS ALL; +LOAD INDEX INTO CACHE t1 PARTITION (p1,`p0`) IGNORE LEAVES; +DROP INDEX `inx_b` on t1; +DROP INDEX `inx_b` on t2; +--error ER_PARTITION_MGMT_ON_NONPARTITIONED +CACHE INDEX t2 PARTITION (p0) KEY (`inx_b`) IN hot_cache; +CACHE INDEX t2 INDEX (`inx_b`) IN hot_cache; +CACHE INDEX t1 PARTITION (p0) KEY (`inx_b`) IN hot_cache; +CACHE INDEX t1 INDEX (`inx_b`) IN hot_cache; +DROP TABLE t1,t2; +SET GLOBAL hot_cache.key_buffer_size = 0; +SET GLOBAL warm_cache.key_buffer_size = 0; +SET @@global.cold_cache.key_buffer_size = 0; +SELECT @@global.default.key_buffer_size a, @@global.default.key_cache_block_size b, @@global.default.key_cache_age_threshold c, @@global.default.key_cache_division_limit d; +SELECT @@global.hot_cache.key_buffer_size a, @@global.hot_cache.key_cache_block_size b, @@global.hot_cache.key_cache_age_threshold c, @@global.hot_cache.key_cache_division_limit d; +SELECT @@global.warm_cache.key_buffer_size a, @@global.warm_cache.key_cache_block_size b, @@global.warm_cache.key_cache_age_threshold c, @@global.warm_cache.key_cache_division_limit d; +SELECT @@global.cold_cache.key_buffer_size a, @@global.cold_cache.key_cache_block_size b, @@global.cold_cache.key_cache_age_threshold c, @@global.cold_cache.key_cache_division_limit d; +--disable_warnings +SET @@global.default.key_buffer_size = @org_key_cache_buffer_size; +--enable_warnings From a2f18f44c6c5e89d7b147a8a1312f734b957965f Mon Sep 17 00:00:00 2001 From: Evgeny Potemkin Date: Thu, 3 Dec 2009 16:15:20 +0300 Subject: [PATCH 023/104] Bug#48508: Crash on prepared statement re-execution. Test case cleanup. --- mysql-test/r/ps.result | 2 ++ mysql-test/t/ps.test | 2 ++ 2 files changed, 4 insertions(+) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index e7894388494..8a19b9b17e1 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -1902,6 +1902,7 @@ execute stmt; a execute stmt; a +deallocate prepare stmt; drop table t1; drop view v1; create table t1(a bigint); @@ -1912,6 +1913,7 @@ execute stmt; 1 execute stmt; 1 +deallocate prepare stmt; drop table t1,t2; # End of 5.0 tests. diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 6134efb5c5c..8f8e943913f 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -1982,6 +1982,7 @@ create view v1 AS select 1 as a from t1 where b; prepare stmt from "select * from v1 where a"; execute stmt; execute stmt; +deallocate prepare stmt; drop table t1; drop view v1; @@ -1991,6 +1992,7 @@ insert into t2 values (null); prepare stmt from "select 1 from t1 join t2 on a xor b where b > 1 and a =1"; execute stmt; execute stmt; +deallocate prepare stmt; drop table t1,t2; --echo # From 99654c27f07a22fcd291d46e97cb01b68e1249fb Mon Sep 17 00:00:00 2001 From: "lars-erik.bjork@sun.com" <> Date: Thu, 3 Dec 2009 17:15:47 +0100 Subject: [PATCH 024/104] This is a patch for bug#41569. "mysql_upgrade (ver 5.1) add 3 fields to mysql.proc table but does not set values". mysql_upgrade (ver 5.1) adds 3 fields (character_set_client, collation_connection and db_collation) to the mysql.proc table, but does not set any values. When we run stored procedures, which were created with mysql 5.0, a warning is logged into the error log. The solution to this is for mysql_upgrade to set default best guess values for these fields. A warning is also written during upgrade, to make the user aware that default values are set. --- client/mysql_upgrade.c | 4 +++ mysql-test/r/mysql_upgrade.result | 42 +++++++++++++++++++++++++++++ mysql-test/t/mysql_upgrade.test | 17 ++++++++++++ scripts/mysql_system_tables_fix.sql | 30 +++++++++++++++++++++ 4 files changed, 93 insertions(+) diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index 52c3636219d..81dcdaa71f1 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -778,6 +778,10 @@ static int run_sql_fix_privilege_tables(void) found_real_errors++; print_line(line); } + else if (strncmp(line, "WARNING", 7) == 0) + { + print_line(line); + } } while ((line= get_line(line)) && *line); } diff --git a/mysql-test/r/mysql_upgrade.result b/mysql-test/r/mysql_upgrade.result index 384442f8c31..72917988594 100644 --- a/mysql-test/r/mysql_upgrade.result +++ b/mysql-test/r/mysql_upgrade.result @@ -127,3 +127,45 @@ mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.user OK set GLOBAL sql_mode=default; +# +# Bug #41569 mysql_upgrade (ver 5.1) add 3 fields to mysql.proc table +# but does not set values. +# +CREATE PROCEDURE testproc() BEGIN END; +UPDATE mysql.proc SET character_set_client = NULL WHERE name LIKE 'testproc'; +UPDATE mysql.proc SET collation_connection = NULL WHERE name LIKE 'testproc'; +UPDATE mysql.proc SET db_collation = NULL WHERE name LIKE 'testproc'; +WARNING: NULL values of the 'character_set_client' column ('mysql.proc' table) have been updated with a default value (latin1). Please verify if necessary. +WARNING: NULL values of the 'collation_connection' column ('mysql.proc' table) have been updated with a default value (latin1_swedish_ci). Please verify if necessary. +WARNING: NULL values of the 'db_collation' column ('mysql.proc' table) have been updated with default values. Please verify if necessary. +mtr.global_suppressions OK +mtr.test_suppressions OK +mysql.columns_priv OK +mysql.db OK +mysql.event OK +mysql.func OK +mysql.general_log +Error : You can't use locks with log tables. +status : OK +mysql.help_category OK +mysql.help_keyword OK +mysql.help_relation OK +mysql.help_topic OK +mysql.host OK +mysql.ndb_binlog_index OK +mysql.plugin OK +mysql.proc OK +mysql.procs_priv OK +mysql.servers OK +mysql.slow_log +Error : You can't use locks with log tables. +status : OK +mysql.tables_priv OK +mysql.time_zone OK +mysql.time_zone_leap_second OK +mysql.time_zone_name OK +mysql.time_zone_transition OK +mysql.time_zone_transition_type OK +mysql.user OK +CALL testproc(); +DROP PROCEDURE testproc; diff --git a/mysql-test/t/mysql_upgrade.test b/mysql-test/t/mysql_upgrade.test index d1f97d7287e..937c9d7a212 100644 --- a/mysql-test/t/mysql_upgrade.test +++ b/mysql-test/t/mysql_upgrade.test @@ -89,3 +89,20 @@ DROP USER mysqltest1@'%'; set GLOBAL sql_mode='STRICT_ALL_TABLES,ANSI_QUOTES,NO_ZERO_DATE'; --exec $MYSQL_UPGRADE --skip-verbose --force 2>&1 eval set GLOBAL sql_mode=default; + + +--echo # +--echo # Bug #41569 mysql_upgrade (ver 5.1) add 3 fields to mysql.proc table +--echo # but does not set values. +--echo # + +# Create a stored procedure and set the fields in question to null. +# When running mysql_upgrade, a warning should be written. + +CREATE PROCEDURE testproc() BEGIN END; +UPDATE mysql.proc SET character_set_client = NULL WHERE name LIKE 'testproc'; +UPDATE mysql.proc SET collation_connection = NULL WHERE name LIKE 'testproc'; +UPDATE mysql.proc SET db_collation = NULL WHERE name LIKE 'testproc'; +--exec $MYSQL_UPGRADE --skip-verbose --force 2>&1 +CALL testproc(); +DROP PROCEDURE testproc; diff --git a/scripts/mysql_system_tables_fix.sql b/scripts/mysql_system_tables_fix.sql index 1844860c84d..4260aee9142 100644 --- a/scripts/mysql_system_tables_fix.sql +++ b/scripts/mysql_system_tables_fix.sql @@ -415,18 +415,48 @@ ALTER TABLE proc ADD character_set_client ALTER TABLE proc MODIFY character_set_client char(32) collate utf8_bin DEFAULT NULL; +SELECT CASE WHEN COUNT(*) > 0 THEN +CONCAT ("WARNING: NULL values of the 'character_set_client' column ('mysql.proc' table) have been updated with a default value (", @@character_set_client, "). Please verify if necessary.") +ELSE NULL +END +AS value FROM proc WHERE character_set_client IS NULL; + +UPDATE proc SET character_set_client = @@character_set_client + WHERE character_set_client IS NULL; + ALTER TABLE proc ADD collation_connection char(32) collate utf8_bin DEFAULT NULL AFTER character_set_client; ALTER TABLE proc MODIFY collation_connection char(32) collate utf8_bin DEFAULT NULL; +SELECT CASE WHEN COUNT(*) > 0 THEN +CONCAT ("WARNING: NULL values of the 'collation_connection' column ('mysql.proc' table) have been updated with a default value (", @@collation_connection, "). Please verify if necessary.") +ELSE NULL +END +AS value FROM proc WHERE collation_connection IS NULL; + +UPDATE proc SET collation_connection = @@collation_connection + WHERE collation_connection IS NULL; + ALTER TABLE proc ADD db_collation char(32) collate utf8_bin DEFAULT NULL AFTER collation_connection; ALTER TABLE proc MODIFY db_collation char(32) collate utf8_bin DEFAULT NULL; +SELECT CASE WHEN COUNT(*) > 0 THEN +CONCAT ("WARNING: NULL values of the 'db_collation' column ('mysql.proc' table) have been updated with default values. Please verify if necessary.") +ELSE NULL +END +AS value FROM proc WHERE db_collation IS NULL; + +UPDATE proc AS p SET db_collation = + ( SELECT DEFAULT_COLLATION_NAME + FROM INFORMATION_SCHEMA.SCHEMATA + WHERE SCHEMA_NAME = p.db) + WHERE db_collation IS NULL; + ALTER TABLE proc ADD body_utf8 longblob DEFAULT NULL AFTER db_collation; ALTER TABLE proc MODIFY body_utf8 longblob DEFAULT NULL; From 2a878de0419f4cd57dd942a0cf1a4961e7d55ea2 Mon Sep 17 00:00:00 2001 From: Gleb Shchepa Date: Thu, 3 Dec 2009 23:38:09 +0400 Subject: [PATCH 025/104] Bug #38883: thd_security_context is not thread safe, crashes? After-push minor code cleanup for WL 2360: unnecessary external reference to LOCK_thread_count has been removed from ha_innodb.cc. --- storage/innobase/handler/ha_innodb.cc | 6 ------ storage/innodb_plugin/handler/ha_innodb.cc | 3 --- 2 files changed, 9 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 30b4fc13012..2467e7b19b5 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -40,12 +40,6 @@ have disabled the InnoDB inlining in this file. */ #include "ha_innodb.h" #include -#ifndef MYSQL_SERVER -/* This is needed because of Bug #3596. Let us hope that pthread_mutex_t -is defined the same in both builds: the MySQL server and the InnoDB plugin. */ -extern pthread_mutex_t LOCK_thread_count; -#endif /* MYSQL_SERVER */ - /** to protect innobase_open_files */ static pthread_mutex_t innobase_share_mutex; /** to force correct commit order in binlog */ diff --git a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc index b51e9186fe4..47b8203091c 100644 --- a/storage/innodb_plugin/handler/ha_innodb.cc +++ b/storage/innodb_plugin/handler/ha_innodb.cc @@ -110,9 +110,6 @@ extern "C" { # ifndef MYSQL_PLUGIN_IMPORT # define MYSQL_PLUGIN_IMPORT /* nothing */ # endif /* MYSQL_PLUGIN_IMPORT */ -/* This is needed because of Bug #3596. Let us hope that pthread_mutex_t -is defined the same in both builds: the MySQL server and the InnoDB plugin. */ -extern MYSQL_PLUGIN_IMPORT pthread_mutex_t LOCK_thread_count; #if MYSQL_VERSION_ID < 50124 /* this is defined in mysql_priv.h inside #ifdef MYSQL_SERVER From e362e9a71bf311e6d241e60fafc04adcf6bb756d Mon Sep 17 00:00:00 2001 From: Alfranio Correia Date: Fri, 4 Dec 2009 14:40:42 +0000 Subject: [PATCH 026/104] BUG#45292 orphan binary log created when starting server twice This patch fixes three bugs as follows. First, aborting the server while purging binary logs might generate orphan files due to how the purge operation was implemented: (purge routine - sql/log.cc - MYSQL_BIN_LOG::purge_logs) 1 - register the files to be removed in a temporary buffer. 2 - update the log-bin.index. 3 - flush the log-bin.index. 4 - erase the files whose names where register in the temporary buffer in step 1. Thus a failure while executing step 4 would generate an orphan file. Second, a similar issue might happen while creating a new binary as follows: (create routine - sql/log.cc - MYSQL_BIN_LOG::open) 1 - open the new log-bin. 2 - update the log-bin.index. Thus a failure while executing step 1 would generate an orphan file. To fix these issues, we record the files to be purged or created before really removing or adding them. So if a failure happens such records can be used to automatically remove dangling files. The new steps might be outlined as follows: (purge routine - sql/log.cc - MYSQL_BIN_LOG::purge_logs) 1 - register the files to be removed in the log-bin.~rec~ placed in the data directory. 2 - update the log-bin.index. 3 - flush the log-bin.index. 4 - delete the log-bin.~rec~. (create routine - sql/log.cc - MYSQL_BIN_LOG::open) 1 - register the file to be created in the log-bin.~rec~ placed in the data directory. 2 - open the new log-bin. 3 - update the log-bin.index. 4 - delete the log-bin.~rec~. (recovery routine - sql/log.cc - MYSQL_BIN_LOG::open_index_file) 1 - open the log-bin.index. 2 - open the log-bin.~rec~. 3 - for each file in log-bin.~rec~. 3.1 Check if the file is in the log-bin.index and if so ignore it. 3.2 Otherwise, delete it. The third issue can be described as follows. The purge operation was allowing to remove a file in use thus leading to the loss of data and possible inconsistencies between the master and slave. Roughly, the routine was only taking into account the dump threads and so if a slave was not connect the file might be delete even though it was in use. --- mysql-test/suite/binlog/r/binlog_index.result | 113 ++++- mysql-test/suite/binlog/t/binlog_index.test | 165 ++++++- sql/log.cc | 440 +++++++++++++----- sql/log.h | 26 +- sql/mysqld.cc | 4 +- sql/rpl_rli.cc | 4 +- 6 files changed, 628 insertions(+), 124 deletions(-) diff --git a/mysql-test/suite/binlog/r/binlog_index.result b/mysql-test/suite/binlog/r/binlog_index.result index d49ceb00501..06d8baf23bf 100644 --- a/mysql-test/suite/binlog/r/binlog_index.result +++ b/mysql-test/suite/binlog/r/binlog_index.result @@ -1,3 +1,8 @@ +call mtr.add_suppression('Attempting backtrace'); +call mtr.add_suppression('MSYQL_BIN_LOG::purge_logs failed to process registered files that would be purged.'); +call mtr.add_suppression('MSYQL_BIN_LOG::open failed to sync the index file'); +call mtr.add_suppression('Turning logging off for the whole duration of the MySQL server process.'); +call mtr.add_suppression('MSYQL_BIN_LOG::purge_logs failed to clean registers before purging logs.'); flush logs; flush logs; flush logs; @@ -21,7 +26,6 @@ flush logs; *** must be a warning master-bin.000001 was not found *** Warnings: Warning 1612 Being purged log master-bin.000001 was not found -Warning 1612 Being purged log master-bin.000001 was not found *** must show one record, of the active binlog, left in the index file after PURGE *** show binary logs; Log_name File_size @@ -37,4 +41,111 @@ Level Code Message Error 1377 a problem with deleting master-bin.000001; consider examining correspondence of your binlog index file to the actual binlog files Error 1377 Fatal error during log purge reset master; +# crash_purge_before_update_index +flush logs; +SET SESSION debug="+d,crash_purge_before_update_index"; +purge binary logs TO 'master-bin.000002'; +ERROR HY000: Lost connection to MySQL server during query +SET @index=LOAD_FILE('MYSQLTEST_VARDIR/mysqld.1/data//master-bin.index'); +SELECT @index; +@index +master-bin.000001 +master-bin.000002 +master-bin.000003 + +# crash_purge_non_critical_after_update_index +flush logs; +SET SESSION debug="+d,crash_purge_non_critical_after_update_index"; +purge binary logs TO 'master-bin.000004'; +ERROR HY000: Lost connection to MySQL server during query +SET @index=LOAD_FILE('MYSQLTEST_VARDIR/mysqld.1/data//master-bin.index'); +SELECT @index; +@index +master-bin.000004 +master-bin.000005 + +# crash_purge_critical_after_update_index +flush logs; +SET SESSION debug="+d,crash_purge_critical_after_update_index"; +purge binary logs TO 'master-bin.000006'; +ERROR HY000: Lost connection to MySQL server during query +SET @index=LOAD_FILE('MYSQLTEST_VARDIR/mysqld.1/data//master-bin.index'); +SELECT @index; +@index +master-bin.000006 +master-bin.000007 + +# crash_create_non_critical_before_update_index +SET SESSION debug="+d,crash_create_non_critical_before_update_index"; +flush logs; +ERROR HY000: Lost connection to MySQL server during query +SET @index=LOAD_FILE('MYSQLTEST_VARDIR/mysqld.1/data//master-bin.index'); +SELECT @index; +@index +master-bin.000006 +master-bin.000007 +master-bin.000008 + +# crash_create_critical_before_update_index +SET SESSION debug="+d,crash_create_critical_before_update_index"; +flush logs; +ERROR HY000: Lost connection to MySQL server during query +SET @index=LOAD_FILE('MYSQLTEST_VARDIR/mysqld.1/data//master-bin.index'); +SELECT @index; +@index +master-bin.000006 +master-bin.000007 +master-bin.000008 +master-bin.000009 + +# crash_create_after_update_index +SET SESSION debug="+d,crash_create_after_update_index"; +flush logs; +ERROR HY000: Lost connection to MySQL server during query +SET @index=LOAD_FILE('MYSQLTEST_VARDIR/mysqld.1/data//master-bin.index'); +SELECT @index; +@index +master-bin.000006 +master-bin.000007 +master-bin.000008 +master-bin.000009 +master-bin.000010 +master-bin.000011 + +# +# This should put the server in unsafe state and stop +# accepting any command. If we inject a fault at this +# point and continue the execution the server crashes. +# Besides the flush command does not report an error. +# +# fault_injection_registering_index +SET SESSION debug="+d,fault_injection_registering_index"; +flush logs; +SET @index=LOAD_FILE('MYSQLTEST_VARDIR/mysqld.1/data//master-bin.index'); +SELECT @index; +@index +master-bin.000006 +master-bin.000007 +master-bin.000008 +master-bin.000009 +master-bin.000010 +master-bin.000011 +master-bin.000012 + +# fault_injection_updating_index +SET SESSION debug="+d,fault_injection_updating_index"; +flush logs; +SET @index=LOAD_FILE('MYSQLTEST_VARDIR/mysqld.1/data//master-bin.index'); +SELECT @index; +@index +master-bin.000006 +master-bin.000007 +master-bin.000008 +master-bin.000009 +master-bin.000010 +master-bin.000011 +master-bin.000012 +master-bin.000013 + +SET SESSION debug=""; End of tests diff --git a/mysql-test/suite/binlog/t/binlog_index.test b/mysql-test/suite/binlog/t/binlog_index.test index 13287465b88..8e54c028dbd 100644 --- a/mysql-test/suite/binlog/t/binlog_index.test +++ b/mysql-test/suite/binlog/t/binlog_index.test @@ -3,6 +3,15 @@ # source include/have_log_bin.inc; source include/not_embedded.inc; +call mtr.add_suppression('Attempting backtrace'); +call mtr.add_suppression('MSYQL_BIN_LOG::purge_logs failed to process registered files that would be purged.'); +call mtr.add_suppression('MSYQL_BIN_LOG::open failed to sync the index file'); +call mtr.add_suppression('Turning logging off for the whole duration of the MySQL server process.'); +call mtr.add_suppression('MSYQL_BIN_LOG::purge_logs failed to clean registers before purging logs.'); +let $old=`select @@debug`; + +let $MYSQLD_DATADIR= `select @@datadir`; +let $INDEX=$MYSQLD_DATADIR/master-bin.index; # # testing purge binary logs TO @@ -13,7 +22,6 @@ flush logs; flush logs; source include/show_binary_logs.inc; -let $MYSQLD_DATADIR= `select @@datadir`; remove_file $MYSQLD_DATADIR/master-bin.000001; # there must be a warning with file names @@ -66,4 +74,159 @@ rmdir $MYSQLD_DATADIR/master-bin.000001; --disable_warnings reset master; --enable_warnings + +--echo # crash_purge_before_update_index +flush logs; + +--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +SET SESSION debug="+d,crash_purge_before_update_index"; +--error 2013 +purge binary logs TO 'master-bin.000002'; + +--enable_reconnect +--source include/wait_until_connected_again.inc + +file_exists $MYSQLD_DATADIR/master-bin.000001; +file_exists $MYSQLD_DATADIR/master-bin.000002; +file_exists $MYSQLD_DATADIR/master-bin.000003; +--chmod 0644 $INDEX +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +-- eval SET @index=LOAD_FILE('$index') +-- replace_regex /\.[\\\/]master/master/ +SELECT @index; + +--echo # crash_purge_non_critical_after_update_index +flush logs; + +--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +SET SESSION debug="+d,crash_purge_non_critical_after_update_index"; +--error 2013 +purge binary logs TO 'master-bin.000004'; + +--enable_reconnect +--source include/wait_until_connected_again.inc + +--error 1 +file_exists $MYSQLD_DATADIR/master-bin.000001; +--error 1 +file_exists $MYSQLD_DATADIR/master-bin.000002; +--error 1 +file_exists $MYSQLD_DATADIR/master-bin.000003; +--chmod 0644 $INDEX +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +-- eval SET @index=LOAD_FILE('$index') +-- replace_regex /\.[\\\/]master/master/ +SELECT @index; + +--echo # crash_purge_critical_after_update_index +flush logs; + +--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +SET SESSION debug="+d,crash_purge_critical_after_update_index"; +--error 2013 +purge binary logs TO 'master-bin.000006'; + +--enable_reconnect +--source include/wait_until_connected_again.inc + +--error 1 +file_exists $MYSQLD_DATADIR/master-bin.000004; +--error 1 +file_exists $MYSQLD_DATADIR/master-bin.000005; +file_exists $MYSQLD_DATADIR/master-bin.000006; +file_exists $MYSQLD_DATADIR/master-bin.000007; +--error 1 +file_exists $MYSQLD_DATADIR/master-bin.000008; +--chmod 0644 $INDEX +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +-- eval SET @index=LOAD_FILE('$index') +-- replace_regex /\.[\\\/]master/master/ +SELECT @index; + +--echo # crash_create_non_critical_before_update_index +--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +SET SESSION debug="+d,crash_create_non_critical_before_update_index"; +--error 2013 +flush logs; + +--enable_reconnect +--source include/wait_until_connected_again.inc + +file_exists $MYSQLD_DATADIR/master-bin.000008; +--error 1 +file_exists $MYSQLD_DATADIR/master-bin.000009; +--chmod 0644 $INDEX +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +-- eval SET @index=LOAD_FILE('$index') +-- replace_regex /\.[\\\/]master/master/ +SELECT @index; + +--echo # crash_create_critical_before_update_index +--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +SET SESSION debug="+d,crash_create_critical_before_update_index"; +--error 2013 +flush logs; + +--enable_reconnect +--source include/wait_until_connected_again.inc + +file_exists $MYSQLD_DATADIR/master-bin.000009; +--error 1 +file_exists $MYSQLD_DATADIR/master-bin.000010; +--error 1 +file_exists $MYSQLD_DATADIR/master-bin.000011; +--chmod 0644 $INDEX +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +-- eval SET @index=LOAD_FILE('$index') +-- replace_regex /\.[\\\/]master/master/ +SELECT @index; + +--echo # crash_create_after_update_index +--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +SET SESSION debug="+d,crash_create_after_update_index"; +--error 2013 +flush logs; + +--enable_reconnect +--source include/wait_until_connected_again.inc + +file_exists $MYSQLD_DATADIR/master-bin.000010; +file_exists $MYSQLD_DATADIR/master-bin.000011; +--chmod 0644 $INDEX +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +-- eval SET @index=LOAD_FILE('$index') +-- replace_regex /\.[\\\/]master/master/ +SELECT @index; + +--echo # +--echo # This should put the server in unsafe state and stop +--echo # accepting any command. If we inject a fault at this +--echo # point and continue the execution the server crashes. +--echo # Besides the flush command does not report an error. +--echo # + +--echo # fault_injection_registering_index +SET SESSION debug="+d,fault_injection_registering_index"; +flush logs; +--source include/restart_mysqld.inc + +--chmod 0644 $INDEX +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +-- eval SET @index=LOAD_FILE('$index') +-- replace_regex /\.[\\\/]master/master/ +SELECT @index; + +--echo # fault_injection_updating_index +SET SESSION debug="+d,fault_injection_updating_index"; +flush logs; +--source include/restart_mysqld.inc + +--chmod 0644 $INDEX +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +-- eval SET @index=LOAD_FILE('$index') +-- replace_regex /\.[\\\/]master/master/ +SELECT @index; + +eval SET SESSION debug="$old"; + --echo End of tests diff --git a/sql/log.cc b/sql/log.cc index b4c9e5eb4cc..f795cdab2ca 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1897,6 +1897,22 @@ void MYSQL_LOG::init(enum_log_type log_type_arg, } +bool MYSQL_LOG::init_and_set_log_file_name(const char *log_name, + const char *new_name, + enum_log_type log_type_arg, + enum cache_type io_cache_type_arg) +{ + init(log_type_arg, io_cache_type_arg); + + if (new_name && !strmov(log_file_name, new_name)) + return TRUE; + else if (!new_name && generate_new_name(log_file_name, log_name)) + return TRUE; + + return FALSE; +} + + /* Open a (new) log file. @@ -1929,17 +1945,14 @@ bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg, write_error= 0; - init(log_type_arg, io_cache_type_arg); - if (!(name= my_strdup(log_name, MYF(MY_WME)))) { name= (char *)log_name; // for the error message goto err; } - if (new_name) - strmov(log_file_name, new_name); - else if (generate_new_name(log_file_name, name)) + if (init_and_set_log_file_name(name, new_name, + log_type_arg, io_cache_type_arg)) goto err; if (io_cache_type == SEQ_READ_APPEND) @@ -2429,7 +2442,7 @@ MYSQL_BIN_LOG::MYSQL_BIN_LOG() */ index_file_name[0] = 0; bzero((char*) &index_file, sizeof(index_file)); - bzero((char*) &purge_temp, sizeof(purge_temp)); + bzero((char*) &purge_index_file, sizeof(purge_index_file)); } /* this is called only once */ @@ -2473,7 +2486,7 @@ void MYSQL_BIN_LOG::init_pthread_objects() bool MYSQL_BIN_LOG::open_index_file(const char *index_file_name_arg, - const char *log_name) + const char *log_name, bool need_mutex) { File index_file_nr= -1; DBUG_ASSERT(!my_b_inited(&index_file)); @@ -2498,7 +2511,8 @@ bool MYSQL_BIN_LOG::open_index_file(const char *index_file_name_arg, init_io_cache(&index_file, index_file_nr, IO_SIZE, WRITE_CACHE, my_seek(index_file_nr,0L,MY_SEEK_END,MYF(0)), - 0, MYF(MY_WME | MY_WAIT_IF_FULL))) + 0, MYF(MY_WME | MY_WAIT_IF_FULL)) || + DBUG_EVALUATE_IF("fault_injection_openning_index", 1, 0)) { /* TODO: all operations creating/deleting the index file or a log, should @@ -2509,6 +2523,28 @@ bool MYSQL_BIN_LOG::open_index_file(const char *index_file_name_arg, my_close(index_file_nr,MYF(0)); return TRUE; } + +#ifdef HAVE_REPLICATION + /* + Sync the index by purging any binary log file that is not registered. + In other words, either purge binary log files that were removed from + the index but not purged from the file system due to a crash or purge + any binary log file that was created but not register in the index + due to a crash. + */ + + if (set_purge_index_file_name(index_file_name_arg) || + open_purge_index_file(FALSE) || + purge_index_entry(NULL, NULL, need_mutex) || + close_purge_index_file() || + DBUG_EVALUATE_IF("fault_injection_recovering_index", 1, 0)) + { + sql_print_error("MYSQL_BIN_LOG::open_index_file failed to sync the index " + "file."); + return TRUE; + } +#endif + return FALSE; } @@ -2533,17 +2569,44 @@ bool MYSQL_BIN_LOG::open(const char *log_name, enum cache_type io_cache_type_arg, bool no_auto_events_arg, ulong max_size_arg, - bool null_created_arg) + bool null_created_arg, + bool need_mutex) { File file= -1; + DBUG_ENTER("MYSQL_BIN_LOG::open"); DBUG_PRINT("enter",("log_type: %d",(int) log_type_arg)); - write_error=0; + if (init_and_set_log_file_name(log_name, new_name, log_type_arg, + io_cache_type_arg)) + { + sql_print_error("MSYQL_BIN_LOG::open failed to generate new file name."); + DBUG_RETURN(1); + } + +#ifdef HAVE_REPLICATION + if (open_purge_index_file(TRUE) || + register_create_index_entry(log_file_name) || + sync_purge_index_file() || + DBUG_EVALUATE_IF("fault_injection_registering_index", 1, 0)) + { + sql_print_error("MSYQL_BIN_LOG::open failed to sync the index file."); + DBUG_RETURN(1); + } + DBUG_EXECUTE_IF("crash_create_non_critical_before_update_index", abort();); +#endif + + write_error= 0; /* open the main log file */ - if (MYSQL_LOG::open(log_name, log_type_arg, new_name, io_cache_type_arg)) + if (MYSQL_LOG::open(log_name, log_type_arg, new_name, + io_cache_type_arg)) + { +#ifdef HAVE_REPLICATION + close_purge_index_file(); +#endif DBUG_RETURN(1); /* all warnings issued */ + } init(no_auto_events_arg, max_size_arg); @@ -2569,9 +2632,6 @@ bool MYSQL_BIN_LOG::open(const char *log_name, write_file_name_to_index_file= 1; } - DBUG_ASSERT(my_b_inited(&index_file) != 0); - reinit_io_cache(&index_file, WRITE_CACHE, - my_b_filelength(&index_file), 0, 0); if (need_start_event && !no_auto_events) { /* @@ -2629,23 +2689,44 @@ bool MYSQL_BIN_LOG::open(const char *log_name, if (write_file_name_to_index_file) { +#ifdef HAVE_REPLICATION + DBUG_EXECUTE_IF("crash_create_critical_before_update_index", abort();); +#endif + + DBUG_ASSERT(my_b_inited(&index_file) != 0); + reinit_io_cache(&index_file, WRITE_CACHE, + my_b_filelength(&index_file), 0, 0); /* As this is a new log file, we write the file name to the index file. As every time we write to the index file, we sync it. */ - if (my_b_write(&index_file, (uchar*) log_file_name, - strlen(log_file_name)) || - my_b_write(&index_file, (uchar*) "\n", 1) || - flush_io_cache(&index_file) || + if (DBUG_EVALUATE_IF("fault_injection_updating_index", 1, 0) || + my_b_write(&index_file, (uchar*) log_file_name, + strlen(log_file_name)) || + my_b_write(&index_file, (uchar*) "\n", 1) || + flush_io_cache(&index_file) || my_sync(index_file.file, MYF(MY_WME))) - goto err; + goto err; + +#ifdef HAVE_REPLICATION + DBUG_EXECUTE_IF("crash_create_after_update_index", abort();); +#endif } } log_state= LOG_OPENED; +#ifdef HAVE_REPLICATION + close_purge_index_file(); +#endif + DBUG_RETURN(0); err: +#ifdef HAVE_REPLICATION + if (is_inited_purge_index_file()) + purge_index_entry(NULL, NULL, need_mutex); + close_purge_index_file(); +#endif sql_print_error("Could not use %s for logging (error %d). \ Turning logging off for the whole duration of the MySQL server process. \ To turn it on again: fix the cause, \ @@ -2902,8 +2983,15 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd) name=0; // Protect against free close(LOG_CLOSE_TO_BE_OPENED); - /* First delete all old log files */ + /* + First delete all old log files and then update the index file. + As we first delete the log files and do not use sort of logging, + a crash may lead to an inconsistent state where the index has + references to non-existent files. + We need to invert the steps and use the purge_index_file methods + in order to make the operation safe. + */ if (find_log_pos(&linfo, NullS, 0)) { error=1; @@ -2970,8 +3058,8 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd) } if (!thd->slave_thread) need_start_event=1; - if (!open_index_file(index_file_name, 0)) - open(save_name, log_type, 0, io_cache_type, no_auto_events, max_size, 0); + if (!open_index_file(index_file_name, 0, FALSE)) + open(save_name, log_type, 0, io_cache_type, no_auto_events, max_size, 0, FALSE); my_free((uchar*) save_name, MYF(0)); err: @@ -3158,7 +3246,7 @@ int MYSQL_BIN_LOG::purge_logs(const char *to_log, bool need_update_threads, ulonglong *decrease_log_space) { - int error; + int error= 0; bool exit_loop= 0; LOG_INFO log_info; THD *thd= current_thd; @@ -3169,33 +3257,15 @@ int MYSQL_BIN_LOG::purge_logs(const char *to_log, pthread_mutex_lock(&LOCK_index); if ((error=find_log_pos(&log_info, to_log, 0 /*no mutex*/))) { - sql_print_error("MYSQL_LOG::purge_logs was called with file %s not " + sql_print_error("MYSQL_BIN_LOG::purge_logs was called with file %s not " "listed in the index.", to_log); goto err; } - /* - For crash recovery reasons the index needs to be updated before - any files are deleted. Move files to be deleted into a temp file - to be processed after the index is updated. - */ - if (!my_b_inited(&purge_temp)) + if ((error= open_purge_index_file(TRUE))) { - if ((error=open_cached_file(&purge_temp, mysql_tmpdir, TEMP_PREFIX, - DISK_BUFFER_SIZE, MYF(MY_WME)))) - { - sql_print_error("MYSQL_LOG::purge_logs failed to open purge_temp"); - goto err; - } - } - else - { - if ((error=reinit_io_cache(&purge_temp, WRITE_CACHE, 0, 0, 1))) - { - sql_print_error("MYSQL_LOG::purge_logs failed to reinit purge_temp " - "for write"); - goto err; - } + sql_print_error("MYSQL_BIN_LOG::purge_logs failed to sync the index file."); + goto err; } /* @@ -3205,51 +3275,177 @@ int MYSQL_BIN_LOG::purge_logs(const char *to_log, if ((error=find_log_pos(&log_info, NullS, 0 /*no mutex*/))) goto err; while ((strcmp(to_log,log_info.log_file_name) || (exit_loop=included)) && + !is_active(log_info.log_file_name) && !log_in_use(log_info.log_file_name)) { - if ((error=my_b_write(&purge_temp, (const uchar*)log_info.log_file_name, - strlen(log_info.log_file_name))) || - (error=my_b_write(&purge_temp, (const uchar*)"\n", 1))) + if ((error= register_purge_index_entry(log_info.log_file_name))) { - sql_print_error("MYSQL_LOG::purge_logs failed to copy %s to purge_temp", + sql_print_error("MYSQL_BIN_LOG::purge_logs failed to copy %s to register file.", log_info.log_file_name); goto err; } if (find_next_log(&log_info, 0) || exit_loop) break; - } + } + + DBUG_EXECUTE_IF("crash_purge_before_update_index", abort();); + + if ((error= sync_purge_index_file())) + { + sql_print_error("MSYQL_BIN_LOG::purge_logs failed to flush register file."); + goto err; + } /* We know how many files to delete. Update index file. */ if ((error=update_log_index(&log_info, need_update_threads))) { - sql_print_error("MSYQL_LOG::purge_logs failed to update the index file"); + sql_print_error("MSYQL_BIN_LOG::purge_logs failed to update the index file"); goto err; } - DBUG_EXECUTE_IF("crash_after_update_index", abort();); + DBUG_EXECUTE_IF("crash_purge_critical_after_update_index", abort();); - /* Switch purge_temp for read. */ - if ((error=reinit_io_cache(&purge_temp, READ_CACHE, 0, 0, 0))) +err: + /* Read each entry from purge_index_file and delete the file. */ + if (is_inited_purge_index_file() && + (error= purge_index_entry(thd, decrease_log_space, FALSE))) + sql_print_error("MSYQL_BIN_LOG::purge_logs failed to process registered files" + " that would be purged."); + close_purge_index_file(); + + DBUG_EXECUTE_IF("crash_purge_non_critical_after_update_index", abort();); + + if (need_mutex) + pthread_mutex_unlock(&LOCK_index); + DBUG_RETURN(error); +} + +int MYSQL_BIN_LOG::set_purge_index_file_name(const char *base_file_name) +{ + int error= 0; + DBUG_ENTER("MYSQL_BIN_LOG::set_purge_index_file_name"); + if (fn_format(purge_index_file_name, base_file_name, mysql_data_home, + ".~rec~", MYF(MY_UNPACK_FILENAME | MY_SAFE_PATH | + MY_REPLACE_EXT)) == NULL) { - sql_print_error("MSYQL_LOG::purge_logs failed to reinit purge_temp " + error= 1; + sql_print_error("MYSQL_BIN_LOG::set_purge_index_file_name failed to set " + "file name."); + } + DBUG_RETURN(error); +} + +int MYSQL_BIN_LOG::open_purge_index_file(bool destroy) +{ + int error= 0; + File file= -1; + + DBUG_ENTER("MYSQL_BIN_LOG::open_purge_index_file"); + + if (destroy) + close_purge_index_file(); + + if (!my_b_inited(&purge_index_file)) + { + if ((file= my_open(purge_index_file_name, O_RDWR | O_CREAT | O_BINARY, + MYF(MY_WME | ME_WAITTANG))) < 0 || + init_io_cache(&purge_index_file, file, IO_SIZE, + (destroy ? WRITE_CACHE : READ_CACHE), + 0, 0, MYF(MY_WME | MY_NABP | MY_WAIT_IF_FULL))) + { + error= 1; + sql_print_error("MYSQL_BIN_LOG::open_purge_index_file failed to open register " + " file."); + } + } + DBUG_RETURN(error); +} + +int MYSQL_BIN_LOG::close_purge_index_file() +{ + int error= 0; + + DBUG_ENTER("MYSQL_BIN_LOG::close_purge_index_file"); + + if (my_b_inited(&purge_index_file)) + { + end_io_cache(&purge_index_file); + error= my_close(purge_index_file.file, MYF(0)); + } + my_delete(purge_index_file_name, MYF(0)); + bzero((char*) &purge_index_file, sizeof(purge_index_file)); + + DBUG_RETURN(error); +} + +bool MYSQL_BIN_LOG::is_inited_purge_index_file() +{ + DBUG_ENTER("MYSQL_BIN_LOG::is_inited_purge_index_file"); + DBUG_RETURN (my_b_inited(&purge_index_file)); +} + +int MYSQL_BIN_LOG::sync_purge_index_file() +{ + int error= 0; + DBUG_ENTER("MYSQL_BIN_LOG::sync_purge_index_file"); + + if ((error= flush_io_cache(&purge_index_file)) || + (error= my_sync(purge_index_file.file, MYF(MY_WME)))) + DBUG_RETURN(error); + + DBUG_RETURN(error); +} + +int MYSQL_BIN_LOG::register_purge_index_entry(const char *entry) +{ + int error= 0; + DBUG_ENTER("MYSQL_BIN_LOG::register_purge_index_entry"); + + if ((error=my_b_write(&purge_index_file, (const uchar*)entry, strlen(entry))) || + (error=my_b_write(&purge_index_file, (const uchar*)"\n", 1))) + DBUG_RETURN (error); + + DBUG_RETURN(error); +} + +int MYSQL_BIN_LOG::register_create_index_entry(const char *entry) +{ + DBUG_ENTER("MYSQL_BIN_LOG::register_create_index_entry"); + DBUG_RETURN(register_purge_index_entry(entry)); +} + +int MYSQL_BIN_LOG::purge_index_entry(THD *thd, ulonglong *decrease_log_space, + bool need_mutex) +{ + MY_STAT s; + int error= 0; + LOG_INFO log_info; + LOG_INFO check_log_info; + + DBUG_ENTER("MYSQL_BIN_LOG:purge_index_entry"); + + DBUG_ASSERT(my_b_inited(&purge_index_file)); + + if ((error=reinit_io_cache(&purge_index_file, READ_CACHE, 0, 0, 0))) + { + sql_print_error("MSYQL_BIN_LOG::purge_index_entry failed to reinit register file " "for read"); goto err; } - /* Read each entry from purge_temp and delete the file. */ for (;;) { uint length; - if ((length=my_b_gets(&purge_temp, log_info.log_file_name, + if ((length=my_b_gets(&purge_index_file, log_info.log_file_name, FN_REFLEN)) <= 1) { - if (purge_temp.error) + if (purge_index_file.error) { - error= purge_temp.error; - sql_print_error("MSYQL_LOG::purge_logs error %d reading from " - "purge_temp", error); + error= purge_index_file.error; + sql_print_error("MSYQL_BIN_LOG::purge_index_entry error %d reading from " + "register file.", error); goto err; } @@ -3260,9 +3456,6 @@ int MYSQL_BIN_LOG::purge_logs(const char *to_log, /* Get rid of the trailing '\n' */ log_info.log_file_name[length-1]= 0; - ha_binlog_index_purge_file(current_thd, log_info.log_file_name); - - MY_STAT s; if (!my_stat(log_info.log_file_name, &s, MYF(0))) { if (my_errno == ENOENT) @@ -3310,64 +3503,92 @@ int MYSQL_BIN_LOG::purge_logs(const char *to_log, } else { - DBUG_PRINT("info",("purging %s",log_info.log_file_name)); - if (!my_delete(log_info.log_file_name, MYF(0))) + if ((error= find_log_pos(&check_log_info, log_info.log_file_name, need_mutex))) { - if (decrease_log_space) - *decrease_log_space-= s.st_size; - } - else - { - if (my_errno == ENOENT) - { - if (thd) - { - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE), - log_info.log_file_name); - } - sql_print_information("Failed to delete file '%s'", - log_info.log_file_name); - my_errno= 0; - } - else + if (error != LOG_INFO_EOF) { if (thd) { push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_BINLOG_PURGE_FATAL_ERR, - "a problem with deleting %s; " - "consider examining correspondence " - "of your binlog index file " - "to the actual binlog files", + "a problem with deleting %s and " + "reading the binlog index file", log_info.log_file_name); } else { - sql_print_information("Failed to delete file '%s'; " + sql_print_information("Failed to delete file '%s' and " + "read the binlog index file", + log_info.log_file_name); + } + goto err; + } + + error= 0; + if (!need_mutex) + { + /* + This is to avoid triggering an error in NDB. + */ + ha_binlog_index_purge_file(current_thd, log_info.log_file_name); + } + + DBUG_PRINT("info",("purging %s",log_info.log_file_name)); + if (!my_delete(log_info.log_file_name, MYF(0))) + { + if (decrease_log_space) + *decrease_log_space-= s.st_size; + } + else + { + if (my_errno == ENOENT) + { + if (thd) + { + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE), + log_info.log_file_name); + } + sql_print_information("Failed to delete file '%s'", + log_info.log_file_name); + my_errno= 0; + } + else + { + if (thd) + { + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + ER_BINLOG_PURGE_FATAL_ERR, + "a problem with deleting %s; " "consider examining correspondence " "of your binlog index file " "to the actual binlog files", log_info.log_file_name); - } - if (my_errno == EMFILE) - { - DBUG_PRINT("info", - ("my_errno: %d, set ret = LOG_INFO_EMFILE", my_errno)); - error= LOG_INFO_EMFILE; + } + else + { + sql_print_information("Failed to delete file '%s'; " + "consider examining correspondence " + "of your binlog index file " + "to the actual binlog files", + log_info.log_file_name); + } + if (my_errno == EMFILE) + { + DBUG_PRINT("info", + ("my_errno: %d, set ret = LOG_INFO_EMFILE", my_errno)); + error= LOG_INFO_EMFILE; + goto err; + } + error= LOG_INFO_FATAL; goto err; } - error= LOG_INFO_FATAL; - goto err; } } } } err: - close_cached_file(&purge_temp); - if (need_mutex) - pthread_mutex_unlock(&LOCK_index); DBUG_RETURN(error); } @@ -3407,7 +3628,8 @@ int MYSQL_BIN_LOG::purge_logs_before_date(time_t purge_time) goto err; while (strcmp(log_file_name, log_info.log_file_name) && - !log_in_use(log_info.log_file_name)) + !is_active(log_info.log_file_name) && + !log_in_use(log_info.log_file_name)) { if (!my_stat(log_info.log_file_name, &stat_area, MYF(0))) { @@ -3416,14 +3638,6 @@ int MYSQL_BIN_LOG::purge_logs_before_date(time_t purge_time) /* It's not fatal if we can't stat a log file that does not exist. */ - if (thd) - { - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE), - log_info.log_file_name); - } - sql_print_information("Failed to execute my_stat on file '%s'", - log_info.log_file_name); my_errno= 0; } else @@ -3618,9 +3832,9 @@ void MYSQL_BIN_LOG::new_file_impl(bool need_lock) */ /* reopen index binlog file, BUG#34582 */ - if (!open_index_file(index_file_name, 0)) - open(old_name, log_type, new_name_ptr, - io_cache_type, no_auto_events, max_size, 1); + if (!open_index_file(index_file_name, 0, FALSE)) + open(old_name, log_type, new_name_ptr, + io_cache_type, no_auto_events, max_size, 1, FALSE); my_free(old_name,MYF(0)); end: @@ -5522,7 +5736,7 @@ int TC_LOG_BINLOG::open(const char *opt_name) if (using_heuristic_recover()) { /* generate a new binlog to mask a corrupted one */ - open(opt_name, LOG_BIN, 0, WRITE_CACHE, 0, max_binlog_size, 0); + open(opt_name, LOG_BIN, 0, WRITE_CACHE, 0, max_binlog_size, 0, TRUE); cleanup(); return 1; } diff --git a/sql/log.h b/sql/log.h index d306d6f7182..8b5dfcb3935 100644 --- a/sql/log.h +++ b/sql/log.h @@ -172,6 +172,10 @@ public: enum_log_type log_type, const char *new_name, enum cache_type io_cache_type_arg); + bool init_and_set_log_file_name(const char *log_name, + const char *new_name, + enum_log_type log_type_arg, + enum cache_type io_cache_type_arg); void init(enum_log_type log_type_arg, enum cache_type io_cache_type_arg); void close(uint exiting); @@ -233,14 +237,15 @@ class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG pthread_cond_t update_cond; ulonglong bytes_written; IO_CACHE index_file; + char index_file_name[FN_REFLEN]; /* - purge_temp is a temp file used in purge_logs so that the index file + purge_file is a temp file used in purge_logs so that the index file can be updated before deleting files from disk, yielding better crash recovery. It is created on demand the first time purge_logs is called and then reused for subsequent calls. It is cleaned up in cleanup(). */ - IO_CACHE purge_temp; - char index_file_name[FN_REFLEN]; + IO_CACHE purge_index_file; + char purge_index_file_name[FN_REFLEN]; /* The max size before rotation (usable only if log_type == LOG_BIN: binary logs and relay logs). @@ -349,9 +354,10 @@ public: const char *new_name, enum cache_type io_cache_type_arg, bool no_auto_events_arg, ulong max_size, - bool null_created); + bool null_created, + bool need_mutex); bool open_index_file(const char *index_file_name_arg, - const char *log_name); + const char *log_name, bool need_mutex); /* Use this to start writing a new log file */ void new_file(); @@ -384,6 +390,16 @@ public: ulonglong *decrease_log_space); int purge_logs_before_date(time_t purge_time); int purge_first_log(Relay_log_info* rli, bool included); + int set_purge_index_file_name(const char *base_file_name); + int open_purge_index_file(bool destroy); + bool is_inited_purge_index_file(); + int close_purge_index_file(); + int clean_purge_index_file(); + int sync_purge_index_file(); + int register_purge_index_entry(const char* entry); + int register_create_index_entry(const char* entry); + int purge_index_entry(THD *thd, ulonglong *decrease_log_space, + bool need_mutex); bool reset_logs(THD* thd); void close(uint exiting); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 5c643b03798..de532e92fda 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3932,7 +3932,7 @@ a file name for --log-bin-index option", opt_binlog_index_name); my_free(opt_bin_logname, MYF(MY_ALLOW_ZERO_PTR)); opt_bin_logname=my_strdup(buf, MYF(0)); } - if (mysql_bin_log.open_index_file(opt_binlog_index_name, ln)) + if (mysql_bin_log.open_index_file(opt_binlog_index_name, ln, TRUE)) { unireg_abort(1); } @@ -4096,7 +4096,7 @@ a file name for --log-bin-index option", opt_binlog_index_name); } if (opt_bin_log && mysql_bin_log.open(opt_bin_logname, LOG_BIN, 0, - WRITE_CACHE, 0, max_binlog_size, 0)) + WRITE_CACHE, 0, max_binlog_size, 0, TRUE)) unireg_abort(1); #ifdef HAVE_REPLICATION diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index a26717d7acf..66de9357a53 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -182,10 +182,10 @@ a file name for --relay-log-index option", opt_relaylog_index_name); note, that if open() fails, we'll still have index file open but a destructor will take care of that */ - if (rli->relay_log.open_index_file(opt_relaylog_index_name, ln) || + if (rli->relay_log.open_index_file(opt_relaylog_index_name, ln, TRUE) || rli->relay_log.open(ln, LOG_BIN, 0, SEQ_READ_APPEND, 0, (max_relay_log_size ? max_relay_log_size : - max_binlog_size), 1)) + max_binlog_size), 1, TRUE)) { pthread_mutex_unlock(&rli->data_lock); sql_print_error("Failed in open_log() called from init_relay_log_info()"); From a2d630d055a63931638427967aa3cb9bfbd53b5e Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Fri, 4 Dec 2009 14:00:20 -0200 Subject: [PATCH 027/104] Bug#41569: mysql_upgrade (ver 5.1) add 3 fields to mysql.proc table but does not set values Post-merge fix: Redirect stderr to a file as to avoid buffering problems due to redirecting stderr to stdout. --- mysql-test/r/mysql_upgrade.result | 6 +++--- mysql-test/t/mysql_upgrade.test | 4 +++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/mysql_upgrade.result b/mysql-test/r/mysql_upgrade.result index 72917988594..821ad31871f 100644 --- a/mysql-test/r/mysql_upgrade.result +++ b/mysql-test/r/mysql_upgrade.result @@ -135,9 +135,6 @@ CREATE PROCEDURE testproc() BEGIN END; UPDATE mysql.proc SET character_set_client = NULL WHERE name LIKE 'testproc'; UPDATE mysql.proc SET collation_connection = NULL WHERE name LIKE 'testproc'; UPDATE mysql.proc SET db_collation = NULL WHERE name LIKE 'testproc'; -WARNING: NULL values of the 'character_set_client' column ('mysql.proc' table) have been updated with a default value (latin1). Please verify if necessary. -WARNING: NULL values of the 'collation_connection' column ('mysql.proc' table) have been updated with a default value (latin1_swedish_ci). Please verify if necessary. -WARNING: NULL values of the 'db_collation' column ('mysql.proc' table) have been updated with default values. Please verify if necessary. mtr.global_suppressions OK mtr.test_suppressions OK mysql.columns_priv OK @@ -169,3 +166,6 @@ mysql.time_zone_transition_type OK mysql.user OK CALL testproc(); DROP PROCEDURE testproc; +WARNING: NULL values of the 'character_set_client' column ('mysql.proc' table) have been updated with a default value (latin1). Please verify if necessary. +WARNING: NULL values of the 'collation_connection' column ('mysql.proc' table) have been updated with a default value (latin1_swedish_ci). Please verify if necessary. +WARNING: NULL values of the 'db_collation' column ('mysql.proc' table) have been updated with default values. Please verify if necessary. diff --git a/mysql-test/t/mysql_upgrade.test b/mysql-test/t/mysql_upgrade.test index 937c9d7a212..24a1d2e1b5d 100644 --- a/mysql-test/t/mysql_upgrade.test +++ b/mysql-test/t/mysql_upgrade.test @@ -103,6 +103,8 @@ CREATE PROCEDURE testproc() BEGIN END; UPDATE mysql.proc SET character_set_client = NULL WHERE name LIKE 'testproc'; UPDATE mysql.proc SET collation_connection = NULL WHERE name LIKE 'testproc'; UPDATE mysql.proc SET db_collation = NULL WHERE name LIKE 'testproc'; ---exec $MYSQL_UPGRADE --skip-verbose --force 2>&1 +--exec $MYSQL_UPGRADE --skip-verbose --force 2> $MYSQLTEST_VARDIR/tmp/41569.txt CALL testproc(); DROP PROCEDURE testproc; +--cat_file $MYSQLTEST_VARDIR/tmp/41569.txt +--remove_file $MYSQLTEST_VARDIR/tmp/41569.txt From 96a3a92c71555d675b25449d692c3ceb4a5b1e2b Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Fri, 4 Dec 2009 13:36:58 -0200 Subject: [PATCH 028/104] Bug#49141: Encode function is significantly slower in 5.1 compared to 5.0 The problem was that the multiple evaluations of a ENCODE or DECODE function within a single statement caused the random generator to be reinitialized at each evaluation, even though the parameters were constants. The solution is to initialize the random generator only once if the password (seed) parameter is constant. This patch borrows code and ideas from Georgi Kodinov's patch. --- mysql-test/r/func_str.result | 29 +++++++++++++++ mysql-test/r/ps.result | 19 ++++++++++ mysql-test/t/func_str.test | 34 +++++++++++++++++ mysql-test/t/ps.test | 16 ++++++++ sql/item_strfunc.cc | 71 +++++++++++++++++------------------- sql/item_strfunc.h | 13 ++++++- sql/sql_crypt.cc | 9 +---- sql/sql_crypt.h | 8 ++-- 8 files changed, 149 insertions(+), 50 deletions(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 2a2fe50ad0f..d144e84dfdc 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -2558,3 +2558,32 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY ALL NULL NULL NULL NULL 2 Using join buffer 2 DERIVED t1 ALL NULL NULL NULL NULL 2 drop table t1; +# +# Bug#49141: Encode function is significantly slower in 5.1 compared to 5.0 +# +DROP TABLE IF EXISTS t1, t2; +CREATE TABLE t1 (a VARCHAR(20), b INT); +CREATE TABLE t2 (a VARCHAR(20), b INT); +INSERT INTO t1 VALUES ('ABC', 1); +INSERT INTO t2 VALUES ('ABC', 1); +SELECT DECODE((SELECT ENCODE('secret', t1.a) FROM t1,t2 WHERE t1.a = t2.a GROUP BY t1.b), t2.a) +FROM t1,t2 WHERE t1.b = t1.b > 0 GROUP BY t2.b; +DECODE((SELECT ENCODE('secret', t1.a) FROM t1,t2 WHERE t1.a = t2.a GROUP BY t1.b), t2.a) +secret +SELECT DECODE((SELECT ENCODE('secret', 'ABC') FROM t1,t2 WHERE t1.a = t2.a GROUP BY t1.b), t2.a) +FROM t1,t2 WHERE t1.b = t1.b > 0 GROUP BY t2.b; +DECODE((SELECT ENCODE('secret', 'ABC') FROM t1,t2 WHERE t1.a = t2.a GROUP BY t1.b), t2.a) +secret +SELECT DECODE((SELECT ENCODE('secret', t1.a) FROM t1,t2 WHERE t1.a = t2.a GROUP BY t1.b), 'ABC') +FROM t1,t2 WHERE t1.b = t1.b > 0 GROUP BY t2.b; +DECODE((SELECT ENCODE('secret', t1.a) FROM t1,t2 WHERE t1.a = t2.a GROUP BY t1.b), 'ABC') +secret +TRUNCATE TABLE t1; +TRUNCATE TABLE t2; +INSERT INTO t1 VALUES ('EDF', 3), ('BCD', 2), ('ABC', 1); +INSERT INTO t2 VALUES ('EDF', 3), ('BCD', 2), ('ABC', 1); +SELECT DECODE((SELECT ENCODE('secret', t1.a) FROM t1,t2 WHERE t1.a = t2.a GROUP BY t1.b LIMIT 1), t2.a) +FROM t2 WHERE t2.b = 1 GROUP BY t2.b; +DECODE((SELECT ENCODE('secret', t1.a) FROM t1,t2 WHERE t1.a = t2.a GROUP BY t1.b LIMIT 1), t2.a) +secret +DROP TABLE t1, t2; diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index f64d58ff8f4..c26a324d00b 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -2947,4 +2947,23 @@ execute stmt; Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation drop table t1; deallocate prepare stmt; +# +# Bug#49141: Encode function is significantly slower in 5.1 compared to 5.0 +# +prepare encode from "select encode(?, ?) into @ciphertext"; +prepare decode from "select decode(?, ?) into @plaintext"; +set @str="abc", @key="cba"; +execute encode using @str, @key; +execute decode using @ciphertext, @key; +select @plaintext; +@plaintext +abc +set @str="bcd", @key="dcb"; +execute encode using @str, @key; +execute decode using @ciphertext, @key; +select @plaintext; +@plaintext +bcd +deallocate prepare encode; +deallocate prepare decode; End of 5.1 tests. diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 66b9eabd385..8942b0a2faf 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -1318,3 +1318,37 @@ insert into t1 values (-1),(null); explain select 1 as a from t1,(select decode(f1,f1) as b from t1) a; explain select 1 as a from t1,(select encode(f1,f1) as b from t1) a; drop table t1; + +--echo # +--echo # Bug#49141: Encode function is significantly slower in 5.1 compared to 5.0 +--echo # + +--disable_warnings +DROP TABLE IF EXISTS t1, t2; +--enable_warnings + +CREATE TABLE t1 (a VARCHAR(20), b INT); +CREATE TABLE t2 (a VARCHAR(20), b INT); + +INSERT INTO t1 VALUES ('ABC', 1); +INSERT INTO t2 VALUES ('ABC', 1); + +SELECT DECODE((SELECT ENCODE('secret', t1.a) FROM t1,t2 WHERE t1.a = t2.a GROUP BY t1.b), t2.a) + FROM t1,t2 WHERE t1.b = t1.b > 0 GROUP BY t2.b; + +SELECT DECODE((SELECT ENCODE('secret', 'ABC') FROM t1,t2 WHERE t1.a = t2.a GROUP BY t1.b), t2.a) + FROM t1,t2 WHERE t1.b = t1.b > 0 GROUP BY t2.b; + +SELECT DECODE((SELECT ENCODE('secret', t1.a) FROM t1,t2 WHERE t1.a = t2.a GROUP BY t1.b), 'ABC') + FROM t1,t2 WHERE t1.b = t1.b > 0 GROUP BY t2.b; + +TRUNCATE TABLE t1; +TRUNCATE TABLE t2; + +INSERT INTO t1 VALUES ('EDF', 3), ('BCD', 2), ('ABC', 1); +INSERT INTO t2 VALUES ('EDF', 3), ('BCD', 2), ('ABC', 1); + +SELECT DECODE((SELECT ENCODE('secret', t1.a) FROM t1,t2 WHERE t1.a = t2.a GROUP BY t1.b LIMIT 1), t2.a) + FROM t2 WHERE t2.b = 1 GROUP BY t2.b; + +DROP TABLE t1, t2; diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 4870f4836df..b0930a42b41 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -3032,5 +3032,21 @@ execute stmt; drop table t1; deallocate prepare stmt; +--echo # +--echo # Bug#49141: Encode function is significantly slower in 5.1 compared to 5.0 +--echo # + +prepare encode from "select encode(?, ?) into @ciphertext"; +prepare decode from "select decode(?, ?) into @plaintext"; +set @str="abc", @key="cba"; +execute encode using @str, @key; +execute decode using @ciphertext, @key; +select @plaintext; +set @str="bcd", @key="dcb"; +execute encode using @str, @key; +execute decode using @ciphertext, @key; +select @plaintext; +deallocate prepare encode; +deallocate prepare decode; --echo End of 5.1 tests. diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 183a628f8e4..b6d3f45f4c2 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1720,68 +1720,65 @@ String *Item_func_encrypt::val_str(String *str) #endif /* HAVE_CRYPT */ } +bool Item_func_encode::seed() +{ + char buf[80]; + ulong rand_nr[2]; + String *key, tmp(buf, sizeof(buf), system_charset_info); + + if (!(key= args[1]->val_str(&tmp))) + return TRUE; + + hash_password(rand_nr, key->ptr(), key->length()); + sql_crypt.init(rand_nr); + + return FALSE; +} + void Item_func_encode::fix_length_and_dec() { max_length=args[0]->max_length; maybe_null=args[0]->maybe_null || args[1]->maybe_null; collation.set(&my_charset_bin); + /* Precompute the seed state if the item is constant. */ + seeded= args[1]->const_item() && + (args[1]->result_type() == STRING_RESULT) && !seed(); } String *Item_func_encode::val_str(String *str) { String *res; - char pw_buff[80]; - String tmp_pw_value(pw_buff, sizeof(pw_buff), system_charset_info); - String *password; DBUG_ASSERT(fixed == 1); if (!(res=args[0]->val_str(str))) { - null_value=1; /* purecov: inspected */ - return 0; /* purecov: inspected */ + null_value= 1; + return NULL; } - if (!(password=args[1]->val_str(& tmp_pw_value))) + if (!seeded && seed()) { - null_value=1; - return 0; + null_value= 1; + return NULL; } - null_value=0; - res=copy_if_not_alloced(str,res,res->length()); - SQL_CRYPT sql_crypt(password->ptr(), password->length()); - sql_crypt.init(); - sql_crypt.encode((char*) res->ptr(),res->length()); - res->set_charset(&my_charset_bin); + null_value= 0; + res= copy_if_not_alloced(str, res, res->length()); + transform(res); + sql_crypt.reinit(); + return res; } -String *Item_func_decode::val_str(String *str) +void Item_func_encode::transform(String *res) { - String *res; - char pw_buff[80]; - String tmp_pw_value(pw_buff, sizeof(pw_buff), system_charset_info); - String *password; - DBUG_ASSERT(fixed == 1); + sql_crypt.encode((char*) res->ptr(),res->length()); + res->set_charset(&my_charset_bin); +} - if (!(res=args[0]->val_str(str))) - { - null_value=1; /* purecov: inspected */ - return 0; /* purecov: inspected */ - } - - if (!(password=args[1]->val_str(& tmp_pw_value))) - { - null_value=1; - return 0; - } - - null_value=0; - res=copy_if_not_alloced(str,res,res->length()); - SQL_CRYPT sql_crypt(password->ptr(), password->length()); - sql_crypt.init(); +void Item_func_decode::transform(String *res) +{ sql_crypt.decode((char*) res->ptr(),res->length()); - return res; } diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 2cdb45100ae..59241872e63 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -351,12 +351,22 @@ public: class Item_func_encode :public Item_str_func { +private: + /** Whether the PRNG has already been seeded. */ + bool seeded; +protected: + SQL_CRYPT sql_crypt; public: Item_func_encode(Item *a, Item *seed): Item_str_func(a, seed) {} String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "encode"; } +protected: + virtual void transform(String *); +private: + /** Provide a seed for the PRNG sequence. */ + bool seed(); }; @@ -364,8 +374,9 @@ class Item_func_decode :public Item_func_encode { public: Item_func_decode(Item *a, Item *seed): Item_func_encode(a, seed) {} - String *val_str(String *); const char *func_name() const { return "decode"; } +protected: + void transform(String *); }; diff --git a/sql/sql_crypt.cc b/sql/sql_crypt.cc index c4f93cc2a33..3d7d248782b 100644 --- a/sql/sql_crypt.cc +++ b/sql/sql_crypt.cc @@ -28,14 +28,7 @@ #include "mysql_priv.h" -SQL_CRYPT::SQL_CRYPT(const char *password, uint length) -{ - ulong rand_nr[2]; - hash_password(rand_nr,password, length); - crypt_init(rand_nr); -} - -void SQL_CRYPT::crypt_init(ulong *rand_nr) +void SQL_CRYPT::init(ulong *rand_nr) { uint i; randominit(&rand,rand_nr[0],rand_nr[1]); diff --git a/sql/sql_crypt.h b/sql/sql_crypt.h index a5a6bee8a58..2b56c387bd1 100644 --- a/sql/sql_crypt.h +++ b/sql/sql_crypt.h @@ -23,15 +23,15 @@ class SQL_CRYPT :public Sql_alloc struct rand_struct rand,org_rand; char decode_buff[256],encode_buff[256]; uint shift; - void crypt_init(ulong *seed); public: - SQL_CRYPT(const char *seed, uint length); + SQL_CRYPT() {} SQL_CRYPT(ulong *seed) { - crypt_init(seed); + init(seed); } ~SQL_CRYPT() {} - void init() { shift=0; rand=org_rand; } + void init(ulong *seed); + void reinit() { shift=0; rand=org_rand; } void encode(char *str, uint length); void decode(char *str, uint length); }; From 7888c9832745701322486be3a7a7d24ed81ba063 Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Fri, 4 Dec 2009 21:58:40 +0400 Subject: [PATCH 029/104] Fix for bug#49199: Optimizer handles incorrectly: field='const1' AND field='const2' in some cases Building multiple equality predicates containing a constant which is compared as a datetime (with a field) we should take this fact into account and compare the constant with another possible constatns as datetimes as well. E.g. for the SELECT ... WHERE a='2001-01-01' AND a='2001-01-01 00:00:00' we should compare '2001-01-01' with '2001-01-01 00:00:00' as datetimes but not as strings. --- mysql-test/r/select.result | 84 ++++++++++++++++++++++++++++++++++++++ mysql-test/t/select.test | 49 ++++++++++++++++++++++ sql/item_cmpfunc.cc | 46 ++++++++++++++++++--- sql/item_cmpfunc.h | 4 ++ sql/sql_select.cc | 2 +- 5 files changed, 178 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index ff59eadab0c..1b2533eec89 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -4456,4 +4456,88 @@ SELECT 1 FROM t2 JOIN t1 ON 1=1 WHERE a != '1' AND NOT a >= b OR NOT ROW(b,a )<> ROW(a,a); 1 DROP TABLE t1,t2; +# +# Bug #49199: Optimizer handles incorrectly: +# field='const1' AND field='const2' in some cases + +CREATE TABLE t1(a DATETIME NOT NULL); +INSERT INTO t1 VALUES('2001-01-01'); +SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00'; +a +2001-01-01 00:00:00 +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 system NULL NULL NULL NULL 1 +Warnings: +Note 1003 select '2001-01-01 00:00:00' AS `a` from `test`.`t1` where 1 +DROP TABLE t1; +CREATE TABLE t1(a DATE NOT NULL); +INSERT INTO t1 VALUES('2001-01-01'); +SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00'; +a +2001-01-01 +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 system NULL NULL NULL NULL 1 +Warnings: +Note 1003 select '2001-01-01' AS `a` from `test`.`t1` where 1 +DROP TABLE t1; +CREATE TABLE t1(a TIMESTAMP NOT NULL); +INSERT INTO t1 VALUES('2001-01-01'); +SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00'; +a +2001-01-01 00:00:00 +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 system NULL NULL NULL NULL 1 +Warnings: +Note 1003 select '2001-01-01 00:00:00' AS `a` from `test`.`t1` where 1 +DROP TABLE t1; +CREATE TABLE t1(a DATETIME NOT NULL, b DATE NOT NULL); +INSERT INTO t1 VALUES('2001-01-01', '2001-01-01'); +SELECT * FROM t1 WHERE a='2001-01-01' AND a=b AND b='2001-01-01 00:00:00'; +a b +2001-01-01 00:00:00 2001-01-01 +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a=b AND b='2001-01-01 00:00:00'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 system NULL NULL NULL NULL 1 +Warnings: +Note 1003 select '2001-01-01 00:00:00' AS `a`,'2001-01-01' AS `b` from `test`.`t1` where 1 +DROP TABLE t1; +CREATE TABLE t1(a DATETIME NOT NULL, b VARCHAR(20) NOT NULL); +INSERT INTO t1 VALUES('2001-01-01', '2001-01-01'); +SELECT * FROM t1 WHERE a='2001-01-01' AND a=b AND b='2001-01-01 00:00:00'; +a b +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a=b AND b='2001-01-01 00:00:00'; +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 +Warnings: +Note 1003 select '2001-01-01 00:00:00' AS `a`,'2001-01-01' AS `b` from `test`.`t1` where 0 +SELECT * FROM t1 WHERE a='2001-01-01 00:00:00' AND a=b AND b='2001-01-01'; +a b +2001-01-01 00:00:00 2001-01-01 +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01 00:00:00' AND a=b AND b='2001-01-01'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 system NULL NULL NULL NULL 1 +Warnings: +Note 1003 select '2001-01-01 00:00:00' AS `a`,'2001-01-01' AS `b` from `test`.`t1` where 1 +DROP TABLE t1; +CREATE TABLE t1(a DATETIME NOT NULL, b DATE NOT NULL); +INSERT INTO t1 VALUES('2001-01-01', '2001-01-01'); +SELECT x.a, y.a, z.a FROM t1 x +JOIN t1 y ON x.a=y.a +JOIN t1 z ON y.a=z.a +WHERE x.a='2001-01-01' AND z.a='2001-01-01 00:00:00'; +a a a +2001-01-01 00:00:00 2001-01-01 00:00:00 2001-01-01 00:00:00 +EXPLAIN EXTENDED SELECT x.a, y.a, z.a FROM t1 x +JOIN t1 y ON x.a=y.a +JOIN t1 z ON y.a=z.a +WHERE x.a='2001-01-01' AND z.a='2001-01-01 00:00:00'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE x system NULL NULL NULL NULL 1 +1 SIMPLE y system NULL NULL NULL NULL 1 +1 SIMPLE z system NULL NULL NULL NULL 1 +Warnings: +Note 1003 select '2001-01-01 00:00:00' AS `a`,'2001-01-01 00:00:00' AS `a`,'2001-01-01 00:00:00' AS `a` from `test`.`t1` `x` join `test`.`t1` `y` join `test`.`t1` `z` where 1 End of 5.0 tests diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index a4d3056b66e..eeabd2641d8 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -3797,4 +3797,53 @@ SELECT 1 FROM t2 JOIN t1 ON 1=1 DROP TABLE t1,t2; +--echo # +--echo # Bug #49199: Optimizer handles incorrectly: +--echo # field='const1' AND field='const2' in some cases +--echo +CREATE TABLE t1(a DATETIME NOT NULL); +INSERT INTO t1 VALUES('2001-01-01'); +SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00'; +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00'; +DROP TABLE t1; + +CREATE TABLE t1(a DATE NOT NULL); +INSERT INTO t1 VALUES('2001-01-01'); +SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00'; +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00'; +DROP TABLE t1; + +CREATE TABLE t1(a TIMESTAMP NOT NULL); +INSERT INTO t1 VALUES('2001-01-01'); +SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00'; +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00'; +DROP TABLE t1; + +CREATE TABLE t1(a DATETIME NOT NULL, b DATE NOT NULL); +INSERT INTO t1 VALUES('2001-01-01', '2001-01-01'); +SELECT * FROM t1 WHERE a='2001-01-01' AND a=b AND b='2001-01-01 00:00:00'; +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a=b AND b='2001-01-01 00:00:00'; +DROP TABLE t1; + +CREATE TABLE t1(a DATETIME NOT NULL, b VARCHAR(20) NOT NULL); +INSERT INTO t1 VALUES('2001-01-01', '2001-01-01'); +SELECT * FROM t1 WHERE a='2001-01-01' AND a=b AND b='2001-01-01 00:00:00'; +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a=b AND b='2001-01-01 00:00:00'; + +SELECT * FROM t1 WHERE a='2001-01-01 00:00:00' AND a=b AND b='2001-01-01'; +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01 00:00:00' AND a=b AND b='2001-01-01'; +DROP TABLE t1; + +CREATE TABLE t1(a DATETIME NOT NULL, b DATE NOT NULL); +INSERT INTO t1 VALUES('2001-01-01', '2001-01-01'); +SELECT x.a, y.a, z.a FROM t1 x + JOIN t1 y ON x.a=y.a + JOIN t1 z ON y.a=z.a + WHERE x.a='2001-01-01' AND z.a='2001-01-01 00:00:00'; +EXPLAIN EXTENDED SELECT x.a, y.a, z.a FROM t1 x + JOIN t1 y ON x.a=y.a + JOIN t1 z ON y.a=z.a + WHERE x.a='2001-01-01' AND z.a='2001-01-01 00:00:00'; + + --echo End of 5.0 tests diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index d03c68b3560..5c2fb9857d5 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -4903,7 +4903,8 @@ Item *Item_bool_rowready_func2::negated_item() } Item_equal::Item_equal(Item_field *f1, Item_field *f2) - : Item_bool_func(), const_item(0), eval_item(0), cond_false(0) + : Item_bool_func(), const_item(0), eval_item(0), cond_false(0), + compare_as_dates(FALSE) { const_item_cache= 0; fields.push_back(f1); @@ -4916,6 +4917,7 @@ Item_equal::Item_equal(Item *c, Item_field *f) const_item_cache= 0; fields.push_back(f); const_item= c; + compare_as_dates= f->is_datetime(); } @@ -4930,9 +4932,45 @@ Item_equal::Item_equal(Item_equal *item_equal) fields.push_back(item); } const_item= item_equal->const_item; + compare_as_dates= item_equal->compare_as_dates; cond_false= item_equal->cond_false; } + +void Item_equal::compare_const(Item *c) +{ + if (compare_as_dates) + { + cmp.set_datetime_cmp_func(&c, &const_item); + cond_false= cmp.compare(); + } + else + { + Item_func_eq *func= new Item_func_eq(c, const_item); + func->set_cmp_func(); + func->quick_fix_field(); + cond_false= !func->val_int(); + } + if (cond_false) + const_item_cache= 1; +} + + +void Item_equal::add(Item *c, Item_field *f) +{ + if (cond_false) + return; + if (!const_item) + { + DBUG_ASSERT(f); + const_item= c; + compare_as_dates= f->is_datetime(); + return; + } + compare_const(c); +} + + void Item_equal::add(Item *c) { if (cond_false) @@ -4942,11 +4980,7 @@ void Item_equal::add(Item *c) const_item= c; return; } - Item_func_eq *func= new Item_func_eq(c, const_item); - func->set_cmp_func(); - func->quick_fix_field(); - if ((cond_false= !func->val_int())) - const_item_cache= 1; + compare_const(c); } void Item_equal::add(Item_field *f) diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index db831c7030c..89bc6f9570b 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1477,7 +1477,9 @@ class Item_equal: public Item_bool_func List fields; /* list of equal field items */ Item *const_item; /* optional constant item equal to fields items */ cmp_item *eval_item; + Arg_comparator cmp; bool cond_false; + bool compare_as_dates; public: inline Item_equal() : Item_bool_func(), const_item(0), eval_item(0), cond_false(0) @@ -1486,6 +1488,8 @@ public: Item_equal(Item *c, Item_field *f); Item_equal(Item_equal *item_equal); inline Item* get_const() { return const_item; } + void compare_const(Item *c); + void add(Item *c, Item_field *f); void add(Item *c); void add(Item_field *f); uint members(); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index df7c5af3ebc..9f0843fe0db 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7237,7 +7237,7 @@ static bool check_simple_equality(Item *left_item, Item *right_item, already contains a constant and its value is not equal to the value of const_item. */ - item_equal->add(const_item); + item_equal->add(const_item, field_item); } else { From 42fead104aea1fd48d694712a98fd2f9c447e351 Mon Sep 17 00:00:00 2001 From: Alfranio Correia Date: Sat, 5 Dec 2009 22:09:41 +0000 Subject: [PATCH 030/104] Post-push fix for BUG#45292. --- mysql-test/suite/binlog/t/binlog_index.test | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/suite/binlog/t/binlog_index.test b/mysql-test/suite/binlog/t/binlog_index.test index 8e54c028dbd..6bfa625422c 100644 --- a/mysql-test/suite/binlog/t/binlog_index.test +++ b/mysql-test/suite/binlog/t/binlog_index.test @@ -3,6 +3,7 @@ # source include/have_log_bin.inc; source include/not_embedded.inc; +source include/have_debug.inc; call mtr.add_suppression('Attempting backtrace'); call mtr.add_suppression('MSYQL_BIN_LOG::purge_logs failed to process registered files that would be purged.'); call mtr.add_suppression('MSYQL_BIN_LOG::open failed to sync the index file'); From 846c81c763d3630ae2e200b8f12a800e68ba1af6 Mon Sep 17 00:00:00 2001 From: Staale Smedseng Date: Sun, 6 Dec 2009 18:11:37 +0100 Subject: [PATCH 031/104] Bug #47391 no stack trace printed to error log on solaris after a crash This patch adds a Solaris-specific version of print_stacktrace() which uses printstack(2), available on all Solaris versions since Solaris 9. (While Solaris 11 adds support for the glibc functions backtrace_*() as of PSARC/2007/162, printstack() is used for consistency over all Solaris versions.) The symbol names are mangled, so use of c++filt may be required as described in the MySQL documentation. --- sql/stacktrace.c | 19 +++++++++++++++++++ sql/stacktrace.h | 3 +++ 2 files changed, 22 insertions(+) diff --git a/sql/stacktrace.c b/sql/stacktrace.c index 4e6ad68c172..295a7a3e1e2 100644 --- a/sql/stacktrace.c +++ b/sql/stacktrace.c @@ -226,6 +226,25 @@ end: stack trace is much more helpful in diagnosing the problem, so please do \n\ resolve it\n"); } + +#elif defined(__sun) + +/* Use Solaris' symbolic stack trace routine. */ +#include + +void print_stacktrace(gptr stack_bottom __attribute__((unused)), + ulong thread_stack __attribute__((unused))) +{ + if (printstack(fileno(stderr)) == -1) + fprintf(stderr, "Error when traversing the stack, stack appears corrupt.\n"); + else + fprintf(stderr, "Please read " + "http://dev.mysql.com/doc/mysql/en/using-stack-trace.html " + "and follow instructions on how to resolve the stack trace. " + "Resolved\nstack trace is much more helpful in diagnosing the " + "problem, so please do \nresolve it\n"); +} + #endif /* TARGET_OS_LINUX */ #endif /* HAVE_STACKTRACE */ diff --git a/sql/stacktrace.h b/sql/stacktrace.h index e5e17cc5b9b..718b545b775 100644 --- a/sql/stacktrace.h +++ b/sql/stacktrace.h @@ -35,6 +35,9 @@ void check_thread_lib(void); #define HAVE_STACKTRACE extern void set_exception_pointers(EXCEPTION_POINTERS *ep); #define init_stacktrace() {} +#elif defined(__sun) +#define HAVE_STACKTRACE +#define init_stacktrace() {} #endif #ifdef HAVE_STACKTRACE From 289c14931b7d8235396c75e36b686f1f1767b60e Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Sun, 6 Dec 2009 23:12:11 +0000 Subject: [PATCH 032/104] BUG#49119: Master crashes when executing 'REVOKE ... ON {PROCEDURE|FUNCTION} FROM ...' The master would hit an assertion when binary log was active. This was due to the fact that the thread's diagnostics area was being cleared before writing to the binlog, independently of mysql_routine_grant returning an error or not. When mysql_routine_grant was to return an error, the return value and the diagnostics area contents would mismatch. Consequently, neither my_ok would be called nor an error would be signaled in the diagnostics area, eventually triggering the assertion in net_end_statement. We fix this by not clearing the diagnostics area at binlogging time. --- mysql-test/suite/rpl/r/rpl_do_grant.result | 73 +++++++++++++++ mysql-test/suite/rpl/t/rpl_do_grant.test | 100 +++++++++++++++++++++ sql/sql_acl.cc | 2 +- 3 files changed, 174 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/rpl/r/rpl_do_grant.result b/mysql-test/suite/rpl/r/rpl_do_grant.result index 0913b1afdbf..65c60acc651 100644 --- a/mysql-test/suite/rpl/r/rpl_do_grant.result +++ b/mysql-test/suite/rpl/r/rpl_do_grant.result @@ -169,4 +169,77 @@ DROP USER 'create_rout_db'@'localhost'; call mtr.add_suppression("Slave: Operation DROP USER failed for 'create_rout_db'@'localhost' Error_code: 1396"); USE mtr; call mtr.add_suppression("Slave: Operation DROP USER failed for 'create_rout_db'@'localhost' Error_code: 1396"); +######## BUG#49119 ####### +### i) test case from the 'how to repeat section' +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +CREATE TABLE t1(c1 INT); +CREATE PROCEDURE p1() SELECT * FROM t1 | +REVOKE EXECUTE ON PROCEDURE p1 FROM 'root'@'localhost'; +ERROR 42000: There is no such grant defined for user 'root' on host 'localhost' on routine 'p1' +DROP TABLE t1; +DROP PROCEDURE p1; +### ii) Test case in which REVOKE partially succeeds +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +CREATE TABLE t1(c1 INT); +CREATE PROCEDURE p1() SELECT * FROM t1 | +CREATE USER 'user49119'@'localhost'; +GRANT EXECUTE ON PROCEDURE p1 TO 'user49119'@'localhost'; +############################################################## +### Showing grants for both users: root and user49119 (master) +SHOW GRANTS FOR 'user49119'@'localhost'; +Grants for user49119@localhost +GRANT USAGE ON *.* TO 'user49119'@'localhost' +GRANT EXECUTE ON PROCEDURE `test`.`p1` TO 'user49119'@'localhost' +SHOW GRANTS FOR CURRENT_USER; +Grants for root@localhost +GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION +############################################################## +############################################################## +### Showing grants for both users: root and user49119 (master) +SHOW GRANTS FOR 'user49119'@'localhost'; +Grants for user49119@localhost +GRANT USAGE ON *.* TO 'user49119'@'localhost' +GRANT EXECUTE ON PROCEDURE `test`.`p1` TO 'user49119'@'localhost' +SHOW GRANTS FOR CURRENT_USER; +Grants for root@localhost +GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION +############################################################## +## This statement will make the revoke fail because root has no +## execute grant. However, it will still revoke the grant for +## user49119. +REVOKE EXECUTE ON PROCEDURE p1 FROM 'user49119'@'localhost', 'root'@'localhost'; +ERROR 42000: There is no such grant defined for user 'root' on host 'localhost' on routine 'p1' +############################################################## +### Showing grants for both users: root and user49119 (master) +### after revoke statement failure +SHOW GRANTS FOR 'user49119'@'localhost'; +Grants for user49119@localhost +GRANT USAGE ON *.* TO 'user49119'@'localhost' +SHOW GRANTS FOR CURRENT_USER; +Grants for root@localhost +GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION +############################################################## +############################################################# +### Showing grants for both users: root and user49119 (slave) +### after revoke statement failure (should match +SHOW GRANTS FOR 'user49119'@'localhost'; +Grants for user49119@localhost +GRANT USAGE ON *.* TO 'user49119'@'localhost' +SHOW GRANTS FOR CURRENT_USER; +Grants for root@localhost +GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION +############################################################## +DROP TABLE t1; +DROP PROCEDURE p1; +DROP USER 'user49119'@'localhost'; "End of test" diff --git a/mysql-test/suite/rpl/t/rpl_do_grant.test b/mysql-test/suite/rpl/t/rpl_do_grant.test index a13adf28b95..d6a06f43d18 100644 --- a/mysql-test/suite/rpl/t/rpl_do_grant.test +++ b/mysql-test/suite/rpl/t/rpl_do_grant.test @@ -216,4 +216,104 @@ connection slave; USE mtr; call mtr.add_suppression("Slave: Operation DROP USER failed for 'create_rout_db'@'localhost' Error_code: 1396"); +# BUG#49119: Master crashes when executing 'REVOKE ... ON +# {PROCEDURE|FUNCTION} FROM ...' +# +# The tests are divided into two test cases: +# +# i) a test case that mimics the one in the bug report. +# +# - We show that, despite the fact, that a revoke command fails +# when binlogging is active, the master will not hit an +# assertion. +# +# ii) a test case that partially succeeds on the master will also +# partially succeed on the slave. +# +# - The revoke statement that partially succeeds tries to revoke +# an EXECUTE grant for two users, and only one of the user has +# the specific grant. This will cause mysql to drop one of the +# grants and report error for the statement. The slave should +# also drop the grants that the master succeed and the SQL +# thread should not stop on statement failure. + +-- echo ######## BUG#49119 ####### +-- echo ### i) test case from the 'how to repeat section' +-- source include/master-slave-reset.inc +-- connection master + +CREATE TABLE t1(c1 INT); +DELIMITER |; +CREATE PROCEDURE p1() SELECT * FROM t1 | +DELIMITER ;| +-- error ER_NONEXISTING_PROC_GRANT +REVOKE EXECUTE ON PROCEDURE p1 FROM 'root'@'localhost'; + +-- sync_slave_with_master + +-- connection master +DROP TABLE t1; +DROP PROCEDURE p1; + +-- sync_slave_with_master + +-- echo ### ii) Test case in which REVOKE partially succeeds + +-- connection master +-- source include/master-slave-reset.inc +-- connection master + +CREATE TABLE t1(c1 INT); +DELIMITER |; +CREATE PROCEDURE p1() SELECT * FROM t1 | +DELIMITER ;| + +CREATE USER 'user49119'@'localhost'; +GRANT EXECUTE ON PROCEDURE p1 TO 'user49119'@'localhost'; + +-- echo ############################################################## +-- echo ### Showing grants for both users: root and user49119 (master) +SHOW GRANTS FOR 'user49119'@'localhost'; +SHOW GRANTS FOR CURRENT_USER; +-- echo ############################################################## + +-- sync_slave_with_master + +-- echo ############################################################## +-- echo ### Showing grants for both users: root and user49119 (master) +SHOW GRANTS FOR 'user49119'@'localhost'; +SHOW GRANTS FOR CURRENT_USER; +-- echo ############################################################## + +-- connection master + +-- echo ## This statement will make the revoke fail because root has no +-- echo ## execute grant. However, it will still revoke the grant for +-- echo ## user49119. +-- error ER_NONEXISTING_PROC_GRANT +REVOKE EXECUTE ON PROCEDURE p1 FROM 'user49119'@'localhost', 'root'@'localhost'; + +-- echo ############################################################## +-- echo ### Showing grants for both users: root and user49119 (master) +-- echo ### after revoke statement failure +SHOW GRANTS FOR 'user49119'@'localhost'; +SHOW GRANTS FOR CURRENT_USER; +-- echo ############################################################## + +-- sync_slave_with_master + +-- echo ############################################################# +-- echo ### Showing grants for both users: root and user49119 (slave) +-- echo ### after revoke statement failure (should match +SHOW GRANTS FOR 'user49119'@'localhost'; +SHOW GRANTS FOR CURRENT_USER; +-- echo ############################################################## + +-- connection master +DROP TABLE t1; +DROP PROCEDURE p1; +DROP USER 'user49119'@'localhost'; + +-- sync_slave_with_master + --echo "End of test" diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 77c72066429..3b81a85c368 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -3378,7 +3378,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, if (write_to_binlog) { - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + write_bin_log(thd, FALSE, thd->query(), thd->query_length()); } rw_unlock(&LOCK_grant); From 3c434c93d0348629ae9cf369919aa6a845bade93 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Mon, 7 Dec 2009 16:38:56 +0200 Subject: [PATCH 033/104] Bug #42760: Select doesn't return desired results when we have null values Part 2 : There was a special optimization on the ref access method for ORDER BY ... DESC that was set without actually looking on the type of the selected index for ORDER BY. Fixed the SELECT ... ORDER BY .. DESC (it uses a different code path compared to the ASC that has been fixed with the previous fix). --- mysql-test/r/order_by.result | 9 +++++++++ mysql-test/t/order_by.test | 9 +++++++++ sql/sql_select.cc | 2 +- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result index f0e5b5fde3d..87b6c3f5455 100644 --- a/mysql-test/r/order_by.result +++ b/mysql-test/r/order_by.result @@ -1111,5 +1111,14 @@ id select_type table type possible_keys key key_len ref rows Extra SELECT 1 AS col FROM t1 WHERE a=2 AND (c=10 OR c IS NULL) ORDER BY c; col 1 +# Must use ref-or-null on the a_c index +EXPLAIN +SELECT 1 AS col FROM t1 WHERE a=2 AND (c=10 OR c IS NULL) ORDER BY c DESC; +id select_type table type possible_keys key key_len ref rows Extra +x x x ref_or_null a_c,a x x x x x +# Must return 1 row +SELECT 1 AS col FROM t1 WHERE a=2 AND (c=10 OR c IS NULL) ORDER BY c DESC; +col +1 DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test index d9a6c0f844d..4da279cc8fd 100644 --- a/mysql-test/t/order_by.test +++ b/mysql-test/t/order_by.test @@ -778,6 +778,15 @@ SELECT 1 AS col FROM t1 WHERE a=2 AND (c=10 OR c IS NULL) ORDER BY c; --echo # Must return 1 row SELECT 1 AS col FROM t1 WHERE a=2 AND (c=10 OR c IS NULL) ORDER BY c; +# part 2 of the problem : DESC test cases +--echo # Must use ref-or-null on the a_c index +--replace_column 1 x 2 x 3 x 6 x 7 x 8 x 9 x 10 x +EXPLAIN +SELECT 1 AS col FROM t1 WHERE a=2 AND (c=10 OR c IS NULL) ORDER BY c DESC; +--echo # Must return 1 row +SELECT 1 AS col FROM t1 WHERE a=2 AND (c=10 OR c IS NULL) ORDER BY c DESC; + + DROP TABLE t1; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 9f0843fe0db..f655db0fc32 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -12824,7 +12824,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, } DBUG_RETURN(1); } - if (tab->ref.key_parts <= used_key_parts) + if (tab->ref.key_parts <= used_key_parts && tab->type == JT_REF) { /* SELECT * FROM t1 WHERE a=1 ORDER BY a DESC,b DESC From b2439d5cbcd6f7c41b3d48674bed3076f14c0ddb Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Tue, 8 Dec 2009 11:14:51 +0100 Subject: [PATCH 034/104] Fixed --fast flag on Linux to use -O3 --- BUILD/build_mccge.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/BUILD/build_mccge.sh b/BUILD/build_mccge.sh index 3345ac3dcb5..8ca31b2d119 100755 --- a/BUILD/build_mccge.sh +++ b/BUILD/build_mccge.sh @@ -1303,7 +1303,11 @@ set_linux_configs() compiler_flags="$compiler_flags -m32" fi if test "x$fast_flag" != "xno" ; then - compiler_flags="$compiler_flags -O2" + if test "x$fast_flag" = "xyes" ; then + compiler_flags="$compiler_flags -O3" + else + compiler_flags="$compiler_flags -O2" + fi else compiler_flags="$compiler_flags -O0" fi From 259b028d8ef613610a6b690bc00c5872977cb23c Mon Sep 17 00:00:00 2001 From: Alfranio Correia Date: Tue, 8 Dec 2009 16:03:19 +0000 Subject: [PATCH 035/104] Post-push fix for BUG#45292. Disabled execution in valgrind to avoid false positive memory leaks due to fault-injection tests (i.e. call to abort()). --- mysql-test/suite/binlog/t/binlog_index.test | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mysql-test/suite/binlog/t/binlog_index.test b/mysql-test/suite/binlog/t/binlog_index.test index 6bfa625422c..9d4a49602a6 100644 --- a/mysql-test/suite/binlog/t/binlog_index.test +++ b/mysql-test/suite/binlog/t/binlog_index.test @@ -3,6 +3,8 @@ # source include/have_log_bin.inc; source include/not_embedded.inc; +# Don't test this under valgrind, memory leaks will occur +--source include/not_valgrind.inc source include/have_debug.inc; call mtr.add_suppression('Attempting backtrace'); call mtr.add_suppression('MSYQL_BIN_LOG::purge_logs failed to process registered files that would be purged.'); From 9058e48121db3a15edcdf0bd75402dc2aad9ed50 Mon Sep 17 00:00:00 2001 From: He Zhenxing Date: Wed, 9 Dec 2009 14:13:56 +0800 Subject: [PATCH 036/104] BUG#45520 rpl_killed_ddl fails sporadically in pb2 There are three issues that caused rpl_killed_ddl fails sporadically in pb2: 1) thd->clear_error() was not called before create Query event if operation is executed successfully. 2) DATABASE d2 might do exist because the statement to CREATE or ALTER it was killed 3) because of bug 43353, kill the query that do DROP FUNCTION or DROP PROCEDURE can result in SP not found This patch fixed all above issues by: 1) Called thd->clear_error() if the operation succeeded. 2) Add IF EXISTS to the DROP DATABASE d2 statement 3) Temporarily disabled testing DROP FUNCTION/PROCEDURE IF EXISTS. --- mysql-test/r/rpl_killed_ddl.result | 12 +++--------- mysql-test/t/rpl_killed_ddl.test | 23 ++++++++++++++++------- sql/sql_db.cc | 5 +++-- 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/mysql-test/r/rpl_killed_ddl.result b/mysql-test/r/rpl_killed_ddl.result index aa419a8556e..b9ee915bdce 100644 --- a/mysql-test/r/rpl_killed_ddl.result +++ b/mysql-test/r/rpl_killed_ddl.result @@ -53,7 +53,7 @@ source include/diff_master_slave.inc; DROP DATABASE d1; source include/kill_query.inc; source include/diff_master_slave.inc; -DROP DATABASE d2; +DROP DATABASE IF EXISTS d2; source include/kill_query.inc; source include/diff_master_slave.inc; CREATE FUNCTION f2 () RETURNS INT DETERMINISTIC @@ -63,10 +63,7 @@ source include/diff_master_slave.inc; ALTER FUNCTION f1 SQL SECURITY INVOKER; source include/kill_query.inc; source include/diff_master_slave.inc; -DROP FUNCTION IF EXISTS f1; -source include/kill_query.inc; -source include/diff_master_slave.inc; -DROP FUNCTION IF EXISTS f2; +DROP FUNCTION f1; source include/kill_query.inc; source include/diff_master_slave.inc; CREATE PROCEDURE p2 (OUT rows INT) @@ -79,10 +76,7 @@ source include/diff_master_slave.inc; ALTER PROCEDURE p1 SQL SECURITY INVOKER COMMENT 'return rows of table t1'; source include/kill_query.inc; source include/diff_master_slave.inc; -DROP PROCEDURE IF EXISTS p1; -source include/kill_query.inc; -source include/diff_master_slave.inc; -DROP PROCEDURE IF EXISTS p2; +DROP PROCEDURE p1; source include/kill_query.inc; source include/diff_master_slave.inc; CREATE TABLE t2 (b int); diff --git a/mysql-test/t/rpl_killed_ddl.test b/mysql-test/t/rpl_killed_ddl.test index f4f2f6ac320..7c07d5eecf0 100644 --- a/mysql-test/t/rpl_killed_ddl.test +++ b/mysql-test/t/rpl_killed_ddl.test @@ -123,7 +123,7 @@ source include/kill_query_and_diff_master_slave.inc; send DROP DATABASE d1; source include/kill_query_and_diff_master_slave.inc; -send DROP DATABASE d2; +send DROP DATABASE IF EXISTS d2; source include/kill_query_and_diff_master_slave.inc; ######## FUNCTION ######## @@ -139,13 +139,21 @@ source include/kill_query_and_diff_master_slave.inc; # function f1 probably does not exist because the ALTER query was # killed -send DROP FUNCTION IF EXISTS f1; +send DROP FUNCTION f1; source include/kill_query_and_diff_master_slave.inc; # function f2 probably does not exist because the CREATE query was # killed -send DROP FUNCTION IF EXISTS f2; -source include/kill_query_and_diff_master_slave.inc; +# +# Temporarily disabled. Because of BUG#43353, KILL the query may +# result in function not found, and for 5.1, DROP statements will be +# logged if the function is not found on master, so the following DROP +# FUNCTION statement may be interrupted and not drop the function on +# master, but still get logged and executed on slave and cause +# inconsistence. Also disable the following DROP PROCEDURE IF EXITS +# below. +#send DROP FUNCTION IF EXISTS f2; +#source include/kill_query_and_diff_master_slave.inc; ######## PROCEDURE ######## @@ -163,11 +171,12 @@ source include/kill_query_and_diff_master_slave.inc; send ALTER PROCEDURE p1 SQL SECURITY INVOKER COMMENT 'return rows of table t1'; source include/kill_query_and_diff_master_slave.inc; -send DROP PROCEDURE IF EXISTS p1; +send DROP PROCEDURE p1; source include/kill_query_and_diff_master_slave.inc; -send DROP PROCEDURE IF EXISTS p2; -source include/kill_query_and_diff_master_slave.inc; +# Temporarily disabled because of bug#43353, see comment above for DROP FUNCTION IF EXISTS +#send DROP PROCEDURE IF EXISTS p2; +#source include/kill_query_and_diff_master_slave.inc; ######## TABLE ######## diff --git a/sql/sql_db.cc b/sql/sql_db.cc index be538783458..2ad3953625f 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -541,6 +541,7 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, file. In this case it's best to just continue as if nothing has happened. (This is a very unlikely senario) */ + thd->clear_error(); } if (!silent) @@ -644,6 +645,7 @@ bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info) if (mysql_bin_log.is_open()) { + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, 0, /* suppress_use */ TRUE, THD::NOT_KILLED); @@ -655,7 +657,6 @@ bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info) qinfo.db = db; qinfo.db_len = (uint) strlen(db); - thd->clear_error(); /* These DDL methods and logging protected with LOCK_mysql_create_db */ mysql_bin_log.write(&qinfo); } @@ -769,6 +770,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) } if (mysql_bin_log.is_open()) { + thd->clear_error(); Query_log_event qinfo(thd, query, query_length, 0, /* suppress_use */ TRUE, THD::NOT_KILLED); /* @@ -779,7 +781,6 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) qinfo.db = db; qinfo.db_len = (uint) strlen(db); - thd->clear_error(); /* These DDL methods and logging protected with LOCK_mysql_create_db */ mysql_bin_log.write(&qinfo); } From 714348a8d3923648e32b32277cfb3c614437580d Mon Sep 17 00:00:00 2001 From: He Zhenxing Date: Wed, 9 Dec 2009 14:27:46 +0800 Subject: [PATCH 037/104] removed rpl_killed_ddl from disabled list --- mysql-test/t/disabled.def | 1 - 1 file changed, 1 deletion(-) diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 7ce67d3fa89..062667c249e 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -25,4 +25,3 @@ loaddata_autocom_ndb : Bug#35148: Error '4009 Cluster Failure' in various tests ndb_autodiscover3 : Bug#35148: Error '4009 Cluster Failure' in various tests on various platforms ndb_autodiscover : Bug#45972: ndb.ndb_autodiscover fails occasionally with pb2 ndb_autodiscover2 : Bug#45972: ndb.ndb_autodiscover fails occasionally with pb2 -rpl_killed_ddl : Bug#45520: rpl_killed_ddl fails sporadically in pb2 From 2b0642a639ffa7845b2a1811b00a26e5f57fb172 Mon Sep 17 00:00:00 2001 From: Olav Sandstaa Date: Wed, 9 Dec 2009 10:16:11 +0100 Subject: [PATCH 038/104] Fix for Bug#49506 Valgrind error in make_cond_for_table_from_pred This fix has been proposed by Sergey Petrunya and has been contributed under SCA by sca@askmonty.org. The cause for this valgrind error is that in the function add_cond_and_fix() in sql_select.cc an Item_cond_and object is created. This is marked as fixed but does not have a correct table_map() attribute. Later, in make_join_select(), if engine_condition_pushdown is in use, this table map is used and results in the valgrind error. The fix is to add a call to update_used_tables() in add_cond_and_fix() so that the table map is updated correctly. This patch is tested by multiple existing tests (e.g. the tests innodb_mysql, innodb, fulltext, compress all produces this valgrind warning/error without this fix). --- sql/sql_select.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 569d8183ab6..b2a4958020a 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -5859,6 +5859,7 @@ inline void add_cond_and_fix(Item **e1, Item *e2) { *e1= res; res->quick_fix_field(); + res->update_used_tables(); } } else From 69fa790fbd4f9b83b853b53ba1b64965fe88c454 Mon Sep 17 00:00:00 2001 From: Evgeny Potemkin Date: Wed, 9 Dec 2009 18:43:45 +0300 Subject: [PATCH 039/104] Bug#49489: Uninitialized cache led to a wrong result. Arg_comparator uses Item_cache objects to store constants being compared when they're need a type conversion. Because this cache wasn't initialized properly Arg_comparator might produce wrong comparison result. The Arg_comparator::cache_converted_constant function now initializes cache prior to usage. --- mysql-test/r/select.result | 10 ++++++++++ mysql-test/t/select.test | 9 +++++++++ sql/item_cmpfunc.cc | 2 +- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index d0b2a575a32..1750051289a 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -4609,4 +4609,14 @@ HAVING v <= 't' ORDER BY pk; v DROP TABLE t1; +# +# Bug#49489 Uninitialized cache led to a wrong result. +# +CREATE TABLE t1(c1 DOUBLE(5,4)); +INSERT INTO t1 VALUES (9.1234); +SELECT * FROM t1 WHERE c1 < 9.12345; +c1 +9.1234 +DROP TABLE t1; +# End of test for bug#49489. End of 5.1 tests diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index ac65e5cbaf5..982aec726f7 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -3964,4 +3964,13 @@ ORDER BY pk; DROP TABLE t1; +--echo # +--echo # Bug#49489 Uninitialized cache led to a wrong result. +--echo # +CREATE TABLE t1(c1 DOUBLE(5,4)); +INSERT INTO t1 VALUES (9.1234); +SELECT * FROM t1 WHERE c1 < 9.12345; +DROP TABLE t1; +--echo # End of test for bug#49489. + --echo End of 5.1 tests diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 5415d6f4f8a..a3c3051d790 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1023,7 +1023,7 @@ Item** Arg_comparator::cache_converted_constant(THD *thd, Item **value, (*value)->const_item() && type != (*value)->result_type()) { Item_cache *cache= Item_cache::get_cache(*value, type); - cache->store(*value); + cache->setup(*value); *cache_item= cache; return cache_item; } From e33a8b2a1a254271d99b6c5f00097fd0d89adb90 Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Wed, 9 Dec 2009 20:19:51 -0700 Subject: [PATCH 040/104] WL#2360 Performance schema Part III: mysys instrumentation --- client/client_priv.h | 23 ++- client/mysqlcheck.c | 9 +- client/mysqldump.c | 24 ++- include/keycache.h | 4 +- include/my_bitmap.h | 4 +- include/my_pthread.h | 18 +- include/my_sys.h | 13 +- include/thr_lock.h | 9 +- mysys/charset.c | 16 +- mysys/default.c | 12 +- mysys/mf_iocache.c | 48 +++--- mysys/mf_iocache2.c | 6 +- mysys/mf_keycache.c | 65 ++++---- mysys/mf_tempdir.c | 12 +- mysys/my_bitmap.c | 14 +- mysys/my_fopen.c | 16 +- mysys/my_gethostbyname.c | 8 +- mysys/my_getopt.c | 42 +++-- mysys/my_getsystime.c | 6 +- mysys/my_init.c | 194 +++++++++++++++++++--- mysys/my_largepage.c | 11 +- mysys/my_lib.c | 8 +- mysys/my_lock.c | 6 +- mysys/my_lockmem.c | 10 +- mysys/my_net.c | 6 +- mysys/my_open.c | 17 +- mysys/my_pread.c | 10 +- mysys/my_pthread.c | 20 +-- mysys/my_thr_init.c | 190 +++++++++++++++------ mysys/my_winfile.c | 6 +- mysys/mysys_priv.h | 6 +- mysys/safemalloc.c | 18 +- mysys/thr_alarm.c | 111 +++++++------ mysys/thr_lock.c | 150 ++++++++--------- mysys/thr_mutex.c | 11 +- plugin/semisync/semisync_master.cc | 24 +-- plugin/semisync/semisync_master.h | 14 +- plugin/semisync/semisync_master_plugin.cc | 36 +++- sql/debug_sync.cc | 96 +++++++---- sql/ha_ndbcluster.cc | 24 +-- sql/ha_ndbcluster_binlog.cc | 38 ++--- sql/item_func.cc | 104 +++++++----- sql/lock.cc | 12 +- sql/mysql_priv.h | 17 +- sql/mysqld.cc | 61 ++++--- sql/replication.h | 6 +- sql/sp_cache.cc | 30 +++- sql/sql_base.cc | 152 ++++++++--------- sql/sql_class.cc | 18 +- sql/sql_class.h | 16 +- sql/sql_db.cc | 116 ++++++++----- sql/sql_delete.cc | 12 +- sql/sql_handler.cc | 6 +- sql/sql_insert.cc | 177 ++++++++++---------- sql/sql_parse.cc | 4 +- sql/sql_partition.cc | 8 +- sql/sql_plugin.cc | 4 +- sql/sql_rename.cc | 10 +- sql/sql_show.cc | 28 ++-- sql/sql_table.cc | 134 +++++++-------- sql/sql_test.cc | 16 +- sql/sql_trigger.cc | 6 +- sql/sql_view.cc | 8 +- storage/federated/ha_federated.cc | 2 +- 64 files changed, 1383 insertions(+), 919 deletions(-) diff --git a/client/client_priv.h b/client/client_priv.h index 53027465771..97a8920f744 100644 --- a/client/client_priv.h +++ b/client/client_priv.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2006 MySQL AB +/* Copyright (C) 2001-2006 MySQL AB, 2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -87,3 +87,24 @@ enum options_client OPT_INIT_COMMAND, OPT_MAX_CLIENT_OPTION }; + +/** + First mysql version supporting the information schema. +*/ +#define FIRST_INFORMATION_SCHEMA_VERSION 50003 + +/** + Name of the information schema database. +*/ +#define INFORMATION_SCHEMA_DB_NAME "information_schema" + +/** + First mysql version supporting the performance schema. +*/ +#define FIRST_PERFORMANCE_SCHEMA_VERSION 50600 + +/** + Name of the performance schema database. +*/ +#define PERFORMANCE_SCHEMA_DB_NAME "performance_schema" + diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index 5c801eb6e26..efbb95b6657 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000 MySQL AB, 2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -644,8 +644,11 @@ static int process_one_db(char *database) static int use_db(char *database) { - if (mysql_get_server_version(sock) >= 50003 && - !my_strcasecmp(&my_charset_latin1, database, "information_schema")) + if (mysql_get_server_version(sock) >= FIRST_INFORMATION_SCHEMA_VERSION && + !my_strcasecmp(&my_charset_latin1, database, INFORMATION_SCHEMA_DB_NAME)) + return 1; + if (mysql_get_server_version(sock) >= FIRST_PERFORMANCE_SCHEMA_VERSION && + !my_strcasecmp(&my_charset_latin1, database, PERFORMANCE_SCHEMA_DB_NAME)) return 1; if (mysql_select_db(sock, database)) { diff --git a/client/mysqldump.c b/client/mysqldump.c index ebf0add4590..f9a64e4c9d2 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -3836,8 +3836,12 @@ static int dump_all_databases() return 1; while ((row= mysql_fetch_row(tableres))) { - if (mysql_get_server_version(mysql) >= 50003 && - !my_strcasecmp(&my_charset_latin1, row[0], "information_schema")) + if (mysql_get_server_version(mysql) >= FIRST_INFORMATION_SCHEMA_VERSION && + !my_strcasecmp(&my_charset_latin1, row[0], INFORMATION_SCHEMA_DB_NAME)) + continue; + + if (mysql_get_server_version(mysql) >= FIRST_PERFORMANCE_SCHEMA_VERSION && + !my_strcasecmp(&my_charset_latin1, row[0], PERFORMANCE_SCHEMA_DB_NAME)) continue; if (dump_all_tables_in_db(row[0])) @@ -3854,8 +3858,12 @@ static int dump_all_databases() } while ((row= mysql_fetch_row(tableres))) { - if (mysql_get_server_version(mysql) >= 50003 && - !my_strcasecmp(&my_charset_latin1, row[0], "information_schema")) + if (mysql_get_server_version(mysql) >= FIRST_INFORMATION_SCHEMA_VERSION && + !my_strcasecmp(&my_charset_latin1, row[0], INFORMATION_SCHEMA_DB_NAME)) + continue; + + if (mysql_get_server_version(mysql) >= FIRST_PERFORMANCE_SCHEMA_VERSION && + !my_strcasecmp(&my_charset_latin1, row[0], PERFORMANCE_SCHEMA_DB_NAME)) continue; if (dump_all_views_in_db(row[0])) @@ -4256,10 +4264,12 @@ static int dump_selected_tables(char *db, char **table_names, int tables) } end= pos; - /* Can't LOCK TABLES in INFORMATION_SCHEMA, so don't try. */ + /* Can't LOCK TABLES in I_S / P_S, so don't try. */ if (lock_tables && - !(mysql_get_server_version(mysql) >= 50003 && - !my_strcasecmp(&my_charset_latin1, db, "information_schema"))) + !(mysql_get_server_version(mysql) >= FIRST_INFORMATION_SCHEMA_VERSION && + !my_strcasecmp(&my_charset_latin1, db, INFORMATION_SCHEMA_DB_NAME)) && + !(mysql_get_server_version(mysql) >= FIRST_PERFORMANCE_SCHEMA_VERSION && + !my_strcasecmp(&my_charset_latin1, db, PERFORMANCE_SCHEMA_DB_NAME))) { if (mysql_real_query(mysql, lock_tables_query.str, lock_tables_query.length-1)) diff --git a/include/keycache.h b/include/keycache.h index a6005bae878..4e715dda88d 100644 --- a/include/keycache.h +++ b/include/keycache.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2003 MySQL AB +/* Copyright (C) 2003 MySQL AB, 2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -70,7 +70,7 @@ typedef struct st_key_cache uchar HUGE_PTR *block_mem; /* memory for block buffers */ BLOCK_LINK *used_last; /* ptr to the last block of the LRU chain */ BLOCK_LINK *used_ins; /* ptr to the insertion block in LRU chain */ - pthread_mutex_t cache_lock; /* to lock access to the cache structure */ + mysql_mutex_t cache_lock; /* to lock access to the cache structure */ KEYCACHE_WQUEUE resize_queue; /* threads waiting during resize operation */ /* Waiting for a zero resize count. Using a queue for symmetry though diff --git a/include/my_bitmap.h b/include/my_bitmap.h index 78642df3362..314dac983b0 100644 --- a/include/my_bitmap.h +++ b/include/my_bitmap.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000 MySQL AB, 2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -34,7 +34,7 @@ typedef struct st_bitmap acquiring the mutex */ #ifdef THREAD - pthread_mutex_t *mutex; + mysql_mutex_t *mutex; #endif } MY_BITMAP; diff --git a/include/my_pthread.h b/include/my_pthread.h index c4d4e3d7adf..bfb5a2f67f4 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -607,6 +607,8 @@ extern pthread_mutexattr_t my_errorcheck_mutexattr; typedef ulong my_thread_id; extern my_bool my_thread_global_init(void); +extern my_bool my_thread_basic_global_init(void); +extern void my_thread_basic_global_reinit(void); extern void my_thread_global_end(void); extern my_bool my_thread_init(void); extern void my_thread_end(void); @@ -637,10 +639,10 @@ extern int pthread_dummy(int); struct st_my_thread_var { int thr_errno; - pthread_cond_t suspend; - pthread_mutex_t mutex; - pthread_mutex_t * volatile current_mutex; - pthread_cond_t * volatile current_cond; + mysql_cond_t suspend; + mysql_mutex_t mutex; + mysql_mutex_t * volatile current_mutex; + mysql_cond_t * volatile current_cond; pthread_t pthread_self; my_thread_id id; int cmp_length; @@ -692,16 +694,16 @@ extern uint thd_lib_detected; #ifdef THREAD #ifndef thread_safe_increment #define thread_safe_increment(V,L) \ - (pthread_mutex_lock((L)), (V)++, pthread_mutex_unlock((L))) + (mysql_mutex_lock((L)), (V)++, mysql_mutex_unlock((L))) #define thread_safe_decrement(V,L) \ - (pthread_mutex_lock((L)), (V)--, pthread_mutex_unlock((L))) + (mysql_mutex_lock((L)), (V)--, mysql_mutex_unlock((L))) #endif #ifndef thread_safe_add #define thread_safe_add(V,C,L) \ - (pthread_mutex_lock((L)), (V)+=(C), pthread_mutex_unlock((L))) + (mysql_mutex_lock((L)), (V)+=(C), mysql_mutex_unlock((L))) #define thread_safe_sub(V,C,L) \ - (pthread_mutex_lock((L)), (V)-=(C), pthread_mutex_unlock((L))) + (mysql_mutex_lock((L)), (V)-=(C), mysql_mutex_unlock((L))) #endif #endif diff --git a/include/my_sys.h b/include/my_sys.h index f4217b17fee..6e66dc30f9b 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -338,7 +338,7 @@ struct st_my_file_info #endif enum file_type type; #if defined(THREAD) && !defined(HAVE_PREAD) && !defined(_WIN32) - pthread_mutex_t mutex; + mysql_mutex_t mutex; #endif }; @@ -358,7 +358,7 @@ typedef struct st_my_tmpdir char **list; uint cur, max; #ifdef THREAD - pthread_mutex_t mutex; + mysql_mutex_t mutex; #endif } MY_TMPDIR; @@ -374,9 +374,9 @@ typedef int (*IO_CACHE_CALLBACK)(struct st_io_cache*); #ifdef THREAD typedef struct st_io_cache_share { - pthread_mutex_t mutex; /* To sync on reads into buffer. */ - pthread_cond_t cond; /* To wait for signals. */ - pthread_cond_t cond_writer; /* For a synchronized writer. */ + mysql_mutex_t mutex; /* To sync on reads into buffer. */ + mysql_cond_t cond; /* To wait for signals. */ + mysql_cond_t cond_writer; /* For a synchronized writer. */ /* Offset in file corresponding to the first byte of buffer. */ my_off_t pos_in_file; /* If a synchronized write cache is the source of the data. */ @@ -437,7 +437,7 @@ typedef struct st_io_cache /* Used when cacheing files */ The lock is for append buffer used in SEQ_READ_APPEND cache need mutex copying from append buffer to read buffer. */ - pthread_mutex_t append_buffer_lock; + mysql_mutex_t append_buffer_lock; /* The following is used when several threads are reading the same file in parallel. They are synchronized on disk @@ -691,6 +691,7 @@ extern const char **my_error_unregister(int first, int last); extern void my_message(uint my_err, const char *str,myf MyFlags); extern void my_message_no_curses(uint my_err, const char *str,myf MyFlags); extern void my_message_curses(uint my_err, const char *str,myf MyFlags); +extern my_bool my_basic_init(void); extern my_bool my_init(void); extern void my_end(int infoflag); extern int my_redel(const char *from, const char *to, int MyFlags); diff --git a/include/thr_lock.h b/include/thr_lock.h index fb70c57c0e7..d669d2dd2ab 100644 --- a/include/thr_lock.h +++ b/include/thr_lock.h @@ -1,4 +1,4 @@ -/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. +/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -115,10 +115,11 @@ typedef struct st_thr_lock_data { THR_LOCK_OWNER *owner; struct st_thr_lock_data *next,**prev; struct st_thr_lock *lock; - pthread_cond_t *cond; + mysql_cond_t *cond; enum thr_lock_type type; void *status_param; /* Param to status functions */ void *debug_print_param; + struct PSI_table *m_psi; } THR_LOCK_DATA; struct st_lock_list { @@ -127,7 +128,7 @@ struct st_lock_list { typedef struct st_thr_lock { LIST list; - pthread_mutex_t mutex; + mysql_mutex_t mutex; struct st_lock_list read_wait; struct st_lock_list read; struct st_lock_list write_wait; @@ -144,7 +145,7 @@ typedef struct st_thr_lock { extern LIST *thr_lock_thread_list; -extern pthread_mutex_t THR_LOCK_lock; +extern mysql_mutex_t THR_LOCK_lock; my_bool init_thr_lock(void); /* Must be called once/thread */ #define thr_lock_owner_init(owner, info_arg) (owner)->info= (info_arg) diff --git a/mysys/charset.c b/mysys/charset.c index 280b2ad6091..3f3f62a0ae1 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -339,10 +339,10 @@ static my_bool my_read_charset_file(const char *filename, myf myflags) !(buf= (uchar*) my_malloc(len,myflags))) return TRUE; - if ((fd=my_open(filename,O_RDONLY,myflags)) < 0) + if ((fd= mysql_file_open(key_file_charset, filename, O_RDONLY, myflags)) < 0) goto error; - tmp_len=my_read(fd, buf, len, myflags); - my_close(fd,myflags); + tmp_len= mysql_file_read(fd, buf, len, myflags); + mysql_file_close(fd, myflags); if (tmp_len != len) goto error; @@ -421,7 +421,7 @@ static my_bool init_available_charsets(myf myflags) To make things thread safe we are not allowing other threads to interfere while we may changing the cs_info_table */ - pthread_mutex_lock(&THR_LOCK_charset); + mysql_mutex_lock(&THR_LOCK_charset); if (!charset_initialized) { bzero(&all_charsets,sizeof(all_charsets)); @@ -444,7 +444,7 @@ static my_bool init_available_charsets(myf myflags) error= my_read_charset_file(fname,myflags); charset_initialized=1; } - pthread_mutex_unlock(&THR_LOCK_charset); + mysql_mutex_unlock(&THR_LOCK_charset); } return error; } @@ -507,7 +507,7 @@ static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags) To make things thread safe we are not allowing other threads to interfere while we may changing the cs_info_table */ - pthread_mutex_lock(&THR_LOCK_charset); + mysql_mutex_lock(&THR_LOCK_charset); if (!(cs->state & (MY_CS_COMPILED|MY_CS_LOADED))) /* if CS is not in memory */ { @@ -529,7 +529,7 @@ static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags) else cs= NULL; - pthread_mutex_unlock(&THR_LOCK_charset); + mysql_mutex_unlock(&THR_LOCK_charset); } return cs; } diff --git a/mysys/default.c b/mysys/default.c index 6468cf2b35d..b9bcbff72da 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright (C) 2000-2003 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -683,7 +683,7 @@ static int search_default_file_with_ext(Process_option_func opt_handler, static const char includedir_keyword[]= "includedir"; static const char include_keyword[]= "include"; const int max_recursion_level= 10; - FILE *fp; + MYSQL_FILE *fp; uint line=0; my_bool found_group=0; uint i; @@ -723,10 +723,10 @@ static int search_default_file_with_ext(Process_option_func opt_handler, } } #endif - if (!(fp= my_fopen(name, O_RDONLY, MYF(0)))) + if (!(fp= mysql_file_fopen(key_file_cnf, name, O_RDONLY, MYF(0)))) return 1; /* Ignore wrong files */ - while (fgets(buff, sizeof(buff) - 1, fp)) + while (mysql_file_fgets(buff, sizeof(buff) - 1, fp)) { line++; /* Ignore comment and empty lines */ @@ -916,11 +916,11 @@ static int search_default_file_with_ext(Process_option_func opt_handler, goto err; } } - my_fclose(fp,MYF(0)); + mysql_file_fclose(fp, MYF(0)); return(0); err: - my_fclose(fp,MYF(0)); + mysql_file_fclose(fp, MYF(0)); return -1; /* Fatal error */ } diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c index 1a47982b221..620ac667a8b 100644 --- a/mysys/mf_iocache.c +++ b/mysys/mf_iocache.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -58,9 +58,9 @@ static void my_aiowait(my_aio_result *result); #ifdef THREAD #define lock_append_buffer(info) \ - pthread_mutex_lock(&(info)->append_buffer_lock) + mysql_mutex_lock(&(info)->append_buffer_lock) #define unlock_append_buffer(info) \ - pthread_mutex_unlock(&(info)->append_buffer_lock) + mysql_mutex_unlock(&(info)->append_buffer_lock) #else #define lock_append_buffer(info) #define unlock_append_buffer(info) @@ -265,7 +265,8 @@ int init_io_cache(IO_CACHE *info, File file, size_t cachesize, info->append_read_pos = info->write_pos = info->write_buffer; info->write_end = info->write_buffer + info->buffer_length; #ifdef THREAD - pthread_mutex_init(&info->append_buffer_lock,MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_IO_CACHE_append_buffer_lock, + &info->append_buffer_lock, MY_MUTEX_INIT_FAST); #endif } #if defined(SAFE_MUTEX) && defined(THREAD) @@ -639,9 +640,10 @@ void init_io_cache_share(IO_CACHE *read_cache, IO_CACHE_SHARE *cshare, DBUG_ASSERT(read_cache->type == READ_CACHE); DBUG_ASSERT(!write_cache || (write_cache->type == WRITE_CACHE)); - pthread_mutex_init(&cshare->mutex, MY_MUTEX_INIT_FAST); - pthread_cond_init(&cshare->cond, 0); - pthread_cond_init(&cshare->cond_writer, 0); + mysql_mutex_init(key_IO_CACHE_SHARE_mutex, + &cshare->mutex, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_IO_CACHE_SHARE_cond, &cshare->cond, 0); + mysql_cond_init(key_IO_CACHE_SHARE_cond_writer, &cshare->cond_writer, 0); cshare->running_threads= num_threads; cshare->total_threads= num_threads; @@ -692,7 +694,7 @@ void remove_io_thread(IO_CACHE *cache) if (cache == cshare->source_cache) flush_io_cache(cache); - pthread_mutex_lock(&cshare->mutex); + mysql_mutex_lock(&cshare->mutex); DBUG_PRINT("io_cache_share", ("%s: 0x%lx", (cache == cshare->source_cache) ? "writer" : "reader", (long) cache)); @@ -715,18 +717,18 @@ void remove_io_thread(IO_CACHE *cache) if (!--cshare->running_threads) { DBUG_PRINT("io_cache_share", ("the last running thread leaves, wake all")); - pthread_cond_signal(&cshare->cond_writer); - pthread_cond_broadcast(&cshare->cond); + mysql_cond_signal(&cshare->cond_writer); + mysql_cond_broadcast(&cshare->cond); } - pthread_mutex_unlock(&cshare->mutex); + mysql_mutex_unlock(&cshare->mutex); if (!total) { DBUG_PRINT("io_cache_share", ("last thread removed, destroy share")); - pthread_cond_destroy (&cshare->cond_writer); - pthread_cond_destroy (&cshare->cond); - pthread_mutex_destroy(&cshare->mutex); + mysql_cond_destroy (&cshare->cond_writer); + mysql_cond_destroy (&cshare->cond); + mysql_mutex_destroy(&cshare->mutex); } DBUG_VOID_RETURN; @@ -767,7 +769,7 @@ static int lock_io_cache(IO_CACHE *cache, my_off_t pos) DBUG_ENTER("lock_io_cache"); /* Enter the lock. */ - pthread_mutex_lock(&cshare->mutex); + mysql_mutex_lock(&cshare->mutex); cshare->running_threads--; DBUG_PRINT("io_cache_share", ("%s: 0x%lx pos: %lu running: %u", (cache == cshare->source_cache) ? @@ -784,7 +786,7 @@ static int lock_io_cache(IO_CACHE *cache, my_off_t pos) while (cshare->running_threads) { DBUG_PRINT("io_cache_share", ("writer waits in lock")); - pthread_cond_wait(&cshare->cond_writer, &cshare->mutex); + mysql_cond_wait(&cshare->cond_writer, &cshare->mutex); } DBUG_PRINT("io_cache_share", ("writer awoke, going to copy")); @@ -796,7 +798,7 @@ static int lock_io_cache(IO_CACHE *cache, my_off_t pos) if (!cshare->running_threads) { DBUG_PRINT("io_cache_share", ("waking writer")); - pthread_cond_signal(&cshare->cond_writer); + mysql_cond_signal(&cshare->cond_writer); } /* @@ -808,7 +810,7 @@ static int lock_io_cache(IO_CACHE *cache, my_off_t pos) cshare->source_cache) { DBUG_PRINT("io_cache_share", ("reader waits in lock")); - pthread_cond_wait(&cshare->cond, &cshare->mutex); + mysql_cond_wait(&cshare->cond, &cshare->mutex); } /* @@ -850,7 +852,7 @@ static int lock_io_cache(IO_CACHE *cache, my_off_t pos) cshare->running_threads) { DBUG_PRINT("io_cache_share", ("reader waits in lock")); - pthread_cond_wait(&cshare->cond, &cshare->mutex); + mysql_cond_wait(&cshare->cond, &cshare->mutex); } /* If the block is not yet read, continue with a locked cache and read. */ @@ -872,7 +874,7 @@ static int lock_io_cache(IO_CACHE *cache, my_off_t pos) Leave the lock. Do not call unlock_io_cache() later. The thread that filled the buffer did this and marked all threads as running. */ - pthread_mutex_unlock(&cshare->mutex); + mysql_mutex_unlock(&cshare->mutex); DBUG_RETURN(0); } @@ -915,8 +917,8 @@ static void unlock_io_cache(IO_CACHE *cache) cshare->total_threads)); cshare->running_threads= cshare->total_threads; - pthread_cond_broadcast(&cshare->cond); - pthread_mutex_unlock(&cshare->mutex); + mysql_cond_broadcast(&cshare->cond); + mysql_mutex_unlock(&cshare->mutex); DBUG_VOID_RETURN; } @@ -1837,7 +1839,7 @@ int end_io_cache(IO_CACHE *info) /* Destroy allocated mutex */ info->type= TYPE_NOT_SET; #ifdef THREAD - pthread_mutex_destroy(&info->append_buffer_lock); + mysql_mutex_destroy(&info->append_buffer_lock); #endif } DBUG_RETURN(error); diff --git a/mysys/mf_iocache2.c b/mysys/mf_iocache2.c index 705a3fc46ec..5e34bff2b51 100644 --- a/mysys/mf_iocache2.c +++ b/mysys/mf_iocache2.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -82,7 +82,7 @@ my_off_t my_b_append_tell(IO_CACHE* info) answer to the question. */ #ifdef THREAD - pthread_mutex_lock(&info->append_buffer_lock); + mysql_mutex_lock(&info->append_buffer_lock); #endif #ifndef DBUG_OFF /* @@ -104,7 +104,7 @@ my_off_t my_b_append_tell(IO_CACHE* info) #endif res = info->end_of_file + (info->write_pos-info->append_read_pos); #ifdef THREAD - pthread_mutex_unlock(&info->append_buffer_lock); + mysql_mutex_unlock(&info->append_buffer_lock); #endif return res; } diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c index 139a61da1f0..9cbe3a21bce 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -59,13 +59,13 @@ time only. Before starting to wait on its condition variable with - pthread_cond_wait(), the thread enters itself to a specific wait queue + mysql_cond_wait(), the thread enters itself to a specific wait queue with link_into_queue() (double linked with '*next' + '**prev') or wait_on_queue() (single linked with '*next'). Another thread, when releasing a resource, looks up the waiting thread in the related wait queue. It sends a signal with - pthread_cond_signal() to the waiting thread. + mysql_cond_signal() to the waiting thread. NOTE: Depending on the particular wait situation, either the sending thread removes the waiting thread from the wait queue with @@ -128,8 +128,8 @@ accessing it; to set this number equal to add #define MAX_THREADS - - to substitute calls of pthread_cond_wait for calls of - pthread_cond_timedwait (wait with timeout set up); + - to substitute calls of mysql_cond_wait for calls of + mysql_cond_timedwait (wait with timeout set up); this setting should be used only when you want to trap a deadlock situation, which theoretically should not happen; to set timeout equal to seconds add @@ -160,7 +160,7 @@ #define COND_FOR_SAVED 1 #define COND_FOR_READERS 2 -typedef pthread_cond_t KEYCACHE_CONDVAR; +typedef mysql_cond_t KEYCACHE_CONDVAR; /* descriptor of the page in the key cache block buffer */ struct st_keycache_page @@ -227,7 +227,7 @@ KEY_CACHE *dflt_key_cache= &dflt_key_cache_var; static int flush_all_key_blocks(KEY_CACHE *keycache); #ifdef THREAD static void wait_on_queue(KEYCACHE_WQUEUE *wqueue, - pthread_mutex_t *mutex); + mysql_mutex_t *mutex); static void release_whole_queue(KEYCACHE_WQUEUE *wqueue); #else #define wait_on_queue(wqueue, mutex) do {} while (0) @@ -314,20 +314,20 @@ static long keycache_thread_id; ((uint) (((char*)(h)-(char *) keycache->hash_link_root)/sizeof(HASH_LINK))) #if (defined(KEYCACHE_TIMEOUT) && !defined(__WIN__)) || defined(KEYCACHE_DEBUG) -static int keycache_pthread_cond_wait(pthread_cond_t *cond, - pthread_mutex_t *mutex); +static int keycache_pthread_cond_wait(mysql_cond_t *cond, + mysql_mutex_t *mutex); #else -#define keycache_pthread_cond_wait pthread_cond_wait +#define keycache_pthread_cond_wait(C, M) mysql_cond_wait(C, M) #endif #if defined(KEYCACHE_DEBUG) -static int keycache_pthread_mutex_lock(pthread_mutex_t *mutex); -static void keycache_pthread_mutex_unlock(pthread_mutex_t *mutex); -static int keycache_pthread_cond_signal(pthread_cond_t *cond); +static int keycache_pthread_mutex_lock(mysql_mutex_t *mutex); +static void keycache_pthread_mutex_unlock(mysql_mutex_t *mutex); +static int keycache_pthread_cond_signal(mysql_cond_t *cond); #else -#define keycache_pthread_mutex_lock pthread_mutex_lock -#define keycache_pthread_mutex_unlock pthread_mutex_unlock -#define keycache_pthread_cond_signal pthread_cond_signal +#define keycache_pthread_mutex_lock(M) mysql_mutex_lock(M) +#define keycache_pthread_mutex_unlock(M) mysql_mutex_unlock(M) +#define keycache_pthread_cond_signal(C) mysql_cond_signal(C) #endif /* defined(KEYCACHE_DEBUG) */ #if !defined(DBUG_OFF) @@ -403,7 +403,8 @@ int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, keycache->cnt_for_resize_op= 0; keycache->waiting_for_resize_cnt.last_thread= NULL; keycache->in_init= 0; - pthread_mutex_init(&keycache->cache_lock, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_KEY_CACHE_cache_lock, + &keycache->cache_lock, MY_MUTEX_INIT_FAST); keycache->resize_queue.last_thread= NULL; } @@ -773,7 +774,7 @@ void end_key_cache(KEY_CACHE *keycache, my_bool cleanup) if (cleanup) { - pthread_mutex_destroy(&keycache->cache_lock); + mysql_mutex_destroy(&keycache->cache_lock); keycache->key_cache_inited= keycache->can_be_used= 0; KEYCACHE_DEBUG_CLOSE; } @@ -888,7 +889,7 @@ static void unlink_from_queue(KEYCACHE_WQUEUE *wqueue, */ static void wait_on_queue(KEYCACHE_WQUEUE *wqueue, - pthread_mutex_t *mutex) + mysql_mutex_t *mutex) { struct st_my_thread_var *last; struct st_my_thread_var *thread= my_thread_var; @@ -4166,7 +4167,7 @@ static int flush_all_key_blocks(KEY_CACHE *keycache) do { - safe_mutex_assert_owner(&keycache->cache_lock); + mysql_mutex_assert_owner(&keycache->cache_lock); total_found= 0; /* @@ -4407,8 +4408,8 @@ static void keycache_dump(KEY_CACHE *keycache) #if defined(KEYCACHE_TIMEOUT) && !defined(__WIN__) -static int keycache_pthread_cond_wait(pthread_cond_t *cond, - pthread_mutex_t *mutex) +static int keycache_pthread_cond_wait(mysql_cond_t *cond, + mysql_mutex_t *mutex) { int rc; struct timeval now; /* time when we started waiting */ @@ -4435,7 +4436,7 @@ static int keycache_pthread_cond_wait(pthread_cond_t *cond, fprintf(keycache_debug_log, "waiting...\n"); fflush(keycache_debug_log); #endif - rc= pthread_cond_timedwait(cond, mutex, &timeout); + rc= mysql_cond_timedwait(cond, mutex, &timeout); KEYCACHE_THREAD_TRACE_BEGIN("finished waiting"); if (rc == ETIMEDOUT || rc == ETIME) { @@ -4456,12 +4457,12 @@ static int keycache_pthread_cond_wait(pthread_cond_t *cond, } #else #if defined(KEYCACHE_DEBUG) -static int keycache_pthread_cond_wait(pthread_cond_t *cond, - pthread_mutex_t *mutex) +static int keycache_pthread_cond_wait(mysql_cond_t *cond, + mysql_mutex_t *mutex) { int rc; KEYCACHE_THREAD_TRACE_END("started waiting"); - rc= pthread_cond_wait(cond, mutex); + rc= mysql_cond_wait(cond, mutex); KEYCACHE_THREAD_TRACE_BEGIN("finished waiting"); return rc; } @@ -4471,27 +4472,27 @@ static int keycache_pthread_cond_wait(pthread_cond_t *cond, #if defined(KEYCACHE_DEBUG) -static int keycache_pthread_mutex_lock(pthread_mutex_t *mutex) +static int keycache_pthread_mutex_lock(mysql_mutex_t *mutex) { int rc; - rc= pthread_mutex_lock(mutex); + rc= mysql_mutex_lock(mutex); KEYCACHE_THREAD_TRACE_BEGIN(""); return rc; } -static void keycache_pthread_mutex_unlock(pthread_mutex_t *mutex) +static void keycache_pthread_mutex_unlock(mysql_mutex_t *mutex) { KEYCACHE_THREAD_TRACE_END(""); - pthread_mutex_unlock(mutex); + mysql_mutex_unlock(mutex); } -static int keycache_pthread_cond_signal(pthread_cond_t *cond) +static int keycache_pthread_cond_signal(mysql_cond_t *cond) { int rc; KEYCACHE_THREAD_TRACE("signal"); - rc= pthread_cond_signal(cond); + rc= mysql_cond_signal(cond); return rc; } diff --git a/mysys/mf_tempdir.c b/mysys/mf_tempdir.c index f41bbab946f..5633182ab3a 100644 --- a/mysys/mf_tempdir.c +++ b/mysys/mf_tempdir.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,7 +29,7 @@ my_bool init_tmpdir(MY_TMPDIR *tmpdir, const char *pathlist) DBUG_ENTER("init_tmpdir"); DBUG_PRINT("enter", ("pathlist: %s", pathlist ? pathlist : "NULL")); - pthread_mutex_init(&tmpdir->mutex, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_TMPDIR_mutex, &tmpdir->mutex, MY_MUTEX_INIT_FAST); if (my_init_dynamic_array(&tmpdir->full_list, sizeof(char*), 1, 5)) goto err; if (!pathlist || !pathlist[0]) @@ -65,7 +65,7 @@ my_bool init_tmpdir(MY_TMPDIR *tmpdir, const char *pathlist) err: delete_dynamic(&tmpdir->full_list); /* Safe to free */ - pthread_mutex_destroy(&tmpdir->mutex); + mysql_mutex_destroy(&tmpdir->mutex); DBUG_RETURN(TRUE); } @@ -75,10 +75,10 @@ char *my_tmpdir(MY_TMPDIR *tmpdir) char *dir; if (!tmpdir->max) return tmpdir->list[0]; - pthread_mutex_lock(&tmpdir->mutex); + mysql_mutex_lock(&tmpdir->mutex); dir=tmpdir->list[tmpdir->cur]; tmpdir->cur= (tmpdir->cur == tmpdir->max) ? 0 : tmpdir->cur+1; - pthread_mutex_unlock(&tmpdir->mutex); + mysql_mutex_unlock(&tmpdir->mutex); return dir; } @@ -90,6 +90,6 @@ void free_tmpdir(MY_TMPDIR *tmpdir) for (i=0; i<=tmpdir->max; i++) my_free(tmpdir->list[i], MYF(0)); delete_dynamic(&tmpdir->full_list); - pthread_mutex_destroy(&tmpdir->mutex); + mysql_mutex_destroy(&tmpdir->mutex); } diff --git a/mysys/my_bitmap.c b/mysys/my_bitmap.c index e127b2584ae..91370bd3727 100644 --- a/mysys/my_bitmap.c +++ b/mysys/my_bitmap.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -87,7 +87,7 @@ static inline void bitmap_lock(MY_BITMAP *map __attribute__((unused))) { #ifdef THREAD if (map->mutex) - pthread_mutex_lock(map->mutex); + mysql_mutex_lock(map->mutex); #endif } @@ -95,7 +95,7 @@ static inline void bitmap_unlock(MY_BITMAP *map __attribute__((unused))) { #ifdef THREAD if (map->mutex) - pthread_mutex_unlock(map->mutex); + mysql_mutex_unlock(map->mutex); #endif } @@ -112,7 +112,7 @@ my_bool bitmap_init(MY_BITMAP *map, my_bitmap_map *buf, uint n_bits, if (thread_safe) { size_in_bytes= ALIGN_SIZE(size_in_bytes); - extra= sizeof(pthread_mutex_t); + extra= sizeof(mysql_mutex_t); } map->mutex= 0; #endif @@ -121,8 +121,8 @@ my_bool bitmap_init(MY_BITMAP *map, my_bitmap_map *buf, uint n_bits, #ifdef THREAD if (thread_safe) { - map->mutex= (pthread_mutex_t *) ((char*) buf + size_in_bytes); - pthread_mutex_init(map->mutex, MY_MUTEX_INIT_FAST); + map->mutex= (mysql_mutex_t *) ((char*) buf + size_in_bytes); + mysql_mutex_init(key_BITMAP_mutex, map->mutex, MY_MUTEX_INIT_FAST); } #endif } @@ -148,7 +148,7 @@ void bitmap_free(MY_BITMAP *map) { #ifdef THREAD if (map->mutex) - pthread_mutex_destroy(map->mutex); + mysql_mutex_destroy(map->mutex); #endif my_free((char*) map->bitmap, MYF(0)); map->bitmap=0; diff --git a/mysys/my_fopen.c b/mysys/my_fopen.c index 879acac0111..3f2bc08df65 100644 --- a/mysys/my_fopen.c +++ b/mysys/my_fopen.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -63,18 +63,18 @@ FILE *my_fopen(const char *filename, int flags, myf MyFlags) thread_safe_increment(my_stream_opened,&THR_LOCK_open); DBUG_RETURN(fd); /* safeguard */ } - pthread_mutex_lock(&THR_LOCK_open); + mysql_mutex_lock(&THR_LOCK_open); if ((my_file_info[filedesc].name= (char*) my_strdup(filename,MyFlags))) { my_stream_opened++; my_file_total_opened++; my_file_info[filedesc].type= STREAM_BY_FOPEN; - pthread_mutex_unlock(&THR_LOCK_open); + mysql_mutex_unlock(&THR_LOCK_open); DBUG_PRINT("exit",("stream: 0x%lx", (long) fd)); DBUG_RETURN(fd); } - pthread_mutex_unlock(&THR_LOCK_open); + mysql_mutex_unlock(&THR_LOCK_open); (void) my_fclose(fd,MyFlags); my_errno=ENOMEM; } @@ -98,7 +98,7 @@ int my_fclose(FILE *fd, myf MyFlags) DBUG_ENTER("my_fclose"); DBUG_PRINT("my",("stream: 0x%lx MyFlags: %d", (long) fd, MyFlags)); - pthread_mutex_lock(&THR_LOCK_open); + mysql_mutex_lock(&THR_LOCK_open); file= my_fileno(fd); #ifndef _WIN32 err= fclose(fd); @@ -119,7 +119,7 @@ int my_fclose(FILE *fd, myf MyFlags) my_file_info[file].type = UNOPEN; my_free(my_file_info[file].name, MYF(MY_ALLOW_ZERO_PTR)); } - pthread_mutex_unlock(&THR_LOCK_open); + mysql_mutex_unlock(&THR_LOCK_open); DBUG_RETURN(err); } /* my_fclose */ @@ -149,7 +149,7 @@ FILE *my_fdopen(File Filedes, const char *name, int Flags, myf MyFlags) } else { - pthread_mutex_lock(&THR_LOCK_open); + mysql_mutex_lock(&THR_LOCK_open); my_stream_opened++; if ((uint) Filedes < (uint) my_file_limit) { @@ -163,7 +163,7 @@ FILE *my_fdopen(File Filedes, const char *name, int Flags, myf MyFlags) } my_file_info[Filedes].type = STREAM_BY_FDOPEN; } - pthread_mutex_unlock(&THR_LOCK_open); + mysql_mutex_unlock(&THR_LOCK_open); } DBUG_PRINT("exit",("stream: 0x%lx", (long) fd)); diff --git a/mysys/my_gethostbyname.c b/mysys/my_gethostbyname.c index 067fdfee9db..4b7e9054d61 100644 --- a/mysys/my_gethostbyname.c +++ b/mysys/my_gethostbyname.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2004 MySQL AB +/* Copyright (C) 2002, 2004 MySQL AB, 2008-2009 Sun Microsystems, Inc This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -79,7 +79,7 @@ struct hostent *my_gethostbyname_r(const char *name, #else /* !HAVE_GETHOSTBYNAME_R */ #ifdef THREAD -extern pthread_mutex_t LOCK_gethostbyname_r; +extern mysql_mutex_t LOCK_gethostbyname_r; #endif /* @@ -96,7 +96,7 @@ struct hostent *my_gethostbyname_r(const char *name, int buflen, int *h_errnop) { struct hostent *hp; - pthread_mutex_lock(&LOCK_gethostbyname_r); + mysql_mutex_lock(&LOCK_gethostbyname_r); hp= gethostbyname(name); *h_errnop= h_errno; return hp; @@ -104,7 +104,7 @@ struct hostent *my_gethostbyname_r(const char *name, void my_gethostbyname_r_free() { - pthread_mutex_unlock(&LOCK_gethostbyname_r); + mysql_mutex_unlock(&LOCK_gethostbyname_r); } #endif /* !HAVE_GETHOSTBYNAME_R */ diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index 2e8f09f14fd..8361d288bc7 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002-2006 MySQL AB +/* Copyright (C) 2002-2006 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -91,16 +91,6 @@ static void default_reporter(enum loglevel level, fflush(stderr); } -/* - function: handle_options - - Sort options; put options first, until special end of options (--), or - until end of argv. Parse options; check that the given option matches with - one of the options in struct 'my_option', return error in case of ambiguous - or unknown option. Check that option was given an argument if it requires - one. Call function 'get_one_option()' once for each option. -*/ - static uchar** (*getopt_get_addr)(const char *, uint, const struct my_option *, int *); void my_getopt_register_get_addr(uchar** (*func_addr)(const char *, uint, @@ -109,6 +99,22 @@ void my_getopt_register_get_addr(uchar** (*func_addr)(const char *, uint, getopt_get_addr= func_addr; } +/** + Handle command line options. + Sort options. + Put options first, until special end of options (--), + or until the end of argv. Parse options, check that the given option + matches with one of the options in struct 'my_option'. + Check that option was given an argument if it requires one + Call the optional 'get_one_option()' function once for each option. + @param [in, out] argc command line options (count) + @param [in, out] argv command line options (values) + @param [in] longopts descriptor of all valid options + @param [in] get_one_option optional callback function to process each option, + can be NULL. + @return error in case of ambiguous or unknown options, + 0 on success. +*/ int handle_options(int *argc, char ***argv, const struct my_option *longopts, my_get_one_option get_one_option) @@ -427,9 +433,9 @@ invalid value '%s'", my_progname, optp->name, optend); continue; } - if (get_one_option(optp->id, optp, - *((my_bool*) value) ? - (char*) "1" : disabled_my_option)) + if (get_one_option && get_one_option(optp->id, optp, + *((my_bool*) value) ? + (char*) "1" : disabled_my_option)) return EXIT_ARGUMENT_INVALID; continue; } @@ -493,7 +499,7 @@ invalid value '%s'", optp->arg_type == NO_ARG) { *((my_bool*) optp->value)= (my_bool) 1; - if (get_one_option(optp->id, optp, argument)) + if (get_one_option && get_one_option(optp->id, optp, argument)) return EXIT_UNSPECIFIED_ERROR; continue; } @@ -513,7 +519,7 @@ invalid value '%s'", { if (optp->var_type == GET_BOOL) *((my_bool*) optp->value)= (my_bool) 1; - if (get_one_option(optp->id, optp, argument)) + if (get_one_option && get_one_option(optp->id, optp, argument)) return EXIT_UNSPECIFIED_ERROR; continue; } @@ -539,7 +545,7 @@ invalid value '%s'", my_progname, argument, optp->name); return error; } - if (get_one_option(optp->id, optp, argument)) + if (get_one_option && get_one_option(optp->id, optp, argument)) return EXIT_UNSPECIFIED_ERROR; break; } @@ -563,7 +569,7 @@ invalid value '%s'", my_progname, argument, optp->name); return error; } - if (get_one_option(optp->id, optp, argument)) + if (get_one_option && get_one_option(optp->id, optp, argument)) return EXIT_UNSPECIFIED_ERROR; (*argc)--; /* option handled (short or long), decrease argument count */ diff --git a/mysys/my_getsystime.c b/mysys/my_getsystime.c index b692b18bfc7..81bb3e15298 100644 --- a/mysys/my_getsystime.c +++ b/mysys/my_getsystime.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2004 MySQL AB +/* Copyright (C) 2004 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -168,7 +168,7 @@ ulonglong my_micro_time_and_time(time_t *time_arg) static time_t cur_time= 0; hrtime_t cur_gethrtime; - pthread_mutex_lock(&THR_LOCK_time); + mysql_mutex_lock(&THR_LOCK_time); cur_gethrtime= gethrtime(); if ((cur_gethrtime - prev_gethrtime) > DELTA_FOR_SECONDS) { @@ -176,7 +176,7 @@ ulonglong my_micro_time_and_time(time_t *time_arg) prev_gethrtime= cur_gethrtime; } *time_arg= cur_time; - pthread_mutex_unlock(&THR_LOCK_time); + mysql_mutex_unlock(&THR_LOCK_time); return cur_gethrtime/1000; #else ulonglong newtime; diff --git a/mysys/my_init.c b/mysys/my_init.c index c4fda599481..fa68bb2b1cb 100644 --- a/mysys/my_init.c +++ b/mysys/my_init.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright (C) 2000-2003 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -43,6 +43,8 @@ static void netware_init(); #endif my_bool my_init_done= 0; +/** True if @c my_basic_init() has been called. */ +my_bool my_basic_init_done= 0; uint mysys_usage_id= 0; /* Incremented for each my_init() */ ulong my_thread_stack_size= 65536; @@ -57,6 +59,57 @@ static ulong atoi_octal(const char *str) return (ulong) tmp; } +MYSQL_FILE *mysql_stdin= NULL; +static MYSQL_FILE instrumented_stdin; + +/** + Perform a limited initialisation of mysys. + This initialisation is sufficient to: + - allocate memory, + - read configuration files, + - parse command lines arguments. + To complete the mysys initialisation, + call my_init(). + @return 0 on success +*/ +my_bool my_basic_init(void) +{ + if (my_basic_init_done) + return 0; + my_basic_init_done= 1; + + mysys_usage_id++; + my_umask= 0660; /* Default umask for new files */ + my_umask_dir= 0700; /* Default umask for new directories */ + + init_glob_errs(); + + instrumented_stdin.m_file= stdin; + instrumented_stdin.m_psi= NULL; /* not yet instrumented */ + mysql_stdin= & instrumented_stdin; + +#if defined(THREAD) + if (my_thread_global_init()) + return 1; +# if defined(SAFE_MUTEX) + safe_mutex_global_init(); /* Must be called early */ +# endif +#endif +#if defined(THREAD) && defined(MY_PTHREAD_FASTMUTEX) && !defined(SAFE_MUTEX) + fastmutex_global_init(); /* Must be called early */ +#endif + netware_init(); +#ifdef THREAD +#if defined(HAVE_PTHREAD_INIT) + pthread_init(); /* Must be called before DBUG_ENTER */ +#endif + if (my_thread_basic_global_init()) + return 1; +#endif + + return 0; +} + /* Init my_sys functions and my_sys variabels @@ -74,26 +127,14 @@ my_bool my_init(void) char * str; if (my_init_done) return 0; - my_init_done=1; - mysys_usage_id++; - my_umask= 0660; /* Default umask for new files */ - my_umask_dir= 0700; /* Default umask for new directories */ - init_glob_errs(); -#if defined(THREAD) + my_init_done= 1; + + if (my_basic_init()) + return 1; + +#ifdef THREAD if (my_thread_global_init()) return 1; -# if defined(SAFE_MUTEX) - safe_mutex_global_init(); /* Must be called early */ -# endif -#endif -#if defined(THREAD) && defined(MY_PTHREAD_FASTMUTEX) && !defined(SAFE_MUTEX) - fastmutex_global_init(); /* Must be called early */ -#endif - netware_init(); -#ifdef THREAD -#if defined(HAVE_PTHREAD_INIT) - pthread_init(); /* Must be called before DBUG_ENTER */ -#endif #if !defined( __WIN__) && !defined(__NETWARE__) sigfillset(&my_signals); /* signals blocked by mf_brkhant */ #endif @@ -239,6 +280,7 @@ Voluntary context switches %ld, Involuntary context switches %ld\n", WSACleanup(); #endif /* __WIN__ */ my_init_done=0; + my_basic_init_done= 0; } /* my_end */ @@ -538,3 +580,117 @@ static void netware_init() DBUG_VOID_RETURN; } #endif /* __NETWARE__ */ + +#ifdef HAVE_PSI_INTERFACE + +#if !defined(HAVE_PREAD) && !defined(_WIN32) +PSI_mutex_key key_my_file_info_mutex; +#endif /* !defined(HAVE_PREAD) && !defined(_WIN32) */ + +#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) +PSI_mutex_key key_LOCK_localtime_r; +#endif /* !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) */ + +#ifndef HAVE_GETHOSTBYNAME_R +PSI_mutex_key key_LOCK_gethostbyname_r; +#endif /* HAVE_GETHOSTBYNAME_R */ + +PSI_mutex_key key_BITMAP_mutex, key_IO_CACHE_append_buffer_lock, + key_IO_CACHE_SHARE_mutex, key_KEY_CACHE_cache_lock, key_LOCK_alarm, + key_my_thread_var_mutex, key_THR_LOCK_charset, key_THR_LOCK_heap, + key_THR_LOCK_isam, key_THR_LOCK_lock, key_THR_LOCK_malloc, + key_THR_LOCK_mutex, key_THR_LOCK_myisam, key_THR_LOCK_net, + key_THR_LOCK_open, key_THR_LOCK_threads, key_THR_LOCK_time, + key_TMPDIR_mutex; + +static PSI_mutex_info all_mysys_mutexes[]= +{ +#if defined(THREAD) && !defined(HAVE_PREAD) && !defined(_WIN32) + { &key_my_file_info_mutex, "st_my_file_info:mutex", 0}, +#endif /* !defined(HAVE_PREAD) && !defined(_WIN32) */ +#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) + { &key_LOCK_localtime_r, "LOCK_localtime_r", PSI_FLAG_GLOBAL}, +#endif /* !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) */ +#ifndef HAVE_GETHOSTBYNAME_R + { &key_LOCK_gethostbyname_r, "LOCK_gethostbyname_r", PSI_FLAG_GLOBAL}, +#endif /* HAVE_GETHOSTBYNAME_R */ + { &key_BITMAP_mutex, "BITMAP::mutex", 0}, + { &key_IO_CACHE_append_buffer_lock, "IO_CACHE::append_buffer_lock", 0}, + { &key_IO_CACHE_SHARE_mutex, "IO_CACHE::SHARE_mutex", 0}, + { &key_KEY_CACHE_cache_lock, "KEY_CACHE::cache_lock", 0}, + { &key_LOCK_alarm, "LOCK_alarm", PSI_FLAG_GLOBAL}, + { &key_my_thread_var_mutex, "my_thread_var::mutex", 0}, + { &key_THR_LOCK_charset, "THR_LOCK_charset", PSI_FLAG_GLOBAL}, + { &key_THR_LOCK_heap, "THR_LOCK_heap", PSI_FLAG_GLOBAL}, + { &key_THR_LOCK_isam, "THR_LOCK_isam", PSI_FLAG_GLOBAL}, + { &key_THR_LOCK_lock, "THR_LOCK_lock", PSI_FLAG_GLOBAL}, + { &key_THR_LOCK_malloc, "THR_LOCK_malloc", PSI_FLAG_GLOBAL}, + { &key_THR_LOCK_mutex, "THR_LOCK::mutex", 0}, + { &key_THR_LOCK_myisam, "THR_LOCK_myisam", PSI_FLAG_GLOBAL}, + { &key_THR_LOCK_net, "THR_LOCK_net", PSI_FLAG_GLOBAL}, + { &key_THR_LOCK_open, "THR_LOCK_open", PSI_FLAG_GLOBAL}, + { &key_THR_LOCK_threads, "THR_LOCK_threads", PSI_FLAG_GLOBAL}, + { &key_THR_LOCK_time, "THR_LOCK_time", PSI_FLAG_GLOBAL}, + { &key_TMPDIR_mutex, "TMPDIR_mutex", PSI_FLAG_GLOBAL} +}; + +PSI_cond_key key_COND_alarm, key_IO_CACHE_SHARE_cond, + key_IO_CACHE_SHARE_cond_writer, key_my_thread_var_suspend, + key_THR_COND_threads; + +static PSI_cond_info all_mysys_conds[]= +{ + { &key_COND_alarm, "COND_alarm", PSI_FLAG_GLOBAL}, + { &key_IO_CACHE_SHARE_cond, "IO_CACHE_SHARE::cond", 0}, + { &key_IO_CACHE_SHARE_cond_writer, "IO_CACHE_SHARE::cond_writer", 0}, + { &key_my_thread_var_suspend, "my_thread_var::suspend", 0}, + { &key_THR_COND_threads, "THR_COND_threads", 0} +}; + +#ifdef USE_ALARM_THREAD +PSI_thread_key key_thread_alarm; + +static PSI_thread_info all_mysys_threads[]= +{ + { &key_thread_alarm, "alarm", PSI_FLAG_GLOBAL} +}; +#endif /* USE_ALARM_THREAD */ + +#ifdef HUGETLB_USE_PROC_MEMINFO +PSI_file_key key_file_proc_meminfo; +#endif /* HUGETLB_USE_PROC_MEMINFO */ +PSI_file_key key_file_charset, key_file_cnf; + +static PSI_file_info all_mysys_files[]= +{ +#ifdef HUGETLB_USE_PROC_MEMINFO + { &key_file_proc_meminfo, "proc_meminfo", 0}, +#endif /* HUGETLB_USE_PROC_MEMINFO */ + { &key_file_charset, "charset", 0}, + { &key_file_cnf, "cnf", 0} +}; + +void my_init_mysys_psi_keys() +{ + const char* category= "mysys"; + int count; + + if (PSI_server == NULL) + return; + + count= sizeof(all_mysys_mutexes)/sizeof(all_mysys_mutexes[0]); + PSI_server->register_mutex(category, all_mysys_mutexes, count); + + count= sizeof(all_mysys_conds)/sizeof(all_mysys_conds[0]); + PSI_server->register_cond(category, all_mysys_conds, count); + +#ifdef USE_ALARM_THREAD + count= sizeof(all_mysys_threads)/sizeof(all_mysys_threads[0]); + PSI_server->register_thread(category, all_mysys_threads, count); +#endif /* USE_ALARM_THREAD */ + + count= sizeof(all_mysys_files)/sizeof(all_mysys_files[0]); + PSI_server->register_file(category, all_mysys_files, count); +} +#endif /* HAVE_PSI_INTERFACE */ + diff --git a/mysys/my_largepage.c b/mysys/my_largepage.c index d96e1048fd0..e65d3a0a5f5 100644 --- a/mysys/my_largepage.c +++ b/mysys/my_largepage.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2004 MySQL AB +/* Copyright (C) 2004 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -91,19 +91,20 @@ void my_large_free(uchar* ptr, myf my_flags __attribute__((unused))) uint my_get_large_page_size_int(void) { - FILE *f; + MYSQL_FILE *f; uint size = 0; char buf[256]; DBUG_ENTER("my_get_large_page_size_int"); - if (!(f = my_fopen("/proc/meminfo", O_RDONLY, MYF(MY_WME)))) + if (!(f= mysql_file_fopen(key_file_proc_meminfo, "/proc/meminfo", + O_RDONLY, MYF(MY_WME)))) goto finish; - while (fgets(buf, sizeof(buf), f)) + while (mysql_file_fgets(buf, sizeof(buf), f)) if (sscanf(buf, "Hugepagesize: %u kB", &size)) break; - my_fclose(f, MYF(MY_WME)); + mysql_file_fclose(f, MYF(MY_WME)); finish: DBUG_RETURN(size * 1024); diff --git a/mysys/my_lib.c b/mysys/my_lib.c index dcc1263f383..0113d1498df 100644 --- a/mysys/my_lib.c +++ b/mysys/my_lib.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -110,7 +110,7 @@ MY_DIR *my_dir(const char *path, myf MyFlags) DBUG_PRINT("my",("path: '%s' MyFlags: %d",path,MyFlags)); #if defined(THREAD) && !defined(HAVE_READDIR_R) - pthread_mutex_lock(&THR_LOCK_open); + mysql_mutex_lock(&THR_LOCK_open); #endif dirp = opendir(directory_file_name(tmp_path,(char *) path)); @@ -173,7 +173,7 @@ MY_DIR *my_dir(const char *path, myf MyFlags) (void) closedir(dirp); #if defined(THREAD) && !defined(HAVE_READDIR_R) - pthread_mutex_unlock(&THR_LOCK_open); + mysql_mutex_unlock(&THR_LOCK_open); #endif result->dir_entry= (FILEINFO *)dir_entries_storage->buffer; result->number_off_files= dir_entries_storage->elements; @@ -185,7 +185,7 @@ MY_DIR *my_dir(const char *path, myf MyFlags) error: #if defined(THREAD) && !defined(HAVE_READDIR_R) - pthread_mutex_unlock(&THR_LOCK_open); + mysql_mutex_unlock(&THR_LOCK_open); #endif my_errno=errno; if (dirp) diff --git a/mysys/my_lock.c b/mysys/my_lock.c index 62f39bd3b71..1436c845286 100644 --- a/mysys/my_lock.c +++ b/mysys/my_lock.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright (C) 2000-2003 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -206,8 +206,8 @@ int my_lock(File fd, int locktype, my_off_t start, my_off_t length, else timeout_sec= WIN_LOCK_INFINITE; - if(win_lock(fd, locktype, start, length, timeout_sec) == 0) - DBUG_RETURN(0); + if (win_lock(fd, locktype, start, length, timeout_sec) == 0) + DBUG_RETURN(0); } #else #if defined(HAVE_FCNTL) diff --git a/mysys/my_lockmem.c b/mysys/my_lockmem.c index f2c6d52a382..1b582783d33 100644 --- a/mysys/my_lockmem.c +++ b/mysys/my_lockmem.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -66,9 +66,9 @@ uchar *my_malloc_lock(uint size,myf MyFlags) element->list.data=(uchar*) element; element->page=ptr; element->size=size; - pthread_mutex_lock(&THR_LOCK_malloc); + mysql_mutex_lock(&THR_LOCK_malloc); mem_list=list_add(mem_list,&element->list); - pthread_mutex_unlock(&THR_LOCK_malloc); + mysql_mutex_unlock(&THR_LOCK_malloc); } DBUG_RETURN(ptr); } @@ -79,7 +79,7 @@ void my_free_lock(uchar *ptr,myf Myflags __attribute__((unused))) LIST *list; struct st_mem_list *element=0; - pthread_mutex_lock(&THR_LOCK_malloc); + mysql_mutex_lock(&THR_LOCK_malloc); for (list=mem_list ; list ; list=list->next) { element=(struct st_mem_list*) list->data; @@ -90,7 +90,7 @@ void my_free_lock(uchar *ptr,myf Myflags __attribute__((unused))) break; } } - pthread_mutex_unlock(&THR_LOCK_malloc); + mysql_mutex_unlock(&THR_LOCK_malloc); if (element) my_free((uchar*) element,MYF(0)); free(ptr); /* Free even if not locked */ diff --git a/mysys/my_net.c b/mysys/my_net.c index 81d977210f8..e584e541175 100644 --- a/mysys/my_net.c +++ b/mysys/my_net.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -35,8 +35,8 @@ void my_inet_ntoa(struct in_addr in, char *buf) { char *ptr; - pthread_mutex_lock(&THR_LOCK_net); + mysql_mutex_lock(&THR_LOCK_net); ptr=inet_ntoa(in); strmov(buf,ptr); - pthread_mutex_unlock(&THR_LOCK_net); + mysql_mutex_unlock(&THR_LOCK_net); } diff --git a/mysys/my_open.c b/mysys/my_open.c index 79a4da242f9..a50baf2c417 100644 --- a/mysys/my_open.c +++ b/mysys/my_open.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -70,7 +70,7 @@ int my_close(File fd, myf MyFlags) DBUG_ENTER("my_close"); DBUG_PRINT("my",("fd: %d MyFlags: %d",fd, MyFlags)); - pthread_mutex_lock(&THR_LOCK_open); + mysql_mutex_lock(&THR_LOCK_open); #ifndef _WIN32 do { @@ -90,12 +90,12 @@ int my_close(File fd, myf MyFlags) { my_free(my_file_info[fd].name, MYF(0)); #if defined(THREAD) && !defined(HAVE_PREAD) && !defined(_WIN32) - pthread_mutex_destroy(&my_file_info[fd].mutex); + mysql_mutex_destroy(&my_file_info[fd].mutex); #endif my_file_info[fd].type = UNOPEN; } my_file_opened--; - pthread_mutex_unlock(&THR_LOCK_open); + mysql_mutex_unlock(&THR_LOCK_open); DBUG_RETURN(err); } /* my_close */ @@ -134,20 +134,21 @@ File my_register_filename(File fd, const char *FileName, enum file_type } else { - pthread_mutex_lock(&THR_LOCK_open); + mysql_mutex_lock(&THR_LOCK_open); if ((my_file_info[fd].name = (char*) my_strdup(FileName,MyFlags))) { my_file_opened++; my_file_total_opened++; my_file_info[fd].type = type_of_file; #if defined(THREAD) && !defined(HAVE_PREAD) && !defined(_WIN32) - pthread_mutex_init(&my_file_info[fd].mutex,MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_my_file_info_mutex, &my_file_info[fd].mutex, + MY_MUTEX_INIT_FAST); #endif - pthread_mutex_unlock(&THR_LOCK_open); + mysql_mutex_unlock(&THR_LOCK_open); DBUG_PRINT("exit",("fd: %d",fd)); DBUG_RETURN(fd); } - pthread_mutex_unlock(&THR_LOCK_open); + mysql_mutex_unlock(&THR_LOCK_open); my_errno= ENOMEM; } (void) my_close(fd, MyFlags); diff --git a/mysys/my_pread.c b/mysys/my_pread.c index eaabcb1b728..d0a0ddaec66 100644 --- a/mysys/my_pread.c +++ b/mysys/my_pread.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -60,12 +60,12 @@ size_t my_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset, { errno= 0; /* Linux, Windows don't reset this on EOF/success */ #if !defined (HAVE_PREAD) && !defined (_WIN32) - pthread_mutex_lock(&my_file_info[Filedes].mutex); + mysql_mutex_lock(&my_file_info[Filedes].mutex); readbytes= (uint) -1; error= (lseek(Filedes, offset, MY_SEEK_SET) == (my_off_t) -1 || (readbytes= read(Filedes, Buffer, Count)) != Count); save_errno= errno; - pthread_mutex_unlock(&my_file_info[Filedes].mutex); + mysql_mutex_unlock(&my_file_info[Filedes].mutex); if (error) errno= save_errno; #else @@ -150,10 +150,10 @@ size_t my_pwrite(File Filedes, const uchar *Buffer, size_t Count, #if !defined (HAVE_PREAD) && !defined (_WIN32) int error; writtenbytes= (size_t) -1; - pthread_mutex_lock(&my_file_info[Filedes].mutex); + mysql_mutex_lock(&my_file_info[Filedes].mutex); error= (lseek(Filedes, offset, MY_SEEK_SET) != (my_off_t) -1 && (writtenbytes= write(Filedes, Buffer, Count)) == Count); - pthread_mutex_unlock(&my_file_info[Filedes].mutex); + mysql_mutex_unlock(&my_file_info[Filedes].mutex); if (error) break; #elif defined (_WIN32) diff --git a/mysys/my_pthread.c b/mysys/my_pthread.c index fd1798ab203..b6b7e7db857 100644 --- a/mysys/my_pthread.c +++ b/mysys/my_pthread.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright (C) 2000-2003 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -96,7 +96,7 @@ int my_sigwait(const sigset_t *set,int *sig) #if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) -extern pthread_mutex_t LOCK_localtime_r; +extern mysql_mutex_t LOCK_localtime_r; #endif @@ -104,10 +104,10 @@ extern pthread_mutex_t LOCK_localtime_r; struct tm *localtime_r(const time_t *clock, struct tm *res) { struct tm *tmp; - pthread_mutex_lock(&LOCK_localtime_r); + mysql_mutex_lock(&LOCK_localtime_r); tmp=localtime(clock); *res= *tmp; - pthread_mutex_unlock(&LOCK_localtime_r); + mysql_mutex_unlock(&LOCK_localtime_r); return res; } #endif @@ -121,10 +121,10 @@ struct tm *localtime_r(const time_t *clock, struct tm *res) struct tm *gmtime_r(const time_t *clock, struct tm *res) { struct tm *tmp; - pthread_mutex_lock(&LOCK_localtime_r); + mysql_mutex_lock(&LOCK_localtime_r); tmp= gmtime(clock); *res= *tmp; - pthread_mutex_unlock(&LOCK_localtime_r); + mysql_mutex_unlock(&LOCK_localtime_r); return res; } #endif @@ -317,14 +317,14 @@ int sigwait(sigset_t *setp, int *sigp) pthread_t sigwait_thread_id; inited=1; sigemptyset(&pending_set); - pthread_mutex_init(&LOCK_sigwait,MY_MUTEX_INIT_FAST); - pthread_cond_init(&COND_sigwait,NULL); + pthread_mutex_init(&LOCK_sigwait, MY_MUTEX_INIT_FAST); + pthread_cond_init(&COND_sigwait, NULL); pthread_attr_init(&thr_attr); pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS); pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED); pthread_attr_setstacksize(&thr_attr,8196); - pthread_create(&sigwait_thread_id,&thr_attr,sigwait_thread,setp); + pthread_create(&sigwait_thread_id, &thr_attr, sigwait_thread, setp); pthread_attr_destroy(&thr_attr); } @@ -351,7 +351,7 @@ int sigwait(sigset_t *setp, int *sigp) return 0; } } - pthread_cond_wait(&COND_sigwait,&LOCK_sigwait); + pthread_cond_wait(&COND_sigwait, &LOCK_sigwait); } return 0; } diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c index ba59c483012..b3d7d63b197 100644 --- a/mysys/my_thr_init.c +++ b/mysys/my_thr_init.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,17 +24,17 @@ #ifdef THREAD pthread_key(struct st_my_thread_var*, THR_KEY_mysys); -pthread_mutex_t THR_LOCK_malloc,THR_LOCK_open, - THR_LOCK_lock,THR_LOCK_isam,THR_LOCK_myisam,THR_LOCK_heap, - THR_LOCK_net, THR_LOCK_charset, THR_LOCK_threads, THR_LOCK_time; -pthread_cond_t THR_COND_threads; +mysql_mutex_t THR_LOCK_malloc, THR_LOCK_open, + THR_LOCK_lock, THR_LOCK_isam, THR_LOCK_myisam, THR_LOCK_heap, + THR_LOCK_net, THR_LOCK_charset, THR_LOCK_threads, THR_LOCK_time; +mysql_cond_t THR_COND_threads; uint THR_thread_count= 0; uint my_thread_end_wait_time= 5; #if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) -pthread_mutex_t LOCK_localtime_r; +mysql_mutex_t LOCK_localtime_r; #endif #ifndef HAVE_GETHOSTBYNAME_R -pthread_mutex_t LOCK_gethostbyname_r; +mysql_mutex_t LOCK_gethostbyname_r; #endif #ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP pthread_mutexattr_t my_fast_mutexattr; @@ -65,6 +65,84 @@ nptl_pthread_exit_hack_handler(void *arg __attribute((unused))) static uint get_thread_lib(void); +/** True if @c my_thread_basic_global_init() has been called. */ +static my_bool my_thread_basic_global_init_done= 0; + +/** + Perform a minimal initialisation of mysys, when compiled with threads. + The initialisation performed is sufficient to: + - allocate memory + - perform file operations + - use charsets + - use my_errno + @sa my_basic_init + @sa my_thread_basic_global_reinit +*/ +my_bool my_thread_basic_global_init(void) +{ + int pth_ret; + + if (my_thread_basic_global_init_done) + return 0; + my_thread_basic_global_init_done= 1; + + mysql_mutex_init(key_THR_LOCK_malloc, &THR_LOCK_malloc, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_THR_LOCK_open, &THR_LOCK_open, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_THR_LOCK_charset, &THR_LOCK_charset, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_THR_LOCK_threads, &THR_LOCK_threads, MY_MUTEX_INIT_FAST); + + if ((pth_ret= pthread_key_create(&THR_KEY_mysys, NULL)) != 0) + { + fprintf(stderr, "Can't initialize threads: error %d\n", pth_ret); + return 1; + } + + if (my_thread_init()) + return 1; + + return 0; +} + +/** + Re-initialize components initialized early with @c my_thread_basic_global_init. + Some mutexes were initialized before the instrumentation. + Destroy + create them again, now that the instrumentation + is in place. + This is safe, since this function() is called before creating new threads, + so the mutexes are not in use. +*/ +void my_thread_basic_global_reinit(void) +{ + struct st_my_thread_var *tmp; + + DBUG_ASSERT(my_thread_basic_global_init_done); + +#ifdef HAVE_PSI_INTERFACE + my_init_mysys_psi_keys(); +#endif + + mysql_mutex_destroy(&THR_LOCK_malloc); + mysql_mutex_init(key_THR_LOCK_malloc, &THR_LOCK_malloc, MY_MUTEX_INIT_FAST); + + mysql_mutex_destroy(&THR_LOCK_open); + mysql_mutex_init(key_THR_LOCK_open, &THR_LOCK_open, MY_MUTEX_INIT_FAST); + + mysql_mutex_destroy(&THR_LOCK_charset); + mysql_mutex_init(key_THR_LOCK_charset, &THR_LOCK_charset, MY_MUTEX_INIT_FAST); + + mysql_mutex_destroy(&THR_LOCK_threads); + mysql_mutex_init(key_THR_LOCK_threads, &THR_LOCK_threads, MY_MUTEX_INIT_FAST); + + tmp= my_pthread_getspecific(struct st_my_thread_var*, THR_KEY_mysys); + DBUG_ASSERT(tmp); + + mysql_mutex_destroy(&tmp->mutex); + mysql_mutex_init(key_my_thread_var_mutex, &tmp->mutex, MY_MUTEX_INIT_FAST); + + mysql_cond_destroy(&tmp->suspend); + mysql_cond_init(key_my_thread_var_suspend, &tmp->suspend, NULL); +} + /* initialize thread environment @@ -78,14 +156,10 @@ static uint get_thread_lib(void); my_bool my_thread_global_init(void) { - int pth_ret; - thd_lib_detected= get_thread_lib(); - - if ((pth_ret= pthread_key_create(&THR_KEY_mysys, NULL)) != 0) - { - fprintf(stderr,"Can't initialize threads: error %d\n", pth_ret); + if (my_thread_basic_global_init()) return 1; - } + + thd_lib_detected= get_thread_lib(); #ifdef TARGET_OS_LINUX /* @@ -137,23 +211,20 @@ my_bool my_thread_global_init(void) PTHREAD_MUTEX_ERRORCHECK); #endif - pthread_mutex_init(&THR_LOCK_malloc,MY_MUTEX_INIT_FAST); - pthread_mutex_init(&THR_LOCK_open,MY_MUTEX_INIT_FAST); - pthread_mutex_init(&THR_LOCK_lock,MY_MUTEX_INIT_FAST); - pthread_mutex_init(&THR_LOCK_isam,MY_MUTEX_INIT_SLOW); - pthread_mutex_init(&THR_LOCK_myisam,MY_MUTEX_INIT_SLOW); - pthread_mutex_init(&THR_LOCK_heap,MY_MUTEX_INIT_FAST); - pthread_mutex_init(&THR_LOCK_net,MY_MUTEX_INIT_FAST); - pthread_mutex_init(&THR_LOCK_charset,MY_MUTEX_INIT_FAST); - pthread_mutex_init(&THR_LOCK_threads,MY_MUTEX_INIT_FAST); - pthread_mutex_init(&THR_LOCK_time,MY_MUTEX_INIT_FAST); - pthread_cond_init(&THR_COND_threads, NULL); + mysql_mutex_init(key_THR_LOCK_lock, &THR_LOCK_lock, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_THR_LOCK_isam, &THR_LOCK_isam, MY_MUTEX_INIT_SLOW); + mysql_mutex_init(key_THR_LOCK_myisam, &THR_LOCK_myisam, MY_MUTEX_INIT_SLOW); + mysql_mutex_init(key_THR_LOCK_heap, &THR_LOCK_heap, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_THR_LOCK_net, &THR_LOCK_net, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_THR_LOCK_time, &THR_LOCK_time, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_THR_COND_threads, &THR_COND_threads, NULL); #if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) - pthread_mutex_init(&LOCK_localtime_r,MY_MUTEX_INIT_SLOW); + mysql_mutex_init(key_LOCK_localtime_r, &LOCK_localtime_r, MY_MUTEX_INIT_SLOW); #endif #ifndef HAVE_GETHOSTBYNAME_R - pthread_mutex_init(&LOCK_gethostbyname_r,MY_MUTEX_INIT_SLOW); + mysql_mutex_init(key_LOCK_gethostbyname_r, + &LOCK_gethostbyname_r, MY_MUTEX_INIT_SLOW); #endif #ifdef _MSC_VER @@ -175,11 +246,11 @@ void my_thread_global_end(void) my_bool all_threads_killed= 1; set_timespec(abstime, my_thread_end_wait_time); - pthread_mutex_lock(&THR_LOCK_threads); + mysql_mutex_lock(&THR_LOCK_threads); while (THR_thread_count > 0) { - int error= pthread_cond_timedwait(&THR_COND_threads, &THR_LOCK_threads, - &abstime); + int error= mysql_cond_timedwait(&THR_COND_threads, &THR_LOCK_threads, + &abstime); if (error == ETIMEDOUT || error == ETIME) { #ifdef HAVE_PTHREAD_KILL @@ -197,7 +268,7 @@ void my_thread_global_end(void) break; } } - pthread_mutex_unlock(&THR_LOCK_threads); + mysql_mutex_unlock(&THR_LOCK_threads); pthread_key_delete(THR_KEY_mysys); #ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP @@ -206,25 +277,25 @@ void my_thread_global_end(void) #ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP pthread_mutexattr_destroy(&my_errorcheck_mutexattr); #endif - pthread_mutex_destroy(&THR_LOCK_malloc); - pthread_mutex_destroy(&THR_LOCK_open); - pthread_mutex_destroy(&THR_LOCK_lock); - pthread_mutex_destroy(&THR_LOCK_isam); - pthread_mutex_destroy(&THR_LOCK_myisam); - pthread_mutex_destroy(&THR_LOCK_heap); - pthread_mutex_destroy(&THR_LOCK_net); - pthread_mutex_destroy(&THR_LOCK_time); - pthread_mutex_destroy(&THR_LOCK_charset); + mysql_mutex_destroy(&THR_LOCK_malloc); + mysql_mutex_destroy(&THR_LOCK_open); + mysql_mutex_destroy(&THR_LOCK_lock); + mysql_mutex_destroy(&THR_LOCK_isam); + mysql_mutex_destroy(&THR_LOCK_myisam); + mysql_mutex_destroy(&THR_LOCK_heap); + mysql_mutex_destroy(&THR_LOCK_net); + mysql_mutex_destroy(&THR_LOCK_time); + mysql_mutex_destroy(&THR_LOCK_charset); if (all_threads_killed) { - pthread_mutex_destroy(&THR_LOCK_threads); - pthread_cond_destroy(&THR_COND_threads); + mysql_mutex_destroy(&THR_LOCK_threads); + mysql_cond_destroy(&THR_COND_threads); } #if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) - pthread_mutex_destroy(&LOCK_localtime_r); + mysql_mutex_destroy(&LOCK_localtime_r); #endif #ifndef HAVE_GETHOSTBYNAME_R - pthread_mutex_destroy(&LOCK_gethostbyname_r); + mysql_mutex_destroy(&LOCK_gethostbyname_r); #endif } @@ -280,17 +351,17 @@ my_bool my_thread_init(void) } pthread_setspecific(THR_KEY_mysys,tmp); tmp->pthread_self= pthread_self(); - pthread_mutex_init(&tmp->mutex,MY_MUTEX_INIT_FAST); - pthread_cond_init(&tmp->suspend, NULL); - tmp->init= 1; + mysql_mutex_init(key_my_thread_var_mutex, &tmp->mutex, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_my_thread_var_suspend, &tmp->suspend, NULL); tmp->stack_ends_here= (char*)&tmp + STACK_DIRECTION * (long)my_thread_stack_size; - pthread_mutex_lock(&THR_LOCK_threads); + mysql_mutex_lock(&THR_LOCK_threads); tmp->id= ++thread_id; ++THR_thread_count; - pthread_mutex_unlock(&THR_LOCK_threads); + mysql_mutex_unlock(&THR_LOCK_threads); + tmp->init= 1; #ifndef DBUG_OFF /* Generate unique name for thread */ (void) my_thread_name(); @@ -322,6 +393,17 @@ void my_thread_end(void) fprintf(stderr,"my_thread_end(): tmp: 0x%lx pthread_self: 0x%lx thread_id: %ld\n", (long) tmp, (long) pthread_self(), tmp ? (long) tmp->id : 0L); #endif + +#ifdef HAVE_PSI_INTERFACE + /* + Remove the instrumentation for this thread. + This must be done before trashing st_my_thread_var, + because the LF_HASH depends on it. + */ + if (PSI_server) + PSI_server->delete_current_thread(); +#endif + if (tmp && tmp->init) { #if !defined(DBUG_OFF) @@ -335,9 +417,9 @@ void my_thread_end(void) #endif #if !defined(__bsdi__) && !defined(__OpenBSD__) /* bsdi and openbsd 3.5 dumps core here */ - pthread_cond_destroy(&tmp->suspend); + mysql_cond_destroy(&tmp->suspend); #endif - pthread_mutex_destroy(&tmp->mutex); + mysql_mutex_destroy(&tmp->mutex); free(tmp); /* @@ -346,11 +428,11 @@ void my_thread_end(void) my_thread_end and thus freed all memory they have allocated in my_thread_init() and DBUG_xxxx */ - pthread_mutex_lock(&THR_LOCK_threads); + mysql_mutex_lock(&THR_LOCK_threads); DBUG_ASSERT(THR_thread_count != 0); if (--THR_thread_count == 0) - pthread_cond_signal(&THR_COND_threads); - pthread_mutex_unlock(&THR_LOCK_threads); + mysql_cond_signal(&THR_COND_threads); + mysql_mutex_unlock(&THR_LOCK_threads); } pthread_setspecific(THR_KEY_mysys,0); } diff --git a/mysys/my_winfile.c b/mysys/my_winfile.c index 6a2cda5ba29..6c0b191ca2c 100644 --- a/mysys/my_winfile.c +++ b/mysys/my_winfile.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2008 MySQL AB +/* Copyright (C) 2008 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -57,7 +57,7 @@ File my_open_osfhandle(HANDLE handle, int oflag) uint i; DBUG_ENTER("my_open_osfhandle"); - pthread_mutex_lock(&THR_LOCK_open); + mysql_mutex_lock(&THR_LOCK_open); for(i= MY_FILE_MIN; i < my_file_limit;i++) { if(my_file_info[i].fhandle == 0) @@ -70,7 +70,7 @@ File my_open_osfhandle(HANDLE handle, int oflag) break; } } - pthread_mutex_unlock(&THR_LOCK_open); + mysql_mutex_unlock(&THR_LOCK_open); if(offset == -1) errno= EMFILE; /* to many file handles open */ DBUG_RETURN(offset); diff --git a/mysys/mysys_priv.h b/mysys/mysys_priv.h index 5c5bd6c2908..3a663dfefbf 100644 --- a/mysys/mysys_priv.h +++ b/mysys/mysys_priv.h @@ -59,9 +59,9 @@ extern PSI_thread_key key_thread_alarm; #endif /* HAVE_PSI_INTERFACE */ -extern pthread_mutex_t THR_LOCK_malloc, THR_LOCK_open, THR_LOCK_keycache; -extern pthread_mutex_t THR_LOCK_lock, THR_LOCK_isam, THR_LOCK_net; -extern pthread_mutex_t THR_LOCK_charset, THR_LOCK_time; +extern mysql_mutex_t THR_LOCK_malloc, THR_LOCK_open, THR_LOCK_keycache; +extern mysql_mutex_t THR_LOCK_lock, THR_LOCK_isam, THR_LOCK_net; +extern mysql_mutex_t THR_LOCK_charset, THR_LOCK_time; #else /* THREAD */ #include #endif /* THREAD */ diff --git a/mysys/safemalloc.c b/mysys/safemalloc.c index c484f1d4c54..675fa62380a 100644 --- a/mysys/safemalloc.c +++ b/mysys/safemalloc.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright (C) 2000-2003 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -178,7 +178,7 @@ void *_mymalloc(size_t size, const char *filename, uint lineno, myf MyFlags) irem->prev= NULL; /* Add this remember structure to the linked list */ - pthread_mutex_lock(&THR_LOCK_malloc); + mysql_mutex_lock(&THR_LOCK_malloc); if ((irem->next= sf_malloc_root)) sf_malloc_root->prev= irem; sf_malloc_root= irem; @@ -188,7 +188,7 @@ void *_mymalloc(size_t size, const char *filename, uint lineno, myf MyFlags) if (sf_malloc_cur_memory > sf_malloc_max_memory) sf_malloc_max_memory= sf_malloc_cur_memory; sf_malloc_count++; - pthread_mutex_unlock(&THR_LOCK_malloc); + mysql_mutex_unlock(&THR_LOCK_malloc); /* Set the memory to the aribtrary wierd value */ if ((MyFlags & MY_ZEROFILL) || !sf_malloc_quick) @@ -291,7 +291,7 @@ void _myfree(void *ptr, const char *filename, uint lineno, myf myflags) } /* Remove this structure from the linked list */ - pthread_mutex_lock(&THR_LOCK_malloc); + mysql_mutex_lock(&THR_LOCK_malloc); if (irem->prev) irem->prev->next= irem->next; else @@ -302,7 +302,7 @@ void _myfree(void *ptr, const char *filename, uint lineno, myf myflags) /* Handle the statistics */ sf_malloc_cur_memory-= irem->datasize; sf_malloc_count--; - pthread_mutex_unlock(&THR_LOCK_malloc); + mysql_mutex_unlock(&THR_LOCK_malloc); #ifndef HAVE_purify /* Mark this data as free'ed */ @@ -365,7 +365,7 @@ void TERMINATE(FILE *file, uint flag) { struct st_irem *irem; DBUG_ENTER("TERMINATE"); - pthread_mutex_lock(&THR_LOCK_malloc); + mysql_mutex_lock(&THR_LOCK_malloc); /* Report the difference between number of calls to @@ -428,7 +428,7 @@ void TERMINATE(FILE *file, uint flag) DBUG_PRINT("safe",("Maximum memory usage: %lu bytes (%luk)", (ulong) sf_malloc_max_memory, (ulong) (sf_malloc_max_memory + 1023L) /1024L)); - pthread_mutex_unlock(&THR_LOCK_malloc); + mysql_mutex_unlock(&THR_LOCK_malloc); DBUG_VOID_RETURN; } @@ -505,7 +505,7 @@ int _sanity(const char *filename, uint lineno) reg2 int flag=0; uint count=0; - pthread_mutex_lock(&THR_LOCK_malloc); + mysql_mutex_lock(&THR_LOCK_malloc); #ifndef PEDANTIC_SAFEMALLOC if (sf_malloc_tampered && (int) sf_malloc_count < 0) sf_malloc_count=0; @@ -513,7 +513,7 @@ int _sanity(const char *filename, uint lineno) count=sf_malloc_count; for (irem= sf_malloc_root; irem != NULL && count-- ; irem= irem->next) flag+= _checkchunk (irem, filename, lineno); - pthread_mutex_unlock(&THR_LOCK_malloc); + mysql_mutex_unlock(&THR_LOCK_malloc); if (count || irem) { const char *format="Error: Safemalloc link list destroyed, discovered at '%s:%d'"; diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c index 9ab862fa755..8ee89cfb55d 100644 --- a/mysys/thr_alarm.c +++ b/mysys/thr_alarm.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -15,6 +15,7 @@ /* To avoid problems with alarms in debug code, we disable DBUG here */ #define FORCE_DBUG_OFF +#include "mysys_priv.h" #include #if defined(THREAD) && !defined(DONT_USE_THR_ALARM) @@ -43,8 +44,8 @@ static sig_handler process_alarm_part2(int sig); #if !defined(__WIN__) -static pthread_mutex_t LOCK_alarm; -static pthread_cond_t COND_alarm; +static mysql_mutex_t LOCK_alarm; +static mysql_cond_t COND_alarm; static sigset_t full_signal_set; static QUEUE alarm_queue; static uint max_used_alarms=0; @@ -52,7 +53,7 @@ pthread_t alarm_thread; #ifdef USE_ALARM_THREAD static void *alarm_handler(void *arg); -#define reschedule_alarms() pthread_cond_signal(&COND_alarm) +#define reschedule_alarms() mysql_cond_signal(&COND_alarm) #else #define reschedule_alarms() pthread_kill(alarm_thread,THR_SERVER_ALARM) #endif @@ -75,8 +76,8 @@ void init_thr_alarm(uint max_alarms) init_queue(&alarm_queue,max_alarms+1,offsetof(ALARM,expire_time),0, compare_ulong,NullS); sigfillset(&full_signal_set); /* Neaded to block signals */ - pthread_mutex_init(&LOCK_alarm,MY_MUTEX_INIT_FAST); - pthread_cond_init(&COND_alarm,NULL); + mysql_mutex_init(key_LOCK_alarm, &LOCK_alarm, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_COND_alarm, &COND_alarm, NULL); if (thd_lib_detected == THD_LIB_LT) thr_client_alarm= SIGALRM; else @@ -97,7 +98,8 @@ void init_thr_alarm(uint max_alarms) pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS); pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED); pthread_attr_setstacksize(&thr_attr,8196); - pthread_create(&alarm_thread,&thr_attr,alarm_handler,NULL); + mysql_thread_create(key_thread_alarm, + &alarm_thread, &thr_attr, alarm_handler, NULL); pthread_attr_destroy(&thr_attr); } #elif defined(USE_ONE_SIGNAL_HAND) @@ -117,14 +119,14 @@ void init_thr_alarm(uint max_alarms) void resize_thr_alarm(uint max_alarms) { - pthread_mutex_lock(&LOCK_alarm); + mysql_mutex_lock(&LOCK_alarm); /* It's ok not to shrink the queue as there may be more pending alarms than than max_alarms */ if (alarm_queue.elements < max_alarms) resize_queue(&alarm_queue,max_alarms+1); - pthread_mutex_unlock(&LOCK_alarm); + mysql_mutex_unlock(&LOCK_alarm); } @@ -162,12 +164,12 @@ my_bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data) #ifndef USE_ONE_SIGNAL_HAND pthread_sigmask(SIG_BLOCK,&full_signal_set,&old_mask); #endif - pthread_mutex_lock(&LOCK_alarm); /* Lock from threads & alarms */ + mysql_mutex_lock(&LOCK_alarm); /* Lock from threads & alarms */ if (alarm_aborted > 0) { /* No signal thread */ DBUG_PRINT("info", ("alarm aborted")); *alrm= 0; /* No alarm */ - pthread_mutex_unlock(&LOCK_alarm); + mysql_mutex_unlock(&LOCK_alarm); #ifndef USE_ONE_SIGNAL_HAND pthread_sigmask(SIG_SETMASK,&old_mask,NULL); #endif @@ -183,7 +185,7 @@ my_bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data) DBUG_PRINT("info", ("alarm queue full")); fprintf(stderr,"Warning: thr_alarm queue is full\n"); *alrm= 0; /* No alarm */ - pthread_mutex_unlock(&LOCK_alarm); + mysql_mutex_unlock(&LOCK_alarm); #ifndef USE_ONE_SIGNAL_HAND pthread_sigmask(SIG_SETMASK,&old_mask,NULL); #endif @@ -198,7 +200,7 @@ my_bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data) { DBUG_PRINT("info", ("failed my_malloc()")); *alrm= 0; /* No alarm */ - pthread_mutex_unlock(&LOCK_alarm); + mysql_mutex_unlock(&LOCK_alarm); #ifndef USE_ONE_SIGNAL_HAND pthread_sigmask(SIG_SETMASK,&old_mask,NULL); #endif @@ -226,7 +228,7 @@ my_bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data) else reschedule_alarms(); /* Reschedule alarms */ } - pthread_mutex_unlock(&LOCK_alarm); + mysql_mutex_unlock(&LOCK_alarm); #ifndef USE_ONE_SIGNAL_HAND pthread_sigmask(SIG_SETMASK,&old_mask,NULL); #endif @@ -251,7 +253,7 @@ void thr_end_alarm(thr_alarm_t *alarmed) #ifndef USE_ONE_SIGNAL_HAND pthread_sigmask(SIG_BLOCK,&full_signal_set,&old_mask); #endif - pthread_mutex_lock(&LOCK_alarm); + mysql_mutex_lock(&LOCK_alarm); alarm_data= (ALARM*) ((uchar*) *alarmed - offsetof(ALARM,alarmed)); for (i=0 ; i < alarm_queue.elements ; i++) @@ -276,7 +278,7 @@ void thr_end_alarm(thr_alarm_t *alarmed) DBUG_PRINT("warning",("Didn't find alarm 0x%lx in queue\n", (long) *alarmed)); } - pthread_mutex_unlock(&LOCK_alarm); + mysql_mutex_unlock(&LOCK_alarm); #ifndef USE_ONE_SIGNAL_HAND pthread_sigmask(SIG_SETMASK,&old_mask,NULL); #endif @@ -319,14 +321,14 @@ sig_handler process_alarm(int sig __attribute__((unused))) #ifndef USE_ALARM_THREAD pthread_sigmask(SIG_SETMASK,&full_signal_set,&old_mask); - pthread_mutex_lock(&LOCK_alarm); + mysql_mutex_lock(&LOCK_alarm); #endif process_alarm_part2(sig); #ifndef USE_ALARM_THREAD #if defined(DONT_REMEMBER_SIGNAL) && !defined(USE_ONE_SIGNAL_HAND) my_sigset(THR_SERVER_ALARM,process_alarm); #endif - pthread_mutex_unlock(&LOCK_alarm); + mysql_mutex_unlock(&LOCK_alarm); pthread_sigmask(SIG_SETMASK,&old_mask,NULL); #endif return; @@ -434,7 +436,7 @@ void end_thr_alarm(my_bool free_structures) DBUG_ENTER("end_thr_alarm"); if (alarm_aborted != 1) /* If memory not freed */ { - pthread_mutex_lock(&LOCK_alarm); + mysql_mutex_lock(&LOCK_alarm); DBUG_PRINT("info",("Resheduling %d waiting alarms",alarm_queue.elements)); alarm_aborted= -1; /* mark aborted */ if (alarm_queue.elements || (alarm_thread_running && free_structures)) @@ -454,21 +456,21 @@ void end_thr_alarm(my_bool free_structures) set_timespec(abstime, 10); /* Wait up to 10 seconds */ while (alarm_thread_running) { - int error= pthread_cond_timedwait(&COND_alarm, &LOCK_alarm, &abstime); + int error= mysql_cond_timedwait(&COND_alarm, &LOCK_alarm, &abstime); if (error == ETIME || error == ETIMEDOUT) break; /* Don't wait forever */ } delete_queue(&alarm_queue); alarm_aborted= 1; - pthread_mutex_unlock(&LOCK_alarm); + mysql_mutex_unlock(&LOCK_alarm); if (!alarm_thread_running) /* Safety */ { - pthread_mutex_destroy(&LOCK_alarm); - pthread_cond_destroy(&COND_alarm); + mysql_mutex_destroy(&LOCK_alarm); + mysql_cond_destroy(&COND_alarm); } } else - pthread_mutex_unlock(&LOCK_alarm); + mysql_mutex_unlock(&LOCK_alarm); } DBUG_VOID_RETURN; } @@ -483,7 +485,7 @@ void thr_alarm_kill(my_thread_id thread_id) uint i; if (alarm_aborted) return; - pthread_mutex_lock(&LOCK_alarm); + mysql_mutex_lock(&LOCK_alarm); for (i=0 ; i < alarm_queue.elements ; i++) { if (((ALARM*) queue_element(&alarm_queue,i))->thread_id == thread_id) @@ -495,13 +497,13 @@ void thr_alarm_kill(my_thread_id thread_id) break; } } - pthread_mutex_unlock(&LOCK_alarm); + mysql_mutex_unlock(&LOCK_alarm); } void thr_alarm_info(ALARM_INFO *info) { - pthread_mutex_lock(&LOCK_alarm); + mysql_mutex_lock(&LOCK_alarm); info->next_alarm_time= 0; info->max_used_alarms= max_used_alarms; if ((info->active_alarms= alarm_queue.elements)) @@ -512,7 +514,7 @@ void thr_alarm_info(ALARM_INFO *info) time_diff= (long) (alarm_data->expire_time - now); info->next_alarm_time= (ulong) (time_diff < 0 ? 0 : time_diff); } - pthread_mutex_unlock(&LOCK_alarm); + mysql_mutex_unlock(&LOCK_alarm); } /* @@ -549,7 +551,7 @@ static void *alarm_handler(void *arg __attribute__((unused))) #endif my_thread_init(); alarm_thread_running= 1; - pthread_mutex_lock(&LOCK_alarm); + mysql_mutex_lock(&LOCK_alarm); for (;;) { if (alarm_queue.elements) @@ -564,7 +566,7 @@ static void *alarm_handler(void *arg __attribute__((unused))) abstime.tv_sec=sleep_time; abstime.tv_nsec=0; next_alarm_expire_time= sleep_time; - if ((error=pthread_cond_timedwait(&COND_alarm,&LOCK_alarm,&abstime)) && + if ((error= mysql_cond_timedwait(&COND_alarm, &LOCK_alarm, &abstime)) && error != ETIME && error != ETIMEDOUT) { #ifdef MAIN @@ -579,7 +581,7 @@ static void *alarm_handler(void *arg __attribute__((unused))) else { next_alarm_expire_time= ~ (time_t) 0; - if ((error=pthread_cond_wait(&COND_alarm,&LOCK_alarm))) + if ((error= mysql_cond_wait(&COND_alarm, &LOCK_alarm))) { #ifdef MAIN printf("Got error: %d from ptread_cond_wait (errno: %d)\n", @@ -591,8 +593,8 @@ static void *alarm_handler(void *arg __attribute__((unused))) } bzero((char*) &alarm_thread,sizeof(alarm_thread)); /* For easy debugging */ alarm_thread_running= 0; - pthread_cond_signal(&COND_alarm); - pthread_mutex_unlock(&LOCK_alarm); + mysql_cond_signal(&COND_alarm); + mysql_mutex_unlock(&LOCK_alarm); pthread_exit(0); return 0; /* Impossible */ } @@ -694,8 +696,8 @@ void resize_thr_alarm(uint max_alarms) #ifdef MAIN #if defined(THREAD) && !defined(DONT_USE_THR_ALARM) -static pthread_cond_t COND_thread_count; -static pthread_mutex_t LOCK_thread_count; +static mysql_cond_t COND_thread_count; +static mysql_mutex_t LOCK_thread_count; static uint thread_count; #ifdef HPUX10 @@ -782,10 +784,10 @@ static void *test_thread(void *arg) thr_end_alarm(&got_alarm); fflush(stdout); } - pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); thread_count--; - pthread_cond_signal(&COND_thread_count); /* Tell main we are ready */ - pthread_mutex_unlock(&LOCK_thread_count); + mysql_cond_signal(&COND_thread_count); /* Tell main we are ready */ + mysql_mutex_unlock(&LOCK_thread_count); free((uchar*) arg); return 0; } @@ -812,9 +814,9 @@ static void *signal_hand(void *arg __attribute__((unused))) my_thread_init(); pthread_detach_this_thread(); init_thr_alarm(10); /* Setup alarm handler */ - pthread_mutex_lock(&LOCK_thread_count); /* Required by bsdi */ - pthread_cond_signal(&COND_thread_count); /* Tell main we are ready */ - pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); /* Required by bsdi */ + mysql_cond_signal(&COND_thread_count); /* Tell main we are ready */ + mysql_mutex_unlock(&LOCK_thread_count); sigemptyset(&set); /* Catch all signals */ sigaddset(&set,SIGINT); @@ -885,8 +887,8 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) { DBUG_PUSH(argv[1]+2); } - pthread_mutex_init(&LOCK_thread_count,MY_MUTEX_INIT_FAST); - pthread_cond_init(&COND_thread_count,NULL); + mysql_mutex_init(0, &LOCK_thread_count, MY_MUTEX_INIT_FAST); + mysql_cond_init(0, &COND_thread_count, NULL); /* Start a alarm handling thread */ sigemptyset(&set); @@ -913,10 +915,11 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) pthread_attr_setstacksize(&thr_attr,65536L); /* Start signal thread and wait for it to start */ - pthread_mutex_lock(&LOCK_thread_count); - pthread_create(&tid,&thr_attr,signal_hand,NULL); - pthread_cond_wait(&COND_thread_count,&LOCK_thread_count); - pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); + mysql_thread_create(0, + &tid, &thr_attr, signal_hand, NULL); + mysql_cond_wait(&COND_thread_count, &LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); DBUG_PRINT("info",("signal thread created")); thr_setconcurrency(3); @@ -926,32 +929,34 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) { param=(int*) malloc(sizeof(int)); *param= i; - pthread_mutex_lock(&LOCK_thread_count); - if ((error=pthread_create(&tid,&thr_attr,test_thread,(void*) param))) + mysql_mutex_lock(&LOCK_thread_count); + if ((error= mysql_thread_create(0, + &tid, &thr_attr, test_thread, + (void*) param))) { printf("Can't create thread %d, error: %d\n",i,error); exit(1); } thread_count++; - pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); } pthread_attr_destroy(&thr_attr); - pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); thr_alarm_info(&alarm_info); printf("Main_thread: Alarms: %u max_alarms: %u next_alarm_time: %lu\n", alarm_info.active_alarms, alarm_info.max_used_alarms, alarm_info.next_alarm_time); while (thread_count) { - pthread_cond_wait(&COND_thread_count,&LOCK_thread_count); + mysql_cond_wait(&COND_thread_count, &LOCK_thread_count); if (thread_count == 1) { printf("Calling end_thr_alarm. This should cancel the last thread\n"); end_thr_alarm(0); } } - pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); thr_alarm_info(&alarm_info); end_thr_alarm(1); printf("Main_thread: Alarms: %u max_alarms: %u next_alarm_time: %lu\n", diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c index 1d724de641c..5a71e58cdbf 100644 --- a/mysys/thr_lock.c +++ b/mysys/thr_lock.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -94,7 +94,7 @@ enum thr_lock_type thr_upgraded_concurrent_insert_lock = TL_WRITE; LIST *thr_lock_thread_list; /* List of threads in use */ ulong max_write_lock_count= ~(ulong) 0L; -static inline pthread_cond_t *get_cond(void) +static inline mysql_cond_t *get_cond(void) { return &my_thread_var->suspend; } @@ -316,16 +316,16 @@ void thr_lock_init(THR_LOCK *lock) { DBUG_ENTER("thr_lock_init"); bzero((char*) lock,sizeof(*lock)); - pthread_mutex_init(&lock->mutex,MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_THR_LOCK_mutex, &lock->mutex, MY_MUTEX_INIT_FAST); lock->read.last= &lock->read.data; lock->read_wait.last= &lock->read_wait.data; lock->write_wait.last= &lock->write_wait.data; lock->write.last= &lock->write.data; - pthread_mutex_lock(&THR_LOCK_lock); /* Add to locks in use */ + mysql_mutex_lock(&THR_LOCK_lock); /* Add to locks in use */ lock->list.data=(void*) lock; thr_lock_thread_list=list_add(thr_lock_thread_list,&lock->list); - pthread_mutex_unlock(&THR_LOCK_lock); + mysql_mutex_unlock(&THR_LOCK_lock); DBUG_VOID_RETURN; } @@ -333,10 +333,10 @@ void thr_lock_init(THR_LOCK *lock) void thr_lock_delete(THR_LOCK *lock) { DBUG_ENTER("thr_lock_delete"); - pthread_mutex_lock(&THR_LOCK_lock); + mysql_mutex_lock(&THR_LOCK_lock); thr_lock_thread_list=list_delete(thr_lock_thread_list,&lock->list); - pthread_mutex_unlock(&THR_LOCK_lock); - pthread_mutex_destroy(&lock->mutex); + mysql_mutex_unlock(&THR_LOCK_lock); + mysql_mutex_destroy(&lock->mutex); DBUG_VOID_RETURN; } @@ -392,7 +392,7 @@ wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data, my_bool in_wait_list) { struct st_my_thread_var *thread_var= my_thread_var; - pthread_cond_t *cond= &thread_var->suspend; + mysql_cond_t *cond= &thread_var->suspend; struct timespec wait_timeout; enum enum_thr_lock_result result= THR_LOCK_ABORTED; my_bool can_deadlock= test(data->owner->info->n_cursors); @@ -439,9 +439,9 @@ wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data, while (!thread_var->abort || in_wait_list) { int rc= (can_deadlock ? - pthread_cond_timedwait(cond, &data->lock->mutex, - &wait_timeout) : - pthread_cond_wait(cond, &data->lock->mutex)); + mysql_cond_timedwait(cond, &data->lock->mutex, + &wait_timeout) : + mysql_cond_wait(cond, &data->lock->mutex)); /* We must break the wait if one of the following occurs: - the connection has been aborted (!thread_var->abort), but @@ -497,13 +497,13 @@ wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data, (*data->lock->get_status)(data->status_param, 0); check_locks(data->lock,"got wait_for_lock",0); } - pthread_mutex_unlock(&data->lock->mutex); + mysql_mutex_unlock(&data->lock->mutex); /* The following must be done after unlock of lock->mutex */ - pthread_mutex_lock(&thread_var->mutex); + mysql_mutex_lock(&thread_var->mutex); thread_var->current_mutex= 0; thread_var->current_cond= 0; - pthread_mutex_unlock(&thread_var->mutex); + mysql_mutex_unlock(&thread_var->mutex); DBUG_RETURN(result); } @@ -522,7 +522,7 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner, data->cond=0; /* safety */ data->type=lock_type; data->owner= owner; /* Must be reset ! */ - pthread_mutex_lock(&lock->mutex); + mysql_mutex_lock(&lock->mutex); DBUG_PRINT("lock",("data: 0x%lx thread: 0x%lx lock: 0x%lx type: %d", (long) data, data->owner->info->thread_id, (long) lock, (int) lock_type)); @@ -747,7 +747,7 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner, /* Can't get lock yet; Wait for it */ DBUG_RETURN(wait_for_lock(wait_queue, data, 0)); end: - pthread_mutex_unlock(&lock->mutex); + mysql_mutex_unlock(&lock->mutex); DBUG_RETURN(result); } @@ -769,7 +769,7 @@ static inline void free_all_read_locks(THR_LOCK *lock, do { - pthread_cond_t *cond=data->cond; + mysql_cond_t *cond= data->cond; if ((int) data->type == (int) TL_READ_NO_INSERT) { if (using_concurrent_insert) @@ -794,7 +794,7 @@ static inline void free_all_read_locks(THR_LOCK *lock, data->owner->info->thread_id)); /* purecov: end */ data->cond=0; /* Mark thread free */ - pthread_cond_signal(cond); + mysql_cond_signal(cond); } while ((data=data->next)); *lock->read_wait.last=0; if (!lock->read_wait.data) @@ -811,7 +811,7 @@ void thr_unlock(THR_LOCK_DATA *data) DBUG_ENTER("thr_unlock"); DBUG_PRINT("lock",("data: 0x%lx thread: 0x%lx lock: 0x%lx", (long) data, data->owner->info->thread_id, (long) lock)); - pthread_mutex_lock(&lock->mutex); + mysql_mutex_lock(&lock->mutex); check_locks(lock,"start of release lock",0); if (((*data->prev)=data->next)) /* remove from lock-list */ @@ -843,7 +843,7 @@ void thr_unlock(THR_LOCK_DATA *data) data->type=TL_UNLOCK; /* Mark unlocked */ check_locks(lock,"after releasing lock",1); wake_up_waiters(lock); - pthread_mutex_unlock(&lock->mutex); + mysql_mutex_unlock(&lock->mutex); DBUG_VOID_RETURN; } @@ -902,9 +902,9 @@ static void wake_up_waiters(THR_LOCK *lock) data->type, data->owner->info->thread_id)); /* purecov: end */ { - pthread_cond_t *cond=data->cond; + mysql_cond_t *cond= data->cond; data->cond=0; /* Mark thread free */ - pthread_cond_signal(cond); /* Start waiting thread */ + mysql_cond_signal(cond); /* Start waiting thread */ } if (data->type != TL_WRITE_ALLOW_WRITE || !lock->write_wait.data || @@ -945,7 +945,7 @@ static void wake_up_waiters(THR_LOCK *lock) goto end; } do { - pthread_cond_t *cond=data->cond; + mysql_cond_t *cond= data->cond; if (((*data->prev)=data->next)) /* remove from wait-list */ data->next->prev= data->prev; else @@ -955,7 +955,7 @@ static void wake_up_waiters(THR_LOCK *lock) lock->write.last= &data->next; data->next=0; /* Only one write lock */ data->cond=0; /* Mark thread free */ - pthread_cond_signal(cond); /* Start waiting thread */ + mysql_cond_signal(cond); /* Start waiting thread */ } while (lock_type == TL_WRITE_ALLOW_WRITE && (data=lock->write_wait.data) && data->type == TL_WRITE_ALLOW_WRITE); @@ -1112,19 +1112,19 @@ void thr_abort_locks(THR_LOCK *lock, my_bool upgrade_lock) { THR_LOCK_DATA *data; DBUG_ENTER("thr_abort_locks"); - pthread_mutex_lock(&lock->mutex); + mysql_mutex_lock(&lock->mutex); for (data=lock->read_wait.data; data ; data=data->next) { data->type=TL_UNLOCK; /* Mark killed */ /* It's safe to signal the cond first: we're still holding the mutex. */ - pthread_cond_signal(data->cond); + mysql_cond_signal(data->cond); data->cond=0; /* Removed from list */ } for (data=lock->write_wait.data; data ; data=data->next) { data->type=TL_UNLOCK; - pthread_cond_signal(data->cond); + mysql_cond_signal(data->cond); data->cond=0; } lock->read_wait.last= &lock->read_wait.data; @@ -1132,7 +1132,7 @@ void thr_abort_locks(THR_LOCK *lock, my_bool upgrade_lock) lock->read_wait.data=lock->write_wait.data=0; if (upgrade_lock && lock->write.data) lock->write.data->type=TL_WRITE_ONLY; - pthread_mutex_unlock(&lock->mutex); + mysql_mutex_unlock(&lock->mutex); DBUG_VOID_RETURN; } @@ -1149,7 +1149,7 @@ my_bool thr_abort_locks_for_thread(THR_LOCK *lock, my_thread_id thread_id) my_bool found= FALSE; DBUG_ENTER("thr_abort_locks_for_thread"); - pthread_mutex_lock(&lock->mutex); + mysql_mutex_lock(&lock->mutex); for (data= lock->read_wait.data; data ; data= data->next) { if (data->owner->info->thread_id == thread_id) /* purecov: tested */ @@ -1158,7 +1158,7 @@ my_bool thr_abort_locks_for_thread(THR_LOCK *lock, my_thread_id thread_id) data->type= TL_UNLOCK; /* Mark killed */ /* It's safe to signal the cond first: we're still holding the mutex. */ found= TRUE; - pthread_cond_signal(data->cond); + mysql_cond_signal(data->cond); data->cond= 0; /* Removed from list */ if (((*data->prev)= data->next)) @@ -1174,7 +1174,7 @@ my_bool thr_abort_locks_for_thread(THR_LOCK *lock, my_thread_id thread_id) DBUG_PRINT("info",("Aborting write-wait lock")); data->type= TL_UNLOCK; found= TRUE; - pthread_cond_signal(data->cond); + mysql_cond_signal(data->cond); data->cond= 0; if (((*data->prev)= data->next)) @@ -1184,7 +1184,7 @@ my_bool thr_abort_locks_for_thread(THR_LOCK *lock, my_thread_id thread_id) } } wake_up_waiters(lock); - pthread_mutex_unlock(&lock->mutex); + mysql_mutex_unlock(&lock->mutex); DBUG_RETURN(found); } @@ -1233,7 +1233,7 @@ void thr_downgrade_write_lock(THR_LOCK_DATA *in_data, #endif DBUG_ENTER("thr_downgrade_write_only_lock"); - pthread_mutex_lock(&lock->mutex); + mysql_mutex_lock(&lock->mutex); DBUG_ASSERT(old_lock_type == TL_WRITE_ONLY); DBUG_ASSERT(old_lock_type > new_lock_type); in_data->type= new_lock_type; @@ -1325,7 +1325,7 @@ void thr_downgrade_write_lock(THR_LOCK_DATA *in_data, next= data->next; if (start_writers && data->type == new_lock_type) { - pthread_cond_t *cond= data->cond; + mysql_cond_t *cond= data->cond; /* It is ok to start this waiter. Move from being first in wait queue to be last in write queue. @@ -1339,7 +1339,7 @@ void thr_downgrade_write_lock(THR_LOCK_DATA *in_data, data->next= 0; check_locks(lock, "Started write lock after downgrade",0); data->cond= 0; - pthread_cond_signal(cond); + mysql_cond_signal(cond); } else { @@ -1379,7 +1379,7 @@ void thr_downgrade_write_lock(THR_LOCK_DATA *in_data, if (new_lock_type != TL_WRITE_ALLOW_READ || data->type != TL_READ_NO_INSERT) { - pthread_cond_t *cond= data->cond; + mysql_cond_t *cond= data->cond; if (((*data->prev)= data->next)) data->next->prev= data->prev; else @@ -1392,13 +1392,13 @@ void thr_downgrade_write_lock(THR_LOCK_DATA *in_data, lock->read_no_write_count++; check_locks(lock, "Started read lock after downgrade",0); data->cond= 0; - pthread_cond_signal(cond); + mysql_cond_signal(cond); } } } check_locks(lock,"after starting waiters after downgrading lock",0); #endif - pthread_mutex_unlock(&lock->mutex); + mysql_mutex_unlock(&lock->mutex); DBUG_VOID_RETURN; } @@ -1410,10 +1410,10 @@ my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data, THR_LOCK *lock=data->lock; DBUG_ENTER("thr_upgrade_write_delay_lock"); - pthread_mutex_lock(&lock->mutex); + mysql_mutex_lock(&lock->mutex); if (data->type == TL_UNLOCK || data->type >= TL_WRITE_LOW_PRIORITY) { - pthread_mutex_unlock(&lock->mutex); + mysql_mutex_unlock(&lock->mutex); DBUG_RETURN(data->type == TL_UNLOCK); /* Test if Aborted */ } check_locks(lock,"before upgrading lock",0); @@ -1427,7 +1427,7 @@ my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data, { /* We have the lock */ if (data->lock->get_status) (*data->lock->get_status)(data->status_param, 0); - pthread_mutex_unlock(&lock->mutex); + mysql_mutex_unlock(&lock->mutex); DBUG_RETURN(0); } @@ -1460,10 +1460,10 @@ my_bool thr_reschedule_write_lock(THR_LOCK_DATA *data) enum thr_lock_type write_lock_type; DBUG_ENTER("thr_reschedule_write_lock"); - pthread_mutex_lock(&lock->mutex); + mysql_mutex_lock(&lock->mutex); if (!lock->read_wait.data) /* No waiting read locks */ { - pthread_mutex_unlock(&lock->mutex); + mysql_mutex_unlock(&lock->mutex); DBUG_RETURN(0); } @@ -1485,7 +1485,7 @@ my_bool thr_reschedule_write_lock(THR_LOCK_DATA *data) lock->write_wait.data=data; free_all_read_locks(lock,0); - pthread_mutex_unlock(&lock->mutex); + mysql_mutex_unlock(&lock->mutex); DBUG_RETURN(thr_upgrade_write_delay_lock(data, write_lock_type)); } @@ -1520,13 +1520,13 @@ void thr_print_locks(void) LIST *list; uint count=0; - pthread_mutex_lock(&THR_LOCK_lock); + mysql_mutex_lock(&THR_LOCK_lock); puts("Current locks:"); for (list= thr_lock_thread_list; list && count++ < MAX_THREADS; list= list_rest(list)) { THR_LOCK *lock=(THR_LOCK*) list->data; - pthread_mutex_lock(&lock->mutex); + mysql_mutex_lock(&lock->mutex); printf("lock: 0x%lx:",(ulong) lock); if ((lock->write_wait.data || lock->read_wait.data) && (! lock->read.data && ! lock->write.data)) @@ -1544,11 +1544,11 @@ void thr_print_locks(void) thr_print_lock("write_wait",&lock->write_wait); thr_print_lock("read",&lock->read); thr_print_lock("read_wait",&lock->read_wait); - pthread_mutex_unlock(&lock->mutex); + mysql_mutex_unlock(&lock->mutex); puts(""); } fflush(stdout); - pthread_mutex_unlock(&THR_LOCK_lock); + mysql_mutex_unlock(&THR_LOCK_lock); } #endif /* THREAD */ @@ -1609,8 +1609,8 @@ int lock_counts[]= {sizeof(test_0)/sizeof(struct st_test), }; -static pthread_cond_t COND_thread_count; -static pthread_mutex_t LOCK_thread_count; +static mysql_cond_t COND_thread_count; +static mysql_mutex_t LOCK_thread_count; static uint thread_count; static ulong sum=0; @@ -1662,7 +1662,7 @@ static void *test_thread(void *arg) data[i].type= tests[param][i].lock_type; } thr_multi_lock(multi_locks, lock_counts[param], &owner); - pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); { int tmp=rand() & 7; /* Do something from 0-2 sec */ if (tmp == 0) @@ -1676,16 +1676,16 @@ static void *test_thread(void *arg) sum+=k; } } - pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); thr_multi_unlock(multi_locks,lock_counts[param]); } printf("Thread %s (%d) ended\n",my_thread_name(),param); fflush(stdout); thr_print_locks(); - pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); thread_count--; - pthread_cond_signal(&COND_thread_count); /* Tell main we are ready */ - pthread_mutex_unlock(&LOCK_thread_count); + mysql_cond_signal(&COND_thread_count); /* Tell main we are ready */ + mysql_mutex_unlock(&LOCK_thread_count); free((uchar*) arg); return 0; } @@ -1702,15 +1702,15 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) printf("Main thread: %s\n",my_thread_name()); - if ((error=pthread_cond_init(&COND_thread_count,NULL))) + if ((error= mysql_cond_init(0, &COND_thread_count, NULL))) { - fprintf(stderr,"Got error: %d from pthread_cond_init (errno: %d)", + fprintf(stderr, "Got error: %d from mysql_cond_init (errno: %d)", error,errno); exit(1); } - if ((error=pthread_mutex_init(&LOCK_thread_count,MY_MUTEX_INIT_FAST))) + if ((error= mysql_mutex_init(0, &LOCK_thread_count, MY_MUTEX_INIT_FAST))) { - fprintf(stderr,"Got error: %d from pthread_cond_init (errno: %d)", + fprintf(stderr, "Got error: %d from mysql_cond_init (errno: %d)", error,errno); exit(1); } @@ -1752,33 +1752,35 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) param=(int*) malloc(sizeof(int)); *param=i; - if ((error=pthread_mutex_lock(&LOCK_thread_count))) + if ((error= mysql_mutex_lock(&LOCK_thread_count))) { - fprintf(stderr,"Got error: %d from pthread_mutex_lock (errno: %d)", - error,errno); + fprintf(stderr, "Got error: %d from mysql_mutex_lock (errno: %d)", + error, errno); exit(1); } - if ((error=pthread_create(&tid,&thr_attr,test_thread,(void*) param))) + if ((error= mysql_thread_create(0, + &tid, &thr_attr, test_thread, + (void*) param))) { - fprintf(stderr,"Got error: %d from pthread_create (errno: %d)\n", - error,errno); - pthread_mutex_unlock(&LOCK_thread_count); + fprintf(stderr, "Got error: %d from mysql_thread_create (errno: %d)\n", + error, errno); + mysql_mutex_unlock(&LOCK_thread_count); exit(1); } thread_count++; - pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); } pthread_attr_destroy(&thr_attr); - if ((error=pthread_mutex_lock(&LOCK_thread_count))) - fprintf(stderr,"Got error: %d from pthread_mutex_lock\n",error); + if ((error= mysql_mutex_lock(&LOCK_thread_count))) + fprintf(stderr, "Got error: %d from mysql_mutex_lock\n", error); while (thread_count) { - if ((error=pthread_cond_wait(&COND_thread_count,&LOCK_thread_count))) - fprintf(stderr,"Got error: %d from pthread_cond_wait\n",error); + if ((error= mysql_cond_wait(&COND_thread_count, &LOCK_thread_count))) + fprintf(stderr, "Got error: %d from mysql_cond_wait\n", error); } - if ((error=pthread_mutex_unlock(&LOCK_thread_count))) - fprintf(stderr,"Got error: %d from pthread_mutex_unlock\n",error); + if ((error= mysql_mutex_unlock(&LOCK_thread_count))) + fprintf(stderr, "Got error: %d from mysql_mutex_unlock\n", error); for (i=0 ; i < (int) array_elements(locks) ; i++) thr_lock_delete(locks+i); #ifdef EXTRA_DEBUG diff --git a/mysys/thr_mutex.c b/mysys/thr_mutex.c index 8f9928026ba..db35d5a13a6 100644 --- a/mysys/thr_mutex.c +++ b/mysys/thr_mutex.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright (C) 2000-2003 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -39,6 +39,7 @@ #endif #endif /* DO_NOT_REMOVE_THREAD_WRAPPERS */ +/* Not instrumented */ static pthread_mutex_t THR_LOCK_mutex; static ulong safe_mutex_count= 0; /* Number of mutexes created */ #ifdef SAFE_MUTEX_DETECT_DESTROY @@ -85,7 +86,9 @@ int safe_mutex_init(safe_mutex_t *mp, pthread_mutex_unlock(&THR_LOCK_mutex); } #else - thread_safe_increment(safe_mutex_count, &THR_LOCK_mutex); + pthread_mutex_lock(&THR_LOCK_mutex); + safe_mutex_count++; + pthread_mutex_unlock(&THR_LOCK_mutex); #endif /* SAFE_MUTEX_DETECT_DESTROY */ return 0; } @@ -344,7 +347,9 @@ int safe_mutex_destroy(safe_mutex_t *mp, const char *file, uint line) mp->info= NULL; /* Get crash if double free */ } #else - thread_safe_sub(safe_mutex_count, 1, &THR_LOCK_mutex); + pthread_mutex_lock(&THR_LOCK_mutex); + safe_mutex_count--; + pthread_mutex_unlock(&THR_LOCK_mutex); #endif /* SAFE_MUTEX_DETECT_DESTROY */ return error; } diff --git a/plugin/semisync/semisync_master.cc b/plugin/semisync/semisync_master.cc index cc83978ad4e..23c78eca587 100644 --- a/plugin/semisync/semisync_master.cc +++ b/plugin/semisync/semisync_master.cc @@ -1,5 +1,5 @@ /* Copyright (C) 2007 Google Inc. - Copyright (C) 2008 MySQL AB + Copyright (C) 2008 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -64,7 +64,7 @@ static int gettimeofday(struct timeval *tv, void *tz) ******************************************************************************/ ActiveTranx::ActiveTranx(int max_connections, - pthread_mutex_t *lock, + mysql_mutex_t *lock, unsigned long trace_level) : Trace(trace_level), num_transactions_(max_connections), num_entries_(max_connections << 1), @@ -416,8 +416,10 @@ int ReplSemiSyncMaster::initObject() max_transactions_ = (int)max_connections; /* Mutex initialization can only be done after MY_INIT(). */ - pthread_mutex_init(&LOCK_binlog_, MY_MUTEX_INIT_FAST); - pthread_cond_init(&COND_binlog_send_, NULL); + mysql_mutex_init(key_ss_mutex_LOCK_binlog_, + &LOCK_binlog_, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_ss_cond_COND_binlog_send_, + &COND_binlog_send_, NULL); if (rpl_semi_sync_master_enabled) result = enableMaster(); @@ -494,8 +496,8 @@ ReplSemiSyncMaster::~ReplSemiSyncMaster() { if (init_done_) { - pthread_mutex_destroy(&LOCK_binlog_); - pthread_cond_destroy(&COND_binlog_send_); + mysql_mutex_destroy(&LOCK_binlog_); + mysql_cond_destroy(&COND_binlog_send_); } delete active_tranxs_; @@ -503,17 +505,17 @@ ReplSemiSyncMaster::~ReplSemiSyncMaster() void ReplSemiSyncMaster::lock() { - pthread_mutex_lock(&LOCK_binlog_); + mysql_mutex_lock(&LOCK_binlog_); } void ReplSemiSyncMaster::unlock() { - pthread_mutex_unlock(&LOCK_binlog_); + mysql_mutex_unlock(&LOCK_binlog_); } void ReplSemiSyncMaster::cond_broadcast() { - pthread_cond_broadcast(&COND_binlog_send_); + mysql_cond_broadcast(&COND_binlog_send_); } int ReplSemiSyncMaster::cond_timewait(struct timespec *wait_time) @@ -522,8 +524,8 @@ int ReplSemiSyncMaster::cond_timewait(struct timespec *wait_time) int wait_res; function_enter(kWho); - wait_res = pthread_cond_timedwait(&COND_binlog_send_, - &LOCK_binlog_, wait_time); + wait_res= mysql_cond_timedwait(&COND_binlog_send_, + &LOCK_binlog_, wait_time); return function_exit(kWho, wait_res); } diff --git a/plugin/semisync/semisync_master.h b/plugin/semisync/semisync_master.h index d2b87745600..dbe8bb9d5e2 100644 --- a/plugin/semisync/semisync_master.h +++ b/plugin/semisync/semisync_master.h @@ -1,5 +1,6 @@ /* Copyright (C) 2007 Google Inc. Copyright (C) 2008 MySQL AB + Copyright (C) 2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,6 +21,11 @@ #include "semisync.h" +#ifdef HAVE_PSI_INTERFACE +extern PSI_mutex_key key_ss_mutex_LOCK_binlog_; +extern PSI_cond_key key_ss_cond_COND_binlog_send_; +#endif + /** This class manages memory for active transaction list. @@ -49,7 +55,7 @@ private: int num_transactions_; /* maximum transactions */ int num_entries_; /* maximum hash table entries */ - pthread_mutex_t *lock_; /* mutex lock */ + mysql_mutex_t *lock_; /* mutex lock */ inline void assert_lock_owner(); @@ -74,7 +80,7 @@ private: } public: - ActiveTranx(int max_connections, pthread_mutex_t *lock, + ActiveTranx(int max_connections, mysql_mutex_t *lock, unsigned long trace_level); ~ActiveTranx(); @@ -124,14 +130,14 @@ class ReplSemiSyncMaster /* This cond variable is signaled when enough binlog has been sent to slave, * so that a waiting trx can return the 'ok' to the client for a commit. */ - pthread_cond_t COND_binlog_send_; + mysql_cond_t COND_binlog_send_; /* Mutex that protects the following state variables and the active * transaction list. * Under no cirumstances we can acquire mysql_bin_log.LOCK_log if we are * already holding LOCK_binlog_ because it can cause deadlocks. */ - pthread_mutex_t LOCK_binlog_; + mysql_mutex_t LOCK_binlog_; /* This is set to true when reply_file_name_ contains meaningful data. */ bool reply_file_name_inited_; diff --git a/plugin/semisync/semisync_master_plugin.cc b/plugin/semisync/semisync_master_plugin.cc index efcb7172b28..e371df3edc3 100644 --- a/plugin/semisync/semisync_master_plugin.cc +++ b/plugin/semisync/semisync_master_plugin.cc @@ -1,5 +1,5 @@ /* Copyright (C) 2007 Google Inc. - Copyright (C) 2008 MySQL AB + Copyright (C) 2008 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -334,9 +334,43 @@ static SHOW_VAR semi_sync_master_status_vars[]= { {NULL, NULL, SHOW_LONG}, }; +#ifdef HAVE_PSI_INTERFACE +PSI_mutex_key key_ss_mutex_LOCK_binlog_; + +static PSI_mutex_info all_semisync_mutexes[]= +{ + { &key_ss_mutex_LOCK_binlog_, "LOCK_binlog_", 0} +}; + +PSI_cond_key key_ss_cond_COND_binlog_send_; + +static PSI_cond_info all_semisync_conds[]= +{ + { &key_ss_cond_COND_binlog_send_, "COND_binlog_send_", 0} +}; + +static void init_semisync_psi_keys(void) +{ + const char* category= "semisync"; + int count; + + if (PSI_server == NULL) + return; + + count= array_elements(all_semisync_mutexes); + PSI_server->register_mutex(category, all_semisync_mutexes, count); + + count= array_elements(all_semisync_conds); + PSI_server->register_cond(category, all_semisync_conds, count); +} +#endif /* HAVE_PSI_INTERFACE */ static int semi_sync_master_plugin_init(void *p) { +#ifdef HAVE_PSI_INTERFACE + init_semisync_psi_keys(); +#endif + if (repl_semisync.initObject()) return 1; if (register_trans_observer(&trans_observer, p)) diff --git a/sql/debug_sync.cc b/sql/debug_sync.cc index 81870e6b7a3..3c8e24f6901 100644 --- a/sql/debug_sync.cc +++ b/sql/debug_sync.cc @@ -221,14 +221,14 @@ There are quite a few places in MySQL, where we use a synchronization pattern like this: - pthread_mutex_lock(&mutex); + mysql_mutex_lock(&mutex); thd->enter_cond(&condition_variable, &mutex, new_message); #if defined(ENABLE_DEBUG_SYNC) if (!thd->killed && !end_of_wait_condition) DEBUG_SYNC(thd, "sync_point_name"); #endif while (!thd->killed && !end_of_wait_condition) - pthread_cond_wait(&condition_variable, &mutex); + mysql_cond_wait(&condition_variable, &mutex); thd->exit_cond(old_message); Here some explanations: @@ -264,12 +264,12 @@ while (!thd->killed && !end_of_wait_condition) { - pthread_mutex_lock(&mutex); + mysql_mutex_lock(&mutex); thd->enter_cond(&condition_variable, &mutex, new_message); if (!thd->killed [&& !end_of_wait_condition]) { [DEBUG_SYNC(thd, "sync_point_name");] - pthread_cond_wait(&condition_variable, &mutex); + mysql_cond_wait(&condition_variable, &mutex); } thd->exit_cond(old_message); } @@ -285,7 +285,7 @@ before sleeping, we hold the mutex, which is registered in mysys_var. The killing thread would try to acquire the mutex before signaling the condition variable. Since the mutex is only released implicitly in - pthread_cond_wait(), the signaling happens at the right place. We + mysql_cond_wait(), the signaling happens at the right place. We have a safe synchronization. === Co-work with the DBUG facility === @@ -373,8 +373,8 @@ struct st_debug_sync_control struct st_debug_sync_globals { String ds_signal; /* signal variable */ - pthread_cond_t ds_cond; /* condition variable */ - pthread_mutex_t ds_mutex; /* mutex variable */ + mysql_cond_t ds_cond; /* condition variable */ + mysql_mutex_t ds_mutex; /* mutex variable */ ulonglong dsp_hits; /* statistics */ ulonglong dsp_executed; /* statistics */ ulonglong dsp_max_active; /* statistics */ @@ -425,6 +425,37 @@ static void debug_sync_C_callback(const char *sync_point_name, debug_sync(current_thd, sync_point_name, name_len); } +#ifdef HAVE_PSI_INTERFACE +static PSI_mutex_key key_debug_sync_globals_ds_mutex; + +static PSI_mutex_info all_debug_sync_mutexes[]= +{ + { &key_debug_sync_globals_ds_mutex, "DEBUG_SYNC::mutex", PSI_FLAG_GLOBAL} +}; + +static PSI_cond_key key_debug_sync_globals_ds_cond; + +static PSI_cond_info all_debug_sync_conds[]= +{ + { &key_debug_sync_globals_ds_cond, "DEBUG_SYNC::cond", PSI_FLAG_GLOBAL} +}; + +static void init_debug_sync_psi_keys(void) +{ + const char* category= "sql"; + int count; + + if (PSI_server == NULL) + return; + + count= array_elements(all_debug_sync_mutexes); + PSI_server->register_mutex(category, all_debug_sync_mutexes, count); + + count= array_elements(all_debug_sync_conds); + PSI_server->register_cond(category, all_debug_sync_conds, count); +} +#endif /* HAVE_PSI_INTERFACE */ + /** Initialize the debug sync facility at server start. @@ -438,15 +469,21 @@ int debug_sync_init(void) { DBUG_ENTER("debug_sync_init"); +#ifdef HAVE_PSI_INTERFACE + init_debug_sync_psi_keys(); +#endif + if (opt_debug_sync_timeout) { int rc; /* Initialize the global variables. */ debug_sync_global.ds_signal.length(0); - if ((rc= pthread_cond_init(&debug_sync_global.ds_cond, NULL)) || - (rc= pthread_mutex_init(&debug_sync_global.ds_mutex, - MY_MUTEX_INIT_FAST))) + if ((rc= mysql_cond_init(key_debug_sync_globals_ds_cond, + &debug_sync_global.ds_cond, NULL)) || + (rc= mysql_mutex_init(key_debug_sync_globals_ds_mutex, + &debug_sync_global.ds_mutex, + MY_MUTEX_INIT_FAST))) DBUG_RETURN(rc); /* purecov: inspected */ /* Set the call back pointer in C files. */ @@ -476,8 +513,8 @@ void debug_sync_end(void) /* Destroy the global variables. */ debug_sync_global.ds_signal.free(); - (void) pthread_cond_destroy(&debug_sync_global.ds_cond); - (void) pthread_mutex_destroy(&debug_sync_global.ds_mutex); + mysql_cond_destroy(&debug_sync_global.ds_cond); + mysql_mutex_destroy(&debug_sync_global.ds_mutex); /* Print statistics. */ { @@ -585,12 +622,12 @@ void debug_sync_end_thread(THD *thd) } /* Statistics. */ - pthread_mutex_lock(&debug_sync_global.ds_mutex); + mysql_mutex_lock(&debug_sync_global.ds_mutex); debug_sync_global.dsp_hits+= ds_control->dsp_hits; debug_sync_global.dsp_executed+= ds_control->dsp_executed; if (debug_sync_global.dsp_max_active < ds_control->dsp_max_active) debug_sync_global.dsp_max_active= ds_control->dsp_max_active; - pthread_mutex_unlock(&debug_sync_global.ds_mutex); + mysql_mutex_unlock(&debug_sync_global.ds_mutex); my_free(ds_control, MYF(0)); thd->debug_sync_control= NULL; @@ -824,9 +861,9 @@ static void debug_sync_reset(THD *thd) ds_control->ds_active= 0; /* Clear the global signal. */ - pthread_mutex_lock(&debug_sync_global.ds_mutex); + mysql_mutex_lock(&debug_sync_global.ds_mutex); debug_sync_global.ds_signal.length(0); - pthread_mutex_unlock(&debug_sync_global.ds_mutex); + mysql_mutex_unlock(&debug_sync_global.ds_mutex); DBUG_VOID_RETURN; } @@ -1659,7 +1696,7 @@ uchar *sys_var_debug_sync::value_ptr(THD *thd, static char on[]= "ON - current signal: '"; // Ensure exclusive access to debug_sync_global.ds_signal - pthread_mutex_lock(&debug_sync_global.ds_mutex); + mysql_mutex_lock(&debug_sync_global.ds_mutex); size_t lgt= (sizeof(on) /* includes '\0' */ + debug_sync_global.ds_signal.length() + 1 /* for '\'' */); @@ -1676,7 +1713,7 @@ uchar *sys_var_debug_sync::value_ptr(THD *thd, *(vptr++)= '\''; *vptr= '\0'; /* We have one byte reserved for the worst case. */ } - pthread_mutex_unlock(&debug_sync_global.ds_mutex); + mysql_mutex_unlock(&debug_sync_global.ds_mutex); } else { @@ -1744,7 +1781,7 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action) read access too, to create a memory barrier in order to avoid that threads just reads an old cached version of the signal. */ - pthread_mutex_lock(&debug_sync_global.ds_mutex); + mysql_mutex_lock(&debug_sync_global.ds_mutex); if (action->signal.length()) { @@ -1758,15 +1795,15 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action) debug_sync_emergency_disable(); /* purecov: tested */ } /* Wake threads waiting in a sync point. */ - pthread_cond_broadcast(&debug_sync_global.ds_cond); + mysql_cond_broadcast(&debug_sync_global.ds_cond); DBUG_PRINT("debug_sync_exec", ("signal '%s' at: '%s'", sig_emit, dsp_name)); } /* end if (action->signal.length()) */ if (action->wait_for.length()) { - pthread_mutex_t *old_mutex; - pthread_cond_t *old_cond; + mysql_mutex_t *old_mutex; + mysql_cond_t *old_cond; int error= 0; struct timespec abstime; @@ -1797,9 +1834,9 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action) while (stringcmp(&debug_sync_global.ds_signal, &action->wait_for) && !thd->killed && opt_debug_sync_timeout) { - error= pthread_cond_timedwait(&debug_sync_global.ds_cond, - &debug_sync_global.ds_mutex, - &abstime); + error= mysql_cond_timedwait(&debug_sync_global.ds_cond, + &debug_sync_global.ds_mutex, + &abstime); DBUG_EXECUTE("debug_sync", { /* Functions as DBUG_PRINT args can change keyword and line nr. */ const char *sig_glob= debug_sync_global.ds_signal.c_ptr(); @@ -1832,18 +1869,17 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action) protected mutex must always unlocked _before_ mysys_var->mutex is locked. (See comment in THD::exit_cond().) */ - pthread_mutex_unlock(&debug_sync_global.ds_mutex); - pthread_mutex_lock(&thd->mysys_var->mutex); + mysql_mutex_unlock(&debug_sync_global.ds_mutex); + mysql_mutex_lock(&thd->mysys_var->mutex); thd->mysys_var->current_mutex= old_mutex; thd->mysys_var->current_cond= old_cond; thd_proc_info(thd, old_proc_info); - pthread_mutex_unlock(&thd->mysys_var->mutex); - + mysql_mutex_unlock(&thd->mysys_var->mutex); } else { /* In case we don't wait, we just release the mutex. */ - pthread_mutex_unlock(&debug_sync_global.ds_mutex); + mysql_mutex_unlock(&debug_sync_global.ds_mutex); } /* end if (action->wait_for.length()) */ } /* end if (action->execute) */ diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index b71a7f602ab..4b72a7c8904 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -6904,7 +6904,7 @@ int ndbcluster_drop_database_impl(const char *path) while ((tabname=it++)) { tablename_to_filename(tabname, tmp, FN_REFLEN - (tmp - full_path)-1); - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); if (ha_ndbcluster::delete_table(0, ndb, full_path, dbname, tabname)) { const NdbError err= dict->getNdbError(); @@ -6914,7 +6914,7 @@ int ndbcluster_drop_database_impl(const char *path) ret= ndb_to_mysql_error(&err); } } - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } DBUG_RETURN(ret); } @@ -7067,7 +7067,7 @@ int ndbcluster_find_all_files(THD *thd) my_free((char*) data, MYF(MY_ALLOW_ZERO_PTR)); my_free((char*) pack_data, MYF(MY_ALLOW_ZERO_PTR)); - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); if (discover) { /* ToDo 4.1 database needs to be created if missing */ @@ -7085,7 +7085,7 @@ int ndbcluster_find_all_files(THD *thd) TRUE); } #endif - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } } while (unhandled && retries); @@ -7178,19 +7178,19 @@ int ndbcluster_find_files(handlerton *hton, THD *thd, file_name->str, reg_ext, 0); if (my_access(name, F_OK)) { - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); DBUG_PRINT("info", ("Table %s listed and need discovery", file_name->str)); if (ndb_create_table_from_engine(thd, db, file_name->str)) { - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_TABLE_EXISTS_ERROR, "Discover of table %s.%s failed", db, file_name->str); continue; } - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } DBUG_PRINT("info", ("%s existed in NDB _and_ on disk ", file_name->str)); file_on_disk= TRUE; @@ -7247,10 +7247,10 @@ int ndbcluster_find_files(handlerton *hton, THD *thd, file_name_str= (char*)my_hash_element(&ok_tables, i); end= end1 + tablename_to_filename(file_name_str, end1, sizeof(name) - (end1 - name)); - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); ndbcluster_create_binlog_setup(ndb, name, end-name, db, file_name_str, TRUE); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } } #endif @@ -7299,7 +7299,7 @@ int ndbcluster_find_files(handlerton *hton, THD *thd, } } - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); // Create new files List_iterator_fast it2(create_list); while ((file_name_str=it2++)) @@ -7314,7 +7314,7 @@ int ndbcluster_find_files(handlerton *hton, THD *thd, } } - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); my_hash_free(&ok_tables); my_hash_free(&ndb_tables); @@ -8214,7 +8214,7 @@ int handle_trailing_share(NDB_SHARE *share) bzero((char*) &table_list,sizeof(table_list)); table_list.db= share->db; table_list.alias= table_list.table_name= share->table_name; - safe_mutex_assert_owner(&LOCK_open); + mysql_mutex_assert_owner(&LOCK_open); close_cached_tables(thd, &table_list, TRUE, FALSE, FALSE); pthread_mutex_lock(&ndbcluster_mutex); diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc index e34a22cf9f4..d2ac46ae235 100644 --- a/sql/ha_ndbcluster_binlog.cc +++ b/sql/ha_ndbcluster_binlog.cc @@ -343,7 +343,7 @@ ndbcluster_binlog_open_table(THD *thd, NDB_SHARE *share, int error; DBUG_ENTER("ndbcluster_binlog_open_table"); - safe_mutex_assert_owner(&LOCK_open); + mysql_mutex_assert_owner(&LOCK_open); init_tmp_table_share(thd, table_share, share->db, 0, share->table_name, share->key); if ((error= open_table_def(thd, table_share, 0))) @@ -891,9 +891,9 @@ int ndbcluster_setup_binlog_table_shares(THD *thd) if (!ndb_schema_share && ndbcluster_check_ndb_schema_share() == 0) { - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); ndb_create_table_from_engine(thd, NDB_REP_DB, NDB_SCHEMA_TABLE); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); if (!ndb_schema_share) { ndbcluster_create_schema_table(thd); @@ -905,9 +905,9 @@ int ndbcluster_setup_binlog_table_shares(THD *thd) if (!ndb_apply_status_share && ndbcluster_check_ndb_apply_status_share() == 0) { - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); ndb_create_table_from_engine(thd, NDB_REP_DB, NDB_APPLY_TABLE); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); if (!ndb_apply_status_share) { ndbcluster_create_ndb_apply_status_table(thd); @@ -917,12 +917,12 @@ int ndbcluster_setup_binlog_table_shares(THD *thd) } if (!ndbcluster_find_all_files(thd)) { - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); ndb_binlog_tables_inited= TRUE; if (ndb_extra_logging) sql_print_information("NDB Binlog: ndb tables writable"); close_cached_tables(NULL, NULL, TRUE, FALSE, FALSE); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); /* Signal injector thread that all is setup */ pthread_cond_signal(&injector_cond); } @@ -1565,8 +1565,8 @@ end: (void) pthread_mutex_lock(&ndb_schema_object->mutex); if (have_lock_open) { - safe_mutex_assert_owner(&LOCK_open); - (void) pthread_mutex_unlock(&LOCK_open); + mysql_mutex_assert_owner(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } while (1) { @@ -1625,7 +1625,7 @@ end: } if (have_lock_open) { - (void) pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); } (void) pthread_mutex_unlock(&ndb_schema_object->mutex); } @@ -1709,7 +1709,7 @@ ndb_handle_schema_change(THD *thd, Ndb *ndb, NdbEventOperation *pOp, { DBUG_DUMP("frm", (uchar*) altered_table->getFrmData(), altered_table->getFrmLength()); - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); Ndb_table_guard ndbtab_g(dict, tabname); const NDBTAB *old= ndbtab_g.get_table(); if (!old && @@ -1747,7 +1747,7 @@ ndb_handle_schema_change(THD *thd, Ndb *ndb, NdbEventOperation *pOp, dbname= table_share->db.str; tabname= table_share->table_name.str; - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } my_free((char*)data, MYF(MY_ALLOW_ZERO_PTR)); my_free((char*)pack_data, MYF(MY_ALLOW_ZERO_PTR)); @@ -1974,7 +1974,7 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb, } // fall through case SOT_CREATE_TABLE: - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); if (ndbcluster_check_if_local_table(schema->db, schema->name)) { DBUG_PRINT("info", ("NDB Binlog: Skipping locally defined table '%s.%s'", @@ -1988,7 +1988,7 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb, { print_could_not_discover_error(thd, schema); } - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); log_query= 1; break; case SOT_DROP_DB: @@ -2257,7 +2257,7 @@ ndb_binlog_thread_handle_schema_event_post_epoch(THD *thd, free_share(&share); share= 0; } - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); if (ndbcluster_check_if_local_table(schema->db, schema->name)) { DBUG_PRINT("info", ("NDB Binlog: Skipping locally defined table '%s.%s'", @@ -2271,7 +2271,7 @@ ndb_binlog_thread_handle_schema_event_post_epoch(THD *thd, { print_could_not_discover_error(thd, schema); } - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } break; default: @@ -3155,8 +3155,8 @@ ndbcluster_handle_drop_table(Ndb *ndb, const char *event_name, #ifdef SYNC_DROP_ thd->proc_info= "Syncing ndb table schema operation and binlog"; (void) pthread_mutex_lock(&share->mutex); - safe_mutex_assert_owner(&LOCK_open); - (void) pthread_mutex_unlock(&LOCK_open); + mysql_mutex_assert_owner(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); int max_timeout= opt_ndb_sync_timeout; while (share->op) { @@ -3182,7 +3182,7 @@ ndbcluster_handle_drop_table(Ndb *ndb, const char *event_name, type_str, share->key); } } - (void) pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); (void) pthread_mutex_unlock(&share->mutex); #else (void) pthread_mutex_lock(&share->mutex); diff --git a/sql/item_func.cc b/sql/item_func.cc index ccb55feff81..f23bc340e71 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1,4 +1,4 @@ -/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. +/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -3287,7 +3287,7 @@ bool udf_handler::get_arguments() { return 0; } ** User level locks */ -pthread_mutex_t LOCK_user_locks; +mysql_mutex_t LOCK_user_locks; static HASH hash_user_locks; class User_level_lock @@ -3298,7 +3298,7 @@ class User_level_lock public: int count; bool locked; - pthread_cond_t cond; + mysql_cond_t cond; my_thread_id thread_id; void set_thread(THD *thd) { thread_id= thd->thread_id; } @@ -3306,7 +3306,7 @@ public: :key_length(length),count(1),locked(1), thread_id(id) { key= (uchar*) my_memdup(key_arg,length,MYF(0)); - pthread_cond_init(&cond,NULL); + mysql_cond_init(key_user_level_lock_cond, &cond, NULL); if (key) { if (my_hash_insert(&hash_user_locks,(uchar*) this)) @@ -3323,7 +3323,7 @@ public: my_hash_delete(&hash_user_locks,(uchar*) this); my_free(key, MYF(0)); } - pthread_cond_destroy(&cond); + mysql_cond_destroy(&cond); } inline bool initialized() { return key != 0; } friend void item_user_lock_release(User_level_lock *ull); @@ -3338,12 +3338,36 @@ uchar *ull_get_key(const User_level_lock *ull, size_t *length, return ull->key; } +#ifdef HAVE_PSI_INTERFACE +static PSI_mutex_key key_LOCK_user_locks; + +static PSI_mutex_info all_user_mutexes[]= +{ + { &key_LOCK_user_locks, "LOCK_user_locks", PSI_FLAG_GLOBAL} +}; + +static void init_user_lock_psi_keys(void) +{ + const char* category= "sql"; + int count; + + if (PSI_server == NULL) + return; + + count= array_elements(all_user_mutexes); + PSI_server->register_mutex(category, all_user_mutexes, count); +} +#endif static bool item_user_lock_inited= 0; void item_user_lock_init(void) { - pthread_mutex_init(&LOCK_user_locks,MY_MUTEX_INIT_SLOW); +#ifdef HAVE_PSI_INTERFACE + init_user_lock_psi_keys(); +#endif + + mysql_mutex_init(key_LOCK_user_locks, &LOCK_user_locks, MY_MUTEX_INIT_SLOW); my_hash_init(&hash_user_locks,system_charset_info, 16,0,0,(my_hash_get_key) ull_get_key,NULL,0); item_user_lock_inited= 1; @@ -3355,7 +3379,7 @@ void item_user_lock_free(void) { item_user_lock_inited= 0; my_hash_free(&hash_user_locks); - pthread_mutex_destroy(&LOCK_user_locks); + mysql_mutex_destroy(&LOCK_user_locks); } } @@ -3364,7 +3388,7 @@ void item_user_lock_release(User_level_lock *ull) ull->locked=0; ull->thread_id= 0; if (--ull->count) - pthread_cond_signal(&ull->cond); + mysql_cond_signal(&ull->cond); else delete ull; } @@ -3407,7 +3431,7 @@ void debug_sync_point(const char* lock_name, uint lock_timeout) struct timespec abstime; size_t lock_name_len; lock_name_len= strlen(lock_name); - pthread_mutex_lock(&LOCK_user_locks); + mysql_mutex_lock(&LOCK_user_locks); if (thd->ull) { @@ -3425,7 +3449,7 @@ void debug_sync_point(const char* lock_name, uint lock_timeout) (uchar*) lock_name, lock_name_len)))) { - pthread_mutex_unlock(&LOCK_user_locks); + mysql_mutex_unlock(&LOCK_user_locks); return; } ull->count++; @@ -3441,7 +3465,7 @@ void debug_sync_point(const char* lock_name, uint lock_timeout) set_timespec(abstime,lock_timeout); while (ull->locked && !thd->killed) { - int error= pthread_cond_timedwait(&ull->cond, &LOCK_user_locks, &abstime); + int error= mysql_cond_timedwait(&ull->cond, &LOCK_user_locks, &abstime); if (error == ETIMEDOUT || error == ETIME) break; } @@ -3457,19 +3481,19 @@ void debug_sync_point(const char* lock_name, uint lock_timeout) ull->set_thread(thd); thd->ull=ull; } - pthread_mutex_unlock(&LOCK_user_locks); - pthread_mutex_lock(&thd->mysys_var->mutex); + mysql_mutex_unlock(&LOCK_user_locks); + mysql_mutex_lock(&thd->mysys_var->mutex); thd_proc_info(thd, 0); thd->mysys_var->current_mutex= 0; thd->mysys_var->current_cond= 0; - pthread_mutex_unlock(&thd->mysys_var->mutex); - pthread_mutex_lock(&LOCK_user_locks); + mysql_mutex_unlock(&thd->mysys_var->mutex); + mysql_mutex_lock(&LOCK_user_locks); if (thd->ull) { item_user_lock_release(thd->ull); thd->ull=0; } - pthread_mutex_unlock(&LOCK_user_locks); + mysql_mutex_unlock(&LOCK_user_locks); } #endif @@ -3487,8 +3511,8 @@ void debug_sync_point(const char* lock_name, uint lock_timeout) #define INTERRUPT_INTERVAL (5 * ULL(1000000000)) -static int interruptible_wait(THD *thd, pthread_cond_t *cond, - pthread_mutex_t *lock, double time) +static int interruptible_wait(THD *thd, mysql_cond_t *cond, + mysql_mutex_t *lock, double time) { int error; struct timespec abstime; @@ -3504,7 +3528,7 @@ static int interruptible_wait(THD *thd, pthread_cond_t *cond, timeout-= slice; set_timespec_nsec(abstime, slice); - error= pthread_cond_timedwait(cond, lock, &abstime); + error= mysql_cond_timedwait(cond, lock, &abstime); if (error == ETIMEDOUT || error == ETIME) { /* Return error if timed out or connection is broken. */ @@ -3547,11 +3571,11 @@ longlong Item_func_get_lock::val_int() if (thd->slave_thread) DBUG_RETURN(1); - pthread_mutex_lock(&LOCK_user_locks); + mysql_mutex_lock(&LOCK_user_locks); if (!res || !res->length()) { - pthread_mutex_unlock(&LOCK_user_locks); + mysql_mutex_unlock(&LOCK_user_locks); null_value=1; DBUG_RETURN(0); } @@ -3574,13 +3598,13 @@ longlong Item_func_get_lock::val_int() if (!ull || !ull->initialized()) { delete ull; - pthread_mutex_unlock(&LOCK_user_locks); + mysql_mutex_unlock(&LOCK_user_locks); null_value=1; // Probably out of memory DBUG_RETURN(0); } ull->set_thread(thd); thd->ull=ull; - pthread_mutex_unlock(&LOCK_user_locks); + mysql_mutex_unlock(&LOCK_user_locks); DBUG_PRINT("info", ("made new lock")); DBUG_RETURN(1); // Got new lock } @@ -3630,13 +3654,13 @@ longlong Item_func_get_lock::val_int() error=0; DBUG_PRINT("info", ("got the lock")); } - pthread_mutex_unlock(&LOCK_user_locks); + mysql_mutex_unlock(&LOCK_user_locks); - pthread_mutex_lock(&thd->mysys_var->mutex); + mysql_mutex_lock(&thd->mysys_var->mutex); thd_proc_info(thd, 0); thd->mysys_var->current_mutex= 0; thd->mysys_var->current_cond= 0; - pthread_mutex_unlock(&thd->mysys_var->mutex); + mysql_mutex_unlock(&thd->mysys_var->mutex); DBUG_RETURN(!error ? 1 : 0); } @@ -3667,7 +3691,7 @@ longlong Item_func_release_lock::val_int() null_value=0; result=0; - pthread_mutex_lock(&LOCK_user_locks); + mysql_mutex_lock(&LOCK_user_locks); if (!(ull= ((User_level_lock*) my_hash_search(&hash_user_locks, (const uchar*) res->ptr(), (size_t) res->length())))) @@ -3688,7 +3712,7 @@ longlong Item_func_release_lock::val_int() thd->ull=0; } } - pthread_mutex_unlock(&LOCK_user_locks); + mysql_mutex_unlock(&LOCK_user_locks); DBUG_RETURN(result); } @@ -3794,7 +3818,7 @@ void Item_func_benchmark::print(String *str, enum_query_type query_type) longlong Item_func_sleep::val_int() { THD *thd= current_thd; - pthread_cond_t cond; + mysql_cond_t cond; double timeout; int error; @@ -3808,13 +3832,13 @@ longlong Item_func_sleep::val_int() When given a very short timeout (< 10 mcs) just return immediately. We assume that the lines between this test and the call - to pthread_cond_timedwait() will be executed in less than 0.00001 sec. + to mysql_cond_timedwait() will be executed in less than 0.00001 sec. */ if (timeout < 0.00001) return 0; - pthread_cond_init(&cond, NULL); - pthread_mutex_lock(&LOCK_user_locks); + mysql_cond_init(key_item_func_sleep_cond, &cond, NULL); + mysql_mutex_lock(&LOCK_user_locks); thd_proc_info(thd, "User sleep"); thd->mysys_var->current_mutex= &LOCK_user_locks; @@ -3829,13 +3853,13 @@ longlong Item_func_sleep::val_int() error= 0; } thd_proc_info(thd, 0); - pthread_mutex_unlock(&LOCK_user_locks); - pthread_mutex_lock(&thd->mysys_var->mutex); + mysql_mutex_unlock(&LOCK_user_locks); + mysql_mutex_lock(&thd->mysys_var->mutex); thd->mysys_var->current_mutex= 0; thd->mysys_var->current_cond= 0; - pthread_mutex_unlock(&thd->mysys_var->mutex); + mysql_mutex_unlock(&thd->mysys_var->mutex); - pthread_cond_destroy(&cond); + mysql_cond_destroy(&cond); return test(!error); // Return 1 killed } @@ -5763,10 +5787,10 @@ longlong Item_func_is_free_lock::val_int() return 0; } - pthread_mutex_lock(&LOCK_user_locks); + mysql_mutex_lock(&LOCK_user_locks); ull= (User_level_lock *) my_hash_search(&hash_user_locks, (uchar*) res->ptr(), (size_t) res->length()); - pthread_mutex_unlock(&LOCK_user_locks); + mysql_mutex_unlock(&LOCK_user_locks); if (!ull || !ull->locked) return 1; return 0; @@ -5782,10 +5806,10 @@ longlong Item_func_is_used_lock::val_int() if (!res || !res->length()) return 0; - pthread_mutex_lock(&LOCK_user_locks); + mysql_mutex_lock(&LOCK_user_locks); ull= (User_level_lock *) my_hash_search(&hash_user_locks, (uchar*) res->ptr(), (size_t) res->length()); - pthread_mutex_unlock(&LOCK_user_locks); + mysql_mutex_unlock(&LOCK_user_locks); if (!ull || !ull->locked) return 0; diff --git a/sql/lock.cc b/sql/lock.cc index 56ae94ddc39..03524712259 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -978,7 +978,7 @@ int lock_and_wait_for_table_name(THD *thd, TABLE_LIST *table_list) if (wait_if_global_read_lock(thd, 0, 1)) DBUG_RETURN(1); - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); if ((lock_retcode = lock_table_name(thd, table_list, TRUE)) < 0) goto end; if (lock_retcode && wait_for_locked_table_names(thd, table_list)) @@ -989,7 +989,7 @@ int lock_and_wait_for_table_name(THD *thd, TABLE_LIST *table_list) error=0; end: - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); start_waiting_global_read_lock(thd); DBUG_RETURN(error); } @@ -1118,7 +1118,7 @@ bool wait_for_locked_table_names(THD *thd, TABLE_LIST *table_list) bool result=0; DBUG_ENTER("wait_for_locked_table_names"); - safe_mutex_assert_owner(&LOCK_open); + mysql_mutex_assert_owner(&LOCK_open); while (locked_named_table(thd,table_list)) { @@ -1128,7 +1128,7 @@ bool wait_for_locked_table_names(THD *thd, TABLE_LIST *table_list) break; } wait_for_condition(thd, &LOCK_open, &COND_refresh); - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); } DBUG_RETURN(result); } @@ -1508,7 +1508,7 @@ bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh, threads could not close their tables. This would make a pretty deadlock. */ - safe_mutex_assert_not_owner(&LOCK_open); + mysql_mutex_assert_not_owner(&LOCK_open); (void) pthread_mutex_lock(&LOCK_global_read_lock); if ((need_exit_cond= must_wait)) @@ -1622,7 +1622,7 @@ bool make_global_read_lock_block_commit(THD *thd) void broadcast_refresh(void) { - pthread_cond_broadcast(&COND_refresh); + mysql_cond_broadcast(&COND_refresh); pthread_cond_broadcast(&COND_global_read_lock); } diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index ca5b48d66bd..8b750f20b19 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1496,8 +1496,8 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds); int setup_ftfuncs(SELECT_LEX* select); int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order); -void wait_for_condition(THD *thd, pthread_mutex_t *mutex, - pthread_cond_t *cond); +void wait_for_condition(THD *thd, mysql_mutex_t *mutex, + mysql_cond_t *cond); int open_tables(THD *thd, TABLE_LIST **tables, uint *counter, uint flags); /* open_and_lock_tables with optional derived handling */ int open_and_lock_tables_derived(THD *thd, TABLE_LIST *tables, bool derived); @@ -1986,13 +1986,15 @@ extern FILE *bootstrap_file; extern int bootstrap_error; extern FILE *stderror_file; extern pthread_key(MEM_ROOT**,THR_MALLOC); -extern pthread_mutex_t LOCK_mysql_create_db, LOCK_open, LOCK_lock_db, - LOCK_mapped_file,LOCK_user_locks, LOCK_status, - LOCK_error_log, LOCK_delayed_insert, LOCK_uuid_generator, - LOCK_delayed_status, LOCK_delayed_create, LOCK_crypt, LOCK_timezone, +extern pthread_mutex_t LOCK_mapped_file, + LOCK_error_log, LOCK_uuid_generator, + LOCK_crypt, LOCK_timezone, LOCK_slave_list, LOCK_active_mi, LOCK_manager, LOCK_global_read_lock, LOCK_global_system_variables, LOCK_user_conn, LOCK_prepared_stmt_count, LOCK_error_messages, LOCK_connection_count; +extern mysql_mutex_t LOCK_mysql_create_db, LOCK_lock_db, LOCK_open, + LOCK_user_locks, LOCK_status, LOCK_delayed_status, LOCK_delayed_insert, + LOCK_delayed_create; extern MYSQL_PLUGIN_IMPORT pthread_mutex_t LOCK_thread_count; #ifdef HAVE_OPENSSL extern pthread_mutex_t LOCK_des_key_file; @@ -2002,7 +2004,8 @@ extern pthread_cond_t COND_server_started; extern int mysqld_server_started; extern rw_lock_t LOCK_grant, LOCK_sys_init_connect, LOCK_sys_init_slave; extern rw_lock_t LOCK_system_variables_hash; -extern pthread_cond_t COND_refresh, COND_thread_count, COND_manager; +extern mysql_cond_t COND_refresh; +extern pthread_cond_t COND_thread_count, COND_manager; extern pthread_cond_t COND_global_read_lock; extern pthread_attr_t connection_attrib; extern I_List threads; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 30ea646d2fd..25523d5b0ae 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -647,14 +647,16 @@ SHOW_COMP_OPTION have_profiling; pthread_key(MEM_ROOT**,THR_MALLOC); pthread_key(THD*, THR_THD); -pthread_mutex_t LOCK_mysql_create_db, LOCK_open, LOCK_thread_count, - LOCK_mapped_file, LOCK_status, LOCK_global_read_lock, +pthread_mutex_t LOCK_thread_count, + LOCK_mapped_file, LOCK_global_read_lock, LOCK_error_log, LOCK_uuid_generator, - LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create, LOCK_crypt, LOCK_global_system_variables, LOCK_user_conn, LOCK_slave_list, LOCK_active_mi, LOCK_connection_count, LOCK_error_messages; +mysql_mutex_t LOCK_open, LOCK_mysql_create_db, LOCK_status, LOCK_delayed_status, + LOCK_delayed_insert, LOCK_delayed_create; + /** The below lock protects access to two global server variables: max_prepared_stmt_count and prepared_stmt_count. These variables @@ -668,7 +670,8 @@ pthread_mutex_t LOCK_des_key_file; #endif rw_lock_t LOCK_grant, LOCK_sys_init_connect, LOCK_sys_init_slave; rw_lock_t LOCK_system_variables_hash; -pthread_cond_t COND_refresh, COND_thread_count, COND_global_read_lock; +mysql_cond_t COND_refresh; +pthread_cond_t COND_thread_count, COND_global_read_lock; pthread_t signal_thread; pthread_attr_t connection_attrib; pthread_mutex_t LOCK_server_started; @@ -958,14 +961,14 @@ static void close_connections(void) if (tmp->mysys_var) { tmp->mysys_var->abort=1; - pthread_mutex_lock(&tmp->mysys_var->mutex); + mysql_mutex_lock(&tmp->mysys_var->mutex); if (tmp->mysys_var->current_cond) { - pthread_mutex_lock(tmp->mysys_var->current_mutex); - pthread_cond_broadcast(tmp->mysys_var->current_cond); - pthread_mutex_unlock(tmp->mysys_var->current_mutex); + mysql_mutex_lock(tmp->mysys_var->current_mutex); + mysql_cond_broadcast(tmp->mysys_var->current_cond); + mysql_mutex_unlock(tmp->mysys_var->current_mutex); } - pthread_mutex_unlock(&tmp->mysys_var->mutex); + mysql_mutex_unlock(&tmp->mysys_var->mutex); } } (void) pthread_mutex_unlock(&LOCK_thread_count); // For unlink from list @@ -1410,17 +1413,17 @@ static void wait_for_signal_thread_to_end() static void clean_up_mutexes() { - (void) pthread_mutex_destroy(&LOCK_mysql_create_db); - (void) pthread_mutex_destroy(&LOCK_lock_db); + mysql_mutex_destroy(&LOCK_mysql_create_db); + mysql_mutex_destroy(&LOCK_lock_db); (void) rwlock_destroy(&LOCK_grant); - (void) pthread_mutex_destroy(&LOCK_open); + mysql_mutex_destroy(&LOCK_open); (void) pthread_mutex_destroy(&LOCK_thread_count); (void) pthread_mutex_destroy(&LOCK_mapped_file); - (void) pthread_mutex_destroy(&LOCK_status); + mysql_mutex_destroy(&LOCK_status); (void) pthread_mutex_destroy(&LOCK_error_log); - (void) pthread_mutex_destroy(&LOCK_delayed_insert); - (void) pthread_mutex_destroy(&LOCK_delayed_status); - (void) pthread_mutex_destroy(&LOCK_delayed_create); + mysql_mutex_destroy(&LOCK_delayed_insert); + mysql_mutex_destroy(&LOCK_delayed_status); + mysql_mutex_destroy(&LOCK_delayed_create); (void) pthread_mutex_destroy(&LOCK_manager); (void) pthread_mutex_destroy(&LOCK_crypt); (void) pthread_mutex_destroy(&LOCK_user_conn); @@ -1448,7 +1451,7 @@ static void clean_up_mutexes() (void) pthread_mutex_destroy(&LOCK_prepared_stmt_count); (void) pthread_mutex_destroy(&LOCK_error_messages); (void) pthread_cond_destroy(&COND_thread_count); - (void) pthread_cond_destroy(&COND_refresh); + mysql_cond_destroy(&COND_refresh); (void) pthread_cond_destroy(&COND_global_read_lock); (void) pthread_cond_destroy(&COND_thread_cache); (void) pthread_cond_destroy(&COND_flush_thread_cache); @@ -3591,16 +3594,20 @@ You should consider changing lower_case_table_names to 1 or 2", static int init_thread_environment() { - (void) pthread_mutex_init(&LOCK_mysql_create_db,MY_MUTEX_INIT_SLOW); - (void) pthread_mutex_init(&LOCK_lock_db,MY_MUTEX_INIT_SLOW); - (void) pthread_mutex_init(&LOCK_open, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_mysql_create_db, + &LOCK_mysql_create_db, MY_MUTEX_INIT_SLOW); + mysql_mutex_init(key_LOCK_lock_db, &LOCK_lock_db, MY_MUTEX_INIT_SLOW); + mysql_mutex_init(key_LOCK_open, &LOCK_open, MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_thread_count,MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_mapped_file,MY_MUTEX_INIT_SLOW); - (void) pthread_mutex_init(&LOCK_status,MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_status, &LOCK_status, MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_error_log,MY_MUTEX_INIT_FAST); - (void) pthread_mutex_init(&LOCK_delayed_insert,MY_MUTEX_INIT_FAST); - (void) pthread_mutex_init(&LOCK_delayed_status,MY_MUTEX_INIT_FAST); - (void) pthread_mutex_init(&LOCK_delayed_create,MY_MUTEX_INIT_SLOW); + mysql_mutex_init(key_LOCK_deleyed_insert, + &LOCK_delayed_insert, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_delayed_status, + &LOCK_delayed_status, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_delayed_create, + &LOCK_delayed_create, MY_MUTEX_INIT_SLOW); (void) pthread_mutex_init(&LOCK_manager,MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_crypt,MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_user_conn, MY_MUTEX_INIT_FAST); @@ -3630,7 +3637,7 @@ static int init_thread_environment() (void) my_rwlock_init(&LOCK_sys_init_slave, NULL); (void) my_rwlock_init(&LOCK_grant, NULL); (void) pthread_cond_init(&COND_thread_count,NULL); - (void) pthread_cond_init(&COND_refresh,NULL); + mysql_cond_init(key_COND_refresh, &COND_refresh, NULL); (void) pthread_cond_init(&COND_global_read_lock,NULL); (void) pthread_cond_init(&COND_thread_cache,NULL); (void) pthread_cond_init(&COND_flush_thread_cache,NULL); @@ -8896,7 +8903,7 @@ static void create_pid_file() /** Clear most status variables. */ void refresh_status(THD *thd) { - pthread_mutex_lock(&LOCK_status); + mysql_mutex_lock(&LOCK_status); /* Add thread's status variabes to global status */ add_to_status(&global_status_var, &thd->status_var); @@ -8910,7 +8917,7 @@ void refresh_status(THD *thd) /* Reset the counters of all key caches (default and named). */ process_key_caches(reset_key_cache_counters); flush_status_time= time((time_t*) 0); - pthread_mutex_unlock(&LOCK_status); + mysql_mutex_unlock(&LOCK_status); /* Set max_used_connections to the number of currently open diff --git a/sql/replication.h b/sql/replication.h index eea77ef9f8e..5e9c09adf31 100644 --- a/sql/replication.h +++ b/sql/replication.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2008 MySQL AB +/* Copyright (C) 2008 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -470,8 +470,8 @@ MYSQL *rpl_connect_master(MYSQL *mysql); held before call this function @param msg The new process message for the thread */ -const char* thd_enter_cond(MYSQL_THD thd, pthread_cond_t *cond, - pthread_mutex_t *mutex, const char *msg); +const char* thd_enter_cond(MYSQL_THD thd, mysql_cond_t *cond, + mysql_mutex_t *mutex, const char *msg); /** Set thread leaving a condition diff --git a/sql/sp_cache.cc b/sql/sp_cache.cc index d9a23d2be4e..e1f2bb1c95b 100644 --- a/sql/sp_cache.cc +++ b/sql/sp_cache.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2002 MySQL AB +/* Copyright (C) 2002 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,7 +20,7 @@ #include "sp_cache.h" #include "sp_head.h" -static pthread_mutex_t Cversion_lock; +static mysql_mutex_t Cversion_lock; static ulong volatile Cversion= 0; @@ -75,12 +75,36 @@ private: HASH m_hashtable; }; // class sp_cache +#ifdef HAVE_PSI_INTERFACE +static PSI_mutex_key key_Cversion_lock; + +static PSI_mutex_info all_sp_cache_mutexes[]= +{ + { &key_Cversion_lock, "Cversion_lock", PSI_FLAG_GLOBAL} +}; + +static void init_sp_cache_psi_keys(void) +{ + const char* category= "sql"; + int count; + + if (PSI_server == NULL) + return; + + count= array_elements(all_sp_cache_mutexes); + PSI_server->register_mutex(category, all_sp_cache_mutexes, count); +} +#endif /* Initialize the SP caching once at startup */ void sp_cache_init() { - pthread_mutex_init(&Cversion_lock, MY_MUTEX_INIT_FAST); +#ifdef HAVE_PSI_INTERFACE + init_sp_cache_psi_keys(); +#endif + + mysql_mutex_init(key_Cversion_lock, &Cversion_lock, MY_MUTEX_INIT_FAST); } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 4a8dd135879..3fd0e6a2376 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -566,7 +566,7 @@ void release_table_share(TABLE_SHARE *share, enum release_type type) (ulong) share, share->db.str, share->table_name.str, share->ref_count, share->version)); - safe_mutex_assert_owner(&LOCK_open); + mysql_mutex_assert_owner(&LOCK_open); pthread_mutex_lock(&share->mutex); if (!--share->ref_count) @@ -619,7 +619,7 @@ TABLE_SHARE *get_cached_table_share(const char *db, const char *table_name) char key[NAME_LEN*2+2]; TABLE_LIST table_list; uint key_length; - safe_mutex_assert_owner(&LOCK_open); + mysql_mutex_assert_owner(&LOCK_open); table_list.db= (char*) db; table_list.table_name= (char*) table_name; @@ -714,7 +714,7 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *db, const char *wild) TABLE_LIST table_list; DBUG_ENTER("list_open_tables"); - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); bzero((char*) &table_list,sizeof(table_list)); start_list= &open_list; open_list=0; @@ -767,7 +767,7 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *db, const char *wild) start_list= &(*start_list)->next; *start_list=0; } - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(open_list); } @@ -864,7 +864,7 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock, DBUG_ASSERT(thd || (!wait_for_refresh && !tables)); if (!have_lock) - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); if (!tables) { refresh_version++; // Force close of open tables @@ -994,7 +994,7 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock, { found=1; DBUG_PRINT("signal", ("Waiting for COND_refresh")); - pthread_cond_wait(&COND_refresh,&LOCK_open); + mysql_cond_wait(&COND_refresh, &LOCK_open); break; } } @@ -1019,14 +1019,14 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock, } } if (!have_lock) - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); if (wait_for_refresh) { - pthread_mutex_lock(&thd->mysys_var->mutex); + mysql_mutex_lock(&thd->mysys_var->mutex); thd->mysys_var->current_mutex= 0; thd->mysys_var->current_cond= 0; thd_proc_info(thd, 0); - pthread_mutex_unlock(&thd->mysys_var->mutex); + mysql_mutex_unlock(&thd->mysys_var->mutex); } DBUG_RETURN(result); } @@ -1049,7 +1049,7 @@ bool close_cached_connection_tables(THD *thd, bool if_wait_for_refresh, bzero(&tmp, sizeof(TABLE_LIST)); if (!have_lock) - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); for (idx= 0; idx < table_def_cache.records; idx++) { @@ -1082,15 +1082,15 @@ bool close_cached_connection_tables(THD *thd, bool if_wait_for_refresh, result= close_cached_tables(thd, tables, TRUE, FALSE, FALSE); if (!have_lock) - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); if (if_wait_for_refresh) { - pthread_mutex_lock(&thd->mysys_var->mutex); + mysql_mutex_lock(&thd->mysys_var->mutex); thd->mysys_var->current_mutex= 0; thd->mysys_var->current_cond= 0; thd->proc_info=0; - pthread_mutex_unlock(&thd->mysys_var->mutex); + mysql_mutex_unlock(&thd->mysys_var->mutex); } DBUG_RETURN(result); @@ -1197,9 +1197,9 @@ static void close_open_tables(THD *thd) { bool found_old_table= 0; - safe_mutex_assert_not_owner(&LOCK_open); + mysql_mutex_assert_not_owner(&LOCK_open); - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); DBUG_PRINT("info", ("thd->open_tables: 0x%lx", (long) thd->open_tables)); @@ -1217,7 +1217,7 @@ static void close_open_tables(THD *thd) broadcast_refresh(); } - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } @@ -2094,7 +2094,7 @@ void unlink_open_table(THD *thd, TABLE *find, bool unlock) TABLE *list, **prev; DBUG_ENTER("unlink_open_table"); - safe_mutex_assert_owner(&LOCK_open); + mysql_mutex_assert_owner(&LOCK_open); memcpy(key, find->s->table_cache_key.str, key_length); /* @@ -2163,14 +2163,14 @@ void drop_open_table(THD *thd, TABLE *table, const char *db_name, else { handlerton *table_type= table->s->db_type(); - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); /* unlink_open_table() also tells threads waiting for refresh or close that something has happened. */ unlink_open_table(thd, table, FALSE); quick_rm_table(table_type, db_name, table_name, 0); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } } @@ -2186,7 +2186,7 @@ void drop_open_table(THD *thd, TABLE *table, const char *db_name, cond Condition to wait for */ -void wait_for_condition(THD *thd, pthread_mutex_t *mutex, pthread_cond_t *cond) +void wait_for_condition(THD *thd, mysql_mutex_t *mutex, mysql_cond_t *cond) { /* Wait until the current table is up to date */ const char *proc_info; @@ -2196,7 +2196,7 @@ void wait_for_condition(THD *thd, pthread_mutex_t *mutex, pthread_cond_t *cond) thd_proc_info(thd, "Waiting for table"); DBUG_ENTER("wait_for_condition"); if (!thd->killed) - (void) pthread_cond_wait(cond, mutex); + mysql_cond_wait(cond, mutex); /* We must unlock mutex first to avoid deadlock becasue conditions are @@ -2209,12 +2209,12 @@ void wait_for_condition(THD *thd, pthread_mutex_t *mutex, pthread_cond_t *cond) mutex is unlocked */ - pthread_mutex_unlock(mutex); - pthread_mutex_lock(&thd->mysys_var->mutex); + mysql_mutex_unlock(mutex); + mysql_mutex_lock(&thd->mysys_var->mutex); thd->mysys_var->current_mutex= 0; thd->mysys_var->current_cond= 0; thd_proc_info(thd, proc_info); - pthread_mutex_unlock(&thd->mysys_var->mutex); + mysql_mutex_unlock(&thd->mysys_var->mutex); DBUG_VOID_RETURN; } @@ -2285,7 +2285,7 @@ bool reopen_name_locked_table(THD* thd, TABLE_LIST* table_list, bool link_in) TABLE orig_table; DBUG_ENTER("reopen_name_locked_table"); - safe_mutex_assert_owner(&LOCK_open); + mysql_mutex_assert_owner(&LOCK_open); if (thd->killed || !table) DBUG_RETURN(TRUE); @@ -2365,7 +2365,7 @@ TABLE *table_cache_insert_placeholder(THD *thd, const char *key, char *key_buff; DBUG_ENTER("table_cache_insert_placeholder"); - safe_mutex_assert_owner(&LOCK_open); + mysql_mutex_assert_owner(&LOCK_open); /* Create a table entry with the right key and with an old refresh version @@ -2425,24 +2425,24 @@ bool lock_table_name_if_not_cached(THD *thd, const char *db, DBUG_ENTER("lock_table_name_if_not_cached"); key_length= (uint)(strmov(strmov(key, db) + 1, table_name) - key) + 1; - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); if (my_hash_search(&open_cache, (uchar *)key, key_length)) { - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); DBUG_PRINT("info", ("Table is cached, name-lock is not obtained")); *table= 0; DBUG_RETURN(FALSE); } if (!(*table= table_cache_insert_placeholder(thd, key, key_length))) { - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(TRUE); } (*table)->open_placeholder= 1; (*table)->next= thd->open_tables; thd->open_tables= *table; - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(FALSE); } @@ -2474,7 +2474,7 @@ bool check_if_table_exists(THD *thd, TABLE_LIST *table, bool *exists) int rc; DBUG_ENTER("check_if_table_exists"); - safe_mutex_assert_owner(&LOCK_open); + mysql_mutex_assert_owner(&LOCK_open); *exists= TRUE; @@ -2699,15 +2699,15 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, */ TABLE tab; table= &tab; - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); if (!open_unireg_entry(thd, table, table_list, alias, key, key_length, mem_root, 0)) { DBUG_ASSERT(table_list->view != 0); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(0); // VIEW } - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } } /* @@ -2740,7 +2740,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, on disk. */ - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); /* If it's the first table from a list of tables used in a query, @@ -2758,7 +2758,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, /* Someone did a refresh while thread was opening tables */ if (refresh) *refresh=1; - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(0); } @@ -2824,7 +2824,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, /* Avoid self-deadlocks by detecting self-dependencies. */ if (table->open_placeholder && table->in_use == thd) { - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); my_error(ER_UPDATE_TABLE_USED, MYF(0), table->s->table_name.str); DBUG_RETURN(0); } @@ -2865,7 +2865,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, } else { - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } /* There is a refresh in progress for this table. @@ -2906,7 +2906,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, if (check_if_table_exists(thd, table_list, &exists)) { - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(NULL); } @@ -2917,7 +2917,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, */ if (!(table= table_cache_insert_placeholder(thd, key, key_length))) { - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(NULL); } /* @@ -2928,7 +2928,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, table->open_placeholder= 1; table->next= thd->open_tables; thd->open_tables= table; - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(table); } /* Table exists. Let us try to open it. */ @@ -2937,7 +2937,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, /* make a new table */ if (!(table=(TABLE*) my_malloc(sizeof(*table),MYF(MY_WME)))) { - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(NULL); } @@ -2946,7 +2946,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, if (error > 0) { my_free((uchar*)table, MYF(0)); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(NULL); } if (table_list->view || error < 0) @@ -2959,7 +2959,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, table_list->view= (LEX*)1; my_free((uchar*)table, MYF(0)); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(0); // VIEW } DBUG_PRINT("info", ("inserting table '%s'.'%s' 0x%lx into the cache", @@ -2970,7 +2970,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, check_unused(); // Debugging call - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); if (refresh) { table->next=thd->open_tables; /* Link into simple list */ @@ -3174,7 +3174,7 @@ void close_data_files_and_morph_locks(THD *thd, const char *db, TABLE *table; DBUG_ENTER("close_data_files_and_morph_locks"); - safe_mutex_assert_owner(&LOCK_open); + mysql_mutex_assert_owner(&LOCK_open); if (thd->lock) { @@ -3313,7 +3313,7 @@ bool reopen_tables(THD *thd, bool get_locks, bool mark_share_as_old) if (!thd->open_tables) DBUG_RETURN(0); - safe_mutex_assert_owner(&LOCK_open); + mysql_mutex_assert_owner(&LOCK_open); if (get_locks) { /* @@ -3576,7 +3576,7 @@ bool wait_for_tables(THD *thd) DBUG_ENTER("wait_for_tables"); thd_proc_info(thd, "Waiting for tables"); - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); while (!thd->killed) { thd->some_tables_deleted=0; @@ -3584,7 +3584,7 @@ bool wait_for_tables(THD *thd) mysql_ha_flush(thd); if (!table_is_used(thd->open_tables,1)) break; - (void) pthread_cond_wait(&COND_refresh,&LOCK_open); + mysql_cond_wait(&COND_refresh, &LOCK_open); } if (thd->killed) result= 1; // aborted @@ -3595,7 +3595,7 @@ bool wait_for_tables(THD *thd) thd->version= refresh_version; result=reopen_tables(thd,0,0); } - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); thd_proc_info(thd, 0); DBUG_RETURN(result); } @@ -3748,7 +3748,7 @@ void assign_new_table_id(TABLE_SHARE *share) /* Preconditions */ DBUG_ASSERT(share != NULL); - safe_mutex_assert_owner(&LOCK_open); + mysql_mutex_assert_owner(&LOCK_open); ulong tid= ++last_table_id; /* get next id */ /* @@ -3872,7 +3872,7 @@ static int open_unireg_entry(THD *thd, TABLE *entry, TABLE_LIST *table_list, uint discover_retry_count= 0; DBUG_ENTER("open_unireg_entry"); - safe_mutex_assert_owner(&LOCK_open); + mysql_mutex_assert_owner(&LOCK_open); retry: if (!(share= get_table_share_with_create(thd, table_list, cache_key, cache_key_length, @@ -4001,7 +4001,7 @@ retry: goto err; } } - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); thd->clear_error(); // Clear error message error= 0; if (open_table_from_share(thd, share, alias, @@ -4024,7 +4024,7 @@ retry: } else thd->clear_error(); // Clear error message - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); unlock_table_name(thd, table_list); if (error) @@ -8430,10 +8430,10 @@ void remove_db_from_cache(const char *db) void flush_tables() { - (void) pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); while (unused_tables) my_hash_delete(&open_cache,(uchar*) unused_tables); - (void) pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } @@ -8504,15 +8504,15 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name, ! in_use->killed) { in_use->killed= THD::KILL_CONNECTION; - pthread_mutex_lock(&in_use->mysys_var->mutex); + mysql_mutex_lock(&in_use->mysys_var->mutex); if (in_use->mysys_var->current_cond) { - pthread_mutex_lock(in_use->mysys_var->current_mutex); + mysql_mutex_lock(in_use->mysys_var->current_mutex); signalled= 1; - pthread_cond_broadcast(in_use->mysys_var->current_cond); - pthread_mutex_unlock(in_use->mysys_var->current_mutex); + mysql_cond_broadcast(in_use->mysys_var->current_cond); + mysql_mutex_unlock(in_use->mysys_var->current_mutex); } - pthread_mutex_unlock(&in_use->mysys_var->mutex); + mysql_mutex_unlock(&in_use->mysys_var->mutex); } /* Now we must abort all tables locks used by this thread @@ -8569,7 +8569,7 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name, { dropping_tables++; if (likely(signalled)) - (void) pthread_cond_wait(&COND_refresh, &LOCK_open); + mysql_cond_wait(&COND_refresh, &LOCK_open); else { struct timespec abstime; @@ -8584,7 +8584,7 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name, remove_table_from_cache routine. */ set_timespec(abstime, 10); - pthread_cond_timedwait(&COND_refresh, &LOCK_open, &abstime); + mysql_cond_timedwait(&COND_refresh, &LOCK_open, &abstime); } dropping_tables--; continue; @@ -8730,12 +8730,12 @@ int abort_and_upgrade_lock(ALTER_PARTITION_PARAM_TYPE *lpt) DBUG_ENTER("abort_and_upgrade_locks"); lpt->old_lock_type= lpt->table->reginfo.lock_type; - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); /* If MERGE child, forward lock handling to parent. */ mysql_lock_abort(lpt->thd, lpt->table->parent ? lpt->table->parent : lpt->table, TRUE); (void) remove_table_from_cache(lpt->thd, lpt->db, lpt->table_name, flags); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(0); } @@ -8757,10 +8757,10 @@ int abort_and_upgrade_lock(ALTER_PARTITION_PARAM_TYPE *lpt) /* purecov: begin deadcode */ void close_open_tables_and_downgrade(ALTER_PARTITION_PARAM_TYPE *lpt) { - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); remove_table_from_cache(lpt->thd, lpt->db, lpt->table_name, RTFC_WAIT_OTHER_THREAD_FLAG); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); /* If MERGE child, forward lock handling to parent. */ mysql_lock_downgrade_write(lpt->thd, lpt->table->parent ? lpt->table->parent : lpt->table, lpt->old_lock_type); @@ -8799,7 +8799,7 @@ void mysql_wait_completed_table(ALTER_PARTITION_PARAM_TYPE *lpt, TABLE *my_table DBUG_ENTER("mysql_wait_completed_table"); key_length=(uint) (strmov(strmov(key,lpt->db)+1,lpt->table_name)-key)+1; - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); HASH_SEARCH_STATE state; for (table= (TABLE*) my_hash_first(&open_cache,(uchar*) key,key_length, &state) ; @@ -8820,14 +8820,14 @@ void mysql_wait_completed_table(ALTER_PARTITION_PARAM_TYPE *lpt, TABLE *my_table ! in_use->killed) { in_use->killed= THD::KILL_CONNECTION; - pthread_mutex_lock(&in_use->mysys_var->mutex); + mysql_mutex_lock(&in_use->mysys_var->mutex); if (in_use->mysys_var->current_cond) { - pthread_mutex_lock(in_use->mysys_var->current_mutex); - pthread_cond_broadcast(in_use->mysys_var->current_cond); - pthread_mutex_unlock(in_use->mysys_var->current_mutex); + mysql_mutex_lock(in_use->mysys_var->current_mutex); + mysql_cond_broadcast(in_use->mysys_var->current_cond); + mysql_mutex_unlock(in_use->mysys_var->current_mutex); } - pthread_mutex_unlock(&in_use->mysys_var->mutex); + mysql_mutex_unlock(&in_use->mysys_var->mutex); } /* Now we must abort all tables locks used by this thread @@ -8857,7 +8857,7 @@ void mysql_wait_completed_table(ALTER_PARTITION_PARAM_TYPE *lpt, TABLE *my_table */ mysql_lock_abort(lpt->thd, my_table->parent ? my_table->parent : my_table, FALSE); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); DBUG_VOID_RETURN; } @@ -9096,7 +9096,7 @@ void close_performance_schema_table(THD *thd, Open_tables_state *backup) mysql_unlock_tables(thd, thd->lock); thd->lock= 0; - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); found_old_table= false; /* @@ -9112,7 +9112,7 @@ void close_performance_schema_table(THD *thd, Open_tables_state *backup) if (found_old_table) broadcast_refresh(); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); thd->restore_backup_open_tables_state(backup); } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index b7d88eca89a..2d1722267d9 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -957,9 +957,9 @@ void THD::init_for_queries() void THD::change_user(void) { - pthread_mutex_lock(&LOCK_status); + mysql_mutex_lock(&LOCK_status); add_to_status(&global_status_var, &status_var); - pthread_mutex_unlock(&LOCK_status); + mysql_mutex_unlock(&LOCK_status); cleanup(); killed= NOT_KILLED; @@ -1018,9 +1018,9 @@ void THD::cleanup(void) unlock_global_read_lock(this); if (ull) { - pthread_mutex_lock(&LOCK_user_locks); + mysql_mutex_lock(&LOCK_user_locks); item_user_lock_release(ull); - pthread_mutex_unlock(&LOCK_user_locks); + mysql_mutex_unlock(&LOCK_user_locks); ull= NULL; } @@ -1159,7 +1159,7 @@ void THD::awake(THD::killed_state state_to_set) } if (mysys_var) { - pthread_mutex_lock(&mysys_var->mutex); + mysql_mutex_lock(&mysys_var->mutex); if (!system_thread) // Don't abort locks mysys_var->abort=1; /* @@ -1183,11 +1183,11 @@ void THD::awake(THD::killed_state state_to_set) */ if (mysys_var->current_cond && mysys_var->current_mutex) { - pthread_mutex_lock(mysys_var->current_mutex); - pthread_cond_broadcast(mysys_var->current_cond); - pthread_mutex_unlock(mysys_var->current_mutex); + mysql_mutex_lock(mysys_var->current_mutex); + mysql_cond_broadcast(mysys_var->current_cond); + mysql_mutex_unlock(mysys_var->current_mutex); } - pthread_mutex_unlock(&mysys_var->mutex); + mysql_mutex_unlock(&mysys_var->mutex); } DBUG_VOID_RETURN; } diff --git a/sql/sql_class.h b/sql/sql_class.h index ed8b995fc96..b90d69e712e 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1874,21 +1874,21 @@ public: enter_cond(); this mutex is then released by exit_cond(). Usage must be: lock mutex; enter_cond(); your code; exit_cond(). */ - inline const char* enter_cond(pthread_cond_t *cond, pthread_mutex_t* mutex, - const char* msg) + inline const char* enter_cond(mysql_cond_t *cond, mysql_mutex_t* mutex, + const char* msg) { const char* old_msg = proc_info; - safe_mutex_assert_owner(mutex); + mysql_mutex_assert_owner(mutex); mysys_var->current_mutex = mutex; mysys_var->current_cond = cond; proc_info = msg; return old_msg; } - inline const char* enter_cond(mysql_cond_t *cond, mysql_mutex_t *mutex, + inline const char* enter_cond(pthread_cond_t *cond, pthread_mutex_t *mutex, const char *msg) { /* TO BE REMOVED: temporary helper, to help with merges */ - return enter_cond(&cond->m_cond, &mutex->m_mutex, msg); + return enter_cond((mysql_cond_t*) cond, (mysql_mutex_t*) mutex, msg); } inline void exit_cond(const char* old_msg) { @@ -1898,12 +1898,12 @@ public: locked (if that would not be the case, you'll get a deadlock if someone does a THD::awake() on you). */ - pthread_mutex_unlock(mysys_var->current_mutex); - pthread_mutex_lock(&mysys_var->mutex); + mysql_mutex_unlock(mysys_var->current_mutex); + mysql_mutex_lock(&mysys_var->mutex); mysys_var->current_mutex = 0; mysys_var->current_cond = 0; proc_info = old_msg; - pthread_mutex_unlock(&mysys_var->mutex); + mysql_mutex_unlock(&mysys_var->mutex); return; } inline time_t query_start() { query_start_used=1; return start_time; } diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 17626f05aa1..eb2e3915177 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright (C) 2000-2003 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -47,7 +47,7 @@ static void mysql_change_db_impl(THD *thd, /* Database lock hash */ HASH lock_db_cache; -pthread_mutex_t LOCK_lock_db; +mysql_mutex_t LOCK_lock_db; int creating_database= 0; // how many database locks are made @@ -103,7 +103,7 @@ static my_bool lock_db_insert(const char *dbname, uint length) my_bool error= 0; DBUG_ENTER("lock_db_insert"); - safe_mutex_assert_owner(&LOCK_lock_db); + mysql_mutex_assert_owner(&LOCK_lock_db); if (!(opt= (my_dblock_t*) my_hash_search(&lock_db_cache, (uchar*) dbname, length))) @@ -138,7 +138,7 @@ end: void lock_db_delete(const char *name, uint length) { my_dblock_t *opt; - safe_mutex_assert_owner(&LOCK_lock_db); + mysql_mutex_assert_owner(&LOCK_lock_db); if ((opt= (my_dblock_t *)my_hash_search(&lock_db_cache, (const uchar*) name, length))) my_hash_delete(&lock_db_cache, (uchar*) opt); @@ -148,7 +148,7 @@ void lock_db_delete(const char *name, uint length) /* Database options hash */ static HASH dboptions; static my_bool dboptions_init= 0; -static rw_lock_t LOCK_dboptions; +static mysql_rwlock_t LOCK_dboptions; /* Structure for database options */ typedef struct my_dbopt_st @@ -199,6 +199,26 @@ void free_dbopt(void *dbopt) my_free((uchar*) dbopt, MYF(0)); } +#ifdef HAVE_PSI_INTERFACE +static PSI_rwlock_key key_rwlock_LOCK_dboptions; + +static PSI_rwlock_info all_database_names_rwlocks[]= +{ + { &key_rwlock_LOCK_dboptions, "LOCK_dboptions", PSI_FLAG_GLOBAL} +}; + +static void init_database_names_psi_keys(void) +{ + const char* category= "sql"; + int count; + + if (PSI_server == NULL) + return; + + count= array_elements(all_database_names_rwlocks); + PSI_server->register_rwlock(category, all_database_names_rwlocks, count); +} +#endif /* Initialize database option hash and locked database hash. @@ -216,8 +236,12 @@ void free_dbopt(void *dbopt) bool my_database_names_init(void) { +#ifdef HAVE_PSI_INTERFACE + init_database_names_psi_keys(); +#endif + bool error= 0; - (void) my_rwlock_init(&LOCK_dboptions, NULL); + mysql_rwlock_init(key_rwlock_LOCK_dboptions, &LOCK_dboptions); if (!dboptions_init) { dboptions_init= 1; @@ -246,7 +270,7 @@ void my_database_names_free(void) { dboptions_init= 0; my_hash_free(&dboptions); - (void) rwlock_destroy(&LOCK_dboptions); + mysql_rwlock_destroy(&LOCK_dboptions); my_hash_free(&lock_db_cache); } } @@ -258,13 +282,13 @@ void my_database_names_free(void) void my_dbopt_cleanup(void) { - rw_wrlock(&LOCK_dboptions); + mysql_rwlock_wrlock(&LOCK_dboptions); my_hash_free(&dboptions); my_hash_init(&dboptions, lower_case_table_names ? &my_charset_bin : system_charset_info, 32, 0, 0, (my_hash_get_key) dboptions_get_key, free_dbopt,0); - rw_unlock(&LOCK_dboptions); + mysql_rwlock_unlock(&LOCK_dboptions); } @@ -288,13 +312,13 @@ static my_bool get_dbopt(const char *dbname, HA_CREATE_INFO *create) length= (uint) strlen(dbname); - rw_rdlock(&LOCK_dboptions); + mysql_rwlock_rdlock(&LOCK_dboptions); if ((opt= (my_dbopt_t*) my_hash_search(&dboptions, (uchar*) dbname, length))) { create->default_table_charset= opt->charset; error= 0; } - rw_unlock(&LOCK_dboptions); + mysql_rwlock_unlock(&LOCK_dboptions); return error; } @@ -320,7 +344,7 @@ static my_bool put_dbopt(const char *dbname, HA_CREATE_INFO *create) length= (uint) strlen(dbname); - rw_wrlock(&LOCK_dboptions); + mysql_rwlock_wrlock(&LOCK_dboptions); if (!(opt= (my_dbopt_t*) my_hash_search(&dboptions, (uchar*) dbname, length))) { @@ -349,7 +373,7 @@ static my_bool put_dbopt(const char *dbname, HA_CREATE_INFO *create) opt->charset= create->default_table_charset; end: - rw_unlock(&LOCK_dboptions); + mysql_rwlock_unlock(&LOCK_dboptions); DBUG_RETURN(error); } @@ -361,11 +385,11 @@ end: void del_dbopt(const char *path) { my_dbopt_t *opt; - rw_wrlock(&LOCK_dboptions); + mysql_rwlock_wrlock(&LOCK_dboptions); if ((opt= (my_dbopt_t *)my_hash_search(&dboptions, (const uchar*) path, strlen(path)))) my_hash_delete(&dboptions, (uchar*) opt); - rw_unlock(&LOCK_dboptions); + mysql_rwlock_unlock(&LOCK_dboptions); } @@ -392,7 +416,8 @@ static bool write_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create) if (put_dbopt(path, create)) return 1; - if ((file=my_create(path, CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0) + if ((file= mysql_file_create(key_file_dbopt, path, CREATE_MODE, + O_RDWR | O_TRUNC, MYF(MY_WME))) >= 0) { ulong length; length= (ulong) (strxnmov(buf, sizeof(buf)-1, "default-character-set=", @@ -401,10 +426,10 @@ static bool write_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create) create->default_table_charset->name, "\n", NullS) - buf); - /* Error is written by my_write */ - if (!my_write(file,(uchar*) buf, length, MYF(MY_NABP+MY_WME))) + /* Error is written by mysql_file_write */ + if (!mysql_file_write(file, (uchar*) buf, length, MYF(MY_NABP+MY_WME))) error=0; - my_close(file,MYF(0)); + mysql_file_close(file, MYF(0)); } return error; } @@ -441,7 +466,8 @@ bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create) DBUG_RETURN(0); /* Otherwise, load options from the .opt file */ - if ((file=my_open(path, O_RDONLY | O_SHARE, MYF(0))) < 0) + if ((file= mysql_file_open(key_file_dbopt, + path, O_RDONLY | O_SHARE, MYF(0))) < 0) goto err1; IO_CACHE cache; @@ -499,7 +525,7 @@ bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create) end_io_cache(&cache); err2: - my_close(file,MYF(0)); + mysql_file_close(file, MYF(0)); err1: DBUG_RETURN(error); } @@ -643,13 +669,13 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, goto exit2; } - pthread_mutex_lock(&LOCK_mysql_create_db); + mysql_mutex_lock(&LOCK_mysql_create_db); /* Check directory */ path_len= build_table_filename(path, sizeof(path) - 1, db, "", "", 0); path[path_len-1]= 0; // Remove last '/' from path - if (my_stat(path,&stat_info,MYF(0))) + if (mysql_file_stat(key_file_misc, path, &stat_info, MYF(0))) { if (!(create_options & HA_LEX_CREATE_IF_NOT_EXISTS)) { @@ -753,7 +779,7 @@ not_silent: } exit: - pthread_mutex_unlock(&LOCK_mysql_create_db); + mysql_mutex_unlock(&LOCK_mysql_create_db); start_waiting_global_read_lock(thd); exit2: DBUG_RETURN(error); @@ -784,7 +810,7 @@ bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info) if ((error=wait_if_global_read_lock(thd,0,1))) goto exit2; - pthread_mutex_lock(&LOCK_mysql_create_db); + mysql_mutex_lock(&LOCK_mysql_create_db); /* Recreate db options file: /dbpath/.db.opt @@ -830,7 +856,7 @@ bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info) my_ok(thd, result); exit: - pthread_mutex_unlock(&LOCK_mysql_create_db); + mysql_mutex_unlock(&LOCK_mysql_create_db); start_waiting_global_read_lock(thd); exit2: DBUG_RETURN(error); @@ -882,7 +908,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) goto exit2; } - pthread_mutex_lock(&LOCK_mysql_create_db); + mysql_mutex_lock(&LOCK_mysql_create_db); length= build_table_filename(path, sizeof(path) - 1, db, "", "", 0); strmov(path+length, MY_DB_OPT_FILE); // Append db option file name @@ -904,9 +930,9 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) } else { - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); remove_db_from_cache(db); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); Drop_table_error_handler err_handler(thd->get_internal_handler()); thd->push_internal_handler(&err_handler); @@ -1030,7 +1056,7 @@ exit: */ if (thd->db && !strcmp(thd->db, db) && error == 0) mysql_change_db_impl(thd, NULL, 0, thd->variables.collation_server); - pthread_mutex_unlock(&LOCK_mysql_create_db); + mysql_mutex_unlock(&LOCK_mysql_create_db); start_waiting_global_read_lock(thd); exit2: DBUG_RETURN(error); @@ -1156,7 +1182,7 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, else { strxmov(filePath, org_path, "/", file->name, NullS); - if (my_delete_with_symlink(filePath,MYF(MY_WME))) + if (mysql_file_delete_with_symlink(key_file_misc, filePath, MYF(MY_WME))) { goto err; } @@ -1234,7 +1260,7 @@ static my_bool rm_dir_w_symlink(const char *org_path, my_bool send_error) DBUG_RETURN(1); if (!error) { - if (my_delete(path, MYF(send_error ? MY_WME : 0))) + if (mysql_file_delete(key_file_misc, path, MYF(send_error ? MY_WME : 0))) { DBUG_RETURN(send_error); } @@ -1311,7 +1337,7 @@ long mysql_rm_arc_files(THD *thd, MY_DIR *dirp, const char *org_path) continue; } strxmov(filePath, org_path, "/", file->name, NullS); - if (my_delete_with_symlink(filePath,MYF(MY_WME))) + if (mysql_file_delete_with_symlink(key_file_misc, filePath, MYF(MY_WME))) { goto err; } @@ -1718,18 +1744,18 @@ static int lock_databases(THD *thd, const char *db1, uint length1, const char *db2, uint length2) { - pthread_mutex_lock(&LOCK_lock_db); + mysql_mutex_lock(&LOCK_lock_db); while (!thd->killed && (my_hash_search(&lock_db_cache,(uchar*) db1, length1) || my_hash_search(&lock_db_cache,(uchar*) db2, length2))) { wait_for_condition(thd, &LOCK_lock_db, &COND_refresh); - pthread_mutex_lock(&LOCK_lock_db); + mysql_mutex_lock(&LOCK_lock_db); } if (thd->killed) { - pthread_mutex_unlock(&LOCK_lock_db); + mysql_mutex_unlock(&LOCK_lock_db); return 1; } @@ -1746,7 +1772,7 @@ lock_databases(THD *thd, const char *db1, uint length1, while (!thd->killed && creating_table) { wait_for_condition(thd, &LOCK_lock_db, &COND_refresh); - pthread_mutex_lock(&LOCK_lock_db); + mysql_mutex_lock(&LOCK_lock_db); } if (thd->killed) @@ -1754,8 +1780,8 @@ lock_databases(THD *thd, const char *db1, uint length1, lock_db_delete(db1, length1); lock_db_delete(db2, length2); creating_database--; - pthread_mutex_unlock(&LOCK_lock_db); - pthread_cond_signal(&COND_refresh); + mysql_mutex_unlock(&LOCK_lock_db); + mysql_cond_signal(&COND_refresh); return(1); } @@ -1763,7 +1789,7 @@ lock_databases(THD *thd, const char *db1, uint length1, We can unlock now as the hash will protect against anyone creating a table in the databases we are using */ - pthread_mutex_unlock(&LOCK_lock_db); + mysql_mutex_unlock(&LOCK_lock_db); return 0; } @@ -1892,7 +1918,7 @@ bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db) */ build_table_filename(path, sizeof(path)-1, new_db.str,"",MY_DB_OPT_FILE, 0); - my_delete(path, MYF(MY_WME)); + mysql_file_delete(key_file_dbopt, path, MYF(MY_WME)); length= build_table_filename(path, sizeof(path)-1, new_db.str, "", "", 0); if (length && path[length-1] == FN_LIBCHAR) path[length-1]=0; // remove ending '\' @@ -1948,7 +1974,7 @@ bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db) old_db->str, "", file->name, 0); build_table_filename(newname, sizeof(newname)-1, new_db.str, "", file->name, 0); - my_rename(oldname, newname, MYF(MY_WME)); + mysql_file_rename(key_file_misc, oldname, newname, MYF(MY_WME)); } my_dirend(dirp); } @@ -1976,14 +2002,14 @@ bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db) error|= mysql_change_db(thd, & new_db, FALSE); exit: - pthread_mutex_lock(&LOCK_lock_db); + mysql_mutex_lock(&LOCK_lock_db); /* Remove the databases from db lock cache */ lock_db_delete(old_db->str, old_db->length); lock_db_delete(new_db.str, new_db.length); creating_database--; /* Signal waiting CREATE TABLE's to continue */ - pthread_cond_signal(&COND_refresh); - pthread_mutex_unlock(&LOCK_lock_db); + mysql_cond_signal(&COND_refresh); + mysql_mutex_unlock(&LOCK_lock_db); DBUG_RETURN(error); } diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index d8aa27c9695..17f1036d70e 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -1166,10 +1166,10 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok) // crashes, replacement works. *(path + path_length - reg_ext_length)= // '\0'; path[path_length - reg_ext_length] = 0; - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); error= ha_create_table(thd, path, table_list->db, table_list->table_name, &create_info, 1); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); query_cache_invalidate3(thd, table_list, 0); end: @@ -1184,15 +1184,15 @@ end: write_bin_log(thd, TRUE, thd->query(), thd->query_length()); my_ok(thd); // This should return record count } - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); unlock_table_name(thd, table_list); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } else if (error) { - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); unlock_table_name(thd, table_list); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } DBUG_RETURN(error); diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index da5ee93fcb9..b6c399d9908 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -143,14 +143,14 @@ static void mysql_ha_close_table(THD *thd, TABLE_LIST *tables, { (*table_ptr)->file->ha_index_or_rnd_end(); if (! is_locked) - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); if (close_thread_table(thd, table_ptr)) { /* Tell threads waiting for refresh that something has happened */ broadcast_refresh(); } if (! is_locked) - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } else if (tables->table) { @@ -775,7 +775,7 @@ void mysql_ha_flush(THD *thd) TABLE_LIST *hash_tables; DBUG_ENTER("mysql_ha_flush"); - safe_mutex_assert_owner(&LOCK_open); + mysql_mutex_assert_owner(&LOCK_open); for (uint i= 0; i < thd->handler_tables_hash.records; i++) { diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index efdc8caa3e5..340765c80e0 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1,4 +1,4 @@ -/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. +/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -888,7 +888,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, thd->net.last_error/errno. For example if there has been a disk full error when writing the row, and it was MyISAM, then thd->net.last_error/errno will be set to - "disk full"... and the my_pwrite() will wait until free + "disk full"... and the mysql_file_pwrite() will wait until free space appears, and so when it finishes then the write_row() was entirely successful */ @@ -1730,8 +1730,8 @@ class Delayed_insert :public ilink { public: THD thd; TABLE *table; - pthread_mutex_t mutex; - pthread_cond_t cond,cond_client; + mysql_mutex_t mutex; + mysql_cond_t cond, cond_client; volatile uint tables_in_use,stacked_inserts; volatile bool status,dead; COPY_INFO info; @@ -1763,9 +1763,9 @@ public: thd.system_thread= SYSTEM_THREAD_DELAYED_INSERT; thd.security_ctx->host_or_ip= ""; bzero((char*) &info,sizeof(info)); - pthread_mutex_init(&mutex,MY_MUTEX_INIT_FAST); - pthread_cond_init(&cond,NULL); - pthread_cond_init(&cond_client,NULL); + mysql_mutex_init(key_delayed_insert_mutex, &mutex, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_delayed_insert_cond, &cond, NULL); + mysql_cond_init(key_delayed_insert_cond_client, &cond_client, NULL); pthread_mutex_lock(&LOCK_thread_count); delayed_insert_threads++; delayed_lock= global_system_variables.low_priority_updates ? @@ -1781,9 +1781,9 @@ public: if (table) close_thread_tables(&thd); pthread_mutex_lock(&LOCK_thread_count); - pthread_mutex_destroy(&mutex); - pthread_cond_destroy(&cond); - pthread_cond_destroy(&cond_client); + mysql_mutex_destroy(&mutex); + mysql_cond_destroy(&cond); + mysql_cond_destroy(&cond_client); thd.unlink(); // Must be unlinked under lock x_free(thd.query()); thd.security_ctx->user= thd.security_ctx->host=0; @@ -1800,18 +1800,18 @@ public: } void unlock() { - pthread_mutex_lock(&LOCK_delayed_insert); + mysql_mutex_lock(&LOCK_delayed_insert); if (!--locks_in_memory) { - pthread_mutex_lock(&mutex); + mysql_mutex_lock(&mutex); if (thd.killed && ! stacked_inserts && ! tables_in_use) { - pthread_cond_signal(&cond); + mysql_cond_signal(&cond); status=1; } - pthread_mutex_unlock(&mutex); + mysql_mutex_unlock(&mutex); } - pthread_mutex_unlock(&LOCK_delayed_insert); + mysql_mutex_unlock(&LOCK_delayed_insert); } inline uint lock_count() { return locks_in_memory; } @@ -1832,7 +1832,7 @@ static Delayed_insert *find_handler(THD *thd, TABLE_LIST *table_list) { thd_proc_info(thd, "waiting for delay_list"); - pthread_mutex_lock(&LOCK_delayed_insert); // Protect master list + mysql_mutex_lock(&LOCK_delayed_insert); // Protect master list I_List_iterator it(delayed_threads); Delayed_insert *di; while ((di= it++)) @@ -1844,7 +1844,7 @@ Delayed_insert *find_handler(THD *thd, TABLE_LIST *table_list) break; } } - pthread_mutex_unlock(&LOCK_delayed_insert); // For unlink from list + mysql_mutex_unlock(&LOCK_delayed_insert); // For unlink from list return di; } @@ -1914,7 +1914,7 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list) if (delayed_insert_threads >= thd->variables.max_insert_delayed_threads) DBUG_RETURN(0); thd_proc_info(thd, "Creating delayed handler"); - pthread_mutex_lock(&LOCK_delayed_create); + mysql_mutex_lock(&LOCK_delayed_create); /* The first search above was done without LOCK_delayed_create. Another thread might have created the handler in between. Search again. @@ -1940,14 +1940,15 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list) di->table_list.alias= di->table_list.table_name= di->thd.query(); di->table_list.db= di->thd.db; di->lock(); - pthread_mutex_lock(&di->mutex); - if ((error= pthread_create(&di->thd.real_id, &connection_attrib, - handle_delayed_insert, (void*) di))) + mysql_mutex_lock(&di->mutex); + if ((error= mysql_thread_create(key_thread_delayed_insert, + &di->thd.real_id, &connection_attrib, + handle_delayed_insert, (void*) di))) { DBUG_PRINT("error", ("Can't create thread to handle delayed insert (error %d)", error)); - pthread_mutex_unlock(&di->mutex); + mysql_mutex_unlock(&di->mutex); di->unlock(); delete di; my_error(ER_CANT_CREATE_THREAD, MYF(ME_FATALERROR), error); @@ -1958,9 +1959,9 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list) thd_proc_info(thd, "waiting for handler open"); while (!di->thd.killed && !di->table && !thd->killed) { - pthread_cond_wait(&di->cond_client, &di->mutex); + mysql_cond_wait(&di->cond_client, &di->mutex); } - pthread_mutex_unlock(&di->mutex); + mysql_mutex_unlock(&di->mutex); thd_proc_info(thd, "got old table"); if (di->thd.killed) { @@ -1983,16 +1984,16 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list) di->unlock(); goto end_create; } - pthread_mutex_lock(&LOCK_delayed_insert); + mysql_mutex_lock(&LOCK_delayed_insert); delayed_threads.append(di); - pthread_mutex_unlock(&LOCK_delayed_insert); + mysql_mutex_unlock(&LOCK_delayed_insert); } - pthread_mutex_unlock(&LOCK_delayed_create); + mysql_mutex_unlock(&LOCK_delayed_create); } - pthread_mutex_lock(&di->mutex); + mysql_mutex_lock(&di->mutex); table_list->table= di->get_local_table(thd); - pthread_mutex_unlock(&di->mutex); + mysql_mutex_unlock(&di->mutex); if (table_list->table) { DBUG_ASSERT(! thd->is_error()); @@ -2003,7 +2004,7 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list) DBUG_RETURN((table_list->table == NULL)); end_create: - pthread_mutex_unlock(&LOCK_delayed_create); + mysql_mutex_unlock(&LOCK_delayed_create); DBUG_RETURN(thd->is_error()); } @@ -2039,10 +2040,10 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) if (!thd.lock) // Table is not locked { thd_proc_info(client_thd, "waiting for handler lock"); - pthread_cond_signal(&cond); // Tell handler to lock table + mysql_cond_signal(&cond); // Tell handler to lock table while (!dead && !thd.lock && ! client_thd->killed) { - pthread_cond_wait(&cond_client,&mutex); + mysql_cond_wait(&cond_client, &mutex); } thd_proc_info(client_thd, "got handler lock"); if (client_thd->killed) @@ -2129,7 +2130,7 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) error: tables_in_use--; status=1; - pthread_cond_signal(&cond); // Inform thread about abort + mysql_cond_signal(&cond); // Inform thread about abort DBUG_RETURN(0); } @@ -2148,9 +2149,9 @@ int write_delayed(THD *thd, TABLE *table, enum_duplicates duplic, (ulong) query.length)); thd_proc_info(thd, "waiting for handler insert"); - pthread_mutex_lock(&di->mutex); + mysql_mutex_lock(&di->mutex); while (di->stacked_inserts >= delayed_queue_size && !thd->killed) - pthread_cond_wait(&di->cond_client,&di->mutex); + mysql_cond_wait(&di->cond_client, &di->mutex); thd_proc_info(thd, "storing row into queue"); if (thd->killed) @@ -2225,15 +2226,15 @@ int write_delayed(THD *thd, TABLE *table, enum_duplicates duplic, di->status=1; if (table->s->blob_fields) unlink_blobs(table); - pthread_cond_signal(&di->cond); + mysql_cond_signal(&di->cond); thread_safe_increment(delayed_rows_in_use,&LOCK_delayed_status); - pthread_mutex_unlock(&di->mutex); + mysql_mutex_unlock(&di->mutex); DBUG_RETURN(0); err: delete row; - pthread_mutex_unlock(&di->mutex); + mysql_mutex_unlock(&di->mutex); DBUG_RETURN(1); } @@ -2246,14 +2247,14 @@ static void end_delayed_insert(THD *thd) { DBUG_ENTER("end_delayed_insert"); Delayed_insert *di=thd->di; - pthread_mutex_lock(&di->mutex); + mysql_mutex_lock(&di->mutex); DBUG_PRINT("info",("tables in use: %d",di->tables_in_use)); if (!--di->tables_in_use || di->thd.killed) { // Unlock table di->status=1; - pthread_cond_signal(&di->cond); + mysql_cond_signal(&di->cond); } - pthread_mutex_unlock(&di->mutex); + mysql_mutex_unlock(&di->mutex); DBUG_VOID_RETURN; } @@ -2262,7 +2263,7 @@ static void end_delayed_insert(THD *thd) void kill_delayed_threads(void) { - pthread_mutex_lock(&LOCK_delayed_insert); // For unlink from list + mysql_mutex_lock(&LOCK_delayed_insert); // For unlink from list I_List_iterator it(delayed_threads); Delayed_insert *di; @@ -2271,7 +2272,7 @@ void kill_delayed_threads(void) di->thd.killed= THD::KILL_CONNECTION; if (di->thd.mysys_var) { - pthread_mutex_lock(&di->thd.mysys_var->mutex); + mysql_mutex_lock(&di->thd.mysys_var->mutex); if (di->thd.mysys_var->current_cond) { /* @@ -2279,15 +2280,15 @@ void kill_delayed_threads(void) in handle_delayed_insert() */ if (&di->mutex != di->thd.mysys_var->current_mutex) - pthread_mutex_lock(di->thd.mysys_var->current_mutex); - pthread_cond_broadcast(di->thd.mysys_var->current_cond); + mysql_mutex_lock(di->thd.mysys_var->current_mutex); + mysql_cond_broadcast(di->thd.mysys_var->current_cond); if (&di->mutex != di->thd.mysys_var->current_mutex) - pthread_mutex_unlock(di->thd.mysys_var->current_mutex); + mysql_mutex_unlock(di->thd.mysys_var->current_mutex); } - pthread_mutex_unlock(&di->thd.mysys_var->mutex); + mysql_mutex_unlock(&di->thd.mysys_var->mutex); } } - pthread_mutex_unlock(&LOCK_delayed_insert); // For unlink from list + mysql_mutex_unlock(&LOCK_delayed_insert); // For unlink from list } @@ -2309,15 +2310,17 @@ pthread_handler_t handle_delayed_insert(void *arg) thd->killed=abort_loop ? THD::KILL_CONNECTION : THD::NOT_KILLED; pthread_mutex_unlock(&LOCK_thread_count); + mysql_thread_set_psi_id(thd->thread_id); + /* - Wait until the client runs into pthread_cond_wait(), + Wait until the client runs into mysql_cond_wait(), where we free it after the table is opened and di linked in the list. If we did not wait here, the client might detect the opened table before it is linked to the list. It would release LOCK_delayed_create and allow another thread to create another handler for the same table, since it does not find one in the list. */ - pthread_mutex_lock(&di->mutex); + mysql_mutex_lock(&di->mutex); if (my_thread_init()) { /* Can't use my_error since store_globals has not yet been called */ @@ -2376,7 +2379,7 @@ pthread_handler_t handle_delayed_insert(void *arg) di->table->copy_blobs=1; /* Tell client that the thread is initialized */ - pthread_cond_signal(&di->cond_client); + mysql_cond_signal(&di->cond_client); /* Now wait until we get an insert or lock to handle */ /* We will not abort as long as a client thread uses this thread */ @@ -2390,12 +2393,12 @@ pthread_handler_t handle_delayed_insert(void *arg) Remove this from delay insert list so that no one can request a table from this */ - pthread_mutex_unlock(&di->mutex); - pthread_mutex_lock(&LOCK_delayed_insert); + mysql_mutex_unlock(&di->mutex); + mysql_mutex_lock(&LOCK_delayed_insert); di->unlink(); lock_count=di->lock_count(); - pthread_mutex_unlock(&LOCK_delayed_insert); - pthread_mutex_lock(&di->mutex); + mysql_mutex_unlock(&LOCK_delayed_insert); + mysql_mutex_lock(&di->mutex); if (!lock_count && !di->tables_in_use && !di->stacked_inserts) break; // Time to die } @@ -2415,15 +2418,15 @@ pthread_handler_t handle_delayed_insert(void *arg) { int error; #if defined(HAVE_BROKEN_COND_TIMEDWAIT) - error=pthread_cond_wait(&di->cond,&di->mutex); + error= mysql_cond_wait(&di->cond, &di->mutex); #else - error=pthread_cond_timedwait(&di->cond,&di->mutex,&abstime); + error= mysql_cond_timedwait(&di->cond, &di->mutex, &abstime); #ifdef EXTRA_DEBUG if (error && error != EINTR && error != ETIMEDOUT) { - fprintf(stderr, "Got error %d from pthread_cond_timedwait\n",error); - DBUG_PRINT("error",("Got error %d from pthread_cond_timedwait", - error)); + fprintf(stderr, "Got error %d from mysql_cond_timedwait\n", error); + DBUG_PRINT("error", ("Got error %d from mysql_cond_timedwait", + error)); } #endif #endif @@ -2436,12 +2439,12 @@ pthread_handler_t handle_delayed_insert(void *arg) } } /* We can't lock di->mutex and mysys_var->mutex at the same time */ - pthread_mutex_unlock(&di->mutex); - pthread_mutex_lock(&di->thd.mysys_var->mutex); + mysql_mutex_unlock(&di->mutex); + mysql_mutex_lock(&di->thd.mysys_var->mutex); di->thd.mysys_var->current_mutex= 0; di->thd.mysys_var->current_cond= 0; - pthread_mutex_unlock(&di->thd.mysys_var->mutex); - pthread_mutex_lock(&di->mutex); + mysql_mutex_unlock(&di->thd.mysys_var->mutex); + mysql_mutex_lock(&di->mutex); } thd_proc_info(&(di->thd), 0); @@ -2466,7 +2469,7 @@ pthread_handler_t handle_delayed_insert(void *arg) di->dead= 1; thd->killed= THD::KILL_CONNECTION; } - pthread_cond_broadcast(&di->cond_client); + mysql_cond_broadcast(&di->cond_client); } if (di->stacked_inserts) { @@ -2486,7 +2489,7 @@ pthread_handler_t handle_delayed_insert(void *arg) */ MYSQL_LOCK *lock=thd->lock; thd->lock=0; - pthread_mutex_unlock(&di->mutex); + mysql_mutex_unlock(&di->mutex); /* We need to release next_insert_id before unlocking. This is enforced by handler::ha_external_lock(). @@ -2495,10 +2498,10 @@ pthread_handler_t handle_delayed_insert(void *arg) mysql_unlock_tables(thd, lock); ha_autocommit_or_rollback(thd, 0); di->group_count=0; - pthread_mutex_lock(&di->mutex); + mysql_mutex_lock(&di->mutex); } if (di->tables_in_use) - pthread_cond_broadcast(&di->cond_client); // If waiting clients + mysql_cond_broadcast(&di->cond_client); // If waiting clients } err: @@ -2527,14 +2530,14 @@ pthread_handler_t handle_delayed_insert(void *arg) di->table=0; di->dead= 1; // If error thd->killed= THD::KILL_CONNECTION; // If error - pthread_cond_broadcast(&di->cond_client); // Safety - pthread_mutex_unlock(&di->mutex); + mysql_cond_broadcast(&di->cond_client); // Safety + mysql_mutex_unlock(&di->mutex); - pthread_mutex_lock(&LOCK_delayed_create); // Because of delayed_get_table - pthread_mutex_lock(&LOCK_delayed_insert); + mysql_mutex_lock(&LOCK_delayed_create); // Because of delayed_get_table + mysql_mutex_lock(&LOCK_delayed_insert); delete di; - pthread_mutex_unlock(&LOCK_delayed_insert); - pthread_mutex_unlock(&LOCK_delayed_create); + mysql_mutex_unlock(&LOCK_delayed_insert); + mysql_mutex_unlock(&LOCK_delayed_create); my_thread_end(); pthread_exit(0); @@ -2581,7 +2584,7 @@ bool Delayed_insert::handle_inserts(void) DBUG_ENTER("handle_inserts"); /* Allow client to insert new rows */ - pthread_mutex_unlock(&mutex); + mysql_mutex_unlock(&mutex); table->next_number_field=table->found_next_number_field; table->use_all_columns(); @@ -2614,12 +2617,12 @@ bool Delayed_insert::handle_inserts(void) */ if (!using_bin_log) table->file->extra(HA_EXTRA_WRITE_CACHE); - pthread_mutex_lock(&mutex); + mysql_mutex_lock(&mutex); while ((row=rows.get())) { stacked_inserts--; - pthread_mutex_unlock(&mutex); + mysql_mutex_unlock(&mutex); memcpy(table->record[0],row->record,table->s->reclength); thd.start_time=row->start_time; @@ -2737,7 +2740,7 @@ bool Delayed_insert::handle_inserts(void) free_delayed_insert_blobs(table); thread_safe_decrement(delayed_rows_in_use,&LOCK_delayed_status); thread_safe_increment(delayed_insert_writes,&LOCK_delayed_status); - pthread_mutex_lock(&mutex); + mysql_mutex_lock(&mutex); /* Reset the table->auto_increment_field_not_null as it is valid for @@ -2759,9 +2762,9 @@ bool Delayed_insert::handle_inserts(void) if (stacked_inserts || tables_in_use) // Let these wait a while { if (tables_in_use) - pthread_cond_broadcast(&cond_client); // If waiting clients + mysql_cond_broadcast(&cond_client); // If waiting clients thd_proc_info(&thd, "reschedule"); - pthread_mutex_unlock(&mutex); + mysql_mutex_unlock(&mutex); if ((error=table->file->extra(HA_EXTRA_NO_CACHE))) { /* This should never happen */ @@ -2780,15 +2783,15 @@ bool Delayed_insert::handle_inserts(void) } if (!using_bin_log) table->file->extra(HA_EXTRA_WRITE_CACHE); - pthread_mutex_lock(&mutex); + mysql_mutex_lock(&mutex); thd_proc_info(&thd, "insert"); } if (tables_in_use) - pthread_cond_broadcast(&cond_client); // If waiting clients + mysql_cond_broadcast(&cond_client); // If waiting clients } } thd_proc_info(&thd, 0); - pthread_mutex_unlock(&mutex); + mysql_mutex_unlock(&mutex); /* We need to flush the pending event when using row-based @@ -2813,7 +2816,7 @@ bool Delayed_insert::handle_inserts(void) goto err; } query_cache_invalidate3(&thd, table, 1); - pthread_mutex_lock(&mutex); + mysql_mutex_lock(&mutex); DBUG_RETURN(0); err: @@ -2837,7 +2840,7 @@ bool Delayed_insert::handle_inserts(void) } DBUG_PRINT("error", ("dropped %lu rows after an error", max_rows)); thread_safe_increment(delayed_insert_errors, &LOCK_delayed_status); - pthread_mutex_lock(&mutex); + mysql_mutex_lock(&mutex); DBUG_RETURN(1); } #endif /* EMBEDDED_LIBRARY */ @@ -3494,7 +3497,7 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE)) { - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); if (reopen_name_locked_table(thd, create_table, FALSE)) { quick_rm_table(create_info->db_type, create_table->db, @@ -3503,7 +3506,7 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, } else table= create_table->table; - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } else { diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 32c94f0908f..0198d2530d8 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2081,11 +2081,11 @@ mysql_execute_command(THD *thd) restore status variables, as we don't want 'show status' to cause changes */ - pthread_mutex_lock(&LOCK_status); + mysql_mutex_lock(&LOCK_status); add_diff_to_status(&global_status_var, &thd->status_var, &old_status_var); thd->status_var= old_status_var; - pthread_mutex_unlock(&LOCK_status); + mysql_mutex_unlock(&LOCK_status); break; } case SQLCOM_SHOW_DATABASES: diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 868dfc3e968..b0fa5354567 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -6223,7 +6223,7 @@ static void alter_partition_lock_handling(ALTER_PARTITION_PARAM_TYPE *lpt) since all table objects were closed and removed as part of the ALTER TABLE of partitioning structure. */ - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); lpt->thd->in_lock_tables= 1; err= reopen_tables(lpt->thd, 1, 1); lpt->thd->in_lock_tables= 0; @@ -6237,7 +6237,7 @@ static void alter_partition_lock_handling(ALTER_PARTITION_PARAM_TYPE *lpt) unlink_open_table(lpt->thd, lpt->table, FALSE); sql_print_warning("We failed to reacquire LOCKs in ALTER TABLE"); } - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } } @@ -6261,9 +6261,9 @@ static int alter_close_tables(ALTER_PARTITION_PARAM_TYPE *lpt) We set lock to zero to ensure we don't do this twice and we set db_stat to zero to ensure we don't close twice. */ - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); close_data_files_and_morph_locks(thd, db, table_name); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(0); } diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 936c9ae8866..098783111a1 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -1372,10 +1372,10 @@ static void plugin_load(MEM_ROOT *tmp_root, int *argc, char **argv) When building an embedded library, if the mysql.plugin table does not exist, we silently ignore the missing table */ - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); if (check_if_table_exists(new_thd, &tables, &table_exists)) table_exists= FALSE; - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); if (!table_exists) goto end; #endif /* EMBEDDED_LIBRARY */ diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index dac96f2e9c4..1dee391fa8b 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -133,10 +133,10 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent) } } - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); if (lock_table_names_exclusively(thd, table_list)) { - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); goto err; } @@ -172,7 +172,7 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent) higher concurrency - query_cache_invalidate can take minutes to complete. */ - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); /* Lets hope this doesn't fail as the result will be messy */ if (!silent && !error) @@ -184,9 +184,9 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent) if (!error) query_cache_invalidate3(thd, table_list, 0); - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); unlock_table_names(thd, table_list, (TABLE_LIST*) 0); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); err: start_waiting_global_read_lock(thd); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index dfb88af95d3..5a644dba15d 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1759,11 +1759,11 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) thd_info->db=thd->strdup(thd_info->db); thd_info->command=(int) tmp->command; if ((mysys_var= tmp->mysys_var)) - pthread_mutex_lock(&mysys_var->mutex); + mysql_mutex_lock(&mysys_var->mutex); thd_info->proc_info= (char*) (tmp->killed == THD::KILL_CONNECTION? "Killed" : 0); thd_info->state_info= thread_state_info(tmp); if (mysys_var) - pthread_mutex_unlock(&mysys_var->mutex); + mysql_mutex_unlock(&mysys_var->mutex); thd_info->start_time= tmp->start_time; thd_info->query=0; @@ -1862,7 +1862,7 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond) } if ((mysys_var= tmp->mysys_var)) - pthread_mutex_lock(&mysys_var->mutex); + mysql_mutex_lock(&mysys_var->mutex); /* COMMAND */ if ((val= (char *) (tmp->killed == THD::KILL_CONNECTION? "Killed" : 0))) table->field[4]->store(val, strlen(val), cs); @@ -1880,7 +1880,7 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond) } if (mysys_var) - pthread_mutex_unlock(&mysys_var->mutex); + mysql_mutex_unlock(&mysys_var->mutex); /* INFO */ if (tmp->query()) @@ -1958,7 +1958,7 @@ int add_status_vars(SHOW_VAR *list) { int res= 0; if (status_vars_inited) - pthread_mutex_lock(&LOCK_status); + mysql_mutex_lock(&LOCK_status); if (!all_status_vars.buffer && // array is not allocated yet - do it now my_init_dynamic_array(&all_status_vars, sizeof(SHOW_VAR), 200, 20)) { @@ -1973,7 +1973,7 @@ int add_status_vars(SHOW_VAR *list) sort_dynamic(&all_status_vars, show_var_cmp); err: if (status_vars_inited) - pthread_mutex_unlock(&LOCK_status); + mysql_mutex_unlock(&LOCK_status); return res; } @@ -2035,7 +2035,7 @@ void remove_status_vars(SHOW_VAR *list) { if (status_vars_inited) { - pthread_mutex_lock(&LOCK_status); + mysql_mutex_lock(&LOCK_status); SHOW_VAR *all= dynamic_element(&all_status_vars, 0, SHOW_VAR *); int a= 0, b= all_status_vars.elements, c= (a+b)/2; @@ -2056,7 +2056,7 @@ void remove_status_vars(SHOW_VAR *list) all[c].type= SHOW_UNDEF; } shrink_var_array(&all_status_vars); - pthread_mutex_unlock(&LOCK_status); + mysql_mutex_unlock(&LOCK_status); } else { @@ -3102,7 +3102,7 @@ static int fill_schema_table_from_frm(THD *thd,TABLE *table, } key_length= create_table_def_key(thd, key, &table_list, 0); - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); share= get_table_share(thd, &table_list, key, key_length, OPEN_VIEW, &error); if (!share) @@ -3149,7 +3149,7 @@ err1: release_table_share(share, RELEASE_NORMAL); err: - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); thd->clear_error(); return res; } @@ -5524,14 +5524,14 @@ int fill_status(THD *thd, TABLE_LIST *tables, COND *cond) tmp1= &thd->status_var; } - pthread_mutex_lock(&LOCK_status); + mysql_mutex_lock(&LOCK_status); if (option_type == OPT_GLOBAL) calc_sum_of_all_status(&tmp); res= show_status_array(thd, wild, (SHOW_VAR *)all_status_vars.buffer, option_type, tmp1, "", tables->table, upper_case_names, cond); - pthread_mutex_unlock(&LOCK_status); + mysql_mutex_unlock(&LOCK_status); DBUG_RETURN(res); } @@ -7192,7 +7192,7 @@ static TABLE_LIST *get_trigger_table(THD *thd, const sp_name *trg_name) { /* Acquire LOCK_open (stop the server). */ - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); /* Load base table name from the TRN-file and create TABLE_LIST object. @@ -7202,7 +7202,7 @@ static TABLE_LIST *get_trigger_table(THD *thd, const sp_name *trg_name) /* Release LOCK_open (continue the server). */ - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); /* That's it. */ diff --git a/sql/sql_table.cc b/sql/sql_table.cc index e594499b4d8..65e320f5218 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1653,7 +1653,7 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags) completing this we write a new phase to the log entry that will deactivate it. */ - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); if (my_delete(frm_name, MYF(MY_WME)) || #ifdef WITH_PARTITION_STORAGE_ENGINE lpt->table->file->ha_create_handler_files(path, shadow_path, @@ -1706,7 +1706,7 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags) #endif err: - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); #ifdef WITH_PARTITION_STORAGE_ENGINE deactivate_ddl_log_entry(part_info->frm_log_entry->entry_pos); part_info->frm_log_entry= NULL; @@ -1869,7 +1869,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, mysql_ha_rm_tables(thd, tables, FALSE); - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); /* If we have the table in the definition cache, we don't have to check the @@ -1890,14 +1890,14 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, table->table_name_length, table->table_name, 1)) { my_error(ER_BAD_LOG_STATEMENT, MYF(0), "DROP"); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(1); } } if (!drop_temporary && lock_table_names_exclusively(thd, tables)) { - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(1); } @@ -2068,7 +2068,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, It's safe to unlock LOCK_open: we have an exclusive lock on the table name. */ - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); thd->thread_specific_used|= tmp_table_deleted; error= 0; if (wrong_tables.length()) @@ -2151,10 +2151,10 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, */ } } - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); err_with_placeholders: unlock_table_names(thd, tables, (TABLE_LIST*) 0); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(error); } @@ -3870,7 +3870,7 @@ bool mysql_create_table_no_lock(THD *thd, goto err; } - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE)) { if (!access(path,F_OK)) @@ -4015,7 +4015,7 @@ bool mysql_create_table_no_lock(THD *thd, write_create_table_bin_log(thd, create_info, internal_tmp_table); error= FALSE; unlock_and_end: - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); err: thd_proc_info(thd, "After create"); @@ -4048,21 +4048,21 @@ bool mysql_create_table(THD *thd, const char *db, const char *table_name, DBUG_ENTER("mysql_create_table"); /* Wait for any database locks */ - pthread_mutex_lock(&LOCK_lock_db); + mysql_mutex_lock(&LOCK_lock_db); while (!thd->killed && my_hash_search(&lock_db_cache,(uchar*) db, strlen(db))) { wait_for_condition(thd, &LOCK_lock_db, &COND_refresh); - pthread_mutex_lock(&LOCK_lock_db); + mysql_mutex_lock(&LOCK_lock_db); } if (thd->killed) { - pthread_mutex_unlock(&LOCK_lock_db); + mysql_mutex_unlock(&LOCK_lock_db); DBUG_RETURN(TRUE); } creating_table++; - pthread_mutex_unlock(&LOCK_lock_db); + mysql_mutex_unlock(&LOCK_lock_db); if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE)) { @@ -4099,14 +4099,14 @@ bool mysql_create_table(THD *thd, const char *db, const char *table_name, unlock: if (name_lock) { - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); unlink_open_table(thd, name_lock, FALSE); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } - pthread_mutex_lock(&LOCK_lock_db); + mysql_mutex_lock(&LOCK_lock_db); if (!--creating_table && creating_database) - pthread_cond_signal(&COND_refresh); - pthread_mutex_unlock(&LOCK_lock_db); + mysql_cond_signal(&COND_refresh); + mysql_mutex_unlock(&LOCK_lock_db); DBUG_RETURN(result); } @@ -4267,7 +4267,7 @@ void wait_while_table_is_used(THD *thd, TABLE *table, table->s->table_name.str, (ulong) table->s, table->db_stat, table->s->version)); - safe_mutex_assert_owner(&LOCK_open); + mysql_mutex_assert_owner(&LOCK_open); (void) table->file->extra(function); /* Mark all tables that are in use as 'old' */ @@ -4352,22 +4352,22 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list, uint key_length; key_length= create_table_def_key(thd, key, table_list, 0); - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); if (!(share= (get_table_share(thd, table_list, key, key_length, 0, &error)))) { - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(0); // Can't open frm file } if (open_table_from_share(thd, share, "", 0, 0, 0, &tmp_table, FALSE)) { release_table_share(share, RELEASE_NORMAL); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(0); // Out of memory } table= &tmp_table; - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } /* A MERGE table must not come here. */ @@ -4421,9 +4421,9 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list, /* If we could open the table, close it */ if (table_list->table) { - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); close_cached_table(thd, table); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } if (lock_and_wait_for_table_name(thd,table_list)) { @@ -4432,27 +4432,27 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list, } if (my_rename(from, tmp, MYF(MY_WME))) { - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); unlock_table_name(thd, table_list); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); error= send_check_errmsg(thd, table_list, "repair", "Failed renaming data file"); goto end; } if (mysql_truncate(thd, table_list, 1)) { - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); unlock_table_name(thd, table_list); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); error= send_check_errmsg(thd, table_list, "repair", "Failed generating table from .frm file"); goto end; } if (my_rename(tmp, from, MYF(MY_WME))) { - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); unlock_table_name(thd, table_list); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); error= send_check_errmsg(thd, table_list, "repair", "Failed restoring .MYD file"); goto end; @@ -4462,23 +4462,23 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list, Now we should be able to open the partially repaired table to finish the repair in the handler later on. */ - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); if (reopen_name_locked_table(thd, table_list, TRUE)) { unlock_table_name(thd, table_list); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); error= send_check_errmsg(thd, table_list, "repair", "Failed to open partially repaired table"); goto end; } - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); end: if (table == &tmp_table) { - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); closefrm(table, 1); // Free allocated memory - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } DBUG_RETURN(error); } @@ -4705,7 +4705,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, if (lock_type == TL_WRITE && table->table->s->version) { DBUG_PRINT("admin", ("removing table from cache")); - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); const char *old_message=thd->enter_cond(&COND_refresh, &LOCK_open, "Waiting to get writelock"); mysql_lock_abort(thd,table->table, TRUE); @@ -4968,10 +4968,10 @@ send_result_message: table->table->file->info(HA_STATUS_CONST); else { - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); remove_table_from_cache(thd, table->table->s->db.str, table->table->s->table_name.str, RTFC_NO_FLAG); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } /* May be something modified consequently we have to invalidate cache */ query_cache_invalidate3(thd, table->table, 0); @@ -5274,12 +5274,12 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table, Also some engines (e.g. NDB cluster) require that LOCK_open should be held during the call to ha_create_table(). See bug #28614 for more info. */ - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); if (src_table->schema_table) { if (mysql_create_like_schema_frm(thd, src_table, dst_path, create_info)) { - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); goto err; } } @@ -5289,7 +5289,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table, my_error(ER_BAD_DB_ERROR,MYF(0),db); else my_error(ER_CANT_CREATE_FILE,MYF(0),dst_path,my_errno); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); goto err; } @@ -5318,7 +5318,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table, if (thd->variables.keep_files_on_create) create_info->options|= HA_CREATE_KEEP_FILES; err= ha_create_table(thd, dst_path, db, table_name, create_info, 1); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); if (create_info->options & HA_LEX_CREATE_TMP_TABLE) { @@ -5392,13 +5392,13 @@ binlog: of this function. */ table->table= name_lock; - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); if (reopen_name_locked_table(thd, table, FALSE)) { - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); goto err; } - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); int result __attribute__((unused))= store_create_info(thd, table, &query, @@ -5422,9 +5422,9 @@ binlog: err: if (name_lock) { - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); unlink_open_table(thd, name_lock, FALSE); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } DBUG_RETURN(res); } @@ -6501,7 +6501,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, if (wait_if_global_read_lock(thd,0,1)) DBUG_RETURN(TRUE); - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); if (lock_table_names(thd, table_list)) { error= 1; @@ -6523,7 +6523,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, unlock_table_names(thd, table_list, (TABLE_LIST*) 0); view_err: - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); start_waiting_global_read_lock(thd); DBUG_RETURN(error); } @@ -6684,17 +6684,17 @@ view_err: while the fact that the table is still open gives us protection from concurrent DDL statements. */ - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); DBUG_EXECUTE_IF("sleep_alter_enable_indexes", my_sleep(6000000);); error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE); /* COND_refresh will be signaled in close_thread_tables() */ break; case DISABLE: - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); error=table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE); /* COND_refresh will be signaled in close_thread_tables() */ break; @@ -6711,7 +6711,7 @@ view_err: table->alias); } - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); /* Unlike to the above case close_cached_table() below will remove ALL instances of TABLE from table cache (it will also remove table lock @@ -6777,7 +6777,7 @@ view_err: } if (name_lock) unlink_open_table(thd, name_lock, FALSE); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); table_list->table= NULL; // For query cache query_cache_invalidate3(thd, table_list, 0); DBUG_RETURN(error); @@ -7138,9 +7138,9 @@ view_err: } else { - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); thd_proc_info(thd, "manage keys"); alter_table_manage_keys(table, table->file->indexes_are_disabled(), alter_info->keys_onoff); @@ -7270,11 +7270,11 @@ view_err: intern_close_table(new_table); my_free(new_table,MYF(0)); } - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); if (error) { (void) quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); goto err; } @@ -7407,7 +7407,7 @@ view_err: if (error) goto err_with_placeholders; } - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); thd_proc_info(thd, "end"); @@ -7454,10 +7454,10 @@ view_err: from the list of open tables and table cache. If we are not under LOCK TABLES we can rely on close_thread_tables() doing this job. */ - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); unlink_open_table(thd, table, FALSE); unlink_open_table(thd, name_lock, FALSE); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } end_temporary: @@ -7514,9 +7514,9 @@ err: } if (name_lock) { - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); unlink_open_table(thd, name_lock, FALSE); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } DBUG_RETURN(TRUE); @@ -7529,7 +7529,7 @@ err_with_placeholders: unlink_open_table(thd, table, FALSE); if (name_lock) unlink_open_table(thd, name_lock, FALSE); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(TRUE); } /* mysql_alter_table */ diff --git a/sql/sql_test.cc b/sql/sql_test.cc index d9beb77f546..af05f1199d4 100644 --- a/sql/sql_test.cc +++ b/sql/sql_test.cc @@ -80,7 +80,7 @@ void print_cached_tables(void) compile_time_assert(TL_WRITE_ONLY+1 == array_elements(lock_descriptions)); /* purecov: begin tested */ - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); puts("DB Table Version Thread Open Lock"); for (idx=unused=0 ; idx < open_cache.records ; idx++) @@ -116,7 +116,7 @@ void print_cached_tables(void) if (my_hash_check(&open_cache)) printf("Error: File hash table is corrupted\n"); fflush(stdout); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); /* purecov: end */ return; } @@ -381,12 +381,12 @@ static void display_table_locks(void) DYNAMIC_ARRAY saved_table_locks; (void) my_init_dynamic_array(&saved_table_locks,sizeof(TABLE_LOCK_INFO),open_cache.records + 20,50); - pthread_mutex_lock(&THR_LOCK_lock); + mysql_mutex_lock(&THR_LOCK_lock); for (list= thr_lock_thread_list; list; list= list_rest(list)) { THR_LOCK *lock=(THR_LOCK*) list->data; - pthread_mutex_lock(&lock->mutex); + mysql_mutex_lock(&lock->mutex); push_locks_into_array(&saved_table_locks, lock->write.data, FALSE, "Locked - write"); push_locks_into_array(&saved_table_locks, lock->write_wait.data, TRUE, @@ -395,9 +395,9 @@ static void display_table_locks(void) "Locked - read"); push_locks_into_array(&saved_table_locks, lock->read_wait.data, TRUE, "Waiting - read"); - pthread_mutex_unlock(&lock->mutex); + mysql_mutex_unlock(&lock->mutex); } - pthread_mutex_unlock(&THR_LOCK_lock); + mysql_mutex_unlock(&THR_LOCK_lock); if (!saved_table_locks.elements) goto end; qsort((uchar*) dynamic_element(&saved_table_locks,0,TABLE_LOCK_INFO *),saved_table_locks.elements,sizeof(TABLE_LOCK_INFO),(qsort_cmp) dl_compare); @@ -473,7 +473,7 @@ void mysql_print_status() /* Print key cache status */ puts("\nKey caches:"); process_key_caches(print_key_cache_status); - pthread_mutex_lock(&LOCK_status); + mysql_mutex_lock(&LOCK_status); printf("\nhandler status:\n\ read_key: %10lu\n\ read_next: %10lu\n\ @@ -489,7 +489,7 @@ update: %10lu\n", tmp.ha_write_count, tmp.ha_delete_count, tmp.ha_update_count); - pthread_mutex_unlock(&LOCK_status); + mysql_mutex_unlock(&LOCK_status); printf("\nTable status:\n\ Opened tables: %10lu\n\ Open tables: %10lu\n\ diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index ecbb6473ec4..c895239064b 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -387,7 +387,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1))) DBUG_RETURN(TRUE); - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); if (!create) { @@ -510,7 +510,7 @@ end: write_bin_log(thd, TRUE, stmt_query.ptr(), stmt_query.length()); } - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); if (need_start_waiting) start_waiting_global_read_lock(thd); @@ -1884,7 +1884,7 @@ bool Table_triggers_list::change_table_name(THD *thd, const char *db, old_table)-(char*)&key[0])+1; if (!is_table_name_exclusively_locked_by_this_thread(thd, key, key_length)) - safe_mutex_assert_owner(&LOCK_open); + mysql_mutex_assert_owner(&LOCK_open); #endif DBUG_ASSERT(my_strcasecmp(table_alias_charset, db, new_db) || diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 83341a53c3e..9d383dcd363 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -620,7 +620,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, res= TRUE; goto err; } - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); res= mysql_register_view(thd, view, mode); if (mysql_bin_log.is_open()) @@ -666,7 +666,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, buff.ptr(), buff.length(), FALSE, FALSE, errcode); } - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); if (mode != VIEW_CREATE_NEW) query_cache_invalidate3(thd, view, 0); start_waiting_global_read_lock(thd); @@ -1579,7 +1579,7 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) bool something_wrong= FALSE; DBUG_ENTER("mysql_drop_view"); - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); for (view= views; view; view= view->next_local) { TABLE_SHARE *share; @@ -1656,7 +1656,7 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) write_bin_log(thd, !something_wrong, thd->query(), thd->query_length()); } - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); if (something_wrong) { diff --git a/storage/federated/ha_federated.cc b/storage/federated/ha_federated.cc index a73a39440d7..eea42904bb0 100644 --- a/storage/federated/ha_federated.cc +++ b/storage/federated/ha_federated.cc @@ -3141,7 +3141,7 @@ int ha_federated::real_connect() to establish Federated connection to guard against a trivial Denial of Service scenerio. */ - safe_mutex_assert_not_owner(&LOCK_open); + mysql_mutex_assert_not_owner(&LOCK_open); DBUG_ASSERT(mysql == NULL); From cc92cd72a4e2bad5a9742862163bdf9b57c301b3 Mon Sep 17 00:00:00 2001 From: He Zhenxing Date: Thu, 10 Dec 2009 11:44:19 +0800 Subject: [PATCH 041/104] Post fix for bug#45520 --- mysql-test/include/kill_query.inc | 2 +- mysql-test/r/rpl_killed_ddl.result | 1 + mysql-test/t/rpl_killed_ddl.test | 5 +++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/mysql-test/include/kill_query.inc b/mysql-test/include/kill_query.inc index 341c3b93535..b303ed0ec39 100644 --- a/mysql-test/include/kill_query.inc +++ b/mysql-test/include/kill_query.inc @@ -52,7 +52,7 @@ if (`SELECT '$debug_lock' != ''`) # reap the result of the waiting query connection $connection_name; -error 0, 1317, 1307, 1306, 1334, 1305; +error 0, 1317, 1307, 1306, 1334, 1305, 1034; reap; connection master; diff --git a/mysql-test/r/rpl_killed_ddl.result b/mysql-test/r/rpl_killed_ddl.result index b9ee915bdce..59c80d8f6cc 100644 --- a/mysql-test/r/rpl_killed_ddl.result +++ b/mysql-test/r/rpl_killed_ddl.result @@ -94,6 +94,7 @@ source include/diff_master_slave.inc; DROP INDEX i1 on t1; source include/kill_query.inc; source include/diff_master_slave.inc; +CREATE TABLE IF NOT EXISTS t4 (a int); CREATE TRIGGER tr2 BEFORE INSERT ON t4 FOR EACH ROW BEGIN DELETE FROM t1 WHERE a=NEW.a; diff --git a/mysql-test/t/rpl_killed_ddl.test b/mysql-test/t/rpl_killed_ddl.test index 7c07d5eecf0..b0d7258998f 100644 --- a/mysql-test/t/rpl_killed_ddl.test +++ b/mysql-test/t/rpl_killed_ddl.test @@ -203,6 +203,11 @@ source include/kill_query_and_diff_master_slave.inc; ######## TRIGGER ######## +# Make sure table t4 exists +connection master; +CREATE TABLE IF NOT EXISTS t4 (a int); +connection master1; + let $diff_statement= SHOW TRIGGERS LIKE 'v%'; DELIMITER //; From 3461cdc1a173d7ca4a5592200440bdc1ac108a29 Mon Sep 17 00:00:00 2001 From: Gleb Shchepa Date: Thu, 10 Dec 2009 10:05:44 +0400 Subject: [PATCH 042/104] Bug #49480: WHERE using YEAR columns returns unexpected results A few problems were found in the fix for bug 43668: 1) Comparison of the YEAR column with NULL always returned TRUE; 2) Comparison of the YEAR column with constants always returned unpredictable result; 3) Unnecessary conversion warnings when comparing a non-integer constant with a NULL value in the YEAR column; The problems described above have been resolved with an exception: zero (i.e. invalid) YEAR column value comparison with 00 or 2000 still fail (it is not a regression and it was not a regression), so MIN/MAX on YEAR column containing zero value still fail. --- mysql-test/r/type_year.result | 264 ++++++++++++++++++++++++++++++++++ mysql-test/t/type_year.test | 106 ++++++++++++++ sql/item_cmpfunc.cc | 144 +++++++------------ sql/item_cmpfunc.h | 9 +- 4 files changed, 421 insertions(+), 102 deletions(-) diff --git a/mysql-test/r/type_year.result b/mysql-test/r/type_year.result index e52947455c8..56b326327c6 100644 --- a/mysql-test/r/type_year.result +++ b/mysql-test/r/type_year.result @@ -46,3 +46,267 @@ a 2001 drop table t1; End of 5.0 tests +# +# Bug #49480: WHERE using YEAR columns returns unexpected results +# +CREATE TABLE t2(yy YEAR(2), c2 CHAR(4)); +CREATE TABLE t4(yyyy YEAR(4), c4 CHAR(4)); +INSERT INTO t2 (c2) VALUES (NULL),(1970),(1999),(2000),(2001),(2069); +INSERT INTO t4 (c4) SELECT c2 FROM t2; +UPDATE t2 SET yy = c2; +UPDATE t4 SET yyyy = c4; +SELECT * FROM t2; +yy c2 +NULL NULL +70 1970 +99 1999 +00 2000 +01 2001 +69 2069 +SELECT * FROM t4; +yyyy c4 +NULL NULL +1970 1970 +1999 1999 +2000 2000 +2001 2001 +2069 2069 +# Comparison of YEAR(2) with YEAR(4) +SELECT * FROM t2, t4 WHERE yy = yyyy; +yy c2 yyyy c4 +70 1970 1970 1970 +99 1999 1999 1999 +00 2000 2000 2000 +01 2001 2001 2001 +69 2069 2069 2069 +SELECT * FROM t2, t4 WHERE yy <=> yyyy; +yy c2 yyyy c4 +NULL NULL NULL NULL +70 1970 1970 1970 +99 1999 1999 1999 +00 2000 2000 2000 +01 2001 2001 2001 +69 2069 2069 2069 +SELECT * FROM t2, t4 WHERE yy < yyyy; +yy c2 yyyy c4 +70 1970 1999 1999 +70 1970 2000 2000 +99 1999 2000 2000 +70 1970 2001 2001 +99 1999 2001 2001 +00 2000 2001 2001 +70 1970 2069 2069 +99 1999 2069 2069 +00 2000 2069 2069 +01 2001 2069 2069 +SELECT * FROM t2, t4 WHERE yy > yyyy; +yy c2 yyyy c4 +99 1999 1970 1970 +00 2000 1970 1970 +01 2001 1970 1970 +69 2069 1970 1970 +00 2000 1999 1999 +01 2001 1999 1999 +69 2069 1999 1999 +01 2001 2000 2000 +69 2069 2000 2000 +69 2069 2001 2001 +# Comparison of YEAR(2) with YEAR(2) +SELECT * FROM t2 a, t2 b WHERE a.yy = b.yy; +yy c2 yy c2 +70 1970 70 1970 +99 1999 99 1999 +00 2000 00 2000 +01 2001 01 2001 +69 2069 69 2069 +SELECT * FROM t2 a, t2 b WHERE a.yy <=> b.yy; +yy c2 yy c2 +NULL NULL NULL NULL +70 1970 70 1970 +99 1999 99 1999 +00 2000 00 2000 +01 2001 01 2001 +69 2069 69 2069 +SELECT * FROM t2 a, t2 b WHERE a.yy < b.yy; +yy c2 yy c2 +70 1970 99 1999 +70 1970 00 2000 +99 1999 00 2000 +70 1970 01 2001 +99 1999 01 2001 +00 2000 01 2001 +70 1970 69 2069 +99 1999 69 2069 +00 2000 69 2069 +01 2001 69 2069 +# Comparison of YEAR(4) with YEAR(4) +SELECT * FROM t4 a, t4 b WHERE a.yyyy = b.yyyy; +yyyy c4 yyyy c4 +1970 1970 1970 1970 +1999 1999 1999 1999 +2000 2000 2000 2000 +2001 2001 2001 2001 +2069 2069 2069 2069 +SELECT * FROM t4 a, t4 b WHERE a.yyyy <=> b.yyyy; +yyyy c4 yyyy c4 +NULL NULL NULL NULL +1970 1970 1970 1970 +1999 1999 1999 1999 +2000 2000 2000 2000 +2001 2001 2001 2001 +2069 2069 2069 2069 +SELECT * FROM t4 a, t4 b WHERE a.yyyy < b.yyyy; +yyyy c4 yyyy c4 +1970 1970 1999 1999 +1970 1970 2000 2000 +1999 1999 2000 2000 +1970 1970 2001 2001 +1999 1999 2001 2001 +2000 2000 2001 2001 +1970 1970 2069 2069 +1999 1999 2069 2069 +2000 2000 2069 2069 +2001 2001 2069 2069 +# Comparison with constants: +SELECT * FROM t2 WHERE yy = NULL; +yy c2 +SELECT * FROM t4 WHERE yyyy = NULL; +yyyy c4 +SELECT * FROM t2 WHERE yy <=> NULL; +yy c2 +NULL NULL +SELECT * FROM t4 WHERE yyyy <=> NULL; +yyyy c4 +NULL NULL +SELECT * FROM t2 WHERE yy < NULL; +yy c2 +SELECT * FROM t2 WHERE yy > NULL; +yy c2 +SELECT * FROM t2 WHERE yy = NOW(); +yy c2 +SELECT * FROM t4 WHERE yyyy = NOW(); +yyyy c4 +SELECT * FROM t2 WHERE yy = 99; +yy c2 +99 1999 +SELECT * FROM t2 WHERE 99 = yy; +yy c2 +99 1999 +SELECT * FROM t4 WHERE yyyy = 99; +yyyy c4 +1999 1999 +SELECT * FROM t2 WHERE yy = 'test'; +yy c2 +00 2000 +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: 'test' +SELECT * FROM t4 WHERE yyyy = 'test'; +yyyy c4 +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: 'test' +SELECT * FROM t2 WHERE yy = '1999'; +yy c2 +99 1999 +SELECT * FROM t4 WHERE yyyy = '1999'; +yyyy c4 +1999 1999 +SELECT * FROM t2 WHERE yy = 1999; +yy c2 +99 1999 +SELECT * FROM t4 WHERE yyyy = 1999; +yyyy c4 +1999 1999 +SELECT * FROM t2 WHERE yy = 1999.1; +yy c2 +99 1999 +SELECT * FROM t4 WHERE yyyy = 1999.1; +yyyy c4 +1999 1999 +SELECT * FROM t2 WHERE yy = 1998.9; +yy c2 +99 1999 +SELECT * FROM t4 WHERE yyyy = 1998.9; +yyyy c4 +1999 1999 +# Coverage tests for YEAR with zero/2000 constants: +SELECT * FROM t2 WHERE yy = 0; +yy c2 +00 2000 +SELECT * FROM t2 WHERE yy = '0'; +yy c2 +00 2000 +SELECT * FROM t2 WHERE yy = '0000'; +yy c2 +00 2000 +SELECT * FROM t2 WHERE yy = '2000'; +yy c2 +00 2000 +SELECT * FROM t2 WHERE yy = 2000; +yy c2 +00 2000 +SELECT * FROM t4 WHERE yyyy = 0; +yyyy c4 +SELECT * FROM t4 WHERE yyyy = '0'; +yyyy c4 +2000 2000 +SELECT * FROM t4 WHERE yyyy = '0000'; +yyyy c4 +SELECT * FROM t4 WHERE yyyy = '2000'; +yyyy c4 +2000 2000 +SELECT * FROM t4 WHERE yyyy = 2000; +yyyy c4 +2000 2000 +# Comparison with constants those are out of YEAR range +# (coverage test for backward compatibility) +SELECT COUNT(yy) FROM t2; +COUNT(yy) +5 +SELECT COUNT(yyyy) FROM t4; +COUNT(yyyy) +5 +SELECT COUNT(*) FROM t2 WHERE yy = -1; +COUNT(*) +0 +SELECT COUNT(*) FROM t4 WHERE yyyy > -1; +COUNT(*) +5 +SELECT COUNT(*) FROM t2 WHERE yy > -1000000000000000000; +COUNT(*) +5 +SELECT COUNT(*) FROM t4 WHERE yyyy > -1000000000000000000; +COUNT(*) +5 +SELECT COUNT(*) FROM t2 WHERE yy < 2156; +COUNT(*) +5 +SELECT COUNT(*) FROM t4 WHERE yyyy < 2156; +COUNT(*) +5 +SELECT COUNT(*) FROM t2 WHERE yy < 1000000000000000000; +COUNT(*) +5 +SELECT COUNT(*) FROM t4 WHERE yyyy < 1000000000000000000; +COUNT(*) +5 +SELECT * FROM t2 WHERE yy < 123; +yy c2 +70 1970 +99 1999 +00 2000 +01 2001 +69 2069 +SELECT * FROM t2 WHERE yy > 123; +yy c2 +SELECT * FROM t4 WHERE yyyy < 123; +yyyy c4 +SELECT * FROM t4 WHERE yyyy > 123; +yyyy c4 +1970 1970 +1999 1999 +2000 2000 +2001 2001 +2069 2069 +DROP TABLE t2, t4; +# +End of 5.1 tests diff --git a/mysql-test/t/type_year.test b/mysql-test/t/type_year.test index 0e174a556d6..16fd39a59d8 100644 --- a/mysql-test/t/type_year.test +++ b/mysql-test/t/type_year.test @@ -30,3 +30,109 @@ select * from t1; drop table t1; --echo End of 5.0 tests + +--echo # +--echo # Bug #49480: WHERE using YEAR columns returns unexpected results +--echo # + +CREATE TABLE t2(yy YEAR(2), c2 CHAR(4)); +CREATE TABLE t4(yyyy YEAR(4), c4 CHAR(4)); + +INSERT INTO t2 (c2) VALUES (NULL),(1970),(1999),(2000),(2001),(2069); +INSERT INTO t4 (c4) SELECT c2 FROM t2; +UPDATE t2 SET yy = c2; +UPDATE t4 SET yyyy = c4; + +SELECT * FROM t2; +SELECT * FROM t4; + +--echo # Comparison of YEAR(2) with YEAR(4) + +SELECT * FROM t2, t4 WHERE yy = yyyy; +SELECT * FROM t2, t4 WHERE yy <=> yyyy; +SELECT * FROM t2, t4 WHERE yy < yyyy; +SELECT * FROM t2, t4 WHERE yy > yyyy; + +--echo # Comparison of YEAR(2) with YEAR(2) + +SELECT * FROM t2 a, t2 b WHERE a.yy = b.yy; +SELECT * FROM t2 a, t2 b WHERE a.yy <=> b.yy; +SELECT * FROM t2 a, t2 b WHERE a.yy < b.yy; + +--echo # Comparison of YEAR(4) with YEAR(4) + +SELECT * FROM t4 a, t4 b WHERE a.yyyy = b.yyyy; +SELECT * FROM t4 a, t4 b WHERE a.yyyy <=> b.yyyy; +SELECT * FROM t4 a, t4 b WHERE a.yyyy < b.yyyy; + +--echo # Comparison with constants: + +SELECT * FROM t2 WHERE yy = NULL; +SELECT * FROM t4 WHERE yyyy = NULL; +SELECT * FROM t2 WHERE yy <=> NULL; +SELECT * FROM t4 WHERE yyyy <=> NULL; +SELECT * FROM t2 WHERE yy < NULL; +SELECT * FROM t2 WHERE yy > NULL; + +SELECT * FROM t2 WHERE yy = NOW(); +SELECT * FROM t4 WHERE yyyy = NOW(); + +SELECT * FROM t2 WHERE yy = 99; +SELECT * FROM t2 WHERE 99 = yy; +SELECT * FROM t4 WHERE yyyy = 99; + +SELECT * FROM t2 WHERE yy = 'test'; +SELECT * FROM t4 WHERE yyyy = 'test'; + +SELECT * FROM t2 WHERE yy = '1999'; +SELECT * FROM t4 WHERE yyyy = '1999'; + +SELECT * FROM t2 WHERE yy = 1999; +SELECT * FROM t4 WHERE yyyy = 1999; + +SELECT * FROM t2 WHERE yy = 1999.1; +SELECT * FROM t4 WHERE yyyy = 1999.1; + +SELECT * FROM t2 WHERE yy = 1998.9; +SELECT * FROM t4 WHERE yyyy = 1998.9; + +--echo # Coverage tests for YEAR with zero/2000 constants: + +SELECT * FROM t2 WHERE yy = 0; +SELECT * FROM t2 WHERE yy = '0'; +SELECT * FROM t2 WHERE yy = '0000'; +SELECT * FROM t2 WHERE yy = '2000'; +SELECT * FROM t2 WHERE yy = 2000; + +SELECT * FROM t4 WHERE yyyy = 0; +SELECT * FROM t4 WHERE yyyy = '0'; +SELECT * FROM t4 WHERE yyyy = '0000'; +SELECT * FROM t4 WHERE yyyy = '2000'; +SELECT * FROM t4 WHERE yyyy = 2000; + +--echo # Comparison with constants those are out of YEAR range +--echo # (coverage test for backward compatibility) + +SELECT COUNT(yy) FROM t2; +SELECT COUNT(yyyy) FROM t4; + +SELECT COUNT(*) FROM t2 WHERE yy = -1; +SELECT COUNT(*) FROM t4 WHERE yyyy > -1; +SELECT COUNT(*) FROM t2 WHERE yy > -1000000000000000000; +SELECT COUNT(*) FROM t4 WHERE yyyy > -1000000000000000000; + +SELECT COUNT(*) FROM t2 WHERE yy < 2156; +SELECT COUNT(*) FROM t4 WHERE yyyy < 2156; +SELECT COUNT(*) FROM t2 WHERE yy < 1000000000000000000; +SELECT COUNT(*) FROM t4 WHERE yyyy < 1000000000000000000; + +SELECT * FROM t2 WHERE yy < 123; +SELECT * FROM t2 WHERE yy > 123; +SELECT * FROM t4 WHERE yyyy < 123; +SELECT * FROM t4 WHERE yyyy > 123; + +DROP TABLE t2, t4; + +--echo # + +--echo End of 5.1 tests diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 5415d6f4f8a..ed31c19e676 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -956,40 +956,9 @@ int Arg_comparator::set_cmp_func(Item_result_field *owner_arg, if (agg_item_set_converter(coll, owner->func_name(), b, 1, MY_COLL_CMP_CONV, 1)) return 1; - } else if (type != ROW_RESULT && ((*a)->field_type() == MYSQL_TYPE_YEAR || - (*b)->field_type() == MYSQL_TYPE_YEAR)) - { - is_nulls_eq= is_owner_equal_func(); - year_as_datetime= FALSE; - - if ((*a)->is_datetime()) - { - year_as_datetime= TRUE; - get_value_a_func= &get_datetime_value; - } else if ((*a)->field_type() == MYSQL_TYPE_YEAR) - get_value_a_func= &get_year_value; - else - { - /* - Because convert_constant_item is called only for EXECUTE in PS mode - the value of get_value_x_func set in PREPARE might be not - valid for EXECUTE. - */ - get_value_a_func= NULL; - } - - if ((*b)->is_datetime()) - { - year_as_datetime= TRUE; - get_value_b_func= &get_datetime_value; - } else if ((*b)->field_type() == MYSQL_TYPE_YEAR) - get_value_b_func= &get_year_value; - else - get_value_b_func= NULL; - - func= &Arg_comparator::compare_year; - return 0; } + else if (try_year_cmp_func(type)) + return 0; a= cache_converted_constant(thd, a, &a_cache, type); b= cache_converted_constant(thd, b, &b_cache, type); @@ -997,6 +966,45 @@ int Arg_comparator::set_cmp_func(Item_result_field *owner_arg, } +/* + Helper function to call from Arg_comparator::set_cmp_func() +*/ + +bool Arg_comparator::try_year_cmp_func(Item_result type) +{ + if (type == ROW_RESULT) + return FALSE; + + bool a_is_year= (*a)->field_type() == MYSQL_TYPE_YEAR; + bool b_is_year= (*b)->field_type() == MYSQL_TYPE_YEAR; + + if (!a_is_year && !b_is_year) + return FALSE; + + if (a_is_year && b_is_year) + { + get_value_a_func= &get_year_value; + get_value_b_func= &get_year_value; + } + else if (a_is_year && (*b)->is_datetime()) + { + get_value_a_func= &get_year_value; + get_value_b_func= &get_datetime_value; + } + else if (b_is_year && (*a)->is_datetime()) + { + get_value_b_func= &get_year_value; + get_value_a_func= &get_datetime_value; + } + else + return FALSE; + + is_nulls_eq= is_owner_equal_func(); + func= &Arg_comparator::compare_datetime; + + return TRUE; +} + /** Convert and cache a constant. @@ -1147,7 +1155,7 @@ get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg, /* - Retrieves YEAR value of 19XX form from given item. + Retrieves YEAR value of 19XX-00-00 00:00:00 form from given item. SYNOPSIS get_year_value() @@ -1159,7 +1167,9 @@ get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg, DESCRIPTION Retrieves the YEAR value of 19XX form from given item for comparison by the - compare_year() function. + compare_datetime() function. + Converts year to DATETIME of form YYYY-00-00 00:00:00 for the compatibility + with the get_datetime_value function result. RETURN obtained value @@ -1186,6 +1196,9 @@ get_year_value(THD *thd, Item ***item_arg, Item **cache_arg, if (value <= 1900) value+= 1900; + /* Convert year to DATETIME of form YYYY-00-00 00:00:00 (YYYY0000000000). */ + value*= 10000000000LL; + return value; } @@ -1615,67 +1628,6 @@ int Arg_comparator::compare_e_row() } -/** - Compare values as YEAR. - - @details - Compare items as YEAR for EQUAL_FUNC and for other comparison functions. - The YEAR values of form 19XX are obtained with help of the get_year_value() - function. - If one of arguments is of DATE/DATETIME type its value is obtained - with help of the get_datetime_value function. In this case YEAR values - prior to comparison are converted to the ulonglong YYYY-00-00 00:00:00 - DATETIME form. - If an argument type neither YEAR nor DATE/DATEIME then val_int function - is used to obtain value for comparison. - - RETURN - If is_nulls_eq is TRUE: - 1 if items are equal or both are null - 0 otherwise - If is_nulls_eq is FALSE: - -1 a < b - 0 a == b or at least one of items is null - 1 a > b - See the table: - is_nulls_eq | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | - a_is_null | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | - b_is_null | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | - result | 1 | 0 | 0 |0/1| 0 | 0 | 0 |-1/0/1| -*/ - -int Arg_comparator::compare_year() -{ - bool a_is_null, b_is_null; - ulonglong val1= get_value_a_func ? - (*get_value_a_func)(thd, &a, &a_cache, *b, &a_is_null) : - (*a)->val_int(); - ulonglong val2= get_value_b_func ? - (*get_value_b_func)(thd, &b, &b_cache, *a, &b_is_null) : - (*b)->val_int(); - if (!(*a)->null_value) - { - if (!(*b)->null_value) - { - if (set_null) - owner->null_value= 0; - /* Convert year to DATETIME of form YYYY-00-00 00:00:00 when necessary. */ - if((*a)->field_type() == MYSQL_TYPE_YEAR && year_as_datetime) - val1*= 10000000000LL; - if((*b)->field_type() == MYSQL_TYPE_YEAR && year_as_datetime) - val2*= 10000000000LL; - - if (val1 < val2) return is_nulls_eq ? 0 : -1; - if (val1 == val2) return is_nulls_eq ? 1 : 0; - return is_nulls_eq ? 0 : 1; - } - } - if (set_null) - owner->null_value= is_nulls_eq ? 0 : 1; - return (is_nulls_eq && (*a)->null_value == (*b)->null_value) ? 1 : 0; -} - - void Item_func_truth::fix_length_and_dec() { maybe_null= 0; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 52af6a31c0c..d4542dac820 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -42,24 +42,22 @@ class Arg_comparator: public Sql_alloc bool is_nulls_eq; // TRUE <=> compare for the EQUAL_FUNC bool set_null; // TRUE <=> set owner->null_value // when one of arguments is NULL. - bool year_as_datetime; // TRUE <=> convert YEAR value to - // the YYYY-00-00 00:00:00 DATETIME - // format. See compare_year. enum enum_date_cmp_type { CMP_DATE_DFLT= 0, CMP_DATE_WITH_DATE, CMP_DATE_WITH_STR, CMP_STR_WITH_DATE }; longlong (*get_value_a_func)(THD *thd, Item ***item_arg, Item **cache_arg, Item *warn_item, bool *is_null); longlong (*get_value_b_func)(THD *thd, Item ***item_arg, Item **cache_arg, Item *warn_item, bool *is_null); + bool try_year_cmp_func(Item_result type); public: DTCollation cmp_collation; /* Allow owner function to use string buffers. */ String value1, value2; Arg_comparator(): thd(0), a_cache(0), b_cache(0), set_null(0), - year_as_datetime(0), get_value_a_func(0), get_value_b_func(0) {}; + get_value_a_func(0), get_value_b_func(0) {}; Arg_comparator(Item **a1, Item **a2): a(a1), b(a2), thd(0), - a_cache(0), b_cache(0), set_null(0), year_as_datetime(0), + a_cache(0), b_cache(0), set_null(0), get_value_a_func(0), get_value_b_func(0) {}; int set_compare_func(Item_result_field *owner, Item_result type); @@ -101,7 +99,6 @@ public: int compare_real_fixed(); int compare_e_real_fixed(); int compare_datetime(); // compare args[0] & args[1] as DATETIMEs - int compare_year(); static enum enum_date_cmp_type can_compare_as_dates(Item *a, Item *b, ulonglong *const_val_arg); From ee06414b5a4d1d2f8e2644228349e94f35ad5808 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Thu, 10 Dec 2009 11:28:38 +0200 Subject: [PATCH 043/104] Bug #49250 : spatial btree index corruption and crash SPATIAL and FULLTEXT indexes don't support algorithm selection. Disabled by creating a special grammar rule for these in the parser. Added some encasulation of duplicate parser code. --- mysql-test/r/fulltext.result | 14 +++++ mysql-test/r/gis.result | 13 +++++ mysql-test/t/fulltext.test | 17 ++++++ mysql-test/t/gis.test | 15 +++++ sql/sql_yacc.yy | 110 +++++++++++++++++++++-------------- 5 files changed, 126 insertions(+), 43 deletions(-) diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result index b0197e0aec2..c27915811d6 100644 --- a/mysql-test/r/fulltext.result +++ b/mysql-test/r/fulltext.result @@ -518,3 +518,17 @@ EXECUTE s; MATCH (col) AGAINST('findme') DEALLOCATE PREPARE s; DROP TABLE t1; +# +# Bug #49250 : spatial btree index corruption and crash +# Part two : fulltext syntax check +# +CREATE TABLE t1(col1 TEXT, +FULLTEXT INDEX USING BTREE (col1)); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'USING BTREE (col1))' at line 2 +CREATE TABLE t2(col1 TEXT); +CREATE FULLTEXT INDEX USING BTREE ON t2(col); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'USING BTREE ON t2(col)' at line 1 +ALTER TABLE t2 ADD FULLTEXT INDEX USING BTREE (col1); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'USING BTREE (col1)' at line 1 +DROP TABLE t2; +End of 5.0 tests diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result index 140c133d75f..158fdb69c10 100644 --- a/mysql-test/r/gis.result +++ b/mysql-test/r/gis.result @@ -983,4 +983,17 @@ GEOMFROMTEXT( SELECT 1 FROM t1 WHERE a <> (SELECT GEOMETRYCOLLECTIONFROMWKB(b) FROM t1); 1 DROP TABLE t1; +# +# Bug #49250 : spatial btree index corruption and crash +# Part one : spatial syntax check +# +CREATE TABLE t1(col1 MULTIPOLYGON NOT NULL, +SPATIAL INDEX USING BTREE (col1)); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'USING BTREE (col1))' at line 2 +CREATE TABLE t2(col1 MULTIPOLYGON NOT NULL); +CREATE SPATIAL INDEX USING BTREE ON t2(col); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'USING BTREE ON t2(col)' at line 1 +ALTER TABLE t2 ADD SPATIAL INDEX USING BTREE (col1); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'USING BTREE (col1)' at line 1 +DROP TABLE t2; End of 5.0 tests diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test index 9551c98f143..bcd27e51f24 100644 --- a/mysql-test/t/fulltext.test +++ b/mysql-test/t/fulltext.test @@ -455,3 +455,20 @@ EXECUTE s; DEALLOCATE PREPARE s; DROP TABLE t1; +--echo # +--echo # Bug #49250 : spatial btree index corruption and crash +--echo # Part two : fulltext syntax check +--echo # + +--error ER_PARSE_ERROR +CREATE TABLE t1(col1 TEXT, + FULLTEXT INDEX USING BTREE (col1)); +CREATE TABLE t2(col1 TEXT); +--error ER_PARSE_ERROR +CREATE FULLTEXT INDEX USING BTREE ON t2(col); +--error ER_PARSE_ERROR +ALTER TABLE t2 ADD FULLTEXT INDEX USING BTREE (col1); + +DROP TABLE t2; + +--echo End of 5.0 tests diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test index 701a6cef6be..d2bfe7d90d4 100644 --- a/mysql-test/t/gis.test +++ b/mysql-test/t/gis.test @@ -669,5 +669,20 @@ SELECT 1 FROM t1 WHERE a <> (SELECT GEOMETRYCOLLECTIONFROMWKB(b) FROM t1); DROP TABLE t1; +--echo # +--echo # Bug #49250 : spatial btree index corruption and crash +--echo # Part one : spatial syntax check +--echo # + +--error ER_PARSE_ERROR +CREATE TABLE t1(col1 MULTIPOLYGON NOT NULL, + SPATIAL INDEX USING BTREE (col1)); +CREATE TABLE t2(col1 MULTIPOLYGON NOT NULL); +--error ER_PARSE_ERROR +CREATE SPATIAL INDEX USING BTREE ON t2(col); +--error ER_PARSE_ERROR +ALTER TABLE t2 ADD SPATIAL INDEX USING BTREE (col1); + +DROP TABLE t2; --echo End of 5.0 tests diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 2fc85b4bda7..3cd61605033 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -418,6 +418,34 @@ Item* handle_sql2003_note184_exception(THD *thd, Item* left, bool equal, DBUG_RETURN(result); } + +static bool add_create_index_prepare (LEX *lex, Table_ident *table) +{ + lex->sql_command= SQLCOM_CREATE_INDEX; + if (!lex->current_select->add_table_to_list(lex->thd, table, NULL, + TL_OPTION_UPDATING)) + return TRUE; + lex->alter_info.reset(); + lex->alter_info.flags= ALTER_ADD_INDEX; + lex->col_list.empty(); + lex->change= NullS; + return FALSE; +} + + +static bool add_create_index (LEX *lex, + Key::Keytype type, const char *name, enum ha_key_alg key_alg, + bool generated= 0) +{ + Key *key= new Key(type, name, key_alg, generated, lex->col_list); + if (key == NULL) + return TRUE; + + lex->alter_info.key_list.push_back(key); + lex->col_list.empty(); + return FALSE; +} + %} %union { int num; @@ -1110,7 +1138,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); option_type opt_var_type opt_var_ident_type %type - key_type opt_unique_or_fulltext constraint_key_type + key_type opt_unique fulltext_or_spatial constraint_key_type + key_type_fulltext_or_spatial %type key_alg opt_btree_or_rtree @@ -1543,27 +1572,25 @@ create: } create2 { Lex->current_select= &Lex->select_lex; } - | CREATE opt_unique_or_fulltext INDEX_SYM ident key_alg ON table_ident + | CREATE opt_unique INDEX_SYM ident key_alg ON table_ident { - LEX *lex=Lex; - lex->sql_command= SQLCOM_CREATE_INDEX; - if (!lex->current_select->add_table_to_list(lex->thd, $7, NULL, - TL_OPTION_UPDATING)) - MYSQL_YYABORT; - lex->alter_info.reset(); - lex->alter_info.flags= ALTER_ADD_INDEX; - lex->col_list.empty(); - lex->change=NullS; - } - '(' key_list ')' - { - LEX *lex=Lex; - Key *key= new Key($2, $4.str, $5, 0, lex->col_list); - if (key == NULL) + if (add_create_index_prepare (Lex, $7)) + MYSQL_YYABORT; + } + '(' key_list ')' + { + if (add_create_index (Lex, $2, $4.str, $5)) + MYSQL_YYABORT; + } + | CREATE fulltext_or_spatial INDEX_SYM ident ON table_ident + { + if (add_create_index_prepare (Lex, $6)) + MYSQL_YYABORT; + } + '(' key_list ')' + { + if (add_create_index (Lex, $2, $4.str, HA_KEY_ALG_UNDEF)) MYSQL_YYABORT; - - lex->alter_info.key_list.push_back(key); - lex->col_list.empty(); } | CREATE DATABASE opt_if_not_exists ident { @@ -3133,23 +3160,18 @@ column_def: key_def: key_type opt_ident key_alg '(' key_list ')' key_alg { - LEX *lex=Lex; - Key *key= new Key($1, $2, $7 ? $7 : $3, 0, lex->col_list); - if (key == NULL) + if (add_create_index (Lex, $1, $2, $7 ? $7 : $3)) + MYSQL_YYABORT; + } + | key_type_fulltext_or_spatial opt_ident '(' key_list ')' + { + if (add_create_index (Lex, $1, $2, HA_KEY_ALG_UNDEF)) MYSQL_YYABORT; - lex->alter_info.key_list.push_back(key); - - lex->col_list.empty(); /* Alloced by sql_alloc */ } | opt_constraint constraint_key_type opt_ident key_alg '(' key_list ')' key_alg { - LEX *lex=Lex; - const char *key_name= $3 ? $3:$1; - Key *key= new Key($2, key_name, $4, 0, lex->col_list); - if (key == NULL) + if (add_create_index (Lex, $2, $3 ? $3:$1, $4)) MYSQL_YYABORT; - lex->alter_info.key_list.push_back(key); - lex->col_list.empty(); /* Alloced by sql_alloc */ } | opt_constraint FOREIGN KEY_SYM opt_ident '(' key_list ')' references { @@ -3164,13 +3186,9 @@ key_def: if (key == NULL) MYSQL_YYABORT; lex->alter_info.key_list.push_back(key); - key= new Key(Key::MULTIPLE, key_name, - HA_KEY_ALG_UNDEF, 1, - lex->col_list); - if (key == NULL) + if (add_create_index (lex, Key::MULTIPLE, key_name, + HA_KEY_ALG_UNDEF, 1)) MYSQL_YYABORT; - lex->alter_info.key_list.push_back(key); - lex->col_list.empty(); /* Alloced by sql_alloc */ } | constraint opt_check_constraint { @@ -3630,7 +3648,10 @@ delete_option: key_type: key_or_index { $$= Key::MULTIPLE; } - | FULLTEXT_SYM opt_key_or_index { $$= Key::FULLTEXT; } + ; + +key_type_fulltext_or_spatial: + FULLTEXT_SYM opt_key_or_index { $$= Key::FULLTEXT; } | SPATIAL_SYM opt_key_or_index { #ifdef HAVE_SPATIAL @@ -3660,10 +3681,8 @@ keys_or_index: | INDEX_SYM {} | INDEXES {}; -opt_unique_or_fulltext: - /* empty */ { $$= Key::MULTIPLE; } - | UNIQUE_SYM { $$= Key::UNIQUE; } - | FULLTEXT_SYM { $$= Key::FULLTEXT;} +fulltext_or_spatial: + FULLTEXT_SYM { $$= Key::FULLTEXT;} | SPATIAL_SYM { #ifdef HAVE_SPATIAL @@ -3676,6 +3695,11 @@ opt_unique_or_fulltext: } ; +opt_unique: + /* empty */ { $$= Key::MULTIPLE; } + | UNIQUE_SYM { $$= Key::UNIQUE; } + ; + key_alg: /* empty */ { $$= HA_KEY_ALG_UNDEF; } | USING opt_btree_or_rtree { $$= $2; } From af22ba911e32f8d82473fa4d2ef36be923193427 Mon Sep 17 00:00:00 2001 From: Date: Fri, 11 Dec 2009 09:57:38 +0800 Subject: [PATCH 044/104] Bug #48742 Replication: incorrect help text for --init-slave The help text for --init-slave=name: "Command(s) that are executed when a slave connects to this master". This text indicate that the --init-slave option is set on a master server, and the master server passes the option's argument to slave which connects to it. This is wrong. Actually the --init-slave option just can be set on a slave server, and then the slave server executes the argument each time the SQL thread starts. Correct the help text for --init-slave option as following: "Command(s) that are executed by a slave server each time the SQL thread starts." --- sql/mysqld.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index ce1d562d0ca..b4eb96ab65a 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5275,7 +5275,8 @@ Disable with --skip-large-pages.", #endif {"init-rpl-role", OPT_INIT_RPL_ROLE, "Set the replication role.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"init-slave", OPT_INIT_SLAVE, "Command(s) that are executed when a slave connects to this master", + {"init-slave", OPT_INIT_SLAVE, "Command(s) that are executed by a slave server \ +each time the SQL thread starts.", (gptr*) &opt_init_slave, (gptr*) &opt_init_slave, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"innodb", OPT_INNODB, "Enable InnoDB (if this version of MySQL supports it). \ From e3df8b6d9a27c1ecd9383a0c5619576d41454c7f Mon Sep 17 00:00:00 2001 From: V Narayanan Date: Fri, 11 Dec 2009 12:31:16 +0530 Subject: [PATCH 045/104] Bug#49329 example (and other) engines use wrong collation for open tables hash This fix changes the character set used within the IBMDB2I handler to hash table names to information about open tables. Previously, tables with names that differed only in letter case would hash to the same data structure. This caused incorrect behavior or errors when two such tables were in use simultaneously. --- mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_49329.result | 9 +++++++++ mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_49329.test | 10 ++++++++++ storage/ibmdb2i/ha_ibmdb2i.cc | 2 +- 3 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_49329.result create mode 100644 mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_49329.test diff --git a/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_49329.result b/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_49329.result new file mode 100644 index 00000000000..d5bfc2579fd --- /dev/null +++ b/mysql-test/suite/ibmdb2i/r/ibmdb2i_bug_49329.result @@ -0,0 +1,9 @@ +create table ABC (i int) engine=ibmdb2i; +insert into ABC values(1); +create table abc (i int) engine=ibmdb2i; +insert into abc values (2); +select * from ABC; +i +1 +drop table ABC; +drop table abc; diff --git a/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_49329.test b/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_49329.test new file mode 100644 index 00000000000..615df284d8f --- /dev/null +++ b/mysql-test/suite/ibmdb2i/t/ibmdb2i_bug_49329.test @@ -0,0 +1,10 @@ +source suite/ibmdb2i/include/have_ibmdb2i.inc; +source include/have_case_sensitive_file_system.inc; + +create table ABC (i int) engine=ibmdb2i; +insert into ABC values(1); +create table abc (i int) engine=ibmdb2i; +insert into abc values (2); +select * from ABC; +drop table ABC; +drop table abc; diff --git a/storage/ibmdb2i/ha_ibmdb2i.cc b/storage/ibmdb2i/ha_ibmdb2i.cc index 0fc2d1e83dc..39096be7848 100644 --- a/storage/ibmdb2i/ha_ibmdb2i.cc +++ b/storage/ibmdb2i/ha_ibmdb2i.cc @@ -284,7 +284,7 @@ static int ibmdb2i_init_func(void *p) was_ILE_inited = false; ibmdb2i_hton= (handlerton *)p; VOID(pthread_mutex_init(&ibmdb2i_mutex,MY_MUTEX_INIT_FAST)); - (void) hash_init(&ibmdb2i_open_tables,system_charset_info,32,0,0, + (void) hash_init(&ibmdb2i_open_tables,table_alias_charset,32,0,0, (hash_get_key) ibmdb2i_get_key,0,0); ibmdb2i_hton->state= SHOW_OPTION_YES; From 1704a8a937b5f14ae79bf6ff4accbe5e4f0ffc06 Mon Sep 17 00:00:00 2001 From: V Narayanan Date: Fri, 11 Dec 2009 12:46:57 +0530 Subject: [PATCH 046/104] Bug#49521 SHOW CREATE TABLE on IBMDB2I tables has incorrect fk constraint format The fix inserts newline and comma characters as appropriate into the constraint reporting code to match the formatting required by SHOW CREATE TABLE. Additionally, a erroneously duplicated copy of check_if_incompatible_data() was removed from db2i_constraints.cc since the correct version is already in ha_ibmdb2i.cc. --- storage/ibmdb2i/db2i_constraints.cc | 28 +--------------------------- 1 file changed, 1 insertion(+), 27 deletions(-) diff --git a/storage/ibmdb2i/db2i_constraints.cc b/storage/ibmdb2i/db2i_constraints.cc index 9a96eda1173..1fde0dd3d14 100644 --- a/storage/ibmdb2i/db2i_constraints.cc +++ b/storage/ibmdb2i/db2i_constraints.cc @@ -329,7 +329,7 @@ char* ha_ibmdb2i::get_foreign_key_create_info(void) /* Process the constraint name. */ - info.strncat(STRING_WITH_LEN(" CONSTRAINT ")); + info.strncat(STRING_WITH_LEN(",\n CONSTRAINT ")); convNameForCreateInfo(thd, info, FKCstDef->CstName.Name, FKCstDef->CstName.Len); @@ -398,7 +398,6 @@ char* ha_ibmdb2i::get_foreign_key_create_info(void) if ((i+1) < cstCnt) { - info.strcat(','); tempPtr = (char*)cstHdr + cstHdr->CstLen; cstHdr = (constraint_hdr_t*)(tempPtr); } @@ -671,28 +670,3 @@ uint ha_ibmdb2i::referenced_by_foreign_key(void) } DBUG_RETURN(count); } - - -bool ha_ibmdb2i::check_if_incompatible_data(HA_CREATE_INFO *info, - uint table_changes) -{ - DBUG_ENTER("ha_ibmdb2i::check_if_incompatible_data"); - uint i; - /* Check that auto_increment value and field definitions were - not changed. */ - if ((info->used_fields & HA_CREATE_USED_AUTO && - info->auto_increment_value != 0) || - table_changes != IS_EQUAL_YES) - DBUG_RETURN(COMPATIBLE_DATA_NO); - /* Check if any fields were renamed. */ - for (i= 0; i < table->s->fields; i++) - { - Field *field= table->field[i]; - if (field->flags & FIELD_IS_RENAMED) - { - DBUG_PRINT("info", ("Field has been renamed, copy table")); - DBUG_RETURN(COMPATIBLE_DATA_NO); - } - } - DBUG_RETURN(COMPATIBLE_DATA_YES); -} From b3eb974ac70527354fc11b5d54497c5bdde92b2a Mon Sep 17 00:00:00 2001 From: "Horst.Hunger" Date: Fri, 11 Dec 2009 09:30:17 +0100 Subject: [PATCH 047/104] Fix for bug#46117: This test is replaced by plugin.test also containing a CRESTE TABLE on example db. Example DB only exists as plugin. --- mysql-test/r/exampledb.result | 8 -------- mysql-test/t/exampledb.test | 22 ---------------------- 2 files changed, 30 deletions(-) delete mode 100644 mysql-test/r/exampledb.result delete mode 100644 mysql-test/t/exampledb.test diff --git a/mysql-test/r/exampledb.result b/mysql-test/r/exampledb.result deleted file mode 100644 index 6eea24e2e1f..00000000000 --- a/mysql-test/r/exampledb.result +++ /dev/null @@ -1,8 +0,0 @@ -drop database if exists events_test; -drop database if exists events_test2; -drop table if exists t1; -CREATE TABLE t1 ( -Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, -Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL -) ENGINE=example; -drop table t1; diff --git a/mysql-test/t/exampledb.test b/mysql-test/t/exampledb.test deleted file mode 100644 index fbb2a18f344..00000000000 --- a/mysql-test/t/exampledb.test +++ /dev/null @@ -1,22 +0,0 @@ -# -# Simple test for the example storage engine -# Taken fromm the select test -# --- source include/have_exampledb.inc - ---disable_warnings -# Clean up if event's test fails -drop database if exists events_test; -drop database if exists events_test2; - -drop table if exists t1; ---enable_warnings - -CREATE TABLE t1 ( - Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, - Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL -) ENGINE=example; - -drop table t1; - -# End of 4.1 tests From 98f738b1986bc7a6f3755a30841c084f12e6e051 Mon Sep 17 00:00:00 2001 From: Kent Boortz Date: Fri, 11 Dec 2009 19:11:49 +0100 Subject: [PATCH 048/104] Define _WIN32_WINNT to the minimum supported Windows version, 0x0500 i.e Windows 2000. Visual Studio 2003 and 2005 require _WIN32_WINNT >= 0x0500 (Win2000) for TryEnterCriticalSection. --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5705a2dfe57..bd597cf29c9 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -146,6 +146,7 @@ IF(MSVC) ENDIF(MSVC) ADD_DEFINITIONS("-D_WINDOWS -D__WIN__ -D_CRT_SECURE_NO_DEPRECATE") +ADD_DEFINITIONS("-D_WIN32_WINNT=0x0500") # This definition is necessary to work around a bug with Intellisense described # here: http://tinyurl.com/2cb428. Syntax highlighting is important for proper From eadf9532fdee35e86544e13911549475af979f98 Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Fri, 11 Dec 2009 12:45:44 -0700 Subject: [PATCH 049/104] Merge cleanup --- include/my_pthread.h | 2 -- sql/ha_ndbcluster.cc | 2 +- sql/ha_ndbcluster_binlog.cc | 2 +- sql/lock.cc | 2 +- sql/mysqld.cc | 10 +++++----- sql/sql_base.cc | 18 +++++++++--------- sql/sql_delete.cc | 2 +- sql/sql_handler.cc | 3 ++- sql/sql_parse.cc | 2 +- sql/sql_rename.cc | 2 +- sql/sql_show.cc | 2 +- sql/sql_table.cc | 2 +- sql/sql_test.cc | 2 +- sql/sql_trigger.cc | 2 +- sql/sql_view.cc | 2 +- 15 files changed, 27 insertions(+), 28 deletions(-) diff --git a/include/my_pthread.h b/include/my_pthread.h index bfb5a2f67f4..0b59aad56f9 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -148,8 +148,6 @@ int pthread_join(pthread_t thread, void **value_ptr); #define pthread_detach_this_thread() #define pthread_condattr_init(A) #define pthread_condattr_destroy(A) -#define pthread_yield() SwitchToThread() - /* per the platform's documentation */ #define pthread_yield() Sleep(0) diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index b60b9463c6b..1103683b56c 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright (C) 2000-2003 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc index 285df1a3313..bdbb57224b0 100644 --- a/sql/ha_ndbcluster_binlog.cc +++ b/sql/ha_ndbcluster_binlog.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright (C) 2000-2003 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sql/lock.cc b/sql/lock.cc index 03524712259..e60259f6acc 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -1,4 +1,4 @@ -/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. +/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 899e5fbbe30..764d799f1f7 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1,4 +1,4 @@ -/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. +/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -648,7 +648,7 @@ SHOW_COMP_OPTION have_profiling; pthread_key(MEM_ROOT**,THR_MALLOC); pthread_key(THD*, THR_THD); pthread_mutex_t LOCK_thread_count, - LOCK_mapped_file, LOCK_global_read_lock, + LOCK_mapped_file, LOCK_global_read_lock, LOCK_error_log, LOCK_uuid_generator, LOCK_crypt, LOCK_global_system_variables, @@ -964,9 +964,9 @@ static void close_connections(void) mysql_mutex_lock(&tmp->mysys_var->mutex); if (tmp->mysys_var->current_cond) { - mysql_mutex_lock(tmp->mysys_var->current_mutex); - mysql_cond_broadcast(tmp->mysys_var->current_cond); - mysql_mutex_unlock(tmp->mysys_var->current_mutex); + mysql_mutex_lock(tmp->mysys_var->current_mutex); + mysql_cond_broadcast(tmp->mysys_var->current_cond); + mysql_mutex_unlock(tmp->mysys_var->current_mutex); } mysql_mutex_unlock(&tmp->mysys_var->mutex); } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 03cd9943dea..c5861af9c5d 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1,4 +1,4 @@ -/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. +/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -994,7 +994,7 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock, { found=1; DBUG_PRINT("signal", ("Waiting for COND_refresh")); - mysql_cond_wait(&COND_refresh, &LOCK_open); + mysql_cond_wait(&COND_refresh, &LOCK_open); break; } } @@ -2825,7 +2825,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, /* Avoid self-deadlocks by detecting self-dependencies. */ if (table->open_placeholder && table->in_use == thd) { - mysql_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); my_error(ER_UPDATE_TABLE_USED, MYF(0), table->s->table_name.str); DBUG_RETURN(0); } @@ -2866,7 +2866,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, } else { - mysql_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } /* There is a refresh in progress for this table. @@ -8503,15 +8503,15 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name, ! in_use->killed) { in_use->killed= THD::KILL_CONNECTION; - mysql_mutex_lock(&in_use->mysys_var->mutex); + mysql_mutex_lock(&in_use->mysys_var->mutex); if (in_use->mysys_var->current_cond) { - mysql_mutex_lock(in_use->mysys_var->current_mutex); + mysql_mutex_lock(in_use->mysys_var->current_mutex); signalled= 1; - mysql_cond_broadcast(in_use->mysys_var->current_cond); - mysql_mutex_unlock(in_use->mysys_var->current_mutex); + mysql_cond_broadcast(in_use->mysys_var->current_cond); + mysql_mutex_unlock(in_use->mysys_var->current_mutex); } - mysql_mutex_unlock(&in_use->mysys_var->mutex); + mysql_mutex_unlock(&in_use->mysys_var->mutex); } /* Now we must abort all tables locks used by this thread diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index d0988ea46f8..1b54f2a76e4 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index b6c399d9908..5b45c35dd22 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -1,4 +1,5 @@ -/* Copyright (C) 2000-2004 MySQL AB +/* Copyright (C) 2000-2004 MySQL AB, 2008-2009 Sun Microsystems, Inc + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index f1cf6380a9b..bdadec180f5 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1,4 +1,4 @@ -/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. +/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index 18ec7f76032..7c52a12c072 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2006 MySQL AB +/* Copyright (C) 2000-2006 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 2f6b60bbd0f..b91dfeec011 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1,4 +1,4 @@ -/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. +/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sql/sql_table.cc b/sql/sql_table.cc index c04a0be7c2f..69de97847cf 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1,4 +1,4 @@ -/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. +/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sql/sql_test.cc b/sql/sql_test.cc index 56ca7111e86..ac1dae3197d 100644 --- a/sql/sql_test.cc +++ b/sql/sql_test.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2006 MySQL AB +/* Copyright (C) 2000-2006 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 154e08aa3d4..4ab9bba03ae 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2004-2005 MySQL AB +/* Copyright (C) 2004-2005 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 8d2d03583de..f511cace885 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2004 MySQL AB +/* Copyright (C) 2004 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by From 6fd94f683874571c98c3111c174ff45023bfc557 Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Sat, 12 Dec 2009 00:06:54 +0300 Subject: [PATCH 050/104] Streamlined the test case for bug #49199 in mysql-trunk-merge to take into account the changes introduced by the fix for bug #30302. --- mysql-test/r/select.result | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 86f85feb2da..a126ca26257 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -4454,7 +4454,7 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:0 id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 system NULL NULL NULL NULL 1 100.00 Warnings: -Note 1003 select '2001-01-01 00:00:00' AS `a` from `test`.`t1` where 1 +Note 1003 select '2001-01-01 00:00:00' AS `a` from dual where 1 DROP TABLE t1; CREATE TABLE t1(a DATE NOT NULL); INSERT INTO t1 VALUES('2001-01-01'); @@ -4465,7 +4465,7 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:0 id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 system NULL NULL NULL NULL 1 100.00 Warnings: -Note 1003 select '2001-01-01' AS `a` from `test`.`t1` where 1 +Note 1003 select '2001-01-01' AS `a` from dual where 1 DROP TABLE t1; CREATE TABLE t1(a TIMESTAMP NOT NULL); INSERT INTO t1 VALUES('2001-01-01'); @@ -4476,7 +4476,7 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:0 id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 system NULL NULL NULL NULL 1 100.00 Warnings: -Note 1003 select '2001-01-01 00:00:00' AS `a` from `test`.`t1` where 1 +Note 1003 select '2001-01-01 00:00:00' AS `a` from dual where 1 DROP TABLE t1; CREATE TABLE t1(a DATETIME NOT NULL, b DATE NOT NULL); INSERT INTO t1 VALUES('2001-01-01', '2001-01-01'); @@ -4487,7 +4487,7 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a=b AND b='2001-01-01 id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 system NULL NULL NULL NULL 1 100.00 Warnings: -Note 1003 select '2001-01-01 00:00:00' AS `a`,'2001-01-01' AS `b` from `test`.`t1` where 1 +Note 1003 select '2001-01-01 00:00:00' AS `a`,'2001-01-01' AS `b` from dual where 1 DROP TABLE t1; CREATE TABLE t1(a DATETIME NOT NULL, b VARCHAR(20) NOT NULL); INSERT INTO t1 VALUES('2001-01-01', '2001-01-01'); @@ -4497,7 +4497,7 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a=b AND b='2001-01-01 id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables Warnings: -Note 1003 select '2001-01-01 00:00:00' AS `a`,'2001-01-01' AS `b` from `test`.`t1` where 0 +Note 1003 select '2001-01-01 00:00:00' AS `a`,'2001-01-01' AS `b` from dual where 0 SELECT * FROM t1 WHERE a='2001-01-01 00:00:00' AND a=b AND b='2001-01-01'; a b 2001-01-01 00:00:00 2001-01-01 @@ -4505,7 +4505,7 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01 00:00:00' AND a=b AND b='2 id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 system NULL NULL NULL NULL 1 100.00 Warnings: -Note 1003 select '2001-01-01 00:00:00' AS `a`,'2001-01-01' AS `b` from `test`.`t1` where 1 +Note 1003 select '2001-01-01 00:00:00' AS `a`,'2001-01-01' AS `b` from dual where 1 DROP TABLE t1; CREATE TABLE t1(a DATETIME NOT NULL, b DATE NOT NULL); INSERT INTO t1 VALUES('2001-01-01', '2001-01-01'); @@ -4524,7 +4524,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE y system NULL NULL NULL NULL 1 100.00 1 SIMPLE z system NULL NULL NULL NULL 1 100.00 Warnings: -Note 1003 select '2001-01-01 00:00:00' AS `a`,'2001-01-01 00:00:00' AS `a`,'2001-01-01 00:00:00' AS `a` from `test`.`t1` `x` join `test`.`t1` `y` join `test`.`t1` `z` where 1 +Note 1003 select '2001-01-01 00:00:00' AS `a`,'2001-01-01 00:00:00' AS `a`,'2001-01-01 00:00:00' AS `a` from dual where 1 DROP TABLE t1; End of 5.0 tests create table t1(a INT, KEY (a)); From 72cceeece222fc3836e21b6a14fc7184966823ad Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Sat, 12 Dec 2009 10:04:52 +0300 Subject: [PATCH 051/104] Disabled binlog.binlog_index, bug#49638. --- mysql-test/suite/binlog/t/disabled.def | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/suite/binlog/t/disabled.def b/mysql-test/suite/binlog/t/disabled.def index 0018387de94..43bc734035d 100644 --- a/mysql-test/suite/binlog/t/disabled.def +++ b/mysql-test/suite/binlog/t/disabled.def @@ -10,4 +10,4 @@ # ############################################################################## binlog_truncate_innodb : BUG#42643 2009-02-06 mats Changes to InnoDB requires to complete fix for BUG#36763 - +binlog_index : BUG#49638 2009-12-12 kaamos From 983770aa6aaa3ce7a231a80472e0ebb7095c9f86 Mon Sep 17 00:00:00 2001 From: Staale Smedseng Date: Sat, 12 Dec 2009 19:11:25 +0100 Subject: [PATCH 052/104] Bug #45058 init_available_charsets uses double checked locking As documented in the bug report, the double checked locking pattern has inherent issues, and cannot guarantee correct initialization. This patch replaces the logic in init_available_charsets() with the use of pthread_once(3). A wrapper function, my_pthread_once(), is introduced and is used in lieu of direct calls to init_available_charsets(). Related defines MY_PTHREAD_ONCE_* are also introduced. For the Windows platform, the implementation in lp:sysbench is ported. For single-thread use, a simple define calls the function and sets the pthread_once control variable. Charset initialization is modified to use my_pthread_once(). --- include/my_no_pthread.h | 8 +++++ include/my_pthread.h | 10 ++++++ include/my_sys.h | 1 - libmysql/libmysql.c | 1 - mysys/charset.c | 77 +++++++++++++---------------------------- mysys/my_init.c | 1 - mysys/my_winthread.c | 32 +++++++++++++++++ netware/libmysqlmain.c | 4 +-- sql/mysqld.cc | 1 - 9 files changed, 77 insertions(+), 58 deletions(-) diff --git a/include/my_no_pthread.h b/include/my_no_pthread.h index b11dbff42f0..511fac407d5 100644 --- a/include/my_no_pthread.h +++ b/include/my_no_pthread.h @@ -47,4 +47,12 @@ #define rw_unlock(A) #define rwlock_destroy(A) +typedef int my_pthread_once_t; +#define MY_PTHREAD_ONCE_INIT 0 +#define MY_PTHREAD_ONCE_DONE 1 + +#define my_pthread_once(C,F) do { \ + if (*(C) != MY_PTHREAD_ONCE_DONE) { F(); *(C)= MY_PTHREAD_ONCE_DONE; } \ + } while(0) + #endif diff --git a/include/my_pthread.h b/include/my_pthread.h index 151cb34faff..e9256610ea7 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -69,6 +69,11 @@ typedef int pthread_mutexattr_t; #define pthread_handler_t EXTERNC void * __cdecl typedef void * (__cdecl *pthread_handler)(void *); +typedef volatile LONG my_pthread_once_t; +#define MY_PTHREAD_ONCE_INIT 0 +#define MY_PTHREAD_ONCE_INPROGRESS 1 +#define MY_PTHREAD_ONCE_DONE 2 + /* Struct and macros to be used in combination with the windows implementation of pthread_cond_timedwait @@ -114,6 +119,7 @@ int pthread_attr_init(pthread_attr_t *connect_att); int pthread_attr_setstacksize(pthread_attr_t *connect_att,DWORD stack); int pthread_attr_setprio(pthread_attr_t *connect_att,int priority); int pthread_attr_destroy(pthread_attr_t *connect_att); +int my_pthread_once(my_pthread_once_t *once_control,void (*init_routine)(void)); struct tm *localtime_r(const time_t *timep,struct tm *tmp); struct tm *gmtime_r(const time_t *timep,struct tm *tmp); @@ -210,6 +216,10 @@ extern int my_pthread_getprio(pthread_t thread_id); #define pthread_handler_t EXTERNC void * typedef void *(* pthread_handler)(void *); +#define my_pthread_once_t pthread_once_t +#define MY_PTHREAD_ONCE_INIT PTHREAD_ONCE_INIT +#define my_pthread_once(C,F) pthread_once(C,F) + /* Test first for RTS or FSU threads */ #if defined(PTHREAD_SCOPE_GLOBAL) && !defined(PTHREAD_SCOPE_SYSTEM) diff --git a/include/my_sys.h b/include/my_sys.h index b4aac3a17bd..a4ff5c30de7 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -951,7 +951,6 @@ extern my_bool resolve_collation(const char *cl_name, CHARSET_INFO *default_cl, CHARSET_INFO **cl); -extern void free_charsets(void); extern char *get_charsets_dir(char *buf); extern my_bool my_charset_same(CHARSET_INFO *cs1, CHARSET_INFO *cs2); extern my_bool init_compiled_charsets(myf flags); diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 1264f2765ba..36b1d9cac72 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -211,7 +211,6 @@ void STDCALL mysql_server_end() } else { - free_charsets(); mysql_thread_end(); } diff --git a/mysys/charset.c b/mysys/charset.c index b23ab084e90..d59be4ab6c7 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -321,7 +321,6 @@ static int add_collation(CHARSET_INFO *cs) #define MY_CHARSET_INDEX "Index.xml" const char *charsets_dir= NULL; -static int charset_initialized=0; static my_bool my_read_charset_file(const char *filename, myf myflags) @@ -399,63 +398,37 @@ static void *cs_alloc(size_t size) } -#ifdef __NETWARE__ -my_bool STDCALL init_available_charsets(myf myflags) -#else -static my_bool init_available_charsets(myf myflags) -#endif +static my_pthread_once_t charsets_initialized= MY_PTHREAD_ONCE_INIT; + +static void init_available_charsets(void) { char fname[FN_REFLEN + sizeof(MY_CHARSET_INDEX)]; - my_bool error=FALSE; - /* - We have to use charset_initialized to not lock on THR_LOCK_charset - inside get_internal_charset... - */ - if (!charset_initialized) + CHARSET_INFO **cs; + + bzero(&all_charsets,sizeof(all_charsets)); + init_compiled_charsets(MYF(0)); + + /* Copy compiled charsets */ + for (cs=all_charsets; + cs < all_charsets+array_elements(all_charsets)-1 ; + cs++) { - CHARSET_INFO **cs; - /* - To make things thread safe we are not allowing other threads to interfere - while we may changing the cs_info_table - */ - pthread_mutex_lock(&THR_LOCK_charset); - if (!charset_initialized) + if (*cs) { - bzero(&all_charsets,sizeof(all_charsets)); - init_compiled_charsets(myflags); - - /* Copy compiled charsets */ - for (cs=all_charsets; - cs < all_charsets+array_elements(all_charsets)-1 ; - cs++) - { - if (*cs) - { - if (cs[0]->ctype) - if (init_state_maps(*cs)) - *cs= NULL; - } - } - - strmov(get_charsets_dir(fname), MY_CHARSET_INDEX); - error= my_read_charset_file(fname,myflags); - charset_initialized=1; + if (cs[0]->ctype) + if (init_state_maps(*cs)) + *cs= NULL; } - pthread_mutex_unlock(&THR_LOCK_charset); } - return error; -} - - -void free_charsets(void) -{ - charset_initialized=0; + + strmov(get_charsets_dir(fname), MY_CHARSET_INDEX); + my_read_charset_file(fname, MYF(0)); } uint get_collation_number(const char *name) { - init_available_charsets(MYF(0)); + my_pthread_once(&charsets_initialized, init_available_charsets); return get_collation_number_internal(name); } @@ -463,7 +436,7 @@ uint get_collation_number(const char *name) uint get_charset_number(const char *charset_name, uint cs_flags) { CHARSET_INFO **cs; - init_available_charsets(MYF(0)); + my_pthread_once(&charsets_initialized, init_available_charsets); for (cs= all_charsets; cs < all_charsets+array_elements(all_charsets)-1 ; @@ -480,7 +453,7 @@ uint get_charset_number(const char *charset_name, uint cs_flags) const char *get_charset_name(uint charset_number) { CHARSET_INFO *cs; - init_available_charsets(MYF(0)); + my_pthread_once(&charsets_initialized, init_available_charsets); cs=all_charsets[charset_number]; if (cs && (cs->number == charset_number) && cs->name ) @@ -538,7 +511,7 @@ CHARSET_INFO *get_charset(uint cs_number, myf flags) if (cs_number == default_charset_info->number) return default_charset_info; - (void) init_available_charsets(MYF(0)); /* If it isn't initialized */ + my_pthread_once(&charsets_initialized, init_available_charsets); if (!cs_number || cs_number >= array_elements(all_charsets)-1) return NULL; @@ -560,7 +533,7 @@ CHARSET_INFO *get_charset_by_name(const char *cs_name, myf flags) { uint cs_number; CHARSET_INFO *cs; - (void) init_available_charsets(MYF(0)); /* If it isn't initialized */ + my_pthread_once(&charsets_initialized, init_available_charsets); cs_number=get_collation_number(cs_name); cs= cs_number ? get_internal_charset(cs_number,flags) : NULL; @@ -585,7 +558,7 @@ CHARSET_INFO *get_charset_by_csname(const char *cs_name, DBUG_ENTER("get_charset_by_csname"); DBUG_PRINT("enter",("name: '%s'", cs_name)); - (void) init_available_charsets(MYF(0)); /* If it isn't initialized */ + my_pthread_once(&charsets_initialized, init_available_charsets); cs_number= get_charset_number(cs_name, cs_flags); cs= cs_number ? get_internal_charset(cs_number, flags) : NULL; diff --git a/mysys/my_init.c b/mysys/my_init.c index a60927be693..453c72f999f 100644 --- a/mysys/my_init.c +++ b/mysys/my_init.c @@ -165,7 +165,6 @@ void my_end(int infoflag) my_print_open_files(); } } - free_charsets(); my_error_unregister_all(); my_once_free(); diff --git a/mysys/my_winthread.c b/mysys/my_winthread.c index e94369bec32..ef2a20c2ddc 100644 --- a/mysys/my_winthread.c +++ b/mysys/my_winthread.c @@ -137,4 +137,36 @@ int win_pthread_setspecific(void *a,void *b,uint length) return 0; } + +/* + One time initialization. For simplicity, we assume initializer thread + does not exit within init_routine(). +*/ +int my_pthread_once(my_pthread_once_t *once_control, + void (*init_routine)(void)) +{ + LONG state= InterlockedCompareExchange(once_control, MY_PTHREAD_ONCE_INPROGRESS, + MY_PTHREAD_ONCE_INIT); + switch(state) + { + case MY_PTHREAD_ONCE_INIT: + /* This is initializer thread */ + (*init_routine)(); + *once_control= MY_PTHREAD_ONCE_DONE; + break; + + case MY_PTHREAD_ONCE_INPROGRESS: + /* init_routine in progress. Wait for its completion */ + while(*once_control == MY_PTHREAD_ONCE_INPROGRESS) + { + Sleep(1); + } + break; + case MY_PTHREAD_ONCE_DONE: + /* Nothing to do */ + break; + } + return 0; +} + #endif diff --git a/netware/libmysqlmain.c b/netware/libmysqlmain.c index 03fdb832176..2b6ea9b7e27 100644 --- a/netware/libmysqlmain.c +++ b/netware/libmysqlmain.c @@ -18,7 +18,7 @@ #include "my_global.h" -my_bool init_available_charsets(myf myflags); +void init_available_charsets(void); /* this function is required so that global memory is allocated against this library nlm, and not against a paticular client */ @@ -31,7 +31,7 @@ int _NonAppStart(void *NLMHandle, void *errorScreen, const char *commandLine, { mysql_server_init(0, NULL, NULL); - init_available_charsets(MYF(0)); + init_available_charsets(); return 0; } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 9aff751ad2f..b145c5ace10 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1287,7 +1287,6 @@ void clean_up(bool print_message) lex_free(); /* Free some memory */ item_create_cleanup(); set_var_free(); - free_charsets(); if (!opt_noacl) { #ifdef HAVE_DLOPEN From a8cfe3d4f74db680084c3ec8a8b6fbd8f71780d6 Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Sun, 13 Dec 2009 23:29:50 +0300 Subject: [PATCH 053/104] Bug #42849: innodb crash with varying time_zone on partitioned timestamp primary key Since TIMESTAMP values are adjusted by the current time zone settings in both numeric and string contexts, using any expressions involving TIMESTAMP values as a (sub)partitioning function leads to undeterministic behavior of partitioned tables. The effect may vary depending on a storage engine, it can be either incorrect data being retrieved or stored, or an assertion failure. The root cause of this is the fact that the calculated partition ID may differ from a previously calculated ID for the same data due to timezone adjustments of the partitioning expression value. Fixed by disabling any expressions involving TIMESTAMP values to be used in partitioning functions with the follwing two exceptions: 1. Creating or altering into a partitioned table that violates the above rule is not allowed, but opening existing such tables results in a warning rather than an error so that such tables could be fixed. 2. UNIX_TIMESTAMP() is the only way to get a timezone-independent value from a TIMESTAMP column, because it returns the internal representation (a time_t value) of a TIMESTAMP argument verbatim. So UNIX_TIMESTAMP(timestamp_column) is allowed and should be used to fix existing tables if one wants to use TIMESTAMP columns with partitioning. --- mysql-test/r/partition_bug18198.result | 2 +- mysql-test/r/partition_error.result | 310 ++++++++++++++++++++- mysql-test/t/partition_bug18198.test | 2 +- mysql-test/t/partition_error.test | 364 ++++++++++++++++++++++++- sql/item.h | 9 + sql/item_func.h | 23 ++ sql/item_timefunc.h | 10 + sql/share/errmsg.txt | 4 +- sql/sql_partition.cc | 39 ++- sql/sql_partition.h | 3 - sql/sql_yacc.yy | 2 +- 11 files changed, 743 insertions(+), 25 deletions(-) diff --git a/mysql-test/r/partition_bug18198.result b/mysql-test/r/partition_bug18198.result index 18d7d904bb0..ee7bf514807 100644 --- a/mysql-test/r/partition_bug18198.result +++ b/mysql-test/r/partition_bug18198.result @@ -126,7 +126,7 @@ ERROR HY000: This partition function is not allowed create table t1 (col1 date) partition by range(unix_timestamp(col1)) (partition p0 values less than (10), partition p1 values less than (30)); -ERROR HY000: This partition function is not allowed +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed create table t1 (col1 datetime) partition by range(week(col1)) (partition p0 values less than (10), partition p1 values less than (30)); diff --git a/mysql-test/r/partition_error.result b/mysql-test/r/partition_error.result index 511806d64bd..b692203823d 100644 --- a/mysql-test/r/partition_error.result +++ b/mysql-test/r/partition_error.result @@ -138,7 +138,7 @@ primary key(a,b)) partition by hash (rand(a)) partitions 2 (partition x1, partition x2); -ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near ') +ERROR 42000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed near ') partitions 2 (partition x1, partition x2)' at line 6 CREATE TABLE t1 ( @@ -149,7 +149,7 @@ primary key(a,b)) partition by range (rand(a)) partitions 2 (partition x1 values less than (0), partition x2 values less than (2)); -ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near ') +ERROR 42000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed near ') partitions 2 (partition x1 values less than (0), partition x2 values less than' at line 6 CREATE TABLE t1 ( @@ -160,7 +160,7 @@ primary key(a,b)) partition by list (rand(a)) partitions 2 (partition x1 values in (1), partition x2 values in (2)); -ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near ') +ERROR 42000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed near ') partitions 2 (partition x1 values in (1), partition x2 values in (2))' at line 6 CREATE TABLE t1 ( @@ -275,7 +275,7 @@ c int not null, primary key (a,b)) partition by key (a) subpartition by hash (rand(a+b)); -ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near ')' at line 7 +ERROR 42000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed near ')' at line 7 CREATE TABLE t1 ( a int not null, b int not null, @@ -372,7 +372,7 @@ partition by range (3+4) partitions 2 (partition x1 values less than (4) tablespace ts1, partition x2 values less than (8) tablespace ts2); -ERROR HY000: Constant/Random expression in (sub)partitioning function is not allowed +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed CREATE TABLE t1 ( a int not null, b int not null, @@ -542,7 +542,7 @@ partition by list (3+4) partitions 2 (partition x1 values in (4) tablespace ts1, partition x2 values in (8) tablespace ts2); -ERROR HY000: Constant/Random expression in (sub)partitioning function is not allowed +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed CREATE TABLE t1 ( a int not null, b int not null, @@ -634,13 +634,13 @@ partition by range (ascii(v)) ERROR HY000: This partition function is not allowed create table t1 (a int) partition by hash (rand(a)); -ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near ')' at line 2 +ERROR 42000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed near ')' at line 2 create table t1 (a int) partition by hash(CURTIME() + a); -ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near ')' at line 2 +ERROR 42000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed near ')' at line 2 create table t1 (a int) partition by hash (NOW()+a); -ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near ')' at line 2 +ERROR 42000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed near ')' at line 2 create table t1 (a int) partition by hash (extract(hour from convert_tz(a, '+00:00', '+00:00'))); ERROR HY000: This partition function is not allowed @@ -651,3 +651,295 @@ ERROR HY000: This partition function is not allowed create table t1 (a char(10)) partition by hash (extractvalue(a,'a')); ERROR HY000: This partition function is not allowed +# +# Bug #42849: innodb crash with varying time_zone on partitioned +# timestamp primary key +# +CREATE TABLE old (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (UNIX_TIMESTAMP(a)) ( +PARTITION p VALUES LESS THAN (1219089600), +PARTITION pmax VALUES LESS THAN MAXVALUE); +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (a) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: The PARTITION function returns the wrong type +ALTER TABLE old +PARTITION BY RANGE (a) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: The PARTITION function returns the wrong type +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (a+0) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (a+0) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (a % 2) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (a % 2) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (ABS(a)) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (ABS(a)) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (CEILING(a)) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (CEILING(a)) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (FLOOR(a)) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (FLOOR(a)) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (TO_DAYS(a)) ( +PARTITION p VALUES LESS THAN (733638), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (TO_DAYS(a)) ( +PARTITION p VALUES LESS THAN (733638), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (DAYOFYEAR(a)) ( +PARTITION p VALUES LESS THAN (231), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (DAYOFYEAR(a)) ( +PARTITION p VALUES LESS THAN (231), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (DAYOFMONTH(a)) ( +PARTITION p VALUES LESS THAN (19), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (DAYOFMONTH(a)) ( +PARTITION p VALUES LESS THAN (19), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (DAYOFWEEK(a)) ( +PARTITION p VALUES LESS THAN (3), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (DAYOFWEEK(a)) ( +PARTITION p VALUES LESS THAN (3), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (MONTH(a)) ( +PARTITION p VALUES LESS THAN (8), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (MONTH(a)) ( +PARTITION p VALUES LESS THAN (8), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (HOUR(a)) ( +PARTITION p VALUES LESS THAN (17), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (HOUR(a)) ( +PARTITION p VALUES LESS THAN (17), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (MINUTE(a)) ( +PARTITION p VALUES LESS THAN (55), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (MINUTE(a)) ( +PARTITION p VALUES LESS THAN (55), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (QUARTER(a)) ( +PARTITION p VALUES LESS THAN (3), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (QUARTER(a)) ( +PARTITION p VALUES LESS THAN (3), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (SECOND(a)) ( +PARTITION p VALUES LESS THAN (7), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (SECOND(a)) ( +PARTITION p VALUES LESS THAN (7), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (YEARWEEK(a)) ( +PARTITION p VALUES LESS THAN (200833), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (YEARWEEK(a)) ( +PARTITION p VALUES LESS THAN (200833), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (YEAR(a)) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (YEAR(a)) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (WEEKDAY(a)) ( +PARTITION p VALUES LESS THAN (3), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (WEEKDAY(a)) ( +PARTITION p VALUES LESS THAN (3), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (TIME_TO_SEC(a)) ( +PARTITION p VALUES LESS THAN (64507), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (TIME_TO_SEC(a)) ( +PARTITION p VALUES LESS THAN (64507), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (EXTRACT(DAY FROM a)) ( +PARTITION p VALUES LESS THAN (18), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (EXTRACT(DAY FROM a)) ( +PARTITION p VALUES LESS THAN (18), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL, b TIMESTAMP NOT NULL, PRIMARY KEY(a,b)) +PARTITION BY RANGE (DATEDIFF(a, a)) ( +PARTITION p VALUES LESS THAN (18), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (DATEDIFF(a, a)) ( +PARTITION p VALUES LESS THAN (18), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (YEAR(a + 0)) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (YEAR(a + 0)) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (TO_DAYS(a + '2008-01-01')) ( +PARTITION p VALUES LESS THAN (733638), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (TO_DAYS(a + '2008-01-01')) ( +PARTITION p VALUES LESS THAN (733638), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (YEAR(a + '2008-01-01')) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (YEAR(a + '2008-01-01')) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old ADD COLUMN b DATE; +CREATE TABLE new (a TIMESTAMP, b DATE) +PARTITION BY RANGE (YEAR(a + b)) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (YEAR(a + b)) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP, b DATE) +PARTITION BY RANGE (TO_DAYS(a + b)) ( +PARTITION p VALUES LESS THAN (733638), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (TO_DAYS(a + b)) ( +PARTITION p VALUES LESS THAN (733638), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP, b date) +PARTITION BY RANGE (UNIX_TIMESTAMP(a + b)) ( +PARTITION p VALUES LESS THAN (1219089600), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (UNIX_TIMESTAMP(a + b)) ( +PARTITION p VALUES LESS THAN (1219089600), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP, b TIMESTAMP) +PARTITION BY RANGE (UNIX_TIMESTAMP(a + b)) ( +PARTITION p VALUES LESS THAN (1219089600), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old MODIFY b TIMESTAMP; +ALTER TABLE old +PARTITION BY RANGE (UNIX_TIMESTAMP(a + b)) ( +PARTITION p VALUES LESS THAN (1219089600), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +DROP TABLE old; +End of 5.1 tests diff --git a/mysql-test/t/partition_bug18198.test b/mysql-test/t/partition_bug18198.test index 7f071c6ec9e..720d483e8ed 100644 --- a/mysql-test/t/partition_bug18198.test +++ b/mysql-test/t/partition_bug18198.test @@ -158,7 +158,7 @@ create table t1 (col1 datetime) partition by range(timestampdiff(day,5,col1)) (partition p0 values less than (10), partition p1 values less than (30)); --- error ER_PARTITION_FUNCTION_IS_NOT_ALLOWED +-- error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR create table t1 (col1 date) partition by range(unix_timestamp(col1)) (partition p0 values less than (10), partition p1 values less than (30)); diff --git a/mysql-test/t/partition_error.test b/mysql-test/t/partition_error.test index 49632f95dfb..1f011f36257 100644 --- a/mysql-test/t/partition_error.test +++ b/mysql-test/t/partition_error.test @@ -466,7 +466,7 @@ partitions 2 # # Partition by range, constant partition function not allowed # ---error ER_CONST_EXPR_IN_PARTITION_FUNC_ERROR +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR CREATE TABLE t1 ( a int not null, b int not null, @@ -681,7 +681,7 @@ partition by list (a); # # Partition by list, constant partition function not allowed # ---error ER_CONST_EXPR_IN_PARTITION_FUNC_ERROR +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR CREATE TABLE t1 ( a int not null, b int not null, @@ -840,4 +840,364 @@ partition by range (a + (select count(*) from t1)) create table t1 (a char(10)) partition by hash (extractvalue(a,'a')); +--echo # +--echo # Bug #42849: innodb crash with varying time_zone on partitioned +--echo # timestamp primary key +--echo # +# A correctly partitioned table to test that trying to repartition it using +# timezone-dependent expression will throw an error. +CREATE TABLE old (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (UNIX_TIMESTAMP(a)) ( +PARTITION p VALUES LESS THAN (1219089600), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +# Check that allowed arithmetic/math functions involving TIMESTAMP values result +# in ER_PARTITION_FUNC_NOT_ALLOWED_ERROR when used as a partitioning function + +--error ER_PARTITION_FUNC_NOT_ALLOWED_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (a) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_PARTITION_FUNC_NOT_ALLOWED_ERROR +ALTER TABLE old +PARTITION BY RANGE (a) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (a+0) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (a+0) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (a % 2) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (a % 2) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (ABS(a)) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (ABS(a)) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (CEILING(a)) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (CEILING(a)) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (FLOOR(a)) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (FLOOR(a)) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +# Check that allowed date/time functions involving TIMESTAMP values result +# in ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR when used as a partitioning function + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (TO_DAYS(a)) ( +PARTITION p VALUES LESS THAN (733638), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (TO_DAYS(a)) ( +PARTITION p VALUES LESS THAN (733638), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (DAYOFYEAR(a)) ( +PARTITION p VALUES LESS THAN (231), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (DAYOFYEAR(a)) ( +PARTITION p VALUES LESS THAN (231), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (DAYOFMONTH(a)) ( +PARTITION p VALUES LESS THAN (19), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (DAYOFMONTH(a)) ( +PARTITION p VALUES LESS THAN (19), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (DAYOFWEEK(a)) ( +PARTITION p VALUES LESS THAN (3), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (DAYOFWEEK(a)) ( +PARTITION p VALUES LESS THAN (3), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (MONTH(a)) ( +PARTITION p VALUES LESS THAN (8), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (MONTH(a)) ( +PARTITION p VALUES LESS THAN (8), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (HOUR(a)) ( +PARTITION p VALUES LESS THAN (17), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (HOUR(a)) ( +PARTITION p VALUES LESS THAN (17), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (MINUTE(a)) ( +PARTITION p VALUES LESS THAN (55), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (MINUTE(a)) ( +PARTITION p VALUES LESS THAN (55), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (QUARTER(a)) ( +PARTITION p VALUES LESS THAN (3), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (QUARTER(a)) ( +PARTITION p VALUES LESS THAN (3), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (SECOND(a)) ( +PARTITION p VALUES LESS THAN (7), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (SECOND(a)) ( +PARTITION p VALUES LESS THAN (7), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (YEARWEEK(a)) ( +PARTITION p VALUES LESS THAN (200833), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (YEARWEEK(a)) ( +PARTITION p VALUES LESS THAN (200833), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (YEAR(a)) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (YEAR(a)) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (WEEKDAY(a)) ( +PARTITION p VALUES LESS THAN (3), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (WEEKDAY(a)) ( +PARTITION p VALUES LESS THAN (3), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (TIME_TO_SEC(a)) ( +PARTITION p VALUES LESS THAN (64507), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (TIME_TO_SEC(a)) ( +PARTITION p VALUES LESS THAN (64507), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (EXTRACT(DAY FROM a)) ( +PARTITION p VALUES LESS THAN (18), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (EXTRACT(DAY FROM a)) ( +PARTITION p VALUES LESS THAN (18), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL, b TIMESTAMP NOT NULL, PRIMARY KEY(a,b)) +PARTITION BY RANGE (DATEDIFF(a, a)) ( +PARTITION p VALUES LESS THAN (18), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (DATEDIFF(a, a)) ( +PARTITION p VALUES LESS THAN (18), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (YEAR(a + 0)) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (YEAR(a + 0)) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (TO_DAYS(a + '2008-01-01')) ( +PARTITION p VALUES LESS THAN (733638), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (TO_DAYS(a + '2008-01-01')) ( +PARTITION p VALUES LESS THAN (733638), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (YEAR(a + '2008-01-01')) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (YEAR(a + '2008-01-01')) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +ALTER TABLE old ADD COLUMN b DATE; + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP, b DATE) +PARTITION BY RANGE (YEAR(a + b)) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (YEAR(a + b)) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP, b DATE) +PARTITION BY RANGE (TO_DAYS(a + b)) ( +PARTITION p VALUES LESS THAN (733638), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (TO_DAYS(a + b)) ( +PARTITION p VALUES LESS THAN (733638), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP, b date) +PARTITION BY RANGE (UNIX_TIMESTAMP(a + b)) ( +PARTITION p VALUES LESS THAN (1219089600), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (UNIX_TIMESTAMP(a + b)) ( +PARTITION p VALUES LESS THAN (1219089600), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP, b TIMESTAMP) +PARTITION BY RANGE (UNIX_TIMESTAMP(a + b)) ( +PARTITION p VALUES LESS THAN (1219089600), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +ALTER TABLE old MODIFY b TIMESTAMP; + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (UNIX_TIMESTAMP(a + b)) ( +PARTITION p VALUES LESS THAN (1219089600), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +DROP TABLE old; + +--echo End of 5.1 tests diff --git a/sql/item.h b/sql/item.h index 3dfcd7c2612..4135ff2b097 100644 --- a/sql/item.h +++ b/sql/item.h @@ -950,6 +950,15 @@ public: virtual Item *equal_fields_propagator(uchar * arg) { return this; } virtual bool set_no_const_sub(uchar *arg) { return FALSE; } virtual Item *replace_equal_field(uchar * arg) { return this; } + /* + Check if an expression value depends on the current timezone. Used by + partitioning code to reject timezone-dependent expressions in a + (sub)partitioning function. + */ + virtual bool is_timezone_dependent_processor(uchar *bool_arg) + { + return FALSE; + } /* For SP local variable returns pointer to Item representing its diff --git a/sql/item_func.h b/sql/item_func.h index 67049af81a2..738f6544204 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -200,6 +200,29 @@ public: null_value=1; return 0.0; } + bool has_timestamp_args() + { + DBUG_ASSERT(fixed == TRUE); + for (uint i= 0; i < arg_count; i++) + { + if (args[i]->type() == Item::FIELD_ITEM && + args[i]->field_type() == MYSQL_TYPE_TIMESTAMP) + return TRUE; + } + return FALSE; + } + /* + We assume the result of any function that has a TIMESTAMP argument to be + timezone-dependent, since a TIMESTAMP value in both numeric and string + contexts is interpreted according to the current timezone. + The only exception is UNIX_TIMESTAMP() which returns the internal + representation of a TIMESTAMP argument verbatim, and thus does not depend on + the timezone. + */ + virtual bool is_timezone_dependent_processor(uchar *bool_arg) + { + return has_timestamp_args(); + } }; diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 9e3c2e8c89f..a7a64090f6c 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -305,6 +305,16 @@ public: Item_func_unix_timestamp(Item *a) :Item_int_func(a) {} longlong val_int(); const char *func_name() const { return "unix_timestamp"; } + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} + /* + UNIX_TIMESTAMP() depends on the current timezone + (and thus may not be used as a partitioning function) + when its argument is NOT of the TIMESTAMP type. + */ + bool is_timezone_dependent_processor(uchar *int_arg) + { + return !has_timestamp_args(); + } void fix_length_and_dec() { decimals=0; diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 7c92c827c87..cc319667060 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5696,8 +5696,8 @@ ER_PARTITION_WRONG_NO_SUBPART_ERROR eng "Wrong number of subpartitions defined, mismatch with previous setting" ger "Falsche Anzahl von Unterpartitionen definiert, stimmt nicht mit vorherigen Einstellungen überein" swe "Antal subpartitioner definierade och antal subpartitioner är inte lika" -ER_CONST_EXPR_IN_PARTITION_FUNC_ERROR - eng "Constant/Random expression in (sub)partitioning function is not allowed" +ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR + eng "Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed" ger "Konstante oder Random-Ausdrücke in (Unter-)Partitionsfunktionen sind nicht erlaubt" swe "Konstanta uttryck eller slumpmässiga uttryck är inte tillåtna (sub)partitioneringsfunktioner" ER_NO_CONST_EXPR_IN_RANGE_OR_LIST_ERROR diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 4a50650b6f4..f3f33ab1dd1 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -869,6 +869,8 @@ int check_signed_flag(partition_info *part_info) part_info Reference to partitioning data structure is_sub_part Is the table subpartitioned as well is_field_to_be_setup Flag if we are to set-up field arrays + is_create_table_ind Indicator of whether openfrm was called as part of + CREATE or ALTER TABLE RETURN VALUE TRUE An error occurred, something was wrong with the @@ -891,8 +893,9 @@ int check_signed_flag(partition_info *part_info) on the field object. */ -bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table, - bool is_sub_part, bool is_field_to_be_setup) +static bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table, + bool is_sub_part, bool is_field_to_be_setup, + bool is_create_table_ind) { partition_info *part_info= table->part_info; uint dir_length, home_dir_length; @@ -982,10 +985,31 @@ bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table, thd->where= save_where; if (unlikely(func_expr->const_item())) { - my_error(ER_CONST_EXPR_IN_PARTITION_FUNC_ERROR, MYF(0)); + my_error(ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR, MYF(0)); clear_field_flag(table); goto end; } + + /* + We don't allow creating partitions with timezone-dependent expressions as + a (sub)partitioning function, but we want to allow such expressions when + opening existing tables for easier maintenance. This exception should be + deprecated at some point in future so that we always throw an error. + */ + if (func_expr->walk(&Item::is_timezone_dependent_processor, + 0, NULL)) + { + if (is_create_table_ind) + { + my_error(ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR, MYF(0)); + goto end; + } + else + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR, + ER(ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR)); + } + if ((!is_sub_part) && (error= check_signed_flag(part_info))) goto end; result= FALSE; @@ -1593,7 +1617,8 @@ bool fix_partition_func(THD *thd, TABLE *table, else { if (unlikely(fix_fields_part_func(thd, part_info->subpart_expr, - table, TRUE, TRUE))) + table, TRUE, TRUE, + is_create_table_ind))) goto end; if (unlikely(part_info->subpart_expr->result_type() != INT_RESULT)) { @@ -1621,7 +1646,8 @@ bool fix_partition_func(THD *thd, TABLE *table, else { if (unlikely(fix_fields_part_func(thd, part_info->part_expr, - table, FALSE, TRUE))) + table, FALSE, TRUE, + is_create_table_ind))) goto end; if (unlikely(part_info->part_expr->result_type() != INT_RESULT)) { @@ -1635,7 +1661,8 @@ bool fix_partition_func(THD *thd, TABLE *table, { const char *error_str; if (unlikely(fix_fields_part_func(thd, part_info->part_expr, - table, FALSE, TRUE))) + table, FALSE, TRUE, + is_create_table_ind))) goto end; if (part_info->part_type == RANGE_PARTITION) { diff --git a/sql/sql_partition.h b/sql/sql_partition.h index 282e24f1853..b9efbf25a00 100644 --- a/sql/sql_partition.h +++ b/sql/sql_partition.h @@ -91,9 +91,6 @@ uint32 get_list_array_idx_for_endpoint(partition_info *part_info, uint32 get_partition_id_range_for_endpoint(partition_info *part_info, bool left_endpoint, bool include_endpoint); -bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table, - bool is_sub_part, bool is_field_to_be_setup); - bool check_part_func_fields(Field **ptr, bool ok_with_charsets); bool field_is_partition_charset(Field *field); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index c40062e5d52..ec6d2cc72cd 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3931,7 +3931,7 @@ part_func_expr: lex->safe_to_cache_query= 1; if (not_corr_func) { - my_parse_error(ER(ER_CONST_EXPR_IN_PARTITION_FUNC_ERROR)); + my_parse_error(ER(ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR)); MYSQL_YYABORT; } $$=$1; From 44e2c65a2d2e8299e8c5b58d5538a6af5a375e38 Mon Sep 17 00:00:00 2001 From: "lars-erik.bjork@sun.com" <> Date: Mon, 14 Dec 2009 00:58:16 +0100 Subject: [PATCH 054/104] This is a patch for Bug#48500 5.0 buffer overflow for ER_UPDATE_INFO, or truncated info message in 5.1 5.0.86 has a buffer overflow/crash, and 5.1.40 has a truncated message. errmsg.txt contains this: ER_UPDATE_INFO rum "Linii identificate (matched): %ld Schimbate: %ld Atentionari (warnings): %ld" When that is sprintf'd into a buffer of STRING_BUFFER_USUAL_SIZE size, a buffer overflow can happen. The solution to this is to use MYSQL_ERRMSG_SIZE for the buffer size, instead of STRING_BUFFER_USUAL_SIZE. This will allow longer strings. To avoid potential crashes, we will also use my_snprintf instead of sprintf. --- sql/sql_update.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 06d1bcaa8fb..35ae0febcec 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -600,8 +600,8 @@ int mysql_update(THD *thd, if (error < 0) { - char buff[STRING_BUFFER_USUAL_SIZE]; - sprintf(buff, ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated, + char buff[MYSQL_ERRMSG_SIZE]; + my_snprintf(buff, sizeof(buff), ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated, (ulong) thd->cuted_fields); thd->row_count_func= (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated; From 70dab5e6b0355fb0b8ba01064d5f2b47e39e3c83 Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Mon, 14 Dec 2009 09:06:46 +0300 Subject: [PATCH 055/104] Post-merge test fix for bug #42849. --- mysql-test/r/partition.result | 12 ++++++------ mysql-test/t/partition.test | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index 7e14a0ea7c8..08357795046 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -24,8 +24,8 @@ a timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, b varchar(10), PRIMARY KEY (a) ) -PARTITION BY RANGE (to_days(a)) ( -PARTITION p1 VALUES LESS THAN (733407), +PARTITION BY RANGE (UNIX_TIMESTAMP(a)) ( +PARTITION p1 VALUES LESS THAN (1199134800), PARTITION pmax VALUES LESS THAN MAXVALUE ); INSERT INTO t1 VALUES ('2007-07-30 17:35:48', 'p1'); @@ -37,7 +37,7 @@ a b 2009-07-14 17:35:55 pmax 2009-09-21 17:31:42 pmax ALTER TABLE t1 REORGANIZE PARTITION pmax INTO ( -PARTITION p3 VALUES LESS THAN (733969), +PARTITION p3 VALUES LESS THAN (1247688000), PARTITION pmax VALUES LESS THAN MAXVALUE); SELECT * FROM t1; a b @@ -51,9 +51,9 @@ t1 CREATE TABLE `t1` ( `b` varchar(10) DEFAULT NULL, PRIMARY KEY (`a`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 -/*!50100 PARTITION BY RANGE (to_days(a)) -(PARTITION p1 VALUES LESS THAN (733407) ENGINE = MyISAM, - PARTITION p3 VALUES LESS THAN (733969) ENGINE = MyISAM, +/*!50100 PARTITION BY RANGE (UNIX_TIMESTAMP(a)) +(PARTITION p1 VALUES LESS THAN (1199134800) ENGINE = MyISAM, + PARTITION p3 VALUES LESS THAN (1247688000) ENGINE = MyISAM, PARTITION pmax VALUES LESS THAN MAXVALUE ENGINE = MyISAM) */ DROP TABLE t1; create table t1 (a int NOT NULL, b varchar(5) NOT NULL) diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index 0ff4b118426..0cbe389dadd 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -53,8 +53,8 @@ CREATE TABLE t1 ( b varchar(10), PRIMARY KEY (a) ) -PARTITION BY RANGE (to_days(a)) ( - PARTITION p1 VALUES LESS THAN (733407), +PARTITION BY RANGE (UNIX_TIMESTAMP(a)) ( + PARTITION p1 VALUES LESS THAN (1199134800), PARTITION pmax VALUES LESS THAN MAXVALUE ); @@ -64,7 +64,7 @@ INSERT INTO t1 VALUES ('2009-09-21 17:31:42', 'pmax'); SELECT * FROM t1; ALTER TABLE t1 REORGANIZE PARTITION pmax INTO ( - PARTITION p3 VALUES LESS THAN (733969), + PARTITION p3 VALUES LESS THAN (1247688000), PARTITION pmax VALUES LESS THAN MAXVALUE); SELECT * FROM t1; SHOW CREATE TABLE t1; From 594f28a5e053f33d98d63844bf4f3da732235ebe Mon Sep 17 00:00:00 2001 From: Satya B Date: Mon, 14 Dec 2009 13:42:26 +0530 Subject: [PATCH 056/104] Fix for BUG#49502 - CMake error compiling 5.1 on Windows When applying innodb snapshot 1.0.6 the storage engine name for innodb plugin under windows was changed from INNODB_PLUGIN to INNOBASE. This is a wrong and changing back the name to INNODB_PLUGIN. --- storage/innodb_plugin/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/innodb_plugin/CMakeLists.txt b/storage/innodb_plugin/CMakeLists.txt index ad483779152..25cd212a473 100644 --- a/storage/innodb_plugin/CMakeLists.txt +++ b/storage/innodb_plugin/CMakeLists.txt @@ -81,4 +81,4 @@ SET(INNODB_PLUGIN_SOURCES btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea ut/ut0byte.c ut/ut0dbg.c ut/ut0mem.c ut/ut0rnd.c ut/ut0ut.c ut/ut0vec.c ut/ut0list.c ut/ut0wqueue.c) ADD_DEFINITIONS(-DHAVE_WINDOWS_ATOMICS -DIB_HAVE_PAUSE_INSTRUCTION) -MYSQL_STORAGE_ENGINE(INNOBASE) +MYSQL_STORAGE_ENGINE(INNODB_PLUGIN) From 10d4a9510deaa5b207dec8e09a8470f765d209e3 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Mon, 14 Dec 2009 15:51:42 +0100 Subject: [PATCH 057/104] Fixed an issue where STOP SLAVE generated a warning to error log which test case couldn't handle, fixed by checking for io slave killed before checking for network error --- sql/slave.cc | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/sql/slave.cc b/sql/slave.cc index 96aa9890c89..ce5bb785792 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1219,6 +1219,8 @@ static int get_master_version_and_clock(MYSQL* mysql, Master_info* mi) mi->clock_diff_with_master= (long) (time((time_t*) 0) - strtoul(master_row[0], 0, 10)); } + else if (check_io_slave_killed(mi->io_thd, mi, NULL)) + goto slave_killed_err; else if (is_network_error(mysql_errno(mysql))) { mi->report(WARNING_LEVEL, mysql_errno(mysql), @@ -1271,7 +1273,9 @@ not always make sense; please check the manual before using it)."; } else if (mysql_errno(mysql)) { - if (is_network_error(mysql_errno(mysql))) + if (check_io_slave_killed(mi->io_thd, mi, NULL)) + goto slave_killed_err; + else if (is_network_error(mysql_errno(mysql))) { mi->report(WARNING_LEVEL, mysql_errno(mysql), "Get master SERVER_ID failed with error: %s", mysql_error(mysql)); @@ -1342,6 +1346,8 @@ be equal for the Statement-format replication to work"; goto err; } } + else if (check_io_slave_killed(mi->io_thd, mi, NULL)) + goto slave_killed_err; else if (is_network_error(mysql_errno(mysql))) { mi->report(WARNING_LEVEL, mysql_errno(mysql), @@ -1403,6 +1409,8 @@ be equal for the Statement-format replication to work"; goto err; } } + else if (check_io_slave_killed(mi->io_thd, mi, NULL)) + goto slave_killed_err; else if (is_network_error(mysql_errno(mysql))) { mi->report(WARNING_LEVEL, mysql_errno(mysql), @@ -1466,6 +1474,11 @@ network_err: if (master_res) mysql_free_result(master_res); DBUG_RETURN(2); + +slave_killed_err: + if (master_res) + mysql_free_result(master_res); + DBUG_RETURN(2); } /* @@ -2884,7 +2897,7 @@ connected: if (ret == 1) /* Fatal error */ goto err; - + if (ret == 2) { if (check_io_slave_killed(mi->io_thd, mi, "Slave I/O thread killed" From 5d32ba4e0702a72fdc60f6028736c1fb82f54073 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Mon, 14 Dec 2009 16:11:47 +0100 Subject: [PATCH 058/104] Recommit of patch for bug#49028 for 5.1. Includes both patch from bug#48737 (without test, which should go to next-mr) and test for bug#49028. --- mysql-test/r/ctype_ucs.result | 20 ++++++++++++++++++++ mysql-test/t/ctype_ucs.test | 10 ++++++++++ strings/ctype-ucs2.c | 10 ---------- 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result index 428629e7e9e..abb21b7cee7 100644 --- a/mysql-test/r/ctype_ucs.result +++ b/mysql-test/r/ctype_ucs.result @@ -116,6 +116,26 @@ select binary 'a a' > 'a', binary 'a \0' > 'a', binary 'a\0' > 'a'; binary 'a a' > 'a' binary 'a \0' > 'a' binary 'a\0' > 'a' 1 1 1 SET CHARACTER SET koi8r; +create table t1 (a varchar(2) character set ucs2 collate ucs2_bin, key(a)); +insert into t1 values ('A'),('A'),('B'),('C'),('D'),('A\t'); +insert into t1 values ('A\0'),('A\0'),('A\0'),('A\0'),('AZ'); +select hex(a) from t1 where a like 'A_' order by a; +hex(a) +00410000 +00410000 +00410000 +00410000 +00410009 +0041005A +select hex(a) from t1 ignore key(a) where a like 'A_' order by a; +hex(a) +00410000 +00410000 +00410000 +00410000 +00410009 +0041005A +drop table t1; CREATE TABLE t1 (word VARCHAR(64) CHARACTER SET ucs2, word2 CHAR(64) CHARACTER SET ucs2); INSERT INTO t1 VALUES (_koi8r'ò',_koi8r'ò'), (X'2004',X'2004'); SELECT hex(word) FROM t1 ORDER BY word; diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test index e247110658b..310576b9478 100644 --- a/mysql-test/t/ctype_ucs.test +++ b/mysql-test/t/ctype_ucs.test @@ -14,6 +14,16 @@ SET character_set_connection=ucs2; SET CHARACTER SET koi8r; +# +# BUG#49028, error in LIKE with ucs2 +# +create table t1 (a varchar(2) character set ucs2 collate ucs2_bin, key(a)); +insert into t1 values ('A'),('A'),('B'),('C'),('D'),('A\t'); +insert into t1 values ('A\0'),('A\0'),('A\0'),('A\0'),('AZ'); +select hex(a) from t1 where a like 'A_' order by a; +select hex(a) from t1 ignore key(a) where a like 'A_' order by a; +drop table t1; + # # Check that 0x20 is only trimmed when it is # a part of real SPACE character, not just a part diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index a1c691a462b..cead55f8a0a 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -1602,16 +1602,6 @@ fill_max_and_min: *min_str++= *max_str++ = ptr[1]; } - /* Temporary fix for handling w_one at end of string (key compression) */ - { - char *tmp; - for (tmp= min_str ; tmp-1 > min_org && tmp[-1] == '\0' && tmp[-2]=='\0';) - { - *--tmp=' '; - *--tmp='\0'; - } - } - *min_length= *max_length = (size_t) (min_str - min_org); while (min_str + 1 < min_end) { From 40468572e1c457b542b8496adb8b91e3041c0a3a Mon Sep 17 00:00:00 2001 From: Andrei Elkin Date: Mon, 14 Dec 2009 18:50:22 +0200 Subject: [PATCH 059/104] correction to the earlier merging: s/return/DBUG_RETURN/ --- sql/rpl_rli.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index f45ab56aa1c..1263b7c52d9 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -1033,7 +1033,7 @@ bool Relay_log_info::is_until_satisfied(THD *thd, Log_event *ev) if (until_condition == UNTIL_MASTER_POS) { if (ev && ev->server_id == (uint32) ::server_id && !replicate_same_server_id) - return FALSE; + DBUG_RETURN(FALSE); log_name= group_master_log_name; log_pos= (!ev)? group_master_log_pos : ((thd->options & OPTION_BEGIN || !ev->log_pos) ? From 30e9b381b261a08e3ecd2306cdb0c4dea92b12f4 Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Mon, 14 Dec 2009 20:27:43 +0300 Subject: [PATCH 060/104] Post-push fixes for the bug #42849: All tests in the parts suite that use partitioning on a timezone-dependent expression were commented out, since it is not valid anymore. --- .../parts/inc/part_blocked_sql_funcs_main.inc | 14 ++- .../suite/parts/inc/partition_timestamp.inc | 82 +++++++------ .../r/part_blocked_sql_func_innodb.result | 98 ---------------- .../r/part_blocked_sql_func_myisam.result | 98 ---------------- .../parts/r/partition_datetime_innodb.result | 108 ------------------ .../parts/r/partition_datetime_myisam.result | 108 ------------------ 6 files changed, 54 insertions(+), 454 deletions(-) diff --git a/mysql-test/suite/parts/inc/part_blocked_sql_funcs_main.inc b/mysql-test/suite/parts/inc/part_blocked_sql_funcs_main.inc index 1a66a26312a..be02e4e0402 100644 --- a/mysql-test/suite/parts/inc/part_blocked_sql_funcs_main.inc +++ b/mysql-test/suite/parts/inc/part_blocked_sql_funcs_main.inc @@ -152,10 +152,16 @@ let $valsqlfunc = timestampdiff(YEAR,'2002-05-01','2001-01-01'); let $coltype = datetime; --source suite/parts/inc/partition_blocked_sql_funcs.inc -let $sqlfunc = unix_timestamp(col1); -let $valsqlfunc = unix_timestamp ('2002-05-01'); -let $coltype = date; ---source suite/parts/inc/partition_blocked_sql_funcs.inc +################################################################################ +# After the fix for bug #42849 the server behavior does not fit into this test's +# architecture: for UNIX_TIMESTAMP() some of the queries in +# suite/parts/inc/partition_blocked_sql_funcs.inc will fail with a different +# error (ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR) and some will succeed where +################################################################################ +#let $sqlfunc = unix_timestamp(col1); +#let $valsqlfunc = unix_timestamp ('2002-05-01'); +#let $coltype = date; +#--source suite/parts/inc/partition_blocked_sql_funcs.inc let $sqlfunc = week(col1); let $valsqlfunc = week('2002-05-01'); diff --git a/mysql-test/suite/parts/inc/partition_timestamp.inc b/mysql-test/suite/parts/inc/partition_timestamp.inc index d152c82a76f..4cf61c155bc 100644 --- a/mysql-test/suite/parts/inc/partition_timestamp.inc +++ b/mysql-test/suite/parts/inc/partition_timestamp.inc @@ -33,42 +33,48 @@ select count(*) from t2; select * from t2; drop table t2; -eval create table t3 (a timestamp not null, primary key(a)) engine=$engine -partition by range (month(a)) subpartition by key (a) -subpartitions 3 ( -partition quarter1 values less than (4), -partition quarter2 values less than (7), -partition quarter3 values less than (10), -partition quarter4 values less than (13) -); -show create table t3; -let $count=12; ---echo $count inserts; -while ($count) -{ -eval insert into t3 values (date_add('1970-01-01 00:00:00',interval $count-1 month)); -dec $count; -} -select count(*) from t3; -select * from t3; -drop table t3; +################################################################################ +# The following 2 tests are no longer valid after bug #42849 has been fixed: +# it is not possible to use a timezone-dependent (such as month(timestamp_col) +# or just a timestamp_col in a numeric context) anymore. +################################################################################ -eval create table t4 (a timestamp not null, primary key(a)) engine=$engine -partition by list (month(a)) subpartition by key (a) -subpartitions 3 ( -partition quarter1 values in (0,1,2,3), -partition quarter2 values in (4,5,6), -partition quarter3 values in (7,8,9), -partition quarter4 values in (10,11,12) -); -show create table t4; -let $count=12; ---echo $count inserts; -while ($count) -{ -eval insert into t4 values (date_add('1970-01-01 00:00:00',interval $count-1 month)); -dec $count; -} -select count(*) from t4; -select * from t4; -drop table t4; +# eval create table t3 (a timestamp not null, primary key(a)) engine=$engine +# partition by range (month(a)) subpartition by key (a) +# subpartitions 3 ( +# partition quarter1 values less than (4), +# partition quarter2 values less than (7), +# partition quarter3 values less than (10), +# partition quarter4 values less than (13) +# ); +# show create table t3; +# let $count=12; +# --echo $count inserts; +# while ($count) +# { +# eval insert into t3 values (date_add('1970-01-01 00:00:00',interval $count-1 month)); +# dec $count; +# } +# select count(*) from t3; +# select * from t3; +# drop table t3; + +# eval create table t4 (a timestamp not null, primary key(a)) engine=$engine +# partition by list (month(a)) subpartition by key (a) +# subpartitions 3 ( +# partition quarter1 values in (0,1,2,3), +# partition quarter2 values in (4,5,6), +# partition quarter3 values in (7,8,9), +# partition quarter4 values in (10,11,12) +# ); +# show create table t4; +# let $count=12; +# --echo $count inserts; +# while ($count) +# { +# eval insert into t4 values (date_add('1970-01-01 00:00:00',interval $count-1 month)); +# dec $count; +# } +# select count(*) from t4; +# select * from t4; +# drop table t4; diff --git a/mysql-test/suite/parts/r/part_blocked_sql_func_innodb.result b/mysql-test/suite/parts/r/part_blocked_sql_func_innodb.result index 57a7b2189ba..21d9548d658 100644 --- a/mysql-test/suite/parts/r/part_blocked_sql_func_innodb.result +++ b/mysql-test/suite/parts/r/part_blocked_sql_func_innodb.result @@ -2942,104 +2942,6 @@ drop table if exists t44 ; drop table if exists t55 ; drop table if exists t66 ; ------------------------------------------------------------------------- ---- unix_timestamp(col1) in partition with coltype date -------------------------------------------------------------------------- -must all fail! -drop table if exists t1 ; -drop table if exists t2 ; -drop table if exists t3 ; -drop table if exists t4 ; -drop table if exists t5 ; -drop table if exists t6 ; -create table t1 (col1 date) engine='INNODB' -partition by range(unix_timestamp(col1)) -(partition p0 values less than (15), -partition p1 values less than (31)); -Got one of the listed errors -create table t2 (col1 date) engine='INNODB' -partition by list(unix_timestamp(col1)) -(partition p0 values in (1,2,3,4,5,6,7,8,9,10), -partition p1 values in (11,12,13,14,15,16,17,18,19,20), -partition p2 values in (21,22,23,24,25,26,27,28,29,30)); -Got one of the listed errors -create table t3 (col1 date) engine='INNODB' -partition by hash(unix_timestamp(col1)); -Got one of the listed errors -create table t4 (colint int, col1 date) engine='INNODB' -partition by range(colint) -subpartition by hash(unix_timestamp(col1)) subpartitions 2 -(partition p0 values less than (15), -partition p1 values less than (31)); -Got one of the listed errors -create table t5 (colint int, col1 date) engine='INNODB' -partition by list(colint) -subpartition by hash(unix_timestamp(col1)) subpartitions 2 -(partition p0 values in (1,2,3,4,5,6,7,8,9,10), -partition p1 values in (11,12,13,14,15,16,17,18,19,20), -partition p2 values in (21,22,23,24,25,26,27,28,29,30)); -Got one of the listed errors -create table t6 (colint int, col1 date) engine='INNODB' -partition by range(colint) -(partition p0 values less than (unix_timestamp ('2002-05-01')), -partition p1 values less than maxvalue); -Got one of the listed errors -drop table if exists t11 ; -drop table if exists t22 ; -drop table if exists t33 ; -drop table if exists t44 ; -drop table if exists t55 ; -drop table if exists t66 ; -create table t11 (col1 date) engine='INNODB' ; -create table t22 (col1 date) engine='INNODB' ; -create table t33 (col1 date) engine='INNODB' ; -create table t44 (colint int, col1 date) engine='INNODB' ; -create table t55 (colint int, col1 date) engine='INNODB' ; -create table t66 (colint int, col1 date) engine='INNODB' ; -alter table t11 -partition by range(unix_timestamp(col1)) -(partition p0 values less than (15), -partition p1 values less than (31)); -Got one of the listed errors -alter table t22 -partition by list(unix_timestamp(col1)) -(partition p0 values in (1,2,3,4,5,6,7,8,9,10), -partition p1 values in (11,12,13,14,15,16,17,18,19,20), -partition p2 values in (21,22,23,24,25,26,27,28,29,30)); -Got one of the listed errors -alter table t33 -partition by hash(unix_timestamp(col1)); -Got one of the listed errors -alter table t44 -partition by range(colint) -subpartition by hash(unix_timestamp(col1)) subpartitions 2 -(partition p0 values less than (15), -partition p1 values less than (31)); -Got one of the listed errors -alter table t55 -partition by list(colint) -subpartition by hash(unix_timestamp(col1)) subpartitions 2 -(partition p0 values in (1,2,3,4,5,6,7,8,9,10), -partition p1 values in (11,12,13,14,15,16,17,18,19,20), -partition p2 values in (21,22,23,24,25,26,27,28,29,30)); -Got one of the listed errors -alter table t66 -partition by range(colint) -(partition p0 values less than (unix_timestamp ('2002-05-01')), -partition p1 values less than maxvalue); -Got one of the listed errors -drop table if exists t1 ; -drop table if exists t2 ; -drop table if exists t3 ; -drop table if exists t4 ; -drop table if exists t5 ; -drop table if exists t6 ; -drop table if exists t11 ; -drop table if exists t22 ; -drop table if exists t33 ; -drop table if exists t44 ; -drop table if exists t55 ; -drop table if exists t66 ; -------------------------------------------------------------------------- --- week(col1) in partition with coltype datetime ------------------------------------------------------------------------- must all fail! diff --git a/mysql-test/suite/parts/r/part_blocked_sql_func_myisam.result b/mysql-test/suite/parts/r/part_blocked_sql_func_myisam.result index 4a67054e82a..cf1a222a6ea 100644 --- a/mysql-test/suite/parts/r/part_blocked_sql_func_myisam.result +++ b/mysql-test/suite/parts/r/part_blocked_sql_func_myisam.result @@ -2942,104 +2942,6 @@ drop table if exists t44 ; drop table if exists t55 ; drop table if exists t66 ; ------------------------------------------------------------------------- ---- unix_timestamp(col1) in partition with coltype date -------------------------------------------------------------------------- -must all fail! -drop table if exists t1 ; -drop table if exists t2 ; -drop table if exists t3 ; -drop table if exists t4 ; -drop table if exists t5 ; -drop table if exists t6 ; -create table t1 (col1 date) engine='MYISAM' -partition by range(unix_timestamp(col1)) -(partition p0 values less than (15), -partition p1 values less than (31)); -Got one of the listed errors -create table t2 (col1 date) engine='MYISAM' -partition by list(unix_timestamp(col1)) -(partition p0 values in (1,2,3,4,5,6,7,8,9,10), -partition p1 values in (11,12,13,14,15,16,17,18,19,20), -partition p2 values in (21,22,23,24,25,26,27,28,29,30)); -Got one of the listed errors -create table t3 (col1 date) engine='MYISAM' -partition by hash(unix_timestamp(col1)); -Got one of the listed errors -create table t4 (colint int, col1 date) engine='MYISAM' -partition by range(colint) -subpartition by hash(unix_timestamp(col1)) subpartitions 2 -(partition p0 values less than (15), -partition p1 values less than (31)); -Got one of the listed errors -create table t5 (colint int, col1 date) engine='MYISAM' -partition by list(colint) -subpartition by hash(unix_timestamp(col1)) subpartitions 2 -(partition p0 values in (1,2,3,4,5,6,7,8,9,10), -partition p1 values in (11,12,13,14,15,16,17,18,19,20), -partition p2 values in (21,22,23,24,25,26,27,28,29,30)); -Got one of the listed errors -create table t6 (colint int, col1 date) engine='MYISAM' -partition by range(colint) -(partition p0 values less than (unix_timestamp ('2002-05-01')), -partition p1 values less than maxvalue); -Got one of the listed errors -drop table if exists t11 ; -drop table if exists t22 ; -drop table if exists t33 ; -drop table if exists t44 ; -drop table if exists t55 ; -drop table if exists t66 ; -create table t11 (col1 date) engine='MYISAM' ; -create table t22 (col1 date) engine='MYISAM' ; -create table t33 (col1 date) engine='MYISAM' ; -create table t44 (colint int, col1 date) engine='MYISAM' ; -create table t55 (colint int, col1 date) engine='MYISAM' ; -create table t66 (colint int, col1 date) engine='MYISAM' ; -alter table t11 -partition by range(unix_timestamp(col1)) -(partition p0 values less than (15), -partition p1 values less than (31)); -Got one of the listed errors -alter table t22 -partition by list(unix_timestamp(col1)) -(partition p0 values in (1,2,3,4,5,6,7,8,9,10), -partition p1 values in (11,12,13,14,15,16,17,18,19,20), -partition p2 values in (21,22,23,24,25,26,27,28,29,30)); -Got one of the listed errors -alter table t33 -partition by hash(unix_timestamp(col1)); -Got one of the listed errors -alter table t44 -partition by range(colint) -subpartition by hash(unix_timestamp(col1)) subpartitions 2 -(partition p0 values less than (15), -partition p1 values less than (31)); -Got one of the listed errors -alter table t55 -partition by list(colint) -subpartition by hash(unix_timestamp(col1)) subpartitions 2 -(partition p0 values in (1,2,3,4,5,6,7,8,9,10), -partition p1 values in (11,12,13,14,15,16,17,18,19,20), -partition p2 values in (21,22,23,24,25,26,27,28,29,30)); -Got one of the listed errors -alter table t66 -partition by range(colint) -(partition p0 values less than (unix_timestamp ('2002-05-01')), -partition p1 values less than maxvalue); -Got one of the listed errors -drop table if exists t1 ; -drop table if exists t2 ; -drop table if exists t3 ; -drop table if exists t4 ; -drop table if exists t5 ; -drop table if exists t6 ; -drop table if exists t11 ; -drop table if exists t22 ; -drop table if exists t33 ; -drop table if exists t44 ; -drop table if exists t55 ; -drop table if exists t66 ; -------------------------------------------------------------------------- --- week(col1) in partition with coltype datetime ------------------------------------------------------------------------- must all fail! diff --git a/mysql-test/suite/parts/r/partition_datetime_innodb.result b/mysql-test/suite/parts/r/partition_datetime_innodb.result index 67517ff5943..48af3343d9a 100644 --- a/mysql-test/suite/parts/r/partition_datetime_innodb.result +++ b/mysql-test/suite/parts/r/partition_datetime_innodb.result @@ -184,114 +184,6 @@ a 1971-01-01 00:00:58 1971-01-01 00:00:59 drop table t2; -create table t3 (a timestamp not null, primary key(a)) engine='InnoDB' -partition by range (month(a)) subpartition by key (a) -subpartitions 3 ( -partition quarter1 values less than (4), -partition quarter2 values less than (7), -partition quarter3 values less than (10), -partition quarter4 values less than (13) -); -show create table t3; -Table Create Table -t3 CREATE TABLE `t3` ( - `a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`a`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1 -/*!50100 PARTITION BY RANGE (month(a)) -SUBPARTITION BY KEY (a) -SUBPARTITIONS 3 -(PARTITION quarter1 VALUES LESS THAN (4) ENGINE = InnoDB, - PARTITION quarter2 VALUES LESS THAN (7) ENGINE = InnoDB, - PARTITION quarter3 VALUES LESS THAN (10) ENGINE = InnoDB, - PARTITION quarter4 VALUES LESS THAN (13) ENGINE = InnoDB) */ -12 inserts; -insert into t3 values (date_add('1970-01-01 00:00:00',interval 12-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 11-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 10-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 9-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 8-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 7-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 6-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 5-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 4-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 3-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 2-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 1-1 month)); -Warnings: -Warning 1264 Out of range value for column 'a' at row 1 -select count(*) from t3; -count(*) -12 -select * from t3; -a -0000-00-00 00:00:00 -1970-02-01 00:00:00 -1970-03-01 00:00:00 -1970-04-01 00:00:00 -1970-05-01 00:00:00 -1970-06-01 00:00:00 -1970-07-01 00:00:00 -1970-08-01 00:00:00 -1970-09-01 00:00:00 -1970-10-01 00:00:00 -1970-11-01 00:00:00 -1970-12-01 00:00:00 -drop table t3; -create table t4 (a timestamp not null, primary key(a)) engine='InnoDB' -partition by list (month(a)) subpartition by key (a) -subpartitions 3 ( -partition quarter1 values in (0,1,2,3), -partition quarter2 values in (4,5,6), -partition quarter3 values in (7,8,9), -partition quarter4 values in (10,11,12) -); -show create table t4; -Table Create Table -t4 CREATE TABLE `t4` ( - `a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`a`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1 -/*!50100 PARTITION BY LIST (month(a)) -SUBPARTITION BY KEY (a) -SUBPARTITIONS 3 -(PARTITION quarter1 VALUES IN (0,1,2,3) ENGINE = InnoDB, - PARTITION quarter2 VALUES IN (4,5,6) ENGINE = InnoDB, - PARTITION quarter3 VALUES IN (7,8,9) ENGINE = InnoDB, - PARTITION quarter4 VALUES IN (10,11,12) ENGINE = InnoDB) */ -12 inserts; -insert into t4 values (date_add('1970-01-01 00:00:00',interval 12-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 11-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 10-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 9-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 8-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 7-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 6-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 5-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 4-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 3-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 2-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 1-1 month)); -Warnings: -Warning 1264 Out of range value for column 'a' at row 1 -select count(*) from t4; -count(*) -12 -select * from t4; -a -0000-00-00 00:00:00 -1970-02-01 00:00:00 -1970-03-01 00:00:00 -1970-04-01 00:00:00 -1970-05-01 00:00:00 -1970-06-01 00:00:00 -1970-07-01 00:00:00 -1970-08-01 00:00:00 -1970-09-01 00:00:00 -1970-10-01 00:00:00 -1970-11-01 00:00:00 -1970-12-01 00:00:00 -drop table t4; create table t1 (a date not null, primary key(a)) engine='InnoDB' partition by key (a) ( partition pa1 max_rows=20 min_rows=2, diff --git a/mysql-test/suite/parts/r/partition_datetime_myisam.result b/mysql-test/suite/parts/r/partition_datetime_myisam.result index ad542870e65..146f291546e 100644 --- a/mysql-test/suite/parts/r/partition_datetime_myisam.result +++ b/mysql-test/suite/parts/r/partition_datetime_myisam.result @@ -184,114 +184,6 @@ a 1971-01-01 00:00:58 1971-01-01 00:00:59 drop table t2; -create table t3 (a timestamp not null, primary key(a)) engine='MyISAM' -partition by range (month(a)) subpartition by key (a) -subpartitions 3 ( -partition quarter1 values less than (4), -partition quarter2 values less than (7), -partition quarter3 values less than (10), -partition quarter4 values less than (13) -); -show create table t3; -Table Create Table -t3 CREATE TABLE `t3` ( - `a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`a`) -) ENGINE=MyISAM DEFAULT CHARSET=latin1 -/*!50100 PARTITION BY RANGE (month(a)) -SUBPARTITION BY KEY (a) -SUBPARTITIONS 3 -(PARTITION quarter1 VALUES LESS THAN (4) ENGINE = MyISAM, - PARTITION quarter2 VALUES LESS THAN (7) ENGINE = MyISAM, - PARTITION quarter3 VALUES LESS THAN (10) ENGINE = MyISAM, - PARTITION quarter4 VALUES LESS THAN (13) ENGINE = MyISAM) */ -12 inserts; -insert into t3 values (date_add('1970-01-01 00:00:00',interval 12-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 11-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 10-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 9-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 8-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 7-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 6-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 5-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 4-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 3-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 2-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 1-1 month)); -Warnings: -Warning 1264 Out of range value for column 'a' at row 1 -select count(*) from t3; -count(*) -12 -select * from t3; -a -0000-00-00 00:00:00 -1970-02-01 00:00:00 -1970-03-01 00:00:00 -1970-04-01 00:00:00 -1970-05-01 00:00:00 -1970-06-01 00:00:00 -1970-07-01 00:00:00 -1970-08-01 00:00:00 -1970-09-01 00:00:00 -1970-10-01 00:00:00 -1970-11-01 00:00:00 -1970-12-01 00:00:00 -drop table t3; -create table t4 (a timestamp not null, primary key(a)) engine='MyISAM' -partition by list (month(a)) subpartition by key (a) -subpartitions 3 ( -partition quarter1 values in (0,1,2,3), -partition quarter2 values in (4,5,6), -partition quarter3 values in (7,8,9), -partition quarter4 values in (10,11,12) -); -show create table t4; -Table Create Table -t4 CREATE TABLE `t4` ( - `a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`a`) -) ENGINE=MyISAM DEFAULT CHARSET=latin1 -/*!50100 PARTITION BY LIST (month(a)) -SUBPARTITION BY KEY (a) -SUBPARTITIONS 3 -(PARTITION quarter1 VALUES IN (0,1,2,3) ENGINE = MyISAM, - PARTITION quarter2 VALUES IN (4,5,6) ENGINE = MyISAM, - PARTITION quarter3 VALUES IN (7,8,9) ENGINE = MyISAM, - PARTITION quarter4 VALUES IN (10,11,12) ENGINE = MyISAM) */ -12 inserts; -insert into t4 values (date_add('1970-01-01 00:00:00',interval 12-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 11-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 10-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 9-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 8-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 7-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 6-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 5-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 4-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 3-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 2-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 1-1 month)); -Warnings: -Warning 1264 Out of range value for column 'a' at row 1 -select count(*) from t4; -count(*) -12 -select * from t4; -a -0000-00-00 00:00:00 -1970-02-01 00:00:00 -1970-03-01 00:00:00 -1970-04-01 00:00:00 -1970-05-01 00:00:00 -1970-06-01 00:00:00 -1970-07-01 00:00:00 -1970-08-01 00:00:00 -1970-09-01 00:00:00 -1970-10-01 00:00:00 -1970-11-01 00:00:00 -1970-12-01 00:00:00 -drop table t4; create table t1 (a date not null, primary key(a)) engine='MyISAM' partition by key (a) ( partition pa1 max_rows=20 min_rows=2, From aa388252872f721578266b32c8879ca338134bf5 Mon Sep 17 00:00:00 2001 From: Date: Tue, 15 Dec 2009 13:14:14 +0800 Subject: [PATCH 061/104] Bug #34628 LOAD DATA CONCURRENT INFILE drops CONCURRENT in binary log 'LOAD DATA CONCURRENT [LOCAL] INFILE ...' statment only is binlogged as 'LOAD DATA [LOCAL] INFILE ...' in SBR and MBR. As a result, if replication is on, queries on slaves will be blocked by the replication SQL thread. This patch write code to write 'CONCURRENT' into the log event if 'CONCURRENT' option is in the original statement in SBR and MBR. --- mysql-test/extra/rpl_tests/rpl_loaddata.test | 60 +++++--- mysql-test/suite/rpl/r/rpl_loaddata.result | 18 +-- .../rpl/r/rpl_loaddata_concurrent.result | 128 ++++++++++++++++++ .../suite/rpl/t/rpl_loaddata_concurrent.test | 12 ++ sql/log_event.cc | 4 + sql/log_event.h | 2 +- 6 files changed, 193 insertions(+), 31 deletions(-) create mode 100644 mysql-test/suite/rpl/r/rpl_loaddata_concurrent.result create mode 100644 mysql-test/suite/rpl/t/rpl_loaddata_concurrent.test diff --git a/mysql-test/extra/rpl_tests/rpl_loaddata.test b/mysql-test/extra/rpl_tests/rpl_loaddata.test index 7db12600456..948b77959f0 100644 --- a/mysql-test/extra/rpl_tests/rpl_loaddata.test +++ b/mysql-test/extra/rpl_tests/rpl_loaddata.test @@ -21,14 +21,26 @@ connection slave; reset master; connection master; +# MTR is not case-sensitive. +let $lower_stmt_head= load data; +let $UPPER_STMT_HEAD= LOAD DATA; +if (`SELECT '$lock_option' <> ''`) +{ + #if $lock_option is null, an extra blank is added into the statement, + #this will change the result of rpl_loaddata test case. so $lock_option + #is set only when it is not null. + let $lower_stmt_head= load data $lock_option; + let $UPPER_STMT_HEAD= LOAD DATA $lock_option; +} + select last_insert_id(); create table t1(a int not null auto_increment, b int, primary key(a) ); -load data infile '../../std_data/rpl_loaddata.dat' into table t1; +eval $lower_stmt_head infile '../../std_data/rpl_loaddata.dat' into table t1; # verify that LAST_INSERT_ID() is set by LOAD DATA INFILE select last_insert_id(); create temporary table t2 (day date,id int(9),category enum('a','b','c'),name varchar(60)); -load data infile '../../std_data/rpl_loaddata2.dat' into table t2 fields terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by '\n##\n' starting by '>' ignore 1 lines; +eval $lower_stmt_head infile '../../std_data/rpl_loaddata2.dat' into table t2 fields terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by '\n##\n' starting by '>' ignore 1 lines; create table t3 (day date,id int(9),category enum('a','b','c'),name varchar(60)); insert into t3 select * from t2; @@ -56,7 +68,7 @@ sync_with_master; insert into t1 values(1,10); connection master; -load data infile '../../std_data/rpl_loaddata.dat' into table t1; +eval $lower_stmt_head infile '../../std_data/rpl_loaddata.dat' into table t1; save_master_pos; connection slave; @@ -70,9 +82,11 @@ connection slave; set global sql_slave_skip_counter=1; start slave; sync_with_master; ---replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 1 # 8 # 9 # 16 # 23 # 33 # -show slave status; +let $last_error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Errno, 1); +echo Last_SQL_Errno=$last_error; +let $last_error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Error, 1); +echo Last_SQL_Error; +echo $last_error; # Trigger error again to test CHANGE MASTER @@ -80,7 +94,7 @@ connection master; set sql_log_bin=0; delete from t1; set sql_log_bin=1; -load data infile '../../std_data/rpl_loaddata.dat' into table t1; +eval $lower_stmt_head infile '../../std_data/rpl_loaddata.dat' into table t1; save_master_pos; connection slave; # The SQL slave thread should be stopped now. @@ -92,9 +106,11 @@ connection slave; stop slave; change master to master_user='test'; change master to master_user='root'; ---replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 1 # 8 # 9 # 16 # 23 # 33 # -show slave status; +let $last_error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Errno, 1); +echo Last_SQL_Errno=$last_error; +let $last_error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Error, 1); +echo Last_SQL_Error; +echo $last_error; # Trigger error again to test RESET SLAVE @@ -105,7 +121,7 @@ connection master; set sql_log_bin=0; delete from t1; set sql_log_bin=1; -load data infile '../../std_data/rpl_loaddata.dat' into table t1; +eval $lower_stmt_head infile '../../std_data/rpl_loaddata.dat' into table t1; save_master_pos; connection slave; # The SQL slave thread should be stopped now. @@ -114,9 +130,11 @@ connection slave; # RESET SLAVE and see if error is cleared in SHOW SLAVE STATUS. stop slave; reset slave; ---replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 1 # 8 # 9 # 16 # 23 # 33 # -show slave status; +let $last_error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Errno, 1); +echo Last_SQL_Errno=$last_error; +let $last_error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Error, 1); +echo Last_SQL_Error; +echo $last_error; # Finally, see if logging is done ok on master for a failing LOAD DATA INFILE @@ -125,7 +143,7 @@ reset master; eval create table t2 (day date,id int(9),category enum('a','b','c'),name varchar(60), unique(day)) engine=$engine_type; # no transactions --error ER_DUP_ENTRY -load data infile '../../std_data/rpl_loaddata2.dat' into table t2 fields +eval $lower_stmt_head infile '../../std_data/rpl_loaddata2.dat' into table t2 fields terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by '\n##\n' starting by '>' ignore 1 lines; select * from t2; @@ -141,7 +159,7 @@ alter table t2 drop key day; connection master; delete from t2; --error ER_DUP_ENTRY -load data infile '../../std_data/rpl_loaddata2.dat' into table t2 fields +eval $lower_stmt_head infile '../../std_data/rpl_loaddata2.dat' into table t2 fields terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by '\n##\n' starting by '>' ignore 1 lines; connection slave; @@ -154,7 +172,7 @@ drop table t1, t2; CREATE TABLE t1 (word CHAR(20) NOT NULL PRIMARY KEY) ENGINE=INNODB; --error ER_DUP_ENTRY -LOAD DATA INFILE "../../std_data/words.dat" INTO TABLE t1; +eval $UPPER_STMT_HEAD INFILE "../../std_data/words.dat" INTO TABLE t1; DROP TABLE IF EXISTS t1; @@ -182,17 +200,17 @@ DROP TABLE IF EXISTS t1; -- echo ### assertion: works with cross-referenced database -- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR --- eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE $db1.t1 +-- eval $UPPER_STMT_HEAD LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE $db1.t1 -- eval use $db1 -- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR -- echo ### assertion: works with fully qualified name on current database -- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR --- eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE $db1.t1 +-- eval $UPPER_STMT_HEAD LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE $db1.t1 -- echo ### assertion: works without fully qualified name on current database -- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR --- eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE t1 +-- eval $UPPER_STMT_HEAD LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE t1 -- echo ### create connection without default database -- echo ### connect (conn2,localhost,root,,*NO-ONE*); @@ -200,7 +218,7 @@ connect (conn2,localhost,root,,*NO-ONE*); -- connection conn2 -- echo ### assertion: works without stating the default database -- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR --- eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE $db1.t1 +-- eval $UPPER_STMT_HEAD LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE $db1.t1 -- echo ### disconnect and switch back to master connection -- disconnect conn2 -- connection master diff --git a/mysql-test/suite/rpl/r/rpl_loaddata.result b/mysql-test/suite/rpl/r/rpl_loaddata.result index ca9c14691b0..a8da9aae68e 100644 --- a/mysql-test/suite/rpl/r/rpl_loaddata.result +++ b/mysql-test/suite/rpl/r/rpl_loaddata.result @@ -34,9 +34,9 @@ insert into t1 values(1,10); load data infile '../../std_data/rpl_loaddata.dat' into table t1; set global sql_slave_skip_counter=1; start slave; -show slave status; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error -# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 2009 # # master-bin.000001 Yes Yes # 0 0 2009 # None 0 No # No 0 0 +Last_SQL_Errno=0 +Last_SQL_Error + set sql_log_bin=0; delete from t1; set sql_log_bin=1; @@ -44,9 +44,9 @@ load data infile '../../std_data/rpl_loaddata.dat' into table t1; stop slave; change master to master_user='test'; change master to master_user='root'; -show slave status; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error -# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 2044 # # master-bin.000001 No No # 0 0 2044 # None 0 No # No 0 0 +Last_SQL_Errno=0 +Last_SQL_Error + set global sql_slave_skip_counter=1; start slave; set sql_log_bin=0; @@ -55,9 +55,9 @@ set sql_log_bin=1; load data infile '../../std_data/rpl_loaddata.dat' into table t1; stop slave; reset slave; -show slave status; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error -# 127.0.0.1 root MASTER_PORT 1 4 # # No No # 0 0 0 # None 0 No # No 0 0 +Last_SQL_Errno=0 +Last_SQL_Error + reset master; create table t2 (day date,id int(9),category enum('a','b','c'),name varchar(60), unique(day)) engine=MyISAM; diff --git a/mysql-test/suite/rpl/r/rpl_loaddata_concurrent.result b/mysql-test/suite/rpl/r/rpl_loaddata_concurrent.result new file mode 100644 index 00000000000..1ea9b33c262 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_loaddata_concurrent.result @@ -0,0 +1,128 @@ +CREATE TABLE t1 (c1 char(50)); +LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE t1; +LOAD DATA CONCURRENT INFILE '../../std_data/words.dat' INTO TABLE t1; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (c1 char(50)) +master-bin.000001 # Begin_load_query # # ;file_id=#;block_len=# +master-bin.000001 # Execute_load_query # # use `test`; LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (c1) ;file_id=# +master-bin.000001 # Begin_load_query # # ;file_id=#;block_len=# +master-bin.000001 # Execute_load_query # # use `test`; LOAD DATA CONCURRENT INFILE '../../std_data/words.dat' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (c1) ;file_id=# +DROP TABLE t1; +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +reset master; +select last_insert_id(); +last_insert_id() +0 +create table t1(a int not null auto_increment, b int, primary key(a) ); +load data CONCURRENT infile '../../std_data/rpl_loaddata.dat' into table t1; +select last_insert_id(); +last_insert_id() +1 +create temporary table t2 (day date,id int(9),category enum('a','b','c'),name varchar(60)); +load data CONCURRENT infile '../../std_data/rpl_loaddata2.dat' into table t2 fields terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by '\n##\n' starting by '>' ignore 1 lines; +create table t3 (day date,id int(9),category enum('a','b','c'),name varchar(60)); +insert into t3 select * from t2; +select * from t1; +a b +1 10 +2 15 +select * from t3; +day id category name +2003-02-22 2461 b a a a @ %  ' " a +2003-03-22 2161 c asdf +2003-03-22 2416 a bbbbb +drop table t1; +drop table t2; +drop table t3; +create table t1(a int, b int, unique(b)); +insert into t1 values(1,10); +load data CONCURRENT infile '../../std_data/rpl_loaddata.dat' into table t1; +set global sql_slave_skip_counter=1; +start slave; +Last_SQL_Errno=0 +Last_SQL_Error + +set sql_log_bin=0; +delete from t1; +set sql_log_bin=1; +load data CONCURRENT infile '../../std_data/rpl_loaddata.dat' into table t1; +stop slave; +change master to master_user='test'; +change master to master_user='root'; +Last_SQL_Errno=0 +Last_SQL_Error + +set global sql_slave_skip_counter=1; +start slave; +set sql_log_bin=0; +delete from t1; +set sql_log_bin=1; +load data CONCURRENT infile '../../std_data/rpl_loaddata.dat' into table t1; +stop slave; +reset slave; +Last_SQL_Errno=0 +Last_SQL_Error + +reset master; +create table t2 (day date,id int(9),category enum('a','b','c'),name varchar(60), +unique(day)) engine=MyISAM; +load data CONCURRENT infile '../../std_data/rpl_loaddata2.dat' into table t2 fields +terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by +'\n##\n' starting by '>' ignore 1 lines; +ERROR 23000: Duplicate entry '2003-03-22' for key 'day' +select * from t2; +day id category name +2003-02-22 2461 b a a a @ %  ' " a +2003-03-22 2161 c asdf +start slave; +select * from t2; +day id category name +2003-02-22 2461 b a a a @ %  ' " a +2003-03-22 2161 c asdf +alter table t2 drop key day; +delete from t2; +load data CONCURRENT infile '../../std_data/rpl_loaddata2.dat' into table t2 fields +terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by +'\n##\n' starting by '>' ignore 1 lines; +ERROR 23000: Duplicate entry '2003-03-22' for key 'day' +drop table t1, t2; +drop table t1, t2; +CREATE TABLE t1 (word CHAR(20) NOT NULL PRIMARY KEY) ENGINE=INNODB; +LOAD DATA CONCURRENT INFILE "../../std_data/words.dat" INTO TABLE t1; +ERROR 23000: Duplicate entry 'Aarhus' for key 'PRIMARY' +DROP TABLE IF EXISTS t1; +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +drop database if exists b48297_db1; +drop database if exists b42897_db2; +create database b48297_db1; +create database b42897_db2; +use b48297_db1; +CREATE TABLE t1 (c1 VARCHAR(256)) engine=MyISAM;; +use b42897_db2; +### assertion: works with cross-referenced database +LOAD DATA CONCURRENT LOCAL INFILE 'MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE b48297_db1.t1; +use b48297_db1; +### assertion: works with fully qualified name on current database +LOAD DATA CONCURRENT LOCAL INFILE 'MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE b48297_db1.t1; +### assertion: works without fully qualified name on current database +LOAD DATA CONCURRENT LOCAL INFILE 'MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE t1; +### create connection without default database +### connect (conn2,localhost,root,,*NO-ONE*); +### assertion: works without stating the default database +LOAD DATA CONCURRENT LOCAL INFILE 'MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE b48297_db1.t1; +### disconnect and switch back to master connection +use b48297_db1; +Comparing tables master:b48297_db1.t1 and slave:b48297_db1.t1 +DROP DATABASE b48297_db1; +DROP DATABASE b42897_db2; diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_concurrent.test b/mysql-test/suite/rpl/t/rpl_loaddata_concurrent.test new file mode 100644 index 00000000000..1276b0f3700 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_loaddata_concurrent.test @@ -0,0 +1,12 @@ +-- source include/not_ndb_default.inc +-- source include/have_log_bin.inc + +CREATE TABLE t1 (c1 char(50)); +LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE t1; +LOAD DATA CONCURRENT INFILE '../../std_data/words.dat' INTO TABLE t1; +-- source include/show_binlog_events.inc +DROP TABLE t1; + +let $lock_option= CONCURRENT; +let $engine_type=MyISAM; +-- source extra/rpl_tests/rpl_loaddata.test diff --git a/sql/log_event.cc b/sql/log_event.cc index 6686a4634f7..9552bfad27f 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -4006,6 +4006,7 @@ uint Load_log_event::get_query_buffer_length() return 5 + db_len + 3 + // "use DB; " 18 + fname_len + 2 + // "LOAD DATA INFILE 'file''" + 11 + // "CONCURRENT " 7 + // LOCAL 9 + // " REPLACE or IGNORE " 13 + table_name_len*2 + // "INTO TABLE `table`" @@ -4033,6 +4034,9 @@ void Load_log_event::print_query(bool need_db, const char *cs, char *buf, pos= strmov(pos, "LOAD DATA "); + if (thd->lex->lock_option == TL_WRITE_CONCURRENT_INSERT) + pos= strmov(pos, "CONCURRENT "); + if (fn_start) *fn_start= pos; diff --git a/sql/log_event.h b/sql/log_event.h index 0b4c63a73af..b3098c04364 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -1766,7 +1766,7 @@ private: @verbatim (1) USE db; - (2) LOAD DATA [LOCAL] INFILE 'file_name' + (2) LOAD DATA [CONCURRENT] [LOCAL] INFILE 'file_name' (3) [REPLACE | IGNORE] (4) INTO TABLE 'table_name' (5) [FIELDS From e76d96c4adddd1ab2868339b82abb49ba7e17cda Mon Sep 17 00:00:00 2001 From: He Zhenxing Date: Tue, 15 Dec 2009 14:48:28 +0800 Subject: [PATCH 062/104] bug#49536 - deadlock on rotate_and_purge when using expire_logs_days Problem is that purge_logs implementation in ndb (ndbcluster_binlog_index_purge_file) calls mysql_parse (with (thd->options & OPTION_BIN_LOG) === 0)) but MYSQL_BIN_LOG first takes LOCK_log and then checks thd->options Solution in this patch, changes so that rotate_and_purge does not hold LOCK_log when calling purge_logs_before_date. I think this is safe as other "purge"-function(s) is called wo/ holding LOCK_log, e.g purge_master_logs --- sql/log.cc | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/sql/log.cc b/sql/log.cc index f795cdab2ca..1adf92e709c 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -4481,6 +4481,9 @@ bool general_log_write(THD *thd, enum enum_server_command command, void MYSQL_BIN_LOG::rotate_and_purge(uint flags) { +#ifdef HAVE_REPLICATION + bool check_purge= false; +#endif if (!(flags & RP_LOCK_LOG_IS_ALREADY_LOCKED)) pthread_mutex_lock(&LOCK_log); if ((flags & RP_FORCE_ROTATE) || @@ -4488,16 +4491,24 @@ void MYSQL_BIN_LOG::rotate_and_purge(uint flags) { new_file_without_locking(); #ifdef HAVE_REPLICATION - if (expire_logs_days) - { - time_t purge_time= my_time(0) - expire_logs_days*24*60*60; - if (purge_time >= 0) - purge_logs_before_date(purge_time); - } + check_purge= true; #endif } if (!(flags & RP_LOCK_LOG_IS_ALREADY_LOCKED)) pthread_mutex_unlock(&LOCK_log); + +#ifdef HAVE_REPLICATION + /* + NOTE: Run purge_logs wo/ holding LOCK_log + as it otherwise will deadlock in ndbcluster_binlog_index_purge_file + */ + if (check_purge && expire_logs_days) + { + time_t purge_time= my_time(0) - expire_logs_days*24*60*60; + if (purge_time >= 0) + purge_logs_before_date(purge_time); + } +#endif } uint MYSQL_BIN_LOG::next_file_id() From 4b603e488125e0bae275936bb35208bb3ddde90a Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Tue, 15 Dec 2009 10:37:10 +0200 Subject: [PATCH 063/104] Bug #49480: WHERE using YEAR columns returns unexpected results Merge the fix from 5.1-bugteam to 5.1-main --- mysql-test/r/type_year.result | 264 ++++++++++++++++++++++++++++++++++ mysql-test/t/type_year.test | 106 ++++++++++++++ sql/item_cmpfunc.cc | 144 +++++++------------ sql/item_cmpfunc.h | 9 +- 4 files changed, 421 insertions(+), 102 deletions(-) diff --git a/mysql-test/r/type_year.result b/mysql-test/r/type_year.result index e52947455c8..56b326327c6 100644 --- a/mysql-test/r/type_year.result +++ b/mysql-test/r/type_year.result @@ -46,3 +46,267 @@ a 2001 drop table t1; End of 5.0 tests +# +# Bug #49480: WHERE using YEAR columns returns unexpected results +# +CREATE TABLE t2(yy YEAR(2), c2 CHAR(4)); +CREATE TABLE t4(yyyy YEAR(4), c4 CHAR(4)); +INSERT INTO t2 (c2) VALUES (NULL),(1970),(1999),(2000),(2001),(2069); +INSERT INTO t4 (c4) SELECT c2 FROM t2; +UPDATE t2 SET yy = c2; +UPDATE t4 SET yyyy = c4; +SELECT * FROM t2; +yy c2 +NULL NULL +70 1970 +99 1999 +00 2000 +01 2001 +69 2069 +SELECT * FROM t4; +yyyy c4 +NULL NULL +1970 1970 +1999 1999 +2000 2000 +2001 2001 +2069 2069 +# Comparison of YEAR(2) with YEAR(4) +SELECT * FROM t2, t4 WHERE yy = yyyy; +yy c2 yyyy c4 +70 1970 1970 1970 +99 1999 1999 1999 +00 2000 2000 2000 +01 2001 2001 2001 +69 2069 2069 2069 +SELECT * FROM t2, t4 WHERE yy <=> yyyy; +yy c2 yyyy c4 +NULL NULL NULL NULL +70 1970 1970 1970 +99 1999 1999 1999 +00 2000 2000 2000 +01 2001 2001 2001 +69 2069 2069 2069 +SELECT * FROM t2, t4 WHERE yy < yyyy; +yy c2 yyyy c4 +70 1970 1999 1999 +70 1970 2000 2000 +99 1999 2000 2000 +70 1970 2001 2001 +99 1999 2001 2001 +00 2000 2001 2001 +70 1970 2069 2069 +99 1999 2069 2069 +00 2000 2069 2069 +01 2001 2069 2069 +SELECT * FROM t2, t4 WHERE yy > yyyy; +yy c2 yyyy c4 +99 1999 1970 1970 +00 2000 1970 1970 +01 2001 1970 1970 +69 2069 1970 1970 +00 2000 1999 1999 +01 2001 1999 1999 +69 2069 1999 1999 +01 2001 2000 2000 +69 2069 2000 2000 +69 2069 2001 2001 +# Comparison of YEAR(2) with YEAR(2) +SELECT * FROM t2 a, t2 b WHERE a.yy = b.yy; +yy c2 yy c2 +70 1970 70 1970 +99 1999 99 1999 +00 2000 00 2000 +01 2001 01 2001 +69 2069 69 2069 +SELECT * FROM t2 a, t2 b WHERE a.yy <=> b.yy; +yy c2 yy c2 +NULL NULL NULL NULL +70 1970 70 1970 +99 1999 99 1999 +00 2000 00 2000 +01 2001 01 2001 +69 2069 69 2069 +SELECT * FROM t2 a, t2 b WHERE a.yy < b.yy; +yy c2 yy c2 +70 1970 99 1999 +70 1970 00 2000 +99 1999 00 2000 +70 1970 01 2001 +99 1999 01 2001 +00 2000 01 2001 +70 1970 69 2069 +99 1999 69 2069 +00 2000 69 2069 +01 2001 69 2069 +# Comparison of YEAR(4) with YEAR(4) +SELECT * FROM t4 a, t4 b WHERE a.yyyy = b.yyyy; +yyyy c4 yyyy c4 +1970 1970 1970 1970 +1999 1999 1999 1999 +2000 2000 2000 2000 +2001 2001 2001 2001 +2069 2069 2069 2069 +SELECT * FROM t4 a, t4 b WHERE a.yyyy <=> b.yyyy; +yyyy c4 yyyy c4 +NULL NULL NULL NULL +1970 1970 1970 1970 +1999 1999 1999 1999 +2000 2000 2000 2000 +2001 2001 2001 2001 +2069 2069 2069 2069 +SELECT * FROM t4 a, t4 b WHERE a.yyyy < b.yyyy; +yyyy c4 yyyy c4 +1970 1970 1999 1999 +1970 1970 2000 2000 +1999 1999 2000 2000 +1970 1970 2001 2001 +1999 1999 2001 2001 +2000 2000 2001 2001 +1970 1970 2069 2069 +1999 1999 2069 2069 +2000 2000 2069 2069 +2001 2001 2069 2069 +# Comparison with constants: +SELECT * FROM t2 WHERE yy = NULL; +yy c2 +SELECT * FROM t4 WHERE yyyy = NULL; +yyyy c4 +SELECT * FROM t2 WHERE yy <=> NULL; +yy c2 +NULL NULL +SELECT * FROM t4 WHERE yyyy <=> NULL; +yyyy c4 +NULL NULL +SELECT * FROM t2 WHERE yy < NULL; +yy c2 +SELECT * FROM t2 WHERE yy > NULL; +yy c2 +SELECT * FROM t2 WHERE yy = NOW(); +yy c2 +SELECT * FROM t4 WHERE yyyy = NOW(); +yyyy c4 +SELECT * FROM t2 WHERE yy = 99; +yy c2 +99 1999 +SELECT * FROM t2 WHERE 99 = yy; +yy c2 +99 1999 +SELECT * FROM t4 WHERE yyyy = 99; +yyyy c4 +1999 1999 +SELECT * FROM t2 WHERE yy = 'test'; +yy c2 +00 2000 +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: 'test' +SELECT * FROM t4 WHERE yyyy = 'test'; +yyyy c4 +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: 'test' +SELECT * FROM t2 WHERE yy = '1999'; +yy c2 +99 1999 +SELECT * FROM t4 WHERE yyyy = '1999'; +yyyy c4 +1999 1999 +SELECT * FROM t2 WHERE yy = 1999; +yy c2 +99 1999 +SELECT * FROM t4 WHERE yyyy = 1999; +yyyy c4 +1999 1999 +SELECT * FROM t2 WHERE yy = 1999.1; +yy c2 +99 1999 +SELECT * FROM t4 WHERE yyyy = 1999.1; +yyyy c4 +1999 1999 +SELECT * FROM t2 WHERE yy = 1998.9; +yy c2 +99 1999 +SELECT * FROM t4 WHERE yyyy = 1998.9; +yyyy c4 +1999 1999 +# Coverage tests for YEAR with zero/2000 constants: +SELECT * FROM t2 WHERE yy = 0; +yy c2 +00 2000 +SELECT * FROM t2 WHERE yy = '0'; +yy c2 +00 2000 +SELECT * FROM t2 WHERE yy = '0000'; +yy c2 +00 2000 +SELECT * FROM t2 WHERE yy = '2000'; +yy c2 +00 2000 +SELECT * FROM t2 WHERE yy = 2000; +yy c2 +00 2000 +SELECT * FROM t4 WHERE yyyy = 0; +yyyy c4 +SELECT * FROM t4 WHERE yyyy = '0'; +yyyy c4 +2000 2000 +SELECT * FROM t4 WHERE yyyy = '0000'; +yyyy c4 +SELECT * FROM t4 WHERE yyyy = '2000'; +yyyy c4 +2000 2000 +SELECT * FROM t4 WHERE yyyy = 2000; +yyyy c4 +2000 2000 +# Comparison with constants those are out of YEAR range +# (coverage test for backward compatibility) +SELECT COUNT(yy) FROM t2; +COUNT(yy) +5 +SELECT COUNT(yyyy) FROM t4; +COUNT(yyyy) +5 +SELECT COUNT(*) FROM t2 WHERE yy = -1; +COUNT(*) +0 +SELECT COUNT(*) FROM t4 WHERE yyyy > -1; +COUNT(*) +5 +SELECT COUNT(*) FROM t2 WHERE yy > -1000000000000000000; +COUNT(*) +5 +SELECT COUNT(*) FROM t4 WHERE yyyy > -1000000000000000000; +COUNT(*) +5 +SELECT COUNT(*) FROM t2 WHERE yy < 2156; +COUNT(*) +5 +SELECT COUNT(*) FROM t4 WHERE yyyy < 2156; +COUNT(*) +5 +SELECT COUNT(*) FROM t2 WHERE yy < 1000000000000000000; +COUNT(*) +5 +SELECT COUNT(*) FROM t4 WHERE yyyy < 1000000000000000000; +COUNT(*) +5 +SELECT * FROM t2 WHERE yy < 123; +yy c2 +70 1970 +99 1999 +00 2000 +01 2001 +69 2069 +SELECT * FROM t2 WHERE yy > 123; +yy c2 +SELECT * FROM t4 WHERE yyyy < 123; +yyyy c4 +SELECT * FROM t4 WHERE yyyy > 123; +yyyy c4 +1970 1970 +1999 1999 +2000 2000 +2001 2001 +2069 2069 +DROP TABLE t2, t4; +# +End of 5.1 tests diff --git a/mysql-test/t/type_year.test b/mysql-test/t/type_year.test index 0e174a556d6..16fd39a59d8 100644 --- a/mysql-test/t/type_year.test +++ b/mysql-test/t/type_year.test @@ -30,3 +30,109 @@ select * from t1; drop table t1; --echo End of 5.0 tests + +--echo # +--echo # Bug #49480: WHERE using YEAR columns returns unexpected results +--echo # + +CREATE TABLE t2(yy YEAR(2), c2 CHAR(4)); +CREATE TABLE t4(yyyy YEAR(4), c4 CHAR(4)); + +INSERT INTO t2 (c2) VALUES (NULL),(1970),(1999),(2000),(2001),(2069); +INSERT INTO t4 (c4) SELECT c2 FROM t2; +UPDATE t2 SET yy = c2; +UPDATE t4 SET yyyy = c4; + +SELECT * FROM t2; +SELECT * FROM t4; + +--echo # Comparison of YEAR(2) with YEAR(4) + +SELECT * FROM t2, t4 WHERE yy = yyyy; +SELECT * FROM t2, t4 WHERE yy <=> yyyy; +SELECT * FROM t2, t4 WHERE yy < yyyy; +SELECT * FROM t2, t4 WHERE yy > yyyy; + +--echo # Comparison of YEAR(2) with YEAR(2) + +SELECT * FROM t2 a, t2 b WHERE a.yy = b.yy; +SELECT * FROM t2 a, t2 b WHERE a.yy <=> b.yy; +SELECT * FROM t2 a, t2 b WHERE a.yy < b.yy; + +--echo # Comparison of YEAR(4) with YEAR(4) + +SELECT * FROM t4 a, t4 b WHERE a.yyyy = b.yyyy; +SELECT * FROM t4 a, t4 b WHERE a.yyyy <=> b.yyyy; +SELECT * FROM t4 a, t4 b WHERE a.yyyy < b.yyyy; + +--echo # Comparison with constants: + +SELECT * FROM t2 WHERE yy = NULL; +SELECT * FROM t4 WHERE yyyy = NULL; +SELECT * FROM t2 WHERE yy <=> NULL; +SELECT * FROM t4 WHERE yyyy <=> NULL; +SELECT * FROM t2 WHERE yy < NULL; +SELECT * FROM t2 WHERE yy > NULL; + +SELECT * FROM t2 WHERE yy = NOW(); +SELECT * FROM t4 WHERE yyyy = NOW(); + +SELECT * FROM t2 WHERE yy = 99; +SELECT * FROM t2 WHERE 99 = yy; +SELECT * FROM t4 WHERE yyyy = 99; + +SELECT * FROM t2 WHERE yy = 'test'; +SELECT * FROM t4 WHERE yyyy = 'test'; + +SELECT * FROM t2 WHERE yy = '1999'; +SELECT * FROM t4 WHERE yyyy = '1999'; + +SELECT * FROM t2 WHERE yy = 1999; +SELECT * FROM t4 WHERE yyyy = 1999; + +SELECT * FROM t2 WHERE yy = 1999.1; +SELECT * FROM t4 WHERE yyyy = 1999.1; + +SELECT * FROM t2 WHERE yy = 1998.9; +SELECT * FROM t4 WHERE yyyy = 1998.9; + +--echo # Coverage tests for YEAR with zero/2000 constants: + +SELECT * FROM t2 WHERE yy = 0; +SELECT * FROM t2 WHERE yy = '0'; +SELECT * FROM t2 WHERE yy = '0000'; +SELECT * FROM t2 WHERE yy = '2000'; +SELECT * FROM t2 WHERE yy = 2000; + +SELECT * FROM t4 WHERE yyyy = 0; +SELECT * FROM t4 WHERE yyyy = '0'; +SELECT * FROM t4 WHERE yyyy = '0000'; +SELECT * FROM t4 WHERE yyyy = '2000'; +SELECT * FROM t4 WHERE yyyy = 2000; + +--echo # Comparison with constants those are out of YEAR range +--echo # (coverage test for backward compatibility) + +SELECT COUNT(yy) FROM t2; +SELECT COUNT(yyyy) FROM t4; + +SELECT COUNT(*) FROM t2 WHERE yy = -1; +SELECT COUNT(*) FROM t4 WHERE yyyy > -1; +SELECT COUNT(*) FROM t2 WHERE yy > -1000000000000000000; +SELECT COUNT(*) FROM t4 WHERE yyyy > -1000000000000000000; + +SELECT COUNT(*) FROM t2 WHERE yy < 2156; +SELECT COUNT(*) FROM t4 WHERE yyyy < 2156; +SELECT COUNT(*) FROM t2 WHERE yy < 1000000000000000000; +SELECT COUNT(*) FROM t4 WHERE yyyy < 1000000000000000000; + +SELECT * FROM t2 WHERE yy < 123; +SELECT * FROM t2 WHERE yy > 123; +SELECT * FROM t4 WHERE yyyy < 123; +SELECT * FROM t4 WHERE yyyy > 123; + +DROP TABLE t2, t4; + +--echo # + +--echo End of 5.1 tests diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index fd5eca8911a..d99748b87a0 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -956,40 +956,9 @@ int Arg_comparator::set_cmp_func(Item_result_field *owner_arg, if (agg_item_set_converter(coll, owner->func_name(), b, 1, MY_COLL_CMP_CONV, 1)) return 1; - } else if (type != ROW_RESULT && ((*a)->field_type() == MYSQL_TYPE_YEAR || - (*b)->field_type() == MYSQL_TYPE_YEAR)) - { - is_nulls_eq= is_owner_equal_func(); - year_as_datetime= FALSE; - - if ((*a)->is_datetime()) - { - year_as_datetime= TRUE; - get_value_a_func= &get_datetime_value; - } else if ((*a)->field_type() == MYSQL_TYPE_YEAR) - get_value_a_func= &get_year_value; - else - { - /* - Because convert_constant_item is called only for EXECUTE in PS mode - the value of get_value_x_func set in PREPARE might be not - valid for EXECUTE. - */ - get_value_a_func= NULL; - } - - if ((*b)->is_datetime()) - { - year_as_datetime= TRUE; - get_value_b_func= &get_datetime_value; - } else if ((*b)->field_type() == MYSQL_TYPE_YEAR) - get_value_b_func= &get_year_value; - else - get_value_b_func= NULL; - - func= &Arg_comparator::compare_year; - return 0; } + else if (try_year_cmp_func(type)) + return 0; a= cache_converted_constant(thd, a, &a_cache, type); b= cache_converted_constant(thd, b, &b_cache, type); @@ -997,6 +966,45 @@ int Arg_comparator::set_cmp_func(Item_result_field *owner_arg, } +/* + Helper function to call from Arg_comparator::set_cmp_func() +*/ + +bool Arg_comparator::try_year_cmp_func(Item_result type) +{ + if (type == ROW_RESULT) + return FALSE; + + bool a_is_year= (*a)->field_type() == MYSQL_TYPE_YEAR; + bool b_is_year= (*b)->field_type() == MYSQL_TYPE_YEAR; + + if (!a_is_year && !b_is_year) + return FALSE; + + if (a_is_year && b_is_year) + { + get_value_a_func= &get_year_value; + get_value_b_func= &get_year_value; + } + else if (a_is_year && (*b)->is_datetime()) + { + get_value_a_func= &get_year_value; + get_value_b_func= &get_datetime_value; + } + else if (b_is_year && (*a)->is_datetime()) + { + get_value_b_func= &get_year_value; + get_value_a_func= &get_datetime_value; + } + else + return FALSE; + + is_nulls_eq= is_owner_equal_func(); + func= &Arg_comparator::compare_datetime; + + return TRUE; +} + /** Convert and cache a constant. @@ -1147,7 +1155,7 @@ get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg, /* - Retrieves YEAR value of 19XX form from given item. + Retrieves YEAR value of 19XX-00-00 00:00:00 form from given item. SYNOPSIS get_year_value() @@ -1159,7 +1167,9 @@ get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg, DESCRIPTION Retrieves the YEAR value of 19XX form from given item for comparison by the - compare_year() function. + compare_datetime() function. + Converts year to DATETIME of form YYYY-00-00 00:00:00 for the compatibility + with the get_datetime_value function result. RETURN obtained value @@ -1186,6 +1196,9 @@ get_year_value(THD *thd, Item ***item_arg, Item **cache_arg, if (value <= 1900) value+= 1900; + /* Convert year to DATETIME of form YYYY-00-00 00:00:00 (YYYY0000000000). */ + value*= 10000000000LL; + return value; } @@ -1615,67 +1628,6 @@ int Arg_comparator::compare_e_row() } -/** - Compare values as YEAR. - - @details - Compare items as YEAR for EQUAL_FUNC and for other comparison functions. - The YEAR values of form 19XX are obtained with help of the get_year_value() - function. - If one of arguments is of DATE/DATETIME type its value is obtained - with help of the get_datetime_value function. In this case YEAR values - prior to comparison are converted to the ulonglong YYYY-00-00 00:00:00 - DATETIME form. - If an argument type neither YEAR nor DATE/DATEIME then val_int function - is used to obtain value for comparison. - - RETURN - If is_nulls_eq is TRUE: - 1 if items are equal or both are null - 0 otherwise - If is_nulls_eq is FALSE: - -1 a < b - 0 a == b or at least one of items is null - 1 a > b - See the table: - is_nulls_eq | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | - a_is_null | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | - b_is_null | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | - result | 1 | 0 | 0 |0/1| 0 | 0 | 0 |-1/0/1| -*/ - -int Arg_comparator::compare_year() -{ - bool a_is_null, b_is_null; - ulonglong val1= get_value_a_func ? - (*get_value_a_func)(thd, &a, &a_cache, *b, &a_is_null) : - (*a)->val_int(); - ulonglong val2= get_value_b_func ? - (*get_value_b_func)(thd, &b, &b_cache, *a, &b_is_null) : - (*b)->val_int(); - if (!(*a)->null_value) - { - if (!(*b)->null_value) - { - if (set_null) - owner->null_value= 0; - /* Convert year to DATETIME of form YYYY-00-00 00:00:00 when necessary. */ - if((*a)->field_type() == MYSQL_TYPE_YEAR && year_as_datetime) - val1*= 10000000000LL; - if((*b)->field_type() == MYSQL_TYPE_YEAR && year_as_datetime) - val2*= 10000000000LL; - - if (val1 < val2) return is_nulls_eq ? 0 : -1; - if (val1 == val2) return is_nulls_eq ? 1 : 0; - return is_nulls_eq ? 0 : 1; - } - } - if (set_null) - owner->null_value= is_nulls_eq ? 0 : 1; - return (is_nulls_eq && (*a)->null_value == (*b)->null_value) ? 1 : 0; -} - - void Item_func_truth::fix_length_and_dec() { maybe_null= 0; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 52af6a31c0c..d4542dac820 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -42,24 +42,22 @@ class Arg_comparator: public Sql_alloc bool is_nulls_eq; // TRUE <=> compare for the EQUAL_FUNC bool set_null; // TRUE <=> set owner->null_value // when one of arguments is NULL. - bool year_as_datetime; // TRUE <=> convert YEAR value to - // the YYYY-00-00 00:00:00 DATETIME - // format. See compare_year. enum enum_date_cmp_type { CMP_DATE_DFLT= 0, CMP_DATE_WITH_DATE, CMP_DATE_WITH_STR, CMP_STR_WITH_DATE }; longlong (*get_value_a_func)(THD *thd, Item ***item_arg, Item **cache_arg, Item *warn_item, bool *is_null); longlong (*get_value_b_func)(THD *thd, Item ***item_arg, Item **cache_arg, Item *warn_item, bool *is_null); + bool try_year_cmp_func(Item_result type); public: DTCollation cmp_collation; /* Allow owner function to use string buffers. */ String value1, value2; Arg_comparator(): thd(0), a_cache(0), b_cache(0), set_null(0), - year_as_datetime(0), get_value_a_func(0), get_value_b_func(0) {}; + get_value_a_func(0), get_value_b_func(0) {}; Arg_comparator(Item **a1, Item **a2): a(a1), b(a2), thd(0), - a_cache(0), b_cache(0), set_null(0), year_as_datetime(0), + a_cache(0), b_cache(0), set_null(0), get_value_a_func(0), get_value_b_func(0) {}; int set_compare_func(Item_result_field *owner, Item_result type); @@ -101,7 +99,6 @@ public: int compare_real_fixed(); int compare_e_real_fixed(); int compare_datetime(); // compare args[0] & args[1] as DATETIMEs - int compare_year(); static enum enum_date_cmp_type can_compare_as_dates(Item *a, Item *b, ulonglong *const_val_arg); From 7b7a5c6e7abb98e86f579332b35e35f78fd6f440 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Tue, 15 Dec 2009 10:54:53 +0200 Subject: [PATCH 064/104] Bug#49489: Uninitialized cache led to a wrong result. Merge the fix from 5.1-bugteam to 5.1-main --- mysql-test/r/select.result | 10 ++++++++++ mysql-test/t/select.test | 9 +++++++++ sql/item_cmpfunc.cc | 2 +- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index d0b2a575a32..1750051289a 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -4609,4 +4609,14 @@ HAVING v <= 't' ORDER BY pk; v DROP TABLE t1; +# +# Bug#49489 Uninitialized cache led to a wrong result. +# +CREATE TABLE t1(c1 DOUBLE(5,4)); +INSERT INTO t1 VALUES (9.1234); +SELECT * FROM t1 WHERE c1 < 9.12345; +c1 +9.1234 +DROP TABLE t1; +# End of test for bug#49489. End of 5.1 tests diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index ac65e5cbaf5..982aec726f7 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -3964,4 +3964,13 @@ ORDER BY pk; DROP TABLE t1; +--echo # +--echo # Bug#49489 Uninitialized cache led to a wrong result. +--echo # +CREATE TABLE t1(c1 DOUBLE(5,4)); +INSERT INTO t1 VALUES (9.1234); +SELECT * FROM t1 WHERE c1 < 9.12345; +DROP TABLE t1; +--echo # End of test for bug#49489. + --echo End of 5.1 tests diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index d99748b87a0..419b79377d7 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1031,7 +1031,7 @@ Item** Arg_comparator::cache_converted_constant(THD *thd, Item **value, (*value)->const_item() && type != (*value)->result_type()) { Item_cache *cache= Item_cache::get_cache(*value, type); - cache->store(*value); + cache->setup(*value); *cache_item= cache; return cache_item; } From b4def7bea14b2102166365c44e359a26ae92d39b Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Tue, 15 Dec 2009 11:03:24 +0200 Subject: [PATCH 065/104] Bug #48985: show create table crashes if previous access to the table was killed Merge the fix from 5.1-bugteam to 5.1-main --- mysql-test/r/show_check.result | 6 ++++++ mysql-test/t/show_check.test | 22 ++++++++++++++++++++++ sql/sql_show.cc | 2 +- 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index e6550bee954..ec0a70ff581 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -1454,4 +1454,10 @@ GRANT PROCESS ON *.* TO test_u@localhost; SHOW ENGINE MYISAM MUTEX; SHOW ENGINE MYISAM STATUS; DROP USER test_u@localhost; +# +# Bug #48985: show create table crashes if previous access to the table +# was killed +# +SHOW CREATE TABLE non_existent; +ERROR 70100: Query execution was interrupted End of 5.1 tests diff --git a/mysql-test/t/show_check.test b/mysql-test/t/show_check.test index 0ce807ae73e..d46261f38d2 100644 --- a/mysql-test/t/show_check.test +++ b/mysql-test/t/show_check.test @@ -1207,6 +1207,28 @@ connection default; DROP USER test_u@localhost; +--echo # +--echo # Bug #48985: show create table crashes if previous access to the table +--echo # was killed +--echo # + +connect(con1,localhost,root,,); +CONNECTION con1; +LET $ID= `SELECT connection_id()`; + +CONNECTION default; +--disable_query_log +eval KILL QUERY $ID; +--enable_query_log + +CONNECTION con1; +--error ER_QUERY_INTERRUPTED +SHOW CREATE TABLE non_existent; + +CONNECTION default; +DISCONNECT con1; + + --echo End of 5.1 tests # Wait till all disconnects are completed diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 2c1f360104b..e55000c0f65 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -719,7 +719,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) thd->push_internal_handler(&view_error_suppressor); bool error= open_normal_and_derived_tables(thd, table_list, 0); thd->pop_internal_handler(); - if (error && thd->main_da.is_error()) + if (error && (thd->killed || thd->main_da.is_error())) DBUG_RETURN(TRUE); } From ca049fbed8123502ba98b24e1a0234ff204c1f9f Mon Sep 17 00:00:00 2001 From: Jon Olav Hauglid Date: Tue, 15 Dec 2009 10:05:20 +0100 Subject: [PATCH 066/104] Bug #48995 abort missing DBUG_RETURN or .. in function "check_key_in_view" check_key_in_view() had one code branch which returned with "return TRUE" rather than "DBUG_RETURN(TRUE)". Only affected debug builds. No test case added. --- sql/sql_view.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_view.cc b/sql/sql_view.cc index ae3af0640a3..eca3922f17a 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1771,7 +1771,7 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view) if (!fld->item->fixed && fld->item->fix_fields(thd, &fld->item)) { thd->mark_used_columns= save_mark_used_columns; - return TRUE; + DBUG_RETURN(TRUE); } } thd->mark_used_columns= save_mark_used_columns; From 9c47ea838078a33ef7fad6d13697c9190c8035b6 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Tue, 15 Dec 2009 13:48:29 +0400 Subject: [PATCH 067/104] Bug#49134 5.1 server segfaults with 2byte collation file Problem: add_collation did not check that cs->number is smaller than the number of elements in the array all_charsets[], so server could crash when loading an Index.xml file with a collation ID greater the number of elements (for example when downgrading from 5.5). Fix: adding a condition to check that cs->number is not out of valid range. --- mysql-test/std_data/Index.xml | 7 +++++++ mysys/charset.c | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/mysql-test/std_data/Index.xml b/mysql-test/std_data/Index.xml index 3dc647d8195..b8f61d59203 100644 --- a/mysql-test/std_data/Index.xml +++ b/mysql-test/std_data/Index.xml @@ -8,6 +8,13 @@ + + + a + b + + + diff --git a/mysys/charset.c b/mysys/charset.c index d59be4ab6c7..b1b91d716ba 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -220,7 +220,8 @@ copy_uca_collation(CHARSET_INFO *to, CHARSET_INFO *from) static int add_collation(CHARSET_INFO *cs) { if (cs->name && (cs->number || - (cs->number=get_collation_number_internal(cs->name)))) + (cs->number=get_collation_number_internal(cs->name))) && + cs->number < array_elements(all_charsets)) { if (!all_charsets[cs->number]) { From 82e6ae0ff171fcf6062d3a43b1bcb4522a176ea3 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Tue, 15 Dec 2009 14:20:29 +0200 Subject: [PATCH 068/104] Bug #48709: Assertion failed in sql_select.cc:11782: int join_read_key(JOIN_TAB*) The eq_ref access method TABLE_REF (accessed through JOIN_TAB) to save state and to track if this is the first row it finds or not. This state was not reset on subquery re-execution causing an assert. Fixed by resetting the state before the subquery re-execution. --- mysql-test/r/subselect.result | 25 +++++++++++++++++++++++++ mysql-test/t/subselect.test | 26 ++++++++++++++++++++++++++ sql/sql_select.cc | 5 +++++ 3 files changed, 56 insertions(+) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 665473df3ef..f446d8feec3 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -4410,6 +4410,31 @@ WHERE a = 230; MAX(b) (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b) NULL 0 DROP TABLE t1, st1, st2; +# +# Bug #48709: Assertion failed in sql_select.cc:11782: +# int join_read_key(JOIN_TAB*) +# +CREATE TABLE t1 (pk int PRIMARY KEY, int_key int); +INSERT INTO t1 VALUES (10,1), (14,1); +CREATE TABLE t2 (pk int PRIMARY KEY, int_key int); +INSERT INTO t2 VALUES (3,3), (5,NULL), (7,3); +# should have eq_ref for t1 +EXPLAIN +SELECT * FROM t2 outr +WHERE outr.int_key NOT IN (SELECT t1.pk FROM t1, t2) +ORDER BY outr.pk; +id select_type table type possible_keys key key_len ref rows Extra +x x outr ALL x x x x x x +x x t1 eq_ref x x x x x x +x x t2 index x x x x x x +# should not crash on debug binaries +SELECT * FROM t2 outr +WHERE outr.int_key NOT IN (SELECT t1.pk FROM t1, t2) +ORDER BY outr.pk; +pk int_key +3 3 +7 3 +DROP TABLE t1,t2; End of 5.0 tests. CREATE TABLE t1 (a INT, b INT); INSERT INTO t1 VALUES (2,22),(1,11),(2,22); diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 7f2dba00ba8..a4314c45cba 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -3368,6 +3368,32 @@ WHERE a = 230; DROP TABLE t1, st1, st2; +--echo # +--echo # Bug #48709: Assertion failed in sql_select.cc:11782: +--echo # int join_read_key(JOIN_TAB*) +--echo # + +CREATE TABLE t1 (pk int PRIMARY KEY, int_key int); +INSERT INTO t1 VALUES (10,1), (14,1); + +CREATE TABLE t2 (pk int PRIMARY KEY, int_key int); +INSERT INTO t2 VALUES (3,3), (5,NULL), (7,3); + +--echo # should have eq_ref for t1 +--replace_column 1 x 2 x 5 x 6 x 7 x 8 x 9 x 10 x +EXPLAIN +SELECT * FROM t2 outr +WHERE outr.int_key NOT IN (SELECT t1.pk FROM t1, t2) +ORDER BY outr.pk; + +--echo # should not crash on debug binaries +SELECT * FROM t2 outr +WHERE outr.int_key NOT IN (SELECT t1.pk FROM t1, t2) +ORDER BY outr.pk; + +DROP TABLE t1,t2; + + --echo End of 5.0 tests. # diff --git a/sql/sql_select.cc b/sql/sql_select.cc index e6980bb2add..cbee09f1fdb 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1622,6 +1622,11 @@ JOIN::reinit() if (join_tab_save) memcpy(join_tab, join_tab_save, sizeof(JOIN_TAB) * tables); + /* need to reset ref access state (see join_read_key) */ + if (join_tab) + for (uint i= 0; i < tables; i++) + join_tab[i].ref.key_err= TRUE; + if (tmp_join) restore_tmp(); From f06d24c18ecc8ff692fcfa7fedf13eb9222d6da6 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Tue, 15 Dec 2009 15:40:08 +0100 Subject: [PATCH 069/104] Fixed atomic instruction headers for Windows and x86-gcc --- include/atomic/generic-msvc.h | 32 ++++++++++++++++++++++++++++---- include/atomic/x86-gcc.h | 6 ++++++ 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/include/atomic/generic-msvc.h b/include/atomic/generic-msvc.h index f1e1b0e88c9..e317e7dc4cc 100644 --- a/include/atomic/generic-msvc.h +++ b/include/atomic/generic-msvc.h @@ -37,18 +37,29 @@ C_MODE_START /*Visual Studio 2003 and earlier do not have prototypes for atomic intrinsics*/ LONG _InterlockedExchange (LONG volatile *Target,LONG Value); -LONG _InterlockedCompareExchange (LONG volatile *Target, LONG Value, LONG Comp); +LONGLONG _InterlockedExchange64 (LONGLONG volatile *Target,LONGLONG Value); +LONG _InterlockedCompareExchange (LONG volatile *Target, + LONG Value, LONG Comp); +LONGLONG _InterlockedCompareExchange64 (LONGLONG volatile *Target, + LONGLONG Value, LONGLONG Comp); LONG _InterlockedExchangeAdd (LONG volatile *Addend, LONG Value); +LONGLONG _InterlockedExchangeAdd64 (LONGLONG volatile *Addend, LONGLONG Value); C_MODE_END #pragma intrinsic(_InterlockedExchangeAdd) #pragma intrinsic(_InterlockedCompareExchange) #pragma intrinsic(_InterlockedExchange) +#pragma intrinsic(_InterlockedExchangeAdd64) +#pragma intrinsic(_InterlockedCompareExchange64) +#pragma intrinsic(_InterlockedExchange64) #endif #define InterlockedExchange _InterlockedExchange #define InterlockedExchangeAdd _InterlockedExchangeAdd #define InterlockedCompareExchange _InterlockedCompareExchange +#define InterlockedExchange64 _InterlockedExchange64 +#define InterlockedExchangeAdd64 _InterlockedExchangeAdd64 +#define InterlockedCompareExchange64 _InterlockedCompareExchange64 /* No need to do something special for InterlockedCompareExchangePointer as it is a #define to InterlockedCompareExchange. The same applies to @@ -57,10 +68,20 @@ C_MODE_END #endif /*_M_IX86*/ #define MY_ATOMIC_MODE "msvc-intrinsics" -#define IL_EXCHG_ADD32(X,Y) InterlockedExchangeAdd((volatile LONG *)(X),(Y)) -#define IL_COMP_EXCHG32(X,Y,Z) InterlockedCompareExchange((volatile LONG *)(X),(Y),(Z)) +#define IL_EXCHG_ADD32(X,Y) \ + InterlockedExchangeAdd((volatile LONG *)(X),(Y)) +#define IL_EXCHG_ADD64(X,Y) \ + InterlockedExchangeAdd64((volatile LONGLONG *)(X),(LONGLONG)(Y)) +#define IL_COMP_EXCHG32(X,Y,Z) \ + InterlockedCompareExchange((volatile LONG *)(X),(Y),(Z)) +#define IL_COMP_EXCHG64(X,Y,Z) \ + InterlockedCompareExchange64((volatile LONGLONG *)(X), \ + (LONGLONG)(Y),(LONGLONG)(Z)) #define IL_COMP_EXCHGptr InterlockedCompareExchangePointer -#define IL_EXCHG32(X,Y) InterlockedExchange((volatile LONG *)(X),(Y)) +#define IL_EXCHG32(X,Y) \ + InterlockedExchange((volatile LONG *)(X),(Y)) +#define IL_EXCHG64(X,Y) \ + InterlockedExchange64((volatile LONGLONG *)(X),(LONGLONG)(Y)) #define IL_EXCHGptr InterlockedExchangePointer #define make_atomic_add_body(S) \ v= IL_EXCHG_ADD ## S (a, v) @@ -108,9 +129,12 @@ static __inline int my_yield_processor() #else /* cleanup */ #undef IL_EXCHG_ADD32 +#undef IL_EXCHG_ADD64 #undef IL_COMP_EXCHG32 +#undef IL_COMP_EXCHG64 #undef IL_COMP_EXCHGptr #undef IL_EXCHG32 +#undef IL_EXCHG64 #undef IL_EXCHGptr #endif diff --git a/include/atomic/x86-gcc.h b/include/atomic/x86-gcc.h index e5e88fa58ff..f19a4a33f3c 100644 --- a/include/atomic/x86-gcc.h +++ b/include/atomic/x86-gcc.h @@ -22,6 +22,12 @@ architectures support double-word (128-bit) cas. */ +/* + No special support of 8 and 16 bit operations are implemented here + currently. +*/ +#undef MY_ATOMIC_HAS_8_AND_16 + #ifdef __x86_64__ # ifdef MY_ATOMIC_NO_XADD # define MY_ATOMIC_MODE "gcc-amd64" LOCK_prefix "-no-xadd" From fe1287ea68dcb8a0ffd01c795a0569bc2d9d134a Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Tue, 15 Dec 2009 17:07:43 +0100 Subject: [PATCH 070/104] Fixed 64-bit atomics on Win x86 and removed support for 8 and 16-bit atomic operations --- include/atomic/generic-msvc.h | 13 +------------ include/my_atomic.h | 7 +++---- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/include/atomic/generic-msvc.h b/include/atomic/generic-msvc.h index e317e7dc4cc..77319aaa93c 100644 --- a/include/atomic/generic-msvc.h +++ b/include/atomic/generic-msvc.h @@ -37,29 +37,18 @@ C_MODE_START /*Visual Studio 2003 and earlier do not have prototypes for atomic intrinsics*/ LONG _InterlockedExchange (LONG volatile *Target,LONG Value); -LONGLONG _InterlockedExchange64 (LONGLONG volatile *Target,LONGLONG Value); -LONG _InterlockedCompareExchange (LONG volatile *Target, - LONG Value, LONG Comp); -LONGLONG _InterlockedCompareExchange64 (LONGLONG volatile *Target, - LONGLONG Value, LONGLONG Comp); +LONG _InterlockedCompareExchange (LONG volatile *Target, LONG Value, LONG Comp); LONG _InterlockedExchangeAdd (LONG volatile *Addend, LONG Value); -LONGLONG _InterlockedExchangeAdd64 (LONGLONG volatile *Addend, LONGLONG Value); C_MODE_END #pragma intrinsic(_InterlockedExchangeAdd) #pragma intrinsic(_InterlockedCompareExchange) #pragma intrinsic(_InterlockedExchange) -#pragma intrinsic(_InterlockedExchangeAdd64) -#pragma intrinsic(_InterlockedCompareExchange64) -#pragma intrinsic(_InterlockedExchange64) #endif #define InterlockedExchange _InterlockedExchange #define InterlockedExchangeAdd _InterlockedExchangeAdd #define InterlockedCompareExchange _InterlockedCompareExchange -#define InterlockedExchange64 _InterlockedExchange64 -#define InterlockedExchangeAdd64 _InterlockedExchangeAdd64 -#define InterlockedCompareExchange64 _InterlockedCompareExchange64 /* No need to do something special for InterlockedCompareExchangePointer as it is a #define to InterlockedCompareExchange. The same applies to diff --git a/include/my_atomic.h b/include/my_atomic.h index 4170e45fe8c..23c3dc749ab 100644 --- a/include/my_atomic.h +++ b/include/my_atomic.h @@ -56,11 +56,10 @@ #define intptr void * /** - On most platforms we implement 8-bit, 16-bit, 32-bit and "pointer" - operations. Thus the symbol below is defined by default; platforms - where we leave out 8-bit or 16-bit operations should undefine it. + Currently we don't support 8-bit and 16-bit operations. + It can be added later if needed. */ -#define MY_ATOMIC_HAS_8_16 1 +#undef MY_ATOMIC_HAS_8_16 #ifndef MY_ATOMIC_MODE_RWLOCKS /* From 4422b0f665fa3cba9f86b1c5e8e242f7839f6335 Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Tue, 15 Dec 2009 21:08:21 +0400 Subject: [PATCH 071/104] Fix for bug#49517: Inconsistent behavior while using NULLable BIGINT and INT columns in comparison Problem: a consequence of the fix for 43668. Some Arg_comparator inner initialization missed, that may lead to unpredictable (wrong) comparison results. Fix: always properly initialize Arg_comparator before its usage. --- mysql-test/r/select.result | 15 +++++++++++++++ mysql-test/t/select.test | 14 ++++++++++++++ sql/item_cmpfunc.cc | 2 +- sql/item_cmpfunc.h | 4 ++-- 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 1750051289a..f38af4ceb32 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -4619,4 +4619,19 @@ c1 9.1234 DROP TABLE t1; # End of test for bug#49489. +# +# Bug #49517: Inconsistent behavior while using +# NULLable BIGINT and INT columns in comparison +# +CREATE TABLE t1(a BIGINT UNSIGNED NOT NULL, b BIGINT NULL, c INT NULL); +INSERT INTO t1 VALUES(105, NULL, NULL); +SELECT * FROM t1 WHERE b < 102; +a b c +SELECT * FROM t1 WHERE c < 102; +a b c +SELECT * FROM t1 WHERE 102 < b; +a b c +SELECT * FROM t1 WHERE 102 < c; +a b c +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 982aec726f7..e81c298166d 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -3973,4 +3973,18 @@ SELECT * FROM t1 WHERE c1 < 9.12345; DROP TABLE t1; --echo # End of test for bug#49489. + +--echo # +--echo # Bug #49517: Inconsistent behavior while using +--echo # NULLable BIGINT and INT columns in comparison +--echo # +CREATE TABLE t1(a BIGINT UNSIGNED NOT NULL, b BIGINT NULL, c INT NULL); +INSERT INTO t1 VALUES(105, NULL, NULL); +SELECT * FROM t1 WHERE b < 102; +SELECT * FROM t1 WHERE c < 102; +SELECT * FROM t1 WHERE 102 < b; +SELECT * FROM t1 WHERE 102 < c; +DROP TABLE t1; + + --echo End of 5.1 tests diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 419b79377d7..e4f26978431 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -895,9 +895,9 @@ int Arg_comparator::set_cmp_func(Item_result_field *owner_arg, ulonglong const_value= (ulonglong)-1; thd= current_thd; owner= owner_arg; + set_null= set_null && owner_arg; a= a1; b= a2; - owner= owner_arg; thd= current_thd; if ((cmp_type= can_compare_as_dates(*a, *b, &const_value))) diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index d4542dac820..05c9fc96ff5 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -54,10 +54,10 @@ public: /* Allow owner function to use string buffers. */ String value1, value2; - Arg_comparator(): thd(0), a_cache(0), b_cache(0), set_null(0), + Arg_comparator(): thd(0), a_cache(0), b_cache(0), set_null(TRUE), get_value_a_func(0), get_value_b_func(0) {}; Arg_comparator(Item **a1, Item **a2): a(a1), b(a2), thd(0), - a_cache(0), b_cache(0), set_null(0), + a_cache(0), b_cache(0), set_null(TRUE), get_value_a_func(0), get_value_b_func(0) {}; int set_compare_func(Item_result_field *owner, Item_result type); From 8d329aa720a2c93708ba09b7433b5aeb994fb52a Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Tue, 15 Dec 2009 19:10:06 +0200 Subject: [PATCH 072/104] Bug #48709: Assertion failed in sql_select.cc:11782: int join_read_key(JOIN_TAB*) The eq_ref access method TABLE_REF (accessed through JOIN_TAB) to save state and to track if this is the first row it finds or not. This state was not reset on subquery re-execution causing an assert. Fixed by resetting the state before the subquery re-execution. --- mysql-test/r/subselect.result | 25 +++++++++++++++++++++++++ mysql-test/t/subselect.test | 26 ++++++++++++++++++++++++++ sql/sql_select.cc | 5 +++++ 3 files changed, 56 insertions(+) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 8c239d5c349..09a650c722b 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -4502,4 +4502,29 @@ WHERE a = 230; MAX(b) (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b) NULL 0 DROP TABLE t1, st1, st2; +# +# Bug #48709: Assertion failed in sql_select.cc:11782: +# int join_read_key(JOIN_TAB*) +# +CREATE TABLE t1 (pk int PRIMARY KEY, int_key int); +INSERT INTO t1 VALUES (10,1), (14,1); +CREATE TABLE t2 (pk int PRIMARY KEY, int_key int); +INSERT INTO t2 VALUES (3,3), (5,NULL), (7,3); +# should have eq_ref for t1 +EXPLAIN +SELECT * FROM t2 outr +WHERE outr.int_key NOT IN (SELECT t1.pk FROM t1, t2) +ORDER BY outr.pk; +id select_type table type possible_keys key key_len ref rows Extra +x x outr ALL x x x x x x +x x t1 eq_ref x x x x x x +x x t2 index x x x x x x +# should not crash on debug binaries +SELECT * FROM t2 outr +WHERE outr.int_key NOT IN (SELECT t1.pk FROM t1, t2) +ORDER BY outr.pk; +pk int_key +3 3 +7 3 +DROP TABLE t1,t2; End of 5.0 tests. diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 2b5d36da796..bd12742f0f1 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -3481,4 +3481,30 @@ WHERE a = 230; DROP TABLE t1, st1, st2; +--echo # +--echo # Bug #48709: Assertion failed in sql_select.cc:11782: +--echo # int join_read_key(JOIN_TAB*) +--echo # + +CREATE TABLE t1 (pk int PRIMARY KEY, int_key int); +INSERT INTO t1 VALUES (10,1), (14,1); + +CREATE TABLE t2 (pk int PRIMARY KEY, int_key int); +INSERT INTO t2 VALUES (3,3), (5,NULL), (7,3); + +--echo # should have eq_ref for t1 +--replace_column 1 x 2 x 5 x 6 x 7 x 8 x 9 x 10 x +EXPLAIN +SELECT * FROM t2 outr +WHERE outr.int_key NOT IN (SELECT t1.pk FROM t1, t2) +ORDER BY outr.pk; + +--echo # should not crash on debug binaries +SELECT * FROM t2 outr +WHERE outr.int_key NOT IN (SELECT t1.pk FROM t1, t2) +ORDER BY outr.pk; + +DROP TABLE t1,t2; + + --echo End of 5.0 tests. diff --git a/sql/sql_select.cc b/sql/sql_select.cc index f655db0fc32..d22a23a10d4 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1553,6 +1553,11 @@ JOIN::reinit() if (join_tab_save) memcpy(join_tab, join_tab_save, sizeof(JOIN_TAB) * tables); + /* need to reset ref access state (see join_read_key) */ + if (join_tab) + for (uint i= 0; i < tables; i++) + join_tab[i].ref.key_err= TRUE; + if (tmp_join) restore_tmp(); From f5a547a971ca4918d9d4c46a526a28352bea7662 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Tue, 15 Dec 2009 18:12:49 +0100 Subject: [PATCH 073/104] Include windows.h in atomics framework for windows --- include/atomic/generic-msvc.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/atomic/generic-msvc.h b/include/atomic/generic-msvc.h index 77319aaa93c..4a50dc4a667 100644 --- a/include/atomic/generic-msvc.h +++ b/include/atomic/generic-msvc.h @@ -23,6 +23,7 @@ */ #undef MY_ATOMIC_HAS_8_16 +#include /* x86 compilers (both VS2003 or VS2005) never use instrinsics, but generate function calls to kernel32 instead, even in the optimized build. From 25f365f610ad00bcf9bccae98a62158332093f1c Mon Sep 17 00:00:00 2001 From: Alexander Nozdrin Date: Tue, 15 Dec 2009 23:20:53 +0300 Subject: [PATCH 074/104] Backporting patch for Bug#47756 from mysql-next-mr-bugfixing into mysql-trunk-bugfixing. NOTE: the "utf8_phone_ci" collation does not exist in mysql-trunk yet, so another collation with 2-byte collation ID is used: "utf8_test_ci". This patch will be null-merged to mysql-next-mr-bugfixing. Original revision: ------------------------------------------------------------ revision-id: bar@mysql.com-20091207121153-hs3bqbmr0719ws21 committer: Alexander Barkov branch nick: mysql-next-mr.b47756 timestamp: Mon 2009-12-07 16:11:53 +0400 message: Bug#47756 Setting 2byte collation ID with 'set names' crashes the server The problem is not actually related to 2byte collation IDs. The same crash happens if you change the collation ID in mysql-test/str_data/Index.xml to a value smaller than 256. Crash happened in SQL parser, because the "ident_map" and "state_map" arrays were not initialized in loadable utf8 collations. Fix: adding proper initialization of the "ident_map" and "state_map" members for loadable utf8 collations. ------------------------------------------------------------ --- mysql-test/r/ctype_ldml.result | 5 +++++ mysql-test/t/ctype_ldml.test | 8 ++++++++ mysys/charset.c | 3 +++ 3 files changed, 16 insertions(+) diff --git a/mysql-test/r/ctype_ldml.result b/mysql-test/r/ctype_ldml.result index 00da0db1735..a63dc91f305 100644 --- a/mysql-test/r/ctype_ldml.result +++ b/mysql-test/r/ctype_ldml.result @@ -369,3 +369,8 @@ s1 a b DROP TABLE t1; +SET NAMES utf8 COLLATE utf8_test_ci; +SHOW COLLATION LIKE 'utf8_test_ci'; +Collation Charset Id Default Compiled Sortlen +utf8_test_ci utf8 353 8 +SET NAMES utf8; diff --git a/mysql-test/t/ctype_ldml.test b/mysql-test/t/ctype_ldml.test index 0fcfd603aad..d134861cd46 100644 --- a/mysql-test/t/ctype_ldml.test +++ b/mysql-test/t/ctype_ldml.test @@ -125,3 +125,11 @@ CREATE TABLE t1 (s1 char(10) character set utf8 collate utf8_maxuserid_ci); INSERT INTO t1 VALUES ('a'),('b'); SELECT * FROM t1 WHERE s1='a' ORDER BY BINARY s1; DROP TABLE t1; + + +# +# Bug#47756 Setting 2byte collation ID with 'set names' crashes the server +# +SET NAMES utf8 COLLATE utf8_test_ci; +SHOW COLLATION LIKE 'utf8_test_ci'; +SET NAMES utf8; diff --git a/mysys/charset.c b/mysys/charset.c index 280b2ad6091..e216f665092 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -255,6 +255,9 @@ static int add_collation(CHARSET_INFO *cs) { #if defined (HAVE_CHARSET_utf8) && defined(HAVE_UCA_COLLATIONS) copy_uca_collation(newcs, &my_charset_utf8_unicode_ci); + newcs->ctype= my_charset_utf8_unicode_ci.ctype; + if (init_state_maps(newcs)) + return MY_XML_ERROR; #endif } else From 7688c7369c8d164f6985860aeb14e5fe6645b592 Mon Sep 17 00:00:00 2001 From: Alexander Nozdrin Date: Tue, 15 Dec 2009 23:23:01 +0300 Subject: [PATCH 075/104] Backporting a patch for Bug#49170 (Inconsistent placement of semisync plugin prevents it from getting tested) from mysql-next-mr-bugfixing to mysql-trunk-bugfixing. Original revision: ------------------------------------------------------------ revision-id: zhenxing.he@sun.com-20091204014339-2m06r42vajhm9vke committer: He Zhenxing branch nick: 5.1-rep-semisync timestamp: Fri 2009-12-04 09:43:39 +0800 message: Bug#49170 Inconsistent placement of semisync plugin prevents it from getting tested Add $basedir/lib/plugin to the search paths for semisync plugins. ------------------------------------------------------------ --- mysql-test/mysql-test-run.pl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index f76cb008c3c..95095586bec 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -1849,11 +1849,13 @@ sub environment_setup { my $lib_semisync_master_plugin= mtr_file_exists(vs_config_dirs('plugin/semisync',$semisync_master_filename), "$basedir/plugin/semisync/.libs/" . $semisync_master_filename, - "$basedir/lib/mysql/plugin/" . $semisync_master_filename); + "$basedir/lib/mysql/plugin/" . $semisync_master_filename, + "$basedir/lib/plugin/" . $semisync_master_filename); my $lib_semisync_slave_plugin= mtr_file_exists(vs_config_dirs('plugin/semisync',$semisync_slave_filename), "$basedir/plugin/semisync/.libs/" . $semisync_slave_filename, - "$basedir/lib/mysql/plugin/" . $semisync_slave_filename); + "$basedir/lib/mysql/plugin/" . $semisync_slave_filename, + "$basedir/lib/plugin/" . $semisync_slave_filename); if ($lib_semisync_master_plugin && $lib_semisync_slave_plugin) { $ENV{'SEMISYNC_MASTER_PLUGIN'}= basename($lib_semisync_master_plugin); From 432c5487e944d65e81cff8097487f6fe0c6e4277 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Tue, 15 Dec 2009 22:15:48 +0100 Subject: [PATCH 076/104] Fixed complex gcc assembler issues with 64-bit operations on 32-bit platforms using PIC codes, commented x86-gcc.h a lot more --- include/atomic/x86-gcc.h | 75 ++++++++++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 23 deletions(-) diff --git a/include/atomic/x86-gcc.h b/include/atomic/x86-gcc.h index f19a4a33f3c..32839e0a67d 100644 --- a/include/atomic/x86-gcc.h +++ b/include/atomic/x86-gcc.h @@ -59,39 +59,68 @@ asm volatile (LOCK_prefix "; cmpxchg %3, %0; setz %2;" \ : "+m" (*a), "+a" (*cmp), "=q" (ret): "r" (set)) -#define make_atomic_cas_bodyptr make_atomic_cas_body32 - -#ifndef __x86_64__ +#ifdef __x86_64__ #define make_atomic_add_body64 make_atomic_add_body32 #define make_atomic_cas_body64 make_atomic_cas_body32 -#else -#define make_atomic_add_body64 \ - int64 tmp=*a; \ - while (!my_atomic_cas64(a, &tmp, tmp+v)); \ - v=tmp; -#define make_atomic_cas_body64 \ - int32 ebx=(set & 0xFFFFFFFF), ecx=(set >> 32); \ - asm volatile (LOCK_prefix "; cmpxchg8b %0; setz %2;" \ - : "+m" (*a), "+A" (*cmp), "=q" (ret) \ - :"b" (ebx), "c" (ecx)) -#endif #define make_atomic_fas_body(S) \ asm volatile ("xchg %0, %1;" : "+r" (v) , "+m" (*a)) -#ifdef MY_ATOMIC_MODE_DUMMY -#define make_atomic_load_body(S) ret=*a -#define make_atomic_store_body(S) *a=v -#else /* Actually 32-bit reads/writes are always atomic on x86 But we add LOCK_prefix here anyway to force memory barriers */ -#define make_atomic_load_body(S) \ - ret=0; \ - asm volatile (LOCK_prefix "; cmpxchg %2, %0" \ - : "+m" (*a), "+a" (ret): "r" (ret)) -#define make_atomic_store_body(S) \ +#define make_atomic_load_body(S) \ + ret=0; \ + asm volatile (LOCK_prefix "; cmpxchg %2, %0" \ + : "+m" (*a), "+a" (ret): "r" (ret)) +#define make_atomic_store_body(S) \ asm volatile ("; xchg %0, %1;" : "+m" (*a), "+r" (v)) + +#else +/* + Use default implementations of 64-bit operations since we solved + the 64-bit problem on 32-bit platforms for CAS, no need to solve it + once more for ADD, LOAD, STORE and FAS as well. + Since we already added add32 support, we need to define add64 + here, but we haven't defined fas, load and store at all, so + we can fallback on default implementations. +*/ +#define make_atomic_add_body64 \ + int64 tmp=*a; \ + while (!my_atomic_cas64(a, &tmp, tmp+v)); \ + v=tmp; + +/* + On some platforms (e.g. Mac OS X and Solaris) the ebx register + is held as a pointer to the global offset table. Thus we're not + allowed to use the b-register on those platforms when compiling + PIC code, to avoid this we push ebx and pop ebx and add a movl + instruction to avoid having ebx in the interface of the assembler + instruction. + + cmpxchg8b works on both 32-bit platforms and 64-bit platforms but + the code here is only used on 32-bit platforms, on 64-bit + platforms the much simpler make_atomic_cas_body32 will work + fine. +*/ +#define make_atomic_cas_body64 \ + int32 ebx=(set & 0xFFFFFFFF), ecx=(set >> 32); \ + asm volatile ("push %%ebx; movl %3, %%ebx;" \ + LOCK_prefix "; cmpxchg8b %0; setz %2; pop %%ebx"\ + : "+m" (*a), "+A" (*cmp), "=q" (ret) \ + :"m" (ebx), "c" (ecx)) +#endif + +/* + The implementation of make_atomic_cas_body32 is adaptable to + the OS word size, so on 64-bit platforms it will automatically + adapt to 64-bits and so it will work also on 64-bit platforms +*/ +#define make_atomic_cas_bodyptr make_atomic_cas_body32 + +#ifdef MY_ATOMIC_MODE_DUMMY +#define make_atomic_load_body(S) ret=*a +#define make_atomic_store_body(S) *a=v #endif #endif /* ATOMIC_X86_GCC_INCLUDED */ From 4bd3686f967daff6dd6b44aab86bdb5cc6048f16 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Wed, 16 Dec 2009 00:33:15 +0100 Subject: [PATCH 077/104] Fix for Windows atomics --- include/atomic/generic-msvc.h | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/include/atomic/generic-msvc.h b/include/atomic/generic-msvc.h index 4a50dc4a667..a84cde6b2c3 100644 --- a/include/atomic/generic-msvc.h +++ b/include/atomic/generic-msvc.h @@ -37,19 +37,17 @@ #else C_MODE_START /*Visual Studio 2003 and earlier do not have prototypes for atomic intrinsics*/ -LONG _InterlockedExchange (LONG volatile *Target,LONG Value); LONG _InterlockedCompareExchange (LONG volatile *Target, LONG Value, LONG Comp); -LONG _InterlockedExchangeAdd (LONG volatile *Addend, LONG Value); +LONGLONG _InterlockedCompareExchange64 (LONGLONG volatile *Target, + LONGLONG Value, LONGLONG Comp); C_MODE_END -#pragma intrinsic(_InterlockedExchangeAdd) #pragma intrinsic(_InterlockedCompareExchange) -#pragma intrinsic(_InterlockedExchange) +#pragma intrinsic(_InterlockedCompareExchange64) #endif -#define InterlockedExchange _InterlockedExchange -#define InterlockedExchangeAdd _InterlockedExchangeAdd #define InterlockedCompareExchange _InterlockedCompareExchange +#define InterlockedCompareExchange64 _InterlockedCompareExchange64 /* No need to do something special for InterlockedCompareExchangePointer as it is a #define to InterlockedCompareExchange. The same applies to @@ -58,33 +56,39 @@ C_MODE_END #endif /*_M_IX86*/ #define MY_ATOMIC_MODE "msvc-intrinsics" -#define IL_EXCHG_ADD32(X,Y) \ - InterlockedExchangeAdd((volatile LONG *)(X),(Y)) -#define IL_EXCHG_ADD64(X,Y) \ - InterlockedExchangeAdd64((volatile LONGLONG *)(X),(LONGLONG)(Y)) +/* Implement using CAS on WIN32 */ #define IL_COMP_EXCHG32(X,Y,Z) \ InterlockedCompareExchange((volatile LONG *)(X),(Y),(Z)) #define IL_COMP_EXCHG64(X,Y,Z) \ InterlockedCompareExchange64((volatile LONGLONG *)(X), \ (LONGLONG)(Y),(LONGLONG)(Z)) #define IL_COMP_EXCHGptr InterlockedCompareExchangePointer + +#define make_atomic_cas_body(S) \ + int ## S initial_cmp= *cmp; \ + int ## S initial_a= IL_COMP_EXCHG ## S (a, set, initial_cmp); \ + if (!(ret= (initial_a == initial_cmp))) *cmp= initial_a; + +#ifndef _M_IX86 +/* Use full set of optimised functions on WIN64 */ +#define IL_EXCHG_ADD32(X,Y) \ + InterlockedExchangeAdd((volatile LONG *)(X),(Y)) +#define IL_EXCHG_ADD64(X,Y) \ + InterlockedExchangeAdd64((volatile LONGLONG *)(X),(LONGLONG)(Y)) #define IL_EXCHG32(X,Y) \ InterlockedExchange((volatile LONG *)(X),(Y)) #define IL_EXCHG64(X,Y) \ InterlockedExchange64((volatile LONGLONG *)(X),(LONGLONG)(Y)) #define IL_EXCHGptr InterlockedExchangePointer + #define make_atomic_add_body(S) \ v= IL_EXCHG_ADD ## S (a, v) -#define make_atomic_cas_body(S) \ - int ## S initial_cmp= *cmp; \ - int ## S initial_a= IL_COMP_EXCHG ## S (a, set, initial_cmp); \ - if (!(ret= (initial_a == initial_cmp))) *cmp= initial_a; #define make_atomic_swap_body(S) \ v= IL_EXCHG ## S (a, v) #define make_atomic_load_body(S) \ ret= 0; /* avoid compiler warning */ \ ret= IL_COMP_EXCHG ## S (a, ret, ret); - +#endif /* my_yield_processor (equivalent of x86 PAUSE instruction) should be used to improve performance on hyperthreaded CPUs. Intel recommends to use it in From 152e8717fe806114022dfe2e038c870174e16cae Mon Sep 17 00:00:00 2001 From: Date: Wed, 16 Dec 2009 12:25:46 +0800 Subject: [PATCH 078/104] Postfix Only relative log events are showed. --- mysql-test/suite/rpl/t/rpl_loaddata_concurrent.test | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_concurrent.test b/mysql-test/suite/rpl/t/rpl_loaddata_concurrent.test index 1276b0f3700..494a0db79fa 100644 --- a/mysql-test/suite/rpl/t/rpl_loaddata_concurrent.test +++ b/mysql-test/suite/rpl/t/rpl_loaddata_concurrent.test @@ -1,6 +1,7 @@ -- source include/not_ndb_default.inc -- source include/have_log_bin.inc +let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); CREATE TABLE t1 (c1 char(50)); LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE t1; LOAD DATA CONCURRENT INFILE '../../std_data/words.dat' INTO TABLE t1; From 8b3d63a6a58a50b4d7d9c7f0945e420a08beb0db Mon Sep 17 00:00:00 2001 From: Date: Wed, 16 Dec 2009 12:41:15 +0800 Subject: [PATCH 079/104] Bug #46827 rpl_circular_for_4_hosts failed on PB2 This test case tests a circular replication of four hosts. A--->B--->C--->D--->A The replicate is slow and needs more time to replicate all data in the circle. The time it spends to replicate, sometimes, is longer than the time that wait_condition.inc spends to wait that all data has been replicated. This cause sporadical failure of this test case. This patch uses sync_slave_with_master to ensure that all data can be replicated successfully in the circle. --- .../suite/rpl/t/rpl_circular_for_4_hosts.test | 21 ++----------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/mysql-test/suite/rpl/t/rpl_circular_for_4_hosts.test b/mysql-test/suite/rpl/t/rpl_circular_for_4_hosts.test index a49253f90c1..3633462d68e 100644 --- a/mysql-test/suite/rpl/t/rpl_circular_for_4_hosts.test +++ b/mysql-test/suite/rpl/t/rpl_circular_for_4_hosts.test @@ -233,16 +233,7 @@ COMMIT; --connection master_a --enable_query_log - ---let $wait_condition= SELECT COUNT(*)=400 FROM t2 WHERE c = 1 ---connection master_a ---source include/wait_condition.inc ---connection master_b ---source include/wait_condition.inc ---connection master_c ---source include/wait_condition.inc ---connection master_d ---source include/wait_condition.inc +--source include/circular_rpl_for_4_hosts_sync.inc --connection master_a SELECT 'Master A',b,COUNT(*) FROM t2 WHERE c = 1 GROUP BY b ORDER BY b; @@ -282,15 +273,7 @@ ROLLBACK; --connection master_a --enable_query_log ---let $wait_condition= SELECT COUNT(*)=200 FROM t2 WHERE c = 2 ---connection master_a ---source include/wait_condition.inc ---connection master_b ---source include/wait_condition.inc ---connection master_c ---source include/wait_condition.inc ---connection master_d ---source include/wait_condition.inc +--source include/circular_rpl_for_4_hosts_sync.inc --connection master_a SELECT 'Master A',b,COUNT(*) FROM t2 WHERE c = 2 GROUP BY b ORDER BY b; From 2cb6f123b6499aafac95c691bcb32be7671cf508 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Wed, 16 Dec 2009 08:45:25 +0100 Subject: [PATCH 080/104] post push patch of bug#49369 updating test by removing select of platform dependend variable. --- mysql-test/r/partition_key_cache.result | 3 --- mysql-test/t/partition_key_cache.test | 1 - 2 files changed, 4 deletions(-) diff --git a/mysql-test/r/partition_key_cache.result b/mysql-test/r/partition_key_cache.result index c09f277840b..7fbab34fa41 100644 --- a/mysql-test/r/partition_key_cache.result +++ b/mysql-test/r/partition_key_cache.result @@ -8,9 +8,6 @@ SELECT @org_key_cache_buffer_size:= @@global.default.key_buffer_size; SET @@global.default.key_buffer_size = 1; Warnings: Warning 1292 Truncated incorrect key_buffer_size value: '1' -SELECT @@global.default.key_buffer_size; -@@global.default.key_buffer_size -36 CREATE TABLE t1 ( a INT, b INT, diff --git a/mysql-test/t/partition_key_cache.test b/mysql-test/t/partition_key_cache.test index 34f3d4de19c..f6ea974ba96 100644 --- a/mysql-test/t/partition_key_cache.test +++ b/mysql-test/t/partition_key_cache.test @@ -10,7 +10,6 @@ DROP TABLE IF EXISTS t1, t2, v, x; SELECT @org_key_cache_buffer_size:= @@global.default.key_buffer_size; --echo # Minimize default key cache (almost disabled). SET @@global.default.key_buffer_size = 1; -SELECT @@global.default.key_buffer_size; CREATE TABLE t1 ( a INT, b INT, From d456e4470dcec35b9c3c35073e516894f41a2900 Mon Sep 17 00:00:00 2001 From: Jonathan Perkin Date: Wed, 16 Dec 2009 10:27:56 +0000 Subject: [PATCH 081/104] Fix previous merge: 'kill -0' (check PID exists) was changed to 'kill -9', meaning a '/etc/init.d/mysql stop' would actually cause mysqld_safe to relaunch mysqld rather than shut it down. --- support-files/mysql.server.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh index ccf4d8ff51d..b5115a5c05e 100644 --- a/support-files/mysql.server.sh +++ b/support-files/mysql.server.sh @@ -303,7 +303,7 @@ case "$mode" in then mysqld_pid=`cat "$mysqld_pid_file_path"` - if (kill -9 $mysqld_pid 2>/dev/null) + if (kill -0 $mysqld_pid 2>/dev/null) then echo $echo_n "Shutting down MySQL" kill $mysqld_pid From 4ff970b08a60f2411fd9d5a48b578375c3007f54 Mon Sep 17 00:00:00 2001 From: Alfranio Correia Date: Wed, 16 Dec 2009 19:52:56 +0000 Subject: [PATCH 082/104] BUG#49638 binlog_index fails in mysql-trunk-merge Calling push_warning/push_warning_printf with a level of WARN_LEVEL_ERROR *is* a bug. We should either use my_error(), or WARN_LEVEL_WARN. --- mysql-test/suite/binlog/r/binlog_index.result | 2 +- sql/log.cc | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/mysql-test/suite/binlog/r/binlog_index.result b/mysql-test/suite/binlog/r/binlog_index.result index 06d8baf23bf..52d698e9f96 100644 --- a/mysql-test/suite/binlog/r/binlog_index.result +++ b/mysql-test/suite/binlog/r/binlog_index.result @@ -38,7 +38,7 @@ purge binary logs TO 'master-bin.000002'; ERROR HY000: Fatal error during log purge show warnings; Level Code Message -Error 1377 a problem with deleting master-bin.000001; consider examining correspondence of your binlog index file to the actual binlog files +Warning 1377 a problem with deleting master-bin.000001; consider examining correspondence of your binlog index file to the actual binlog files Error 1377 Fatal error during log purge reset master; # crash_purge_before_update_index diff --git a/sql/log.cc b/sql/log.cc index 1adf92e709c..2fd29588922 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -3014,7 +3014,7 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd) } else { - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_BINLOG_PURGE_FATAL_ERR, "a problem with deleting %s; " "consider examining correspondence " @@ -3045,7 +3045,7 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd) } else { - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_BINLOG_PURGE_FATAL_ERR, "a problem with deleting %s; " "consider examining correspondence " @@ -3481,7 +3481,7 @@ int MYSQL_BIN_LOG::purge_index_entry(THD *thd, ulonglong *decrease_log_space, */ if (thd) { - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_BINLOG_PURGE_FATAL_ERR, "a problem with getting info on being purged %s; " "consider examining correspondence " @@ -3509,7 +3509,7 @@ int MYSQL_BIN_LOG::purge_index_entry(THD *thd, ulonglong *decrease_log_space, { if (thd) { - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_BINLOG_PURGE_FATAL_ERR, "a problem with deleting %s and " "reading the binlog index file", @@ -3557,7 +3557,7 @@ int MYSQL_BIN_LOG::purge_index_entry(THD *thd, ulonglong *decrease_log_space, { if (thd) { - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_BINLOG_PURGE_FATAL_ERR, "a problem with deleting %s; " "consider examining correspondence " @@ -3647,7 +3647,7 @@ int MYSQL_BIN_LOG::purge_logs_before_date(time_t purge_time) */ if (thd) { - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_BINLOG_PURGE_FATAL_ERR, "a problem with getting info on being purged %s; " "consider examining correspondence " From 2fed66077443fe8a856adcc63ff53c8666a52317 Mon Sep 17 00:00:00 2001 From: Magne Mahre Date: Wed, 16 Dec 2009 20:53:56 +0100 Subject: [PATCH 083/104] Bug#47017 rpl_timezone fails on PB-2 with mismatch error The bug is caused by a race condition between the INSERT DELAYED thread and the client thread's FLUSH TABLE. The FLUSH TABLE does not guarantee (as is (wrongly) suggested in the test case) that the INSERT DELAYED is ever executed. The execution of the test case will thus not be deterministic. The fix has been to do a deterministic verification that both threads are complete by checking the content of the table. --- mysql-test/suite/rpl/t/rpl_timezone.test | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/rpl/t/rpl_timezone.test b/mysql-test/suite/rpl/t/rpl_timezone.test index 40a2a4444b9..45d1f12b5d5 100644 --- a/mysql-test/suite/rpl/t/rpl_timezone.test +++ b/mysql-test/suite/rpl/t/rpl_timezone.test @@ -179,8 +179,11 @@ insert into t1 values('2008-12-23 19:39:39',1); --connection master1 SET @@session.time_zone='+02:00'; insert delayed into t1 values ('2008-12-23 19:39:39',2); -# Forces table t1 to be closed and flushes the query cache. -# This makes sure that 'delayed insert' is executed before next statement. + +# wait for the delayed insert to be executed +let $wait_condition= SELECT date FROM t1 WHERE a=2; +--source include/wait_condition.inc + flush table t1; flush logs; select * from t1; From 092f25caeb80f7473d2e76afd996bea38e7700fd Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Thu, 17 Dec 2009 09:55:03 +0400 Subject: [PATCH 084/104] Fix for bug#49465: valgrind warnings and incorrect live checksum... Problem: inserting a record we don't set unused null bits in the record buffer if no default field values used. That may lead to wrong live checksum calculation. Fix: set unused null bits in the record buffer in such cases. --- mysql-test/r/myisam.result | 15 +++++++++++++++ mysql-test/t/myisam.test | 14 ++++++++++++++ sql/sql_insert.cc | 11 ++++++++++- 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index 53bb022147e..9c8e5c2863d 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -1883,4 +1883,19 @@ CHECK TABLE t1; Table Op Msg_type Msg_text test.t1 check status OK DROP TABLE t1; +# +# Bug #49465: valgrind warnings and incorrect live checksum... +# +CREATE TABLE t1( +a VARCHAR(1), b VARCHAR(1), c VARCHAR(1), +f VARCHAR(1), g VARCHAR(1), h VARCHAR(1), +i VARCHAR(1), j VARCHAR(1), k VARCHAR(1)) CHECKSUM=1; +INSERT INTO t1 VALUES('', '', '', '', '', '', '', '', ''); +CHECKSUM TABLE t1 QUICK; +Table Checksum +test.t1 467455460 +CHECKSUM TABLE t1 EXTENDED; +Table Checksum +test.t1 467455460 +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index 254b0378aa8..d0a480348a3 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -1225,4 +1225,18 @@ SELECT a FROM t1; CHECK TABLE t1; DROP TABLE t1; + +--echo # +--echo # Bug #49465: valgrind warnings and incorrect live checksum... +--echo # +CREATE TABLE t1( +a VARCHAR(1), b VARCHAR(1), c VARCHAR(1), +f VARCHAR(1), g VARCHAR(1), h VARCHAR(1), +i VARCHAR(1), j VARCHAR(1), k VARCHAR(1)) CHECKSUM=1; +INSERT INTO t1 VALUES('', '', '', '', '', '', '', '', ''); +CHECKSUM TABLE t1 QUICK; +CHECKSUM TABLE t1 EXTENDED; +DROP TABLE t1; + + --echo End of 5.0 tests diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index b0958201795..76d4378a6f1 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -787,12 +787,21 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, restore_record(table,s->default_values); // Get empty record else { + TABLE_SHARE *share= table->s; + /* Fix delete marker. No need to restore rest of record since it will be overwritten by fill_record() anyway (and fill_record() does not use default values in this case). */ - table->record[0][0]= table->s->default_values[0]; + table->record[0][0]= share->default_values[0]; + + /* Fix undefined null_bits. */ + if (share->null_bytes > 1 && share->last_null_bit_pos) + { + table->record[0][share->null_bytes - 1]= + share->default_values[share->null_bytes - 1]; + } } if (fill_record_n_invoke_before_triggers(thd, table->field, *values, 0, table->triggers, From b0c9164cc9135ef57960bb7da653833c3715772f Mon Sep 17 00:00:00 2001 From: Martin Hansson Date: Thu, 17 Dec 2009 10:55:18 +0100 Subject: [PATCH 085/104] Bug#47650: using group by with rollup without indexes returns incorrect results with where An outer join of a const table (outer) and a normal table (inner) with GROUP BY on a field from the outer table would optimize away GROUP BY, and thus trigger the optimization to do away with a temporary table if grouping was performed on columns from the const table, hence executing the query with filesort without temporary table. But this should not be done if there is a non-indexed access to the inner table, since filesort does not handle joins. It expects either ref access, range ditto or table scan. The join condition will thus not be applied. Fixed by always forcing execution with temporary table in the case of ROLLUP with a query involving an outer join. This is a slightly broader class of queries than need fixing, but it is hard to ascertain the position of a ROLLUP field wrt outer join with current query representation. --- mysql-test/r/join_outer.result | 35 ++++++++++++++++++++++++++++++++++ mysql-test/t/join_outer.test | 29 ++++++++++++++++++++++++++++ sql/sql_select.cc | 14 +++++++++++++- 3 files changed, 77 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result index 1e4fc91b8bd..083be3737f7 100644 --- a/mysql-test/r/join_outer.result +++ b/mysql-test/r/join_outer.result @@ -1254,3 +1254,38 @@ SELECT * FROM t1 LEFT JOIN t2 ON e<>0 WHERE c=1 AND d<=>NULL; c e d 1 0 NULL DROP TABLE t1,t2; +# +# Bug#47650: using group by with rollup without indexes returns incorrect +# results with where +# +CREATE TABLE t1 ( a INT ); +INSERT INTO t1 VALUES (1); +CREATE TABLE t2 ( a INT, b INT ); +INSERT INTO t2 VALUES (1, 1),(1, 2),(1, 3),(2, 4),(2, 5); +EXPLAIN +SELECT t1.a, COUNT( t2.b ), SUM( t2.b ), MAX( t2.b ) +FROM t1 LEFT JOIN t2 USING( a ) +GROUP BY t1.a WITH ROLLUP; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 system NULL NULL NULL NULL 1 Using temporary; Using filesort +1 SIMPLE t2 ALL NULL NULL NULL NULL 5 +SELECT t1.a, COUNT( t2.b ), SUM( t2.b ), MAX( t2.b ) +FROM t1 LEFT JOIN t2 USING( a ) +GROUP BY t1.a WITH ROLLUP; +a COUNT( t2.b ) SUM( t2.b ) MAX( t2.b ) +1 3 6 3 +NULL 3 6 3 +EXPLAIN +SELECT t1.a, COUNT( t2.b ), SUM( t2.b ), MAX( t2.b ) +FROM t1 JOIN t2 USING( a ) +GROUP BY t1.a WITH ROLLUP; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 system NULL NULL NULL NULL 1 Using filesort +1 SIMPLE t2 ALL NULL NULL NULL NULL 5 Using where +SELECT t1.a, COUNT( t2.b ), SUM( t2.b ), MAX( t2.b ) +FROM t1 JOIN t2 USING( a ) +GROUP BY t1.a WITH ROLLUP; +a COUNT( t2.b ) SUM( t2.b ) MAX( t2.b ) +1 3 6 3 +NULL 3 6 3 +DROP TABLE t1, t2; diff --git a/mysql-test/t/join_outer.test b/mysql-test/t/join_outer.test index 35aec71ebb8..aeaa69657c6 100644 --- a/mysql-test/t/join_outer.test +++ b/mysql-test/t/join_outer.test @@ -867,3 +867,32 @@ SELECT * FROM t1 LEFT JOIN t2 ON e<>0 WHERE c=1 AND d<=>NULL; DROP TABLE t1,t2; +--echo # +--echo # Bug#47650: using group by with rollup without indexes returns incorrect +--echo # results with where +--echo # +CREATE TABLE t1 ( a INT ); +INSERT INTO t1 VALUES (1); + +CREATE TABLE t2 ( a INT, b INT ); +INSERT INTO t2 VALUES (1, 1),(1, 2),(1, 3),(2, 4),(2, 5); + +EXPLAIN +SELECT t1.a, COUNT( t2.b ), SUM( t2.b ), MAX( t2.b ) +FROM t1 LEFT JOIN t2 USING( a ) +GROUP BY t1.a WITH ROLLUP; + +SELECT t1.a, COUNT( t2.b ), SUM( t2.b ), MAX( t2.b ) +FROM t1 LEFT JOIN t2 USING( a ) +GROUP BY t1.a WITH ROLLUP; + +EXPLAIN +SELECT t1.a, COUNT( t2.b ), SUM( t2.b ), MAX( t2.b ) +FROM t1 JOIN t2 USING( a ) +GROUP BY t1.a WITH ROLLUP; + +SELECT t1.a, COUNT( t2.b ), SUM( t2.b ), MAX( t2.b ) +FROM t1 JOIN t2 USING( a ) +GROUP BY t1.a WITH ROLLUP; + +DROP TABLE t1, t2; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index cbee09f1fdb..6383fe63012 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7124,7 +7124,19 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond, for (order=first_order; order ; order=order->next) { table_map order_tables=order->item[0]->used_tables(); - if (order->item[0]->with_sum_func) + if (order->item[0]->with_sum_func || + /* + If the outer table of an outer join is const (either by itself or + after applying WHERE condition), grouping on a field from such a + table will be optimized away and filesort without temporary table + will be used unless we prevent that now. Filesort is not fit to + handle joins and the join condition is not applied. We can't detect + the case without an expensive test, however, so we force temporary + table for all queries containing more than one table, ROLLUP, and an + outer join. + */ + (join->tables > 1 && join->rollup.state == ROLLUP::STATE_INITED && + join->outer_join)) *simple_order=0; // Must do a temp table to sort else if (!(order_tables & not_const_tables)) { From 801deedcf265bd3fe90e45c93b37133b68a19ba9 Mon Sep 17 00:00:00 2001 From: Satya B Date: Thu, 17 Dec 2009 16:55:50 +0530 Subject: [PATCH 086/104] Fix for Bug#37408 - Compressed MyISAM files should not require/use mmap() When compressed myisam files are opened, they are always memory mapped sometimes causing memory swapping problems. When we mmap the myisam compressed tables of size greater than the memory available, the kswapd0 process utilization is very high consuming 30-40% of the cpu. This happens only with linux kernels older than 2.6.9 With newer linux kernels, we don't have this problem of high cpu consumption and this option may not be required. The option 'myisam_mmap_size' is added to limit the amount of memory used for memory mapping of myisam files. This option is not dynamic. The default value on 32 bit system is 4294967295 bytes and on 64 bit system it is 18446744073709547520 bytes. Note: Testcase only tests the option variable. The actual bug has be to tested manually. --- include/my_global.h | 3 +++ include/myisam.h | 4 ++++ myisam/mi_packrec.c | 35 ++++++++++++++++++++++++++++++++++- myisam/mi_static.c | 3 ++- myisam/myisamdef.h | 1 - mysql-test/r/variables.result | 6 ++++++ mysql-test/t/variables.test | 6 ++++++ mysys/my_thr_init.c | 6 +++++- sql/mysqld.cc | 7 ++++++- sql/set_var.cc | 12 ++++++++++++ 10 files changed, 78 insertions(+), 5 deletions(-) diff --git a/include/my_global.h b/include/my_global.h index 6910ae092e1..595c7cd793b 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -793,6 +793,9 @@ typedef SOCKET_SIZE_TYPE size_socket; #define DBL_MAX 1.79769313486231470e+308 #define FLT_MAX ((float)3.40282346638528860e+38) #endif +#ifndef SIZE_T_MAX +#define SIZE_T_MAX (~((size_t) 0)) +#endif #ifndef HAVE_FINITE #define finite(x) (1.0 / fabs(x) > 0.0) diff --git a/include/myisam.h b/include/myisam.h index ad585f79608..acc2d689b75 100644 --- a/include/myisam.h +++ b/include/myisam.h @@ -270,6 +270,8 @@ extern ulong myisam_bulk_insert_tree_size, myisam_data_pointer_size; /* usually used to check if a symlink points into the mysql data home */ /* which is normally forbidden */ extern int (*myisam_test_invalid_symlink)(const char *filename); +extern ulonglong myisam_mmap_size, myisam_mmap_used; +extern pthread_mutex_t THR_LOCK_myisam_mmap; /* Prototypes for myisam-functions */ @@ -315,6 +317,8 @@ extern int mi_delete_all_rows(struct st_myisam_info *info); extern ulong _mi_calc_blob_length(uint length , const byte *pos); extern uint mi_get_pointer_length(ulonglong file_length, uint def); +#define MEMMAP_EXTRA_MARGIN 7 /* Write this as a suffix for mmap file */ + /* this is used to pass to mysql_myisamchk_table -- by Sasha Pachev */ #define MYISAMCHK_REPAIR 1 /* equivalent to myisamchk -r */ diff --git a/myisam/mi_packrec.c b/myisam/mi_packrec.c index 75cf45d5434..f04c65da505 100644 --- a/myisam/mi_packrec.c +++ b/myisam/mi_packrec.c @@ -1499,12 +1499,26 @@ my_bool _mi_memmap_file(MI_INFO *info) { byte *file_map; MYISAM_SHARE *share=info->s; + my_bool eom; + DBUG_ENTER("mi_memmap_file"); if (!share->file_map) { my_off_t data_file_length= share->state.state.data_file_length; - if (data_file_length > (my_off_t) (~((size_t) 0)) - MEMMAP_EXTRA_MARGIN) + + if (myisam_mmap_size != SIZE_T_MAX) + { + pthread_mutex_lock(&THR_LOCK_myisam_mmap); + eom= data_file_length > myisam_mmap_size - myisam_mmap_used - MEMMAP_EXTRA_MARGIN; + if (!eom) + myisam_mmap_used+= data_file_length + MEMMAP_EXTRA_MARGIN; + pthread_mutex_unlock(&THR_LOCK_myisam_mmap); + } + else + eom= data_file_length > myisam_mmap_size - MEMMAP_EXTRA_MARGIN; + + if (eom) { DBUG_PRINT("warning", ("File is too large for mmap")); DBUG_RETURN(0); @@ -1513,6 +1527,12 @@ my_bool _mi_memmap_file(MI_INFO *info) data_file_length + MEMMAP_EXTRA_MARGIN) { DBUG_PRINT("warning",("File isn't extended for memmap")); + if (myisam_mmap_size != SIZE_T_MAX) + { + pthread_mutex_lock(&THR_LOCK_myisam_mmap); + myisam_mmap_used-= data_file_length + MEMMAP_EXTRA_MARGIN; + pthread_mutex_unlock(&THR_LOCK_myisam_mmap); + } DBUG_RETURN(0); } file_map=(byte*) @@ -1522,6 +1542,12 @@ my_bool _mi_memmap_file(MI_INFO *info) { DBUG_PRINT("warning",("mmap failed: errno: %d",errno)); my_errno=errno; + if (myisam_mmap_size != SIZE_T_MAX) + { + pthread_mutex_lock(&THR_LOCK_myisam_mmap); + myisam_mmap_used-= data_file_length + MEMMAP_EXTRA_MARGIN; + pthread_mutex_unlock(&THR_LOCK_myisam_mmap); + } DBUG_RETURN(0); } share->file_map= file_map; @@ -1538,6 +1564,13 @@ void _mi_unmap_file(MI_INFO *info) VOID(my_munmap(info->s->file_map, (size_t) info->s->state.state.data_file_length+ MEMMAP_EXTRA_MARGIN)); + + if (myisam_mmap_size != SIZE_T_MAX) + { + pthread_mutex_lock(&THR_LOCK_myisam_mmap); + myisam_mmap_used-= info->s->state.state.data_file_length + MEMMAP_EXTRA_MARGIN; + pthread_mutex_unlock(&THR_LOCK_myisam_mmap); + } } diff --git a/myisam/mi_static.c b/myisam/mi_static.c index ab7d3dc592b..b6464e452d7 100644 --- a/myisam/mi_static.c +++ b/myisam/mi_static.c @@ -40,7 +40,8 @@ ulong myisam_concurrent_insert= 0; my_off_t myisam_max_temp_length= MAX_FILE_SIZE; ulong myisam_bulk_insert_tree_size=8192*1024; ulong myisam_data_pointer_size=4; - +ulonglong myisam_mmap_size= SIZE_T_MAX, myisam_mmap_used= 0; +pthread_mutex_t THR_LOCK_myisam_mmap; static int always_valid(const char *filename __attribute__((unused))) { diff --git a/myisam/myisamdef.h b/myisam/myisamdef.h index 4ebd5648d26..13ca945eae8 100644 --- a/myisam/myisamdef.h +++ b/myisam/myisamdef.h @@ -428,7 +428,6 @@ typedef struct st_mi_sort_param #define MI_MAX_BLOCK_LENGTH ((((ulong) 1 << 24)-1) & (~ (ulong) (MI_DYN_ALIGN_SIZE-1))) #define MI_REC_BUFF_OFFSET ALIGN_SIZE(MI_DYN_DELETE_BLOCK_HEADER+sizeof(uint32)) -#define MEMMAP_EXTRA_MARGIN 7 /* Write this as a suffix for file */ #define PACK_TYPE_SELECTED 1 /* Bits in field->pack_type */ #define PACK_TYPE_SPACE_FIELDS 2 diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index 496f0b69fb8..e24117187d2 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -904,3 +904,9 @@ set global server_id =@my_server_id; set global slow_launch_time =@my_slow_launch_time; set global storage_engine =@my_storage_engine; set global thread_cache_size =@my_thread_cache_size; +# +# BUG#37408 - Compressed MyISAM files should not require/use mmap() +# +# Test 'myisam_mmap_size' option is not dynamic +SET @@myisam_mmap_size= 500M; +ERROR HY000: Variable 'myisam_mmap_size' is a read only variable diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index 91f75cf6cd4..cff6a5a0767 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -765,3 +765,9 @@ set global slow_launch_time =@my_slow_launch_time; set global storage_engine =@my_storage_engine; set global thread_cache_size =@my_thread_cache_size; +--echo # +--echo # BUG#37408 - Compressed MyISAM files should not require/use mmap() +--echo # +--echo # Test 'myisam_mmap_size' option is not dynamic +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SET @@myisam_mmap_size= 500M; diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c index 64fc99952e9..8dcffaebbbb 100644 --- a/mysys/my_thr_init.c +++ b/mysys/my_thr_init.c @@ -30,7 +30,9 @@ pthread_key(struct st_my_thread_var, THR_KEY_mysys); #endif /* USE_TLS */ pthread_mutex_t THR_LOCK_malloc,THR_LOCK_open, THR_LOCK_lock,THR_LOCK_isam,THR_LOCK_myisam,THR_LOCK_heap, - THR_LOCK_net, THR_LOCK_charset, THR_LOCK_threads; + THR_LOCK_net, THR_LOCK_charset, THR_LOCK_threads, + THR_LOCK_myisam_mmap; + pthread_cond_t THR_COND_threads; uint THR_thread_count= 0; uint my_thread_end_wait_time= 5; @@ -143,6 +145,7 @@ my_bool my_thread_global_init(void) pthread_mutex_init(&THR_LOCK_lock,MY_MUTEX_INIT_FAST); pthread_mutex_init(&THR_LOCK_isam,MY_MUTEX_INIT_SLOW); pthread_mutex_init(&THR_LOCK_myisam,MY_MUTEX_INIT_SLOW); + pthread_mutex_init(&THR_LOCK_myisam_mmap,MY_MUTEX_INIT_FAST); pthread_mutex_init(&THR_LOCK_heap,MY_MUTEX_INIT_FAST); pthread_mutex_init(&THR_LOCK_net,MY_MUTEX_INIT_FAST); pthread_mutex_init(&THR_LOCK_charset,MY_MUTEX_INIT_FAST); @@ -208,6 +211,7 @@ void my_thread_global_end(void) pthread_mutex_destroy(&THR_LOCK_lock); pthread_mutex_destroy(&THR_LOCK_isam); pthread_mutex_destroy(&THR_LOCK_myisam); + pthread_mutex_destroy(&THR_LOCK_myisam_mmap); pthread_mutex_destroy(&THR_LOCK_heap); pthread_mutex_destroy(&THR_LOCK_net); pthread_mutex_destroy(&THR_LOCK_charset); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index b4eb96ab65a..4b0739cc2d2 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4975,7 +4975,8 @@ enum options_mysqld OPT_MAX_WRITE_LOCK_COUNT, OPT_BULK_INSERT_BUFFER_SIZE, OPT_MAX_ERROR_COUNT, OPT_MULTI_RANGE_COUNT, OPT_MYISAM_DATA_POINTER_SIZE, OPT_MYISAM_BLOCK_SIZE, OPT_MYISAM_MAX_EXTRA_SORT_FILE_SIZE, - OPT_MYISAM_MAX_SORT_FILE_SIZE, OPT_MYISAM_SORT_BUFFER_SIZE, + OPT_MYISAM_MAX_SORT_FILE_SIZE, OPT_MYISAM_MMAP_SIZE, + OPT_MYISAM_SORT_BUFFER_SIZE, OPT_MYISAM_STATS_METHOD, OPT_NET_BUFFER_LENGTH, OPT_NET_RETRY_COUNT, OPT_NET_READ_TIMEOUT, OPT_NET_WRITE_TIMEOUT, @@ -6255,6 +6256,10 @@ The minimum value for this variable is 4096.", (gptr*) &max_system_variables.myisam_max_sort_file_size, 0, GET_ULL, REQUIRED_ARG, (longlong) LONG_MAX, 0, (ulonglong) MAX_FILE_SIZE, 0, 1024*1024, 0}, + {"myisam_mmap_size", OPT_MYISAM_MMAP_SIZE, + "Can be used to restrict the total memory used for memory mmaping of myisam files", + (gptr*) &myisam_mmap_size, (gptr*) &myisam_mmap_size, 0, + GET_ULL, REQUIRED_ARG, SIZE_T_MAX, MEMMAP_EXTRA_MARGIN, SIZE_T_MAX, 0, 1, 0}, {"myisam_repair_threads", OPT_MYISAM_REPAIR_THREADS, "Number of threads to use when repairing MyISAM tables. The value of 1 disables parallel repair.", (gptr*) &global_system_variables.myisam_repair_threads, diff --git a/sql/set_var.cc b/sql/set_var.cc index c885f7160e9..4871afd2c56 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -122,6 +122,7 @@ static byte *get_error_count(THD *thd); static byte *get_warning_count(THD *thd); static byte *get_have_innodb(THD *thd); static byte *get_tmpdir(THD *thd); +static byte *get_myisam_mmap_size(THD *thd); /* Variable definition list @@ -623,6 +624,10 @@ sys_var_thd_bool sys_keep_files_on_create("keep_files_on_create", &SV::keep_files_on_create); +static sys_var_readonly sys_myisam_mmap_size("myisam_mmap_size", + OPT_GLOBAL, + SHOW_LONGLONG, + get_myisam_mmap_size); /* @@ -723,6 +728,7 @@ sys_var *sys_variables[]= &sys_multi_range_count, &sys_myisam_data_pointer_size, &sys_myisam_max_sort_file_size, + &sys_myisam_mmap_size, &sys_myisam_repair_threads, &sys_myisam_sort_buffer_size, &sys_myisam_stats_method, @@ -1026,6 +1032,7 @@ struct show_var_st init_vars[]= { {sys_myisam_data_pointer_size.name, (char*) &sys_myisam_data_pointer_size, SHOW_SYS}, {sys_myisam_max_sort_file_size.name, (char*) &sys_myisam_max_sort_file_size, SHOW_SYS}, + {sys_myisam_mmap_size.name, (char*) &sys_myisam_mmap_size, SHOW_SYS}, {"myisam_recover_options", (char*) &myisam_recover_options_str, SHOW_CHAR_PTR}, {sys_myisam_repair_threads.name, (char*) &sys_myisam_repair_threads, SHOW_SYS}, @@ -3181,6 +3188,11 @@ static byte *get_tmpdir(THD *thd) return (byte*)mysql_tmpdir; } +static byte *get_myisam_mmap_size(THD *thd) +{ + return (byte *)&myisam_mmap_size; +} + /**************************************************************************** Main handling of variables: - Initialisation From f9a7ac066469440fb73cc2b5cafc2723cb47d217 Mon Sep 17 00:00:00 2001 From: Martin Hansson Date: Thu, 17 Dec 2009 13:38:27 +0100 Subject: [PATCH 087/104] Backport of fix for bug#35020 --- mysql-test/r/query_cache.result | 107 +++++++++++++--------------- mysql-test/r/show_check.result | 15 +--- mysql-test/t/query_cache.test | 112 +++++++++++++++++++++-------- mysql-test/t/show_check.test | 10 +-- sql/sql_yacc.yy | 122 ++++++++++++++++++++++---------- 5 files changed, 226 insertions(+), 140 deletions(-) diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index b67fa9322ee..9cde630e4ed 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -176,21 +176,6 @@ a 1 2 3 -select * from t1 union select sql_cache * from t1; -a -1 -2 -3 -select * from t1 where a IN (select sql_cache a from t1); -a -1 -2 -3 -select * from t1 where a IN (select a from t1 union select sql_cache a from t1); -a -1 -2 -3 show status like "Qcache_hits"; Variable_name Value Qcache_hits 4 @@ -207,41 +192,6 @@ a 1 2 3 -select * from t1 union select sql_no_cache * from t1; -a -1 -2 -3 -select * from t1 where a IN (select sql_no_cache a from t1); -a -1 -2 -3 -select * from t1 where a IN (select a from t1 union select sql_no_cache a from t1); -a -1 -2 -3 -select sql_cache sql_no_cache * from t1; -a -1 -2 -3 -select sql_cache * from t1 union select sql_no_cache * from t1; -a -1 -2 -3 -select sql_cache * from t1 where a IN (select sql_no_cache a from t1); -a -1 -2 -3 -select sql_cache * from t1 where a IN (select a from t1 union select sql_no_cache a from t1); -a -1 -2 -3 show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 0 @@ -1490,12 +1440,6 @@ insert into t1 values ('c'); a drop table t1; set GLOBAL query_cache_size= default; -set GLOBAL query_cache_size=1000000; -create table t1 (a char); -insert into t1 values ('c'); -a -drop table t1; -set GLOBAL query_cache_size= default; SET GLOBAL query_cache_size=64*1024*1024; CREATE TABLE t1 (id INT); CREATE PROCEDURE proc29856(IN theUPC TEXT) @@ -1723,4 +1667,55 @@ SELECT 1 FROM t1 GROUP BY 1 DROP TABLE t1; SET GLOBAL query_cache_size= default; +CREATE TABLE t1( a INT ); +SET @v = ( SELECT SQL_CACHE 1 ); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1 )' at line 1 +SET @v = ( SELECT SQL_NO_CACHE 1 ); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1 )' at line 1 +SELECT a FROM t1 WHERE a IN ( SELECT SQL_CACHE a FROM t1 ); +ERROR 42S22: Unknown column 'SQL_CACHE' in 'field list' +SELECT a FROM t1 WHERE a IN ( SELECT SQL_NO_CACHE a FROM t1 ); +ERROR 42S22: Unknown column 'SQL_NO_CACHE' in 'field list' +SELECT ( SELECT SQL_CACHE a FROM t1 ); +ERROR 42S22: Unknown column 'SQL_CACHE' in 'field list' +SELECT ( SELECT SQL_NO_CACHE a FROM t1 ); +ERROR 42S22: Unknown column 'SQL_NO_CACHE' in 'field list' +SELECT SQL_CACHE * FROM t1; +a +SELECT SQL_NO_CACHE * FROM t1; +a +SELECT * FROM t1 UNION SELECT SQL_CACHE * FROM t1; +ERROR 42000: Incorrect usage/placement of 'SQL_CACHE' +SELECT * FROM t1 UNION SELECT SQL_NO_CACHE * FROM t1; +ERROR 42000: Incorrect usage/placement of 'SQL_NO_CACHE' +SELECT * FROM t1 WHERE a IN (SELECT SQL_CACHE a FROM t1); +ERROR 42S22: Unknown column 'SQL_CACHE' in 'field list' +SELECT * FROM t1 WHERE a IN (SELECT a FROM t1 UNION SELECT SQL_CACHE a FROM t1); +ERROR 42S22: Unknown column 'SQL_CACHE' in 'field list' +SELECT * FROM t1 UNION SELECT SQL_NO_CACHE * FROM t1; +ERROR 42000: Incorrect usage/placement of 'SQL_NO_CACHE' +SELECT * FROM t1 WHERE a IN (SELECT SQL_NO_CACHE a FROM t1); +ERROR 42S22: Unknown column 'SQL_NO_CACHE' in 'field list' +SELECT * FROM t1 WHERE a IN +(SELECT a FROM t1 UNION SELECT SQL_NO_CACHE a FROM t1); +ERROR 42S22: Unknown column 'SQL_NO_CACHE' in 'field list' +SELECT SQL_CACHE SQL_NO_CACHE * FROM t1; +ERROR HY000: Incorrect usage of SQL_CACHE and SQL_NO_CACHE +SELECT SQL_NO_CACHE SQL_CACHE * FROM t1; +ERROR HY000: Incorrect usage of SQL_NO_CACHE and SQL_CACHE +SELECT SQL_CACHE * FROM t1 UNION SELECT SQL_CACHE * FROM t1; +ERROR 42000: Incorrect usage/placement of 'SQL_CACHE' +SELECT SQL_CACHE * FROM t1 UNION SELECT SQL_NO_CACHE * FROM t1; +ERROR 42000: Incorrect usage/placement of 'SQL_NO_CACHE' +SELECT SQL_NO_CACHE * FROM t1 UNION SELECT SQL_CACHE * FROM t1; +ERROR 42000: Incorrect usage/placement of 'SQL_CACHE' +SELECT SQL_NO_CACHE * FROM t1 UNION SELECT SQL_NO_CACHE * FROM t1; +ERROR 42000: Incorrect usage/placement of 'SQL_NO_CACHE' +SELECT SQL_CACHE * FROM t1 WHERE a IN +(SELECT SQL_NO_CACHE a FROM t1); +ERROR 42S22: Unknown column 'SQL_NO_CACHE' in 'field list' +SELECT SQL_CACHE * FROM t1 WHERE a IN +(SELECT a FROM t1 UNION SELECT SQL_NO_CACHE a FROM t1); +ERROR 42S22: Unknown column 'SQL_NO_CACHE' in 'field list' +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index 50384149a26..44544724848 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -737,20 +737,11 @@ View Create View character_set_client collation_connection v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select sql_no_cache now() AS `NOW()` binary binary DROP VIEW v1; CREATE VIEW v1 AS SELECT SQL_CACHE SQL_NO_CACHE NOW(); -SHOW CREATE VIEW v1; -View Create View character_set_client collation_connection -v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select sql_no_cache now() AS `NOW()` binary binary -DROP VIEW v1; +ERROR HY000: Incorrect usage of SQL_CACHE and SQL_NO_CACHE CREATE VIEW v1 AS SELECT SQL_NO_CACHE SQL_CACHE NOW(); -SHOW CREATE VIEW v1; -View Create View character_set_client collation_connection -v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select sql_no_cache now() AS `NOW()` binary binary -DROP VIEW v1; +ERROR HY000: Incorrect usage of SQL_NO_CACHE and SQL_CACHE CREATE VIEW v1 AS SELECT SQL_CACHE SQL_NO_CACHE SQL_CACHE NOW(); -SHOW CREATE VIEW v1; -View Create View character_set_client collation_connection -v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select sql_no_cache now() AS `NOW()` binary binary -DROP VIEW v1; +ERROR HY000: Incorrect usage of SQL_CACHE and SQL_NO_CACHE CREATE PROCEDURE p1() BEGIN SET @s= 'CREATE VIEW v1 AS SELECT SQL_CACHE 1'; diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test index 0edc9cca385..d6e73cbc88d 100644 --- a/mysql-test/t/query_cache.test +++ b/mysql-test/t/query_cache.test @@ -94,10 +94,6 @@ select sql_cache * from t1 union select * from t1; set query_cache_type=2; select sql_cache * from t1 union select * from t1; -# all sql_cache statements, except for the first select, are ignored. -select * from t1 union select sql_cache * from t1; -select * from t1 where a IN (select sql_cache a from t1); -select * from t1 where a IN (select a from t1 union select sql_cache a from t1); show status like "Qcache_hits"; show status like "Qcache_queries_in_cache"; set query_cache_type=on; @@ -110,15 +106,6 @@ show status like "Qcache_queries_in_cache"; # SELECT SQL_NO_CACHE # select sql_no_cache * from t1; -# sql_no_cache can occur in any nested select to turn on cacheing for the whole -# expression and it will always override a sql_cache statement. -select * from t1 union select sql_no_cache * from t1; -select * from t1 where a IN (select sql_no_cache a from t1); -select * from t1 where a IN (select a from t1 union select sql_no_cache a from t1); -select sql_cache sql_no_cache * from t1; -select sql_cache * from t1 union select sql_no_cache * from t1; -select sql_cache * from t1 where a IN (select sql_no_cache a from t1); -select sql_cache * from t1 where a IN (select a from t1 union select sql_no_cache a from t1); show status like "Qcache_queries_in_cache"; drop table t1; # @@ -1044,22 +1031,25 @@ set GLOBAL query_cache_size= default; # Bug #29053 SQL_CACHE in UNION causes non-deterministic functions to be cached # -set GLOBAL query_cache_size=1000000; - -create table t1 (a char); -insert into t1 values ('c'); - -let $q1= `select RAND() from t1 union select sql_cache 1 from t1;`; -let $q2= `select RAND() from t1 union select sql_cache 1 from t1;`; - +# This syntax is no longer allowed, therefore the test case has been commented +# out. +# See test for Bug#35020 below. +#set GLOBAL query_cache_size=1000000; +# +#create table t1 (a char); +#insert into t1 values ('c'); +# +#let $q1= `select RAND() from t1 union select sql_cache 1 from t1;`; +#let $q2= `select RAND() from t1 union select sql_cache 1 from t1;`; +# # disabling the logging of the query because the times are different each run. ---disable_query_log -eval select a from t1 where "$q1" = "$q2"; ---enable_query_log - -drop table t1; - -set GLOBAL query_cache_size= default; +#--disable_query_log +#eval select a from t1 where "$q1" = "$q2"; +#--enable_query_log +# +#drop table t1; +# +#set GLOBAL query_cache_size= default; # # Bug#29856: Insufficient buffer space led to a server crash. @@ -1307,5 +1297,69 @@ SELECT 1 FROM t1 GROUP BY DROP TABLE t1; SET GLOBAL query_cache_size= default; ---echo End of 5.1 tests +# +# Bug#35020: illegal sql_cache select syntax +# +CREATE TABLE t1( a INT ); + +--error ER_PARSE_ERROR +SET @v = ( SELECT SQL_CACHE 1 ); +--error ER_PARSE_ERROR +SET @v = ( SELECT SQL_NO_CACHE 1 ); + +# +# Keywords 'SQL_CACHE' and 'SQL_NO_CACHE' are allowed as column names. +# Hence the error messages are not intuitive. +# +--error ER_BAD_FIELD_ERROR +SELECT a FROM t1 WHERE a IN ( SELECT SQL_CACHE a FROM t1 ); +--error ER_BAD_FIELD_ERROR +SELECT a FROM t1 WHERE a IN ( SELECT SQL_NO_CACHE a FROM t1 ); +--error ER_BAD_FIELD_ERROR +SELECT ( SELECT SQL_CACHE a FROM t1 ); +--error ER_BAD_FIELD_ERROR +SELECT ( SELECT SQL_NO_CACHE a FROM t1 ); + +SELECT SQL_CACHE * FROM t1; +SELECT SQL_NO_CACHE * FROM t1; + +# SQL_CACHE is only allowed once in first top-level select. +--error ER_CANT_USE_OPTION_HERE +SELECT * FROM t1 UNION SELECT SQL_CACHE * FROM t1; +--error ER_CANT_USE_OPTION_HERE +SELECT * FROM t1 UNION SELECT SQL_NO_CACHE * FROM t1; +--error ER_BAD_FIELD_ERROR +SELECT * FROM t1 WHERE a IN (SELECT SQL_CACHE a FROM t1); +--error ER_BAD_FIELD_ERROR +SELECT * FROM t1 WHERE a IN (SELECT a FROM t1 UNION SELECT SQL_CACHE a FROM t1); + +--error ER_CANT_USE_OPTION_HERE +SELECT * FROM t1 UNION SELECT SQL_NO_CACHE * FROM t1; +--error ER_BAD_FIELD_ERROR +SELECT * FROM t1 WHERE a IN (SELECT SQL_NO_CACHE a FROM t1); +--error ER_BAD_FIELD_ERROR +SELECT * FROM t1 WHERE a IN + (SELECT a FROM t1 UNION SELECT SQL_NO_CACHE a FROM t1); +--error ER_WRONG_USAGE +SELECT SQL_CACHE SQL_NO_CACHE * FROM t1; +--error ER_WRONG_USAGE +SELECT SQL_NO_CACHE SQL_CACHE * FROM t1; +--error ER_CANT_USE_OPTION_HERE +SELECT SQL_CACHE * FROM t1 UNION SELECT SQL_CACHE * FROM t1; +--error ER_CANT_USE_OPTION_HERE +SELECT SQL_CACHE * FROM t1 UNION SELECT SQL_NO_CACHE * FROM t1; +--error ER_CANT_USE_OPTION_HERE +SELECT SQL_NO_CACHE * FROM t1 UNION SELECT SQL_CACHE * FROM t1; +--error ER_CANT_USE_OPTION_HERE +SELECT SQL_NO_CACHE * FROM t1 UNION SELECT SQL_NO_CACHE * FROM t1; +--error ER_BAD_FIELD_ERROR +SELECT SQL_CACHE * FROM t1 WHERE a IN + (SELECT SQL_NO_CACHE a FROM t1); +--error ER_BAD_FIELD_ERROR +SELECT SQL_CACHE * FROM t1 WHERE a IN + (SELECT a FROM t1 UNION SELECT SQL_NO_CACHE a FROM t1); + +DROP TABLE t1; + +--echo End of 5.1 tests diff --git a/mysql-test/t/show_check.test b/mysql-test/t/show_check.test index 6e07f717db6..6d1d493168c 100644 --- a/mysql-test/t/show_check.test +++ b/mysql-test/t/show_check.test @@ -550,18 +550,14 @@ CREATE VIEW v1 AS SELECT SQL_NO_CACHE NOW(); SHOW CREATE VIEW v1; DROP VIEW v1; -# Check that SQL_NO_CACHE always wins. +--error ER_WRONG_USAGE CREATE VIEW v1 AS SELECT SQL_CACHE SQL_NO_CACHE NOW(); -SHOW CREATE VIEW v1; -DROP VIEW v1; +--error ER_WRONG_USAGE CREATE VIEW v1 AS SELECT SQL_NO_CACHE SQL_CACHE NOW(); -SHOW CREATE VIEW v1; -DROP VIEW v1; +--error ER_WRONG_USAGE CREATE VIEW v1 AS SELECT SQL_CACHE SQL_NO_CACHE SQL_CACHE NOW(); -SHOW CREATE VIEW v1; -DROP VIEW v1; # Check CREATE VIEW in a prepared statement in a procedure. delimiter |; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index a57897f4eac..533db6fdd6e 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -735,10 +735,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %pure_parser /* We have threads */ /* - Currently there are 173 shift/reduce conflicts. + Currently there are 172 shift/reduce conflicts. We should not introduce new conflicts any more. */ -%expect 173 +%expect 172 /* Comments for TOKENS. @@ -7098,50 +7098,63 @@ select_option_list: ; select_option: - STRAIGHT_JOIN { Select->options|= SELECT_STRAIGHT_JOIN; } - | HIGH_PRIORITY - { - if (check_simple_select()) - MYSQL_YYABORT; - Lex->lock_option= TL_READ_HIGH_PRIORITY; - Lex->current_select->lock_option= TL_READ_HIGH_PRIORITY; - } - | DISTINCT { Select->options|= SELECT_DISTINCT; } - | SQL_SMALL_RESULT { Select->options|= SELECT_SMALL_RESULT; } - | SQL_BIG_RESULT { Select->options|= SELECT_BIG_RESULT; } - | SQL_BUFFER_RESULT - { - if (check_simple_select()) - MYSQL_YYABORT; - Select->options|= OPTION_BUFFER_RESULT; - } - | SQL_CALC_FOUND_ROWS - { - if (check_simple_select()) - MYSQL_YYABORT; - Select->options|= OPTION_FOUND_ROWS; - } + query_expression_option | SQL_NO_CACHE_SYM { - Lex->safe_to_cache_query=0; - Lex->select_lex.options&= ~OPTION_TO_QUERY_CACHE; - Lex->select_lex.sql_cache= SELECT_LEX::SQL_NO_CACHE; + /* + Allow this flag only on the first top-level SELECT statement, if + SQL_CACHE wasn't specified, and only once per query. + */ + if (Lex->current_select != &Lex->select_lex) + { + my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_NO_CACHE"); + MYSQL_YYABORT; + } + else if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_CACHE) + { + my_error(ER_WRONG_USAGE, MYF(0), "SQL_CACHE", "SQL_NO_CACHE"); + MYSQL_YYABORT; + } + else if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_NO_CACHE) + { + my_error(ER_DUP_ARGUMENT, MYF(0), "SQL_NO_CACHE"); + MYSQL_YYABORT; + } + else + { + Lex->safe_to_cache_query=0; + Lex->select_lex.options&= ~OPTION_TO_QUERY_CACHE; + Lex->select_lex.sql_cache= SELECT_LEX::SQL_NO_CACHE; + } } | SQL_CACHE_SYM { - /* - Honor this flag only if SQL_NO_CACHE wasn't specified AND - we are parsing the outermost SELECT in the query. - */ - if (Lex->select_lex.sql_cache != SELECT_LEX::SQL_NO_CACHE && - Lex->current_select == &Lex->select_lex) + /* + Allow this flag only on the first top-level SELECT statement, if + SQL_NO_CACHE wasn't specified, and only once per query. + */ + if (Lex->current_select != &Lex->select_lex) + { + my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_CACHE"); + MYSQL_YYABORT; + } + else if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_NO_CACHE) + { + my_error(ER_WRONG_USAGE, MYF(0), "SQL_NO_CACHE", "SQL_CACHE"); + MYSQL_YYABORT; + } + else if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_CACHE) + { + my_error(ER_DUP_ARGUMENT, MYF(0), "SQL_CACHE"); + MYSQL_YYABORT; + } + else { Lex->safe_to_cache_query=1; Lex->select_lex.options|= OPTION_TO_QUERY_CACHE; Lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE; } } - | ALL { Select->options|= SELECT_ALL; } ; select_lock_type: @@ -9213,7 +9226,7 @@ select_part2_derived: mysql_init_select(lex); lex->current_select->parsing_place= SELECT_LIST; } - select_options select_item_list + opt_query_expression_options select_item_list { Select->parsing_place= NO_MATTER; } @@ -13561,6 +13574,43 @@ subselect_end: } ; +opt_query_expression_options: + /* empty */ + | query_expression_option_list + ; + +query_expression_option_list: + query_expression_option_list query_expression_option + | query_expression_option + ; + +query_expression_option: + STRAIGHT_JOIN { Select->options|= SELECT_STRAIGHT_JOIN; } + | HIGH_PRIORITY + { + if (check_simple_select()) + MYSQL_YYABORT; + Lex->lock_option= TL_READ_HIGH_PRIORITY; + Lex->current_select->lock_option= TL_READ_HIGH_PRIORITY; + } + | DISTINCT { Select->options|= SELECT_DISTINCT; } + | SQL_SMALL_RESULT { Select->options|= SELECT_SMALL_RESULT; } + | SQL_BIG_RESULT { Select->options|= SELECT_BIG_RESULT; } + | SQL_BUFFER_RESULT + { + if (check_simple_select()) + MYSQL_YYABORT; + Select->options|= OPTION_BUFFER_RESULT; + } + | SQL_CALC_FOUND_ROWS + { + if (check_simple_select()) + MYSQL_YYABORT; + Select->options|= OPTION_FOUND_ROWS; + } + | ALL { Select->options|= SELECT_ALL; } + ; + /************************************************************************** CREATE VIEW | TRIGGER | PROCEDURE statements. From 0f7397908466421a857fd1718766c41ef7648c9b Mon Sep 17 00:00:00 2001 From: Andrei Elkin Date: Thu, 17 Dec 2009 16:34:11 +0200 Subject: [PATCH 088/104] Bug #49740 rpl.rpl_temporary fails in PB2 in mysql-trunk-merge The test allowed random coincidence of connection ids for two concurrent sessions performing CREATE/DROP temp tables. Fixed with correcting the test. The sessions connection ids are not changed from their defaults anymore. --- mysql-test/r/rpl_temporary.result | 2 ++ mysql-test/t/rpl_temporary.test | 2 ++ 2 files changed, 4 insertions(+) diff --git a/mysql-test/r/rpl_temporary.result b/mysql-test/r/rpl_temporary.result index 1326c7491f5..45e1a2776f7 100644 --- a/mysql-test/r/rpl_temporary.result +++ b/mysql-test/r/rpl_temporary.result @@ -16,8 +16,10 @@ ERROR 42000: Access denied; you need the SUPER privilege for this operation SELECT @@session.sql_select_limit = @save_select_limit; @@session.sql_select_limit = @save_select_limit 1 +SET @save_conn_id= connection_id(); SET @@session.pseudo_thread_id=100; SET @@session.pseudo_thread_id=connection_id(); +SET @@session.pseudo_thread_id=@save_conn_id; SET @@session.sql_log_bin=0; SET @@session.sql_log_bin=1; drop table if exists t1,t2; diff --git a/mysql-test/t/rpl_temporary.test b/mysql-test/t/rpl_temporary.test index 4cd538877eb..b85262b565d 100644 --- a/mysql-test/t/rpl_temporary.test +++ b/mysql-test/t/rpl_temporary.test @@ -41,8 +41,10 @@ SET @@session.sql_select_limit=10, @@session.sql_log_bin=0; SELECT @@session.sql_select_limit = @save_select_limit; #shouldn't have changed # Now as root, to be sure it works connection con2; +SET @save_conn_id= connection_id(); SET @@session.pseudo_thread_id=100; SET @@session.pseudo_thread_id=connection_id(); +SET @@session.pseudo_thread_id=@save_conn_id; SET @@session.sql_log_bin=0; SET @@session.sql_log_bin=1; From 29c60cd5b7250995a5ac79c0fd703c0db5d612eb Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Thu, 17 Dec 2009 18:39:10 +0100 Subject: [PATCH 089/104] BUG#49591, Fixed version string in SHOW CREATE TABLE to accomodate for column list partitioning and new function to_seconds --- mysql-test/r/partition_column.result | 16 ++++++------ mysql-test/r/partition_range.result | 37 ++++++++++++++++++++++++++++ mysql-test/r/partition_utf8.result | 6 ++--- mysql-test/t/partition_range.test | 13 ++++++++++ sql/item.h | 9 +++++++ sql/item_timefunc.h | 9 +++++++ sql/partition_info.cc | 36 +++++++++++++++++++++++++++ sql/partition_info.h | 1 + sql/sql_show.cc | 2 +- 9 files changed, 117 insertions(+), 12 deletions(-) diff --git a/mysql-test/r/partition_column.result b/mysql-test/r/partition_column.result index 784df3045f0..a64ca8e405d 100644 --- a/mysql-test/r/partition_column.result +++ b/mysql-test/r/partition_column.result @@ -69,7 +69,7 @@ Table Create Table t1 CREATE TABLE `t1` ( `a` varchar(5) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 -/*!50100 PARTITION BY LIST COLUMNS(a) +/*!50500 PARTITION BY LIST COLUMNS(a) (PARTITION p0 VALUES IN ('''') ENGINE = MyISAM, PARTITION p1 VALUES IN ('\\') ENGINE = MyISAM, PARTITION p2 VALUES IN ('\0') ENGINE = MyISAM) */ @@ -128,7 +128,7 @@ t1 CREATE TABLE `t1` ( `c` varchar(25) DEFAULT NULL, `d` datetime DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 -/*!50100 PARTITION BY RANGE COLUMNS(a,b,c,d) +/*!50500 PARTITION BY RANGE COLUMNS(a,b,c,d) SUBPARTITION BY HASH (to_seconds(d)) SUBPARTITIONS 4 (PARTITION p0 VALUES LESS THAN (1,'0',MAXVALUE,'1900-01-01') ENGINE = MyISAM, @@ -211,7 +211,7 @@ t1 CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 -/*!50100 PARTITION BY LIST COLUMNS(a,b) +/*!50500 PARTITION BY LIST COLUMNS(a,b) (PARTITION p0 VALUES IN ((1,NULL),(2,NULL),(NULL,NULL)) ENGINE = MyISAM, PARTITION p1 VALUES IN ((1,1),(2,2)) ENGINE = MyISAM, PARTITION p2 VALUES IN ((3,NULL),(NULL,1)) ENGINE = MyISAM) */ @@ -245,7 +245,7 @@ t1 CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 -/*!50100 PARTITION BY LIST COLUMNS(a,b) +/*!50500 PARTITION BY LIST COLUMNS(a,b) (PARTITION p0 VALUES IN ((1,NULL),(2,NULL),(NULL,NULL)) ENGINE = MyISAM, PARTITION p1 VALUES IN ((1,1),(2,2)) ENGINE = MyISAM, PARTITION p2 VALUES IN ((3,NULL),(NULL,1)) ENGINE = MyISAM) */ @@ -299,7 +299,7 @@ Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 -/*!50100 PARTITION BY LIST COLUMNS(a) +/*!50500 PARTITION BY LIST COLUMNS(a) (PARTITION p0 VALUES IN (2,1) ENGINE = MyISAM, PARTITION p1 VALUES IN (4,NULL,3) ENGINE = MyISAM) */ insert into t1 values (1); @@ -314,7 +314,7 @@ Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 -/*!50100 PARTITION BY LIST COLUMNS(a) +/*!50500 PARTITION BY LIST COLUMNS(a) (PARTITION p0 VALUES IN (2,1) ENGINE = MyISAM, PARTITION p1 VALUES IN (4,NULL,3) ENGINE = MyISAM) */ drop table t1; @@ -349,7 +349,7 @@ t1 CREATE TABLE `t1` ( `c` varchar(5) DEFAULT NULL, `d` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 -/*!50100 PARTITION BY RANGE COLUMNS(a,b,c) +/*!50500 PARTITION BY RANGE COLUMNS(a,b,c) SUBPARTITION BY KEY (c,d) SUBPARTITIONS 3 (PARTITION p0 VALUES LESS THAN (1,'abc','abc') ENGINE = MyISAM, @@ -382,7 +382,7 @@ t1 CREATE TABLE `t1` ( `b` varchar(2) DEFAULT NULL, `c` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 -/*!50100 PARTITION BY RANGE COLUMNS(a,b,c) +/*!50500 PARTITION BY RANGE COLUMNS(a,b,c) (PARTITION p0 VALUES LESS THAN (1,'A',1) ENGINE = MyISAM, PARTITION p1 VALUES LESS THAN (1,'B',1) ENGINE = MyISAM) */ insert into t1 values (1, 'A', 1); diff --git a/mysql-test/r/partition_range.result b/mysql-test/r/partition_range.result index 87cb4fba306..0bd7605a5c8 100644 --- a/mysql-test/r/partition_range.result +++ b/mysql-test/r/partition_range.result @@ -1,6 +1,19 @@ drop table if exists t1, t2; create table t1 (a int) partition by range (a) +subpartition by hash(to_seconds(a)) +(partition p0 values less than (1)); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +/*!50500 PARTITION BY RANGE (a) +SUBPARTITION BY HASH (to_seconds(a)) +(PARTITION p0 VALUES LESS THAN (1) ENGINE = MyISAM) */ +drop table t1; +create table t1 (a int) +partition by range (a) ( partition p0 values less than (NULL), partition p1 values less than (MAXVALUE)); ERROR HY000: Not allowed to use NULL value in VALUES LESS THAN @@ -30,6 +43,14 @@ id select_type table partitions type possible_keys key key_len ref rows Extra explain partitions select * from t1 where a < '2007-03-07 23:59:59'; id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 4 Using where +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` datetime NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +/*!50500 PARTITION BY RANGE (TO_SECONDS(a)) +(PARTITION p0 VALUES LESS THAN (63340531200) ENGINE = MyISAM, + PARTITION p1 VALUES LESS THAN (63342604800) ENGINE = MyISAM) */ drop table t1; create table t1 (a date) partition by range(to_seconds(a)) @@ -53,6 +74,14 @@ select * from t1 where a <= '2005-01-01'; a 2003-12-30 2004-12-31 +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` date DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +/*!50500 PARTITION BY RANGE (to_seconds(a)) +(PARTITION p0 VALUES LESS THAN (63240134400) ENGINE = MyISAM, + PARTITION p1 VALUES LESS THAN (63271756800) ENGINE = MyISAM) */ drop table t1; create table t1 (a datetime) partition by range(to_seconds(a)) @@ -75,6 +104,14 @@ id select_type table partitions type possible_keys key key_len ref rows Extra select * from t1 where a <= '2005-01-01'; a 2004-01-01 11:59:29 +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` datetime DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +/*!50500 PARTITION BY RANGE (to_seconds(a)) +(PARTITION p0 VALUES LESS THAN (63240177600) ENGINE = MyISAM, + PARTITION p1 VALUES LESS THAN (63271800000) ENGINE = MyISAM) */ drop table t1; create table t1 (a int, b char(20)) partition by range columns(a,b) diff --git a/mysql-test/r/partition_utf8.result b/mysql-test/r/partition_utf8.result index 0fae7bb16b6..339871f1f4a 100644 --- a/mysql-test/r/partition_utf8.result +++ b/mysql-test/r/partition_utf8.result @@ -7,7 +7,7 @@ Table Create Table t1 CREATE TABLE `t1` ( `a` varchar(2) CHARACTER SET cp1250 DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 -/*!50100 PARTITION BY LIST COLUMNS(a) +/*!50500 PARTITION BY LIST COLUMNS(a) (PARTITION p0 VALUES IN (_cp1250 0x81) ENGINE = MyISAM) */ drop table t1; create table t1 (a varchar(2) character set cp1250) @@ -18,7 +18,7 @@ Table Create Table t1 CREATE TABLE `t1` ( `a` varchar(2) CHARACTER SET cp1250 DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 -/*!50100 PARTITION BY LIST COLUMNS(a) +/*!50500 PARTITION BY LIST COLUMNS(a) (PARTITION p0 VALUES IN ('€') ENGINE = MyISAM) */ drop table t1; create table t1 (a varchar(1500), b varchar(1570)) @@ -45,7 +45,7 @@ Table Create Table t1 CREATE TABLE `t1` ( `a` varchar(2) CHARACTER SET ucs2 DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 -/*!50100 PARTITION BY LIST COLUMNS(a) +/*!50500 PARTITION BY LIST COLUMNS(a) (PARTITION p0 VALUES IN ('†') ENGINE = MyISAM, PARTITION p1 VALUES IN ('') ENGINE = MyISAM) */ insert into t1 values (''); diff --git a/mysql-test/t/partition_range.test b/mysql-test/t/partition_range.test index 07c345faed5..6c0b5ca77d6 100644 --- a/mysql-test/t/partition_range.test +++ b/mysql-test/t/partition_range.test @@ -9,6 +9,16 @@ drop table if exists t1, t2; --enable_warnings +# +#BUG#49591, Add proper version number to SHOW CREATE TABLE +# +create table t1 (a int) +partition by range (a) +subpartition by hash(to_seconds(a)) +(partition p0 values less than (1)); +show create table t1; +drop table t1; + --error ER_NULL_IN_VALUES_LESS_THAN create table t1 (a int) partition by range (a) @@ -30,6 +40,7 @@ explain partitions select * from t1 where a < '2007-03-08 00:00:01'; explain partitions select * from t1 where a <= '2007-03-08 00:00:00'; explain partitions select * from t1 where a <= '2007-03-07 23:59:59'; explain partitions select * from t1 where a < '2007-03-07 23:59:59'; +show create table t1; drop table t1; # # New test cases for new function to_seconds @@ -44,6 +55,7 @@ explain partitions select * from t1 where a <= '2003-12-31'; select * from t1 where a <= '2003-12-31'; explain partitions select * from t1 where a <= '2005-01-01'; select * from t1 where a <= '2005-01-01'; +show create table t1; drop table t1; create table t1 (a datetime) @@ -56,6 +68,7 @@ explain partitions select * from t1 where a <= '2004-01-01 11:59.59'; select * from t1 where a <= '2004-01-01 11:59:59'; explain partitions select * from t1 where a <= '2005-01-01'; select * from t1 where a <= '2005-01-01'; +show create table t1; drop table t1; # diff --git a/sql/item.h b/sql/item.h index 24d800300e7..2c798123852 100644 --- a/sql/item.h +++ b/sql/item.h @@ -894,6 +894,15 @@ public: (*traverser)(this, arg); } + /* + This is used to get the most recent version of any function in + an item tree. The version is the version where a MySQL function + was introduced in. So any function which is added should use + this function and set the int_arg to maximum of the input data + and their own version info. + */ + virtual bool intro_version(uchar *int_arg) { return 0; } + virtual bool remove_dependence_processor(uchar * arg) { return 0; } virtual bool remove_fixed(uchar * arg) { fixed= 0; return 0; } virtual bool cleanup_processor(uchar *arg); diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index cdd74c8c601..31726585e88 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -91,6 +91,15 @@ public: enum_monotonicity_info get_monotonicity_info() const; longlong val_int_endpoint(bool left_endp, bool *incl_endp); bool check_partition_func_processor(uchar *bool_arg) { return FALSE;} + + bool intro_version(uchar *int_arg) + { + int *input_version= (int*)int_arg; + /* This function was introduced in 5.5 */ + int output_version= (*input_version, 50500); + *input_version= output_version; + return 0; + } }; diff --git a/sql/partition_info.cc b/sql/partition_info.cc index 56d79ac0d45..65029a817de 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -115,6 +115,42 @@ char *partition_info::create_default_partition_names(uint part_no, } +/* + Generate a version string for partition expression + This function must be updated every time there is a possibility for + a new function of a higher version number than 5.5.0. + + SYNOPSIS + set_show_version_string() + RETURN VALUES + None +*/ +void partition_info::set_show_version_string(String *packet) +{ + int version= 0; + if (column_list) + packet->append(STRING_WITH_LEN("\n/*!50500")); + else + { + if (part_expr) + part_expr->walk(&Item::intro_version, 0, (uchar*)&version); + if (subpart_expr) + subpart_expr->walk(&Item::intro_version, 0, (uchar*)&version); + if (version == 0) + { + /* No new functions in partition function */ + packet->append(STRING_WITH_LEN("\n/*!50100")); + } + else + { + char buf[65]; + char *buf_ptr= longlong10_to_str((longlong)version, buf, 10); + packet->append(STRING_WITH_LEN("\n/*!")); + packet->append(buf, (size_t)(buf_ptr - buf)); + } + } +} + /* Create a unique name for the subpartition as part_name'sp''subpart_no' SYNOPSIS diff --git a/sql/partition_info.h b/sql/partition_info.h index 0ac8dec4945..479714a3928 100644 --- a/sql/partition_info.h +++ b/sql/partition_info.h @@ -302,6 +302,7 @@ public: bool check_partition_field_length(); bool init_column_part(); bool add_column_list_value(THD *thd, Item *item); + void set_show_version_string(String *packet); private: static int list_part_cmp(const void* a, const void* b); bool set_up_default_partitions(handler *file, HA_CREATE_INFO *info, diff --git a/sql/sql_show.cc b/sql/sql_show.cc index b9f5015f8f0..1b1545f538c 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1497,7 +1497,7 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet, show_table_options, NULL, NULL)))) { - packet->append(STRING_WITH_LEN("\n/*!50100")); + table->part_info->set_show_version_string(packet); packet->append(part_syntax, part_syntax_len); packet->append(STRING_WITH_LEN(" */")); my_free(part_syntax, MYF(0)); From 1ee57905893b66437152c8282614eef39a39fe63 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Fri, 18 Dec 2009 09:29:18 +0100 Subject: [PATCH 090/104] Added extra checks of 64-bit atomic support on GCC and Solaris, also added 64-bit support in solaris.h which was missing --- configure.in | 21 ++++++++++++++++++ include/atomic/solaris.h | 46 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 284fbf5ea49..d4b01e238f6 100644 --- a/configure.in +++ b/configure.in @@ -1889,6 +1889,7 @@ AC_CACHE_CHECK([whether the compiler provides atomic builtins], ], [[ int foo= -10; int bar= 10; + long long int foo64= -10; long long int bar64= 10; if (!__sync_fetch_and_add(&foo, bar) || foo) return -1; bar= __sync_lock_test_and_set(&foo, bar); @@ -1897,6 +1898,14 @@ AC_CACHE_CHECK([whether the compiler provides atomic builtins], bar= __sync_val_compare_and_swap(&bar, foo, 15); if (bar) return -1; + if (!__sync_fetch_and_add(&foo64, bar64) || foo64) + return -1; + bar64= __sync_lock_test_and_set(&foo64, bar64); + if (bar64 || foo64 != 10) + return -1; + bar64= __sync_val_compare_and_swap(&bar64, foo, 15); + if (bar64) + return -1; return 0; ]] )], @@ -1918,6 +1927,7 @@ AC_CACHE_CHECK([whether the OS provides atomic_* functions like Solaris], ] [[ int foo = -10; int bar = 10; + int64_t foo64 = -10; int64_t bar64 = 10; if (atomic_add_int_nv((uint_t *)&foo, bar) || foo) return -1; bar = atomic_swap_uint((uint_t *)&foo, (uint_t)bar); @@ -1926,6 +1936,17 @@ AC_CACHE_CHECK([whether the OS provides atomic_* functions like Solaris], bar = atomic_cas_uint((uint_t *)&bar, (uint_t)foo, 15); if (bar) return -1; + if (atomic_add_64_nv((volatile uint64_t *)&foo64, bar64) || foo64) + return -1; + bar64 = atomic_swap_64((volatile uint64_t *)&foo64, (uint64_t)bar64); + if (bar64 || foo64 != 10) + return -1; + bar64 = atomic_cas_64((volatile uint64_t *)&bar64, (uint_t)foo64, 15); + if (bar64) + return -1; + foo64 = atomic_or_64((volatile uint64_t *)&bar64, 0); + if (foo64) + return -1; return 0; ]] )], diff --git a/include/atomic/solaris.h b/include/atomic/solaris.h index 45efd9faaba..34c0c6de0ed 100644 --- a/include/atomic/solaris.h +++ b/include/atomic/solaris.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2008 MySQL AB +/* Copyright (C) 2008 MySQL AB, 2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -60,6 +60,18 @@ my_atomic_cas32(int32 volatile *a, int32 *cmp, int32 set) return ret; } +STATIC_INLINE int +my_atomic_cas64(int64 volatile *a, int64 *cmp, int64 set) +{ + int ret; + int64 sav; + sav = (int64) atomic_cas_64((volatile uint64_t *)a, (uint64_t)*cmp, + (uint64_t)set); + if (! (ret = (sav == *cmp))) + *cmp = sav; + return ret; +} + STATIC_INLINE int my_atomic_casptr(void * volatile *a, void **cmp, void *set) { @@ -97,6 +109,14 @@ my_atomic_add32(int32 volatile *a, int32 v) return (nv - v); } +STATIC_INLINE int64 +my_atomic_add64(int64 volatile *a, int64 v) +{ + int64 nv; + nv = atomic_add_64_nv((volatile uint64_t *)a, v); + return (nv - v); +} + /* ------------------------------------------------------------------------ */ #ifdef MY_ATOMIC_MODE_DUMMY @@ -110,6 +130,9 @@ my_atomic_load16(int16 volatile *a) { return (*a); } STATIC_INLINE int32 my_atomic_load32(int32 volatile *a) { return (*a); } +STATIC_INLINE int64 +my_atomic_load64(int64 volatile *a) { return (*a); } + STATIC_INLINE void * my_atomic_loadptr(void * volatile *a) { return (*a); } @@ -124,6 +147,9 @@ my_atomic_store16(int16 volatile *a, int16 v) { *a = v; } STATIC_INLINE void my_atomic_store32(int32 volatile *a, int32 v) { *a = v; } +STATIC_INLINE void +my_atomic_store64(int64 volatile *a, int64 v) { *a = v; } + STATIC_INLINE void my_atomic_storeptr(void * volatile *a, void *v) { *a = v; } @@ -149,6 +175,12 @@ my_atomic_load32(int32 volatile *a) return ((int32) atomic_or_32_nv((volatile uint32_t *)a, 0)); } +STATIC_INLINE int64 +my_atomic_load64(int64 volatile *a) +{ + return ((int64) atomic_or_64_nv((volatile uint64_t *)a, 0)); +} + STATIC_INLINE void * my_atomic_loadptr(void * volatile *a) { @@ -175,6 +207,12 @@ my_atomic_store32(int32 volatile *a, int32 v) (void) atomic_swap_32((volatile uint32_t *)a, (uint32_t)v); } +STATIC_INLINE void +my_atomic_store64(int64 volatile *a, int64 v) +{ + (void) atomic_swap_64((volatile uint64_t *)a, (uint64_t)v); +} + STATIC_INLINE void my_atomic_storeptr(void * volatile *a, void *v) { @@ -203,6 +241,12 @@ my_atomic_fas32(int32 volatile *a, int32 v) return ((int32) atomic_swap_32((volatile uint32_t *)a, (uint32_t)v)); } +STATIC_INLINE int64 +my_atomic_fas64(int64 volatile *a, int64 v) +{ + return ((int64) atomic_swap_64((volatile uint64_t *)a, (uint64_t)v)); +} + STATIC_INLINE void * my_atomic_fasptr(void * volatile *a, void *v) { From 39ca1f0e1dfd81ece2aef759376ee8bf4ebd41b0 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Fri, 18 Dec 2009 11:15:21 +0100 Subject: [PATCH 091/104] Fixed Solaris Atomics build issues --- configure.in | 8 +++----- include/atomic/nolock.h | 3 ++- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/configure.in b/configure.in index d4b01e238f6..5db4f034f0c 100644 --- a/configure.in +++ b/configure.in @@ -1922,9 +1922,9 @@ AC_CACHE_CHECK([whether the OS provides atomic_* functions like Solaris], [mysql_cv_solaris_atomic], [AC_RUN_IFELSE( [AC_LANG_PROGRAM( - [ + [[ #include - ] + ]], [[ int foo = -10; int bar = 10; int64_t foo64 = -10; int64_t bar64 = 10; @@ -1944,9 +1944,7 @@ AC_CACHE_CHECK([whether the OS provides atomic_* functions like Solaris], bar64 = atomic_cas_64((volatile uint64_t *)&bar64, (uint_t)foo64, 15); if (bar64) return -1; - foo64 = atomic_or_64((volatile uint64_t *)&bar64, 0); - if (foo64) - return -1; + atomic_or_64((volatile uint64_t *)&bar64, 0); return 0; ]] )], diff --git a/include/atomic/nolock.h b/include/atomic/nolock.h index e4cd9ab9896..b2eaea34095 100644 --- a/include/atomic/nolock.h +++ b/include/atomic/nolock.h @@ -17,7 +17,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #if defined(__i386__) || defined(_MSC_VER) || defined(__x86_64__) \ - || defined(HAVE_GCC_ATOMIC_BUILTINS) + || defined(HAVE_GCC_ATOMIC_BUILTINS) \ + || defined(HAVE_SOLARIS_ATOMIC) # ifdef MY_ATOMIC_MODE_DUMMY # define LOCK_prefix "" From 1ae71305508b3accac3406d567815a8dd4cabd11 Mon Sep 17 00:00:00 2001 From: Alfranio Correia Date: Fri, 18 Dec 2009 11:15:46 +0000 Subject: [PATCH 092/104] Post-merge fix after BUG##45292 Updated suppressed warning messages. --- mysql-test/suite/rpl/t/rpl_bug41902.test | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/rpl/t/rpl_bug41902.test b/mysql-test/suite/rpl/t/rpl_bug41902.test index 05f13bbc848..d16fb986cea 100644 --- a/mysql-test/suite/rpl/t/rpl_bug41902.test +++ b/mysql-test/suite/rpl/t/rpl_bug41902.test @@ -52,10 +52,10 @@ purge binary logs to 'master-bin.000001'; --disable_query_log call mtr.add_suppression("Failed to locate old binlog or relay log files"); -call mtr.add_suppression("MYSQL_LOG::purge_logs was called with file ./master-bin.000001 not listed in the index"); +call mtr.add_suppression("MYSQL_BIN_LOG::purge_logs was called with file ./master-bin.000001 not listed in the index"); connection slave; call mtr.add_suppression("Failed to locate old binlog or relay log files"); -call mtr.add_suppression("MYSQL_LOG::purge_logs was called with file ./master-bin.000001 not listed in the index"); +call mtr.add_suppression("MYSQL_BIN_LOG::purge_logs was called with file ./master-bin.000001 not listed in the index"); --enable_query_log --echo End of the tests From e378fa5be0881129100dadd36a172d2ed95e1617 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Fri, 18 Dec 2009 21:39:24 +0100 Subject: [PATCH 093/104] Bug #49811: inconsistent usage of SAFEMALLOC in debug compilation on windows Remove per-project SAFEMALLOCs definitions, as they result in malloc/free mismatches. --- plugin/semisync/CMakeLists.txt | 3 --- storage/innobase/CMakeLists.txt | 7 ------- 2 files changed, 10 deletions(-) diff --git a/plugin/semisync/CMakeLists.txt b/plugin/semisync/CMakeLists.txt index ad26298b0b7..cf8863e970f 100644 --- a/plugin/semisync/CMakeLists.txt +++ b/plugin/semisync/CMakeLists.txt @@ -15,9 +15,6 @@ # This is CMakeLists.txt for semi-sync replication plugins -SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") -SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") - # Add common include directories INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/zlib ${CMAKE_SOURCE_DIR}/sql diff --git a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt index d67b518642c..b63ed840f3c 100644 --- a/storage/innobase/CMakeLists.txt +++ b/storage/innobase/CMakeLists.txt @@ -15,13 +15,6 @@ # This is the CMakeLists for InnoDB Plugin - -# TODO: remove the two FLAGS_DEBUG settings when merging into -# 6.0-based trees, like is already the case for other engines in -# those trees. -SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") -SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") - # Starting at 5.1.38, MySQL CMake files are simplified. But the plugin # CMakeLists.txt still needs to work with previous versions of MySQL. IF (MYSQL_VERSION_ID GREATER "50137") From 763b01c9f1bbc5477351c02ee6f0378926ca47ff Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Sat, 19 Dec 2009 08:37:08 +0100 Subject: [PATCH 094/104] Post-merge fix: wait for statement result before disconnecting. Otherwise the statement might affect unrelated tests. mysql-test/t/lock_multi.test, Reap statement status --- mysql-test/t/lock_multi.test | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mysql-test/t/lock_multi.test b/mysql-test/t/lock_multi.test index 75ee6d07723..5670276ee2e 100644 --- a/mysql-test/t/lock_multi.test +++ b/mysql-test/t/lock_multi.test @@ -625,9 +625,11 @@ let $wait_condition= --source include/wait_condition.inc let $tlwb= `show status like 'Table_locks_waited'`; unlock tables; +connection waiter; +--reap +connection default; drop table t1; disconnect waiter; -connection default; --disable_query_log eval SET @tlwa= SUBSTRING_INDEX('$tlwa', ' ', -1); eval SET @tlwb= SUBSTRING_INDEX('$tlwb', ' ', -1); From 30390a5e95d1dd465eac5ff9c2249836815fcf0c Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Sat, 19 Dec 2009 08:46:37 +0100 Subject: [PATCH 095/104] Make choices of atomic implementation based on highest stability --- include/atomic/nolock.h | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/include/atomic/nolock.h b/include/atomic/nolock.h index b2eaea34095..f1eaf8c65ab 100644 --- a/include/atomic/nolock.h +++ b/include/atomic/nolock.h @@ -25,17 +25,29 @@ # else # define LOCK_prefix "lock" # endif - -# ifdef HAVE_GCC_ATOMIC_BUILTINS -# include "gcc_builtins.h" -# elif __GNUC__ -# include "x86-gcc.h" -# elif defined(_MSC_VER) +/* + We choose implementation as follows: + ------------------------------------ + On Windows using Visual C++ the native implementation should be + preferrable. When using gcc we prefer the native x86 implementation, + we prefer the Solaris implementation before the gcc because of + stability preference, we choose gcc implementation if nothing else + works on gcc. If neither Visual C++ or gcc we still choose the + Solaris implementation on Solaris (mainly for SunStudio compiles. +*/ +# if defined(_MSV_VER) # include "generic-msvc.h" +# elif __GNUC__ +# if defined(__i386__) || defined(__x86_64__) +# include "x86-gcc.h" +# elif defined(HAVE_SOLARIS_ATOMIC) +# include "solaris.h" +# elif defined(HAVE_GCC_ATOMIC_BUILTINS) +# include "gcc_builtins.h" +# endif +# elif defined(HAVE_SOLARIS_ATOMIC) +# include "solaris.h" # endif -#elif defined(HAVE_SOLARIS_ATOMIC) -#include "solaris.h" -#endif #if defined(make_atomic_cas_body) || defined(MY_ATOMICS_MADE) /* From 2e72189535e3be76c82c58aa2164990674b08216 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Sat, 19 Dec 2009 08:54:05 +0100 Subject: [PATCH 096/104] Increase probability of correct atomics implementation by choosing stable implementations first --- include/atomic/nolock.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/atomic/nolock.h b/include/atomic/nolock.h index f1eaf8c65ab..9ec5eb5a2fd 100644 --- a/include/atomic/nolock.h +++ b/include/atomic/nolock.h @@ -48,6 +48,7 @@ # elif defined(HAVE_SOLARIS_ATOMIC) # include "solaris.h" # endif +#endif #if defined(make_atomic_cas_body) || defined(MY_ATOMICS_MADE) /* From 56d81f3bc1fda0180a4e99b4b4cb45e8deb3355e Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Sat, 19 Dec 2009 12:48:39 +0100 Subject: [PATCH 097/104] Fixed solaris builds --- include/my_atomic.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/my_atomic.h b/include/my_atomic.h index 23c3dc749ab..fbeacb66e1d 100644 --- a/include/my_atomic.h +++ b/include/my_atomic.h @@ -69,8 +69,16 @@ #endif #ifndef make_atomic_cas_body +/* + When implementing atomics using solaris.h we will end up here. + In this case we have already implemented all atomic functions + and no more work is needed, this is indicated by MY_ATOMICS_MADE + being defined but not make_atomic_cas_body. +*/ +#ifndef MY_ATOMICS_MADE /* nolock.h was not able to generate even a CAS function, fall back */ #include "atomic/rwlock.h" +#endif #else /* define missing functions by using the already generated ones */ #ifndef make_atomic_add_body From 18a30d093373611b2c16790ecc99d932712df4f4 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Sat, 19 Dec 2009 13:26:00 +0100 Subject: [PATCH 098/104] Post-merge fix: wait for statement result before disconnecting. Otherwise the statement might affect unrelated tests. mysql-test/t/lock_multi.test, Reap statement status --- mysql-test/t/lock_multi.test | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mysql-test/t/lock_multi.test b/mysql-test/t/lock_multi.test index 47b5aa0292b..4df1a0f3478 100644 --- a/mysql-test/t/lock_multi.test +++ b/mysql-test/t/lock_multi.test @@ -626,9 +626,11 @@ let $wait_condition= --source include/wait_condition.inc let $tlwb= `show status like 'Table_locks_waited'`; unlock tables; +connection waiter; +--reap +connection default; drop table t1; disconnect waiter; -connection default; --disable_query_log eval SET @tlwa= SUBSTRING_INDEX('$tlwa', ' ', -1); eval SET @tlwb= SUBSTRING_INDEX('$tlwb', ' ', -1); From 1a6d85eab62d08af7021bc424bef4eb260e3137d Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Sat, 19 Dec 2009 17:44:45 +0100 Subject: [PATCH 099/104] Fixed Solaris build issues --- include/my_atomic.h | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/include/my_atomic.h b/include/my_atomic.h index fbeacb66e1d..f0d193c2528 100644 --- a/include/my_atomic.h +++ b/include/my_atomic.h @@ -68,18 +68,12 @@ #include "atomic/nolock.h" #endif -#ifndef make_atomic_cas_body -/* - When implementing atomics using solaris.h we will end up here. - In this case we have already implemented all atomic functions - and no more work is needed, this is indicated by MY_ATOMICS_MADE - being defined but not make_atomic_cas_body. -*/ -#ifndef MY_ATOMICS_MADE +#ifndef MY_ATOMIC_NOLOCK /* nolock.h was not able to generate even a CAS function, fall back */ #include "atomic/rwlock.h" #endif -#else + +#ifndef MY_ATOMICS_MADE /* define missing functions by using the already generated ones */ #ifndef make_atomic_add_body #define make_atomic_add_body(S) \ @@ -102,7 +96,6 @@ #define make_atomic_store_body(S) \ (void)(my_atomic_fas ## S (a, v)); #endif -#endif /* transparent_union doesn't work in g++ @@ -295,6 +288,7 @@ make_atomic_store(ptr) #undef make_atomic_store_body #undef make_atomic_fas_body #undef intptr +#endif /* the macro below defines (as an expression) the code that From 5bce1e06429c3d58457051f0c439f130609df375 Mon Sep 17 00:00:00 2001 From: Mikael Ronstrom Date: Sat, 19 Dec 2009 18:24:52 +0100 Subject: [PATCH 100/104] Yet one more fix for Solaris atomics in builds --- include/my_atomic.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/my_atomic.h b/include/my_atomic.h index f0d193c2528..751afcb77db 100644 --- a/include/my_atomic.h +++ b/include/my_atomic.h @@ -287,8 +287,8 @@ make_atomic_store(ptr) #undef make_atomic_load_body #undef make_atomic_store_body #undef make_atomic_fas_body -#undef intptr #endif +#undef intptr /* the macro below defines (as an expression) the code that From e3976aa9ae7f91fb08c8d61801631c9af821f6b1 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Sun, 20 Dec 2009 21:20:11 +0000 Subject: [PATCH 101/104] Fix inconsistently defined THR_LOCK_myisam_mmap It was pthread_mutex_t in mi_static.c and mysql_mutex_t in my_thr_init.c Solaris linker complains about different size of the symbol. Fix : use mysql_mutex_t everywhere. --- include/myisam.h | 2 +- storage/myisam/mi_packrec.c | 16 ++++++++-------- storage/myisam/mi_static.c | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/myisam.h b/include/myisam.h index e9d1e4ab43e..e6404cb5405 100644 --- a/include/myisam.h +++ b/include/myisam.h @@ -260,7 +260,7 @@ extern ulong myisam_bulk_insert_tree_size, myisam_data_pointer_size; /* which is normally forbidden */ extern int (*myisam_test_invalid_symlink)(const char *filename); extern ulonglong myisam_mmap_size, myisam_mmap_used; -extern pthread_mutex_t THR_LOCK_myisam_mmap; +extern mysql_mutex_t THR_LOCK_myisam_mmap; /* Prototypes for myisam-functions */ diff --git a/storage/myisam/mi_packrec.c b/storage/myisam/mi_packrec.c index b3a6bf78566..580c58e6ea1 100644 --- a/storage/myisam/mi_packrec.c +++ b/storage/myisam/mi_packrec.c @@ -1502,11 +1502,11 @@ my_bool _mi_memmap_file(MI_INFO *info) if (myisam_mmap_size != SIZE_T_MAX) { - pthread_mutex_lock(&THR_LOCK_myisam_mmap); + mysql_mutex_lock(&THR_LOCK_myisam_mmap); eom= data_file_length > myisam_mmap_size - myisam_mmap_used - MEMMAP_EXTRA_MARGIN; if (!eom) myisam_mmap_used+= data_file_length + MEMMAP_EXTRA_MARGIN; - pthread_mutex_unlock(&THR_LOCK_myisam_mmap); + mysql_mutex_unlock(&THR_LOCK_myisam_mmap); } else eom= data_file_length > myisam_mmap_size - MEMMAP_EXTRA_MARGIN; @@ -1522,9 +1522,9 @@ my_bool _mi_memmap_file(MI_INFO *info) DBUG_PRINT("warning",("File isn't extended for memmap")); if (myisam_mmap_size != SIZE_T_MAX) { - pthread_mutex_lock(&THR_LOCK_myisam_mmap); + mysql_mutex_lock(&THR_LOCK_myisam_mmap); myisam_mmap_used-= data_file_length + MEMMAP_EXTRA_MARGIN; - pthread_mutex_unlock(&THR_LOCK_myisam_mmap); + mysql_mutex_unlock(&THR_LOCK_myisam_mmap); } DBUG_RETURN(0); } @@ -1534,9 +1534,9 @@ my_bool _mi_memmap_file(MI_INFO *info) { if (myisam_mmap_size != SIZE_T_MAX) { - pthread_mutex_lock(&THR_LOCK_myisam_mmap); + mysql_mutex_lock(&THR_LOCK_myisam_mmap); myisam_mmap_used-= data_file_length + MEMMAP_EXTRA_MARGIN; - pthread_mutex_unlock(&THR_LOCK_myisam_mmap); + mysql_mutex_unlock(&THR_LOCK_myisam_mmap); } DBUG_RETURN(0); } @@ -1555,9 +1555,9 @@ void _mi_unmap_file(MI_INFO *info) if (myisam_mmap_size != SIZE_T_MAX) { - pthread_mutex_lock(&THR_LOCK_myisam_mmap); + mysql_mutex_lock(&THR_LOCK_myisam_mmap); myisam_mmap_used-= info->s->mmaped_length + MEMMAP_EXTRA_MARGIN; - pthread_mutex_unlock(&THR_LOCK_myisam_mmap); + mysql_mutex_unlock(&THR_LOCK_myisam_mmap); } } diff --git a/storage/myisam/mi_static.c b/storage/myisam/mi_static.c index b763308a4a9..85a3124cba9 100644 --- a/storage/myisam/mi_static.c +++ b/storage/myisam/mi_static.c @@ -41,7 +41,7 @@ my_off_t myisam_max_temp_length= MAX_FILE_SIZE; ulong myisam_bulk_insert_tree_size=8192*1024; ulong myisam_data_pointer_size=4; ulonglong myisam_mmap_size= SIZE_T_MAX, myisam_mmap_used= 0; -pthread_mutex_t THR_LOCK_myisam_mmap; +mysql_mutex_t THR_LOCK_myisam_mmap; static int always_valid(const char *filename __attribute__((unused))) { From 858cf5555ce7e9468d006905a67f8b908e57dd87 Mon Sep 17 00:00:00 2001 From: Alexander Nozdrin Date: Mon, 21 Dec 2009 13:20:43 +0300 Subject: [PATCH 102/104] Disable plugin_load.test due to Bug#42144. --- mysql-test/collections/default.experimental | 1 - mysql-test/t/disabled.def | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/collections/default.experimental b/mysql-test/collections/default.experimental index 7f5faa23c1b..52422f5d140 100644 --- a/mysql-test/collections/default.experimental +++ b/mysql-test/collections/default.experimental @@ -12,7 +12,6 @@ main.lock_multi_bug38499 # Bug#47448 2009-09-19 alik main.lock_m main.lock_multi_bug38691 @solaris # Bug#47792 2009-10-02 alik main.lock_multi_bug38691 times out sporadically on Solaris 10 main.log_tables # Bug#47924 2009-10-08 alik main.log_tables times out sporadically main.plugin # Bug#47146 Linking problem with example plugin when dtrace enabled -main.plugin_load # Bug#47146 rpl.rpl_get_master_version_and_clock* # Bug#49191 2009-12-01 Daogang rpl_get_master_version_and_clock failed on PB2: COM_REGISTER_SLAVE failed rpl.rpl_heartbeat_basic # BUG#43828 2009-10-22 luis fails sporadically diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 3d9dc72ee45..97237d5da73 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -13,3 +13,4 @@ kill : Bug#37780 2008-12-03 HHunger need some changes to be query_cache_28249 : Bug#43861 2009-03-25 main.query_cache_28249 fails sporadicallyr innodb-autoinc : Bug#49267 2009-12-02 test fails on windows because of different case mode innodb : Bug#49396 2009-12-03 test fails in embedded mode +plugin_load : Bug#42144 2009-12-21 alik plugin_load fails From 4309b204029c7657343aa5dd9d57dcef14182309 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Mon, 21 Dec 2009 11:38:31 +0100 Subject: [PATCH 103/104] Bug#48737: Partitions: search fails with ucs2 Recommit of patch: http://lists.mysql.com/commits/91400 Test case only (code part was pushes as bug-49028) --- mysql-test/r/partition_column.result | 24 ++++++++++++++++++++++++ mysql-test/t/partition_column.test | 17 +++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/mysql-test/r/partition_column.result b/mysql-test/r/partition_column.result index a64ca8e405d..ddc48b635cf 100644 --- a/mysql-test/r/partition_column.result +++ b/mysql-test/r/partition_column.result @@ -9,6 +9,30 @@ partition by range columns (a,b,c) ( partition p0 values less than (1, maxvalue, 10), partition p1 values less than (1, maxvalue, maxvalue)); ERROR HY000: VALUES LESS THAN value must be strictly increasing for each partition +create table t1 (a varchar(5) character set ucs2 collate ucs2_bin) +partition by range columns (a) +(partition p0 values less than (0x0041)); +insert into t1 values (0x00410000); +select hex(a) from t1 where a like 'A_'; +hex(a) +00410000 +explain partitions select hex(a) from t1 where a like 'A_'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0 system NULL NULL NULL NULL 1 +alter table t1 remove partitioning; +select hex(a) from t1 where a like 'A_'; +hex(a) +00410000 +create index a on t1 (a); +select hex(a) from t1 where a like 'A_'; +hex(a) +00410000 +insert into t1 values ('A_'); +select hex(a) from t1; +hex(a) +00410000 +0041005F +drop table t1; create table t1 (a varchar(1) character set latin1 collate latin1_general_ci) partition by range columns(a) ( partition p0 values less than ('a'), diff --git a/mysql-test/t/partition_column.test b/mysql-test/t/partition_column.test index 9e47b94b036..a0e944ceb09 100644 --- a/mysql-test/t/partition_column.test +++ b/mysql-test/t/partition_column.test @@ -23,6 +23,23 @@ partition by range columns (a,b,c) ( partition p0 values less than (1, maxvalue, 10), partition p1 values less than (1, maxvalue, maxvalue)); +# +# BUG#48737, Search fails with ucs2 +# +create table t1 (a varchar(5) character set ucs2 collate ucs2_bin) +partition by range columns (a) +(partition p0 values less than (0x0041)); +insert into t1 values (0x00410000); +select hex(a) from t1 where a like 'A_'; +explain partitions select hex(a) from t1 where a like 'A_'; +alter table t1 remove partitioning; +select hex(a) from t1 where a like 'A_'; +create index a on t1 (a); +select hex(a) from t1 where a like 'A_'; +insert into t1 values ('A_'); +select hex(a) from t1; +drop table t1; + # # BUG#48161, Delivering too few records using collate syntax with partitions # From 9ce5872e038157e2a241d1b0726cbf56496fa5e1 Mon Sep 17 00:00:00 2001 From: Alexander Nozdrin Date: Mon, 21 Dec 2009 18:35:38 +0300 Subject: [PATCH 104/104] Fix default.conf. --- .bzr-mysql/default.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bzr-mysql/default.conf b/.bzr-mysql/default.conf index 08ca040642e..f33ccdf6753 100644 --- a/.bzr-mysql/default.conf +++ b/.bzr-mysql/default.conf @@ -1,4 +1,4 @@ [MYSQL] post_commit_to = "commits@lists.mysql.com" post_push_to = "commits@lists.mysql.com" -tree_name = "mysql-5.5-trunk-bugfixing" +tree_name = "mysql-5.5-trunk"