Merge from mysq-next-mr-wtf.

This commit is contained in:
Alexander Nozdrin 2009-10-02 16:14:59 +04:00
commit 8e0204fb58
83 changed files with 3769 additions and 1243 deletions

View File

@ -556,7 +556,7 @@ parse_package()
package="pro"
;;
extended )
package=""
package="extended"
;;
cge )
package="cge"

View File

@ -42,6 +42,13 @@ ADD_DEFINITIONS(-DSHAREDIR="share")
# Set debug options
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DFORCE_INIT_OF_VARS")
# Do not use SAFEMALLOC for Windows builds, as Debug CRT has the same functionality
# Neither SAFE_MUTEX works on Windows and it has been explicitely undefined in
# my_pthread.h
IF(NOT WIN32)
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
ENDIF(NOT WIN32)
SET(localstatedir "C:\\mysql\\data")
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/support-files/my-huge.cnf.sh
@ -55,9 +62,6 @@ CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/support-files/my-medium.cnf.sh
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/support-files/my-small.cnf.sh
${CMAKE_SOURCE_DIR}/support-files/my-small.ini @ONLY)
ADD_DEFINITIONS(-D__NT__)
IF(CYBOZU)
ADD_DEFINITIONS(-DCYBOZU)
ENDIF(CYBOZU)

View File

@ -14,13 +14,6 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
INCLUDE("${PROJECT_SOURCE_DIR}/win/mysql_manifest.cmake")
# We use the "mysqlclient_notls" library here just as safety, in case
# any of the clients here would go beyond the client API and access the
# Thread Local Storage directly.
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/zlib
${CMAKE_SOURCE_DIR}/extra/yassl/include
@ -30,27 +23,27 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/strings)
ADD_EXECUTABLE(mysql completion_hash.cc mysql.cc readline.cc sql_string.cc ../mysys/my_conio.c)
TARGET_LINK_LIBRARIES(mysql mysqlclient_notls wsock32)
TARGET_LINK_LIBRARIES(mysql mysqlclient)
ADD_EXECUTABLE(mysqltest mysqltest.cc)
SET_SOURCE_FILES_PROPERTIES(mysqltest.cc PROPERTIES COMPILE_FLAGS "-DTHREADS")
TARGET_LINK_LIBRARIES(mysqltest mysqlclient mysys regex wsock32 dbug)
TARGET_LINK_LIBRARIES(mysqltest mysqlclient mysys regex dbug)
ADD_EXECUTABLE(mysqlcheck mysqlcheck.c)
TARGET_LINK_LIBRARIES(mysqlcheck mysqlclient_notls wsock32)
TARGET_LINK_LIBRARIES(mysqlcheck mysqlclient)
ADD_EXECUTABLE(mysqldump mysqldump.c ../sql-common/my_user.c ../mysys/mf_getdate.c)
TARGET_LINK_LIBRARIES(mysqldump mysqlclient_notls wsock32)
TARGET_LINK_LIBRARIES(mysqldump mysqlclient)
ADD_EXECUTABLE(mysqlimport mysqlimport.c)
TARGET_LINK_LIBRARIES(mysqlimport mysqlclient_notls wsock32)
TARGET_LINK_LIBRARIES(mysqlimport mysqlclient)
ADD_EXECUTABLE(mysql_upgrade mysql_upgrade.c ../mysys/my_getpagesize.c)
TARGET_LINK_LIBRARIES(mysql_upgrade mysqlclient_notls wsock32)
TARGET_LINK_LIBRARIES(mysql_upgrade mysqlclient)
ADD_DEPENDENCIES(mysql_upgrade GenFixPrivs)
ADD_EXECUTABLE(mysqlshow mysqlshow.c)
TARGET_LINK_LIBRARIES(mysqlshow mysqlclient_notls wsock32)
TARGET_LINK_LIBRARIES(mysqlshow mysqlclient)
ADD_EXECUTABLE(mysqlbinlog mysqlbinlog.cc
../mysys/mf_tempdir.c
@ -59,14 +52,14 @@ ADD_EXECUTABLE(mysqlbinlog mysqlbinlog.cc
../mysys/my_bitmap.c
../mysys/my_vle.c
../mysys/base64.c)
TARGET_LINK_LIBRARIES(mysqlbinlog mysqlclient_notls wsock32)
TARGET_LINK_LIBRARIES(mysqlbinlog mysqlclient)
ADD_EXECUTABLE(mysqladmin mysqladmin.cc)
TARGET_LINK_LIBRARIES(mysqladmin mysqlclient_notls wsock32)
TARGET_LINK_LIBRARIES(mysqladmin mysqlclient)
ADD_EXECUTABLE(mysqlslap mysqlslap.c)
SET_SOURCE_FILES_PROPERTIES(mysqlslap.c PROPERTIES COMPILE_FLAGS "-DTHREADS")
TARGET_LINK_LIBRARIES(mysqlslap mysqlclient mysys zlib wsock32 dbug)
TARGET_LINK_LIBRARIES(mysqlslap mysqlclient mysys zlib dbug)
ADD_EXECUTABLE(echo echo.c)

View File

@ -18,7 +18,6 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/dbug)
SET(DBUG_SOURCES dbug.c factorial.c sanity.c)
IF(NOT SOURCE_SUBLIBS)
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
ADD_LIBRARY(dbug ${DBUG_SOURCES})
ENDIF(NOT SOURCE_SUBLIBS)

View File

@ -14,13 +14,11 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
INCLUDE("${PROJECT_SOURCE_DIR}/win/mysql_manifest.cmake")
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
ADD_EXECUTABLE(comp_err comp_err.c)
TARGET_LINK_LIBRARIES(comp_err debug dbug mysys strings zlib wsock32)
TARGET_LINK_LIBRARIES(comp_err dbug mysys strings zlib)
GET_TARGET_PROPERTY(COMP_ERR_EXE comp_err LOCATION)
@ -39,16 +37,16 @@ ADD_CUSTOM_TARGET(GenError
DEPENDS ${PROJECT_SOURCE_DIR}/include/mysqld_error.h)
ADD_EXECUTABLE(my_print_defaults my_print_defaults.c)
TARGET_LINK_LIBRARIES(my_print_defaults strings mysys debug dbug taocrypt wsock32)
TARGET_LINK_LIBRARIES(my_print_defaults strings mysys dbug taocrypt)
ADD_EXECUTABLE(perror perror.c)
TARGET_LINK_LIBRARIES(perror strings mysys debug dbug wsock32)
TARGET_LINK_LIBRARIES(perror strings mysys dbug)
ADD_EXECUTABLE(resolveip resolveip.c)
TARGET_LINK_LIBRARIES(resolveip strings mysys debug dbug wsock32)
TARGET_LINK_LIBRARIES(resolveip strings mysys dbug)
ADD_EXECUTABLE(replace replace.c)
TARGET_LINK_LIBRARIES(replace strings mysys debug dbug wsock32)
TARGET_LINK_LIBRARIES(replace strings mysys dbug)
IF(EMBED_MANIFESTS)
MYSQL_EMBED_MANIFEST("myTest" "asInvoker")

View File

@ -27,6 +27,9 @@
#include <fcntl.h>
#include <io.h>
#include <malloc.h>
#include <sys/stat.h>
#include <process.h> /* getpid()*/
#define HAVE_SMEM 1
@ -174,7 +177,7 @@ typedef uint rf_SetTimer;
#define SIZEOF_CHARP 4
#endif
#define HAVE_BROKEN_NETINET_INCLUDES
#ifdef __NT__
#ifdef _WIN32
#define HAVE_NAMED_PIPE /* We can only create pipes on NT */
#endif
@ -287,11 +290,6 @@ inline ulonglong double2ulonglong(double d)
#define strcasecmp stricmp
#define strncasecmp strnicmp
#ifndef __NT__
#undef FILE_SHARE_DELETE
#define FILE_SHARE_DELETE 0 /* Not implemented on Win 98/ME */
#endif
#ifdef NOT_USED
#define HAVE_SNPRINTF /* Gave link error */
#define _snprintf snprintf
@ -341,7 +339,7 @@ inline ulonglong double2ulonglong(double d)
#define thread_safe_increment(V,L) InterlockedIncrement((long*) &(V))
#define thread_safe_decrement(V,L) InterlockedDecrement((long*) &(V))
/* The following is only used for statistics, so it should be good enough */
#ifdef __NT__ /* This should also work on Win98 but .. */
#ifdef _WIN32
#define thread_safe_add(V,C,L) InterlockedExchangeAdd((long*) &(V),(C))
#define thread_safe_sub(V,C,L) InterlockedExchangeAdd((long*) &(V),-(long) (C))
#endif

View File

@ -31,7 +31,7 @@ extern "C" {
#if defined(__WIN__)
typedef CRITICAL_SECTION pthread_mutex_t;
typedef HANDLE pthread_t;
typedef DWORD pthread_t;
typedef struct thread_attr {
DWORD dwStackSize ;
DWORD dwCreatingFlag ;
@ -64,8 +64,7 @@ typedef struct {
typedef int pthread_mutexattr_t;
#define win_pthread_self my_thread_var->pthread_self
#define pthread_self() win_pthread_self
#define pthread_self() GetCurrentThreadId()
#define pthread_handler_t EXTERNC void * __cdecl
typedef void * (__cdecl *pthread_handler)(void *);
@ -99,8 +98,7 @@ struct timespec {
(ABSTIME).max_timeout_msec= (long)((NSEC)/1000000); \
}
void win_pthread_init(void);
int win_pthread_setspecific(void *A,void *B,uint length);
int win_pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_create(pthread_t *,pthread_attr_t *,pthread_handler,void *);
int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);
@ -117,42 +115,25 @@ int pthread_attr_destroy(pthread_attr_t *connect_att);
struct tm *localtime_r(const time_t *timep,struct tm *tmp);
struct tm *gmtime_r(const time_t *timep,struct tm *tmp);
void pthread_exit(void *a);
int pthread_join(pthread_t thread, void **value_ptr);
void pthread_exit(void *a); /* was #define pthread_exit(A) ExitThread(A)*/
#define ETIMEDOUT 145 /* Win32 doesn't have this */
#define getpid() GetCurrentThreadId()
#define HAVE_LOCALTIME_R 1
#define _REENTRANT 1
#define HAVE_PTHREAD_ATTR_SETSTACKSIZE 1
/*
Windows has two ways to use thread local storage. The most efficient
is using __declspec(thread), but that does not work properly when
used in a .dll that is loaded at runtime, after program load. So for
libmysql.dll and libmysqld.dll we define USE_TLS in order to use the
TlsXxx() API instead, which works in all cases.
*/
#ifdef USE_TLS /* For LIBMYSQL.DLL */
#undef SAFE_MUTEX /* This will cause conflicts */
#define pthread_key(T,V) DWORD V
#define pthread_key_create(A,B) ((*A=TlsAlloc())==0xFFFFFFFF)
#define pthread_key_delete(A) TlsFree(A)
#define my_pthread_setspecific_ptr(T,V) (!TlsSetValue((T),(V)))
#define pthread_setspecific(A,B) (!TlsSetValue((A),(B)))
#define pthread_getspecific(A) (TlsGetValue(A))
#define my_pthread_getspecific(T,A) ((T) TlsGetValue(A))
#define my_pthread_getspecific_ptr(T,V) ((T) TlsGetValue(V))
#define my_pthread_setspecific_ptr(T,V) (!TlsSetValue((T),(V)))
#define pthread_setspecific(A,B) (!TlsSetValue((A),(B)))
#else
#define pthread_key(T,V) __declspec(thread) T V
#define pthread_key_create(A,B) pthread_dummy(0)
#define pthread_key_delete(A) pthread_dummy(0)
#define pthread_getspecific(A) (&(A))
#define my_pthread_getspecific(T,A) (&(A))
#define my_pthread_getspecific_ptr(T,V) (V)
#define my_pthread_setspecific_ptr(T,V) ((T)=(V),0)
#define pthread_setspecific(A,B) win_pthread_setspecific(&(A),(B),sizeof(A))
#endif /* USE_TLS */
#define pthread_equal(A,B) ((A) == (B))
#define pthread_mutex_init(A,B) (InitializeCriticalSection(A),0)
@ -163,7 +144,6 @@ void pthread_exit(void *a); /* was #define pthread_exit(A) ExitThread(A)*/
#define my_pthread_setprio(A,B) SetThreadPriority(GetCurrentThread(), (B))
#define pthread_kill(A,B) pthread_dummy((A) ? 0 : ESRCH)
#define pthread_join(A,B) (WaitForSingleObject((A), INFINITE) != WAIT_OBJECT_0)
/* Dummy defines for easier code */
#define pthread_attr_setdetachstate(A,B) pthread_dummy(0)

View File

@ -640,7 +640,7 @@ extern int my_access(const char *path, int amode);
extern int check_if_legal_filename(const char *path);
extern int check_if_legal_tablename(const char *path);
#if defined(__WIN__) && defined(__NT__)
#ifdef _WIN32
extern int nt_share_delete(const char *name,myf MyFlags);
#define my_delete_allow_opened(fname,flags) nt_share_delete((fname),(flags))
#else

View File

@ -14,8 +14,6 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
INCLUDE("${PROJECT_SOURCE_DIR}/win/mysql_manifest.cmake")
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
# Note that we don't link with the libraries "strings" or "mysys"
# here, instead we recompile the files needed and include them
@ -100,31 +98,15 @@ SET(CLIENT_SOURCES ../mysys/array.c ../strings/bchange.c ../strings/bmove.c
../vio/viossl.c ../vio/viosslfactories.c ../strings/xml.c ../mysys/mf_qsort.c
../mysys/my_getsystime.c ../mysys/my_sync.c ../mysys/my_winerr.c ../mysys/my_winfile.c ${LIB_SOURCES})
# Need to set USE_TLS for building the DLL, since __declspec(thread)
# approach to thread local storage does not work properly in DLLs.
#
# The static library might be used to form another DLL, as is the case
# with the ODBC driver, so it has to be compiled with USE_TLS as well.
#
# We create a third library without USE_TLS for internal use. We can't
# be sure that some client application part of this build doesn't go
# beond the documented API, and try access the Thread Local Storage.
# The "_notls" means no Tls*() functions used, i.e. "static" TLS.
ADD_LIBRARY(mysqlclient STATIC ${CLIENT_SOURCES})
ADD_DEPENDENCIES(mysqlclient GenError)
TARGET_LINK_LIBRARIES(mysqlclient)
ADD_LIBRARY(mysqlclient_notls STATIC ${CLIENT_SOURCES})
ADD_DEPENDENCIES(mysqlclient_notls GenError)
TARGET_LINK_LIBRARIES(mysqlclient_notls)
ADD_LIBRARY(libmysql SHARED ${CLIENT_SOURCES} dll.c libmysql.def)
IF(WIN32)
SET_TARGET_PROPERTIES(libmysql mysqlclient PROPERTIES COMPILE_FLAGS "-DUSE_TLS")
ENDIF(WIN32)
ADD_DEPENDENCIES(libmysql GenError)
TARGET_LINK_LIBRARIES(libmysql wsock32)
TARGET_LINK_LIBRARIES(libmysql)
IF(EMBED_MANIFESTS)
MYSQL_EMBED_MANIFEST("myTest" "asInvoker")

View File

@ -13,15 +13,6 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
# Need to set USE_TLS, since __declspec(thread) approach to thread local
# storage does not work properly in DLLs.
IF(WIN32)
ADD_DEFINITIONS(-DUSE_TLS)
ENDIF(WIN32)
ADD_DEFINITIONS(-DMYSQL_SERVER -DEMBEDDED_LIBRARY -DHAVE_DLOPEN)
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include
@ -139,7 +130,7 @@ SET(LIBMYSQLD_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
../sql/time.cc ../sql/tztime.cc ../sql/uniques.cc ../sql/unireg.cc
../sql/partition_info.cc ../sql/sql_connect.cc
../sql/scheduler.cc ../sql/event_parse_data.cc
./sql/sql_signal.cc
../sql/sql_signal.cc
${GEN_SOURCES}
${LIB_SOURCES})

View File

@ -20,9 +20,6 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/extra/yassl/include)
# Currently does not work with DBUG, there are missing symbols reported.
IF(WIN32)
ADD_DEFINITIONS(-DUSE_TLS)
ENDIF(WIN32)
ADD_DEFINITIONS(-DEMBEDDED_LIBRARY)

View File

@ -5085,7 +5085,6 @@ sub valgrind_arguments {
else
{
mtr_add_arg($args, "--tool=memcheck"); # From >= 2.1.2 needs this option
mtr_add_arg($args, "--alignment=8");
mtr_add_arg($args, "--leak-check=yes");
mtr_add_arg($args, "--num-callers=16");
mtr_add_arg($args, "--suppressions=%s/valgrind.supp", $glob_mysql_test_dir)

View File

@ -5,7 +5,7 @@ count(distinct n)
100
explain extended select count(distinct n) from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 index NULL n 4 NULL 200 100.00 Using index
1 SIMPLE t1 range NULL n 4 NULL 10 100.00 Using index for group-by
Warnings:
Note 1003 select count(distinct `test`.`t1`.`n`) AS `count(distinct n)` from `test`.`t1`
drop table t1;

View File

@ -1800,23 +1800,23 @@ b
a
explain select count(distinct a1,a2,b) from t1 where (a2 >= 'b') and (b = 'a');
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL idx_t1_2 147 NULL 128 Using where; Using index
1 SIMPLE t1 range NULL idx_t1_1 147 NULL 17 Using where; Using index for group-by
explain select count(distinct a1,a2,b,c) from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121');
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL idx_t1_1 163 NULL 128 Using where; Using index
1 SIMPLE t1 range NULL idx_t1_1 163 NULL 65 Using where; Using index for group-by (scanning)
explain extended select count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 index idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 147 NULL 128 75.00 Using where; Using index
1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 14 100.00 Using where; Using index for group-by
Warnings:
Note 1003 select count(distinct `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`) AS `count(distinct a1,a2,b)` from `test`.`t1` where ((`test`.`t1`.`b` = 'c') and (`test`.`t1`.`a1` > 'a') and (`test`.`t1`.`a2` > 'a'))
explain select count(distinct b) from t1 where (a2 >= 'b') and (b = 'a');
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL idx_t1_2 147 NULL 128 Using where; Using index
explain extended select ord(a1) + count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a');
explain extended select 98 + count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 index idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 147 NULL 128 75.00 Using where; Using index
1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 14 100.00 Using where; Using index for group-by
Warnings:
Note 1003 select (ord(`test`.`t1`.`a1`) + count(distinct `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`)) AS `ord(a1) + count(distinct a1,a2,b)` from `test`.`t1` where ((`test`.`t1`.`a1` > 'a') and (`test`.`t1`.`a2` > 'a'))
Note 1003 select (98 + count(distinct `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`)) AS `98 + count(distinct a1,a2,b)` from `test`.`t1` where ((`test`.`t1`.`a1` > 'a') and (`test`.`t1`.`a2` > 'a'))
select count(distinct a1,a2,b) from t1 where (a2 >= 'b') and (b = 'a');
count(distinct a1,a2,b)
4
@ -1829,8 +1829,8 @@ count(distinct a1,a2,b)
select count(distinct b) from t1 where (a2 >= 'b') and (b = 'a');
count(distinct b)
1
select ord(a1) + count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a');
ord(a1) + count(distinct a1,a2,b)
select 98 + count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a');
98 + count(distinct a1,a2,b)
104
explain select a1,a2,b, concat(min(c), max(c)) from t1 where a1 < 'd' group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
@ -2514,3 +2514,257 @@ a MAX(b)
2 1
DROP TABLE t;
End of 5.1 tests
#
# WL#3220 (Loose index scan for COUNT DISTINCT)
#
CREATE TABLE t1 (a INT, b INT, c INT, KEY (a,b));
INSERT INTO t1 VALUES (1,1,1), (1,2,1), (1,3,1), (1,4,1);
INSERT INTO t1 SELECT a, b + 4, 1 FROM t1;
INSERT INTO t1 SELECT a + 1, b, 1 FROM t1;
CREATE TABLE t2 (a INT, b INT, c INT, d INT, e INT, f INT, KEY (a,b,c));
INSERT INTO t2 VALUES (1,1,1,1,1,1), (1,2,1,1,1,1), (1,3,1,1,1,1),
(1,4,1,1,1,1);
INSERT INTO t2 SELECT a, b + 4, c,d,e,f FROM t2;
INSERT INTO t2 SELECT a + 1, b, c,d,e,f FROM t2;
EXPLAIN SELECT COUNT(DISTINCT a) FROM t1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range NULL a 5 NULL 9 Using index for group-by
SELECT COUNT(DISTINCT a) FROM t1;
COUNT(DISTINCT a)
2
EXPLAIN SELECT COUNT(DISTINCT a,b) FROM t1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range NULL a 10 NULL 9 Using index for group-by
SELECT COUNT(DISTINCT a,b) FROM t1;
COUNT(DISTINCT a,b)
16
EXPLAIN SELECT COUNT(DISTINCT b,a) FROM t1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range NULL a 10 NULL 9 Using index for group-by
SELECT COUNT(DISTINCT b,a) FROM t1;
COUNT(DISTINCT b,a)
16
EXPLAIN SELECT COUNT(DISTINCT b) FROM t1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL a 10 NULL 16 Using index
SELECT COUNT(DISTINCT b) FROM t1;
COUNT(DISTINCT b)
8
EXPLAIN SELECT COUNT(DISTINCT a) FROM t1 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range NULL a 5 NULL 9 Using index for group-by
SELECT COUNT(DISTINCT a) FROM t1 GROUP BY a;
COUNT(DISTINCT a)
1
1
EXPLAIN SELECT COUNT(DISTINCT b) FROM t1 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range NULL a 10 NULL 9 Using index for group-by
SELECT COUNT(DISTINCT b) FROM t1 GROUP BY a;
COUNT(DISTINCT b)
8
8
EXPLAIN SELECT COUNT(DISTINCT a) FROM t1 GROUP BY b;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL a 10 NULL 16 Using index; Using filesort
SELECT COUNT(DISTINCT a) FROM t1 GROUP BY b;
COUNT(DISTINCT a)
2
2
2
2
2
2
2
2
EXPLAIN SELECT DISTINCT COUNT(DISTINCT a) FROM t1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL a 10 NULL 16 Using index
SELECT DISTINCT COUNT(DISTINCT a) FROM t1;
COUNT(DISTINCT a)
2
EXPLAIN SELECT COUNT(DISTINCT a, b + 0) FROM t1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL a 10 NULL 16 Using index
SELECT COUNT(DISTINCT a, b + 0) FROM t1;
COUNT(DISTINCT a, b + 0)
16
EXPLAIN SELECT COUNT(DISTINCT a) FROM t1 HAVING COUNT(DISTINCT b) < 10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range NULL a 10 NULL 9 Using index for group-by
SELECT COUNT(DISTINCT a) FROM t1 HAVING COUNT(DISTINCT b) < 10;
COUNT(DISTINCT a)
EXPLAIN SELECT COUNT(DISTINCT a) FROM t1 HAVING COUNT(DISTINCT c) < 10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 16
SELECT COUNT(DISTINCT a) FROM t1 HAVING COUNT(DISTINCT c) < 10;
COUNT(DISTINCT a)
2
EXPLAIN SELECT 1 FROM t1 HAVING COUNT(DISTINCT a) < 10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range NULL a 5 NULL 9 Using index for group-by
SELECT 1 FROM t1 HAVING COUNT(DISTINCT a) < 10;
1
1
EXPLAIN SELECT 1 FROM t1 GROUP BY a HAVING COUNT(DISTINCT b) > 1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range NULL a 10 NULL 9 Using index for group-by
SELECT 1 FROM t1 GROUP BY a HAVING COUNT(DISTINCT b) > 1;
1
1
1
EXPLAIN SELECT COUNT(DISTINCT t1_1.a) FROM t1 t1_1, t1 t1_2 GROUP BY t1_1.a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1_1 index NULL a 10 NULL 16 Using index; Using temporary; Using filesort
1 SIMPLE t1_2 index NULL a 10 NULL 16 Using index; Using join buffer
SELECT COUNT(DISTINCT t1_1.a) FROM t1 t1_1, t1 t1_2 GROUP BY t1_1.a;
COUNT(DISTINCT t1_1.a)
1
1
EXPLAIN SELECT COUNT(DISTINCT a), 12 FROM t1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range NULL a 5 NULL 9 Using index for group-by
SELECT COUNT(DISTINCT a), 12 FROM t1;
COUNT(DISTINCT a) 12
2 12
EXPLAIN SELECT COUNT(DISTINCT a, b, c) FROM t2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range NULL a 15 NULL 9 Using index for group-by
SELECT COUNT(DISTINCT a, b, c) FROM t2;
COUNT(DISTINCT a, b, c)
16
EXPLAIN SELECT COUNT(DISTINCT a), SUM(DISTINCT a), AVG(DISTINCT a) FROM t2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range NULL a 5 NULL 9 Using index for group-by
SELECT COUNT(DISTINCT a), SUM(DISTINCT a), AVG(DISTINCT a) FROM t2;
COUNT(DISTINCT a) SUM(DISTINCT a) AVG(DISTINCT a)
2 3 1.5000
EXPLAIN SELECT COUNT(DISTINCT a), SUM(DISTINCT a), AVG(DISTINCT f) FROM t2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 16
SELECT COUNT(DISTINCT a), SUM(DISTINCT a), AVG(DISTINCT f) FROM t2;
COUNT(DISTINCT a) SUM(DISTINCT a) AVG(DISTINCT f)
2 3 1.0000
EXPLAIN SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, a) FROM t2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range NULL a 10 NULL 9 Using index for group-by
SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, a) FROM t2;
COUNT(DISTINCT a, b) COUNT(DISTINCT b, a)
16 16
EXPLAIN SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, f) FROM t2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 16
SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, f) FROM t2;
COUNT(DISTINCT a, b) COUNT(DISTINCT b, f)
16 8
EXPLAIN SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, d) FROM t2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 16
SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, d) FROM t2;
COUNT(DISTINCT a, b) COUNT(DISTINCT b, d)
16 8
EXPLAIN SELECT a, c, COUNT(DISTINCT c, a, b) FROM t2 GROUP BY a, b, c;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range NULL a 15 NULL 9 Using index for group-by
SELECT a, c, COUNT(DISTINCT c, a, b) FROM t2 GROUP BY a, b, c;
a c COUNT(DISTINCT c, a, b)
1 1 1
1 1 1
1 1 1
1 1 1
1 1 1
1 1 1
1 1 1
2 1 1
2 1 1
2 1 1
2 1 1
2 1 1
2 1 1
2 1 1
2 1 1
2 1 1
EXPLAIN SELECT COUNT(DISTINCT c, a, b) FROM t2
WHERE a > 5 AND b BETWEEN 10 AND 20 GROUP BY a, b, c;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range a a 15 NULL 1 Using where; Using index for group-by
SELECT COUNT(DISTINCT c, a, b) FROM t2
WHERE a > 5 AND b BETWEEN 10 AND 20 GROUP BY a, b, c;
COUNT(DISTINCT c, a, b)
EXPLAIN SELECT COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 WHERE a = 5
GROUP BY b;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ref a a 5 const 1 Using where; Using index
SELECT COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 WHERE a = 5
GROUP BY b;
COUNT(DISTINCT b) SUM(DISTINCT b)
EXPLAIN SELECT a, COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range NULL a 10 NULL 9 Using index for group-by
SELECT a, COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 GROUP BY a;
a COUNT(DISTINCT b) SUM(DISTINCT b)
2 8 36
2 8 36
EXPLAIN SELECT COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range NULL a 10 NULL 9 Using index for group-by
SELECT COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 GROUP BY a;
COUNT(DISTINCT b) SUM(DISTINCT b)
8 36
8 36
EXPLAIN SELECT COUNT(DISTINCT a, b) FROM t2 WHERE c = 13 AND d = 42;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 16 Using where
SELECT COUNT(DISTINCT a, b) FROM t2 WHERE c = 13 AND d = 42;
COUNT(DISTINCT a, b)
0
EXPLAIN SELECT a, COUNT(DISTINCT a), SUM(DISTINCT a) FROM t2
WHERE b = 13 AND c = 42 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range NULL a 15 NULL 9 Using where; Using index for group-by
SELECT a, COUNT(DISTINCT a), SUM(DISTINCT a) FROM t2
WHERE b = 13 AND c = 42 GROUP BY a;
a COUNT(DISTINCT a) SUM(DISTINCT a)
EXPLAIN SELECT COUNT(DISTINCT a, b), SUM(DISTINCT a) FROM t2 WHERE b = 42;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range NULL a 10 NULL 9 Using where; Using index for group-by
SELECT COUNT(DISTINCT a, b), SUM(DISTINCT a) FROM t2 WHERE b = 42;
COUNT(DISTINCT a, b) SUM(DISTINCT a)
0 NULL
EXPLAIN SELECT SUM(DISTINCT a), MAX(b) FROM t2 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range NULL a 5 NULL 9 Using index for group-by
SELECT SUM(DISTINCT a), MAX(b) FROM t2 GROUP BY a;
SUM(DISTINCT a) MAX(b)
1 8
2 8
EXPLAIN SELECT 42 * (a + c + COUNT(DISTINCT c, a, b)) FROM t2 GROUP BY a, b, c;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range NULL a 15 NULL 9 Using index for group-by
SELECT 42 * (a + c + COUNT(DISTINCT c, a, b)) FROM t2 GROUP BY a, b, c;
42 * (a + c + COUNT(DISTINCT c, a, b))
126
126
126
126
126
126
126
168
168
168
168
168
168
168
168
168
EXPLAIN SELECT (SUM(DISTINCT a) + MAX(b)) FROM t2 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range NULL a 5 NULL 9 Using index for group-by
SELECT (SUM(DISTINCT a) + MAX(b)) FROM t2 GROUP BY a;
(SUM(DISTINCT a) + MAX(b))
9
10
DROP TABLE t1,t2;
# end of WL#3220 tests

View File

@ -0,0 +1,18 @@
drop table if exists t1, t2, t3, t4;
create table t1 (a int)
partition by list (a)
(partition p1 values in (0));
alter table t1 truncate partition p1,p1;
ERROR HY000: Incorrect partition name
alter table t1 truncate partition p0;
ERROR HY000: Incorrect partition name
drop table t1;
create table t1 (a int)
partition by list (a)
subpartition by hash (a)
subpartitions 1
(partition p1 values in (1)
(subpartition sp1));
alter table t1 truncate partition sp1;
ERROR HY000: Incorrect partition name
drop table t1;

View File

@ -13,6 +13,7 @@
# part_optA-D Extra partitioning options (E.g. INDEX/DATA DIR) #
# #
# have_bug33158 NDB case insensitive create, but case sensitive rename #
# no_truncate No support for truncate partition #
#------------------------------------------------------------------------------#
# Original Author: mattiasj #
# Original Date: 2008-06-27 #
@ -518,6 +519,95 @@ DROP TABLE TableA;
}
# End of $can_only_key
if ($no_truncate)
{
--echo # Verify that TRUNCATE PARTITION gives error
eval CREATE TABLE t1
(a BIGINT AUTO_INCREMENT PRIMARY KEY,
b VARCHAR(255))
ENGINE = $engine
PARTITION BY KEY (a)
(PARTITION LT1000,
PARTITION LT2000,
PARTITION MAX);
INSERT INTO t1 VALUES (NULL, "First"), (NULL, "Second"), (999, "Last in LT1000"), (NULL, "First in LT2000"), (NULL, "Second in LT2000"), (1999, "Last in LT2000"), (NULL, "First in MAX"), (NULL, "Second in MAX");
--error ER_PARTITION_MGMT_ON_NONPARTITIONED, ER_ILLEGAL_HA
ALTER TABLE t1 TRUNCATE PARTITION MAX;
}
if (!$no_truncate)
{
--echo # Testing TRUNCATE PARTITION
eval CREATE TABLE t1
(a BIGINT AUTO_INCREMENT PRIMARY KEY,
b VARCHAR(255))
ENGINE = $engine
PARTITION BY RANGE (a)
(PARTITION LT1000 VALUES LESS THAN (1000),
PARTITION LT2000 VALUES LESS THAN (2000),
PARTITION MAX VALUES LESS THAN MAXVALUE);
INSERT INTO t1 VALUES (NULL, "First"), (NULL, "Second"), (999, "Last in LT1000"), (NULL, "First in LT2000"), (NULL, "Second in LT2000"), (1999, "Last in LT2000"), (NULL, "First in MAX"), (NULL, "Second in MAX");
SHOW CREATE TABLE t1;
SELECT * FROM t1 ORDER BY a;
ALTER TABLE t1 ANALYZE PARTITION MAX;
--echo # Truncate without FLUSH
ALTER TABLE t1 TRUNCATE PARTITION MAX;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (1)");
SELECT * FROM t1 WHERE a >= 2000;
--echo # Truncate with FLUSH after
ALTER TABLE t1 TRUNCATE PARTITION MAX;
FLUSH TABLES;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (2)");
SELECT * FROM t1 WHERE a >= 2000;
--echo # Truncate with FLUSH before
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION MAX;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (3)");
SELECT * FROM t1 WHERE a >= 2000;
--echo # Truncate with FLUSH after INSERT
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION MAX;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (4)");
SELECT * FROM t1 WHERE a >= 2000;
--echo # Truncate without FLUSH
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (1)");
SELECT * FROM t1 ORDER BY a;
--echo # Truncate with FLUSH after
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
FLUSH TABLES;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (2)");
SELECT * FROM t1 ORDER BY a;
--echo # Truncate with FLUSH before
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (3)");
SELECT * FROM t1 ORDER BY a;
--echo # Truncate with FLUSH after INSERT
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (4)");
SELECT * FROM t1 ORDER BY a;
--echo # Truncate without FLUSH
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (1)");
SELECT * FROM t1 ORDER BY a;
--echo # Truncate with FLUSH after
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
FLUSH TABLES;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (2)");
SELECT * FROM t1 ORDER BY a;
--echo # Truncate with FLUSH before
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (3)");
SELECT * FROM t1 ORDER BY a;
--echo # Truncate with FLUSH after INSERT
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (4)");
SELECT * FROM t1 ORDER BY a;
DROP TABLE t1;
}
--echo # Cleaning up before exit
eval USE $old_db;
DROP DATABASE MySQL_Test_DB;

View File

@ -915,6 +915,18 @@ TableA CREATE TABLE `TableA` (
) ENGINE=ARCHIVE DEFAULT CHARSET=latin1
# Cleaning up after LIST PARTITIONING test
DROP TABLE TableA;
# Verify that TRUNCATE PARTITION gives error
CREATE TABLE t1
(a BIGINT AUTO_INCREMENT PRIMARY KEY,
b VARCHAR(255))
ENGINE = 'Archive'
PARTITION BY KEY (a)
(PARTITION LT1000,
PARTITION LT2000,
PARTITION MAX);
INSERT INTO t1 VALUES (NULL, "First"), (NULL, "Second"), (999, "Last in LT1000"), (NULL, "First in LT2000"), (NULL, "Second in LT2000"), (1999, "Last in LT2000"), (NULL, "First in MAX"), (NULL, "Second in MAX");
ALTER TABLE t1 TRUNCATE PARTITION MAX;
Got one of the listed errors
# Cleaning up before exit
USE test;
DROP DATABASE MySQL_Test_DB;

View File

@ -915,6 +915,170 @@ TableA CREATE TABLE `TableA` (
) ENGINE=InnoDB DEFAULT CHARSET=latin1
# Cleaning up after LIST PARTITIONING test
DROP TABLE TableA;
# Testing TRUNCATE PARTITION
CREATE TABLE t1
(a BIGINT AUTO_INCREMENT PRIMARY KEY,
b VARCHAR(255))
ENGINE = 'InnoDB'
PARTITION BY RANGE (a)
(PARTITION LT1000 VALUES LESS THAN (1000),
PARTITION LT2000 VALUES LESS THAN (2000),
PARTITION MAX VALUES LESS THAN MAXVALUE);
INSERT INTO t1 VALUES (NULL, "First"), (NULL, "Second"), (999, "Last in LT1000"), (NULL, "First in LT2000"), (NULL, "Second in LT2000"), (1999, "Last in LT2000"), (NULL, "First in MAX"), (NULL, "Second in MAX");
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` bigint(20) NOT NULL AUTO_INCREMENT,
`b` varchar(255) DEFAULT NULL,
PRIMARY KEY (`a`)
) ENGINE=InnoDB AUTO_INCREMENT=2002 DEFAULT CHARSET=latin1
/*!50100 PARTITION BY RANGE (a)
(PARTITION LT1000 VALUES LESS THAN (1000) ENGINE = InnoDB,
PARTITION LT2000 VALUES LESS THAN (2000) ENGINE = InnoDB,
PARTITION MAX VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */
SELECT * FROM t1 ORDER BY a;
a b
1 First
2 Second
999 Last in LT1000
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First in MAX
2001 Second in MAX
ALTER TABLE t1 ANALYZE PARTITION MAX;
Table Op Msg_type Msg_text
MySQL_Test_DB.t1 analyze status OK
# Truncate without FLUSH
ALTER TABLE t1 TRUNCATE PARTITION MAX;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (1)");
SELECT * FROM t1 WHERE a >= 2000;
a b
2000 First after TRUNCATE MAX (1)
# Truncate with FLUSH after
ALTER TABLE t1 TRUNCATE PARTITION MAX;
FLUSH TABLES;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (2)");
SELECT * FROM t1 WHERE a >= 2000;
a b
2000 First after TRUNCATE MAX (2)
# Truncate with FLUSH before
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION MAX;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (3)");
SELECT * FROM t1 WHERE a >= 2000;
a b
2000 First after TRUNCATE MAX (3)
# Truncate with FLUSH after INSERT
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION MAX;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (4)");
SELECT * FROM t1 WHERE a >= 2000;
a b
2000 First after TRUNCATE MAX (4)
# Truncate without FLUSH
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (1)");
SELECT * FROM t1 ORDER BY a;
a b
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
# Truncate with FLUSH after
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
FLUSH TABLES;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (2)");
SELECT * FROM t1 ORDER BY a;
a b
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
# Truncate with FLUSH before
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (3)");
SELECT * FROM t1 ORDER BY a;
a b
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
# Truncate with FLUSH after INSERT
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (4)");
SELECT * FROM t1 ORDER BY a;
a b
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
# Truncate without FLUSH
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (1)");
SELECT * FROM t1 ORDER BY a;
a b
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
2005 First after TRUNCATE LT2000 (1)
# Truncate with FLUSH after
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
FLUSH TABLES;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (2)");
SELECT * FROM t1 ORDER BY a;
a b
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
2005 First after TRUNCATE LT2000 (1)
2006 First after TRUNCATE LT2000 (2)
# Truncate with FLUSH before
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (3)");
SELECT * FROM t1 ORDER BY a;
a b
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
2005 First after TRUNCATE LT2000 (1)
2006 First after TRUNCATE LT2000 (2)
2007 First after TRUNCATE LT2000 (3)
# Truncate with FLUSH after INSERT
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (4)");
SELECT * FROM t1 ORDER BY a;
a b
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
2005 First after TRUNCATE LT2000 (1)
2006 First after TRUNCATE LT2000 (2)
2007 First after TRUNCATE LT2000 (3)
2008 First after TRUNCATE LT2000 (4)
DROP TABLE t1;
# Cleaning up before exit
USE test;
DROP DATABASE MySQL_Test_DB;

View File

@ -915,6 +915,170 @@ TableA CREATE TABLE `TableA` (
) ENGINE=MEMORY DEFAULT CHARSET=latin1
# Cleaning up after LIST PARTITIONING test
DROP TABLE TableA;
# Testing TRUNCATE PARTITION
CREATE TABLE t1
(a BIGINT AUTO_INCREMENT PRIMARY KEY,
b VARCHAR(255))
ENGINE = 'Memory'
PARTITION BY RANGE (a)
(PARTITION LT1000 VALUES LESS THAN (1000),
PARTITION LT2000 VALUES LESS THAN (2000),
PARTITION MAX VALUES LESS THAN MAXVALUE);
INSERT INTO t1 VALUES (NULL, "First"), (NULL, "Second"), (999, "Last in LT1000"), (NULL, "First in LT2000"), (NULL, "Second in LT2000"), (1999, "Last in LT2000"), (NULL, "First in MAX"), (NULL, "Second in MAX");
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` bigint(20) NOT NULL AUTO_INCREMENT,
`b` varchar(255) DEFAULT NULL,
PRIMARY KEY (`a`)
) ENGINE=MEMORY AUTO_INCREMENT=2002 DEFAULT CHARSET=latin1
/*!50100 PARTITION BY RANGE (a)
(PARTITION LT1000 VALUES LESS THAN (1000) ENGINE = MEMORY,
PARTITION LT2000 VALUES LESS THAN (2000) ENGINE = MEMORY,
PARTITION MAX VALUES LESS THAN MAXVALUE ENGINE = MEMORY) */
SELECT * FROM t1 ORDER BY a;
a b
1 First
2 Second
999 Last in LT1000
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First in MAX
2001 Second in MAX
ALTER TABLE t1 ANALYZE PARTITION MAX;
Table Op Msg_type Msg_text
MySQL_Test_DB.t1 analyze note The storage engine for the table doesn't support analyze
# Truncate without FLUSH
ALTER TABLE t1 TRUNCATE PARTITION MAX;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (1)");
SELECT * FROM t1 WHERE a >= 2000;
a b
2000 First after TRUNCATE MAX (1)
# Truncate with FLUSH after
ALTER TABLE t1 TRUNCATE PARTITION MAX;
FLUSH TABLES;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (2)");
SELECT * FROM t1 WHERE a >= 2000;
a b
2000 First after TRUNCATE MAX (2)
# Truncate with FLUSH before
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION MAX;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (3)");
SELECT * FROM t1 WHERE a >= 2000;
a b
2000 First after TRUNCATE MAX (3)
# Truncate with FLUSH after INSERT
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION MAX;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (4)");
SELECT * FROM t1 WHERE a >= 2000;
a b
2000 First after TRUNCATE MAX (4)
# Truncate without FLUSH
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (1)");
SELECT * FROM t1 ORDER BY a;
a b
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
# Truncate with FLUSH after
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
FLUSH TABLES;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (2)");
SELECT * FROM t1 ORDER BY a;
a b
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
# Truncate with FLUSH before
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (3)");
SELECT * FROM t1 ORDER BY a;
a b
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
# Truncate with FLUSH after INSERT
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (4)");
SELECT * FROM t1 ORDER BY a;
a b
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
# Truncate without FLUSH
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (1)");
SELECT * FROM t1 ORDER BY a;
a b
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
2005 First after TRUNCATE LT2000 (1)
# Truncate with FLUSH after
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
FLUSH TABLES;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (2)");
SELECT * FROM t1 ORDER BY a;
a b
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
2005 First after TRUNCATE LT2000 (1)
2006 First after TRUNCATE LT2000 (2)
# Truncate with FLUSH before
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (3)");
SELECT * FROM t1 ORDER BY a;
a b
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
2005 First after TRUNCATE LT2000 (1)
2006 First after TRUNCATE LT2000 (2)
2007 First after TRUNCATE LT2000 (3)
# Truncate with FLUSH after INSERT
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (4)");
SELECT * FROM t1 ORDER BY a;
a b
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
2005 First after TRUNCATE LT2000 (1)
2006 First after TRUNCATE LT2000 (2)
2007 First after TRUNCATE LT2000 (3)
2008 First after TRUNCATE LT2000 (4)
DROP TABLE t1;
# Cleaning up before exit
USE test;
DROP DATABASE MySQL_Test_DB;

View File

@ -915,6 +915,170 @@ TableA CREATE TABLE `TableA` (
) ENGINE=MyISAM DEFAULT CHARSET=latin1
# Cleaning up after LIST PARTITIONING test
DROP TABLE TableA;
# Testing TRUNCATE PARTITION
CREATE TABLE t1
(a BIGINT AUTO_INCREMENT PRIMARY KEY,
b VARCHAR(255))
ENGINE = 'MyISAM'
PARTITION BY RANGE (a)
(PARTITION LT1000 VALUES LESS THAN (1000),
PARTITION LT2000 VALUES LESS THAN (2000),
PARTITION MAX VALUES LESS THAN MAXVALUE);
INSERT INTO t1 VALUES (NULL, "First"), (NULL, "Second"), (999, "Last in LT1000"), (NULL, "First in LT2000"), (NULL, "Second in LT2000"), (1999, "Last in LT2000"), (NULL, "First in MAX"), (NULL, "Second in MAX");
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` bigint(20) NOT NULL AUTO_INCREMENT,
`b` varchar(255) DEFAULT NULL,
PRIMARY KEY (`a`)
) ENGINE=MyISAM AUTO_INCREMENT=2002 DEFAULT CHARSET=latin1
/*!50100 PARTITION BY RANGE (a)
(PARTITION LT1000 VALUES LESS THAN (1000) ENGINE = MyISAM,
PARTITION LT2000 VALUES LESS THAN (2000) ENGINE = MyISAM,
PARTITION MAX VALUES LESS THAN MAXVALUE ENGINE = MyISAM) */
SELECT * FROM t1 ORDER BY a;
a b
1 First
2 Second
999 Last in LT1000
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First in MAX
2001 Second in MAX
ALTER TABLE t1 ANALYZE PARTITION MAX;
Table Op Msg_type Msg_text
MySQL_Test_DB.t1 analyze status OK
# Truncate without FLUSH
ALTER TABLE t1 TRUNCATE PARTITION MAX;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (1)");
SELECT * FROM t1 WHERE a >= 2000;
a b
2000 First after TRUNCATE MAX (1)
# Truncate with FLUSH after
ALTER TABLE t1 TRUNCATE PARTITION MAX;
FLUSH TABLES;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (2)");
SELECT * FROM t1 WHERE a >= 2000;
a b
2000 First after TRUNCATE MAX (2)
# Truncate with FLUSH before
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION MAX;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (3)");
SELECT * FROM t1 WHERE a >= 2000;
a b
2000 First after TRUNCATE MAX (3)
# Truncate with FLUSH after INSERT
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION MAX;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (4)");
SELECT * FROM t1 WHERE a >= 2000;
a b
2000 First after TRUNCATE MAX (4)
# Truncate without FLUSH
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (1)");
SELECT * FROM t1 ORDER BY a;
a b
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
# Truncate with FLUSH after
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
FLUSH TABLES;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (2)");
SELECT * FROM t1 ORDER BY a;
a b
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
# Truncate with FLUSH before
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (3)");
SELECT * FROM t1 ORDER BY a;
a b
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
# Truncate with FLUSH after INSERT
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (4)");
SELECT * FROM t1 ORDER BY a;
a b
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
# Truncate without FLUSH
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (1)");
SELECT * FROM t1 ORDER BY a;
a b
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
2005 First after TRUNCATE LT2000 (1)
# Truncate with FLUSH after
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
FLUSH TABLES;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (2)");
SELECT * FROM t1 ORDER BY a;
a b
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
2005 First after TRUNCATE LT2000 (1)
2006 First after TRUNCATE LT2000 (2)
# Truncate with FLUSH before
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (3)");
SELECT * FROM t1 ORDER BY a;
a b
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
2005 First after TRUNCATE LT2000 (1)
2006 First after TRUNCATE LT2000 (2)
2007 First after TRUNCATE LT2000 (3)
# Truncate with FLUSH after INSERT
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (4)");
SELECT * FROM t1 ORDER BY a;
a b
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
2005 First after TRUNCATE LT2000 (1)
2006 First after TRUNCATE LT2000 (2)
2007 First after TRUNCATE LT2000 (3)
2008 First after TRUNCATE LT2000 (4)
DROP TABLE t1;
# Cleaning up before exit
USE test;
DROP DATABASE MySQL_Test_DB;

View File

@ -181,6 +181,18 @@ TableA CREATE TABLE `TableA` (
) ENGINE=ndbcluster DEFAULT CHARSET=latin1
# Cleaning up after KEY PARTITIONING test
DROP TABLE TableA;
# Verify that TRUNCATE PARTITION gives error
CREATE TABLE t1
(a BIGINT AUTO_INCREMENT PRIMARY KEY,
b VARCHAR(255))
ENGINE = 'NDBCluster'
PARTITION BY KEY (a)
(PARTITION LT1000,
PARTITION LT2000,
PARTITION MAX);
INSERT INTO t1 VALUES (NULL, "First"), (NULL, "Second"), (999, "Last in LT1000"), (NULL, "First in LT2000"), (NULL, "Second in LT2000"), (1999, "Last in LT2000"), (NULL, "First in MAX"), (NULL, "Second in MAX");
ALTER TABLE t1 TRUNCATE PARTITION MAX;
Got one of the listed errors
# Cleaning up before exit
USE test;
DROP DATABASE MySQL_Test_DB;

View File

@ -882,6 +882,18 @@ TableA CREATE TABLE `tablea` (
) ENGINE=ARCHIVE DEFAULT CHARSET=latin1
# Cleaning up after LIST PARTITIONING test
DROP TABLE TableA;
# Verify that TRUNCATE PARTITION gives error
CREATE TABLE t1
(a BIGINT AUTO_INCREMENT PRIMARY KEY,
b VARCHAR(255))
ENGINE = 'Archive'
PARTITION BY KEY (a)
(PARTITION LT1000,
PARTITION LT2000,
PARTITION MAX);
INSERT INTO t1 VALUES (NULL, "First"), (NULL, "Second"), (999, "Last in LT1000"), (NULL, "First in LT2000"), (NULL, "Second in LT2000"), (1999, "Last in LT2000"), (NULL, "First in MAX"), (NULL, "Second in MAX");
ALTER TABLE t1 TRUNCATE PARTITION MAX;
Got one of the listed errors
# Cleaning up before exit
USE test;
DROP DATABASE MySQL_Test_DB;

View File

@ -882,6 +882,170 @@ TableA CREATE TABLE `tablea` (
) ENGINE=InnoDB DEFAULT CHARSET=latin1
# Cleaning up after LIST PARTITIONING test
DROP TABLE TableA;
# Testing TRUNCATE PARTITION
CREATE TABLE t1
(a BIGINT AUTO_INCREMENT PRIMARY KEY,
b VARCHAR(255))
ENGINE = 'InnoDB'
PARTITION BY RANGE (a)
(PARTITION LT1000 VALUES LESS THAN (1000),
PARTITION LT2000 VALUES LESS THAN (2000),
PARTITION MAX VALUES LESS THAN MAXVALUE);
INSERT INTO t1 VALUES (NULL, "First"), (NULL, "Second"), (999, "Last in LT1000"), (NULL, "First in LT2000"), (NULL, "Second in LT2000"), (1999, "Last in LT2000"), (NULL, "First in MAX"), (NULL, "Second in MAX");
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` bigint(20) NOT NULL AUTO_INCREMENT,
`b` varchar(255) DEFAULT NULL,
PRIMARY KEY (`a`)
) ENGINE=InnoDB AUTO_INCREMENT=2002 DEFAULT CHARSET=latin1
/*!50100 PARTITION BY RANGE (a)
(PARTITION LT1000 VALUES LESS THAN (1000) ENGINE = InnoDB,
PARTITION LT2000 VALUES LESS THAN (2000) ENGINE = InnoDB,
PARTITION MAX VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */
SELECT * FROM t1 ORDER BY a;
a b
1 First
2 Second
999 Last in LT1000
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First in MAX
2001 Second in MAX
ALTER TABLE t1 ANALYZE PARTITION MAX;
Table Op Msg_type Msg_text
mysql_test_db.t1 analyze status OK
# Truncate without FLUSH
ALTER TABLE t1 TRUNCATE PARTITION MAX;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (1)");
SELECT * FROM t1 WHERE a >= 2000;
a b
2000 First after TRUNCATE MAX (1)
# Truncate with FLUSH after
ALTER TABLE t1 TRUNCATE PARTITION MAX;
FLUSH TABLES;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (2)");
SELECT * FROM t1 WHERE a >= 2000;
a b
2000 First after TRUNCATE MAX (2)
# Truncate with FLUSH before
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION MAX;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (3)");
SELECT * FROM t1 WHERE a >= 2000;
a b
2000 First after TRUNCATE MAX (3)
# Truncate with FLUSH after INSERT
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION MAX;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (4)");
SELECT * FROM t1 WHERE a >= 2000;
a b
2000 First after TRUNCATE MAX (4)
# Truncate without FLUSH
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (1)");
SELECT * FROM t1 ORDER BY a;
a b
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
# Truncate with FLUSH after
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
FLUSH TABLES;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (2)");
SELECT * FROM t1 ORDER BY a;
a b
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
# Truncate with FLUSH before
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (3)");
SELECT * FROM t1 ORDER BY a;
a b
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
# Truncate with FLUSH after INSERT
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (4)");
SELECT * FROM t1 ORDER BY a;
a b
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
# Truncate without FLUSH
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (1)");
SELECT * FROM t1 ORDER BY a;
a b
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
2005 First after TRUNCATE LT2000 (1)
# Truncate with FLUSH after
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
FLUSH TABLES;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (2)");
SELECT * FROM t1 ORDER BY a;
a b
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
2005 First after TRUNCATE LT2000 (1)
2006 First after TRUNCATE LT2000 (2)
# Truncate with FLUSH before
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (3)");
SELECT * FROM t1 ORDER BY a;
a b
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
2005 First after TRUNCATE LT2000 (1)
2006 First after TRUNCATE LT2000 (2)
2007 First after TRUNCATE LT2000 (3)
# Truncate with FLUSH after INSERT
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (4)");
SELECT * FROM t1 ORDER BY a;
a b
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
2005 First after TRUNCATE LT2000 (1)
2006 First after TRUNCATE LT2000 (2)
2007 First after TRUNCATE LT2000 (3)
2008 First after TRUNCATE LT2000 (4)
DROP TABLE t1;
# Cleaning up before exit
USE test;
DROP DATABASE MySQL_Test_DB;

View File

@ -882,6 +882,170 @@ TableA CREATE TABLE `tablea` (
) ENGINE=MEMORY DEFAULT CHARSET=latin1
# Cleaning up after LIST PARTITIONING test
DROP TABLE TableA;
# Testing TRUNCATE PARTITION
CREATE TABLE t1
(a BIGINT AUTO_INCREMENT PRIMARY KEY,
b VARCHAR(255))
ENGINE = 'Memory'
PARTITION BY RANGE (a)
(PARTITION LT1000 VALUES LESS THAN (1000),
PARTITION LT2000 VALUES LESS THAN (2000),
PARTITION MAX VALUES LESS THAN MAXVALUE);
INSERT INTO t1 VALUES (NULL, "First"), (NULL, "Second"), (999, "Last in LT1000"), (NULL, "First in LT2000"), (NULL, "Second in LT2000"), (1999, "Last in LT2000"), (NULL, "First in MAX"), (NULL, "Second in MAX");
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` bigint(20) NOT NULL AUTO_INCREMENT,
`b` varchar(255) DEFAULT NULL,
PRIMARY KEY (`a`)
) ENGINE=MEMORY AUTO_INCREMENT=2002 DEFAULT CHARSET=latin1
/*!50100 PARTITION BY RANGE (a)
(PARTITION LT1000 VALUES LESS THAN (1000) ENGINE = MEMORY,
PARTITION LT2000 VALUES LESS THAN (2000) ENGINE = MEMORY,
PARTITION MAX VALUES LESS THAN MAXVALUE ENGINE = MEMORY) */
SELECT * FROM t1 ORDER BY a;
a b
1 First
2 Second
999 Last in LT1000
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First in MAX
2001 Second in MAX
ALTER TABLE t1 ANALYZE PARTITION MAX;
Table Op Msg_type Msg_text
mysql_test_db.t1 analyze note The storage engine for the table doesn't support analyze
# Truncate without FLUSH
ALTER TABLE t1 TRUNCATE PARTITION MAX;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (1)");
SELECT * FROM t1 WHERE a >= 2000;
a b
2000 First after TRUNCATE MAX (1)
# Truncate with FLUSH after
ALTER TABLE t1 TRUNCATE PARTITION MAX;
FLUSH TABLES;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (2)");
SELECT * FROM t1 WHERE a >= 2000;
a b
2000 First after TRUNCATE MAX (2)
# Truncate with FLUSH before
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION MAX;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (3)");
SELECT * FROM t1 WHERE a >= 2000;
a b
2000 First after TRUNCATE MAX (3)
# Truncate with FLUSH after INSERT
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION MAX;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (4)");
SELECT * FROM t1 WHERE a >= 2000;
a b
2000 First after TRUNCATE MAX (4)
# Truncate without FLUSH
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (1)");
SELECT * FROM t1 ORDER BY a;
a b
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
# Truncate with FLUSH after
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
FLUSH TABLES;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (2)");
SELECT * FROM t1 ORDER BY a;
a b
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
# Truncate with FLUSH before
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (3)");
SELECT * FROM t1 ORDER BY a;
a b
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
# Truncate with FLUSH after INSERT
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (4)");
SELECT * FROM t1 ORDER BY a;
a b
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
# Truncate without FLUSH
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (1)");
SELECT * FROM t1 ORDER BY a;
a b
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
2005 First after TRUNCATE LT2000 (1)
# Truncate with FLUSH after
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
FLUSH TABLES;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (2)");
SELECT * FROM t1 ORDER BY a;
a b
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
2005 First after TRUNCATE LT2000 (1)
2006 First after TRUNCATE LT2000 (2)
# Truncate with FLUSH before
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (3)");
SELECT * FROM t1 ORDER BY a;
a b
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
2005 First after TRUNCATE LT2000 (1)
2006 First after TRUNCATE LT2000 (2)
2007 First after TRUNCATE LT2000 (3)
# Truncate with FLUSH after INSERT
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (4)");
SELECT * FROM t1 ORDER BY a;
a b
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
2005 First after TRUNCATE LT2000 (1)
2006 First after TRUNCATE LT2000 (2)
2007 First after TRUNCATE LT2000 (3)
2008 First after TRUNCATE LT2000 (4)
DROP TABLE t1;
# Cleaning up before exit
USE test;
DROP DATABASE MySQL_Test_DB;

View File

@ -882,6 +882,170 @@ TableA CREATE TABLE `tablea` (
) ENGINE=MyISAM DEFAULT CHARSET=latin1
# Cleaning up after LIST PARTITIONING test
DROP TABLE TableA;
# Testing TRUNCATE PARTITION
CREATE TABLE t1
(a BIGINT AUTO_INCREMENT PRIMARY KEY,
b VARCHAR(255))
ENGINE = 'MyISAM'
PARTITION BY RANGE (a)
(PARTITION LT1000 VALUES LESS THAN (1000),
PARTITION LT2000 VALUES LESS THAN (2000),
PARTITION MAX VALUES LESS THAN MAXVALUE);
INSERT INTO t1 VALUES (NULL, "First"), (NULL, "Second"), (999, "Last in LT1000"), (NULL, "First in LT2000"), (NULL, "Second in LT2000"), (1999, "Last in LT2000"), (NULL, "First in MAX"), (NULL, "Second in MAX");
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` bigint(20) NOT NULL AUTO_INCREMENT,
`b` varchar(255) DEFAULT NULL,
PRIMARY KEY (`a`)
) ENGINE=MyISAM AUTO_INCREMENT=2002 DEFAULT CHARSET=latin1
/*!50100 PARTITION BY RANGE (a)
(PARTITION LT1000 VALUES LESS THAN (1000) ENGINE = MyISAM,
PARTITION LT2000 VALUES LESS THAN (2000) ENGINE = MyISAM,
PARTITION MAX VALUES LESS THAN MAXVALUE ENGINE = MyISAM) */
SELECT * FROM t1 ORDER BY a;
a b
1 First
2 Second
999 Last in LT1000
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First in MAX
2001 Second in MAX
ALTER TABLE t1 ANALYZE PARTITION MAX;
Table Op Msg_type Msg_text
mysql_test_db.t1 analyze status OK
# Truncate without FLUSH
ALTER TABLE t1 TRUNCATE PARTITION MAX;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (1)");
SELECT * FROM t1 WHERE a >= 2000;
a b
2000 First after TRUNCATE MAX (1)
# Truncate with FLUSH after
ALTER TABLE t1 TRUNCATE PARTITION MAX;
FLUSH TABLES;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (2)");
SELECT * FROM t1 WHERE a >= 2000;
a b
2000 First after TRUNCATE MAX (2)
# Truncate with FLUSH before
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION MAX;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (3)");
SELECT * FROM t1 WHERE a >= 2000;
a b
2000 First after TRUNCATE MAX (3)
# Truncate with FLUSH after INSERT
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION MAX;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (4)");
SELECT * FROM t1 WHERE a >= 2000;
a b
2000 First after TRUNCATE MAX (4)
# Truncate without FLUSH
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (1)");
SELECT * FROM t1 ORDER BY a;
a b
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
# Truncate with FLUSH after
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
FLUSH TABLES;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (2)");
SELECT * FROM t1 ORDER BY a;
a b
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
# Truncate with FLUSH before
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (3)");
SELECT * FROM t1 ORDER BY a;
a b
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
# Truncate with FLUSH after INSERT
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (4)");
SELECT * FROM t1 ORDER BY a;
a b
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
# Truncate without FLUSH
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (1)");
SELECT * FROM t1 ORDER BY a;
a b
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
2005 First after TRUNCATE LT2000 (1)
# Truncate with FLUSH after
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
FLUSH TABLES;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (2)");
SELECT * FROM t1 ORDER BY a;
a b
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
2005 First after TRUNCATE LT2000 (1)
2006 First after TRUNCATE LT2000 (2)
# Truncate with FLUSH before
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (3)");
SELECT * FROM t1 ORDER BY a;
a b
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
2005 First after TRUNCATE LT2000 (1)
2006 First after TRUNCATE LT2000 (2)
2007 First after TRUNCATE LT2000 (3)
# Truncate with FLUSH after INSERT
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (4)");
SELECT * FROM t1 ORDER BY a;
a b
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
2005 First after TRUNCATE LT2000 (1)
2006 First after TRUNCATE LT2000 (2)
2007 First after TRUNCATE LT2000 (3)
2008 First after TRUNCATE LT2000 (4)
DROP TABLE t1;
# Cleaning up before exit
USE test;
DROP DATABASE MySQL_Test_DB;

View File

@ -219,6 +219,18 @@ TableA CREATE TABLE `tablea` (
) ENGINE=ndbcluster DEFAULT CHARSET=latin1
# Cleaning up after KEY PARTITIONING test
DROP TABLE TableA;
# Verify that TRUNCATE PARTITION gives error
CREATE TABLE t1
(a BIGINT AUTO_INCREMENT PRIMARY KEY,
b VARCHAR(255))
ENGINE = 'NDBCluster'
PARTITION BY KEY (a)
(PARTITION LT1000,
PARTITION LT2000,
PARTITION MAX);
INSERT INTO t1 VALUES (NULL, "First"), (NULL, "Second"), (999, "Last in LT1000"), (NULL, "First in LT2000"), (NULL, "Second in LT2000"), (1999, "Last in LT2000"), (NULL, "First in MAX"), (NULL, "Second in MAX");
ALTER TABLE t1 TRUNCATE PARTITION MAX;
Got one of the listed errors
# Cleaning up before exit
USE test;
DROP DATABASE MySQL_Test_DB;

View File

@ -882,6 +882,18 @@ TableA CREATE TABLE `TableA` (
) ENGINE=ARCHIVE DEFAULT CHARSET=latin1
# Cleaning up after LIST PARTITIONING test
DROP TABLE TableA;
# Verify that TRUNCATE PARTITION gives error
CREATE TABLE t1
(a BIGINT AUTO_INCREMENT PRIMARY KEY,
b VARCHAR(255))
ENGINE = 'Archive'
PARTITION BY KEY (a)
(PARTITION LT1000,
PARTITION LT2000,
PARTITION MAX);
INSERT INTO t1 VALUES (NULL, "First"), (NULL, "Second"), (999, "Last in LT1000"), (NULL, "First in LT2000"), (NULL, "Second in LT2000"), (1999, "Last in LT2000"), (NULL, "First in MAX"), (NULL, "Second in MAX");
ALTER TABLE t1 TRUNCATE PARTITION MAX;
Got one of the listed errors
# Cleaning up before exit
USE test;
DROP DATABASE MySQL_Test_DB;

View File

@ -882,6 +882,170 @@ TableA CREATE TABLE `TableA` (
) ENGINE=InnoDB DEFAULT CHARSET=latin1
# Cleaning up after LIST PARTITIONING test
DROP TABLE TableA;
# Testing TRUNCATE PARTITION
CREATE TABLE t1
(a BIGINT AUTO_INCREMENT PRIMARY KEY,
b VARCHAR(255))
ENGINE = 'InnoDB'
PARTITION BY RANGE (a)
(PARTITION LT1000 VALUES LESS THAN (1000),
PARTITION LT2000 VALUES LESS THAN (2000),
PARTITION MAX VALUES LESS THAN MAXVALUE);
INSERT INTO t1 VALUES (NULL, "First"), (NULL, "Second"), (999, "Last in LT1000"), (NULL, "First in LT2000"), (NULL, "Second in LT2000"), (1999, "Last in LT2000"), (NULL, "First in MAX"), (NULL, "Second in MAX");
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` bigint(20) NOT NULL AUTO_INCREMENT,
`b` varchar(255) DEFAULT NULL,
PRIMARY KEY (`a`)
) ENGINE=InnoDB AUTO_INCREMENT=2002 DEFAULT CHARSET=latin1
/*!50100 PARTITION BY RANGE (a)
(PARTITION LT1000 VALUES LESS THAN (1000) ENGINE = InnoDB,
PARTITION LT2000 VALUES LESS THAN (2000) ENGINE = InnoDB,
PARTITION MAX VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */
SELECT * FROM t1 ORDER BY a;
a b
1 First
2 Second
999 Last in LT1000
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First in MAX
2001 Second in MAX
ALTER TABLE t1 ANALYZE PARTITION MAX;
Table Op Msg_type Msg_text
mysql_test_db.t1 analyze status OK
# Truncate without FLUSH
ALTER TABLE t1 TRUNCATE PARTITION MAX;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (1)");
SELECT * FROM t1 WHERE a >= 2000;
a b
2000 First after TRUNCATE MAX (1)
# Truncate with FLUSH after
ALTER TABLE t1 TRUNCATE PARTITION MAX;
FLUSH TABLES;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (2)");
SELECT * FROM t1 WHERE a >= 2000;
a b
2000 First after TRUNCATE MAX (2)
# Truncate with FLUSH before
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION MAX;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (3)");
SELECT * FROM t1 WHERE a >= 2000;
a b
2000 First after TRUNCATE MAX (3)
# Truncate with FLUSH after INSERT
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION MAX;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (4)");
SELECT * FROM t1 WHERE a >= 2000;
a b
2000 First after TRUNCATE MAX (4)
# Truncate without FLUSH
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (1)");
SELECT * FROM t1 ORDER BY a;
a b
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
# Truncate with FLUSH after
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
FLUSH TABLES;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (2)");
SELECT * FROM t1 ORDER BY a;
a b
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
# Truncate with FLUSH before
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (3)");
SELECT * FROM t1 ORDER BY a;
a b
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
# Truncate with FLUSH after INSERT
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (4)");
SELECT * FROM t1 ORDER BY a;
a b
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
# Truncate without FLUSH
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (1)");
SELECT * FROM t1 ORDER BY a;
a b
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
2005 First after TRUNCATE LT2000 (1)
# Truncate with FLUSH after
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
FLUSH TABLES;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (2)");
SELECT * FROM t1 ORDER BY a;
a b
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
2005 First after TRUNCATE LT2000 (1)
2006 First after TRUNCATE LT2000 (2)
# Truncate with FLUSH before
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (3)");
SELECT * FROM t1 ORDER BY a;
a b
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
2005 First after TRUNCATE LT2000 (1)
2006 First after TRUNCATE LT2000 (2)
2007 First after TRUNCATE LT2000 (3)
# Truncate with FLUSH after INSERT
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (4)");
SELECT * FROM t1 ORDER BY a;
a b
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
2005 First after TRUNCATE LT2000 (1)
2006 First after TRUNCATE LT2000 (2)
2007 First after TRUNCATE LT2000 (3)
2008 First after TRUNCATE LT2000 (4)
DROP TABLE t1;
# Cleaning up before exit
USE test;
DROP DATABASE MySQL_Test_DB;

View File

@ -882,6 +882,170 @@ TableA CREATE TABLE `TableA` (
) ENGINE=MEMORY DEFAULT CHARSET=latin1
# Cleaning up after LIST PARTITIONING test
DROP TABLE TableA;
# Testing TRUNCATE PARTITION
CREATE TABLE t1
(a BIGINT AUTO_INCREMENT PRIMARY KEY,
b VARCHAR(255))
ENGINE = 'Memory'
PARTITION BY RANGE (a)
(PARTITION LT1000 VALUES LESS THAN (1000),
PARTITION LT2000 VALUES LESS THAN (2000),
PARTITION MAX VALUES LESS THAN MAXVALUE);
INSERT INTO t1 VALUES (NULL, "First"), (NULL, "Second"), (999, "Last in LT1000"), (NULL, "First in LT2000"), (NULL, "Second in LT2000"), (1999, "Last in LT2000"), (NULL, "First in MAX"), (NULL, "Second in MAX");
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` bigint(20) NOT NULL AUTO_INCREMENT,
`b` varchar(255) DEFAULT NULL,
PRIMARY KEY (`a`)
) ENGINE=MEMORY AUTO_INCREMENT=2002 DEFAULT CHARSET=latin1
/*!50100 PARTITION BY RANGE (a)
(PARTITION LT1000 VALUES LESS THAN (1000) ENGINE = MEMORY,
PARTITION LT2000 VALUES LESS THAN (2000) ENGINE = MEMORY,
PARTITION MAX VALUES LESS THAN MAXVALUE ENGINE = MEMORY) */
SELECT * FROM t1 ORDER BY a;
a b
1 First
2 Second
999 Last in LT1000
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First in MAX
2001 Second in MAX
ALTER TABLE t1 ANALYZE PARTITION MAX;
Table Op Msg_type Msg_text
mysql_test_db.t1 analyze note The storage engine for the table doesn't support analyze
# Truncate without FLUSH
ALTER TABLE t1 TRUNCATE PARTITION MAX;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (1)");
SELECT * FROM t1 WHERE a >= 2000;
a b
2000 First after TRUNCATE MAX (1)
# Truncate with FLUSH after
ALTER TABLE t1 TRUNCATE PARTITION MAX;
FLUSH TABLES;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (2)");
SELECT * FROM t1 WHERE a >= 2000;
a b
2000 First after TRUNCATE MAX (2)
# Truncate with FLUSH before
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION MAX;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (3)");
SELECT * FROM t1 WHERE a >= 2000;
a b
2000 First after TRUNCATE MAX (3)
# Truncate with FLUSH after INSERT
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION MAX;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (4)");
SELECT * FROM t1 WHERE a >= 2000;
a b
2000 First after TRUNCATE MAX (4)
# Truncate without FLUSH
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (1)");
SELECT * FROM t1 ORDER BY a;
a b
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
# Truncate with FLUSH after
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
FLUSH TABLES;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (2)");
SELECT * FROM t1 ORDER BY a;
a b
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
# Truncate with FLUSH before
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (3)");
SELECT * FROM t1 ORDER BY a;
a b
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
# Truncate with FLUSH after INSERT
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (4)");
SELECT * FROM t1 ORDER BY a;
a b
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
# Truncate without FLUSH
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (1)");
SELECT * FROM t1 ORDER BY a;
a b
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
2005 First after TRUNCATE LT2000 (1)
# Truncate with FLUSH after
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
FLUSH TABLES;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (2)");
SELECT * FROM t1 ORDER BY a;
a b
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
2005 First after TRUNCATE LT2000 (1)
2006 First after TRUNCATE LT2000 (2)
# Truncate with FLUSH before
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (3)");
SELECT * FROM t1 ORDER BY a;
a b
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
2005 First after TRUNCATE LT2000 (1)
2006 First after TRUNCATE LT2000 (2)
2007 First after TRUNCATE LT2000 (3)
# Truncate with FLUSH after INSERT
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (4)");
SELECT * FROM t1 ORDER BY a;
a b
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
2005 First after TRUNCATE LT2000 (1)
2006 First after TRUNCATE LT2000 (2)
2007 First after TRUNCATE LT2000 (3)
2008 First after TRUNCATE LT2000 (4)
DROP TABLE t1;
# Cleaning up before exit
USE test;
DROP DATABASE MySQL_Test_DB;

View File

@ -882,6 +882,170 @@ TableA CREATE TABLE `TableA` (
) ENGINE=MyISAM DEFAULT CHARSET=latin1
# Cleaning up after LIST PARTITIONING test
DROP TABLE TableA;
# Testing TRUNCATE PARTITION
CREATE TABLE t1
(a BIGINT AUTO_INCREMENT PRIMARY KEY,
b VARCHAR(255))
ENGINE = 'MyISAM'
PARTITION BY RANGE (a)
(PARTITION LT1000 VALUES LESS THAN (1000),
PARTITION LT2000 VALUES LESS THAN (2000),
PARTITION MAX VALUES LESS THAN MAXVALUE);
INSERT INTO t1 VALUES (NULL, "First"), (NULL, "Second"), (999, "Last in LT1000"), (NULL, "First in LT2000"), (NULL, "Second in LT2000"), (1999, "Last in LT2000"), (NULL, "First in MAX"), (NULL, "Second in MAX");
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` bigint(20) NOT NULL AUTO_INCREMENT,
`b` varchar(255) DEFAULT NULL,
PRIMARY KEY (`a`)
) ENGINE=MyISAM AUTO_INCREMENT=2002 DEFAULT CHARSET=latin1
/*!50100 PARTITION BY RANGE (a)
(PARTITION LT1000 VALUES LESS THAN (1000) ENGINE = MyISAM,
PARTITION LT2000 VALUES LESS THAN (2000) ENGINE = MyISAM,
PARTITION MAX VALUES LESS THAN MAXVALUE ENGINE = MyISAM) */
SELECT * FROM t1 ORDER BY a;
a b
1 First
2 Second
999 Last in LT1000
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First in MAX
2001 Second in MAX
ALTER TABLE t1 ANALYZE PARTITION MAX;
Table Op Msg_type Msg_text
mysql_test_db.t1 analyze status OK
# Truncate without FLUSH
ALTER TABLE t1 TRUNCATE PARTITION MAX;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (1)");
SELECT * FROM t1 WHERE a >= 2000;
a b
2000 First after TRUNCATE MAX (1)
# Truncate with FLUSH after
ALTER TABLE t1 TRUNCATE PARTITION MAX;
FLUSH TABLES;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (2)");
SELECT * FROM t1 WHERE a >= 2000;
a b
2000 First after TRUNCATE MAX (2)
# Truncate with FLUSH before
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION MAX;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (3)");
SELECT * FROM t1 WHERE a >= 2000;
a b
2000 First after TRUNCATE MAX (3)
# Truncate with FLUSH after INSERT
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION MAX;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (4)");
SELECT * FROM t1 WHERE a >= 2000;
a b
2000 First after TRUNCATE MAX (4)
# Truncate without FLUSH
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (1)");
SELECT * FROM t1 ORDER BY a;
a b
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
# Truncate with FLUSH after
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
FLUSH TABLES;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (2)");
SELECT * FROM t1 ORDER BY a;
a b
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
# Truncate with FLUSH before
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (3)");
SELECT * FROM t1 ORDER BY a;
a b
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
# Truncate with FLUSH after INSERT
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT1000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (4)");
SELECT * FROM t1 ORDER BY a;
a b
1000 First in LT2000
1001 Second in LT2000
1999 Last in LT2000
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
# Truncate without FLUSH
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (1)");
SELECT * FROM t1 ORDER BY a;
a b
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
2005 First after TRUNCATE LT2000 (1)
# Truncate with FLUSH after
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
FLUSH TABLES;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (2)");
SELECT * FROM t1 ORDER BY a;
a b
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
2005 First after TRUNCATE LT2000 (1)
2006 First after TRUNCATE LT2000 (2)
# Truncate with FLUSH before
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (3)");
SELECT * FROM t1 ORDER BY a;
a b
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
2005 First after TRUNCATE LT2000 (1)
2006 First after TRUNCATE LT2000 (2)
2007 First after TRUNCATE LT2000 (3)
# Truncate with FLUSH after INSERT
FLUSH TABLES;
ALTER TABLE t1 TRUNCATE PARTITION LT2000;
INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (4)");
SELECT * FROM t1 ORDER BY a;
a b
2000 First after TRUNCATE MAX (4)
2001 First after TRUNCATE LT1000 (1)
2002 First after TRUNCATE LT1000 (2)
2003 First after TRUNCATE LT1000 (3)
2004 First after TRUNCATE LT1000 (4)
2005 First after TRUNCATE LT2000 (1)
2006 First after TRUNCATE LT2000 (2)
2007 First after TRUNCATE LT2000 (3)
2008 First after TRUNCATE LT2000 (4)
DROP TABLE t1;
# Cleaning up before exit
USE test;
DROP DATABASE MySQL_Test_DB;

View File

@ -219,6 +219,18 @@ TableA CREATE TABLE `TableA` (
) ENGINE=ndbcluster DEFAULT CHARSET=latin1
# Cleaning up after KEY PARTITIONING test
DROP TABLE TableA;
# Verify that TRUNCATE PARTITION gives error
CREATE TABLE t1
(a BIGINT AUTO_INCREMENT PRIMARY KEY,
b VARCHAR(255))
ENGINE = 'NDBCluster'
PARTITION BY KEY (a)
(PARTITION LT1000,
PARTITION LT2000,
PARTITION MAX);
INSERT INTO t1 VALUES (NULL, "First"), (NULL, "Second"), (999, "Last in LT1000"), (NULL, "First in LT2000"), (NULL, "Second in LT2000"), (1999, "Last in LT2000"), (NULL, "First in MAX"), (NULL, "Second in MAX");
ALTER TABLE t1 TRUNCATE PARTITION MAX;
Got one of the listed errors
# Cleaning up before exit
USE test;
DROP DATABASE MySQL_Test_DB;

View File

@ -35,6 +35,7 @@
##### Storage engine to be tested
--source include/have_archive.inc
let $engine= 'Archive';
let $no_truncate= 1;
#------------------------------------------------------------------------------#
# Execute the tests to be applied to all storage engines

View File

@ -41,6 +41,8 @@ let $can_only_key= 1;
# Allow hash/list/range partitioning with ndb
#SET new=on;
let $engine= 'NDBCluster';
# NDB does not yet support TRUNCATE PARTITION
let $no_truncate= 1;
#------------------------------------------------------------------------------#
# Execute the tests to be applied to all storage engines

View File

@ -32,6 +32,7 @@
##### Storage engine to be tested
--source include/have_archive.inc
let $engine= 'Archive';
let $no_truncate= 1;
#------------------------------------------------------------------------------#
# Execute the tests to be applied to all storage engines

View File

@ -38,6 +38,8 @@ let $can_only_key= 1;
# Allow hash/list/range partitioning with ndb
#SET new=on;
let $engine= 'NDBCluster';
# NDB does not yet support TRUNCATE PARTITION
let $no_truncate= 1;
#------------------------------------------------------------------------------#
# Execute the tests to be applied to all storage engines

View File

@ -32,6 +32,7 @@
##### Storage engine to be tested
--source include/have_archive.inc
let $engine= 'Archive';
let $no_truncate= 1;
#------------------------------------------------------------------------------#
# Execute the tests to be applied to all storage engines

View File

@ -37,6 +37,8 @@ let $can_only_key= 1;
# Allow hash/list/range partitioning with ndb
#SET new=on;
let $engine= 'NDBCluster';
# NDB does not yet support TRUNCATE PARTITION
let $no_truncate= 1;
#------------------------------------------------------------------------------#
# Execute the tests to be applied to all storage engines

View File

@ -570,13 +570,13 @@ explain select count(distinct a1,a2,b) from t1 where (a2 >= 'b') and (b = 'a');
explain select count(distinct a1,a2,b,c) from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121');
explain extended select count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c');
explain select count(distinct b) from t1 where (a2 >= 'b') and (b = 'a');
explain extended select ord(a1) + count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a');
explain extended select 98 + count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a');
select count(distinct a1,a2,b) from t1 where (a2 >= 'b') and (b = 'a');
select count(distinct a1,a2,b,c) from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121');
select count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c');
select count(distinct b) from t1 where (a2 >= 'b') and (b = 'a');
select ord(a1) + count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a');
select 98 + count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a');
#
# Queries with expressions in the select clause
@ -1033,3 +1033,124 @@ SELECT a, MAX(b) FROM t WHERE b GROUP BY a;
DROP TABLE t;
--echo End of 5.1 tests
--echo #
--echo # WL#3220 (Loose index scan for COUNT DISTINCT)
--echo #
CREATE TABLE t1 (a INT, b INT, c INT, KEY (a,b));
INSERT INTO t1 VALUES (1,1,1), (1,2,1), (1,3,1), (1,4,1);
INSERT INTO t1 SELECT a, b + 4, 1 FROM t1;
INSERT INTO t1 SELECT a + 1, b, 1 FROM t1;
CREATE TABLE t2 (a INT, b INT, c INT, d INT, e INT, f INT, KEY (a,b,c));
INSERT INTO t2 VALUES (1,1,1,1,1,1), (1,2,1,1,1,1), (1,3,1,1,1,1),
(1,4,1,1,1,1);
INSERT INTO t2 SELECT a, b + 4, c,d,e,f FROM t2;
INSERT INTO t2 SELECT a + 1, b, c,d,e,f FROM t2;
EXPLAIN SELECT COUNT(DISTINCT a) FROM t1;
SELECT COUNT(DISTINCT a) FROM t1;
EXPLAIN SELECT COUNT(DISTINCT a,b) FROM t1;
SELECT COUNT(DISTINCT a,b) FROM t1;
EXPLAIN SELECT COUNT(DISTINCT b,a) FROM t1;
SELECT COUNT(DISTINCT b,a) FROM t1;
EXPLAIN SELECT COUNT(DISTINCT b) FROM t1;
SELECT COUNT(DISTINCT b) FROM t1;
EXPLAIN SELECT COUNT(DISTINCT a) FROM t1 GROUP BY a;
SELECT COUNT(DISTINCT a) FROM t1 GROUP BY a;
EXPLAIN SELECT COUNT(DISTINCT b) FROM t1 GROUP BY a;
SELECT COUNT(DISTINCT b) FROM t1 GROUP BY a;
EXPLAIN SELECT COUNT(DISTINCT a) FROM t1 GROUP BY b;
SELECT COUNT(DISTINCT a) FROM t1 GROUP BY b;
EXPLAIN SELECT DISTINCT COUNT(DISTINCT a) FROM t1;
SELECT DISTINCT COUNT(DISTINCT a) FROM t1;
EXPLAIN SELECT COUNT(DISTINCT a, b + 0) FROM t1;
SELECT COUNT(DISTINCT a, b + 0) FROM t1;
EXPLAIN SELECT COUNT(DISTINCT a) FROM t1 HAVING COUNT(DISTINCT b) < 10;
SELECT COUNT(DISTINCT a) FROM t1 HAVING COUNT(DISTINCT b) < 10;
EXPLAIN SELECT COUNT(DISTINCT a) FROM t1 HAVING COUNT(DISTINCT c) < 10;
SELECT COUNT(DISTINCT a) FROM t1 HAVING COUNT(DISTINCT c) < 10;
EXPLAIN SELECT 1 FROM t1 HAVING COUNT(DISTINCT a) < 10;
SELECT 1 FROM t1 HAVING COUNT(DISTINCT a) < 10;
EXPLAIN SELECT 1 FROM t1 GROUP BY a HAVING COUNT(DISTINCT b) > 1;
SELECT 1 FROM t1 GROUP BY a HAVING COUNT(DISTINCT b) > 1;
EXPLAIN SELECT COUNT(DISTINCT t1_1.a) FROM t1 t1_1, t1 t1_2 GROUP BY t1_1.a;
SELECT COUNT(DISTINCT t1_1.a) FROM t1 t1_1, t1 t1_2 GROUP BY t1_1.a;
EXPLAIN SELECT COUNT(DISTINCT a), 12 FROM t1;
SELECT COUNT(DISTINCT a), 12 FROM t1;
EXPLAIN SELECT COUNT(DISTINCT a, b, c) FROM t2;
SELECT COUNT(DISTINCT a, b, c) FROM t2;
EXPLAIN SELECT COUNT(DISTINCT a), SUM(DISTINCT a), AVG(DISTINCT a) FROM t2;
SELECT COUNT(DISTINCT a), SUM(DISTINCT a), AVG(DISTINCT a) FROM t2;
EXPLAIN SELECT COUNT(DISTINCT a), SUM(DISTINCT a), AVG(DISTINCT f) FROM t2;
SELECT COUNT(DISTINCT a), SUM(DISTINCT a), AVG(DISTINCT f) FROM t2;
EXPLAIN SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, a) FROM t2;
SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, a) FROM t2;
EXPLAIN SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, f) FROM t2;
SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, f) FROM t2;
EXPLAIN SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, d) FROM t2;
SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, d) FROM t2;
EXPLAIN SELECT a, c, COUNT(DISTINCT c, a, b) FROM t2 GROUP BY a, b, c;
SELECT a, c, COUNT(DISTINCT c, a, b) FROM t2 GROUP BY a, b, c;
EXPLAIN SELECT COUNT(DISTINCT c, a, b) FROM t2
WHERE a > 5 AND b BETWEEN 10 AND 20 GROUP BY a, b, c;
SELECT COUNT(DISTINCT c, a, b) FROM t2
WHERE a > 5 AND b BETWEEN 10 AND 20 GROUP BY a, b, c;
EXPLAIN SELECT COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 WHERE a = 5
GROUP BY b;
SELECT COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 WHERE a = 5
GROUP BY b;
EXPLAIN SELECT a, COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 GROUP BY a;
SELECT a, COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 GROUP BY a;
EXPLAIN SELECT COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 GROUP BY a;
SELECT COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 GROUP BY a;
EXPLAIN SELECT COUNT(DISTINCT a, b) FROM t2 WHERE c = 13 AND d = 42;
SELECT COUNT(DISTINCT a, b) FROM t2 WHERE c = 13 AND d = 42;
EXPLAIN SELECT a, COUNT(DISTINCT a), SUM(DISTINCT a) FROM t2
WHERE b = 13 AND c = 42 GROUP BY a;
SELECT a, COUNT(DISTINCT a), SUM(DISTINCT a) FROM t2
WHERE b = 13 AND c = 42 GROUP BY a;
EXPLAIN SELECT COUNT(DISTINCT a, b), SUM(DISTINCT a) FROM t2 WHERE b = 42;
SELECT COUNT(DISTINCT a, b), SUM(DISTINCT a) FROM t2 WHERE b = 42;
EXPLAIN SELECT SUM(DISTINCT a), MAX(b) FROM t2 GROUP BY a;
SELECT SUM(DISTINCT a), MAX(b) FROM t2 GROUP BY a;
EXPLAIN SELECT 42 * (a + c + COUNT(DISTINCT c, a, b)) FROM t2 GROUP BY a, b, c;
SELECT 42 * (a + c + COUNT(DISTINCT c, a, b)) FROM t2 GROUP BY a, b, c;
EXPLAIN SELECT (SUM(DISTINCT a) + MAX(b)) FROM t2 GROUP BY a;
SELECT (SUM(DISTINCT a) + MAX(b)) FROM t2 GROUP BY a;
DROP TABLE t1,t2;
--echo # end of WL#3220 tests

View File

@ -0,0 +1,26 @@
#
# Simple tests to verify truncate partition syntax
#
--source include/have_partition.inc
--disable_warnings
drop table if exists t1, t2, t3, t4;
--enable_warnings
create table t1 (a int)
partition by list (a)
(partition p1 values in (0));
--error ER_WRONG_PARTITION_NAME
alter table t1 truncate partition p1,p1;
--error ER_WRONG_PARTITION_NAME
alter table t1 truncate partition p0;
drop table t1;
create table t1 (a int)
partition by list (a)
subpartition by hash (a)
subpartitions 1
(partition p1 values in (1)
(subpartition sp1));
--error ER_WRONG_PARTITION_NAME
alter table t1 truncate partition sp1;
drop table t1;

View File

@ -13,8 +13,6 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
# Only the server link with this library, the client libraries and the client
# executables all link with recompiles of source found in the "mysys" directory.
# So we only need to create one version of this library, with the "static"

View File

@ -36,7 +36,7 @@ int my_delete(const char *name, myf MyFlags)
DBUG_RETURN(err);
} /* my_delete */
#if defined(__WIN__) && defined(__NT__)
#if defined(__WIN__)
/*
Delete file which is possibly not closed.

View File

@ -27,6 +27,8 @@
#ifdef _MSC_VER
#include <locale.h>
#include <crtdbg.h>
/* WSAStartup needs winsock library*/
#pragma comment(lib, "ws2_32")
#endif
my_bool have_tcpip=0;
static void my_win_init(void);

View File

@ -23,11 +23,7 @@
#include <signal.h>
#ifdef THREAD
#ifdef USE_TLS
pthread_key(struct st_my_thread_var*, THR_KEY_mysys);
#else
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_time;
@ -46,7 +42,9 @@ pthread_mutexattr_t my_fast_mutexattr;
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
pthread_mutexattr_t my_errorcheck_mutexattr;
#endif
#ifdef _MSC_VER
static void install_sigabrt_handler();
#endif
#ifdef TARGET_OS_LINUX
/*
@ -149,15 +147,18 @@ my_bool my_thread_global_init(void)
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);
#if defined( __WIN__) || defined(OS2)
win_pthread_init();
#endif
#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R)
pthread_mutex_init(&LOCK_localtime_r,MY_MUTEX_INIT_SLOW);
#endif
#ifndef HAVE_GETHOSTBYNAME_R
pthread_mutex_init(&LOCK_gethostbyname_r,MY_MUTEX_INIT_SLOW);
#endif
#ifdef _MSC_VER
install_sigabrt_handler();
#endif
if (my_thread_init())
{
my_thread_global_end(); /* Clean up */
@ -258,7 +259,6 @@ my_bool my_thread_init(void)
(ulong) pthread_self());
#endif
#if !defined(__WIN__) || defined(USE_TLS)
if (my_pthread_getspecific(struct st_my_thread_var *,THR_KEY_mysys))
{
#ifdef EXTRA_DEBUG_THREADS
@ -267,26 +267,18 @@ my_bool my_thread_init(void)
#endif
goto end;
}
#ifdef _MSC_VER
install_sigabrt_handler();
#endif
if (!(tmp= (struct st_my_thread_var *) calloc(1, sizeof(*tmp))))
{
error= 1;
goto end;
}
pthread_setspecific(THR_KEY_mysys,tmp);
#else /* defined(__WIN__) && !(defined(USE_TLS) */
/*
Skip initialization if the thread specific variable is already initialized
*/
if (THR_KEY_mysys.id)
goto end;
tmp= &THR_KEY_mysys;
#endif
#if defined(__WIN__) && defined(EMBEDDED_LIBRARY)
tmp->pthread_self= (pthread_t) getpid();
#else
tmp->pthread_self= pthread_self();
#endif
pthread_mutex_init(&tmp->mutex,MY_MUTEX_INIT_FAST);
pthread_cond_init(&tmp->suspend, NULL);
tmp->init= 1;
@ -342,11 +334,7 @@ void my_thread_end(void)
pthread_cond_destroy(&tmp->suspend);
#endif
pthread_mutex_destroy(&tmp->mutex);
#if !defined(__WIN__) || defined(USE_TLS)
free(tmp);
#else
tmp->init= 0;
#endif
/*
Decrement counter for number of running threads. We are using this
@ -360,10 +348,7 @@ void my_thread_end(void)
pthread_cond_signal(&THR_COND_threads);
pthread_mutex_unlock(&THR_LOCK_threads);
}
/* The following free has to be done, even if my_thread_var() is 0 */
#if !defined(__WIN__) || defined(USE_TLS)
pthread_setspecific(THR_KEY_mysys,0);
#endif
}
struct st_my_thread_var *_my_thread_var(void)
@ -419,4 +404,30 @@ static uint get_thread_lib(void)
return THD_LIB_OTHER;
}
#ifdef _WIN32
/*
In Visual Studio 2005 and later, default SIGABRT handler will overwrite
any unhandled exception filter set by the application and will try to
call JIT debugger. This is not what we want, this we calling __debugbreak
to stop in debugger, if process is being debugged or to generate
EXCEPTION_BREAKPOINT and then handle_segfault will do its magic.
*/
#if (_MSC_VER >= 1400)
static void my_sigabrt_handler(int sig)
{
__debugbreak();
}
#endif /*_MSC_VER >=1400 */
static void install_sigabrt_handler(void)
{
#if (_MSC_VER >=1400)
/*abort() should not override our exception filter*/
_set_abort_behavior(0,_CALL_REPORTFAULT);
signal(SIGABRT,my_sigabrt_handler);
#endif /* _MSC_VER >=1400 */
}
#endif
#endif /* THREAD */

View File

@ -16,12 +16,11 @@
/*****************************************************************************
** The following is a simple implementation of posix conditions
*****************************************************************************/
#if defined(_WIN32)
#undef SAFE_MUTEX /* Avoid safe_mutex redefinitions */
#include "mysys_priv.h"
#if defined(THREAD) && defined(__WIN__)
#include <m_string.h>
#undef getpid
#include <process.h>
#include <sys/timeb.h>

View File

@ -314,10 +314,10 @@ size_t my_win_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset)
if(!ReadFile(hFile, Buffer, (DWORD)Count, &nBytesRead, &ov))
{
DWORD lastError= GetLastError();
/*
ERROR_BROKEN_PIPE is returned when no more data coming
through e.g. a command pipe in windows : see MSDN on ReadFile.
*/
/*
ERROR_BROKEN_PIPE is returned when no more data coming
through e.g. a command pipe in windows : see MSDN on ReadFile.
*/
if(lastError == ERROR_HANDLE_EOF || lastError == ERROR_BROKEN_PIPE)
DBUG_RETURN(0); /*return 0 at EOF*/
my_osmaperr(lastError);
@ -367,8 +367,8 @@ size_t my_win_pwrite(File Filedes, const uchar *Buffer, size_t Count,
LARGE_INTEGER li;
DBUG_ENTER("my_win_pwrite");
DBUG_PRINT("my",("Filedes: %d, Buffer: %p, Count: %zd, offset: %llu",
Filedes, Buffer, Count, (ulonglong)offset));
DBUG_PRINT("my",("Filedes: %d, Buffer: %p, Count: %llu, offset: %llu",
Filedes, Buffer, (ulonglong)Count, (ulonglong)offset));
if(!Count)
DBUG_RETURN(0);
@ -425,7 +425,8 @@ size_t my_win_write(File fd, const uchar *Buffer, size_t Count)
HANDLE hFile;
DBUG_ENTER("my_win_write");
DBUG_PRINT("my",("Filedes: %d, Buffer: %p, Count %zd", fd, Buffer, Count));
DBUG_PRINT("my",("Filedes: %d, Buffer: %p, Count %llu", fd, Buffer,
(ulonglong)Count));
if(my_get_open_flags(fd) & _O_APPEND)
{
/*

View File

@ -14,33 +14,23 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*****************************************************************************
** Simulation of posix threads calls for WIN95 and NT
** Simulation of posix threads calls for Windows
*****************************************************************************/
#if defined (_WIN32)
/* SAFE_MUTEX will not work until the thread structure is up to date */
#undef SAFE_MUTEX
#include "mysys_priv.h"
#if defined(THREAD) && defined(__WIN__)
#include <m_string.h>
#undef getpid
#include <process.h>
#include <signal.h>
static pthread_mutex_t THR_LOCK_thread;
static void install_sigabrt_handler(void);
struct pthread_map
struct thread_start_parameter
{
HANDLE pthreadself;
pthread_handler func;
void *param;
void *arg;
};
void win_pthread_init(void)
{
pthread_mutex_init(&THR_LOCK_thread,MY_MUTEX_INIT_FAST);
}
/**
Adapter to @c pthread_mutex_trylock()
@ -62,79 +52,81 @@ win_pthread_mutex_trylock(pthread_mutex_t *mutex)
return EBUSY;
}
/*
** We have tried to use '_beginthreadex' instead of '_beginthread' here
** but in this case the program leaks about 512 characters for each
** created thread !
** As we want to save the created thread handler for other threads to
** use and to be returned by pthread_self() (instead of the Win32 pseudo
** handler), we have to go trough pthread_start() to catch the returned handler
** in the new thread.
*/
pthread_handler_t pthread_start(void *param)
static unsigned int __stdcall pthread_start(void *p)
{
pthread_handler func=((struct pthread_map *) param)->func;
void *func_param=((struct pthread_map *) param)->param;
my_thread_init(); /* Will always succeed in windows */
pthread_mutex_lock(&THR_LOCK_thread); /* Wait for beginthread to return */
win_pthread_self=((struct pthread_map *) param)->pthreadself;
pthread_mutex_unlock(&THR_LOCK_thread);
free((char*) param); /* Free param from create */
pthread_exit((void*) (*func)(func_param));
return 0; /* Safety */
struct thread_start_parameter *par= (struct thread_start_parameter *)p;
pthread_handler func= par->func;
void *arg= par->arg;
free(p);
(*func)(arg);
return 0;
}
int pthread_create(pthread_t *thread_id, pthread_attr_t *attr,
pthread_handler func, void *param)
pthread_handler func, void *param)
{
HANDLE hThread;
struct pthread_map *map;
uintptr_t handle;
struct thread_start_parameter *par;
unsigned int stack_size;
DBUG_ENTER("pthread_create");
if (!(map=malloc(sizeof(*map))))
DBUG_RETURN(-1);
map->func=func;
map->param=param;
pthread_mutex_lock(&THR_LOCK_thread);
#ifdef __BORLANDC__
hThread=(HANDLE)_beginthread((void(_USERENTRY *)(void *)) pthread_start,
attr->dwStackSize ? attr->dwStackSize :
65535, (void*) map);
#else
hThread=(HANDLE)_beginthread((void( __cdecl *)(void *)) pthread_start,
attr->dwStackSize ? attr->dwStackSize :
65535, (void*) map);
#endif
DBUG_PRINT("info", ("hThread=%lu",(long) hThread));
*thread_id=map->pthreadself=hThread;
pthread_mutex_unlock(&THR_LOCK_thread);
par= (struct thread_start_parameter *)malloc(sizeof(*par));
if (!par)
goto error_return;
if (hThread == (HANDLE) -1)
{
int error=errno;
DBUG_PRINT("error",
("Can't create thread to handle request (error %d)",error));
DBUG_RETURN(error ? error : -1);
}
VOID(SetThreadPriority(hThread, attr->priority)) ;
par->func= func;
par->arg= param;
stack_size= attr?attr->dwStackSize:0;
handle= _beginthreadex(NULL, stack_size , pthread_start, par, 0, thread_id);
if (!handle)
goto error_return;
DBUG_PRINT("info", ("thread id=%u",*thread_id));
/* Do not need thread handle, close it */
CloseHandle((HANDLE)handle);
DBUG_RETURN(0);
error_return:
DBUG_PRINT("error",
("Can't create thread to handle request (error %d)",errno));
DBUG_RETURN(-1);
}
void pthread_exit(void *a)
{
_endthread();
_endthreadex(0);
}
/* This is neaded to get the macro pthread_setspecific to work */
int win_pthread_setspecific(void *a,void *b,uint length)
int pthread_join(pthread_t thread, void **value_ptr)
{
memcpy(a,b,length);
DWORD ret;
HANDLE handle;
handle= OpenThread(SYNCHRONIZE, FALSE, thread);
if (!handle)
{
errno= EINVAL;
goto error_return;
}
ret= WaitForSingleObject(handle, INFINITE);
if(ret != WAIT_OBJECT_0)
{
errno= EINVAL;
goto error_return;
}
CloseHandle(handle);
return 0;
error_return:
if(handle)
CloseHandle(handle);
return -1;
}
#endif

View File

@ -13,8 +13,6 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG -DSAFEMALLOC -DSAFE_MUTEX")
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG -DSAFEMALLOC -DSAFE_MUTEX")
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)

View File

@ -24,7 +24,7 @@ ADD_CUSTOM_COMMAND(OUTPUT ${PROJECT_SOURCE_DIR}/scripts/mysql_fix_privilege_tabl
# Build comp_sql - used for embedding SQL in C or C++ programs
ADD_EXECUTABLE(comp_sql comp_sql.c)
TARGET_LINK_LIBRARIES(comp_sql debug dbug mysys strings)
TARGET_LINK_LIBRARIES(comp_sql dbug mysys strings)
# Use comp_sql to build mysql_fix_privilege_tables_sql.c
GET_TARGET_PROPERTY(COMP_SQL_EXE comp_sql LOCATION)

View File

@ -15,9 +15,9 @@
INCLUDE("${PROJECT_SOURCE_DIR}/win/mysql_manifest.cmake")
SET(CMAKE_CXX_FLAGS_DEBUG
"${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX -DUSE_SYMDIR /Zi")
"${CMAKE_CXX_FLAGS_DEBUG} -DUSE_SYMDIR /Zi")
SET(CMAKE_C_FLAGS_DEBUG
"${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX -DUSE_SYMDIR /Zi")
"${CMAKE_C_FLAGS_DEBUG} -DUSE_SYMDIR /Zi")
SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /MAP /MAPINFO:EXPORTS")
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include
@ -96,7 +96,6 @@ SET_TARGET_PROPERTIES(mysqld PROPERTIES ENABLE_EXPORTS TRUE)
SET (MYSQLD_CORE_LIBS mysys zlib dbug strings yassl taocrypt vio regex sql)
TARGET_LINK_LIBRARIES(mysqld ${MYSQLD_CORE_LIBS} ${MYSQLD_STATIC_ENGINE_LIBS})
TARGET_LINK_LIBRARIES(mysqld ws2_32.lib)
IF(MSVC AND NOT WITHOUT_DYNAMIC_PLUGINS)
@ -129,7 +128,7 @@ ADD_CUSTOM_COMMAND(
# Gen_lex_hash
ADD_EXECUTABLE(gen_lex_hash gen_lex_hash.cc)
TARGET_LINK_LIBRARIES(gen_lex_hash debug dbug mysqlclient wsock32)
TARGET_LINK_LIBRARIES(gen_lex_hash dbug mysqlclient)
GET_TARGET_PROPERTY(GEN_LEX_HASH_EXE gen_lex_hash LOCATION)
ADD_CUSTOM_COMMAND(
OUTPUT ${PROJECT_SOURCE_DIR}/sql/lex_hash.h
@ -152,4 +151,4 @@ SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES
ADD_LIBRARY(udf_example MODULE udf_example.c udf_example.def)
ADD_DEPENDENCIES(udf_example strings GenError)
TARGET_LINK_LIBRARIES(udf_example strings wsock32)
TARGET_LINK_LIBRARIES(udf_example strings)

View File

@ -1934,9 +1934,12 @@ public:
virtual bool str_needs_quotes() { return TRUE; }
my_decimal *val_decimal(my_decimal *);
int cmp(const uchar *a, const uchar *b)
{
DBUG_ASSERT(ptr == a);
return Field_bit::key_cmp(b, bytes_in_rec+test(bit_len));
{
DBUG_ASSERT(ptr == a || ptr == b);
if (ptr == a)
return Field_bit::key_cmp(b, bytes_in_rec+test(bit_len));
else
return Field_bit::key_cmp(a, bytes_in_rec+test(bit_len)) * -1;
}
int cmp_binary_offset(uint row_offset)
{ return cmp_offset(row_offset); }

View File

@ -849,9 +849,12 @@ int ha_partition::rename_partitions(const char *path)
#define ANALYZE_PARTS 2
#define CHECK_PARTS 3
#define REPAIR_PARTS 4
#define ASSIGN_KEYCACHE_PARTS 5
#define PRELOAD_KEYS_PARTS 6
static const char *opt_op_name[]= {NULL,
"optimize", "analyze", "check", "repair" };
"optimize", "analyze", "check", "repair",
"assign_to_keycache", "preload_keys"};
/*
Optimize table
@ -936,7 +939,44 @@ int ha_partition::repair(THD *thd, HA_CHECK_OPT *check_opt)
DBUG_RETURN(handle_opt_partitions(thd, check_opt, REPAIR_PARTS));
}
/**
Assign to keycache
@param thd Thread object
@param check_opt Check/analyze/repair/optimize options
@return
@retval >0 Error
@retval 0 Success
*/
int ha_partition::assign_to_keycache(THD *thd, HA_CHECK_OPT *check_opt)
{
DBUG_ENTER("ha_partition::assign_to_keycache");
DBUG_RETURN(handle_opt_partitions(thd, check_opt, ASSIGN_KEYCACHE_PARTS));
}
/**
Preload to keycache
@param thd Thread object
@param check_opt Check/analyze/repair/optimize options
@return
@retval >0 Error
@retval 0 Success
*/
int ha_partition::preload_keys(THD *thd, HA_CHECK_OPT *check_opt)
{
DBUG_ENTER("ha_partition::preload_keys");
DBUG_RETURN(handle_opt_partitions(thd, check_opt, PRELOAD_KEYS_PARTS));
}
/*
Handle optimize/analyze/check/repair of one partition
@ -967,6 +1007,10 @@ static int handle_opt_part(THD *thd, HA_CHECK_OPT *check_opt,
error= file->ha_check(thd, check_opt);
else if (flag == REPAIR_PARTS)
error= file->ha_repair(thd, check_opt);
else if (flag == ASSIGN_KEYCACHE_PARTS)
error= file->assign_to_keycache(thd, check_opt);
else if (flag == PRELOAD_KEYS_PARTS)
error= file->preload_keys(thd, check_opt);
else
{
DBUG_ASSERT(FALSE);
@ -1064,7 +1108,7 @@ int ha_partition::handle_opt_partitions(THD *thd, HA_CHECK_OPT *check_opt,
it should only do named partitions, otherwise all partitions
*/
if (!(thd->lex->alter_info.flags & ALTER_ADMIN_PARTITION) ||
part_elem->part_state == PART_CHANGED)
part_elem->part_state == PART_ADMIN)
{
if (m_is_sub_partitioned)
{
@ -1096,6 +1140,12 @@ int ha_partition::handle_opt_partitions(THD *thd, HA_CHECK_OPT *check_opt,
"Subpartition %s returned error",
sub_elem->partition_name);
}
/* reset part_state for the remaining partitions */
do
{
if (part_elem->part_state == PART_ADMIN)
part_elem->part_state= PART_NORMAL;
} while (part_elem= part_it++);
DBUG_RETURN(error);
}
} while (++j < no_subparts);
@ -1122,9 +1172,16 @@ int ha_partition::handle_opt_partitions(THD *thd, HA_CHECK_OPT *check_opt,
opt_op_name[flag], "Partition %s returned error",
part_elem->partition_name);
}
/* reset part_state for the remaining partitions */
do
{
if (part_elem->part_state == PART_ADMIN)
part_elem->part_state= PART_NORMAL;
} while (part_elem= part_it++);
DBUG_RETURN(error);
}
}
part_elem->part_state= PART_NORMAL;
}
} while (++i < no_parts);
DBUG_RETURN(FALSE);
@ -3221,6 +3278,9 @@ int ha_partition::delete_row(const uchar *buf)
Called from sql_delete.cc by mysql_delete().
Called from sql_select.cc by JOIN::reinit().
Called from sql_union.cc by st_select_lex_unit::exec().
Also used for handle ALTER TABLE t TRUNCATE PARTITION ...
NOTE: auto increment value will be truncated in that partition as well!
*/
int ha_partition::delete_all_rows()
@ -3233,11 +3293,84 @@ int ha_partition::delete_all_rows()
if (thd->lex->sql_command == SQLCOM_TRUNCATE)
{
Alter_info *alter_info= &thd->lex->alter_info;
HA_DATA_PARTITION *ha_data= (HA_DATA_PARTITION*) table_share->ha_data;
/* TRUNCATE also means resetting auto_increment */
lock_auto_increment();
ha_data->next_auto_inc_val= 0;
ha_data->auto_inc_initialized= FALSE;
unlock_auto_increment();
if (alter_info->flags & ALTER_ADMIN_PARTITION)
{
/* ALTER TABLE t TRUNCATE PARTITION ... */
List_iterator<partition_element> part_it(m_part_info->partitions);
int saved_error= 0;
uint no_parts= m_part_info->no_parts;
uint no_subparts= m_part_info->no_subparts;
uint i= 0;
uint no_parts_set= alter_info->partition_names.elements;
uint no_parts_found= set_part_state(alter_info, m_part_info,
PART_ADMIN);
if (no_parts_set != no_parts_found &&
(!(alter_info->flags & ALTER_ALL_PARTITION)))
DBUG_RETURN(HA_ERR_NO_PARTITION_FOUND);
/*
Cannot return HA_ERR_WRONG_COMMAND here without correct pruning
since that whould delete the whole table row by row in sql_delete.cc
*/
bitmap_clear_all(&m_part_info->used_partitions);
do
{
partition_element *part_elem= part_it++;
if (part_elem->part_state == PART_ADMIN)
{
if (m_is_sub_partitioned)
{
List_iterator<partition_element>
subpart_it(part_elem->subpartitions);
partition_element *sub_elem;
uint j= 0, part;
do
{
sub_elem= subpart_it++;
part= i * no_subparts + j;
bitmap_set_bit(&m_part_info->used_partitions, part);
if (!saved_error)
{
DBUG_PRINT("info", ("truncate subpartition %u (%s)",
part, sub_elem->partition_name));
if ((error= m_file[part]->ha_delete_all_rows()))
saved_error= error;
/* If not reset_auto_increment is supported, just accept it */
if (!saved_error &&
(error= m_file[part]->ha_reset_auto_increment(0)) &&
error != HA_ERR_WRONG_COMMAND)
saved_error= error;
}
} while (++j < no_subparts);
}
else
{
DBUG_PRINT("info", ("truncate partition %u (%s)", i,
part_elem->partition_name));
bitmap_set_bit(&m_part_info->used_partitions, i);
if (!saved_error)
{
if ((error= m_file[i]->ha_delete_all_rows()) && !saved_error)
saved_error= error;
/* If not reset_auto_increment is supported, just accept it */
if (!saved_error &&
(error= m_file[i]->ha_reset_auto_increment(0)) &&
error != HA_ERR_WRONG_COMMAND)
saved_error= error;
}
}
part_elem->part_state= PART_NORMAL;
}
} while (++i < no_parts);
DBUG_RETURN(saved_error);
}
truncate= TRUE;
}
file= m_file;
@ -5912,12 +6045,14 @@ enum row_type ha_partition::get_row_type() const
void ha_partition::print_error(int error, myf errflag)
{
THD *thd= ha_thd();
DBUG_ENTER("ha_partition::print_error");
/* Should probably look for my own errors first */
DBUG_PRINT("enter", ("error: %d", error));
if (error == HA_ERR_NO_PARTITION_FOUND)
if (error == HA_ERR_NO_PARTITION_FOUND &&
thd->lex->sql_command != SQLCOM_TRUNCATE)
m_part_info->print_no_partition_found(table);
else
m_file[m_last_part]->print_error(error, errflag);

View File

@ -1071,12 +1071,13 @@ public:
virtual int backup(TD* thd, HA_CHECK_OPT *check_opt);
virtual int restore(THD* thd, HA_CHECK_OPT *check_opt);
virtual int assign_to_keycache(THD* thd, HA_CHECK_OPT *check_opt);
virtual int preload_keys(THD *thd, HA_CHECK_OPT *check_opt);
virtual int dump(THD* thd, int fd = -1);
virtual int net_read_dump(NET* net);
virtual uint checksum() const;
*/
/* Enabled keycache for performance reasons, WL#4571 */
virtual int assign_to_keycache(THD* thd, HA_CHECK_OPT *check_opt);
virtual int preload_keys(THD* thd, HA_CHECK_OPT* check_opt);
/*
-------------------------------------------------------------------------

View File

@ -2777,6 +2777,9 @@ void handler::print_error(int error, myf errflag)
case HA_ERR_TABLE_NEEDS_UPGRADE:
textno=ER_TABLE_NEEDS_UPGRADE;
break;
case HA_ERR_NO_PARTITION_FOUND:
textno=ER_WRONG_PARTITION_NAME;
break;
case HA_ERR_TABLE_READONLY:
textno= ER_OPEN_AS_READONLY;
break;

File diff suppressed because it is too large Load Diff

View File

@ -22,7 +22,87 @@
#include <my_tree.h>
/*
class Item_sum;
class Aggregator_distinct;
class Aggregator_simple;
/**
The abstract base class for the Aggregator_* classes.
It implements the data collection functions (setup/add/clear)
as either pass-through to the real functionality or
as collectors into an Unique (for distinct) structure.
Note that update_field/reset_field are not in that
class, because they're simply not called when
GROUP BY/DISTINCT can be handled with help of index on grouped
fields (quick_group = 0);
*/
class Aggregator : public Sql_alloc
{
friend class Item_sum;
friend class Item_sum_sum;
friend class Item_sum_count;
friend class Item_sum_avg;
/*
All members are protected as this class is not usable outside of an
Item_sum descendant.
*/
protected:
/* the aggregate function class to act on */
Item_sum *item_sum;
/**
When feeding back the data in endup() from Unique/temp table back to
Item_sum::add() methods we must read the data from Unique (and not
recalculate the functions that are given as arguments to the aggregate
function.
This flag is to tell the add() methods to take the data from the Unique
instead by calling the relevant val_..() method
*/
bool use_distinct_values;
public:
Aggregator (Item_sum *arg): item_sum(arg), use_distinct_values(FALSE) {}
virtual ~Aggregator () {} /* Keep gcc happy */
enum Aggregator_type { SIMPLE_AGGREGATOR, DISTINCT_AGGREGATOR };
virtual Aggregator_type Aggrtype() = 0;
/**
Called before adding the first row.
Allocates and sets up the internal aggregation structures used,
e.g. the Unique instance used to calculate distinct.
*/
virtual bool setup(THD *) = 0;
/**
Called when we need to wipe out all the data from the aggregator :
all the values acumulated and all the state.
Cleans up the internal structures and resets them to their initial state.
*/
virtual void clear() = 0;
/**
Called when there's a new value to be aggregated.
Updates the internal state of the aggregator to reflect the new value.
*/
virtual bool add() = 0;
/**
Called when there are no more data and the final value is to be retrieved.
Finalises the state of the aggregator, so the final result can be retrieved.
*/
virtual void endup() = 0;
};
class st_select_lex;
/**
Class Item_sum is the base class used for special expressions that SQL calls
'set functions'. These expressions are formed with the help of aggregate
functions such as SUM, MAX, GROUP_CONCAT etc.
@ -215,13 +295,32 @@
TODO: to catch queries where the limit is exceeded to make the
code clean here.
*/
class st_select_lex;
*/
class Item_sum :public Item_result_field
{
public:
/**
Aggregator class instance. Not set initially. Allocated only after
it is determined if the incoming data are already distinct.
*/
Aggregator *aggr;
/**
Used in making ROLLUP. Set for the ROLLUP copies of the original
Item_sum and passed to create_tmp_field() to cause it to work
over the temp table buffer that is referenced by
Item_result_field::result_field.
*/
bool force_copy_fields;
/**
Indicates how the aggregate function was specified by the parser :
1 if it was written as AGGREGATE(DISTINCT),
0 if it was AGGREGATE()
*/
bool with_distinct;
enum Sumfunctype
{ COUNT_FUNC, COUNT_DISTINCT_FUNC, SUM_FUNC, SUM_DISTINCT_FUNC, AVG_FUNC,
AVG_DISTINCT_FUNC, MIN_FUNC, MAX_FUNC, STD_FUNC,
@ -263,47 +362,28 @@ public:
Item_sum() :quick_group(1), arg_count(0), forced_const(FALSE)
{
mark_as_sum_func();
init_aggregator();
}
Item_sum(Item *a) :quick_group(1), arg_count(1), args(tmp_args),
orig_args(tmp_orig_args), forced_const(FALSE)
{
args[0]=a;
mark_as_sum_func();
init_aggregator();
}
Item_sum( Item *a, Item *b ) :quick_group(1), arg_count(2), args(tmp_args),
orig_args(tmp_orig_args), forced_const(FALSE)
{
args[0]=a; args[1]=b;
mark_as_sum_func();
init_aggregator();
}
Item_sum(List<Item> &list);
//Copy constructor, need to perform subselects with temporary tables
Item_sum(THD *thd, Item_sum *item);
enum Type type() const { return SUM_FUNC_ITEM; }
virtual enum Sumfunctype sum_func () const=0;
/*
This method is similar to add(), but it is called when the current
aggregation group changes. Thus it performs a combination of
clear() and add().
*/
inline bool reset() { clear(); return add(); };
/*
Prepare this item for evaluation of an aggregate value. This is
called by reset() when a group changes, or, for correlated
subqueries, between subquery executions. E.g. for COUNT(), this
method should set count= 0;
*/
virtual void clear()= 0;
/*
This method is called for the next row in the same group. Its
purpose is to aggregate the new value to the previous values in
the group (i.e. since clear() was called last time). For example,
for COUNT(), do count++.
*/
virtual bool add()=0;
inline bool reset() { aggregator_clear(); return aggregator_add(); };
/*
Called when new group is started and results are being saved in
@ -343,11 +423,6 @@ public:
{ return new Item_field(field); }
table_map used_tables() const { return used_tables_cache; }
void update_used_tables ();
void cleanup()
{
Item::cleanup();
forced_const= FALSE;
}
bool is_null() { return null_value; }
void make_const ()
{
@ -359,7 +434,9 @@ public:
virtual void print(String *str, enum_query_type query_type);
void fix_num_length_and_dec();
/*
/**
Mark an aggregate as having no rows.
This function is called by the execution engine to assign 'NO ROWS
FOUND' value to an aggregate item, when the underlying result set
has no rows. Such value, in a general case, may be different from
@ -367,10 +444,15 @@ public:
may be initialized to 0 by clear() and to NULL by
no_rows_in_result().
*/
void no_rows_in_result() { clear(); }
virtual bool setup(THD *thd) {return 0;}
virtual void make_unique() {}
void no_rows_in_result()
{
if (!aggr)
set_aggregator(with_distinct ?
Aggregator::DISTINCT_AGGREGATOR :
Aggregator::SIMPLE_AGGREGATOR);
reset();
}
virtual void make_unique() { force_copy_fields= TRUE; }
Item *get_tmp_table_item(THD *thd);
virtual Field *create_tmp_field(bool group, TABLE *table,
uint convert_blob_length);
@ -381,14 +463,178 @@ public:
st_select_lex *depended_from()
{ return (nest_level == aggr_level ? 0 : aggr_sel); }
Item *get_arg(int i) { return args[i]; }
Item *set_arg(int i, THD *thd, Item *new_val);
Item *get_arg(uint i) { return args[i]; }
Item *set_arg(uint i, THD *thd, Item *new_val);
uint get_arg_count() { return arg_count; }
/* Initialization of distinct related members */
void init_aggregator()
{
aggr= NULL;
with_distinct= FALSE;
force_copy_fields= FALSE;
}
/**
Called to initialize the aggregator.
*/
inline bool aggregator_setup(THD *thd) { return aggr->setup(thd); };
/**
Called to cleanup the aggregator.
*/
inline void aggregator_clear() { aggr->clear(); }
/**
Called to add value to the aggregator.
*/
inline bool aggregator_add() { return aggr->add(); };
/* stores the declared DISTINCT flag (from the parser) */
void set_distinct(bool distinct)
{
with_distinct= distinct;
quick_group= with_distinct ? 0 : 1;
}
/**
Set the type of aggregation : DISTINCT or not.
Called when the final determination is done about the aggregation
type and the object is about to be used.
*/
int set_aggregator(Aggregator::Aggregator_type aggregator);
virtual void clear()= 0;
virtual bool add()= 0;
virtual bool setup(THD *thd) {return 0;}
void cleanup ();
};
class Unique;
/**
The distinct aggregator.
Implements AGGFN (DISTINCT ..)
Collects all the data into an Unique (similarly to what Item_sum_distinct
does currently) and then (if applicable) iterates over the list of
unique values and pumps them back into its object
*/
class Aggregator_distinct : public Aggregator
{
friend class Item_sum_sum;
friend class Item_sum_count;
friend class Item_sum_avg;
protected:
/*
flag to prevent consecutive runs of endup(). Normally in endup there are
expensive calculations (like walking the distinct tree for example)
which we must do only once if there are no data changes.
We can re-use the data for the second and subsequent val_xxx() calls.
endup_done set to TRUE also means that the calculated values for
the aggregate functions are correct and don't need recalculation.
*/
bool endup_done;
/*
Used depending on the type of the aggregate function and the presence of
blob columns in it:
- For COUNT(DISTINCT) and no blob fields this points to a real temporary
table. It's used as a hash table.
- For AVG/SUM(DISTINCT) or COUNT(DISTINCT) with blob fields only the
in-memory data structure of a temporary table is constructed.
It's used by the Field classes to transform data into row format.
*/
TABLE *table;
/*
An array of field lengths on row allocated and used only for
COUNT(DISTINCT) with multiple columns and no blobs. Used in
Aggregator_distinct::composite_key_cmp (called from Unique to compare
nodes
*/
uint32 *field_lengths;
/*
used in conjunction with 'table' to support the access to Field classes
for COUNT(DISTINCT). Needed by copy_fields()/copy_funcs().
*/
TMP_TABLE_PARAM *tmp_table_param;
/*
If there are no blobs in the COUNT(DISTINCT) arguments, we can use a tree,
which is faster than heap table. In that case, we still use the table
to help get things set up, but we insert nothing in it.
For AVG/SUM(DISTINCT) we always use this tree (as it takes a single
argument) to get the distinct rows.
*/
Unique *tree;
/*
The length of the temp table row. Must be a member of the class as it
gets passed down to simple_raw_key_cmp () as a compare function argument
to Unique. simple_raw_key_cmp () is used as a fast comparison function
when the entire row can be binary compared.
*/
uint tree_key_length;
/*
Set to true if the result is known to be always NULL.
If set deactivates creation and usage of the temporary table (in the
'table' member) and the Unique instance (in the 'tree' member) as well as
the calculation of the final value on the first call to
Item_[sum|avg|count]::val_xxx().
*/
bool always_null;
public:
Aggregator_distinct (Item_sum *sum) :
Aggregator(sum), table(NULL), tmp_table_param(NULL), tree(NULL),
always_null(FALSE) {}
virtual ~Aggregator_distinct ();
Aggregator_type Aggrtype() { return DISTINCT_AGGREGATOR; }
bool setup(THD *);
void clear();
bool add();
void endup();
bool unique_walk_function(void *element);
static int composite_key_cmp(void* arg, uchar* key1, uchar* key2);
};
/**
The pass-through aggregator.
Implements AGGFN (DISTINCT ..) by knowing it gets distinct data on input.
So it just pumps them back to the Item_sum descendant class.
*/
class Aggregator_simple : public Aggregator
{
public:
Aggregator_simple (Item_sum *sum) :
Aggregator(sum) {}
Aggregator_type Aggrtype() { return Aggregator::SIMPLE_AGGREGATOR; }
bool setup(THD * thd) { return item_sum->setup(thd); }
void clear() { item_sum->clear(); }
bool add() { return item_sum->add(); }
void endup() {};
};
class Item_sum_num :public Item_sum
{
friend class Aggregator_distinct;
protected:
/*
val_xxx() functions may be called several times during the execution of a
@ -443,9 +689,15 @@ protected:
void fix_length_and_dec();
public:
Item_sum_sum(Item *item_par) :Item_sum_num(item_par) {}
Item_sum_sum(Item *item_par, bool distinct= FALSE) :Item_sum_num(item_par)
{
set_distinct(distinct);
}
Item_sum_sum(THD *thd, Item_sum_sum *item);
enum Sumfunctype sum_func () const {return SUM_FUNC;}
enum Sumfunctype sum_func () const
{
return with_distinct ? SUM_DISTINCT_FUNC : SUM_FUNC;
}
void clear();
bool add();
double val_real();
@ -456,109 +708,50 @@ public:
void reset_field();
void update_field();
void no_rows_in_result() {}
const char *func_name() const { return "sum("; }
const char *func_name() const
{
return with_distinct ? "sum(distinct " : "sum(";
}
Item *copy_or_same(THD* thd);
};
/* Common class for SUM(DISTINCT), AVG(DISTINCT) */
class Unique;
class Item_sum_distinct :public Item_sum_num
{
protected:
/* storage for the summation result */
ulonglong count;
Hybrid_type val;
/* storage for unique elements */
Unique *tree;
TABLE *table;
enum enum_field_types table_field_type;
uint tree_key_length;
protected:
Item_sum_distinct(THD *thd, Item_sum_distinct *item);
public:
Item_sum_distinct(Item *item_par);
~Item_sum_distinct();
bool setup(THD *thd);
void clear();
void cleanup();
bool add();
double val_real();
my_decimal *val_decimal(my_decimal *);
longlong val_int();
String *val_str(String *str);
/* XXX: does it need make_unique? */
enum Sumfunctype sum_func () const { return SUM_DISTINCT_FUNC; }
void reset_field() {} // not used
void update_field() {} // not used
virtual void no_rows_in_result() {}
void fix_length_and_dec();
enum Item_result result_type () const { return val.traits->type(); }
virtual void calculate_val_and_count();
virtual bool unique_walk_function(void *elem);
};
/*
Item_sum_sum_distinct - implementation of SUM(DISTINCT expr).
See also: MySQL manual, chapter 'Adding New Functions To MySQL'
and comments in item_sum.cc.
*/
class Item_sum_sum_distinct :public Item_sum_distinct
{
private:
Item_sum_sum_distinct(THD *thd, Item_sum_sum_distinct *item)
:Item_sum_distinct(thd, item) {}
public:
Item_sum_sum_distinct(Item *item_arg) :Item_sum_distinct(item_arg) {}
enum Sumfunctype sum_func () const { return SUM_DISTINCT_FUNC; }
const char *func_name() const { return "sum(distinct "; }
Item *copy_or_same(THD* thd) { return new Item_sum_sum_distinct(thd, this); }
};
/* Item_sum_avg_distinct - SELECT AVG(DISTINCT expr) FROM ... */
class Item_sum_avg_distinct: public Item_sum_distinct
{
private:
Item_sum_avg_distinct(THD *thd, Item_sum_avg_distinct *original)
:Item_sum_distinct(thd, original) {}
public:
uint prec_increment;
Item_sum_avg_distinct(Item *item_arg) : Item_sum_distinct(item_arg) {}
void fix_length_and_dec();
virtual void calculate_val_and_count();
enum Sumfunctype sum_func () const { return AVG_DISTINCT_FUNC; }
const char *func_name() const { return "avg(distinct "; }
Item *copy_or_same(THD* thd) { return new Item_sum_avg_distinct(thd, this); }
};
class Item_sum_count :public Item_sum_int
{
longlong count;
friend class Aggregator_distinct;
void clear();
bool add();
void cleanup();
public:
Item_sum_count(Item *item_par)
:Item_sum_int(item_par),count(0)
{}
/**
Constructs an instance for COUNT(DISTINCT)
@param list a list of the arguments to the aggregate function
This constructor is called by the parser only for COUNT (DISTINCT).
*/
Item_sum_count(List<Item> &list)
:Item_sum_int(list),count(0)
{
set_distinct(TRUE);
}
Item_sum_count(THD *thd, Item_sum_count *item)
:Item_sum_int(thd, item), count(item->count)
{}
enum Sumfunctype sum_func () const { return COUNT_FUNC; }
void clear();
enum Sumfunctype sum_func () const
{
return with_distinct ? COUNT_DISTINCT_FUNC : COUNT_FUNC;
}
void no_rows_in_result() { count=0; }
bool add();
void make_const(longlong count_arg)
{
count=count_arg;
@ -566,79 +759,15 @@ class Item_sum_count :public Item_sum_int
}
longlong val_int();
void reset_field();
void cleanup();
void update_field();
const char *func_name() const { return "count("; }
const char *func_name() const
{
return with_distinct ? "count(distinct " : "count(";
}
Item *copy_or_same(THD* thd);
};
class TMP_TABLE_PARAM;
class Item_sum_count_distinct :public Item_sum_int
{
TABLE *table;
uint32 *field_lengths;
TMP_TABLE_PARAM *tmp_table_param;
bool force_copy_fields;
/*
If there are no blobs, we can use a tree, which
is faster than heap table. In that case, we still use the table
to help get things set up, but we insert nothing in it
*/
Unique *tree;
/*
Storage for the value of count between calls to val_int() so val_int()
will not recalculate on each call. Validitiy of the value is stored in
is_evaluated.
*/
longlong count;
/*
Following is 0 normal object and pointer to original one for copy
(to correctly free resources)
*/
Item_sum_count_distinct *original;
uint tree_key_length;
bool always_null; // Set to 1 if the result is always NULL
friend int composite_key_cmp(void* arg, uchar* key1, uchar* key2);
friend int simple_str_key_cmp(void* arg, uchar* key1, uchar* key2);
public:
Item_sum_count_distinct(List<Item> &list)
:Item_sum_int(list), table(0), field_lengths(0), tmp_table_param(0),
force_copy_fields(0), tree(0), count(0),
original(0), always_null(FALSE)
{ quick_group= 0; }
Item_sum_count_distinct(THD *thd, Item_sum_count_distinct *item)
:Item_sum_int(thd, item), table(item->table),
field_lengths(item->field_lengths),
tmp_table_param(item->tmp_table_param),
force_copy_fields(0), tree(item->tree), count(item->count),
original(item), tree_key_length(item->tree_key_length),
always_null(item->always_null)
{}
~Item_sum_count_distinct();
void cleanup();
enum Sumfunctype sum_func () const { return COUNT_DISTINCT_FUNC; }
void clear();
bool add();
longlong val_int();
void reset_field() { return ;} // Never called
void update_field() { return ; } // Never called
const char *func_name() const { return "count(distinct "; }
bool setup(THD *thd);
void make_unique();
Item *copy_or_same(THD* thd);
void no_rows_in_result() {}
};
/* Item to get the value of a stored sum function */
class Item_sum_avg;
@ -674,13 +803,18 @@ public:
uint prec_increment;
uint f_precision, f_scale, dec_bin_size;
Item_sum_avg(Item *item_par) :Item_sum_sum(item_par), count(0) {}
Item_sum_avg(Item *item_par, bool distinct= FALSE)
:Item_sum_sum(item_par, distinct), count(0)
{}
Item_sum_avg(THD *thd, Item_sum_avg *item)
:Item_sum_sum(thd, item), count(item->count),
prec_increment(item->prec_increment) {}
void fix_length_and_dec();
enum Sumfunctype sum_func () const {return AVG_FUNC;}
enum Sumfunctype sum_func () const
{
return with_distinct ? AVG_DISTINCT_FUNC : AVG_FUNC;
}
void clear();
bool add();
double val_real();
@ -693,7 +827,10 @@ public:
Item *result_item(Field *field)
{ return new Item_avg_field(hybrid_type, this); }
void no_rows_in_result() {}
const char *func_name() const { return "avg("; }
const char *func_name() const
{
return with_distinct ? "avg(distinct " : "avg(";
}
Item *copy_or_same(THD* thd);
Field *create_tmp_field(bool group, TABLE *table, uint convert_blob_length);
void cleanup()

View File

@ -33,7 +33,7 @@
#include <stdarg.h>
#include <m_ctype.h> // For test_if_number
#ifdef __NT__
#ifdef _WIN32
#include "message.h"
#endif
@ -1794,7 +1794,7 @@ err:
DBUG_RETURN(-1);
}
#ifdef __NT__
#ifdef _WIN32
static int eventSource = 0;
static void setup_windows_event_source()
@ -1829,7 +1829,7 @@ static void setup_windows_event_source()
RegCloseKey(hRegKey);
}
#endif /* __NT__ */
#endif /* _WIN32 */
/**
@ -1960,7 +1960,7 @@ bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
#ifdef EMBEDDED_LIBRARY
"embedded library\n",
my_progname, server_version, MYSQL_COMPILATION_COMMENT
#elif __NT__
#elif _WIN32
"started with:\nTCP Port: %d, Named Pipe: %s\n",
my_progname, server_version, MYSQL_COMPILATION_COMMENT,
mysqld_port, mysqld_unix_port
@ -4851,7 +4851,7 @@ void MYSQL_BIN_LOG::signal_update()
DBUG_VOID_RETURN;
}
#ifdef __NT__
#ifdef _WIN32
static void print_buffer_to_nt_eventlog(enum loglevel level, char *buff,
size_t length, size_t buffLen)
{
@ -4884,7 +4884,7 @@ static void print_buffer_to_nt_eventlog(enum loglevel level, char *buff,
DBUG_VOID_RETURN;
}
#endif /* __NT__ */
#endif /* _WIN32 */
/**
@ -4946,7 +4946,7 @@ int vprint_msg_to_log(enum loglevel level, const char *format, va_list args)
length= my_vsnprintf(buff, sizeof(buff), format, args);
print_buffer_to_file(level, buff);
#ifdef __NT__
#ifdef _WIN32
print_buffer_to_nt_eventlog(level, buff, length, sizeof(buff));
#endif

View File

@ -732,7 +732,7 @@ static NTService Service; ///< Service object for WinNT
#endif /* EMBEDDED_LIBRARY */
#endif /* __WIN__ */
#ifdef __NT__
#ifdef _WIN32
static char pipe_name[512];
static SECURITY_ATTRIBUTES saPipeSecurity;
static SECURITY_DESCRIPTOR sdPipeDescriptor;
@ -805,11 +805,14 @@ static void set_server_version(void);
static int init_thread_environment();
static char *get_relative_path(const char *path);
static int fix_paths(void);
pthread_handler_t handle_connections_sockets(void *arg);
void handle_connections_sockets();
#ifdef _WIN32
pthread_handler_t handle_connections_sockets_thread(void *arg);
#endif
pthread_handler_t kill_server_thread(void *arg);
static void bootstrap(FILE *file);
static bool read_init_file(char *file_name);
#ifdef __NT__
#ifdef _WIN32
pthread_handler_t handle_connections_namedpipes(void *arg);
#endif
#ifdef HAVE_SMEM
@ -895,7 +898,7 @@ static void close_connections(void)
ip_sock= INVALID_SOCKET;
}
}
#ifdef __NT__
#ifdef _WIN32
if (hPipe != INVALID_HANDLE_VALUE && opt_enable_named_pipe)
{
HANDLE temp;
@ -1687,7 +1690,7 @@ static void network_init(void)
}
}
#ifdef __NT__
#ifdef _WIN32
/* create named pipe */
if (Service.IsNT() && mysqld_unix_port[0] && !opt_bootstrap &&
opt_enable_named_pipe)
@ -2034,29 +2037,7 @@ static BOOL WINAPI console_event_handler( DWORD type )
}
/*
In Visual Studio 2005 and later, default SIGABRT handler will overwrite
any unhandled exception filter set by the application and will try to
call JIT debugger. This is not what we want, this we calling __debugbreak
to stop in debugger, if process is being debugged or to generate
EXCEPTION_BREAKPOINT and then handle_segfault will do its magic.
*/
#if (_MSC_VER >= 1400)
static void my_sigabrt_handler(int sig)
{
__debugbreak();
}
#endif /*_MSC_VER >=1400 */
void win_install_sigabrt_handler(void)
{
#if (_MSC_VER >=1400)
/*abort() should not override our exception filter*/
_set_abort_behavior(0,_CALL_REPORTFAULT);
signal(SIGABRT,my_sigabrt_handler);
#endif /* _MSC_VER >=1400 */
}
#ifdef DEBUG_UNHANDLED_EXCEPTION_FILTER
#define DEBUGGER_ATTACH_TIMEOUT 120
@ -2135,7 +2116,6 @@ LONG WINAPI my_unhandler_exception_filter(EXCEPTION_POINTERS *ex_pointers)
static void init_signals(void)
{
win_install_sigabrt_handler();
if(opt_console)
SetConsoleCtrlHandler(console_event_handler,TRUE);
@ -4132,7 +4112,8 @@ static void create_shutdown_thread()
#ifdef __WIN__
hEventShutdown=CreateEvent(0, FALSE, FALSE, shutdown_event_name);
pthread_t hThread;
if (pthread_create(&hThread,&connection_attrib,handle_shutdown,0))
if (pthread_create(&hThread,&connection_attrib,
handle_connections_sockets_thread, 0))
sql_print_warning("Can't create thread to handle shutdown requests");
// On "Stop Service" we have to do regular shutdown
@ -4143,12 +4124,11 @@ static void create_shutdown_thread()
#endif /* EMBEDDED_LIBRARY */
#if (defined(__NT__) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY)
#if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY)
static void handle_connections_methods()
{
pthread_t hThread;
DBUG_ENTER("handle_connections_methods");
#ifdef __NT__
if (hPipe == INVALID_HANDLE_VALUE &&
(!have_tcpip || opt_disable_networking) &&
!opt_enable_shared_memory)
@ -4156,12 +4136,10 @@ static void handle_connections_methods()
sql_print_error("TCP/IP, --shared-memory, or --named-pipe should be configured on NT OS");
unireg_abort(1); // Will not return
}
#endif
pthread_mutex_lock(&LOCK_thread_count);
(void) pthread_cond_init(&COND_handler_count,NULL);
handler_count=0;
#ifdef __NT__
if (hPipe != INVALID_HANDLE_VALUE)
{
handler_count++;
@ -4172,12 +4150,11 @@ static void handle_connections_methods()
handler_count--;
}
}
#endif /* __NT__ */
if (have_tcpip && !opt_disable_networking)
{
handler_count++;
if (pthread_create(&hThread,&connection_attrib,
handle_connections_sockets, 0))
handle_connections_sockets_thread, 0))
{
sql_print_warning("Can't create thread to handle TCP/IP");
handler_count--;
@ -4212,7 +4189,7 @@ void decrement_handler_count()
}
#else
#define decrement_handler_count()
#endif /* defined(__NT__) || defined(HAVE_SMEM) */
#endif /* defined(_WIN32) || defined(HAVE_SMEM) */
#ifndef EMBEDDED_LIBRARY
@ -4506,18 +4483,11 @@ we force server id to 2, but this MySQL server will not act as a slave.");
pthread_cond_signal(&COND_server_started);
pthread_mutex_unlock(&LOCK_server_started);
#if defined(__NT__) || defined(HAVE_SMEM)
#if defined(_WIN32) || defined(HAVE_SMEM)
handle_connections_methods();
#else
#ifdef __WIN__
if (!have_tcpip || opt_disable_networking)
{
sql_print_error("TCP/IP unavailable or disabled with --skip-networking; no available interfaces");
unireg_abort(1);
}
#endif
handle_connections_sockets(0);
#endif /* __NT__ */
handle_connections_sockets();
#endif /* _WIN32 || HAVE_SMEM */
/* (void) pthread_attr_destroy(&connection_attrib); */
@ -4992,7 +4962,7 @@ inline void kill_broken_server()
/* Handle new connections and spawn new process to handle them */
#ifndef EMBEDDED_LIBRARY
pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused)))
void handle_connections_sockets()
{
my_socket sock,new_sock;
uint error_count=0;
@ -5195,13 +5165,19 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused)))
create_new_thread(thd);
}
decrement_handler_count();
DBUG_RETURN(0);
DBUG_VOID_RETURN;
}
#ifdef __NT__
#ifdef _WIN32
pthread_handler_t handle_connections_sockets_thread(void *arg)
{
my_thread_init();
handle_connections_sockets();
decrement_handler_count();
return 0;
}
pthread_handler_t handle_connections_namedpipes(void *arg)
{
HANDLE hConnectedPipe;
@ -5281,7 +5257,7 @@ pthread_handler_t handle_connections_namedpipes(void *arg)
decrement_handler_count();
DBUG_RETURN(0);
}
#endif /* __NT__ */
#endif /* _WIN32 */
#ifdef HAVE_SMEM
@ -5857,7 +5833,7 @@ struct my_option my_long_options[] =
"Deprecated option, use --external-locking instead.",
(uchar**) &opt_external_locking, (uchar**) &opt_external_locking,
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
#ifdef __NT__
#ifdef _WIN32
{"enable-named-pipe", OPT_HAVE_NAMED_PIPE, "Enable the named pipe (NT).",
(uchar**) &opt_enable_named_pipe, (uchar**) &opt_enable_named_pipe, 0, GET_BOOL,
NO_ARG, 0, 0, 0, 0, 0, 0},

View File

@ -708,7 +708,8 @@ static
TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
double read_time);
static
TRP_GROUP_MIN_MAX *get_best_group_min_max(PARAM *param, SEL_TREE *tree);
TRP_GROUP_MIN_MAX *get_best_group_min_max(PARAM *param, SEL_TREE *tree,
double read_time);
static double get_index_only_read_time(const PARAM* param, ha_rows records,
int keynr);
@ -2049,7 +2050,7 @@ public:
class TRP_GROUP_MIN_MAX : public TABLE_READ_PLAN
{
private:
bool have_min, have_max;
bool have_min, have_max, have_agg_distinct;
KEY_PART_INFO *min_max_arg_part;
uint group_prefix_len;
uint used_key_parts;
@ -2061,11 +2062,13 @@ private:
SEL_TREE *range_tree; /* Represents all range predicates in the query. */
SEL_ARG *index_tree; /* The SEL_ARG sub-tree corresponding to index_info. */
uint param_idx; /* Index of used key in param->key. */
/* Number of records selected by the ranges in index_tree. */
bool is_index_scan; /* Use index_next() instead of random read */
public:
/* Number of records selected by the ranges in index_tree. */
ha_rows quick_prefix_records;
public:
TRP_GROUP_MIN_MAX(bool have_min_arg, bool have_max_arg,
TRP_GROUP_MIN_MAX(bool have_min_arg, bool have_max_arg,
bool have_agg_distinct_arg,
KEY_PART_INFO *min_max_arg_part_arg,
uint group_prefix_len_arg, uint used_key_parts_arg,
uint group_key_parts_arg, KEY *index_info_arg,
@ -2074,11 +2077,12 @@ public:
SEL_TREE *tree_arg, SEL_ARG *index_tree_arg,
uint param_idx_arg, ha_rows quick_prefix_records_arg)
: have_min(have_min_arg), have_max(have_max_arg),
have_agg_distinct(have_agg_distinct_arg),
min_max_arg_part(min_max_arg_part_arg),
group_prefix_len(group_prefix_len_arg), used_key_parts(used_key_parts_arg),
group_key_parts(group_key_parts_arg), index_info(index_info_arg),
index(index_arg), key_infix_len(key_infix_len_arg), range_tree(tree_arg),
index_tree(index_tree_arg), param_idx(param_idx_arg),
index_tree(index_tree_arg), param_idx(param_idx_arg), is_index_scan(FALSE),
quick_prefix_records(quick_prefix_records_arg)
{
if (key_infix_len)
@ -2088,6 +2092,7 @@ public:
QUICK_SELECT_I *make_quick(PARAM *param, bool retrieve_full_rows,
MEM_ROOT *parent_alloc);
void use_index_scan() { is_index_scan= TRUE; }
};
@ -2349,7 +2354,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
Try to construct a QUICK_GROUP_MIN_MAX_SELECT.
Notice that it can be constructed no matter if there is a range tree.
*/
group_trp= get_best_group_min_max(&param, tree);
group_trp= get_best_group_min_max(&param, tree, best_read_time);
if (group_trp)
{
param.table->quick_condition_rows= min(group_trp->records,
@ -9048,15 +9053,10 @@ cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts,
double *read_cost, ha_rows *records);
/*
/**
Test if this access method is applicable to a GROUP query with MIN/MAX
functions, and if so, construct a new TRP object.
SYNOPSIS
get_best_group_min_max()
param Parameter from test_quick_select
sel_tree Range tree generated by get_mm_tree
DESCRIPTION
Test whether a query can be computed via a QUICK_GROUP_MIN_MAX_SELECT.
Queries computable via a QUICK_GROUP_MIN_MAX_SELECT must satisfy the
@ -9167,17 +9167,16 @@ cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts,
- Lift the limitation in condition (B3), that is, make this access method
applicable to ROLLUP queries.
RETURN
If mem_root != NULL
- valid TRP_GROUP_MIN_MAX object if this QUICK class can be used for
the query
- NULL o/w.
If mem_root == NULL
- NULL
@param param Parameter from test_quick_select
@param sel_tree Range tree generated by get_mm_tree
@param read_time Best read time so far (=table/index scan time)
@return table read plan
@retval NULL Loose index scan not applicable or mem_root == NULL
@retval !NULL Loose index scan table read plan
*/
static TRP_GROUP_MIN_MAX *
get_best_group_min_max(PARAM *param, SEL_TREE *tree)
get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
{
THD *thd= param->thd;
JOIN *join= thd->lex->current_select->join;
@ -9198,25 +9197,33 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
ORDER *tmp_group;
Item *item;
Item_field *item_field;
bool is_agg_distinct;
List<Item_field> agg_distinct_flds;
DBUG_ENTER("get_best_group_min_max");
/* Perform few 'cheap' tests whether this access method is applicable. */
if (!join)
DBUG_RETURN(NULL); /* This is not a select statement. */
if ((join->tables != 1) || /* The query must reference one table. */
((!join->group_list) && /* Neither GROUP BY nor a DISTINCT query. */
(!join->select_distinct)) ||
(join->select_lex->olap == ROLLUP_TYPE)) /* Check (B3) for ROLLUP */
DBUG_RETURN(NULL);
if (table->s->keys == 0) /* There are no indexes to use. */
DBUG_RETURN(NULL);
/* Analyze the query in more detail. */
List_iterator<Item> select_items_it(join->fields_list);
/* Check (SA1,SA4) and store the only MIN/MAX argument - the C attribute.*/
if (join->make_sum_func_list(join->all_fields, join->fields_list, 1))
DBUG_RETURN(NULL);
List_iterator<Item> select_items_it(join->fields_list);
is_agg_distinct = is_indexed_agg_distinct(join, &agg_distinct_flds);
if ((!join->group_list) && /* Neither GROUP BY nor a DISTINCT query. */
(!join->select_distinct) &&
!is_agg_distinct)
DBUG_RETURN(NULL);
/* Analyze the query in more detail. */
if (join->sum_funcs[0])
{
Item_sum *min_max_item;
@ -9227,6 +9234,10 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
have_min= TRUE;
else if (min_max_item->sum_func() == Item_sum::MAX_FUNC)
have_max= TRUE;
else if (min_max_item->sum_func() == Item_sum::COUNT_DISTINCT_FUNC ||
min_max_item->sum_func() == Item_sum::SUM_DISTINCT_FUNC ||
min_max_item->sum_func() == Item_sum::AVG_DISTINCT_FUNC)
continue;
else
DBUG_RETURN(NULL);
@ -9243,13 +9254,12 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
DBUG_RETURN(NULL);
}
}
/* Check (SA5). */
if (join->select_distinct)
{
while ((item= select_items_it++))
{
if (item->type() != Item::FIELD_ITEM)
if (item->real_item()->type() != Item::FIELD_ITEM)
DBUG_RETURN(NULL);
}
}
@ -9257,7 +9267,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
/* Check (GA4) - that there are no expressions among the group attributes. */
for (tmp_group= join->group_list; tmp_group; tmp_group= tmp_group->next)
{
if ((*tmp_group->item)->type() != Item::FIELD_ITEM)
if ((*tmp_group->item)->real_item()->type() != Item::FIELD_ITEM)
DBUG_RETURN(NULL);
}
@ -9276,6 +9286,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
uint best_param_idx= 0;
const uint pk= param->table->s->primary_key;
uint max_key_part;
SEL_ARG *cur_index_tree= NULL;
ha_rows cur_quick_prefix_records= 0;
uint cur_param_idx=MAX_KEY;
@ -9329,6 +9340,8 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
}
}
max_key_part= 0;
used_key_parts_map.clear_all();
/*
Check (GA1) for GROUP BY queries.
*/
@ -9352,6 +9365,8 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
{
cur_group_prefix_len+= cur_part->store_length;
++cur_group_key_parts;
max_key_part= cur_part - cur_index_info->key_part + 1;
used_key_parts_map.set_bit(max_key_part);
}
else
goto next_index;
@ -9365,14 +9380,26 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
Later group_fields_array of ORDER objects is used to convert the query
to a GROUP query.
*/
else if (join->select_distinct)
if ((!join->group_list && join->select_distinct) ||
is_agg_distinct)
{
select_items_it.rewind();
used_key_parts_map.clear_all();
uint max_key_part= 0;
while ((item= select_items_it++))
if (!is_agg_distinct)
{
item_field= (Item_field*) item; /* (SA5) already checked above. */
select_items_it.rewind();
}
List_iterator<Item_field> agg_distinct_flds_it (agg_distinct_flds);
while (NULL != (item = (is_agg_distinct ?
(Item *) agg_distinct_flds_it++ : select_items_it++)))
{
/* (SA5) already checked above. */
item_field= (Item_field*) item->real_item();
DBUG_ASSERT(item->real_item()->type() == Item::FIELD_ITEM);
/* not doing loose index scan for derived tables */
if (!item_field->field)
goto next_index;
/* Find the order of the key part in the index. */
key_part_nr= get_field_keypart(cur_index_info, item_field->field);
/*
@ -9381,7 +9408,8 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
*/
if (used_key_parts_map.is_set(key_part_nr))
continue;
if (key_part_nr < 1 || key_part_nr > join->fields_list.elements)
if (key_part_nr < 1 ||
(!is_agg_distinct && key_part_nr > join->fields_list.elements))
goto next_index;
cur_part= cur_index_info->key_part + key_part_nr - 1;
cur_group_prefix_len+= cur_part->store_length;
@ -9401,10 +9429,6 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
if (all_parts != cur_parts)
goto next_index;
}
else
{
DBUG_ASSERT(FALSE);
}
/* Check (SA2). */
if (min_max_arg_item)
@ -9558,7 +9582,8 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
/* The query passes all tests, so construct a new TRP object. */
read_plan= new (param->mem_root)
TRP_GROUP_MIN_MAX(have_min, have_max, min_max_arg_part,
TRP_GROUP_MIN_MAX(have_min, have_max, is_agg_distinct,
min_max_arg_part,
group_prefix_len, used_key_parts,
group_key_parts, index_info, index,
key_infix_len,
@ -9572,6 +9597,11 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
read_plan->read_cost= best_read_cost;
read_plan->records= best_records;
if (read_time < best_read_cost && is_agg_distinct)
{
read_plan->read_cost= 0;
read_plan->use_index_scan();
}
DBUG_PRINT("info",
("Returning group min/max plan: cost: %g, records: %lu",
@ -10077,11 +10107,12 @@ TRP_GROUP_MIN_MAX::make_quick(PARAM *param, bool retrieve_full_rows,
quick= new QUICK_GROUP_MIN_MAX_SELECT(param->table,
param->thd->lex->current_select->join,
have_min, have_max, min_max_arg_part,
have_min, have_max,
have_agg_distinct, min_max_arg_part,
group_prefix_len, group_key_parts,
used_key_parts, index_info, index,
read_cost, records, key_infix_len,
key_infix, parent_alloc);
key_infix, parent_alloc, is_index_scan);
if (!quick)
DBUG_RETURN(NULL);
@ -10161,6 +10192,9 @@ TRP_GROUP_MIN_MAX::make_quick(PARAM *param, bool retrieve_full_rows,
key_infix_len Length of the key infix appended to the group prefix
key_infix Infix of constants from equality predicates
parent_alloc Memory pool for this and quick_prefix_select data
is_index_scan get the next different key not by jumping on it via
index read, but by scanning until the end of the
rows with equal key value.
RETURN
None
@ -10168,20 +10202,22 @@ TRP_GROUP_MIN_MAX::make_quick(PARAM *param, bool retrieve_full_rows,
QUICK_GROUP_MIN_MAX_SELECT::
QUICK_GROUP_MIN_MAX_SELECT(TABLE *table, JOIN *join_arg, bool have_min_arg,
bool have_max_arg,
bool have_max_arg, bool have_agg_distinct_arg,
KEY_PART_INFO *min_max_arg_part_arg,
uint group_prefix_len_arg, uint group_key_parts_arg,
uint used_key_parts_arg, KEY *index_info_arg,
uint use_index, double read_cost_arg,
ha_rows records_arg, uint key_infix_len_arg,
uchar *key_infix_arg, MEM_ROOT *parent_alloc)
uchar *key_infix_arg, MEM_ROOT *parent_alloc,
bool is_index_scan_arg)
:join(join_arg), index_info(index_info_arg),
group_prefix_len(group_prefix_len_arg),
group_key_parts(group_key_parts_arg), have_min(have_min_arg),
have_max(have_max_arg), seen_first_key(FALSE),
min_max_arg_part(min_max_arg_part_arg), key_infix(key_infix_arg),
key_infix_len(key_infix_len_arg), min_functions_it(NULL),
max_functions_it(NULL)
have_max(have_max_arg), have_agg_distinct(have_agg_distinct_arg),
seen_first_key(FALSE), min_max_arg_part(min_max_arg_part_arg),
key_infix(key_infix_arg), key_infix_len(key_infix_len_arg),
min_functions_it(NULL), max_functions_it(NULL),
is_index_scan(is_index_scan_arg)
{
head= table;
file= head->file;
@ -10744,6 +10780,56 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_max()
}
/**
Find the next different key value by skiping all the rows with the same key
value.
Implements a specialized loose index access method for queries
containing aggregate functions with distinct of the form:
SELECT [SUM|COUNT|AVG](DISTINCT a,...) FROM t
This method comes to replace the index scan + Unique class
(distinct selection) for loose index scan that visits all the rows of a
covering index instead of jumping in the begining of each group.
TODO: Placeholder function. To be replaced by a handler API call
@param is_index_scan hint to use index scan instead of random index read
to find the next different value.
@param file table handler
@param key_part group key to compare
@param record row data
@param group_prefix current key prefix data
@param group_prefix_len length of the current key prefix data
@param group_key_parts number of the current key prefix columns
@return status
@retval 0 success
@retval !0 failure
*/
static int index_next_different (bool is_index_scan, handler *file,
KEY_PART_INFO *key_part, uchar * record,
const uchar * group_prefix,
uint group_prefix_len,
uint group_key_parts)
{
if (is_index_scan)
{
int result= 0;
while (!key_cmp (key_part, group_prefix, group_prefix_len))
{
result= file->index_next(record);
if (result)
return(result);
}
return result;
}
else
return file->index_read_map(record, group_prefix,
make_prev_keypart_map(group_key_parts),
HA_READ_AFTER_KEY);
}
/*
Determine the prefix of the next group.
@ -10790,9 +10876,9 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_prefix()
else
{
/* Load the first key in this group into record. */
result= file->index_read_map(record, group_prefix,
make_prev_keypart_map(group_key_parts),
HA_READ_AFTER_KEY);
result= index_next_different (is_index_scan, file, index_info->key_part,
record, group_prefix, group_prefix_len,
group_key_parts);
if (result)
DBUG_RETURN(result);
}

View File

@ -616,6 +616,7 @@ private:
uchar *last_prefix; /* Prefix of the last group for detecting EOF. */
bool have_min; /* Specify whether we are computing */
bool have_max; /* a MIN, a MAX, or both. */
bool have_agg_distinct;/* aggregate_function(DISTINCT ...). */
bool seen_first_key; /* Denotes whether the first key was retrieved.*/
KEY_PART_INFO *min_max_arg_part; /* The keypart of the only argument field */
/* of all MIN/MAX functions. */
@ -629,6 +630,11 @@ private:
List<Item_sum> *max_functions;
List_iterator<Item_sum> *min_functions_it;
List_iterator<Item_sum> *max_functions_it;
/*
Use index scan to get the next different key instead of jumping into it
through index read
*/
bool is_index_scan;
public:
/*
The following two members are public to allow easy access from
@ -646,12 +652,13 @@ private:
void update_max_result();
public:
QUICK_GROUP_MIN_MAX_SELECT(TABLE *table, JOIN *join, bool have_min,
bool have_max, KEY_PART_INFO *min_max_arg_part,
bool have_max, bool have_agg_distinct,
KEY_PART_INFO *min_max_arg_part,
uint group_prefix_len, uint group_key_parts,
uint used_key_parts, KEY *index_info, uint
use_index, double read_cost, ha_rows records, uint
key_infix_len, uchar *key_infix, MEM_ROOT
*parent_alloc);
*parent_alloc, bool is_index_scan);
~QUICK_GROUP_MIN_MAX_SELECT();
bool add_range(SEL_ARG *sel_range);
void update_key_stat();
@ -667,6 +674,12 @@ public:
#ifndef DBUG_OFF
void dbug_dump(int indent, bool verbose);
#endif
bool is_agg_distinct() { return have_agg_distinct; }
virtual void append_loose_scan_type(String *str)
{
if (is_index_scan)
str->append(STRING_WITH_LEN(" (scanning)"));
}
};

View File

@ -355,10 +355,13 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
const_result= 0;
break;
}
item_sum->set_aggregator (item_sum->with_distinct ?
Aggregator::DISTINCT_AGGREGATOR :
Aggregator::SIMPLE_AGGREGATOR);
if (!count)
{
/* If count == 0, then we know that is_exact_count == TRUE. */
((Item_sum_min*) item_sum)->clear(); /* Set to NULL. */
((Item_sum_min*) item_sum)->aggregator_clear(); /* Set to NULL. */
}
else
((Item_sum_min*) item_sum)->reset(); /* Set to the constant value. */
@ -443,10 +446,13 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
const_result= 0;
break;
}
item_sum->set_aggregator (item_sum->with_distinct ?
Aggregator::DISTINCT_AGGREGATOR :
Aggregator::SIMPLE_AGGREGATOR);
if (!count)
{
/* If count != 1, then we know that is_exact_count == TRUE. */
((Item_sum_max*) item_sum)->clear(); /* Set to NULL. */
((Item_sum_max*) item_sum)->aggregator_clear(); /* Set to NULL. */
}
else
((Item_sum_max*) item_sum)->reset(); /* Set to the constant value. */

View File

@ -32,7 +32,8 @@ enum partition_state {
PART_REORGED_DROPPED= 5,
PART_CHANGED= 6,
PART_IS_CHANGED= 7,
PART_IS_ADDED= 8
PART_IS_ADDED= 8,
PART_ADMIN= 9
};
/*

View File

@ -434,7 +434,7 @@ static sys_var_thd_enum sys_myisam_stats_method(&vars, "myisam_stats_met
&myisam_stats_method_typelib,
NULL);
#ifdef __NT__
#ifdef _WIN32
/* purecov: begin inspected */
static sys_var_const sys_named_pipe(&vars, "named_pipe",
OPT_GLOBAL, SHOW_MY_BOOL,

View File

@ -54,6 +54,7 @@
class Reprepare_observer
{
public:
Reprepare_observer() {}
/**
Check if a change of metadata is OK. In future
the signature of this method may be extended to accept the old

View File

@ -39,10 +39,6 @@
#define MIN_HANDSHAKE_SIZE 6
#endif /* HAVE_OPENSSL */
#ifdef __WIN__
extern void win_install_sigabrt_handler();
#endif
/*
Get structure for logging connection data for the current user
*/
@ -612,13 +608,8 @@ void thd_init_client_charset(THD *thd, uint cs_number)
bool init_new_connection_handler_thread()
{
pthread_detach_this_thread();
#if defined(__WIN__)
win_install_sigabrt_handler();
#else
/* Win32 calls this in pthread_create */
if (my_thread_init())
return 1;
#endif /* __WIN__ */
return 0;
}
@ -958,7 +949,7 @@ static bool login_connection(THD *thd)
if (error)
{ // Wrong permissions
#ifdef __NT__
#ifdef _WIN32
if (vio_type(net->vio) == VIO_TYPE_NAMEDPIPE)
my_sleep(1000); /* must wait after eof() */
#endif

View File

@ -1075,6 +1075,7 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
{
handlerton *table_type= table->s->db_type();
TABLE_SHARE *share= table->s;
/* Note that a temporary table cannot be partitioned */
if (!ha_check_storage_engine_flag(table_type, HTON_CAN_RECREATE))
goto trunc_by_del;
@ -1113,8 +1114,22 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
table_list->db, table_list->table_name);
DBUG_RETURN(TRUE);
}
if (!ha_check_storage_engine_flag(ha_resolve_by_legacy_type(thd, table_type),
HTON_CAN_RECREATE))
#ifdef WITH_PARTITION_STORAGE_ENGINE
/*
TODO: Add support for TRUNCATE PARTITION for NDB and other engines
supporting native partitioning
*/
if (table_type != DB_TYPE_PARTITION_DB &&
thd->lex->alter_info.flags & ALTER_ADMIN_PARTITION)
{
my_error(ER_PARTITION_MGMT_ON_NONPARTITIONED, MYF(0));
DBUG_RETURN(TRUE);
}
#endif
if (!ha_check_storage_engine_flag(ha_resolve_by_legacy_type(thd,
table_type),
HTON_CAN_RECREATE) ||
thd->lex->alter_info.flags & ALTER_ADMIN_PARTITION)
goto trunc_by_del;
if (lock_and_wait_for_table_name(thd, table_list))

View File

@ -2498,7 +2498,6 @@ pthread_handler_t handle_delayed_insert(void *arg)
since it does not find one in the list.
*/
pthread_mutex_lock(&di->mutex);
#if !defined( __WIN__) /* Win32 calls this in pthread_create */
if (my_thread_init())
{
/* Can't use my_error since store_globals has not yet been called */
@ -2506,13 +2505,9 @@ pthread_handler_t handle_delayed_insert(void *arg)
ER(ER_OUT_OF_RESOURCES), NULL);
goto end;
}
#endif
handle_delayed_insert_impl(thd, di);
#ifndef __WIN__
end:
#endif
/*
di should be unlinked from the thread handler list and have no active
clients

View File

@ -4185,13 +4185,15 @@ uint set_part_state(Alter_info *alter_info, partition_info *tab_part_info,
/*
Mark the partition.
I.e mark the partition as a partition to be "changed" by
analyzing/optimizing/rebuilding/checking/repairing
analyzing/optimizing/rebuilding/checking/repairing/...
*/
no_parts_found++;
part_elem->part_state= part_state;
DBUG_PRINT("info", ("Setting part_state to %u for partition %s",
part_state, part_elem->partition_name));
}
else
part_elem->part_state= PART_NORMAL;
} while (++part_count < tab_part_info->no_parts);
return no_parts_found;
}

View File

@ -222,6 +222,7 @@ static void update_tmptable_sum_func(Item_sum **func,TABLE *tmp_table);
static void copy_sum_funcs(Item_sum **func_ptr, Item_sum **end);
static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab);
static bool setup_sum_funcs(THD *thd, Item_sum **func_ptr);
static bool prepare_sum_aggregators(Item_sum **func_ptr, bool need_distinct);
static bool init_sum_functions(Item_sum **func, Item_sum **end);
static bool update_sum_func(Item_sum **func);
static void select_describe(JOIN *join, bool need_tmp_table,bool need_order,
@ -1232,7 +1233,11 @@ JOIN::optimize()
if (test_if_subpart(group_list, order) ||
(!group_list && tmp_table_param.sum_func_count))
{
order=0;
if (is_indexed_agg_distinct(this, NULL))
sort_and_group= 0;
}
// Can't use sort on head table if using row cache
if (full_join)
@ -1410,8 +1415,16 @@ JOIN::optimize()
single table queries, thus it is sufficient to test only the first
join_tab element of the plan for its access method.
*/
bool need_distinct= TRUE;
if (join_tab->is_using_loose_index_scan())
{
tmp_table_param.precomputed_group_by= TRUE;
if (join_tab->is_using_agg_loose_index_scan())
{
need_distinct= FALSE;
tmp_table_param.precomputed_group_by= FALSE;
}
}
/* Create a tmp table if distinct or if the sort is too complicated */
if (need_tmp)
@ -1472,6 +1485,7 @@ JOIN::optimize()
HA_POS_ERROR, HA_POS_ERROR, FALSE) ||
alloc_group_fields(this, group_list) ||
make_sum_func_list(all_fields, fields_list, 1) ||
prepare_sum_aggregators(sum_funcs, need_distinct) ||
setup_sum_funcs(thd, sum_funcs))
{
DBUG_RETURN(1);
@ -1481,6 +1495,7 @@ JOIN::optimize()
else
{
if (make_sum_func_list(all_fields, fields_list, 0) ||
prepare_sum_aggregators(sum_funcs, need_distinct) ||
setup_sum_funcs(thd, sum_funcs))
{
DBUG_RETURN(1);
@ -1953,7 +1968,9 @@ JOIN::exec()
}
}
if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list,
1, TRUE))
1, TRUE) ||
prepare_sum_aggregators(curr_join->sum_funcs,
!curr_join->join_tab->is_using_agg_loose_index_scan()))
DBUG_VOID_RETURN;
curr_join->group_list= 0;
if (!curr_join->sort_and_group &&
@ -2056,6 +2073,8 @@ JOIN::exec()
if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list,
1, TRUE) ||
prepare_sum_aggregators (curr_join->sum_funcs, !curr_join->join_tab ||
!curr_join->join_tab->is_using_agg_loose_index_scan()) ||
setup_sum_funcs(curr_join->thd, curr_join->sum_funcs) ||
thd->is_fatal_error)
DBUG_VOID_RETURN;
@ -3937,6 +3956,82 @@ static void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array)
}
/**
Check for the presence of AGGFN(DISTINCT a) queries that may be subject
to loose index scan.
Check if the query is a subject to AGGFN(DISTINCT) using loose index scan
(QUICK_GROUP_MIN_MAX_SELECT).
Optionally (if out_args is supplied) will push the arguments of
AGGFN(DISTINCT) to the list
@param join the join to check
@param[out] out_args list of aggregate function arguments
@return does the query qualify for indexed AGGFN(DISTINCT)
@retval true it does
@retval false AGGFN(DISTINCT) must apply distinct in it.
*/
bool
is_indexed_agg_distinct(JOIN *join, List<Item_field> *out_args)
{
Item_sum **sum_item_ptr;
bool result= false;
if (join->tables != 1 || /* reference more than 1 table */
join->select_distinct || /* or a DISTINCT */
join->select_lex->olap == ROLLUP_TYPE) /* Check (B3) for ROLLUP */
return false;
if (join->make_sum_func_list(join->all_fields, join->fields_list, 1))
return false;
for (sum_item_ptr= join->sum_funcs; *sum_item_ptr; sum_item_ptr++)
{
Item_sum *sum_item= *sum_item_ptr;
Item *expr;
/* aggregate is not AGGFN(DISTINCT) or more than 1 argument to it */
switch (sum_item->sum_func())
{
case Item_sum::MIN_FUNC:
case Item_sum::MAX_FUNC:
continue;
case Item_sum::COUNT_DISTINCT_FUNC:
break;
case Item_sum::AVG_DISTINCT_FUNC:
case Item_sum::SUM_DISTINCT_FUNC:
if (sum_item->get_arg_count() == 1)
break;
/* fall through */
default: return false;
}
/*
We arrive here for every COUNT(DISTINCT),AVG(DISTINCT) or SUM(DISTINCT).
Collect the arguments of the aggregate functions to a list.
We don't worry about duplicates as these will be sorted out later in
get_best_group_min_max
*/
for (uint i= 0; i < sum_item->get_arg_count(); i++)
{
expr= sum_item->get_arg(i);
/* The AGGFN(DISTINCT) arg is not an attribute? */
if (expr->real_item()->type() != Item::FIELD_ITEM)
return false;
/*
If we came to this point the AGGFN(DISTINCT) loose index scan
optimization is applicable
*/
if (out_args)
out_args->push_back((Item_field *) expr);
result= true;
}
}
return result;
}
/**
Discover the indexes that can be used for GROUP BY or DISTINCT queries.
@ -3979,6 +4074,10 @@ add_group_and_distinct_keys(JOIN *join, JOIN_TAB *join_tab)
item->walk(&Item::collect_item_field_processor, 0,
(uchar*) &indexed_fields);
}
else if (is_indexed_agg_distinct(join, &indexed_fields))
{
join->sort_and_group= 1;
}
else
return;
@ -10377,6 +10476,7 @@ TABLE *create_virtual_tmp_table(THD *thd, List<Create_field> &field_list)
bzero(share, sizeof(*share));
table->field= field;
table->s= share;
table->temp_pool_slot= MY_BIT_NONE;
share->blob_field= blob_field;
share->fields= field_count;
share->blob_ptr_size= portable_sizeof_char_ptr;
@ -14532,7 +14632,7 @@ setup_new_fields(THD *thd, List<Item> &fields,
optimize away 'order by'.
*/
static ORDER *
ORDER *
create_distinct_group(THD *thd, Item **ref_pointer_array,
ORDER *order_list, List<Item> &fields,
List<Item> &all_fields,
@ -15334,7 +15434,22 @@ static bool setup_sum_funcs(THD *thd, Item_sum **func_ptr)
DBUG_ENTER("setup_sum_funcs");
while ((func= *(func_ptr++)))
{
if (func->setup(thd))
if (func->aggregator_setup(thd))
DBUG_RETURN(TRUE);
}
DBUG_RETURN(FALSE);
}
static bool prepare_sum_aggregators(Item_sum **func_ptr, bool need_distinct)
{
Item_sum *func;
DBUG_ENTER("setup_sum_funcs");
while ((func= *(func_ptr++)))
{
if (func->set_aggregator(need_distinct && func->with_distinct ?
Aggregator::DISTINCT_AGGREGATOR :
Aggregator::SIMPLE_AGGREGATOR))
DBUG_RETURN(TRUE);
}
DBUG_RETURN(FALSE);
@ -15384,7 +15499,7 @@ init_sum_functions(Item_sum **func_ptr, Item_sum **end_ptr)
/* If rollup, calculate the upper sum levels */
for ( ; *func_ptr ; func_ptr++)
{
if ((*func_ptr)->add())
if ((*func_ptr)->aggregator_add())
return 1;
}
return 0;
@ -15396,7 +15511,7 @@ update_sum_func(Item_sum **func_ptr)
{
Item_sum *func;
for (; (func= (Item_sum*) *func_ptr) ; func_ptr++)
if (func->add())
if (func->aggregator_add())
return 1;
return 0;
}
@ -16313,7 +16428,12 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
if (key_read)
{
if (quick_type == QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX)
{
QUICK_GROUP_MIN_MAX_SELECT *qgs=
(QUICK_GROUP_MIN_MAX_SELECT *) tab->select->quick;
extra.append(STRING_WITH_LEN("; Using index for group-by"));
qgs->append_loose_scan_type(&extra);
}
else
extra.append(STRING_WITH_LEN("; Using index"));
}

View File

@ -218,6 +218,11 @@ typedef struct st_join_table {
(select->quick->get_type() ==
QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX));
}
bool is_using_agg_loose_index_scan ()
{
return (is_using_loose_index_scan() &&
((QUICK_GROUP_MIN_MAX_SELECT *)select->quick)->is_agg_distinct());
}
} JOIN_TAB;
enum_nested_loop_state sub_select_cache(JOIN *join, JOIN_TAB *join_tab, bool
@ -564,6 +569,8 @@ Field* create_tmp_field_from_field(THD *thd, Field* org_field,
const char *name, TABLE *table,
Item_field *item, uint convert_blob_length);
bool is_indexed_agg_distinct(JOIN *join, List<Item_field> *out_args);
/* functions from opt_sum.cc */
bool simple_pred(Item_func *func_item, Item **args, bool *inv_order);
int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds);

View File

@ -4567,6 +4567,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
/*
Set up which partitions that should be processed
if ALTER TABLE t ANALYZE/CHECK/OPTIMIZE/REPAIR PARTITION ..
CACHE INDEX/LOAD INDEX for specified partitions
*/
Alter_info *alter_info= &lex->alter_info;
@ -4580,7 +4581,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
uint no_parts_found;
uint no_parts_opt= alter_info->partition_names.elements;
no_parts_found= set_part_state(alter_info, table->table->part_info,
PART_CHANGED);
PART_ADMIN);
if (no_parts_found != no_parts_opt &&
(!(alter_info->flags & ALTER_ALL_PARTITION)))
{

View File

@ -1278,7 +1278,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
slave master_def master_defs master_file_def slave_until_opts
repair restore backup analyze check start checksum
field_list field_list_item field_spec kill column_def key_def
keycache_list assign_to_keycache preload_list preload_keys
keycache_list keycache_list_or_parts assign_to_keycache
assign_to_keycache_parts
preload_list preload_list_or_parts preload_keys preload_keys_parts
select_item_list select_item values_list no_braces
opt_limit_clause delete_limit_clause fields opt_values values
procedure_list procedure_list2 procedure_item
@ -3933,17 +3935,9 @@ opt_partitioning:
;
partitioning:
PARTITION_SYM
PARTITION_SYM have_partitioning
{
#ifdef WITH_PARTITION_STORAGE_ENGINE
LEX *lex= Lex;
LEX_STRING partition_name={C_STRING_WITH_LEN("partition")};
if (!plugin_is_ready(&partition_name, MYSQL_STORAGE_ENGINE_PLUGIN))
{
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0),
"--skip-partition");
MYSQL_YYABORT;
}
lex->part_info= new partition_info();
if (!lex->part_info)
{
@ -3954,16 +3948,29 @@ partitioning:
{
lex->alter_info.flags|= ALTER_PARTITION;
}
#else
my_error(ER_FEATURE_DISABLED, MYF(0),
"partitioning", "--with-partition");
MYSQL_YYABORT;
#endif
}
partition
;
have_partitioning:
/* empty */
{
#ifdef WITH_PARTITION_STORAGE_ENGINE
LEX_STRING partition_name={C_STRING_WITH_LEN("partition")};
if (!plugin_is_ready(&partition_name, MYSQL_STORAGE_ENGINE_PLUGIN))
{
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0),
"--skip-partition");
MYSQL_YYABORT;
}
#else
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0),
"--skip-partition");
MYSQL_YYABORT;
#endif
}
;
partition_entry:
PARTITION_SYM
{
@ -5624,7 +5631,6 @@ alter:
if (!lex->select_lex.add_table_to_list(thd, $4, NULL,
TL_OPTION_UPDATING))
MYSQL_YYABORT;
lex->alter_info.reset();
lex->col_list.empty();
lex->select_lex.init_order();
lex->select_lex.db=
@ -5858,7 +5864,7 @@ alter_commands:
all_or_alt_part_name_list
{
LEX *lex= Lex;
lex->sql_command = SQLCOM_OPTIMIZE;
lex->sql_command= SQLCOM_OPTIMIZE;
lex->alter_info.flags|= ALTER_ADMIN_PARTITION;
lex->no_write_to_binlog= $3;
lex->check_opt.init();
@ -5868,7 +5874,7 @@ alter_commands:
all_or_alt_part_name_list
{
LEX *lex= Lex;
lex->sql_command = SQLCOM_ANALYZE;
lex->sql_command= SQLCOM_ANALYZE;
lex->alter_info.flags|= ALTER_ADMIN_PARTITION;
lex->no_write_to_binlog= $3;
lex->check_opt.init();
@ -5876,7 +5882,7 @@ alter_commands:
| CHECK_SYM PARTITION_SYM all_or_alt_part_name_list
{
LEX *lex= Lex;
lex->sql_command = SQLCOM_CHECK;
lex->sql_command= SQLCOM_CHECK;
lex->alter_info.flags|= ALTER_ADMIN_PARTITION;
lex->check_opt.init();
}
@ -5885,7 +5891,7 @@ alter_commands:
all_or_alt_part_name_list
{
LEX *lex= Lex;
lex->sql_command = SQLCOM_REPAIR;
lex->sql_command= SQLCOM_REPAIR;
lex->alter_info.flags|= ALTER_ADMIN_PARTITION;
lex->no_write_to_binlog= $3;
lex->check_opt.init();
@ -5898,6 +5904,13 @@ alter_commands:
lex->no_write_to_binlog= $3;
lex->alter_info.no_parts= $4;
}
| TRUNCATE_SYM PARTITION_SYM all_or_alt_part_name_list
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_TRUNCATE;
lex->alter_info.flags|= ALTER_ADMIN_PARTITION;
lex->check_opt.init();
}
| reorg_partition_rule
;
@ -6483,14 +6496,23 @@ table_to_table:
;
keycache:
CACHE_SYM INDEX_SYM keycache_list IN_SYM key_cache_name
CACHE_SYM INDEX_SYM
{
Lex->alter_info.reset();
}
keycache_list_or_parts IN_SYM key_cache_name
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_ASSIGN_TO_KEYCACHE;
lex->ident= $5;
lex->ident= $6;
}
;
keycache_list_or_parts:
keycache_list
| assign_to_keycache_parts
;
keycache_list:
assign_to_keycache
| keycache_list ',' assign_to_keycache
@ -6505,6 +6527,15 @@ assign_to_keycache:
}
;
assign_to_keycache_parts:
table_ident adm_partition cache_keys_spec
{
if (!Select->add_table_to_list(YYTHD, $1, NULL, 0, TL_READ,
Select->pop_index_hints()))
MYSQL_YYABORT;
}
;
key_cache_name:
ident { $$= $1; }
| DEFAULT { $$ = default_key_cache_base; }
@ -6515,11 +6546,17 @@ preload:
{
LEX *lex=Lex;
lex->sql_command=SQLCOM_PRELOAD_KEYS;
lex->alter_info.reset();
}
preload_list
preload_list_or_parts
{}
;
preload_list_or_parts:
preload_keys_parts
| preload_list
;
preload_list:
preload_keys
| preload_list ',' preload_keys
@ -6534,6 +6571,23 @@ preload_keys:
}
;
preload_keys_parts:
table_ident adm_partition cache_keys_spec opt_ignore_leaves
{
if (!Select->add_table_to_list(YYTHD, $1, NULL, $4, TL_READ,
Select->pop_index_hints()))
MYSQL_YYABORT;
}
;
adm_partition:
PARTITION_SYM have_partitioning
{
Lex->alter_info.flags|= ALTER_ADMIN_PARTITION;
}
'(' all_or_alt_part_name_list ')'
;
cache_keys_spec:
{
Lex->select_lex.alloc_index_hints(YYTHD);
@ -8128,7 +8182,7 @@ sum_expr:
}
| AVG_SYM '(' DISTINCT in_sum_expr ')'
{
$$= new (YYTHD->mem_root) Item_sum_avg_distinct($4);
$$= new (YYTHD->mem_root) Item_sum_avg($4, TRUE);
if ($$ == NULL)
MYSQL_YYABORT;
}
@ -8171,7 +8225,7 @@ sum_expr:
{ Select->in_sum_expr--; }
')'
{
$$= new (YYTHD->mem_root) Item_sum_count_distinct(* $5);
$$= new (YYTHD->mem_root) Item_sum_count(* $5);
if ($$ == NULL)
MYSQL_YYABORT;
}
@ -8236,7 +8290,7 @@ sum_expr:
}
| SUM_SYM '(' DISTINCT in_sum_expr ')'
{
$$= new (YYTHD->mem_root) Item_sum_sum_distinct($4);
$$= new (YYTHD->mem_root) Item_sum_sum($4, TRUE);
if ($$ == NULL)
MYSQL_YYABORT;
}
@ -9953,6 +10007,7 @@ truncate:
{
LEX* lex= Lex;
lex->sql_command= SQLCOM_TRUNCATE;
lex->alter_info.reset();
lex->select_lex.options= 0;
lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE_UNSPECIFIED;
lex->select_lex.init_order();

View File

@ -139,6 +139,11 @@ typedef long long longlong;
#include <mysql.h>
#include <ctype.h>
#ifdef _WIN32
/* inet_aton needs winsock library */
#pragma comment(lib, "ws2_32")
#endif
static pthread_mutex_t LOCK_hostname;
#ifdef HAVE_DLOPEN

View File

@ -13,9 +13,6 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake")
SET(BLACKHOLE_SOURCES ha_blackhole.cc ha_blackhole.h)

View File

@ -13,8 +13,6 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake")
SET(CSV_SOURCES ha_tina.cc ha_tina.h transparent_file.cc transparent_file.h)

View File

@ -13,8 +13,6 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake")
SET(EXAMPLE_SOURCES ha_example.cc)
MYSQL_STORAGE_ENGINE(EXAMPLE)

View File

@ -13,8 +13,6 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake")
SET(HEAP_SOURCES _check.c _rectest.c hp_block.c hp_clear.c hp_close.c hp_create.c

View File

@ -16,11 +16,7 @@
# 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")
INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake")
# Include directories under innobase

View File

@ -15,8 +15,6 @@
INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake")
INCLUDE("${PROJECT_SOURCE_DIR}/win/mysql_manifest.cmake")
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
SET(MYISAM_SOURCES ft_boolean_search.c ft_nlq_search.c ft_parser.c ft_static.c ft_stem.c
ha_myisam.cc
@ -34,16 +32,16 @@ MYSQL_STORAGE_ENGINE(MYISAM)
IF(NOT SOURCE_SUBLIBS)
ADD_EXECUTABLE(myisam_ftdump myisam_ftdump.c)
TARGET_LINK_LIBRARIES(myisam_ftdump myisam mysys debug dbug strings zlib wsock32)
TARGET_LINK_LIBRARIES(myisam_ftdump myisam mysys dbug strings zlib)
ADD_EXECUTABLE(myisamchk myisamchk.c)
TARGET_LINK_LIBRARIES(myisamchk myisam mysys debug dbug strings zlib wsock32)
TARGET_LINK_LIBRARIES(myisamchk myisam mysys dbug strings zlib)
ADD_EXECUTABLE(myisamlog myisamlog.c)
TARGET_LINK_LIBRARIES(myisamlog myisam mysys debug dbug strings zlib wsock32)
TARGET_LINK_LIBRARIES(myisamlog myisam mysys dbug strings zlib)
ADD_EXECUTABLE(myisampack myisampack.c)
TARGET_LINK_LIBRARIES(myisampack myisam mysys debug dbug strings zlib wsock32)
TARGET_LINK_LIBRARIES(myisampack myisam mysys dbug strings zlib)
SET_TARGET_PROPERTIES(myisamchk myisampack PROPERTIES LINK_FLAGS "setargv.obj")

View File

@ -12,8 +12,6 @@
# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake")

View File

@ -13,9 +13,6 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG -DSAFEMALLOC -DSAFE_MUTEX")
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG -DSAFEMALLOC -DSAFE_MUTEX")
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
SET(STRINGS_SOURCES bchange.c bcmp.c bfill.c bmove512.c bmove_upp.c ctype-big5.c ctype-bin.c ctype-cp932.c

View File

@ -13,15 +13,12 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# About "mysqlclient_notls", see note in "client/CMakeLists.txt"
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
ADD_DEFINITIONS("-DMYSQL_CLIENT")
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
ADD_EXECUTABLE(mysql_client_test mysql_client_test.c ../mysys/my_memmem.c)
TARGET_LINK_LIBRARIES(mysql_client_test mysqlclient_notls wsock32)
TARGET_LINK_LIBRARIES(mysql_client_test mysqlclient)
ADD_EXECUTABLE(bug25714 bug25714.c)
TARGET_LINK_LIBRARIES(bug25714 mysqlclient_notls wsock32)
TARGET_LINK_LIBRARIES(bug25714 mysqlclient)

View File

@ -13,8 +13,6 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG -DSAFEMALLOC -DSAFE_MUTEX")
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG -DSAFEMALLOC -DSAFE_MUTEX")
ADD_DEFINITIONS(-DUSE_SYMDIR)
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/extra/yassl/include)

View File

@ -264,7 +264,7 @@ int vio_close(Vio * vio)
#ifdef __WIN__
if (vio->type == VIO_TYPE_NAMEDPIPE)
{
#if defined(__NT__) && defined(MYSQL_SERVER)
#if defined(MYSQL_SERVER)
CancelIo(vio->hPipe);
DisconnectNamedPipe(vio->hPipe);
#endif
@ -450,7 +450,7 @@ int vio_close_pipe(Vio * vio)
{
int r;
DBUG_ENTER("vio_close_pipe");
#if defined(__NT__) && defined(MYSQL_SERVER)
#if defined(MYSQL_SERVER)
CancelIo(vio->hPipe);
DisconnectNamedPipe(vio->hPipe);
#endif