weave merge of mysql-5.5->mysql-5.5-security

This commit is contained in:
Georgi Kodinov 2011-05-10 17:20:26 +03:00
commit 712f2d3833
199 changed files with 4845 additions and 1738 deletions

View File

@ -43,6 +43,10 @@
*.vcxproj *.vcxproj
*.vcxproj.filters *.vcxproj.filters
*/*.dir/* */*.dir/*
*.dir
Debug
MySql.sdf
Win32
*/*_pure_*warnings */*_pure_*warnings
*/.deps */.deps
*/.libs/* */.libs/*
@ -615,6 +619,7 @@ include/mysql_h.ic
include/mysql_version.h include/mysql_version.h
include/mysqld_ername.h include/mysqld_ername.h
include/mysqld_error.h include/mysqld_error.h
include/mysqld_error.h.rule
include/openssl include/openssl
include/probes_mysql_dtrace.h include/probes_mysql_dtrace.h
include/readline include/readline
@ -1897,7 +1902,9 @@ scripts/mysql_find_rows
scripts/mysql_fix_extensions scripts/mysql_fix_extensions
scripts/mysql_fix_privilege_tables scripts/mysql_fix_privilege_tables
scripts/mysql_fix_privilege_tables.sql scripts/mysql_fix_privilege_tables.sql
scripts/mysql_fix_privilege_tables.sql.rule
scripts/mysql_fix_privilege_tables_sql.c scripts/mysql_fix_privilege_tables_sql.c
scripts/mysql_fix_privilege_tables_sql.c.rule
scripts/mysql_install_db scripts/mysql_install_db
scripts/mysql_secure_installation scripts/mysql_secure_installation
scripts/mysql_setpermission scripts/mysql_setpermission
@ -2137,6 +2144,7 @@ sql/handlerton.cc
sql/html sql/html
sql/latex sql/latex
sql/lex_hash.h sql/lex_hash.h
sql/lex_hash.h.rule
sql/link_sources sql/link_sources
sql/max/* sql/max/*
sql/message.h sql/message.h
@ -2168,6 +2176,7 @@ sql/sql_builtin.cc
sql/sql_select.cc.orig sql/sql_select.cc.orig
sql/sql_yacc.cc sql/sql_yacc.cc
sql/sql_yacc.h sql/sql_yacc.h
sql/sql_yacc.h.rule
sql/sql_yacc.output sql/sql_yacc.output
sql/sql_yacc.yy.orig sql/sql_yacc.yy.orig
sql/test_time sql/test_time

View File

@ -31,6 +31,7 @@ Usage: $0 [-h|-n] [configure-options]
-h, --help Show this help message. -h, --help Show this help message.
-n, --just-print Don't actually run any commands; just print them. -n, --just-print Don't actually run any commands; just print them.
-c, --just-configure Stop after running configure. -c, --just-configure Stop after running configure.
--with-debug=full Build with full debug(no optimizations, keep call stack).
--warning-mode=[old|pedantic|maintainer] --warning-mode=[old|pedantic|maintainer]
Influences the debug flags. Old is default. Influences the debug flags. Old is default.
--prefix=path Build with prefix 'path'. --prefix=path Build with prefix 'path'.
@ -46,6 +47,8 @@ parse_options()
case "$1" in case "$1" in
--prefix=*) --prefix=*)
prefix=`get_key_value "$1"`;; prefix=`get_key_value "$1"`;;
--with-debug=full)
full_debug="=full";;
--warning-mode=*) --warning-mode=*)
warning_mode=`get_key_value "$1"`;; warning_mode=`get_key_value "$1"`;;
-c | --just-configure) -c | --just-configure)
@ -76,6 +79,7 @@ just_print=
just_configure= just_configure=
warning_mode= warning_mode=
maintainer_mode= maintainer_mode=
full_debug=
parse_options "$@" parse_options "$@"
@ -154,7 +158,11 @@ base_cxxflags="-felide-constructors -fno-exceptions -fno-rtti"
fast_cflags="-O3 -fno-omit-frame-pointer" fast_cflags="-O3 -fno-omit-frame-pointer"
debug_configs="--with-debug" debug_configs="--with-debug"
debug_cflags="$debug_cflags $debug_extra_cflags" if [ -z "$full_debug" ]
then
debug_cflags="$debug_cflags $debug_extra_cflags"
fi
# #
# Configuration options. # Configuration options.

View File

@ -966,7 +966,8 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
passed --short-form, because --short-form disables printing passed --short-form, because --short-form disables printing
row events. row events.
*/ */
if (!print_event_info->printed_fd_event && !short_form) if (!print_event_info->printed_fd_event && !short_form &&
opt_base64_output_mode != BASE64_OUTPUT_DECODE_ROWS)
{ {
const char* type_str= ev->get_type_str(); const char* type_str= ev->get_type_str();
if (opt_base64_output_mode == BASE64_OUTPUT_NEVER) if (opt_base64_output_mode == BASE64_OUTPUT_NEVER)

View File

@ -4598,13 +4598,14 @@ static int my_kill(int pid, int sig)
command called command command called command
DESCRIPTION DESCRIPTION
shutdown [<timeout>] shutdown_server [<timeout>]
*/ */
void do_shutdown_server(struct st_command *command) void do_shutdown_server(struct st_command *command)
{ {
int timeout=60, pid; long timeout=60;
int pid;
DYNAMIC_STRING ds_pidfile_name; DYNAMIC_STRING ds_pidfile_name;
MYSQL* mysql = &cur_con->mysql; MYSQL* mysql = &cur_con->mysql;
static DYNAMIC_STRING ds_timeout; static DYNAMIC_STRING ds_timeout;
@ -4619,8 +4620,9 @@ void do_shutdown_server(struct st_command *command)
if (ds_timeout.length) if (ds_timeout.length)
{ {
timeout= atoi(ds_timeout.str); char* endptr;
if (timeout == 0) timeout= strtol(ds_timeout.str, &endptr, 10);
if (*endptr != '\0')
die("Illegal argument for timeout: '%s'", ds_timeout.str); die("Illegal argument for timeout: '%s'", ds_timeout.str);
} }
dynstr_free(&ds_timeout); dynstr_free(&ds_timeout);
@ -4662,7 +4664,7 @@ void do_shutdown_server(struct st_command *command)
DBUG_PRINT("info", ("Process %d does not exist anymore", pid)); DBUG_PRINT("info", ("Process %d does not exist anymore", pid));
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
DBUG_PRINT("info", ("Sleeping, timeout: %d", timeout)); DBUG_PRINT("info", ("Sleeping, timeout: %ld", timeout));
my_sleep(1000000L); my_sleep(1000000L);
} }
@ -10069,7 +10071,7 @@ int find_set(REP_SETS *sets,REP_SET *find)
return i; return i;
} }
} }
return i; /* return new postion */ return i; /* return new position */
} }
/* find if there is a found_set with same table_offset & found_offset /* find if there is a found_set with same table_offset & found_offset
@ -10089,7 +10091,7 @@ int find_found(FOUND_SET *found_set,uint table_offset, int found_offset)
found_set[i].table_offset=table_offset; found_set[i].table_offset=table_offset;
found_set[i].found_offset=found_offset; found_set[i].found_offset=found_offset;
found_sets++; found_sets++;
return -i-2; /* return new postion */ return -i-2; /* return new position */
} }
/* Return 1 if regexp starts with \b or ends with \b*/ /* Return 1 if regexp starts with \b or ends with \b*/

View File

@ -19,8 +19,16 @@
# plugin_audit.h and plugin_ftparser.h. # plugin_audit.h and plugin_ftparser.h.
# #
# We use gcc specific preprocessing command and sed/diff, so it will # We use gcc specific preprocessing command and sed/diff, so it will
# only be run on Unix and only if gcc is used. # only be run on Unix and only if gcc is used. On some Unixes,
IF(CMAKE_COMPILER_IS_GNUCC AND CMAKE_SYSTEM_NAME MATCHES "Linux") # (Solaris) sed or diff might act differently from GNU, so we run only
# on systems we can trust.
IF(APPLE OR CMAKE_SYSTEM_NAME MATCHES "Linux")
SET(RUN_ABI_CHECK 1)
ELSE()
SET(RUN_ABI_CHECK 0)
ENDIF()
IF(CMAKE_COMPILER_IS_GNUCC AND RUN_ABI_CHECK)
IF(CMAKE_C_COMPILER MATCHES "ccache$") IF(CMAKE_C_COMPILER MATCHES "ccache$")
SET(COMPILER ${CMAKE_C_COMPILER_ARG1}) SET(COMPILER ${CMAKE_C_COMPILER_ARG1})
STRING(REGEX REPLACE "^ " "" COMPILER ${COMPILER}) STRING(REGEX REPLACE "^ " "" COMPILER ${COMPILER})

View File

@ -35,7 +35,7 @@ ENDMACRO()
# Setup G++ (GNU C++ compiler) warning options. # Setup G++ (GNU C++ compiler) warning options.
MACRO(SET_MYSQL_MAINTAINER_GNU_CXX_OPTIONS) MACRO(SET_MYSQL_MAINTAINER_GNU_CXX_OPTIONS)
SET(MY_MAINTAINER_CXX_WARNINGS SET(MY_MAINTAINER_CXX_WARNINGS
"${MY_MAINTAINER_WARNINGS} -Wno-unused-parameter" "${MY_MAINTAINER_WARNINGS} -Wno-unused-parameter -Woverloaded-virtual"
CACHE STRING "C++ warning options used in maintainer builds.") CACHE STRING "C++ warning options used in maintainer builds.")
ENDMACRO() ENDMACRO()

View File

@ -1,4 +1,4 @@
# Copyright (C) 2010 Sun Microsystems, Inc # Copyright (C) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@ -192,3 +192,4 @@ IF(NOT HAVE_SIZE_OF_SSIZE_T)
ENDIF() ENDIF()
SET(FN_NO_CASE_SENSE 1) SET(FN_NO_CASE_SENSE 1)
SET(USE_SYMDIR 1)

View File

@ -76,9 +76,6 @@ SET(HAVE_FTRUNCATE CACHE INTERNAL "")
SET(HAVE_GETADDRINFO 1 CACHE INTERNAL "") SET(HAVE_GETADDRINFO 1 CACHE INTERNAL "")
SET(HAVE_GETCWD 1 CACHE INTERNAL "") SET(HAVE_GETCWD 1 CACHE INTERNAL "")
SET(HAVE_GETHOSTBYADDR_R CACHE INTERNAL "") SET(HAVE_GETHOSTBYADDR_R CACHE INTERNAL "")
SET(HAVE_GETHOSTBYNAME_R CACHE INTERNAL "")
SET(HAVE_GETHOSTBYNAME_R_GLIBC2_STYLE CACHE INTERNAL "")
SET(HAVE_GETHOSTBYNAME_R_RETURN_INT CACHE INTERNAL "")
SET(HAVE_GETHRTIME CACHE INTERNAL "") SET(HAVE_GETHRTIME CACHE INTERNAL "")
SET(HAVE_GETLINE CACHE INTERNAL "") SET(HAVE_GETLINE CACHE INTERNAL "")
SET(HAVE_GETNAMEINFO CACHE INTERNAL "") SET(HAVE_GETNAMEINFO CACHE INTERNAL "")
@ -104,6 +101,10 @@ SET(HAVE_IPV6_V6ONLY 1 CACHE INTERNAL "")
SET(HAVE_ISINF CACHE INTERNAL "") SET(HAVE_ISINF CACHE INTERNAL "")
SET(HAVE_ISNAN CACHE INTERNAL "") SET(HAVE_ISNAN CACHE INTERNAL "")
SET(HAVE_ISSETUGID CACHE INTERNAL "") SET(HAVE_ISSETUGID CACHE INTERNAL "")
SET(HAVE_GETUID CACHE INTERNAL "")
SET(HAVE_GETEUID CACHE INTERNAL "")
SET(HAVE_GETGID CACHE INTERNAL "")
SET(HAVE_GETEGID CACHE INTERNAL "")
SET(HAVE_LANGINFO_H CACHE INTERNAL "") SET(HAVE_LANGINFO_H CACHE INTERNAL "")
SET(HAVE_LDIV 1 CACHE INTERNAL "") SET(HAVE_LDIV 1 CACHE INTERNAL "")
SET(HAVE_LIMITS_H 1 CACHE INTERNAL "") SET(HAVE_LIMITS_H 1 CACHE INTERNAL "")

View File

@ -478,7 +478,13 @@ el_source(EditLine *el, const char *fname)
fp = NULL; fp = NULL;
if (fname == NULL) { if (fname == NULL) {
#ifdef HAVE_ISSETUGID /* XXXMYSQL: Bug#49967 */
#if defined(HAVE_GETUID) && defined(HAVE_GETEUID) && \
defined(HAVE_GETGID) && defined(HAVE_GETEGID)
#define HAVE_IDENTITY_FUNCS 1
#endif
#if (defined(HAVE_ISSETUGID) || defined(HAVE_IDENTITY_FUNCS))
static const char elpath[] = "/.editrc"; static const char elpath[] = "/.editrc";
/* XXXMYSQL: Portability fix (for which platforms?) */ /* XXXMYSQL: Portability fix (for which platforms?) */
#ifdef MAXPATHLEN #ifdef MAXPATHLEN
@ -486,9 +492,13 @@ el_source(EditLine *el, const char *fname)
#else #else
char path[4096]; char path[4096];
#endif #endif
#ifdef HAVE_ISSETUGID
if (issetugid()) if (issetugid())
return (-1); return (-1);
#elif defined(HAVE_IDENTITY_FUNCS)
if (getuid() != geteuid() || getgid() != getegid())
return (-1);
#endif
if ((ptr = getenv("HOME")) == NULL) if ((ptr = getenv("HOME")) == NULL)
return (-1); return (-1);
if (strlcpy(path, ptr, sizeof(path)) >= sizeof(path)) if (strlcpy(path, ptr, sizeof(path)) >= sizeof(path))
@ -498,9 +508,10 @@ el_source(EditLine *el, const char *fname)
fname = path; fname = path;
#else #else
/* /*
* If issetugid() is missing, always return an error, in order * If issetugid() or the above mentioned get[e][u|g]id()
* to keep from inadvertently opening up the user to a security * functions are missing, always return an error, in order
* hole. * to keep from inadvertently opening up the user to a
* security hole.
*/ */
return (-1); return (-1);
#endif #endif

View File

@ -1012,8 +1012,10 @@ vi_histedit(EditLine *el, int c __attribute__((__unused__)))
if (fd < 0) if (fd < 0)
return CC_ERROR; return CC_ERROR;
cp = el->el_line.buffer; cp = el->el_line.buffer;
write(fd, cp, el->el_line.lastchar - cp +0u); if (write(fd, cp, el->el_line.lastchar - cp +0u) == -1)
write(fd, "\n", 1); goto error;
if (write(fd, "\n", 1) == -1)
goto error;
pid = fork(); pid = fork();
switch (pid) { switch (pid) {
case -1: case -1:
@ -1041,6 +1043,12 @@ vi_histedit(EditLine *el, int c __attribute__((__unused__)))
unlink(tempfile); unlink(tempfile);
/* return CC_REFRESH; */ /* return CC_REFRESH; */
return ed_newline(el, 0); return ed_newline(el, 0);
/* XXXMYSQL: Avoid compiler warnings. */
error:
close(fd);
unlink(tempfile);
return CC_ERROR;
} }
/* vi_history_word(): /* vi_history_word():

View File

@ -125,6 +125,7 @@
#cmakedefine FIONREAD_IN_SYS_IOCTL 1 #cmakedefine FIONREAD_IN_SYS_IOCTL 1
#cmakedefine GWINSZ_IN_SYS_IOCTL 1 #cmakedefine GWINSZ_IN_SYS_IOCTL 1
#cmakedefine TIOCSTAT_IN_SYS_IOCTL 1 #cmakedefine TIOCSTAT_IN_SYS_IOCTL 1
#cmakedefine FIONREAD_IN_SYS_FILIO 1
/* Functions we may want to use. */ /* Functions we may want to use. */
#cmakedefine HAVE_AIOWAIT 1 #cmakedefine HAVE_AIOWAIT 1
@ -157,7 +158,6 @@
#cmakedefine HAVE_GETADDRINFO 1 #cmakedefine HAVE_GETADDRINFO 1
#cmakedefine HAVE_GETCWD 1 #cmakedefine HAVE_GETCWD 1
#cmakedefine HAVE_GETHOSTBYADDR_R 1 #cmakedefine HAVE_GETHOSTBYADDR_R 1
#cmakedefine HAVE_GETHOSTBYNAME_R 1
#cmakedefine HAVE_GETHRTIME 1 #cmakedefine HAVE_GETHRTIME 1
#cmakedefine HAVE_GETLINE 1 #cmakedefine HAVE_GETLINE 1
#cmakedefine HAVE_GETNAMEINFO 1 #cmakedefine HAVE_GETNAMEINFO 1
@ -174,6 +174,10 @@
#cmakedefine gmtime_r @gmtime_r@ #cmakedefine gmtime_r @gmtime_r@
#cmakedefine HAVE_INITGROUPS 1 #cmakedefine HAVE_INITGROUPS 1
#cmakedefine HAVE_ISSETUGID 1 #cmakedefine HAVE_ISSETUGID 1
#cmakedefine HAVE_GETUID 1
#cmakedefine HAVE_GETEUID 1
#cmakedefine HAVE_GETGID 1
#cmakedefine HAVE_GETEGID 1
#cmakedefine HAVE_ISNAN 1 #cmakedefine HAVE_ISNAN 1
#cmakedefine HAVE_ISINF 1 #cmakedefine HAVE_ISINF 1
#cmakedefine HAVE_LARGE_PAGE_OPTION 1 #cmakedefine HAVE_LARGE_PAGE_OPTION 1
@ -448,8 +452,6 @@
#cmakedefine HAVE_SOLARIS_STYLE_GETHOST 1 #cmakedefine HAVE_SOLARIS_STYLE_GETHOST 1
#cmakedefine HAVE_GETHOSTBYNAME_R_GLIBC2_STYLE 1
#cmakedefine HAVE_GETHOSTBYNAME_R_RETURN_INT 1
#cmakedefine MY_ATOMIC_MODE_DUMMY 1 #cmakedefine MY_ATOMIC_MODE_DUMMY 1
#cmakedefine MY_ATOMIC_MODE_RWLOCKS 1 #cmakedefine MY_ATOMIC_MODE_RWLOCKS 1
@ -513,6 +515,7 @@
#cmakedefine EXTRA_DEBUG 1 #cmakedefine EXTRA_DEBUG 1
#cmakedefine BACKUP_TEST 1 #cmakedefine BACKUP_TEST 1
#cmakedefine CYBOZU 1 #cmakedefine CYBOZU 1
#cmakedefine USE_SYMDIR 1
/* Character sets and collations */ /* Character sets and collations */
#cmakedefine MYSQL_DEFAULT_CHARSET_NAME "@MYSQL_DEFAULT_CHARSET_NAME@" #cmakedefine MYSQL_DEFAULT_CHARSET_NAME "@MYSQL_DEFAULT_CHARSET_NAME@"

View File

@ -350,7 +350,6 @@ CHECK_FUNCTION_EXISTS (fseeko HAVE_FSEEKO)
CHECK_FUNCTION_EXISTS (fsync HAVE_FSYNC) CHECK_FUNCTION_EXISTS (fsync HAVE_FSYNC)
CHECK_FUNCTION_EXISTS (getcwd HAVE_GETCWD) CHECK_FUNCTION_EXISTS (getcwd HAVE_GETCWD)
CHECK_FUNCTION_EXISTS (gethostbyaddr_r HAVE_GETHOSTBYADDR_R) CHECK_FUNCTION_EXISTS (gethostbyaddr_r HAVE_GETHOSTBYADDR_R)
CHECK_FUNCTION_EXISTS (gethostbyname_r HAVE_GETHOSTBYNAME_R)
CHECK_FUNCTION_EXISTS (gethrtime HAVE_GETHRTIME) CHECK_FUNCTION_EXISTS (gethrtime HAVE_GETHRTIME)
CHECK_FUNCTION_EXISTS (getnameinfo HAVE_GETNAMEINFO) CHECK_FUNCTION_EXISTS (getnameinfo HAVE_GETNAMEINFO)
CHECK_FUNCTION_EXISTS (getpass HAVE_GETPASS) CHECK_FUNCTION_EXISTS (getpass HAVE_GETPASS)
@ -363,6 +362,10 @@ CHECK_FUNCTION_EXISTS (getwd HAVE_GETWD)
CHECK_FUNCTION_EXISTS (gmtime_r HAVE_GMTIME_R) CHECK_FUNCTION_EXISTS (gmtime_r HAVE_GMTIME_R)
CHECK_FUNCTION_EXISTS (initgroups HAVE_INITGROUPS) CHECK_FUNCTION_EXISTS (initgroups HAVE_INITGROUPS)
CHECK_FUNCTION_EXISTS (issetugid HAVE_ISSETUGID) CHECK_FUNCTION_EXISTS (issetugid HAVE_ISSETUGID)
CHECK_FUNCTION_EXISTS (getuid HAVE_GETUID)
CHECK_FUNCTION_EXISTS (geteuid HAVE_GETEUID)
CHECK_FUNCTION_EXISTS (getgid HAVE_GETGID)
CHECK_FUNCTION_EXISTS (getegid HAVE_GETEGID)
CHECK_FUNCTION_EXISTS (ldiv HAVE_LDIV) CHECK_FUNCTION_EXISTS (ldiv HAVE_LDIV)
CHECK_FUNCTION_EXISTS (localtime_r HAVE_LOCALTIME_R) CHECK_FUNCTION_EXISTS (localtime_r HAVE_LOCALTIME_R)
CHECK_FUNCTION_EXISTS (longjmp HAVE_LONGJMP) CHECK_FUNCTION_EXISTS (longjmp HAVE_LONGJMP)
@ -488,6 +491,7 @@ CHECK_SYMBOL_EXISTS(getpagesize "unistd.h" HAVE_GETPAGESIZE)
CHECK_SYMBOL_EXISTS(TIOCGWINSZ "sys/ioctl.h" GWINSZ_IN_SYS_IOCTL) CHECK_SYMBOL_EXISTS(TIOCGWINSZ "sys/ioctl.h" GWINSZ_IN_SYS_IOCTL)
CHECK_SYMBOL_EXISTS(FIONREAD "sys/ioctl.h" FIONREAD_IN_SYS_IOCTL) CHECK_SYMBOL_EXISTS(FIONREAD "sys/ioctl.h" FIONREAD_IN_SYS_IOCTL)
CHECK_SYMBOL_EXISTS(TIOCSTAT "sys/ioctl.h" TIOCSTAT_IN_SYS_IOCTL) CHECK_SYMBOL_EXISTS(TIOCSTAT "sys/ioctl.h" TIOCSTAT_IN_SYS_IOCTL)
CHECK_SYMBOL_EXISTS(FIONREAD "sys/filio.h" FIONREAD_IN_SYS_FILIO)
CHECK_SYMBOL_EXISTS(gettimeofday "sys/time.h" HAVE_GETTIMEOFDAY) CHECK_SYMBOL_EXISTS(gettimeofday "sys/time.h" HAVE_GETTIMEOFDAY)
CHECK_SYMBOL_EXISTS(finite "math.h" HAVE_FINITE_IN_MATH_H) CHECK_SYMBOL_EXISTS(finite "math.h" HAVE_FINITE_IN_MATH_H)
@ -921,44 +925,6 @@ CHECK_CXX_SOURCE_COMPILES("
" "
HAVE_SOLARIS_STYLE_GETHOST) HAVE_SOLARIS_STYLE_GETHOST)
CHECK_CXX_SOURCE_COMPILES("
#undef inline
#if !defined(SCO) && !defined(__osf__) && !defined(_REENTRANT)
#define _REENTRANT
#endif
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
int main()
{
int ret = gethostbyname_r((const char *) 0,
(struct hostent*) 0, (char*) 0, 0, (struct hostent **) 0, (int *) 0);
return 0;
}"
HAVE_GETHOSTBYNAME_R_GLIBC2_STYLE)
CHECK_CXX_SOURCE_COMPILES("
#undef inline
#if !defined(SCO) && !defined(__osf__) && !defined(_REENTRANT)
#define _REENTRANT
#endif
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
int main()
{
int ret = gethostbyname_r((const char *) 0, (struct hostent*) 0, (struct hostent_data*) 0);
return 0;
}"
HAVE_GETHOSTBYNAME_R_RETURN_INT)
# Use of ALARMs to wakeup on timeout on sockets # Use of ALARMs to wakeup on timeout on sockets
# #
# This feature makes use of a mutex and is a scalability hog we # This feature makes use of a mutex and is a scalability hog we

View File

@ -1,17 +1,19 @@
/* Copyright (C) 2000 MySQL AB /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or
it under the terms of the GNU General Public License as published by modify it under the terms of the GNU General Public License
the Free Software Foundation; version 2 of the License. as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA */
/* /*
Replace strings in textfile Replace strings in textfile
@ -818,7 +820,7 @@ static short find_set(REP_SETS *sets,REP_SET *find)
return (short) i; return (short) i;
} }
} }
return (short) i; /* return new postion */ return (short) i; /* return new position */
} }
@ -841,7 +843,7 @@ static short find_found(FOUND_SET *found_set,uint table_offset,
found_set[i].table_offset=table_offset; found_set[i].table_offset=table_offset;
found_set[i].found_offset=found_offset; found_set[i].found_offset=found_offset;
found_sets++; found_sets++;
return (short) (-i-2); /* return new postion */ return (short) (-i-2); /* return new position */
} }
/* Return 1 if regexp starts with \b or ends with \b*/ /* Return 1 if regexp starts with \b or ends with \b*/

View File

@ -346,7 +346,7 @@ extern CHARSET_INFO my_charset_utf32_bin;
extern CHARSET_INFO my_charset_utf32_general_ci; extern CHARSET_INFO my_charset_utf32_general_ci;
extern CHARSET_INFO my_charset_utf32_unicode_ci; extern CHARSET_INFO my_charset_utf32_unicode_ci;
extern CHARSET_INFO my_charset_utf8_general_ci; extern MYSQL_PLUGIN_IMPORT CHARSET_INFO my_charset_utf8_general_ci;
extern CHARSET_INFO my_charset_utf8_unicode_ci; extern CHARSET_INFO my_charset_utf8_unicode_ci;
extern CHARSET_INFO my_charset_utf8_bin; extern CHARSET_INFO my_charset_utf8_bin;
extern CHARSET_INFO my_charset_utf8mb4_bin; extern CHARSET_INFO my_charset_utf8mb4_bin;

View File

@ -301,9 +301,6 @@ C_MODE_END
#undef HAVE_PWRITE #undef HAVE_PWRITE
#endif #endif
#ifdef UNDEF_HAVE_GETHOSTBYNAME_R /* For OSF4.x */
#undef HAVE_GETHOSTBYNAME_R
#endif
#ifdef UNDEF_HAVE_INITGROUPS /* For AIX 4.3 */ #ifdef UNDEF_HAVE_INITGROUPS /* For AIX 4.3 */
#undef HAVE_INITGROUPS #undef HAVE_INITGROUPS
#endif #endif

View File

@ -573,6 +573,8 @@ typedef struct st_mysql_bind
} MYSQL_BIND; } MYSQL_BIND;
struct st_mysql_stmt_extension;
/* statement handler */ /* statement handler */
typedef struct st_mysql_stmt typedef struct st_mysql_stmt
{ {
@ -618,7 +620,7 @@ typedef struct st_mysql_stmt
metadata fields when doing mysql_stmt_store_result. metadata fields when doing mysql_stmt_store_result.
*/ */
my_bool update_max_length; my_bool update_max_length;
void *extension; struct st_mysql_stmt_extension *extension;
} MYSQL_STMT; } MYSQL_STMT;
enum enum_stmt_attr_type enum enum_stmt_attr_type

View File

@ -512,6 +512,7 @@ typedef struct st_mysql_bind
my_bool is_null_value; my_bool is_null_value;
void *extension; void *extension;
} MYSQL_BIND; } MYSQL_BIND;
struct st_mysql_stmt_extension;
typedef struct st_mysql_stmt typedef struct st_mysql_stmt
{ {
MEM_ROOT mem_root; MEM_ROOT mem_root;
@ -541,7 +542,7 @@ typedef struct st_mysql_stmt
unsigned char bind_result_done; unsigned char bind_result_done;
my_bool unbuffered_fetch_cancelled; my_bool unbuffered_fetch_cancelled;
my_bool update_max_length; my_bool update_max_length;
void *extension; struct st_mysql_stmt_extension *extension;
} MYSQL_STMT; } MYSQL_STMT;
enum enum_stmt_attr_type enum enum_stmt_attr_type
{ {

View File

@ -156,8 +156,7 @@ mysql_client_register_plugin(struct st_mysql *mysql,
@retval 0 on success, 1 in case of failure @retval 0 on success, 1 in case of failure
**/ **/
int STDCALL mysql_plugin_options(struct st_mysql_client_plugin *plugin, int mysql_plugin_options(struct st_mysql_client_plugin *plugin,
const char *option, const char *option, const void *value);
const void *value);
#endif #endif

View File

@ -35,6 +35,5 @@ mysql_client_find_plugin(struct st_mysql *mysql, const char *name, int type);
struct st_mysql_client_plugin * struct st_mysql_client_plugin *
mysql_client_register_plugin(struct st_mysql *mysql, mysql_client_register_plugin(struct st_mysql *mysql,
struct st_mysql_client_plugin *plugin); struct st_mysql_client_plugin *plugin);
int STDCALL mysql_plugin_options(struct st_mysql_client_plugin *plugin, int mysql_plugin_options(struct st_mysql_client_plugin *plugin,
const char *option, const char *option, const void *value);
const void *value);

View File

@ -1,4 +1,4 @@
# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@ -134,6 +134,12 @@ CACHE INTERNAL "Functions exported by client API"
) )
IF(WIN32)
ADD_SUBDIRECTORY(authentication_win)
SET(WITH_AUTHENTICATION_WIN 1)
ADD_DEFINITIONS(-DAUTHENTICATION_WIN)
ENDIF(WIN32)
SET(CLIENT_SOURCES SET(CLIENT_SOURCES
get_password.c get_password.c
libmysql.c libmysql.c
@ -151,6 +157,10 @@ ADD_DEPENDENCIES(clientlib GenError)
SET(LIBS clientlib dbug strings vio mysys ${ZLIB_LIBRARY} ${SSL_LIBRARIES} ${LIBDL}) SET(LIBS clientlib dbug strings vio mysys ${ZLIB_LIBRARY} ${SSL_LIBRARIES} ${LIBDL})
IF(WITH_AUTHENTICATION_WIN)
LIST(APPEND LIBS auth_win_client)
ENDIF(WITH_AUTHENTICATION_WIN)
# Merge several convenience libraries into one big mysqlclient # Merge several convenience libraries into one big mysqlclient
# and link them together into shared library. # and link them together into shared library.
MERGE_LIBRARIES(mysqlclient STATIC ${LIBS} COMPONENT Development) MERGE_LIBRARIES(mysqlclient STATIC ${LIBS} COMPONENT Development)

View File

@ -0,0 +1,33 @@
# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# Configuration for building Windows Authentication Plugin (client-side)
#
ADD_DEFINITIONS(-DSECURITY_WIN32)
ADD_DEFINITIONS(-DDEBUG_ERRROR_LOG) # no error logging in production builds
ADD_DEFINITIONS(-DWINAUTH_USE_DBUG_LIB) # it is OK to use dbug library in statically
# linked plugin
SET(HEADERS common.h handshake.h)
SET(PLUGIN_SOURCES plugin_client.cc handshake_client.cc log_client.cc common.cc handshake.cc)
ADD_CONVENIENCE_LIBRARY(auth_win_client ${PLUGIN_SOURCES} ${HEADERS})
TARGET_LINK_LIBRARIES(auth_win_client Secur32)
# In IDE, group headers in a separate folder.
SOURCE_GROUP(Headers REGULAR_EXPRESSION ".*h$")

View File

@ -0,0 +1,492 @@
/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "common.h"
#include <sddl.h> // for ConvertSidToStringSid()
#include <secext.h> // for GetUserNameEx()
template <> void error_log_print<error_log_level::INFO>(const char *fmt, ...);
template <> void error_log_print<error_log_level::WARNING>(const char *fmt, ...);
template <> void error_log_print<error_log_level::ERROR>(const char *fmt, ...);
/** Connection class **************************************************/
/**
Create connection out of an active MYSQL_PLUGIN_VIO object.
@param[in] vio pointer to a @c MYSQL_PLUGIN_VIO object used for
connection - it can not be NULL
*/
Connection::Connection(MYSQL_PLUGIN_VIO *vio): m_vio(vio), m_error(0)
{
DBUG_ASSERT(vio);
}
/**
Write data to the connection.
@param[in] blob data to be written
@return 0 on success, VIO error code on failure.
@note In case of error, VIO error code is stored in the connection object
and can be obtained with @c error() method.
*/
int Connection::write(const Blob &blob)
{
m_error= m_vio->write_packet(m_vio, blob.ptr(), blob.len());
#ifndef DBUG_OFF
if (m_error)
DBUG_PRINT("error", ("vio write error %d", m_error));
#endif
return m_error;
}
/**
Read data from connection.
@return A Blob containing read packet or null Blob in case of error.
@note In case of error, VIO error code is stored in the connection object
and can be obtained with @c error() method.
*/
Blob Connection::read()
{
unsigned char *ptr;
int len= m_vio->read_packet(m_vio, &ptr);
if (len < 0)
{
m_error= true;
return Blob();
}
return Blob(ptr, len);
}
/** Sid class *****************************************************/
/**
Create Sid object corresponding to a given account name.
@param[in] account_name name of a Windows account
The account name can be in any form accepted by @c LookupAccountName()
function.
@note In case of errors created object is invalid and its @c is_valid()
method returns @c false.
*/
Sid::Sid(const wchar_t *account_name): m_data(NULL)
#ifndef DBUG_OFF
, m_as_string(NULL)
#endif
{
DWORD sid_size= 0, domain_size= 0;
bool success;
// Determine required buffer sizes
success= LookupAccountNameW(NULL, account_name, NULL, &sid_size,
NULL, &domain_size, &m_type);
if (!success && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
#ifndef DBUG_OFF
Error_message_buf error_buf;
DBUG_PRINT("error", ("Could not determine SID buffer size, "
"LookupAccountName() failed with error %X (%s)",
GetLastError(), get_last_error_message(error_buf)));
#endif
return;
}
// Query for SID (domain is ignored)
wchar_t *domain= new wchar_t[domain_size];
m_data= (TOKEN_USER*) new BYTE[sid_size + sizeof(TOKEN_USER)];
m_data->User.Sid= (BYTE*)m_data + sizeof(TOKEN_USER);
success= LookupAccountNameW(NULL, account_name,
m_data->User.Sid, &sid_size,
domain, &domain_size,
&m_type);
if (!success || !is_valid())
{
#ifndef DBUG_OFF
Error_message_buf error_buf;
DBUG_PRINT("error", ("Could not determine SID of '%S', "
"LookupAccountName() failed with error %X (%s)",
account_name, GetLastError(),
get_last_error_message(error_buf)));
#endif
goto fail;
}
goto end;
fail:
if (m_data)
delete [] m_data;
m_data= NULL;
end:
if (domain)
delete [] domain;
}
/**
Create Sid object corresponding to a given security token.
@param[in] token security token of a Windows account
@note In case of errors created object is invalid and its @c is_valid()
method returns @c false.
*/
Sid::Sid(HANDLE token): m_data(NULL)
#ifndef DBUG_OFF
, m_as_string(NULL)
#endif
{
DWORD req_size= 0;
bool success;
// Determine required buffer size
success= GetTokenInformation(token, TokenUser, NULL, 0, &req_size);
if (!success && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
#ifndef DBUG_OFF
Error_message_buf error_buf;
DBUG_PRINT("error", ("Could not determine SID buffer size, "
"GetTokenInformation() failed with error %X (%s)",
GetLastError(), get_last_error_message(error_buf)));
#endif
return;
}
m_data= (TOKEN_USER*) new BYTE[req_size];
success= GetTokenInformation(token, TokenUser, m_data, req_size, &req_size);
if (!success || !is_valid())
{
delete [] m_data;
m_data= NULL;
#ifndef DBUG_OFF
if (!success)
{
Error_message_buf error_buf;
DBUG_PRINT("error", ("Could not read SID from security token, "
"GetTokenInformation() failed with error %X (%s)",
GetLastError(), get_last_error_message(error_buf)));
}
#endif
}
}
Sid::~Sid()
{
if (m_data)
delete [] m_data;
#ifndef DBUG_OFF
if (m_as_string)
LocalFree(m_as_string);
#endif
}
/// Check if Sid object is valid.
bool Sid::is_valid(void) const
{
return m_data && m_data->User.Sid && IsValidSid(m_data->User.Sid);
}
#ifndef DBUG_OFF
/**
Produces string representation of the SID.
@return String representation of the SID or NULL in case of errors.
@note Memory allocated for the string is automatically freed in Sid's
destructor.
*/
const char* Sid::as_string()
{
if (!m_data)
return NULL;
if (!m_as_string)
{
bool success= ConvertSidToStringSid(m_data->User.Sid, &m_as_string);
if (!success)
{
#ifndef DBUG_OFF
Error_message_buf error_buf;
DBUG_PRINT("error", ("Could not get textual representation of a SID, "
"ConvertSidToStringSid() failed with error %X (%s)",
GetLastError(), get_last_error_message(error_buf)));
#endif
m_as_string= NULL;
return NULL;
}
}
return m_as_string;
}
#endif
bool Sid::operator ==(const Sid &other)
{
if (!is_valid() || !other.is_valid())
return false;
return EqualSid(m_data->User.Sid, other.m_data->User.Sid);
}
/** Generating User Principal Name *************************/
/**
Call Windows API functions to get UPN of the current user and store it
in internal buffer.
*/
UPN::UPN(): m_buf(NULL)
{
wchar_t buf1[MAX_SERVICE_NAME_LENGTH];
// First we try to use GetUserNameEx.
m_len= sizeof(buf1)/sizeof(wchar_t);
if (!GetUserNameExW(NameUserPrincipal, buf1, (PULONG)&m_len))
{
if (GetLastError())
{
#ifndef DBUG_OFF
Error_message_buf error_buf;
DBUG_PRINT("note", ("When determining UPN"
", GetUserNameEx() failed with error %X (%s)",
GetLastError(), get_last_error_message(error_buf)));
#endif
if (ERROR_MORE_DATA == GetLastError())
ERROR_LOG(INFO, ("Buffer overrun when determining UPN:"
" need %ul characters but have %ul",
m_len, sizeof(buf1)/sizeof(WCHAR)));
}
m_len= 0; // m_len == 0 indicates invalid UPN
return;
}
/*
UPN is stored in buf1 in wide-char format - convert it to utf8
for sending over network.
*/
m_buf= wchar_to_utf8(buf1, &m_len);
if(!m_buf)
ERROR_LOG(ERROR, ("Failed to convert UPN to utf8"));
// Note: possible error would be indicated by the fact that m_buf is NULL.
return;
}
UPN::~UPN()
{
if (m_buf)
free(m_buf);
}
/**
Convert a wide-char string to utf8 representation.
@param[in] string null-terminated wide-char string to be converted
@param[in,out] len length of the string to be converted or 0; on
return length (in bytes, excluding terminating
null character) of the converted string
If len is 0 then the length of the string will be computed by this function.
@return Pointer to a buffer containing utf8 representation or NULL in
case of error.
@note The returned buffer must be freed with @c free() call.
*/
char* wchar_to_utf8(const wchar_t *string, size_t *len)
{
char *buf= NULL;
size_t str_len= len && *len ? *len : wcslen(string);
/*
A conversion from utf8 to wchar_t will never take more than 3 bytes per
character, so a buffer of length 3 * str_len schould be sufficient.
We check that assumption with an assertion later.
*/
size_t buf_len= 3 * str_len;
buf= (char*)malloc(buf_len + 1);
if (!buf)
{
DBUG_PRINT("error",("Out of memory when converting string '%S' to utf8",
string));
return NULL;
}
int res= WideCharToMultiByte(CP_UTF8, // convert to UTF-8
0, // conversion flags
string, // input buffer
str_len, // its length
buf, buf_len, // output buffer and its size
NULL, NULL); // default character (not used)
if (res)
{
buf[res]= '\0';
if (len)
*len= res;
return buf;
}
// res is 0 which indicates error
#ifndef DBUG_OFF
Error_message_buf error_buf;
DBUG_PRINT("error", ("Could not convert string '%S' to utf8"
", WideCharToMultiByte() failed with error %X (%s)",
string, GetLastError(),
get_last_error_message(error_buf)));
#endif
// Let's check our assumption about sufficient buffer size
DBUG_ASSERT(ERROR_INSUFFICIENT_BUFFER != GetLastError());
return NULL;
}
/**
Convert an utf8 string to a wide-char string.
@param[in] string null-terminated utf8 string to be converted
@param[in,out] len length of the string to be converted or 0; on
return length (in chars) of the converted string
If len is 0 then the length of the string will be computed by this function.
@return Pointer to a buffer containing wide-char representation or NULL in
case of error.
@note The returned buffer must be freed with @c free() call.
*/
wchar_t* utf8_to_wchar(const char *string, size_t *len)
{
size_t buf_len;
/*
Note: length (in bytes) of an utf8 string is always bigger than the
number of characters in this string. Hence a buffer of size len will
be sufficient. We add 1 for the terminating null character.
*/
buf_len= len && *len ? *len : strlen(string);
wchar_t *buf= (wchar_t*)malloc((buf_len+1)*sizeof(wchar_t));
if (!buf)
{
DBUG_PRINT("error",("Out of memory when converting utf8 string '%s'"
" to wide-char representation", string));
return NULL;
}
size_t res;
res= MultiByteToWideChar(CP_UTF8, // convert from UTF-8
0, // conversion flags
string, // input buffer
buf_len, // its size
buf, buf_len); // output buffer and its size
if (res)
{
buf[res]= '\0';
if (len)
*len= res;
return buf;
}
// error in MultiByteToWideChar()
#ifndef DBUG_OFF
Error_message_buf error_buf;
DBUG_PRINT("error", ("Could not convert UPN from UTF-8"
", MultiByteToWideChar() failed with error %X (%s)",
GetLastError(), get_last_error_message(error_buf)));
#endif
// Let's check our assumption about sufficient buffer size
DBUG_ASSERT(ERROR_INSUFFICIENT_BUFFER != GetLastError());
return NULL;
}
/** Error handling ****************************************************/
/**
Returns error message corresponding to the last Windows error given
by GetLastError().
@note Error message is overwritten by next call to
@c get_last_error_message().
*/
const char* get_last_error_message(Error_message_buf buf)
{
int error= GetLastError();
buf[0]= '\0';
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)buf, sizeof(buf), NULL );
return buf;
}

View File

@ -0,0 +1,324 @@
/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifndef COMMON_H
#define COMMON_H
#include <my_global.h>
#include <windows.h>
#include <sspi.h> // for CtxtHandle
#include <mysql/plugin_auth.h> // for MYSQL_PLUGIN_VIO
/// Maximum length of the target service name.
#define MAX_SERVICE_NAME_LENGTH 1024
/** Debugging and error reporting infrastructure ***************************/
/*
Note: We use plugin local logging and error reporting mechanisms until
WL#2940 (plugin service: error reporting) is available.
*/
#undef INFO
#undef WARNING
#undef ERROR
struct error_log_level
{
typedef enum {INFO, WARNING, ERROR} type;
};
/*
If DEBUG_ERROR_LOG is defined then error logging happens only
in debug-copiled code. Otherwise ERROR_LOG() expands to
error_log_print() even in production code. Note that in client
plugin, error_log_print() will print nothing if opt_auth_win_clinet_log
is 0.
Note: Macro ERROR_LOG() can use printf-like format string like this:
ERROR_LOG(Level, ("format string", args));
The implementation should handle it correctly. Currently it is passed
to fprintf() (see error_log_vprint() function).
*/
extern "C" int opt_auth_win_client_log;
#if defined(DEBUG_ERROR_LOG) && defined(DBUG_OFF)
#define ERROR_LOG(Level, Msg) do {} while (0)
#else
#define ERROR_LOG(Level, Msg) error_log_print< error_log_level::Level > Msg
#endif
void error_log_vprint(error_log_level::type level,
const char *fmt, va_list args);
template <error_log_level::type Level>
void error_log_print(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
error_log_vprint(Level, fmt, args);
va_end(args);
}
typedef char Error_message_buf[1024];
const char* get_last_error_message(Error_message_buf);
/*
Internal implementation of debug message printing which does not use
dbug library. This is invoked via macro:
DBUG_PRINT_DO(Keyword, ("format string", args));
This is supposed to be used as an implementation of DBUG_PRINT() macro,
unless the dbug library implementation is used or debug messages are disabled.
*/
#ifndef DBUG_OFF
#define DBUG_PRINT_DO(Keyword, Msg) \
do { \
if (2 > opt_auth_win_client_log) break; \
fprintf(stderr, "winauth: %s: ", Keyword); \
debug_msg Msg; \
} while (0)
inline
void debug_msg(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
fputc('\n', stderr);
fflush(stderr);
va_end(args);
}
#else
#define DBUG_PRINT_DO(K, M) do {} while (0)
#endif
#ifndef WINAUTH_USE_DBUG_LIB
#undef DBUG_PRINT
#define DBUG_PRINT(Keyword, Msg) DBUG_PRINT_DO(Keyword, Msg)
/*
Redefine few more debug macros to make sure that no symbols from
dbug library are used.
*/
#undef DBUG_ENTER
#define DBUG_ENTER(X) do {} while (0)
#undef DBUG_RETURN
#define DBUG_RETURN(X) return (X)
#undef DBUG_ASSERT
#ifndef DBUG_OFF
#define DBUG_ASSERT(X) assert (X)
#else
#define DBUG_ASSERT(X) do {} while (0)
#endif
#undef DBUG_DUMP
#define DBUG_DUMP(A,B,C) do {} while (0)
#endif
/** Blob class *************************************************************/
typedef unsigned char byte;
/**
Class representing a region of memory (e.g., a string or binary buffer).
@note This class does not allocate memory. It merely describes a region
of memory which must be allocated externally (if it is dynamic memory).
*/
class Blob
{
byte *m_ptr; ///< Pointer to the first byte of the memory region.
size_t m_len; ///< Length of the memory region.
public:
Blob(): m_ptr(NULL), m_len(0)
{}
Blob(const byte *ptr, const size_t len)
: m_ptr(const_cast<byte*>(ptr)), m_len(len)
{}
Blob(const char *str): m_ptr((byte*)str)
{
m_len= strlen(str);
}
byte* ptr() const
{
return m_ptr;
}
size_t len() const
{
return m_len;
}
byte& operator[](unsigned pos) const
{
static byte out_of_range= 0; // alas, no exceptions...
return pos < len() ? m_ptr[pos] : out_of_range;
}
bool is_null() const
{
return m_ptr == NULL;
}
void trim(size_t l)
{
m_len= l;
}
};
/** Connection class *******************************************************/
/**
Convenience wrapper around MYSQL_PLUGIN_VIO object providing basic
read/write operations.
*/
class Connection
{
MYSQL_PLUGIN_VIO *m_vio; ///< Pointer to @c MYSQL_PLUGIN_VIO structure.
/**
If non-zero, indicates that connection is broken. If this has happened
because of failed operation, stores non-zero error code from that failure.
*/
int m_error;
public:
Connection(MYSQL_PLUGIN_VIO *vio);
int write(const Blob&);
Blob read();
int error() const
{
return m_error;
}
};
/** Sid class **************************************************************/
/**
Class for storing and manipulating Windows security identifiers (SIDs).
*/
class Sid
{
TOKEN_USER *m_data; ///< Pointer to structure holding identifier's data.
SID_NAME_USE m_type; ///< Type of identified entity.
public:
Sid(const wchar_t*);
Sid(HANDLE sec_token);
~Sid();
bool is_valid(void) const;
bool is_group(void) const
{
return m_type == SidTypeGroup
|| m_type == SidTypeWellKnownGroup
|| m_type == SidTypeAlias;
}
bool is_user(void) const
{
return m_type == SidTypeUser;
}
bool operator==(const Sid&);
operator PSID() const
{
return (PSID)m_data->User.Sid;
}
#ifndef DBUG_OFF
private:
char *m_as_string; ///< Cached string representation of the SID.
public:
const char* as_string();
#endif
};
/** UPN class **************************************************************/
/**
An object of this class obtains and stores User Principal Name of the
account under which current process is running.
*/
class UPN
{
char *m_buf; ///< Pointer to UPN in utf8 representation.
size_t m_len; ///< Length of the name.
public:
UPN();
~UPN();
bool is_valid() const
{
return m_len > 0;
}
const Blob as_blob() const
{
return m_len ? Blob((byte*)m_buf, m_len) : Blob();
}
const char* as_string() const
{
return (const char*)m_buf;
}
};
char* wchar_to_utf8(const wchar_t*, size_t*);
wchar_t* utf8_to_wchar(const char*, size_t*);
#endif

View File

@ -0,0 +1,289 @@
/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "handshake.h"
/** Handshake class implementation **********************************/
/**
Create common part of handshake context.
@param[in] ssp name of the SSP (Security Service Provider) to
be used for authentication
@param[in] side is this handshake object used for server- or
client-side handshake
Prepare for handshake using the @c ssp security module. We use
"Negotiate" which picks best available module. Parameter @c side
tells if this is preparing for server or client side authentication
and is used to prepare appropriate credentials.
*/
Handshake::Handshake(const char *ssp, side_t side)
: m_atts(0L), m_error(0), m_complete(FALSE),
m_have_credentials(false), m_have_sec_context(false)
#ifndef DBUG_OFF
, m_ssp_info(NULL)
#endif
{
SECURITY_STATUS ret;
// Obtain credentials for the authentication handshake.
ret= AcquireCredentialsHandle(NULL, (SEC_CHAR*)ssp,
side == SERVER ? SECPKG_CRED_INBOUND : SECPKG_CRED_OUTBOUND,
NULL, NULL, NULL, NULL, &m_cred, &m_expire);
if (ret != SEC_E_OK)
{
DBUG_PRINT("error", ("AcqireCredentialsHandle() failed"
" with error %X", ret));
ERROR_LOG(ERROR, ("Could not obtain local credentials"
" required for authentication"));
m_error= ret;
}
m_have_credentials= true;
}
Handshake::~Handshake()
{
if (m_have_credentials)
FreeCredentialsHandle(&m_cred);
if (m_have_sec_context)
DeleteSecurityContext(&m_sctx);
m_output.free();
#ifndef DBUG_OFF
if (m_ssp_info)
FreeContextBuffer(m_ssp_info);
#endif
}
/**
Read and process data packets from the other end of a connection.
@param[IN] con a connection to read packets from
Packets are read and processed until authentication handshake is
complete. It is assumed that the peer will send at least one packet.
Packets are processed with @c process_data() method. If new data is
generated during packet processing, this data is sent to the peer and
another round of packet exchange starts.
@return 0 on success.
@note In case of error, appropriate error message is logged.
*/
int Handshake::packet_processing_loop()
{
m_round= 0;
do {
++m_round;
// Read packet send by the peer
DBUG_PRINT("info", ("Waiting for packet"));
Blob packet= read_packet();
if (error())
{
ERROR_LOG(ERROR, ("Error reading packet in round %d", m_round));
return 1;
}
DBUG_PRINT("info", ("Got packet of length %d", packet.len()));
/*
Process received data, possibly generating new data to be sent.
*/
Blob new_data= process_data(packet);
if (error())
{
ERROR_LOG(ERROR, ("Error processing packet in round %d", m_round));
return 1;
}
/*
If new data has been generated, send it to the peer. Otherwise
handshake must be completed.
*/
if (!new_data.is_null())
{
DBUG_PRINT("info", ("Round %d started", m_round));
DBUG_PRINT("info", ("Sending packet of length %d", new_data.len()));
int ret= write_packet(new_data);
if (ret)
{
ERROR_LOG(ERROR, ("Error writing packet in round %d", m_round));
return 1;
}
DBUG_PRINT("info", ("Data sent"));
}
else if (!is_complete())
{
ERROR_LOG(ERROR, ("No data to send in round %d"
" but handshake is not complete", m_round));
return 1;
}
/*
To protect against malicious clients, break handshake exchange if
too many rounds.
*/
if (m_round > MAX_HANDSHAKE_ROUNDS)
{
ERROR_LOG(ERROR, ("Authentication handshake could not be completed"
" after %d rounds", m_round));
return 1;
}
} while(!is_complete());
ERROR_LOG(INFO, ("Handshake completed after %d rounds", m_round));
return 0;
}
#ifndef DBUG_OFF
/**
Get name of the security package which was used in authentication.
This method should be called only after handshake was completed. It is
available only in debug builds.
@return Name of security package or NULL if it can not be obtained.
*/
const char* Handshake::ssp_name()
{
if (!m_ssp_info && m_complete)
{
SecPkgContext_PackageInfo pinfo;
int ret= QueryContextAttributes(&m_sctx, SECPKG_ATTR_PACKAGE_INFO, &pinfo);
if (SEC_E_OK == ret)
{
m_ssp_info= pinfo.PackageInfo;
}
else
DBUG_PRINT("error",
("Could not obtain SSP info from authentication context"
", QueryContextAttributes() failed with error %X", ret));
}
return m_ssp_info ? m_ssp_info->Name : NULL;
}
#endif
/**
Process result of @c {Initialize,Accept}SecurityContext() function.
@param[in] ret return code from @c {Initialize,Accept}SecurityContext()
function
This function analyses return value of Windows
@c {Initialize,Accept}SecurityContext() function. A call to
@c CompleteAuthToken() is done if requested. If authentication is complete,
this fact is marked in the internal state of the Handshake object.
If errors are detected the object is moved to error state.
@return True if error has been detected.
*/
bool Handshake::process_result(int ret)
{
/*
First check for errors and set the m_complete flag if the result
indicates that handshake is complete.
*/
switch (ret)
{
case SEC_E_OK:
case SEC_I_COMPLETE_NEEDED:
// Handshake completed
m_complete= true;
break;
case SEC_I_CONTINUE_NEEDED:
case SEC_I_COMPLETE_AND_CONTINUE:
break;
default:
m_error= ret;
return true;
}
m_have_sec_context= true;
/*
If the result indicates a need for this, complete the authentication
token.
*/
switch (ret)
{
case SEC_I_COMPLETE_NEEDED:
case SEC_I_COMPLETE_AND_CONTINUE:
ret= CompleteAuthToken(&m_sctx, &m_output);
if (ret != 0)
{
DBUG_PRINT("error", ("CompleteAuthToken() failed with error %X", ret));
m_error= ret;
return true;
}
default:
break;
}
return false;
}
/** Security_buffer class implementation **********************************/
Security_buffer::Security_buffer(const Blob &blob): m_allocated(false)
{
init(blob.ptr(), blob.len());
}
Security_buffer::Security_buffer(): m_allocated(true)
{
init(NULL, 0);
}
void Security_buffer::free(void)
{
if (!m_allocated)
return;
if (!ptr())
return;
FreeContextBuffer(ptr());
m_allocated= false;
}

View File

@ -0,0 +1,181 @@
/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifndef HANDSHAKE_H
#define HANDSHAKE_H
#include "common.h"
/**
Name of the SSP (Security Support Provider) to be used for authentication.
We use "Negotiate" which will find the most secure SSP which can be used
and redirect to that SSP.
*/
#define SSP_NAME "Negotiate"
/**
Maximal number of rounds in authentication handshake.
Server will interrupt authentication handshake with error if client's
identity can not be determined within this many rounds.
*/
#define MAX_HANDSHAKE_ROUNDS 50
/// Convenience wrapper around @c SecBufferDesc.
class Security_buffer: public SecBufferDesc
{
SecBuffer m_buf; ///< A @c SecBuffer instance.
void init(byte *ptr, size_t len)
{
ulVersion= 0;
cBuffers= 1;
pBuffers= &m_buf;
m_buf.BufferType= SECBUFFER_TOKEN;
m_buf.pvBuffer= ptr;
m_buf.cbBuffer= len;
}
/// If @c false, no deallocation will be done in the destructor.
bool m_allocated;
public:
Security_buffer(const Blob&);
Security_buffer();
~Security_buffer()
{
free();
}
byte* ptr() const
{
return (byte*)m_buf.pvBuffer;
}
size_t len() const
{
return m_buf.cbBuffer;
}
bool is_valid() const
{
return ptr() != NULL;
}
const Blob as_blob() const
{
return Blob(ptr(), len());
}
void free(void);
};
/// Common base for Handshake_{server,client}.
class Handshake
{
public:
typedef enum {CLIENT, SERVER} side_t;
Handshake(const char *ssp, side_t side);
virtual ~Handshake();
int Handshake::packet_processing_loop();
bool virtual is_complete() const
{
return m_complete;
}
int error() const
{
return m_error;
}
protected:
/// Security context object created during the handshake.
CtxtHandle m_sctx;
/// Credentials of the principal performing this handshake.
CredHandle m_cred;
/// Stores expiry date of the created security context.
TimeStamp m_expire;
/// Stores attributes of the created security context.
ULONG m_atts;
/**
Round of the handshake (starting from round 1). One round
consist of reading packet from the other side, processing it and
optionally sending a reply (see @c packet_processing_loop()).
*/
unsigned int m_round;
/// If non-zero, stores error code of the last failed operation.
int m_error;
/// @c true when handshake is complete.
bool m_complete;
/// @c true when the principal credentials has been determined.
bool m_have_credentials;
/// @c true when the security context has been created.
bool m_have_sec_context;
/// Buffer for data to be send to the other side.
Security_buffer m_output;
bool process_result(int);
/**
This method is used inside @c packet_processing_loop to process
data packets received from the other end.
@param[IN] data data to be processed
@return A blob with data to be sent to the other end or null blob if
no more data needs to be exchanged.
*/
virtual Blob process_data(const Blob &data) =0;
/// Read packet from the other end.
virtual Blob read_packet() =0;
/// Write packet to the other end.
virtual int write_packet(Blob &data) =0;
#ifndef DBUG_OFF
private:
SecPkgInfo *m_ssp_info;
public:
const char* ssp_name();
#endif
};
#endif

View File

@ -0,0 +1,378 @@
/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "handshake.h"
#include <mysql.h> // for MYSQL structure
/// Client-side context for authentication handshake
class Handshake_client: public Handshake
{
/**
Name of the server's service for which we authenticate.
The service name is sent by server in the initial packet. If no
service name is used, this member is @c NULL.
*/
SEC_WCHAR *m_service_name;
/// Buffer for storing service name obtained from server.
SEC_WCHAR m_service_name_buf[MAX_SERVICE_NAME_LENGTH];
Connection &m_con;
public:
Handshake_client(Connection &con, const char *target, size_t len);
~Handshake_client();
Blob first_packet();
Blob process_data(const Blob&);
Blob read_packet();
int write_packet(Blob &data);
};
/**
Create authentication handshake context for client.
@param con connection for communication with the peer
@param target name of the target service with which we will authenticate
(can be NULL if not used)
Some security packages (like Kerberos) require providing explicit name
of the service with which a client wants to authenticate. The server-side
authentication plugin sends this name in the greeting packet
(see @c win_auth_handshake_{server,client}() functions).
*/
Handshake_client::Handshake_client(Connection &con,
const char *target, size_t len)
: Handshake(SSP_NAME, CLIENT), m_service_name(NULL), m_con(con)
{
if (!target || 0 == len)
return;
// Convert received UPN to internal WCHAR representation.
m_service_name= utf8_to_wchar(target, &len);
if (m_service_name)
DBUG_PRINT("info", ("Using target service: %S\n", m_service_name));
else
{
/*
Note: we ignore errors here - m_target will be NULL, the target name
will not be used and system will fall-back to NTLM authentication. But
we leave trace in error log.
*/
ERROR_LOG(WARNING, ("Could not decode UPN sent by the server"
"; target service name will not be used"
" and Kerberos authentication will not work"));
}
}
Handshake_client::~Handshake_client()
{
if (m_service_name)
free(m_service_name);
}
Blob Handshake_client::read_packet()
{
/*
We do a fake read in the first round because first
packet from the server containing UPN must be read
before the handshake context is created and the packet
processing loop starts. We return an empty blob here
and process_data() function will ignore it.
*/
if (m_round == 1)
return Blob();
// Otherwise we read packet from the connection.
Blob packet= m_con.read();
m_error= m_con.error();
if (!m_error && packet.is_null())
m_error= true; // (no specific error code assigned)
if (m_error)
return Blob();
DBUG_PRINT("dump", ("Got the following bytes"));
DBUG_DUMP("dump", packet.ptr(), packet.len());
return packet;
}
int Handshake_client::write_packet(Blob &data)
{
/*
Length of the first data payload send by client authentication plugin is
limited to 255 bytes (because it is wrapped inside client authentication
packet and is length-encoded with 1 byte for the length).
If the data payload is longer than 254 bytes, then it is sent in two parts:
first part of length 255 will be embedded in the authentication packet,
second part will be sent in the following packet. Byte 255 of the first
part contains information about the total length of the payload. It is a
number of blocks of size 512 bytes which is sufficient to store the
combined packets.
Server's logic for reading first client's payload is as follows
(see Handshake_server::read_packet()):
1. Read data from the authentication packet, if it is shorter than 255 bytes
then that is all data sent by client.
2. If there is 255 bytes of data in the authentication packet, read another
packet and append it to the data, skipping byte 255 of the first packet
which can be used to allocate buffer of appropriate size.
*/
size_t len2= 0; // length of the second part of first data payload
byte saved_byte; // for saving byte 255 in which data length is stored
if (m_round == 1 && data.len() > 254)
{
len2= data.len() - 254;
DBUG_PRINT("info", ("Splitting first packet of length %lu"
", %lu bytes will be sent in a second part",
data.len(), len2));
/*
Store in byte 255 the number of 512b blocks that are needed to
keep all the data.
*/
unsigned block_count= data.len()/512 + ((data.len() % 512) ? 1 : 0);
DBUG_ASSERT(block_count < (unsigned)0x100);
saved_byte= data[254];
data[254] = block_count;
data.trim(255);
}
DBUG_PRINT("dump", ("Sending the following data"));
DBUG_DUMP("dump", data.ptr(), data.len());
int ret= m_con.write(data);
if (ret)
return ret;
// Write second part if it is present.
if (len2)
{
data[254]= saved_byte;
Blob data2(data.ptr() + 254, len2);
DBUG_PRINT("info", ("Sending second part of data"));
DBUG_DUMP("info", data2.ptr(), data2.len());
ret= m_con.write(data2);
}
return ret;
}
/**
Process data sent by server.
@param[in] data blob with data from server
This method analyses data sent by server during authentication handshake.
If client should continue packet exchange, this method returns data to
be sent to the server next. If no more data needs to be exchanged, an
empty blob is returned and @c is_complete() is @c true. In case of error
an empty blob is returned and @c error() gives non-zero error code.
When invoked for the first time (in the first round of the handshake)
there is no data from the server (data blob is null) and the intial
packet is generated without an input.
@return Data to be sent to the server next or null blob if no more data
needs to be exchanged or in case of error.
*/
Blob Handshake_client::process_data(const Blob &data)
{
#if !defined(DBUG_OFF) && defined(WINAUTH_USE_DBUG_LIB)
/*
Code for testing the logic for sending the first client payload.
A fake data of length given by environment variable TEST_PACKET_LENGTH
(or default 255 bytes) is sent to the server. First 2 bytes of the
payload contain its total length (LSB first). The length of test data
is limited to 2048 bytes.
Upon receiving test data, server will check that data is correct and
refuse connection. If server detects data errors it will crash on
assertion.
This code is executed if debug flag "winauth_first_packet_test" is
set, e.g. using client option:
--debug="d,winauth_first_packet_test"
The same debug flag must be enabled in the server, e.g. using
statement:
SET GLOBAL debug= '+d,winauth_first_packet_test';
*/
static byte test_buf[2048];
if (m_round == 1
&& DBUG_EVALUATE_IF("winauth_first_packet_test", true, false))
{
const char *env= getenv("TEST_PACKET_LENGTH");
size_t len= env ? atoi(env) : 0;
if (!len)
len= 255;
if (len > sizeof(test_buf))
len= sizeof(test_buf);
// Store data length in first 2 bytes.
byte *ptr= test_buf;
*ptr++= len & 0xFF;
*ptr++= len >> 8;
// Fill remaining bytes with known values.
for (byte b= 0; ptr < test_buf + len; ++ptr, ++b)
*ptr= b;
return Blob(test_buf, len);
};
#endif
Security_buffer input(data);
SECURITY_STATUS ret;
m_output.free();
ret= InitializeSecurityContextW(
&m_cred,
m_round == 1 ? NULL : &m_sctx, // partial context
m_service_name, // service name
ASC_REQ_ALLOCATE_MEMORY, // requested attributes
0, // reserved
SECURITY_NETWORK_DREP, // data representation
m_round == 1 ? NULL : &input, // input data
0, // reserved
&m_sctx, // context
&m_output, // output data
&m_atts, // attributes
&m_expire); // expire date
if (process_result(ret))
{
DBUG_PRINT("error",
("InitializeSecurityContext() failed with error %X", ret));
return Blob();
}
return m_output.as_blob();
}
/**********************************************************************/
/**
Perform authentication handshake from client side.
@param[in] vio pointer to @c MYSQL_PLUGIN_VIO instance to be used
for communication with the server
@param[in] mysql pointer to a MySQL connection for which we authenticate
After reading the initial packet from server, containing its UPN to be
used as service name, client starts packet exchange by sending the first
packet in this exchange. While handshake is not yet completed, client
reads packets sent by the server and process them, possibly generating new
data to be sent to the server.
This function reports errors.
@return 0 on success.
*/
int win_auth_handshake_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
{
DBUG_ENTER("win_auth_handshake_client");
/*
Check if we should enable logging.
*/
{
const char *opt= getenv("AUTHENTICATION_WIN_LOG");
int opt_val= opt ? atoi(opt) : 0;
if (opt && !opt_val)
{
if (!strncasecmp("on", opt, 2)) opt_val= 1;
if (!strncasecmp("yes", opt, 3)) opt_val= 1;
if (!strncasecmp("true", opt, 4)) opt_val= 1;
if (!strncasecmp("debug", opt, 5)) opt_val= 2;
if (!strncasecmp("dbug", opt, 4)) opt_val= 2;
}
opt_auth_win_client_log= opt_val;
}
ERROR_LOG(INFO, ("Authentication handshake for account %s", mysql->user));
// Create connection object.
Connection con(vio);
DBUG_ASSERT(!con.error());
// Read initial packet from server containing service name.
Blob service_name= con.read();
if (con.error() || service_name.is_null())
{
ERROR_LOG(ERROR, ("Error reading initial packet"));
DBUG_RETURN(CR_ERROR);
}
DBUG_PRINT("info", ("Got initial packet of length %d", service_name.len()));
// Create authentication handshake context using the given service name.
Handshake_client hndshk(con,
service_name[0] ? (char *)service_name.ptr() : NULL,
service_name.len());
if (hndshk.error())
{
ERROR_LOG(ERROR, ("Could not create authentication handshake context"));
DBUG_RETURN(CR_ERROR);
}
DBUG_ASSERT(!hndshk.error());
/*
Read and process packets from server until handshake is complete.
Note that the first read from server is dummy
(see Handshake_client::read_packet()) as we already have read the
first packet to establish service name.
*/
if (hndshk.packet_processing_loop())
DBUG_RETURN(CR_ERROR);
DBUG_ASSERT(!hndshk.error() && hndshk.is_complete());
DBUG_RETURN(CR_OK);
}

View File

@ -0,0 +1,55 @@
/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <my_global.h>
#include "common.h"
/**
This option is set in win_auth_handshake_client() function
in handshake_client.cc.
Values:
0 - no logging
1 - log error/warning/info messages
2 - also log debug messages
Note: No error or debug messages are logged in production code
(see logging macros in common.h).
*/
int opt_auth_win_client_log= 0;
// Client-side logging function
void error_log_vprint(error_log_level::type level,
const char *fmt, va_list args)
{
if (0 == opt_auth_win_client_log)
return;
const char *level_string= "";
switch (level)
{
case error_log_level::INFO: level_string= "Note"; break;
case error_log_level::WARNING: level_string= "Warning"; break;
case error_log_level::ERROR: level_string= "ERROR"; break;
}
fprintf(stderr, "Windows Authentication Plugin %s: ", level_string);
vfprintf(stderr, fmt, args);
fputc('\n', stderr);
fflush(stderr);
}

View File

@ -0,0 +1,58 @@
/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <my_global.h>
#include <mysql.h>
#include <mysql/plugin_auth.h>
#include <mysql/client_plugin.h>
#include "common.h"
static int win_auth_client_plugin_init(char*, size_t, int, va_list)
{
return 0;
}
static int win_auth_client_plugin_deinit()
{
return 0;
}
int win_auth_handshake_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql);
/*
Client plugin declaration. This is added to mysql_client_builtins[]
in sql-common/client.c
*/
extern "C"
st_mysql_client_plugin_AUTHENTICATION win_auth_client_plugin=
{
MYSQL_CLIENT_AUTHENTICATION_PLUGIN,
MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION,
"authentication_windows_client",
"Rafal Somla",
"Windows Authentication Plugin - client side",
{0,1,0},
"GPL",
NULL,
win_auth_client_plugin_init,
win_auth_client_plugin_deinit,
NULL, // option handling
win_auth_handshake_client
};

View File

@ -94,6 +94,11 @@ sig_handler my_pipe_sig_handler(int sig);
static my_bool mysql_client_init= 0; static my_bool mysql_client_init= 0;
static my_bool org_my_init_done= 0; static my_bool org_my_init_done= 0;
typedef struct st_mysql_stmt_extension
{
MEM_ROOT fields_mem_root;
} MYSQL_STMT_EXT;
/* /*
Initialize the MySQL client library Initialize the MySQL client library
@ -1480,11 +1485,16 @@ mysql_stmt_init(MYSQL *mysql)
MYSQL_STMT *stmt; MYSQL_STMT *stmt;
DBUG_ENTER("mysql_stmt_init"); DBUG_ENTER("mysql_stmt_init");
if (!(stmt= (MYSQL_STMT *) my_malloc(sizeof(MYSQL_STMT), if (!(stmt=
(MYSQL_STMT *) my_malloc(sizeof (MYSQL_STMT),
MYF(MY_WME | MY_ZEROFILL))) ||
!(stmt->extension=
(MYSQL_STMT_EXT *) my_malloc(sizeof (MYSQL_STMT_EXT),
MYF(MY_WME | MY_ZEROFILL)))) MYF(MY_WME | MY_ZEROFILL))))
{ {
set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate); set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
DBUG_RETURN(0); my_free(stmt);
DBUG_RETURN(NULL);
} }
init_alloc_root(&stmt->mem_root, 2048, 2048); init_alloc_root(&stmt->mem_root, 2048, 2048);
@ -1499,6 +1509,8 @@ mysql_stmt_init(MYSQL *mysql)
strmov(stmt->sqlstate, not_error_sqlstate); strmov(stmt->sqlstate, not_error_sqlstate);
/* The rest of statement members was bzeroed inside malloc */ /* The rest of statement members was bzeroed inside malloc */
init_alloc_root(&stmt->extension->fields_mem_root, 2048, 0);
DBUG_RETURN(stmt); DBUG_RETURN(stmt);
} }
@ -1571,6 +1583,7 @@ mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, ulong length)
stmt->bind_param_done= stmt->bind_result_done= FALSE; stmt->bind_param_done= stmt->bind_result_done= FALSE;
stmt->param_count= stmt->field_count= 0; stmt->param_count= stmt->field_count= 0;
free_root(&stmt->mem_root, MYF(MY_KEEP_PREALLOC)); free_root(&stmt->mem_root, MYF(MY_KEEP_PREALLOC));
free_root(&stmt->extension->fields_mem_root, MYF(0));
int4store(buff, stmt->stmt_id); int4store(buff, stmt->stmt_id);
@ -1631,21 +1644,21 @@ mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, ulong length)
static void alloc_stmt_fields(MYSQL_STMT *stmt) static void alloc_stmt_fields(MYSQL_STMT *stmt)
{ {
MYSQL_FIELD *fields, *field, *end; MYSQL_FIELD *fields, *field, *end;
MEM_ROOT *alloc= &stmt->mem_root; MEM_ROOT *fields_mem_root= &stmt->extension->fields_mem_root;
MYSQL *mysql= stmt->mysql; MYSQL *mysql= stmt->mysql;
DBUG_ASSERT(mysql->field_count); DBUG_ASSERT(stmt->field_count);
stmt->field_count= mysql->field_count; free_root(fields_mem_root, MYF(0));
/* /*
Get the field information for non-select statements Get the field information for non-select statements
like SHOW and DESCRIBE commands like SHOW and DESCRIBE commands
*/ */
if (!(stmt->fields= (MYSQL_FIELD *) alloc_root(alloc, if (!(stmt->fields= (MYSQL_FIELD *) alloc_root(fields_mem_root,
sizeof(MYSQL_FIELD) * sizeof(MYSQL_FIELD) *
stmt->field_count)) || stmt->field_count)) ||
!(stmt->bind= (MYSQL_BIND *) alloc_root(alloc, !(stmt->bind= (MYSQL_BIND *) alloc_root(fields_mem_root,
sizeof(MYSQL_BIND) * sizeof(MYSQL_BIND) *
stmt->field_count))) stmt->field_count)))
{ {
@ -1658,18 +1671,36 @@ static void alloc_stmt_fields(MYSQL_STMT *stmt)
field && fields < end; fields++, field++) field && fields < end; fields++, field++)
{ {
*field= *fields; /* To copy all numeric parts. */ *field= *fields; /* To copy all numeric parts. */
field->catalog= strmake_root(alloc, fields->catalog, field->catalog= strmake_root(fields_mem_root,
fields->catalog,
fields->catalog_length); fields->catalog_length);
field->db= strmake_root(alloc, fields->db, fields->db_length); field->db= strmake_root(fields_mem_root,
field->table= strmake_root(alloc, fields->table, fields->table_length); fields->db,
field->org_table= strmake_root(alloc, fields->org_table, fields->db_length);
field->table= strmake_root(fields_mem_root,
fields->table,
fields->table_length);
field->org_table= strmake_root(fields_mem_root,
fields->org_table,
fields->org_table_length); fields->org_table_length);
field->name= strmake_root(alloc, fields->name, fields->name_length); field->name= strmake_root(fields_mem_root,
field->org_name= strmake_root(alloc, fields->org_name, fields->name,
fields->name_length);
field->org_name= strmake_root(fields_mem_root,
fields->org_name,
fields->org_name_length); fields->org_name_length);
field->def= fields->def ? strmake_root(alloc, fields->def, if (fields->def)
fields->def_length) : 0; {
field->def_length= field->def ? fields->def_length : 0; field->def= strmake_root(fields_mem_root,
fields->def,
fields->def_length);
field->def_length= fields->def_length;
}
else
{
field->def= NULL;
field->def_length= 0;
}
field->extension= 0; /* Avoid dangling links. */ field->extension= 0; /* Avoid dangling links. */
field->max_length= 0; /* max_length is set in mysql_stmt_store_result() */ field->max_length= 0; /* max_length is set in mysql_stmt_store_result() */
} }
@ -2387,6 +2418,9 @@ static void reinit_result_set_metadata(MYSQL_STMT *stmt)
prepared statements can't send result set metadata for these queries prepared statements can't send result set metadata for these queries
on prepare stage. Read it now. on prepare stage. Read it now.
*/ */
stmt->field_count= stmt->mysql->field_count;
alloc_stmt_fields(stmt); alloc_stmt_fields(stmt);
} }
else else
@ -2404,7 +2438,7 @@ static void reinit_result_set_metadata(MYSQL_STMT *stmt)
previous branch always works. previous branch always works.
TODO: send metadata only when it's really necessary and add a warning TODO: send metadata only when it's really necessary and add a warning
'Metadata changed' when it's sent twice. 'Metadata changed' when it's sent twice.
*/ */
update_stmt_fields(stmt); update_stmt_fields(stmt);
} }
} }
@ -4605,6 +4639,7 @@ my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
free_root(&stmt->result.alloc, MYF(0)); free_root(&stmt->result.alloc, MYF(0));
free_root(&stmt->mem_root, MYF(0)); free_root(&stmt->mem_root, MYF(0));
free_root(&stmt->extension->fields_mem_root, MYF(0));
if (mysql) if (mysql)
{ {
@ -4639,6 +4674,7 @@ my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
} }
} }
my_free(stmt->extension);
my_free(stmt); my_free(stmt);
DBUG_RETURN(test(rc)); DBUG_RETURN(test(rc));
@ -4805,16 +4841,13 @@ int STDCALL mysql_stmt_next_result(MYSQL_STMT *stmt)
stmt->state= MYSQL_STMT_EXECUTE_DONE; stmt->state= MYSQL_STMT_EXECUTE_DONE;
stmt->bind_result_done= FALSE; stmt->bind_result_done= FALSE;
stmt->field_count= mysql->field_count;
if (mysql->field_count) if (mysql->field_count)
{ {
alloc_stmt_fields(stmt); alloc_stmt_fields(stmt);
prepare_to_fetch_result(stmt); prepare_to_fetch_result(stmt);
} }
else
{
stmt->field_count= mysql->field_count;
}
DBUG_RETURN(0); DBUG_RETURN(0);
} }

View File

@ -104,4 +104,3 @@ EXPORTS
mysql_server_end mysql_server_end
mysql_set_character_set mysql_set_character_set
mysql_get_character_set_info mysql_get_character_set_info
mysql_plugin_options

View File

@ -2,6 +2,7 @@
# in alphabetical order. This also helps with merge conflict resolution. # in alphabetical order. This also helps with merge conflict resolution.
binlog.binlog_multi_engine # joro : NDB tests marked as experimental as agreed with bochklin binlog.binlog_multi_engine # joro : NDB tests marked as experimental as agreed with bochklin
binlog.binlog_bug23533 # skozlov: BUG#12371924
funcs_1.charset_collation_1 # depends on compile-time decisions funcs_1.charset_collation_1 # depends on compile-time decisions
@ -14,19 +15,13 @@ main.sp @solaris # Bug#47791 2010-01-20 alik Several tes
main.type_float @freebsd # Bug#38965 2010-05-04 alik test cases gis-rtree, type_float, type_newdecimal fail in embedded server main.type_float @freebsd # Bug#38965 2010-05-04 alik test cases gis-rtree, type_float, type_newdecimal fail in embedded server
main.wait_timeout @solaris # Bug#51244 2010-04-26 alik wait_timeout fails on OpenSolaris main.wait_timeout @solaris # Bug#51244 2010-04-26 alik wait_timeout fails on OpenSolaris
rpl.rpl_heartbeat_basic # BUG#12403008 2011-04-27 sven fails sporadically
rpl.rpl_innodb_bug28430 # Bug#46029 rpl.rpl_innodb_bug28430 # Bug#46029
rpl.rpl_show_slave_hosts # BUG#12416700 2011-05-02 sven fails sporadically
sys_vars.max_sp_recursion_depth_func @solaris # Bug#47791 2010-01-20 alik Several test cases fail on Solaris with error Thread stack overrun sys_vars.max_sp_recursion_depth_func @solaris # Bug#47791 2010-01-20 alik Several test cases fail on Solaris with error Thread stack overrun
sys_vars.plugin_dir_basic # Bug#52223 2010-11-24 alik Test "plugin_dir_basic" does not support RPM build (test) directory structure sys_vars.plugin_dir_basic # Bug#52223 2010-11-24 alik Test "plugin_dir_basic" does not support RPM build (test) directory structure
sys_vars.slow_query_log_func @solaris # Bug#54819 2010-06-26 alik sys_vars.slow_query_log_func fails sporadically on Solaris 10
sys_vars.wait_timeout_func # Bug#41255 2010-04-26 alik wait_timeout_func fails sys_vars.wait_timeout_func # Bug#41255 2010-04-26 alik wait_timeout_func fails
sys_vars.sys_vars # Bug #59148 2011-01-10 joro 'INSTALL PLUGIN rpl_semi_sync_master' fails in release build with debug binaries
sys_vars.rpl_semi_sync_master_enabled_basic # Bug #59148 2011-01-10 joro 'INSTALL PLUGIN rpl_semi_sync_master' fails in release build with debug binaries
sys_vars.rpl_semi_sync_master_timeout_basic # Bug #59148 2011-01-10 joro 'INSTALL PLUGIN rpl_semi_sync_master' fails in release build with debug binaries
sys_vars.rpl_semi_sync_master_trace_level_basic # Bug #59148 2011-01-10 joro 'INSTALL PLUGIN rpl_semi_sync_master' fails in release build with debug binaries
sys_vars.rpl_semi_sync_master_wait_no_slave_basic # Bug #59148 2011-01-10 joro 'INSTALL PLUGIN rpl_semi_sync_master' fails in release build with debug binaries
rpl.rpl_semi_sync_event # Bug #59148 2011-02-02 svoj 'INSTALL PLUGIN rpl_semi_sync_master' fails in release build with debug binaries
rpl.rpl_semi_sync # Bug #59148 2011-02-02 svoj 'INSTALL PLUGIN rpl_semi_sync_master' fails in release build with debug binaries
# BUG #59055 : All ndb tests should be removed from the repository # BUG #59055 : All ndb tests should be removed from the repository
# Leaving the sys_vars tests for now. sys_vars.all_vars.test fails on removing ndb tests # Leaving the sys_vars tests for now. sys_vars.all_vars.test fails on removing ndb tests

View File

@ -396,7 +396,7 @@ sync_slave_with_master;
# Error reaction is up to sql_mode of the slave sql (bug#38173) # Error reaction is up to sql_mode of the slave sql (bug#38173)
#--echo *** Create t9 on slave *** #--echo *** Create t9 on slave ***
# Please, check BUG#47741 to see why you are not testing NDB. # Please, check BUG#47741 to see why you are not testing NDB.
if ($engine_type != NDB) if (`SELECT UPPER(LEFT($engine_type, 3)) != 'NDB'`)
{ {
STOP SLAVE; STOP SLAVE;
RESET SLAVE; RESET SLAVE;
@ -440,12 +440,13 @@ if ($engine_type != NDB)
#--let $slave_skip_counter= 2 #--let $slave_skip_counter= 2
#--let $show_slave_sql_error= 1 #--let $show_slave_sql_error= 1
#--source include/wait_for_slave_sql_error_and_skip.inc #--source include/wait_for_slave_sql_error_and_skip.inc
}
#--echo *** Drop t9 *** #--echo *** Drop t9 ***
connection master; connection master;
DROP TABLE t9; DROP TABLE t9;
sync_slave_with_master; sync_slave_with_master;
}
############################################ ############################################
# More columns in slave at middle of table # # More columns in slave at middle of table #

View File

@ -1,5 +1,5 @@
# -*- cperl -*- # -*- cperl -*-
# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public # modify it under the terms of the GNU Library General Public
@ -150,7 +150,11 @@ sub fix_tmpdir {
sub fix_log_error { sub fix_log_error {
my ($self, $config, $group_name, $group)= @_; my ($self, $config, $group_name, $group)= @_;
my $dir= $self->{ARGS}->{vardir}; my $dir= $self->{ARGS}->{vardir};
return "$dir/log/$group_name.err"; if ( $::opt_valgrind and $::opt_debug ) {
return "$dir/log/$group_name.trace";
} else {
return "$dir/log/$group_name.err";
}
} }
sub fix_log { sub fix_log {

View File

@ -1,5 +1,5 @@
# -*- cperl -*- # -*- cperl -*-
# Copyright (C) 2008 MySQL AB # Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@ -156,8 +156,7 @@ sub my_find_paths {
# User can select to look in a special build dir # User can select to look in a special build dir
# which is a subdirectory of any of the paths # which is a subdirectory of any of the paths
my @extra_dirs; my @extra_dirs;
my $build_dir= $::opt_config_dir || $ENV{MTR_VS_CONFIG} my $build_dir= $::opt_vs_config || $ENV{MTR_VS_CONFIG} || $ENV{MTR_BUILD_DIR};
|| $ENV{MTR_BUILD_DIR};
push(@extra_dirs, $build_dir) if defined $build_dir; push(@extra_dirs, $build_dir) if defined $build_dir;
if (defined $extension){ if (defined $extension){

View File

@ -94,7 +94,7 @@ eval {
local $SIG{INT}= \&handle_signal; local $SIG{INT}= \&handle_signal;
local $SIG{CHLD}= sub { local $SIG{CHLD}= sub {
message("Got signal @_"); message("Got signal @_");
kill(9, -$child_pid); kill('KILL', -$child_pid);
my $ret= waitpid($child_pid, 0); my $ret= waitpid($child_pid, 0);
if ($? & 127){ if ($? & 127){
exit(65); # Killed by signal exit(65); # Killed by signal
@ -134,7 +134,7 @@ if ( $@ ) {
# Use negative pid in order to kill the whole # Use negative pid in order to kill the whole
# process group # process group
# #
my $ret= kill(9, -$child_pid); my $ret= kill('KILL', -$child_pid);
message("Killed child: $child_pid, ret: $ret"); message("Killed child: $child_pid, ret: $ret");
if ($ret > 0) { if ($ret > 0) {
message("Killed child: $child_pid"); message("Killed child: $child_pid");

View File

@ -1,5 +1,5 @@
# -*- cperl -*- # -*- cperl -*-
# Copyright (C) 2004, 2006 MySQL AB, 2009 Sun Microsystems, Inc. # Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@ -31,7 +31,7 @@ sub gcov_prepare ($) {
# #
# Collect gcov statistics. # Collect gcov statistics.
# Arguments: # Arguments:
# $dir basedir, normally source directory # $dir basedir, normally build directory
# $gcov gcov utility program [path] name # $gcov gcov utility program [path] name
# $gcov_msg message file name # $gcov_msg message file name
# $gcov_err error file name # $gcov_err error file name
@ -43,29 +43,25 @@ sub gcov_collect ($$$) {
my $start_dir= cwd(); my $start_dir= cwd();
print "Collecting source coverage info using '$gcov'...\n"; print "Collecting source coverage info using '$gcov'...\n";
-f "$start_dir/$gcov_msg" and unlink("$start_dir/$gcov_msg"); -f "$dir/$gcov_msg" and unlink("$dir/$gcov_msg");
-f "$start_dir/$gcov_err" and unlink("$start_dir/$gcov_err"); -f "$dir/$gcov_err" and unlink("$dir/$gcov_err");
my @dirs= `find "$dir" -type d -print | sort`; my @dirs= `find "$dir" -type d -print | sort`;
#print "List of directories:\n@dirs\n"; #print "List of directories:\n@dirs\n";
foreach my $d ( @dirs ) { foreach my $d ( @dirs ) {
my $dir_reported= 0;
chomp($d); chomp($d);
chdir($d) or next; chdir($d) or next;
foreach my $f ( (glob("*.h"), glob("*.cc"), glob("*.c")) ) { my @flist= glob("*.*.gcno");
$f =~ /(.*)\.[ch]c?/; print ("Collecting in '$d'...\n") if @flist;
-f "$1.gcno" or next;
if (!$dir_reported) { foreach my $f (@flist) {
print "Collecting in '$d'...\n"; system("$gcov $f 2>>$dir/$gcov_err >>$dir/$gcov_msg");
$dir_reported= 1;
}
system("$gcov $f 2>>$start_dir/$gcov_err >>$start_dir/$gcov_msg");
} }
chdir($start_dir); chdir($start_dir);
} }
print "gcov info in $gcov_msg, errors in $gcov_err\n"; print "gcov info in $dir/$gcov_msg, errors in $dir/$gcov_err\n";
} }

View File

@ -210,8 +210,8 @@ our $opt_clean_vardir= $ENV{'MTR_CLEAN_VARDIR'};
our $opt_gcov; our $opt_gcov;
our $opt_gcov_exe= "gcov"; our $opt_gcov_exe= "gcov";
our $opt_gcov_err= "mysql-test-gcov.msg"; our $opt_gcov_err= "mysql-test-gcov.err";
our $opt_gcov_msg= "mysql-test-gcov.err"; our $opt_gcov_msg= "mysql-test-gcov.msg";
our $opt_gprof; our $opt_gprof;
our %gprof_dirs; our %gprof_dirs;
@ -274,12 +274,13 @@ my $opt_strace_client;
our $opt_user = "root"; our $opt_user = "root";
my $opt_valgrind= 0; our $opt_valgrind= 0;
my $opt_valgrind_mysqld= 0; my $opt_valgrind_mysqld= 0;
my $opt_valgrind_mysqltest= 0; my $opt_valgrind_mysqltest= 0;
my @default_valgrind_args= ("--show-reachable=yes"); my @default_valgrind_args= ("--show-reachable=yes");
my @valgrind_args; my @valgrind_args;
my $opt_valgrind_path; my $opt_valgrind_path;
my $valgrind_reports= 0;
my $opt_callgrind; my $opt_callgrind;
my %mysqld_logs; my %mysqld_logs;
my $opt_debug_sync_timeout= 300; # Default timeout for WAIT_FOR actions. my $opt_debug_sync_timeout= 300; # Default timeout for WAIT_FOR actions.
@ -504,10 +505,29 @@ sub main {
push @$completed, run_ctest() if $opt_ctest; push @$completed, run_ctest() if $opt_ctest;
if ($opt_valgrind) {
# Create minimalistic "test" for the reporting
my $tinfo = My::Test->new
(
name => 'valgrind_report',
);
# Set dummy worker id to align report with normal tests
$tinfo->{worker} = 0 if $opt_parallel > 1;
if ($valgrind_reports) {
$tinfo->{result}= 'MTR_RES_FAILED';
$tinfo->{comment}= "Valgrind reported failures at shutdown, see above";
$tinfo->{failures}= 1;
} else {
$tinfo->{result}= 'MTR_RES_PASSED';
}
mtr_report_test($tinfo);
push @$completed, $tinfo;
}
mtr_print_line(); mtr_print_line();
if ( $opt_gcov ) { if ( $opt_gcov ) {
gcov_collect($basedir, $opt_gcov_exe, gcov_collect($bindir, $opt_gcov_exe,
$opt_gcov_msg, $opt_gcov_err); $opt_gcov_msg, $opt_gcov_err);
} }
@ -704,6 +724,9 @@ sub run_test_server ($$$) {
elsif ($line =~ /^SPENT/) { elsif ($line =~ /^SPENT/) {
add_total_times($line); add_total_times($line);
} }
elsif ($line eq 'VALGREP' && $opt_valgrind) {
$valgrind_reports= 1;
}
else { else {
mtr_error("Unknown response: '$line' from client"); mtr_error("Unknown response: '$line' from client");
} }
@ -889,6 +912,7 @@ sub run_worker ($) {
my $valgrind_reports= 0; my $valgrind_reports= 0;
if ($opt_valgrind_mysqld) { if ($opt_valgrind_mysqld) {
$valgrind_reports= valgrind_exit_reports(); $valgrind_reports= valgrind_exit_reports();
print $server "VALGREP\n" if $valgrind_reports;
} }
if ( $opt_gprof ) { if ( $opt_gprof ) {
gprof_collect (find_mysqld($basedir), keys %gprof_dirs); gprof_collect (find_mysqld($basedir), keys %gprof_dirs);
@ -1198,7 +1222,7 @@ sub command_line_setup {
chomp; chomp;
# remove comments (# foo) at the beginning of the line, or after a # remove comments (# foo) at the beginning of the line, or after a
# blank at the end of the line # blank at the end of the line
s/( +|^)#.*$//; s/(\s+|^)#.*$//;
# If @ platform specifier given, use this entry only if it contains # If @ platform specifier given, use this entry only if it contains
# @<platform> or @!<xxx> where xxx != platform # @<platform> or @!<xxx> where xxx != platform
if (/\@.*/) if (/\@.*/)
@ -1209,8 +1233,8 @@ sub command_line_setup {
s/\@.*$//; s/\@.*$//;
} }
# remove whitespace # remove whitespace
s/^ +//; s/^\s+//;
s/ +$//; s/\s+$//;
# if nothing left, don't need to remember this line # if nothing left, don't need to remember this line
if ( $_ eq "" ) { if ( $_ eq "" ) {
next; next;
@ -2196,7 +2220,12 @@ sub environment_setup {
$ENV{'DEFAULT_MASTER_PORT'}= $mysqld_variables{'port'}; $ENV{'DEFAULT_MASTER_PORT'}= $mysqld_variables{'port'};
$ENV{'MYSQL_TMP_DIR'}= $opt_tmpdir; $ENV{'MYSQL_TMP_DIR'}= $opt_tmpdir;
$ENV{'MYSQLTEST_VARDIR'}= $opt_vardir; $ENV{'MYSQLTEST_VARDIR'}= $opt_vardir;
# Used for guessing default plugin dir, we can't really know for sure
$ENV{'MYSQL_LIBDIR'}= "$basedir/lib"; $ENV{'MYSQL_LIBDIR'}= "$basedir/lib";
# Override if this does not exist, but lib64 does (best effort)
if (! -d "$basedir/lib" && -d "$basedir/lib64") {
$ENV{'MYSQL_LIBDIR'}= "$basedir/lib64";
}
$ENV{'MYSQL_BINDIR'}= "$bindir"; $ENV{'MYSQL_BINDIR'}= "$bindir";
$ENV{'MYSQL_SHAREDIR'}= $path_language; $ENV{'MYSQL_SHAREDIR'}= $path_language;
$ENV{'MYSQL_CHARSETSDIR'}= $path_charsetsdir; $ENV{'MYSQL_CHARSETSDIR'}= $path_charsetsdir;
@ -4092,6 +4121,9 @@ sub extract_warning_lines ($$) {
); );
my $skip_valgrind= 0; my $skip_valgrind= 0;
my $last_pat= "";
my $num_rep= 0;
foreach my $line ( @lines ) foreach my $line ( @lines )
{ {
if ($opt_valgrind_mysqld) { if ($opt_valgrind_mysqld) {
@ -4106,11 +4138,29 @@ sub extract_warning_lines ($$) {
{ {
if ( $line =~ /$pat/ ) if ( $line =~ /$pat/ )
{ {
print $Fwarn $line; # Remove initial timestamp and look for consecutive identical lines
my $line_pat= $line;
$line_pat =~ s/^[0-9: ]*//;
if ($line_pat eq $last_pat) {
$num_rep++;
} else {
# Previous line had been repeated, report that first
if ($num_rep) {
print $Fwarn ".... repeated $num_rep times: $last_pat";
$num_rep= 0;
}
$last_pat= $line_pat;
print $Fwarn $line;
}
last; last;
} }
} }
} }
# Catch the case of last warning being repeated
if ($num_rep) {
print $Fwarn ".... repeated $num_rep times: $last_pat";
}
$Fwarn = undef; # Close file $Fwarn = undef; # Close file
} }
@ -4747,13 +4797,6 @@ sub mysqld_start ($$) {
unlink($mysqld->value('pid-file')); unlink($mysqld->value('pid-file'));
my $output= $mysqld->value('#log-error'); my $output= $mysqld->value('#log-error');
if ( $opt_valgrind and $opt_debug )
{
# When both --valgrind and --debug is selected, send
# all output to the trace file, making it possible to
# see the exact location where valgrind complains
$output= "$opt_vardir/log/".$mysqld->name().".trace";
}
# Remember this log file for valgrind error report search # Remember this log file for valgrind error report search
$mysqld_logs{$output}= 1 if $opt_valgrind; $mysqld_logs{$output}= 1 if $opt_valgrind;
# Remember data dir for gmon.out files if using gprof # Remember data dir for gmon.out files if using gprof
@ -5660,6 +5703,7 @@ sub valgrind_exit_reports() {
@culprits); @culprits);
mtr_print_line(); mtr_print_line();
print ("$valgrind_rep\n"); print ("$valgrind_rep\n");
$found_err= 1;
$err_in_report= 0; $err_in_report= 0;
} }
# Make ready to collect new report # Make ready to collect new report

View File

@ -1391,3 +1391,16 @@ CREATE DATABASE db1 CHARACTER SET utf8;
CREATE TABLE db1.t1 (bar TINYTEXT, KEY (bar(100))); CREATE TABLE db1.t1 (bar TINYTEXT, KEY (bar(100)));
ALTER TABLE db1.t1 ADD baz INT; ALTER TABLE db1.t1 ADD baz INT;
DROP DATABASE db1; DROP DATABASE db1;
#
# Bug#11938039 RE-EXECUTION OF FRM-ONLY ALTER TABLE WITH RENAME
# CLAUSE FAILS OR ABORTS SERVER.
#
drop table if exists t1;
create table t1 (a int);
prepare stmt1 from 'alter table t1 alter column a set default 1, rename to t2';
execute stmt1;
rename table t2 to t1;
# The below statement should succeed and not emit error or abort server.
execute stmt1;
deallocate prepare stmt1;
drop table t2;

View File

@ -1,3 +1,4 @@
call mtr.add_suppression("Column count of mysql.event is wrong. Expected .*, found .*\. The table is probably corrupted");
drop database if exists events_test; drop database if exists events_test;
drop database if exists db_x; drop database if exists db_x;
drop database if exists mysqltest_db2; drop database if exists mysqltest_db2;
@ -259,33 +260,36 @@ events_test intact_check root@localhost SYSTEM RECURRING NULL 10 # # NULL ENABLE
Try to alter mysql.event: the server should fail to load Try to alter mysql.event: the server should fail to load
event information after mysql.event was tampered with. event information after mysql.event was tampered with.
First, let's add a column to the end and make sure everything First, let's add a column to the end and check the error is emitted.
works as before
ALTER TABLE mysql.event ADD dummy INT; ALTER TABLE mysql.event ADD dummy INT;
SHOW EVENTS; SHOW EVENTS;
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation ERROR HY000: Failed to open mysql.event
events_test intact_check root@localhost SYSTEM RECURRING NULL 10 # # NULL ENABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci
SELECT event_name FROM INFORMATION_SCHEMA.events; SELECT event_name FROM INFORMATION_SCHEMA.events;
event_name ERROR HY000: Failed to open mysql.event
intact_check
SHOW CREATE EVENT intact_check; SHOW CREATE EVENT intact_check;
Event sql_mode time_zone Create Event character_set_client collation_connection Database Collation ERROR HY000: Failed to open mysql.event
intact_check SYSTEM CREATE DEFINER=`root`@`localhost` EVENT `intact_check` ON SCHEDULE EVERY 10 HOUR STARTS '#' ON COMPLETION NOT PRESERVE ENABLE DO SELECT "nothing" latin1 latin1_swedish_ci latin1_swedish_ci
DROP EVENT no_such_event; DROP EVENT no_such_event;
ERROR HY000: Unknown event 'no_such_event' ERROR HY000: Failed to open mysql.event
CREATE EVENT intact_check_1 ON SCHEDULE EVERY 5 HOUR DO SELECT 5; CREATE EVENT intact_check_1 ON SCHEDULE EVERY 5 HOUR DO SELECT 5;
ERROR HY000: Failed to open mysql.event
ALTER EVENT intact_check_1 ON SCHEDULE EVERY 8 HOUR DO SELECT 8; ALTER EVENT intact_check_1 ON SCHEDULE EVERY 8 HOUR DO SELECT 8;
ERROR HY000: Failed to open mysql.event
ALTER EVENT intact_check_1 RENAME TO intact_check_2; ALTER EVENT intact_check_1 RENAME TO intact_check_2;
ERROR HY000: Failed to open mysql.event
DROP EVENT intact_check_1; DROP EVENT intact_check_1;
ERROR HY000: Unknown event 'intact_check_1' ERROR HY000: Failed to open mysql.event
DROP EVENT intact_check_2; DROP EVENT intact_check_2;
ERROR HY000: Failed to open mysql.event
DROP EVENT intact_check; DROP EVENT intact_check;
ERROR HY000: Failed to open mysql.event
DROP DATABASE IF EXISTS mysqltest_no_such_database; DROP DATABASE IF EXISTS mysqltest_no_such_database;
Warnings: Warnings:
Note 1008 Can't drop database 'mysqltest_no_such_database'; database doesn't exist Note 1008 Can't drop database 'mysqltest_no_such_database'; database doesn't exist
CREATE DATABASE mysqltest_db2; CREATE DATABASE mysqltest_db2;
DROP DATABASE mysqltest_db2; DROP DATABASE mysqltest_db2;
Warnings:
Error 1545 Failed to open mysql.event
SELECT @@event_scheduler; SELECT @@event_scheduler;
@@event_scheduler @@event_scheduler
OFF OFF
@ -294,6 +298,7 @@ Variable_name Value
event_scheduler OFF event_scheduler OFF
SET GLOBAL event_scheduler=OFF; SET GLOBAL event_scheduler=OFF;
ALTER TABLE mysql.event DROP dummy; ALTER TABLE mysql.event DROP dummy;
DROP EVENT intact_check;
CREATE EVENT intact_check ON SCHEDULE EVERY 10 HOUR DO SELECT "nothing"; CREATE EVENT intact_check ON SCHEDULE EVERY 10 HOUR DO SELECT "nothing";
Now let's add a column to the first position: the server Now let's add a column to the first position: the server
@ -301,30 +306,32 @@ expects to see event schema name there
ALTER TABLE mysql.event ADD dummy INT FIRST; ALTER TABLE mysql.event ADD dummy INT FIRST;
SHOW EVENTS; SHOW EVENTS;
ERROR HY000: Cannot load from mysql.event. The table is probably corrupted ERROR HY000: Failed to open mysql.event
SELECT event_name FROM INFORMATION_SCHEMA.events; SELECT event_name FROM INFORMATION_SCHEMA.events;
ERROR HY000: Cannot load from mysql.event. The table is probably corrupted ERROR HY000: Failed to open mysql.event
SHOW CREATE EVENT intact_check; SHOW CREATE EVENT intact_check;
ERROR HY000: Unknown event 'intact_check' ERROR HY000: Failed to open mysql.event
DROP EVENT no_such_event; DROP EVENT no_such_event;
ERROR HY000: Unknown event 'no_such_event' ERROR HY000: Failed to open mysql.event
CREATE EVENT intact_check_1 ON SCHEDULE EVERY 5 HOUR DO SELECT 5; CREATE EVENT intact_check_1 ON SCHEDULE EVERY 5 HOUR DO SELECT 5;
ERROR HY000: Failed to store event name. Error code 2 from storage engine. ERROR HY000: Failed to open mysql.event
ALTER EVENT intact_check_1 ON SCHEDULE EVERY 8 HOUR DO SELECT 8; ALTER EVENT intact_check_1 ON SCHEDULE EVERY 8 HOUR DO SELECT 8;
ERROR HY000: Unknown event 'intact_check_1' ERROR HY000: Failed to open mysql.event
ALTER EVENT intact_check_1 RENAME TO intact_check_2; ALTER EVENT intact_check_1 RENAME TO intact_check_2;
ERROR HY000: Unknown event 'intact_check_1' ERROR HY000: Failed to open mysql.event
DROP EVENT intact_check_1; DROP EVENT intact_check_1;
ERROR HY000: Unknown event 'intact_check_1' ERROR HY000: Failed to open mysql.event
DROP EVENT intact_check_2; DROP EVENT intact_check_2;
ERROR HY000: Unknown event 'intact_check_2' ERROR HY000: Failed to open mysql.event
DROP EVENT intact_check; DROP EVENT intact_check;
ERROR HY000: Unknown event 'intact_check' ERROR HY000: Failed to open mysql.event
DROP DATABASE IF EXISTS mysqltest_no_such_database; DROP DATABASE IF EXISTS mysqltest_no_such_database;
Warnings: Warnings:
Note 1008 Can't drop database 'mysqltest_no_such_database'; database doesn't exist Note 1008 Can't drop database 'mysqltest_no_such_database'; database doesn't exist
CREATE DATABASE mysqltest_db2; CREATE DATABASE mysqltest_db2;
DROP DATABASE mysqltest_db2; DROP DATABASE mysqltest_db2;
Warnings:
Error 1545 Failed to open mysql.event
SELECT @@event_scheduler; SELECT @@event_scheduler;
@@event_scheduler @@event_scheduler
OFF OFF
@ -345,29 +352,32 @@ Drop some columns and try more checks.
ALTER TABLE mysql.event DROP comment, DROP starts; ALTER TABLE mysql.event DROP comment, DROP starts;
SHOW EVENTS; SHOW EVENTS;
ERROR HY000: Cannot load from mysql.event. The table is probably corrupted ERROR HY000: Failed to open mysql.event
SELECT event_name FROM INFORMATION_SCHEMA.EVENTS; SELECT event_name FROM INFORMATION_SCHEMA.EVENTS;
ERROR HY000: Cannot load from mysql.event. The table is probably corrupted ERROR HY000: Failed to open mysql.event
SHOW CREATE EVENT intact_check; SHOW CREATE EVENT intact_check;
ERROR HY000: Cannot load from mysql.event. The table is probably corrupted ERROR HY000: Failed to open mysql.event
DROP EVENT no_such_event; DROP EVENT no_such_event;
ERROR HY000: Unknown event 'no_such_event' ERROR HY000: Failed to open mysql.event
CREATE EVENT intact_check_1 ON SCHEDULE EVERY 5 HOUR DO SELECT 5; CREATE EVENT intact_check_1 ON SCHEDULE EVERY 5 HOUR DO SELECT 5;
ERROR HY000: Column count of mysql.event is wrong. Expected 22, found 20. The table is probably corrupted ERROR HY000: Failed to open mysql.event
ALTER EVENT intact_check_1 ON SCHEDULE EVERY 8 HOUR DO SELECT 8; ALTER EVENT intact_check_1 ON SCHEDULE EVERY 8 HOUR DO SELECT 8;
ERROR HY000: Unknown event 'intact_check_1' ERROR HY000: Failed to open mysql.event
ALTER EVENT intact_check_1 RENAME TO intact_check_2; ALTER EVENT intact_check_1 RENAME TO intact_check_2;
ERROR HY000: Unknown event 'intact_check_1' ERROR HY000: Failed to open mysql.event
DROP EVENT intact_check_1; DROP EVENT intact_check_1;
ERROR HY000: Unknown event 'intact_check_1' ERROR HY000: Failed to open mysql.event
DROP EVENT intact_check_2; DROP EVENT intact_check_2;
ERROR HY000: Unknown event 'intact_check_2' ERROR HY000: Failed to open mysql.event
DROP EVENT intact_check; DROP EVENT intact_check;
ERROR HY000: Failed to open mysql.event
DROP DATABASE IF EXISTS mysqltest_no_such_database; DROP DATABASE IF EXISTS mysqltest_no_such_database;
Warnings: Warnings:
Note 1008 Can't drop database 'mysqltest_no_such_database'; database doesn't exist Note 1008 Can't drop database 'mysqltest_no_such_database'; database doesn't exist
CREATE DATABASE mysqltest_db2; CREATE DATABASE mysqltest_db2;
DROP DATABASE mysqltest_db2; DROP DATABASE mysqltest_db2;
Warnings:
Error 1545 Failed to open mysql.event
SELECT @@event_scheduler; SELECT @@event_scheduler;
@@event_scheduler @@event_scheduler
OFF OFF
@ -425,4 +435,42 @@ CREATE TABLE mysql.event like event_like;
DROP TABLE event_like; DROP TABLE event_like;
SHOW EVENTS; SHOW EVENTS;
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation
#
# Bug#12394306: the sever may crash if mysql.event is corrupted
#
CREATE EVENT ev1 ON SCHEDULE EVERY 5 HOUR DO SELECT 5;
ALTER EVENT ev1 ON SCHEDULE EVERY 8 HOUR DO SELECT 8;
CREATE TABLE event_original LIKE mysql.event;
INSERT INTO event_original SELECT * FROM mysql.event;
ALTER TABLE mysql.event MODIFY modified CHAR(1);
Warnings:
Warning 1265 Data truncated for column 'modified' at row 1
SHOW EVENTS;
ERROR HY000: Failed to open mysql.event
SELECT event_name, created, last_altered FROM information_schema.events;
ERROR HY000: Failed to open mysql.event
CREATE EVENT ev2 ON SCHEDULE EVERY 5 HOUR DO SELECT 5;
ERROR HY000: Failed to open mysql.event
ALTER EVENT ev1 ON SCHEDULE EVERY 9 HOUR DO SELECT 9;
ERROR HY000: Failed to open mysql.event
DROP TABLE mysql.event;
RENAME TABLE event_original TO mysql.event;
DROP EVENT ev1;
SHOW EVENTS;
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation
#
# End of tests
#
drop database events_test; drop database events_test;

View File

@ -1,3 +1,4 @@
call mtr.add_suppression("Column count of mysql.event is wrong. Expected .*, found .*\. The table is probably corrupted");
set global event_scheduler=off; set global event_scheduler=off;
drop database if exists events_test; drop database if exists events_test;
create database events_test; create database events_test;
@ -52,6 +53,8 @@ Warnings:
Note 1008 Can't drop database 'mysqltest_database_not_exists'; database doesn't exist Note 1008 Can't drop database 'mysqltest_database_not_exists'; database doesn't exist
create database mysqltest_db1; create database mysqltest_db1;
drop database mysqltest_db1; drop database mysqltest_db1;
Warnings:
Error 1545 Failed to open mysql.event
Restore the original mysql.event table Restore the original mysql.event table
drop table mysql.event; drop table mysql.event;
rename table event_like to mysql.event; rename table event_like to mysql.event;

View File

@ -135,4 +135,17 @@ SELECT * FROM t1 PROCEDURE ANALYSE();
Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
test.t1.a e e- 1 2 0 0 1.3333 NULL ENUM('e','e-') NOT NULL test.t1.a e e- 1 2 0 0 1.3333 NULL ENUM('e','e-') NOT NULL
DROP TABLE t1; DROP TABLE t1;
#
# Bug#11756242 48137: PROCEDURE ANALYSE() LEAKS MEMORY WHEN RETURNING NULL
#
CREATE TABLE t1(f1 INT) ENGINE=MYISAM;
CREATE TABLE t2(f2 INT) ENGINE=INNODB;
INSERT INTO t2 VALUES (1);
SELECT DISTINCTROW f1 FROM t1 NATURAL RIGHT OUTER JOIN t2 PROCEDURE ANALYSE();
Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
test.t1.f1 NULL NULL 0 0 0 1 0.0 0.0 CHAR(0)
SELECT * FROM t2 LIMIT 1 PROCEDURE ANALYSE();
Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
test.t2.f2 1 1 1 1 0 0 1.0000 0.0000 ENUM('1') NOT NULL
DROP TABLE t1, t2;
End of 5.1 tests End of 5.1 tests

View File

@ -1746,6 +1746,17 @@ MAX(LENGTH(a)) LENGTH(MAX(a)) MIN(a) MAX(a) CONCAT(MIN(a)) CONCAT(MAX(a))
20 20 18446668621106209655 18446668621106209655 18446668621106209655 18446668621106209655 20 20 18446668621106209655 18446668621106209655 18446668621106209655 18446668621106209655
DROP TABLE t1; DROP TABLE t1;
# #
# Bug #11766270 59343: YEAR(4): INCORRECT RESULT AND VALGRIND WARNINGS WITH MIN/MAX, UNION
#
CREATE TABLE t1(f1 YEAR(4));
INSERT INTO t1 VALUES (0000),(2001);
(SELECT MAX(f1) FROM t1) UNION (SELECT MAX(f1) FROM t1);
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def MAX(f1) MAX(f1) 13 4 4 Y 32864 0 63
MAX(f1)
2001
DROP TABLE t1;
#
End of 5.1 tests End of 5.1 tests
# #
# Bug#52123 Assertion failed: aggregator == aggr->Aggrtype(), # Bug#52123 Assertion failed: aggregator == aggr->Aggrtype(),

View File

@ -770,4 +770,10 @@ CASE a WHEN a THEN a END
NULL NULL
DROP TABLE t1; DROP TABLE t1;
# #
# Bug #11766212 59270: NOT IN (YEAR( ... ), ... ) PRODUCES MANY VALGRIND WARNINGS
#
SELECT 1 IN (YEAR(FROM_UNIXTIME(NULL)) ,1);
1 IN (YEAR(FROM_UNIXTIME(NULL)) ,1)
1
#
End of 5.1 tests End of 5.1 tests

View File

@ -521,6 +521,28 @@ CREATE TABLE t1 SELECT CEIL(LINESTRINGFROMWKB(1) DIV NULL);
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1 SELECT FLOOR(LINESTRINGFROMWKB(1) DIV NULL); CREATE TABLE t1 SELECT FLOOR(LINESTRINGFROMWKB(1) DIV NULL);
DROP TABLE t1; DROP TABLE t1;
#
# Bug#11765923 58937: MANY VALGRIND ERRORS AFTER GROUPING BY RESULT OF DECIMAL COLUMN FUNCTION
#
CREATE TABLE t1(f1 DECIMAL(22,1));
INSERT INTO t1 VALUES (0),(1);
SELECT ROUND(f1, f1) FROM t1;
ROUND(f1, f1)
0.0
1.0
SELECT ROUND(f1, f1) FROM t1 GROUP BY 1;
ROUND(f1, f1)
0.0
1.0
DROP TABLE t1;
#
# Bug#11764671 57533: UNINITIALISED VALUES IN COPY_AND_CONVERT (SQL_STRING.CC) WITH CERTAIN CHA
#
SELECT ROUND(LEAST(15, -4939092, 0.2704), STDDEV('a'));
ROUND(LEAST(15, -4939092, 0.2704), STDDEV('a'))
-4939092.0000
Warnings:
Warning 1292 Truncated incorrect DOUBLE value: 'a'
End of 5.1 tests End of 5.1 tests
# #
# Bug #8433: Overflow must be an error # Bug #8433: Overflow must be an error

View File

@ -1377,6 +1377,18 @@ NULL
SELECT ADDDATE(MONTH(FROM_UNIXTIME(NULL)),INTERVAL 1 HOUR); SELECT ADDDATE(MONTH(FROM_UNIXTIME(NULL)),INTERVAL 1 HOUR);
ADDDATE(MONTH(FROM_UNIXTIME(NULL)),INTERVAL 1 HOUR) ADDDATE(MONTH(FROM_UNIXTIME(NULL)),INTERVAL 1 HOUR)
NULL NULL
#
# Bug#11889186 60503: CRASH IN MAKE_DATE_TIME WITH DATE_FORMAT / STR_TO_DATE COMBINATION
#
SELECT DATE_FORMAT('0000-00-11', '%W');
DATE_FORMAT('0000-00-11', '%W')
NULL
SELECT DATE_FORMAT('0000-00-11', '%a');
DATE_FORMAT('0000-00-11', '%a')
NULL
SELECT DATE_FORMAT('0000-00-11', '%w');
DATE_FORMAT('0000-00-11', '%w')
NULL
End of 5.1 tests End of 5.1 tests
# #
# Bug#57039: constant subtime expression returns incorrect result. # Bug#57039: constant subtime expression returns incorrect result.

View File

@ -547,4 +547,26 @@ FROM t1 JOIN t2 ON t2.f2 LIKE 'x'
HAVING field1 < 7; HAVING field1 < 7;
field1 field1
DROP TABLE t1,t2; DROP TABLE t1,t2;
#
# Bug#48916 Server incorrectly processing HAVING clauses with an ORDER BY clause
#
CREATE TABLE t1 (f1 INT, f2 INT);
INSERT INTO t1 VALUES (1, 0), (2, 1), (3, 2);
CREATE TABLE t2 (f1 INT, f2 INT);
SELECT t1.f1
FROM t1
HAVING (3, 2) IN (SELECT f1, f2 FROM t2) AND t1.f1 >= 0
ORDER BY t1.f1;
f1
SELECT t1.f1
FROM t1
HAVING (3, 2) IN (SELECT 4, 2) AND t1.f1 >= 0
ORDER BY t1.f1;
f1
SELECT t1.f1
FROM t1
HAVING 2 IN (SELECT f2 FROM t2) AND t1.f1 >= 0
ORDER BY t1.f1;
f1
DROP TABLE t1,t2;
End of 5.1 tests End of 5.1 tests

View File

@ -532,4 +532,20 @@ a
0 0
1 1
DROP TABLE t1; DROP TABLE t1;
#
# Bug#11765139 58069: LOAD DATA INFILE: VALGRIND REPORTS INVALID MEMORY READS AND WRITES WITH U
#
CREATE TABLE t1(f1 INT);
SELECT 0xE1BB30 INTO OUTFILE 't1.dat';
LOAD DATA INFILE 't1.dat' IGNORE INTO TABLE t1 CHARACTER SET utf8;
DROP TABLE t1;
#
# Bug#11765141 - 58072: LOAD DATA INFILE: LEAKS IO CACHE MEMORY
# WHEN ERROR OCCURS
#
SELECT '1\n' INTO DUMPFILE 'MYSQLTEST_VARDIR/tmp/bug11735141.txt';
create table t1(a point);
LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/bug11735141.txt' INTO TABLE t1;
ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
drop table t1;
End of 5.1 tests End of 5.1 tests

View File

@ -109,3 +109,13 @@ count(*)
35840 35840
drop table t1; drop table t1;
drop table t2; drop table t2;
RESET MASTER;
USE test;
SET @old_binlog_format= @@binlog_format;
SET SESSION binlog_format=ROW;
CREATE TABLE t1(c1 INT);
INSERT INTO t1 VALUES (1);
FLUSH LOGS;
DROP TABLE t1;
SET SESSION binlog_format= @old_binlog_format;
RESET MASTER;

View File

@ -239,3 +239,12 @@ a
DROP TABLE t1; DROP TABLE t1;
# Should not be any files left here # Should not be any files left here
# End of bug#30102 test. # End of bug#30102 test.
# Test of post-push fix for bug#11766249/59316
CREATE TABLE t1 (a INT, b VARCHAR(255), PRIMARY KEY (a))
ENGINE = MyISAM
PARTITION BY RANGE (a)
(PARTITION p0 VALUES LESS THAN (0) MAX_ROWS=100,
PARTITION p1 VALUES LESS THAN (100) MAX_ROWS=100,
PARTITION pMax VALUES LESS THAN MAXVALUE);
INSERT INTO t1 VALUES (1, "Partition p1, first row");
DROP TABLE t1;

View File

@ -5084,6 +5084,24 @@ i
DROP TABLE t1,t1s,t2s; DROP TABLE t1,t1s,t2s;
End of 5.1 tests End of 5.1 tests
# #
# Bug #11765713 58705:
# OPTIMIZER LET ENGINE DEPEND ON UNINITIALIZED VALUES
# CREATED BY OPT_SUM_QUERY
#
CREATE TABLE t1(a INT NOT NULL, KEY (a));
INSERT INTO t1 VALUES (0), (1);
SELECT 1 as foo FROM t1 WHERE a < SOME
(SELECT a FROM t1 WHERE a <=>
(SELECT a FROM t1)
);
ERROR 21000: Subquery returns more than 1 row
SELECT 1 as foo FROM t1 WHERE a < SOME
(SELECT a FROM t1 WHERE a <=>
(SELECT a FROM t1 where a is null)
);
foo
DROP TABLE t1;
#
# Bug #57704: Cleanup code dies with void TABLE::set_keyread(bool): # Bug #57704: Cleanup code dies with void TABLE::set_keyread(bool):
# Assertion `file' failed. # Assertion `file' failed.
# #

View File

@ -2208,4 +2208,22 @@ trigger_name
# Clean-up. # Clean-up.
drop temporary table t1; drop temporary table t1;
drop table t1; drop table t1;
End of 6.0 tests.
#
# Bug #12362125: SP INOUT HANDLING IS BROKEN FOR TEXT TYPE.
#
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(c TEXT);
CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
BEGIN
DECLARE v TEXT;
SET v = 'aaa';
SET NEW.c = v;
END|
INSERT INTO t1 VALUES('qazwsxedc');
SELECT c FROM t1;
c
aaa
DROP TABLE t1;
End of 5.5 tests.

View File

@ -523,6 +523,69 @@ a
2000-01-01 00:00:01 2000-01-01 00:00:01
2000-01-01 00:00:01 2000-01-01 00:00:01
DROP TABLE t1; DROP TABLE t1;
#
# Bug#50774: failed to get the correct resultset when timestamp values
# are appended with .0
#
CREATE TABLE t1 ( a TIMESTAMP, KEY ( a ) );
INSERT INTO t1 VALUES( '2010-02-01 09:31:01' );
INSERT INTO t1 VALUES( '2010-02-01 09:31:02' );
INSERT INTO t1 VALUES( '2010-02-01 09:31:03' );
INSERT INTO t1 VALUES( '2010-02-01 09:31:04' );
SELECT * FROM t1 WHERE a >= '2010-02-01 09:31:02.0';
a
2010-02-01 09:31:02
2010-02-01 09:31:03
2010-02-01 09:31:04
SELECT * FROM t1 WHERE '2010-02-01 09:31:02.0' <= a;
a
2010-02-01 09:31:02
2010-02-01 09:31:03
2010-02-01 09:31:04
SELECT * FROM t1 WHERE a <= '2010-02-01 09:31:02.0';
a
2010-02-01 09:31:01
2010-02-01 09:31:02
SELECT * FROM t1 WHERE '2010-02-01 09:31:02.0' >= a;
a
2010-02-01 09:31:01
2010-02-01 09:31:02
EXPLAIN
SELECT * FROM t1 WHERE a >= '2010-02-01 09:31:02.0';
id select_type table type possible_keys key key_len ref rows Extra
x x x range x x x x x x
SELECT * FROM t1 WHERE a >= '2010-02-01 09:31:02.0';
a
2010-02-01 09:31:02
2010-02-01 09:31:03
2010-02-01 09:31:04
CREATE TABLE t2 ( a TIMESTAMP, KEY ( a DESC ) );
INSERT INTO t2 VALUES( '2010-02-01 09:31:01' );
INSERT INTO t2 VALUES( '2010-02-01 09:31:02' );
INSERT INTO t2 VALUES( '2010-02-01 09:31:03' );
INSERT INTO t2 VALUES( '2010-02-01 09:31:04' );
INSERT INTO t2 VALUES( '2010-02-01 09:31:05' );
INSERT INTO t2 VALUES( '2010-02-01 09:31:06' );
INSERT INTO t2 VALUES( '2010-02-01 09:31:07' );
INSERT INTO t2 VALUES( '2010-02-01 09:31:08' );
INSERT INTO t2 VALUES( '2010-02-01 09:31:09' );
INSERT INTO t2 VALUES( '2010-02-01 09:31:10' );
INSERT INTO t2 VALUES( '2010-02-01 09:31:11' );
# The bug would cause the range optimizer's comparison to use an open
# interval here. This reveals itself only in the number of reads
# performed.
FLUSH STATUS;
EXPLAIN
SELECT * FROM t2 WHERE a < '2010-02-01 09:31:02.0';
id select_type table type possible_keys key key_len ref rows Extra
x x x range x x x x x x
SELECT * FROM t2 WHERE a < '2010-02-01 09:31:02.0';
a
2010-02-01 09:31:01
SHOW STATUS LIKE 'Handler_read_next';
Variable_name Value
Handler_read_next 1
DROP TABLE t1, t2;
End of 5.1 tests End of 5.1 tests
Bug#50888 valgrind warnings in Field_timestamp::val_str Bug#50888 valgrind warnings in Field_timestamp::val_str

View File

@ -316,3 +316,25 @@ SHOW ERRORS;
Level Code Message Level Code Message
Error 1051 Unknown table 't1' Error 1051 Unknown table 't1'
End of 5.0 tests End of 5.0 tests
-- Bug#55847
DROP TABLE IF EXISTS t1;
DROP FUNCTION IF EXISTS f1;
CREATE TABLE t1(a INT UNIQUE);
CREATE FUNCTION f1(x INT) RETURNS INT
BEGIN
INSERT INTO t1 VALUES(x);
INSERT INTO t1 VALUES(x);
RETURN x;
END|
SHOW TABLES WHERE f1(11) = 11;
ERROR 23000: Duplicate entry '11' for key 'a'
SHOW WARNINGS;
Level Code Message
Error 1062 Duplicate entry '11' for key 'a'
DROP TABLE t1;
DROP FUNCTION f1;

View File

@ -166,3 +166,66 @@ ERROR XA102: XA_RBDEADLOCK: Transaction branch was rolled back: deadlock was det
XA END 'b'; XA END 'b';
XA ROLLBACK 'b'; XA ROLLBACK 'b';
DROP TABLE t1; DROP TABLE t1;
#
# Bug#11766752 59936: multiple xa assertions - transactional
# statement fuzzer
#
CREATE TABLE t1 (a INT) engine=InnoDB;
XA START 'a';
INSERT INTO t1 VALUES (1);
SAVEPOINT savep;
ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the ACTIVE state
XA END 'a';
SELECT * FROM t1;
ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the IDLE state
INSERT INTO t1 VALUES (2);
ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the IDLE state
SAVEPOINT savep;
ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the IDLE state
SET @a=(SELECT * FROM t1);
ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the IDLE state
XA PREPARE 'a';
SELECT * FROM t1;
ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the PREPARED state
INSERT INTO t1 VALUES (2);
ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the PREPARED state
SAVEPOINT savep;
ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the PREPARED state
SET @a=(SELECT * FROM t1);
ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the PREPARED state
UPDATE t1 SET a=1 WHERE a=2;
ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the PREPARED state
XA COMMIT 'a';
SELECT * FROM t1;
a
1
DROP TABLE t1;
#
# Bug#12352846 - TRANS_XA_START(THD*):
# ASSERTION THD->TRANSACTION.XID_STATE.XID.IS_NULL()
# FAILED
#
DROP TABLE IF EXISTS t1, t2;
CREATE TABLE t1 (a INT);
CREATE TABLE t2 (a INT);
START TRANSACTION;
INSERT INTO t1 VALUES (1);
# Connection con2
XA START 'xid1';
# Sending:
INSERT INTO t2 SELECT a FROM t1;
# Connection default
# Waiting until INSERT ... is blocked
DELETE FROM t1;
COMMIT;
# Connection con2
# Reaping: INSERT INTO t2 SELECT a FROM t1
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
XA COMMIT 'xid1';
ERROR XA102: XA_RBDEADLOCK: Transaction branch was rolled back: deadlock was detected
XA START 'xid1';
XA END 'xid1';
XA PREPARE 'xid1';
XA ROLLBACK 'xid1';
# Connection default
DROP TABLE t1, t2;

View File

@ -0,0 +1,15 @@
SET AUTOCOMMIT=0;
CREATE TABLE t1 (a INT NOT NULL AUTO_INCREMENT, b TEXT, PRIMARY KEY(a)) ENGINE=InnoDB;
SELECT COUNT(*) FROM t1;
COUNT(*)
1000
SET GLOBAL binlog_cache_size=4096;
SET GLOBAL max_binlog_cache_size=4096;
START TRANSACTION;
CREATE TABLE t2 SELECT * FROM t1;
ERROR HY000: Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mysqld variable and try again
COMMIT;
SHOW TABLES LIKE 't%';
Tables_in_test (t%)
t1
DROP TABLE t1;

View File

@ -0,0 +1,10 @@
CREATE TABLE t1(id INT);
SHOW TABLES;
Tables_in_test
t1
FLUSH LOGS;
DROP TABLE t1;
SHOW TABLES;
Tables_in_test
t1
DROP TABLE t1;

View File

@ -4,33 +4,47 @@
############################################################# #############################################################
--source include/have_innodb.inc --source include/have_innodb.inc
--source include/have_log_bin.inc
--source include/have_binlog_format_row.inc --source include/have_binlog_format_row.inc
--source include/master-slave.inc
SET AUTOCOMMIT=0; SET AUTOCOMMIT=0;
SET GLOBAL max_binlog_cache_size=4096;
SHOW VARIABLES LIKE 'max_binlog_cache_size';
# Create 1st table
CREATE TABLE t1 (a INT NOT NULL AUTO_INCREMENT, b TEXT, PRIMARY KEY(a)) ENGINE=InnoDB; CREATE TABLE t1 (a INT NOT NULL AUTO_INCREMENT, b TEXT, PRIMARY KEY(a)) ENGINE=InnoDB;
--disable_query_log --disable_query_log
let $i= 1000; let $i= 1000;
while ($i) while ($i)
{ {
BEGIN;
eval INSERT INTO t1 VALUES($i, REPEAT('x', 4096)); eval INSERT INTO t1 VALUES($i, REPEAT('x', 4096));
COMMIT;
dec $i; dec $i;
} }
--enable_query_log --enable_query_log
SELECT COUNT(*) FROM t1; SELECT COUNT(*) FROM t1;
# Set small value for max_binlog_cache_size
let $saved_binlog_cache_size= query_get_value(SELECT @@binlog_cache_size AS Value, Value, 1);
let $saved_max_binlog_cache_size= query_get_value(SELECT @@max_binlog_cache_size AS Value, Value, 1);
SET GLOBAL binlog_cache_size=4096;
SET GLOBAL max_binlog_cache_size=4096;
# New value of max_binlog_cache_size will apply to new session
disconnect default;
connect(default,localhost,root,,test);
# Copied data from t1 into t2 large than max_binlog_cache_size # Copied data from t1 into t2 large than max_binlog_cache_size
START TRANSACTION; START TRANSACTION;
--error 1534 --error ER_TRANS_CACHE_FULL
CREATE TABLE t2 SELECT * FROM t1; CREATE TABLE t2 SELECT * FROM t1;
COMMIT; COMMIT;
SHOW TABLES LIKE 't%'; SHOW TABLES LIKE 't%';
# 5.1 End of Test # 5.1 End of Test
--source include/rpl_end.inc --disable_query_log
eval SET GLOBAL max_binlog_cache_size=$saved_max_binlog_cache_size;
eval SET GLOBAL binlog_cache_size=$saved_binlog_cache_size;
--enable_query_log
DROP TABLE t1;
disconnect default;
connect(default,localhost,root,,test);

View File

@ -13,17 +13,18 @@
# #
# #
--source include/master-slave.inc --source include/have_log_bin.inc
--source include/have_binlog_format_mixed.inc
create table t1(id int); CREATE TABLE t1(id INT);
let $binlog= query_get_value(SHOW MASTER STATUS, File, 1);
let $binlog_path= `SELECT CONCAT(@@DATADIR, '$binlog')`;
SHOW TABLES;
FLUSH LOGS;
DROP TABLE t1;
show tables; --exec $MYSQL_BINLOG $binlog_path | $MYSQL test
SHOW TABLES;
--source include/show_master_status.inc # Clean up
DROP TABLE t1;
flush logs;
--exec $MYSQL_BINLOG $MYSQL_TEST_DIR/var/log/master-bin.000001 | $MYSQL test
drop table t1;
--source include/rpl_end.inc

View File

@ -1,8 +0,0 @@
[row]
binlog-format=row
[stmt]
binlog-format=statement
[mix]
binlog-format=mixed

View File

@ -1,3 +0,0 @@
a
b
c

View File

@ -1,5 +0,0 @@
INSTALL PLUGIN example SONAME 'ha_example.so';
SELECT @@global.connect_timeout AS connect_timeout, @@global.local_infile AS local_infile;
connect_timeout 4711
local_infile 1
UNINSTALL PLUGIN example;

View File

@ -1,33 +0,0 @@
stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
**** On Master ****
CREATE TABLE t1 (b CHAR(10));
**** On Slave ****
STOP SLAVE;
**** On Master ****
LOAD DATA INFILE FILENAME
SELECT COUNT(*) FROM t1;
COUNT(*)
3
show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (b CHAR(10))
master-bin.000001 # Begin_load_query # # ;file_id=#;block_len=#
master-bin.000001 # Execute_load_query # # use `test`; LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/rpl_bug12691.dat' INTO TABLE `t1` FIELDS TERMINATED BY '|' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (`b`) ;file_id=#
**** On Slave ****
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
START SLAVE;
SELECT COUNT(*) FROM t1;
COUNT(*)
0
**** On Master ****
DROP TABLE t1;

View File

@ -1,23 +0,0 @@
stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
DROP TABLE IF EXISTS t1,t2;
SET AUTOCOMMIT=0;
SET GLOBAL max_binlog_cache_size=4096;
SHOW VARIABLES LIKE 'max_binlog_cache_size';
Variable_name Value
max_binlog_cache_size 4096
CREATE TABLE t1 (a INT NOT NULL AUTO_INCREMENT, b TEXT, PRIMARY KEY(a)) ENGINE=InnoDB;
SELECT COUNT(*) FROM t1;
COUNT(*)
1000
START TRANSACTION;
CREATE TABLE t2 SELECT * FROM t1;
ERROR HY000: Writing one row to the row-based binary log failed
COMMIT;
SHOW TABLES LIKE 't%';
Tables_in_test (t%)
t1

View File

@ -1,16 +0,0 @@
stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
CREATE TABLE t1 (a VARCHAR(10) PRIMARY KEY) ENGINE=MyISAM;
INSERT INTO t1 VALUES ('a');
UPDATE t1 SET a = 'MyISAM';
SELECT * FROM t1 ORDER BY a;
a
MyISAM
SELECT * FROM t1 ORDER BY a;
a
MyISAM
DROP TABLE t1;

View File

@ -1,16 +0,0 @@
stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
CREATE TABLE t1 ( a INT, b INT DEFAULT -3 );
INSERT INTO t1 VALUES (1, DEFAULT);
UPDATE t1 SET a = 3;
SELECT * FROM t1 ORDER BY a;
a b
3 -3
SELECT * FROM t1 ORDER BY a;
a b
3 -3
DROP TABLE t1;

View File

@ -1,15 +0,0 @@
stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
create table `t1` (`id` int not null auto_increment primary key);
create trigger `trg` before insert on `t1` for each row begin end;
set @@global.debug="+d,simulate_bug33029";
stop slave;
start slave;
insert into `t1` values ();
select * from t1;
id
1

View File

@ -1,18 +0,0 @@
stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
drop table if exists t1;
Warnings:
Note 1051 Unknown table 't1'
create table t1(id int);
show tables;
Tables_in_test
t1
show master status;
File Position Binlog_Do_DB Binlog_Ignore_DB
master-bin.000001 # <Binlog_Do_DB> <Binlog_Ignore_DB>
flush logs;
drop table t1;

View File

@ -1,17 +0,0 @@
stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
CREATE TABLE char128_utf8 (
i1 INT NOT NULL,
c CHAR(128) CHARACTER SET utf8 NOT NULL,
i2 INT NOT NULL);
INSERT INTO char128_utf8 VALUES ( 1, "123", 1 );
SELECT * FROM char128_utf8;
i1 c i2
1 123 1
SELECT * FROM char128_utf8;
i1 c i2
1 123 1

View File

@ -1,56 +0,0 @@
stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
create table t1i(n int primary key) engine=innodb;
create table t2m(n int primary key) engine=myisam;
begin;
insert into t1i values (1);
insert into t1i values (2);
insert into t1i values (3);
commit;
begin;
insert into t1i values (5);
begin;
insert into t1i values (4);
insert into t2m values (1);
update t1i set n = 5 where n = 4;
commit;
zero
0
*** kill sql thread ***
rollback;
*** sql thread is *not* running: No ***
*** the prove: the killed slave has not finished the current transaction ***
three
3
one
1
zero
0
delete from t2m;
start slave sql_thread;
delete from t1i;
delete from t2m;
begin;
insert into t1i values (5);
begin;
insert into t1i values (4);
update t1i set n = 5 where n = 4;
commit;
zero
0
stop slave sql_thread;
rollback;
*** sql thread is *not* running: No ***
*** the prove: the stopped slave has rolled back the current transaction ***
zero
0
zero
0
one
1
start slave sql_thread;
drop table t1i, t2m;

View File

@ -1,2 +0,0 @@
--defaults-file=std_data/bug57108.cnf
$EXAMPLE_PLUGIN_OPT

View File

@ -1,12 +0,0 @@
--source include/not_windows_embedded.inc
--source include/have_example_plugin.inc
# Test that we can install a plugin despite the fact that we have
# switched directory after starting the server and am using a relative
# --defaults-file.
--replace_regex /\.dll/.so/
eval INSTALL PLUGIN example SONAME '$EXAMPLE_PLUGIN';
--query_vertical SELECT @@global.connect_timeout AS connect_timeout, @@global.local_infile AS local_infile
UNINSTALL PLUGIN example;

View File

@ -1,48 +0,0 @@
# Bug#12691: Exec_master_log_pos corrupted with SQL_SLAVE_SKIP_COUNTER
--source include/master-slave.inc
--source include/have_binlog_format_mixed_or_statement.inc
--echo
--echo **** On Master ****
CREATE TABLE t1 (b CHAR(10));
--echo
--echo **** On Slave ****
--sync_slave_with_master
STOP SLAVE;
--source include/wait_for_slave_to_stop.inc
--connection master
--echo
--echo **** On Master ****
--exec cp $MYSQL_TEST_DIR/suite/bugs/data/rpl_bug12691.dat $MYSQLTEST_VARDIR/tmp/
--echo LOAD DATA INFILE FILENAME
--disable_query_log
--eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/tmp/rpl_bug12691.dat' INTO TABLE t1 FIELDS TERMINATED BY '|'
--enable_query_log
--remove_file $MYSQLTEST_VARDIR/tmp/rpl_bug12691.dat
SELECT COUNT(*) FROM t1;
source include/show_binlog_events.inc;
--save_master_pos
--connection slave
--echo
--echo **** On Slave ****
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
START SLAVE;
--source include/wait_for_slave_to_start.inc
--sync_with_master
SELECT COUNT(*) FROM t1;
# Clean up
--connection master
--echo
--echo **** On Master ****
DROP TABLE t1;
--source include/rpl_end.inc

View File

@ -1,25 +0,0 @@
# BUG#31582: 5.1-telco-6.1 -> 5.1.22. Slave crashes when reading
# UPDATE for VARCHAR
# This is a problem for any update statement replicating from an old
# server to a new server. The bug consisted of a new slave trying to
# read two column bitmaps, but there is only one available in the old
# format.
# This test case should be executed replicating from an old server to
# a new server, so make sure you have one handy.
source include/master-slave.inc;
CREATE TABLE t1 (a VARCHAR(10) PRIMARY KEY) ENGINE=MyISAM;
INSERT INTO t1 VALUES ('a');
UPDATE t1 SET a = 'MyISAM';
SELECT * FROM t1 ORDER BY a;
sync_slave_with_master;
SELECT * FROM t1 ORDER BY a;
connection master;
DROP TABLE t1;
--source include/rpl_end.inc

View File

@ -1,25 +0,0 @@
#
# BUG#31583: 5.1-telco-6.1 -> 5.1.22. Slave returns Error in unknown event
# This is a problem for any update statement replicating from an old
# server to a new server. The bug consisted of a new slave trying to
# read two column bitmaps, but there is only one available in the old
# format.
# This test case should be executed replicating from an old server to
# a new server, so make sure you have one handy.
source include/master-slave.inc;
CREATE TABLE t1 ( a INT, b INT DEFAULT -3 );
INSERT INTO t1 VALUES (1, DEFAULT);
UPDATE t1 SET a = 3;
SELECT * FROM t1 ORDER BY a;
sync_slave_with_master;
SELECT * FROM t1 ORDER BY a;
connection master;
DROP TABLE t1;
--source include/rpl_end.inc

View File

@ -1,26 +0,0 @@
#
# Bug #36443 Server crashes when executing insert when insert trigger on table
#
# Emulating the former bug#33029 situation to see that there is no crash anymore.
#
source include/master-slave.inc;
create table `t1` (`id` int not null auto_increment primary key);
create trigger `trg` before insert on `t1` for each row begin end;
sync_slave_with_master;
set @@global.debug="+d,simulate_bug33029";
stop slave;
start slave;
connection master;
insert into `t1` values ();
sync_slave_with_master;
select * from t1;
--source include/rpl_end.inc

View File

@ -1,166 +0,0 @@
#
# Bug #38205 Row-based Replication (RBR) causes inconsistencies: HA_ERR_FOUND_DUPP_KEY
# Bug#319 if while a non-transactional slave is replicating a transaction possible problem
#
# Verifying the fact that STOP SLAVE in the middle of a group execution waits
# for the end of the group before the slave sql thread will stop.
# The patch refines STOP SLAVE to not interrupt a transaction or other type of
# the replication events group (the part I).
# Killing the sql thread continues to provide a "hard" stop (the part II).
#
# Non-deterministic tests
#
source include/master-slave.inc;
source include/have_innodb.inc;
#
# Part II, killed sql slave leaves instantly
#
# A. multi-statement transaction as the replication group
connection master;
create table t1i(n int primary key) engine=innodb;
create table t2m(n int primary key) engine=myisam;
sync_slave_with_master;
connection master;
begin;
insert into t1i values (1);
insert into t1i values (2);
insert into t1i values (3);
commit;
sync_slave_with_master;
#
# todo: first challenge is to find out the SQL thread id
# the following is not fully reliable
#
let $id=`SELECT id from information_schema.processlist where user like 'system user' and state like '%Has read all relay log%' or user like 'system user' and state like '%Reading event from the relay log%'`;
connection slave;
begin;
insert into t1i values (5);
connection master;
let $pos0_master= query_get_value(SHOW MASTER STATUS, Position, 1);
begin;
insert into t1i values (4);
insert into t2m values (1); # non-ta update
update t1i set n = 5 where n = 4; # to block at. can't be played with killed
commit;
let $pos1_master= query_get_value(SHOW MASTER STATUS, Position, 1);
connection slave;
# slave sql thread must be locked out by the conn `slave' explicit lock
let $pos0_slave= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1);
--disable_query_log
eval select $pos0_master - $pos0_slave as zero;
--enable_query_log
connection slave1;
let $count= 1;
let $table= t2m;
source include/wait_until_rows_count.inc;
#
# todo: may fail as said above
#
--echo *** kill sql thread ***
--disable_query_log
eval kill connection $id;
--enable_query_log
connection slave;
rollback; # release the sql thread
connection slave1;
source include/wait_for_slave_sql_to_stop.inc;
let $sql_status= query_get_value(SHOW SLAVE STATUS, Slave_SQL_Running, 1);
--echo *** sql thread is *not* running: $sql_status ***
let $pos1_slave= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1);
connection slave;
--echo *** the prove: the killed slave has not finished the current transaction ***
--disable_query_log
select count(*) as three from t1i;
eval select $pos1_master > $pos1_slave as one;
eval select $pos1_slave - $pos0_slave as zero;
--enable_query_log
delete from t2m; # remove the row to be able to replay
start slave sql_thread;
#
# Part I: B The homogenous transaction remains interuptable in between
#
connection master;
delete from t1i;
delete from t2m;
sync_slave_with_master;
begin;
insert into t1i values (5);
connection master;
let $pos0_master= query_get_value(SHOW MASTER STATUS, Position, 1);
begin;
insert into t1i values (4);
update t1i set n = 5 where n = 4; # to block at. not to be played
commit;
let $pos1_master= query_get_value(SHOW MASTER STATUS, Position, 1);
connection slave1;
# slave sql can't advance as must be locked by the conn `slave' trans
let $pos0_slave= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1);
--disable_query_log
eval select $pos0_master - $pos0_slave as zero;
--enable_query_log
#
# the replicated trans is blocked by the slave's local.
# However, it's not easy to catch the exact moment when it happens.
# The test issues sleep which makes the test either non-deterministic or
# wasting too much time.
#
--sleep 3
send stop slave sql_thread;
connection slave;
rollback; # release the sql thread
connection slave1;
reap;
source include/wait_for_slave_sql_to_stop.inc;
let $sql_status= query_get_value(SHOW SLAVE STATUS, Slave_SQL_Running, 1);
--echo *** sql thread is *not* running: $sql_status ***
let $pos1_slave= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1);
--echo *** the prove: the stopped slave has rolled back the current transaction ***
--disable_query_log
select count(*) as zero from t1i;
eval select $pos0_master - $pos0_slave as zero;
eval select $pos1_master > $pos0_slave as one;
--enable_query_log
start slave sql_thread;
# clean-up
connection master;
drop table t1i, t2m;
--source include/rpl_end.inc

View File

@ -0,0 +1,17 @@
create table `bug59410_1`(`a` int)engine=innodb;
insert into `bug59410_1` values (1),(2),(3);
select 1 from `bug59410_1` where `a` <> any (
select 1 from `bug59410_1` where `a` <> 1 for update)
for update;
1
1
1
drop table bug59410_1;
create table bug59410_2(`a` char(1),`b` int)engine=innodb;
insert into bug59410_2 values('0',0);
set transaction isolation level read uncommitted;
start transaction;
set @a=(select b from bug59410_2 where
(select 1 from bug59410_2 where a group by @a=b)
group by @a:=b);
drop table bug59410_2;

View File

@ -0,0 +1,57 @@
CREATE TABLE t(a INT PRIMARY KEY, b INT)ENGINE=InnoDB;
INSERT INTO t VALUES(2,2),(4,4),(8,8),(16,16),(32,32);
COMMIT;
XA START '123';
INSERT INTO t VALUES(1,1);
XA END '123';
XA PREPARE '123';
XA START '456';
INSERT INTO t VALUES(3,47),(5,67);
UPDATE t SET b=2*b WHERE a BETWEEN 5 AND 8;
XA END '456';
XA PREPARE '456';
XA START '789';
UPDATE t SET b=4*a WHERE a=32;
XA END '789';
XA PREPARE '789';
call mtr.add_suppression("Found 3 prepared XA transactions");
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT * FROM t;
a b
1 1
2 2
3 47
4 4
5 134
8 16
16 16
32 128
COMMIT;
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT * FROM t;
a b
1 1
2 2
3 47
4 4
5 134
8 16
16 16
32 128
COMMIT;
XA RECOVER;
formatID gtrid_length bqual_length data
1 3 0 789
1 3 0 456
1 3 0 123
XA ROLLBACK '123';
XA ROLLBACK '456';
XA COMMIT '789';
SELECT * FROM t;
a b
2 2
4 4
8 8
16 16
32 128
DROP TABLE t;

View File

@ -71,3 +71,47 @@ FK1_Key FK2_Key
DROP TABLE Bug_60196; DROP TABLE Bug_60196;
DROP TABLE Bug_60196_FK1; DROP TABLE Bug_60196_FK1;
DROP TABLE Bug_60196_FK2; DROP TABLE Bug_60196_FK2;
CREATE TABLE Bug_60309_FK (
ID INT PRIMARY KEY,
ID2 INT,
KEY K2(ID2)
) ENGINE=InnoDB;
CREATE TABLE Bug_60309 (
ID INT PRIMARY KEY,
FK_ID INT,
KEY (FK_ID),
CONSTRAINT FK FOREIGN KEY (FK_ID) REFERENCES Bug_60309_FK (ID)
) ENGINE=InnoDB;
INSERT INTO Bug_60309_FK (ID, ID2) VALUES (1, 1), (2, 2), (3, 3);
INSERT INTO Bug_60309 VALUES (1, 1);
INSERT INTO Bug_60309 VALUES (2, 99);
ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`bug_60309`, CONSTRAINT `FK` FOREIGN KEY (`FK_ID`) REFERENCES `Bug_60309_FK` (`ID`))
SELECT * FROM Bug_60309_FK;
ID ID2
1 1
2 2
3 3
SELECT * FROM Bug_60309;
ID FK_ID
1 1
# Stop server
# Restart server.
#
# Try to insert more to the example table with foreign keys.
# Bug60309 causes the foreign key file not to be found after
# the resstart above.
#
SELECT * FROM Bug_60309;
ID FK_ID
1 1
INSERT INTO Bug_60309 VALUES (2, 2);
INSERT INTO Bug_60309 VALUES (3, 3);
SELECT * FROM Bug_60309;
ID FK_ID
1 1
2 2
3 3
# Clean up.
DROP TABLE Bug_60309;
DROP TABLE Bug_60309_FK;

View File

@ -0,0 +1,24 @@
#
# Bug#59410 read uncommitted: unlock row could not find a 3 mode lock on the record
#
-- source include/have_innodb.inc
# only interested that the following do not produce something like
# InnoDB: Error: unlock row could not find a 2 mode lock on the record
# in the error log
create table `bug59410_1`(`a` int)engine=innodb;
insert into `bug59410_1` values (1),(2),(3);
select 1 from `bug59410_1` where `a` <> any (
select 1 from `bug59410_1` where `a` <> 1 for update)
for update;
drop table bug59410_1;
create table bug59410_2(`a` char(1),`b` int)engine=innodb;
insert into bug59410_2 values('0',0);
set transaction isolation level read uncommitted;
start transaction;
set @a=(select b from bug59410_2 where
(select 1 from bug59410_2 where a group by @a=b)
group by @a:=b);
drop table bug59410_2;

View File

@ -0,0 +1,68 @@
# Bug #59641 Prepared XA transaction causes shutdown hang after a crash
-- source include/not_embedded.inc
-- source include/have_innodb.inc
CREATE TABLE t(a INT PRIMARY KEY, b INT)ENGINE=InnoDB;
INSERT INTO t VALUES(2,2),(4,4),(8,8),(16,16),(32,32);
COMMIT;
XA START '123';
INSERT INTO t VALUES(1,1);
XA END '123';
XA PREPARE '123';
CONNECT (con1,localhost,root,,);
CONNECTION con1;
XA START '456';
INSERT INTO t VALUES(3,47),(5,67);
UPDATE t SET b=2*b WHERE a BETWEEN 5 AND 8;
XA END '456';
XA PREPARE '456';
CONNECT (con2,localhost,root,,);
CONNECTION con2;
XA START '789';
UPDATE t SET b=4*a WHERE a=32;
XA END '789';
XA PREPARE '789';
CONNECT (con3,localhost,root,,);
CONNECTION con3;
# The server would issue this warning on restart.
call mtr.add_suppression("Found 3 prepared XA transactions");
# Kill the server without sending a shutdown command
-- exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
-- shutdown_server 0
-- source include/wait_until_disconnected.inc
# Restart the server.
-- exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
-- enable_reconnect
-- source include/wait_until_connected_again.inc
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT * FROM t;
COMMIT;
# Shut down the server. This would hang because of the bug.
-- exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
-- shutdown_server
-- source include/wait_until_disconnected.inc
# Restart the server.
-- exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
-- enable_reconnect
-- source include/wait_until_connected_again.inc
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT * FROM t;
COMMIT;
XA RECOVER;
XA ROLLBACK '123';
XA ROLLBACK '456';
XA COMMIT '789';
SELECT * FROM t;
DROP TABLE t;

View File

@ -85,3 +85,73 @@ DROP TABLE Bug_60196;
DROP TABLE Bug_60196_FK1; DROP TABLE Bug_60196_FK1;
DROP TABLE Bug_60196_FK2; DROP TABLE Bug_60196_FK2;
# Bug#60309/12356829
# MYSQL 5.5.9 FOR MAC OSX HAS BUG WITH FOREIGN KEY CONSTRAINTS
# This testcase is different from that for Bug#60196 in that the
# referenced table contains a secondary key. When the engine is
# restarted, the referenced table is opened by the purge thread,
# which does not notice that lower_case_table_names == 2.
#
# Create test data.
#
CREATE TABLE Bug_60309_FK (
ID INT PRIMARY KEY,
ID2 INT,
KEY K2(ID2)
) ENGINE=InnoDB;
CREATE TABLE Bug_60309 (
ID INT PRIMARY KEY,
FK_ID INT,
KEY (FK_ID),
CONSTRAINT FK FOREIGN KEY (FK_ID) REFERENCES Bug_60309_FK (ID)
) ENGINE=InnoDB;
INSERT INTO Bug_60309_FK (ID, ID2) VALUES (1, 1), (2, 2), (3, 3);
INSERT INTO Bug_60309 VALUES (1, 1);
--error ER_NO_REFERENCED_ROW_2
INSERT INTO Bug_60309 VALUES (2, 99);
SELECT * FROM Bug_60309_FK;
SELECT * FROM Bug_60309;
--echo # Stop server
# Write file to make mysql-test-run.pl wait for the server to stop
-- exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
# Send a shutdown request to the server
-- shutdown_server 10
# Call script that will poll the server waiting for it to disapear
-- source include/wait_until_disconnected.inc
--echo # Restart server.
# Write file to make mysql-test-run.pl start up the server again
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
# Turn on reconnect
--enable_reconnect
# Call script that will poll the server waiting for it to be back online again
--source include/wait_until_connected_again.inc
# Turn off reconnect again
--disable_reconnect
--echo #
--echo # Try to insert more to the example table with foreign keys.
--echo # Bug60309 causes the foreign key file not to be found after
--echo # the resstart above.
--echo #
SELECT * FROM Bug_60309;
INSERT INTO Bug_60309 VALUES (2, 2);
INSERT INTO Bug_60309 VALUES (3, 3);
SELECT * FROM Bug_60309;
--echo
--echo # Clean up.
DROP TABLE Bug_60309;
DROP TABLE Bug_60309_FK;

View File

@ -37,7 +37,7 @@ if ($do_file_tests)
eval SET @aux = load_file('$ls_file'); eval SET @aux = load_file('$ls_file');
# clean up # clean up
remove_file $ls_file; --remove_file $ls_file
} }
if (!$do_file_tests) if (!$do_file_tests)
{ {

View File

@ -23,6 +23,7 @@ DROP TABLE t1;
--eval $create_statement --eval $create_statement
--eval $insert_statement --eval $insert_statement
--echo # State before failure --echo # State before failure
--replace_result #p# #P# #sp# #SP#
--list_files $DATADIR/test --list_files $DATADIR/test
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
--sorted_result --sorted_result
@ -32,6 +33,7 @@ LOCK TABLE t1 WRITE;
--eval $fail_statement --eval $fail_statement
--enable_abort_on_error --enable_abort_on_error
--echo # State after failure --echo # State after failure
--replace_result #p# #P# #sp# #SP#
--list_files $DATADIR/test --list_files $DATADIR/test
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
--sorted_result --sorted_result

View File

@ -45,6 +45,9 @@ if ($do_file_tests)
--list_files_append_file $ls_file $MYSQLTEST_VARDIR/mysql-test-idx-dir t1* --list_files_append_file $ls_file $MYSQLTEST_VARDIR/mysql-test-idx-dir t1*
} }
eval SET @aux = load_file('$ls_file'); eval SET @aux = load_file('$ls_file');
# clean up
--remove_file $ls_file
} }
if (!$do_file_tests) if (!$do_file_tests)
{ {

View File

@ -43,6 +43,9 @@ if ($do_file_tests)
--list_files_append_file $ls_file $MYSQLTEST_VARDIR/mysql-test-idx-dir t1* --list_files_append_file $ls_file $MYSQLTEST_VARDIR/mysql-test-idx-dir t1*
} }
eval SET @aux = load_file('$ls_file'); eval SET @aux = load_file('$ls_file');
# clean up
--remove_file $ls_file
} }
if (!$do_file_tests) if (!$do_file_tests)
{ {

View File

@ -0,0 +1,12 @@
include/master-slave.inc
[connection master]
CREATE TABLE char128_utf8 (i1 INT NOT NULL, c CHAR(128) CHARACTER SET utf8 NOT NULL, i2 INT NOT NULL);
INSERT INTO char128_utf8 VALUES ( 1, "123", 1 );
SELECT * FROM char128_utf8;
i1 c i2
1 123 1
SELECT * FROM char128_utf8;
i1 c i2
1 123 1
DROP TABLE char128_utf8;
include/rpl_end.inc

View File

@ -22,7 +22,7 @@ change master to master_port=MASTER_PORT;
start slave until master_log_file='master-bin.000001', master_log_pos=UNTIL_POS; start slave until master_log_file='master-bin.000001', master_log_pos=UNTIL_POS;
include/wait_for_slave_io_to_start.inc include/wait_for_slave_io_to_start.inc
include/wait_for_slave_sql_to_stop.inc include/wait_for_slave_sql_to_stop.inc
*** checking until postion execution: must be only t1 in the list *** *** checking until position execution: must be only t1 in the list ***
show tables; show tables;
Tables_in_test Tables_in_test
t1 t1

View File

@ -7,15 +7,16 @@ source include/master-slave.inc;
source include/have_binlog_format_row.inc; source include/have_binlog_format_row.inc;
connection master; connection master;
CREATE TABLE char128_utf8 ( CREATE TABLE char128_utf8 (i1 INT NOT NULL, c CHAR(128) CHARACTER SET utf8 NOT NULL, i2 INT NOT NULL);
i1 INT NOT NULL,
c CHAR(128) CHARACTER SET utf8 NOT NULL,
i2 INT NOT NULL);
INSERT INTO char128_utf8 VALUES ( 1, "123", 1 ); INSERT INTO char128_utf8 VALUES ( 1, "123", 1 );
SELECT * FROM char128_utf8; SELECT * FROM char128_utf8;
sync_slave_with_master; sync_slave_with_master;
SELECT * FROM char128_utf8; SELECT * FROM char128_utf8;
# Clean up
connection master;
DROP TABLE char128_utf8;
sync_slave_with_master;
--source include/rpl_end.inc --source include/rpl_end.inc

View File

@ -8,32 +8,32 @@
connection master; connection master;
CREATE TABLE t1(n INT NOT NULL AUTO_INCREMENT PRIMARY KEY); CREATE TABLE t1(n INT NOT NULL AUTO_INCREMENT PRIMARY KEY);
INSERT INTO t1 VALUES (1),(2),(3),(4); INSERT INTO t1 VALUES (1),(2),(3),(4);
# Save master log postion for query DROP TABLE t1 # Save master log position for query DROP TABLE t1
let $master_pos_drop_t1= query_get_value(SHOW MASTER STATUS, Position, 1); let $master_pos_drop_t1= query_get_value(SHOW MASTER STATUS, Position, 1);
DROP TABLE t1; DROP TABLE t1;
# Save master log postion for query DROP TABLE t1 # Save master log position for query DROP TABLE t1
save_master_pos; save_master_pos;
let $master_pos_drop_t1= query_get_value(SHOW BINLOG EVENTS, Pos, 7); let $master_pos_drop_t1= query_get_value(SHOW BINLOG EVENTS, Pos, 7);
let $master_log_file= query_get_value(SHOW BINLOG EVENTS, Log_name, 7); let $master_log_file= query_get_value(SHOW BINLOG EVENTS, Log_name, 7);
# Save master log postion for query CREATE TABLE t2 # Save master log position for query CREATE TABLE t2
let $master_pos_create_t2= query_get_value(SHOW MASTER STATUS, Position, 1); let $master_pos_create_t2= query_get_value(SHOW MASTER STATUS, Position, 1);
CREATE TABLE t2(n INT NOT NULL AUTO_INCREMENT PRIMARY KEY); CREATE TABLE t2(n INT NOT NULL AUTO_INCREMENT PRIMARY KEY);
#show binlog events; #show binlog events;
INSERT INTO t2 VALUES (1),(2); INSERT INTO t2 VALUES (1),(2);
# Save master log postion for query INSERT INTO t2 VALUES (1),(2); # Save master log position for query INSERT INTO t2 VALUES (1),(2);
let $master_pos_insert1_t2= query_get_value(SHOW MASTER STATUS, Position, 1); let $master_pos_insert1_t2= query_get_value(SHOW MASTER STATUS, Position, 1);
sync_slave_with_master; sync_slave_with_master;
#show binlog events; #show binlog events;
# Save relay log postion for query INSERT INTO t2 VALUES (1),(2); # Save relay log position for query INSERT INTO t2 VALUES (1),(2);
let $relay_pos_insert1_t2= query_get_value(SHOW SLAVE STATUS, Relay_Log_Pos, 1); let $relay_pos_insert1_t2= query_get_value(SHOW SLAVE STATUS, Relay_Log_Pos, 1);
connection master; connection master;
INSERT INTO t2 VALUES (3),(4); INSERT INTO t2 VALUES (3),(4);
DROP TABLE t2; DROP TABLE t2;
# Save master log postion for query DROP TABLE t2; # Save master log position for query DROP TABLE t2;
let $master_pos_drop_t2= query_get_value(SHOW MASTER STATUS, Position, 1); let $master_pos_drop_t2= query_get_value(SHOW MASTER STATUS, Position, 1);
sync_slave_with_master; sync_slave_with_master;
#show binlog events; #show binlog events;

View File

@ -50,7 +50,7 @@ eval start slave until master_log_file='master-bin.000001', master_log_pos=$unti
--source include/wait_for_slave_io_to_start.inc --source include/wait_for_slave_io_to_start.inc
--source include/wait_for_slave_sql_to_stop.inc --source include/wait_for_slave_sql_to_stop.inc
--echo *** checking until postion execution: must be only t1 in the list *** --echo *** checking until position execution: must be only t1 in the list ***
show tables; show tables;
# cleanup # cleanup

View File

@ -1159,3 +1159,20 @@ CREATE TABLE db1.t1 (bar TINYTEXT, KEY (bar(100)));
ALTER TABLE db1.t1 ADD baz INT; ALTER TABLE db1.t1 ADD baz INT;
DROP DATABASE db1; DROP DATABASE db1;
--echo #
--echo # Bug#11938039 RE-EXECUTION OF FRM-ONLY ALTER TABLE WITH RENAME
--echo # CLAUSE FAILS OR ABORTS SERVER.
--echo #
--disable_warnings
drop table if exists t1;
--enable_warnings
create table t1 (a int);
prepare stmt1 from 'alter table t1 alter column a set default 1, rename to t2';
execute stmt1;
rename table t2 to t1;
--echo # The below statement should succeed and not emit error or abort server.
execute stmt1;
deallocate prepare stmt1;
drop table t2;

View File

@ -4,6 +4,8 @@
# Can't test with embedded server that doesn't support grants # Can't test with embedded server that doesn't support grants
-- source include/not_embedded.inc -- source include/not_embedded.inc
call mtr.add_suppression("Column count of mysql.event is wrong. Expected .*, found .*\. The table is probably corrupted");
--disable_warnings --disable_warnings
drop database if exists events_test; drop database if exists events_test;
drop database if exists db_x; drop database if exists db_x;
@ -270,23 +272,28 @@ SHOW EVENTS;
--echo Try to alter mysql.event: the server should fail to load --echo Try to alter mysql.event: the server should fail to load
--echo event information after mysql.event was tampered with. --echo event information after mysql.event was tampered with.
--echo --echo
--echo First, let's add a column to the end and make sure everything --echo First, let's add a column to the end and check the error is emitted.
--echo works as before
--echo --echo
ALTER TABLE mysql.event ADD dummy INT; ALTER TABLE mysql.event ADD dummy INT;
--replace_column 8 # 9 # --error ER_EVENT_OPEN_TABLE_FAILED
SHOW EVENTS; SHOW EVENTS;
--error ER_EVENT_OPEN_TABLE_FAILED
SELECT event_name FROM INFORMATION_SCHEMA.events; SELECT event_name FROM INFORMATION_SCHEMA.events;
--replace_regex /STARTS '[^']+'/STARTS '#'/ --error ER_EVENT_OPEN_TABLE_FAILED
SHOW CREATE EVENT intact_check; SHOW CREATE EVENT intact_check;
--error ER_EVENT_DOES_NOT_EXIST --error ER_EVENT_OPEN_TABLE_FAILED
DROP EVENT no_such_event; DROP EVENT no_such_event;
--error ER_EVENT_OPEN_TABLE_FAILED
CREATE EVENT intact_check_1 ON SCHEDULE EVERY 5 HOUR DO SELECT 5; CREATE EVENT intact_check_1 ON SCHEDULE EVERY 5 HOUR DO SELECT 5;
--error ER_EVENT_OPEN_TABLE_FAILED
ALTER EVENT intact_check_1 ON SCHEDULE EVERY 8 HOUR DO SELECT 8; ALTER EVENT intact_check_1 ON SCHEDULE EVERY 8 HOUR DO SELECT 8;
--error ER_EVENT_OPEN_TABLE_FAILED
ALTER EVENT intact_check_1 RENAME TO intact_check_2; ALTER EVENT intact_check_1 RENAME TO intact_check_2;
--error ER_EVENT_DOES_NOT_EXIST --error ER_EVENT_OPEN_TABLE_FAILED
DROP EVENT intact_check_1; DROP EVENT intact_check_1;
--error ER_EVENT_OPEN_TABLE_FAILED
DROP EVENT intact_check_2; DROP EVENT intact_check_2;
--error ER_EVENT_OPEN_TABLE_FAILED
DROP EVENT intact_check; DROP EVENT intact_check;
DROP DATABASE IF EXISTS mysqltest_no_such_database; DROP DATABASE IF EXISTS mysqltest_no_such_database;
CREATE DATABASE mysqltest_db2; CREATE DATABASE mysqltest_db2;
@ -296,6 +303,7 @@ SHOW VARIABLES LIKE 'event_scheduler';
SET GLOBAL event_scheduler=OFF; SET GLOBAL event_scheduler=OFF;
# Clean up # Clean up
ALTER TABLE mysql.event DROP dummy; ALTER TABLE mysql.event DROP dummy;
DROP EVENT intact_check;
CREATE EVENT intact_check ON SCHEDULE EVERY 10 HOUR DO SELECT "nothing"; CREATE EVENT intact_check ON SCHEDULE EVERY 10 HOUR DO SELECT "nothing";
--echo --echo
--echo Now let's add a column to the first position: the server --echo Now let's add a column to the first position: the server
@ -303,24 +311,26 @@ CREATE EVENT intact_check ON SCHEDULE EVERY 10 HOUR DO SELECT "nothing";
--echo --echo
ALTER TABLE mysql.event ADD dummy INT FIRST; ALTER TABLE mysql.event ADD dummy INT FIRST;
--error ER_CANNOT_LOAD_FROM_TABLE --error ER_CANNOT_LOAD_FROM_TABLE
--error ER_EVENT_OPEN_TABLE_FAILED
SHOW EVENTS; SHOW EVENTS;
--error ER_CANNOT_LOAD_FROM_TABLE --error ER_CANNOT_LOAD_FROM_TABLE
--error ER_EVENT_OPEN_TABLE_FAILED
SELECT event_name FROM INFORMATION_SCHEMA.events; SELECT event_name FROM INFORMATION_SCHEMA.events;
--error ER_EVENT_DOES_NOT_EXIST --error ER_EVENT_OPEN_TABLE_FAILED
SHOW CREATE EVENT intact_check; SHOW CREATE EVENT intact_check;
--error ER_EVENT_DOES_NOT_EXIST --error ER_EVENT_OPEN_TABLE_FAILED
DROP EVENT no_such_event; DROP EVENT no_such_event;
--error ER_EVENT_STORE_FAILED --error ER_EVENT_OPEN_TABLE_FAILED
CREATE EVENT intact_check_1 ON SCHEDULE EVERY 5 HOUR DO SELECT 5; CREATE EVENT intact_check_1 ON SCHEDULE EVERY 5 HOUR DO SELECT 5;
--error ER_EVENT_DOES_NOT_EXIST --error ER_EVENT_OPEN_TABLE_FAILED
ALTER EVENT intact_check_1 ON SCHEDULE EVERY 8 HOUR DO SELECT 8; ALTER EVENT intact_check_1 ON SCHEDULE EVERY 8 HOUR DO SELECT 8;
--error ER_EVENT_DOES_NOT_EXIST --error ER_EVENT_OPEN_TABLE_FAILED
ALTER EVENT intact_check_1 RENAME TO intact_check_2; ALTER EVENT intact_check_1 RENAME TO intact_check_2;
--error ER_EVENT_DOES_NOT_EXIST --error ER_EVENT_OPEN_TABLE_FAILED
DROP EVENT intact_check_1; DROP EVENT intact_check_1;
--error ER_EVENT_DOES_NOT_EXIST --error ER_EVENT_OPEN_TABLE_FAILED
DROP EVENT intact_check_2; DROP EVENT intact_check_2;
--error ER_EVENT_DOES_NOT_EXIST --error ER_EVENT_OPEN_TABLE_FAILED
DROP EVENT intact_check; DROP EVENT intact_check;
# Should work OK # Should work OK
DROP DATABASE IF EXISTS mysqltest_no_such_database; DROP DATABASE IF EXISTS mysqltest_no_such_database;
@ -341,25 +351,25 @@ INSERT INTO event_like SELECT * FROM mysql.event;
--echo --echo
--echo --echo
ALTER TABLE mysql.event DROP comment, DROP starts; ALTER TABLE mysql.event DROP comment, DROP starts;
--error ER_CANNOT_LOAD_FROM_TABLE --error ER_EVENT_OPEN_TABLE_FAILED
SHOW EVENTS; SHOW EVENTS;
--error ER_CANNOT_LOAD_FROM_TABLE --error ER_EVENT_OPEN_TABLE_FAILED
SELECT event_name FROM INFORMATION_SCHEMA.EVENTS; SELECT event_name FROM INFORMATION_SCHEMA.EVENTS;
--error ER_CANNOT_LOAD_FROM_TABLE --error ER_EVENT_OPEN_TABLE_FAILED
SHOW CREATE EVENT intact_check; SHOW CREATE EVENT intact_check;
--error ER_EVENT_DOES_NOT_EXIST --error ER_EVENT_OPEN_TABLE_FAILED
DROP EVENT no_such_event; DROP EVENT no_such_event;
--error ER_COL_COUNT_DOESNT_MATCH_CORRUPTED --error ER_EVENT_OPEN_TABLE_FAILED
CREATE EVENT intact_check_1 ON SCHEDULE EVERY 5 HOUR DO SELECT 5; CREATE EVENT intact_check_1 ON SCHEDULE EVERY 5 HOUR DO SELECT 5;
--error ER_EVENT_DOES_NOT_EXIST --error ER_EVENT_OPEN_TABLE_FAILED
ALTER EVENT intact_check_1 ON SCHEDULE EVERY 8 HOUR DO SELECT 8; ALTER EVENT intact_check_1 ON SCHEDULE EVERY 8 HOUR DO SELECT 8;
--error ER_EVENT_DOES_NOT_EXIST --error ER_EVENT_OPEN_TABLE_FAILED
ALTER EVENT intact_check_1 RENAME TO intact_check_2; ALTER EVENT intact_check_1 RENAME TO intact_check_2;
--error ER_EVENT_DOES_NOT_EXIST --error ER_EVENT_OPEN_TABLE_FAILED
DROP EVENT intact_check_1; DROP EVENT intact_check_1;
--error ER_EVENT_DOES_NOT_EXIST --error ER_EVENT_OPEN_TABLE_FAILED
DROP EVENT intact_check_2; DROP EVENT intact_check_2;
# Should succeed --error ER_EVENT_OPEN_TABLE_FAILED
DROP EVENT intact_check; DROP EVENT intact_check;
DROP DATABASE IF EXISTS mysqltest_no_such_database; DROP DATABASE IF EXISTS mysqltest_no_such_database;
CREATE DATABASE mysqltest_db2; CREATE DATABASE mysqltest_db2;
@ -407,9 +417,54 @@ CREATE TABLE mysql.event like event_like;
DROP TABLE event_like; DROP TABLE event_like;
--replace_column 8 # 9 # --replace_column 8 # 9 #
SHOW EVENTS; SHOW EVENTS;
#
# End of tests --echo
# --echo #
--echo # Bug#12394306: the sever may crash if mysql.event is corrupted
--echo #
--echo
CREATE EVENT ev1 ON SCHEDULE EVERY 5 HOUR DO SELECT 5;
ALTER EVENT ev1 ON SCHEDULE EVERY 8 HOUR DO SELECT 8;
--echo
CREATE TABLE event_original LIKE mysql.event;
INSERT INTO event_original SELECT * FROM mysql.event;
--echo
ALTER TABLE mysql.event MODIFY modified CHAR(1);
--echo
--error ER_EVENT_OPEN_TABLE_FAILED
SHOW EVENTS;
--echo
--error ER_EVENT_OPEN_TABLE_FAILED
SELECT event_name, created, last_altered FROM information_schema.events;
--echo
--error ER_EVENT_OPEN_TABLE_FAILED
CREATE EVENT ev2 ON SCHEDULE EVERY 5 HOUR DO SELECT 5;
--echo
--error ER_EVENT_OPEN_TABLE_FAILED
ALTER EVENT ev1 ON SCHEDULE EVERY 9 HOUR DO SELECT 9;
--echo
DROP TABLE mysql.event;
RENAME TABLE event_original TO mysql.event;
--echo
DROP EVENT ev1;
--echo
SHOW EVENTS;
--echo
--echo #
--echo # End of tests
--echo #
let $wait_condition= let $wait_condition=
select count(*) = 0 from information_schema.processlist select count(*) = 0 from information_schema.processlist

View File

@ -1,6 +1,8 @@
# Can't test with embedded server that doesn't support grants # Can't test with embedded server that doesn't support grants
-- source include/not_embedded.inc -- source include/not_embedded.inc
call mtr.add_suppression("Column count of mysql.event is wrong. Expected .*, found .*\. The table is probably corrupted");
# #
# Test that when the server is restarted, it checks mysql.event table, # Test that when the server is restarted, it checks mysql.event table,
# and disables the scheduler if it's not up to date. # and disables the scheduler if it's not up to date.

View File

@ -1,6 +1,7 @@
# #
# Test of procedure analyse # Test of procedure analyse
# #
-- source include/have_innodb.inc
--disable_warnings --disable_warnings
drop table if exists t1,t2; drop table if exists t1,t2;
@ -144,4 +145,15 @@ INSERT INTO t1 VALUES ('e'),('e'),('e-');
SELECT * FROM t1 PROCEDURE ANALYSE(); SELECT * FROM t1 PROCEDURE ANALYSE();
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # Bug#11756242 48137: PROCEDURE ANALYSE() LEAKS MEMORY WHEN RETURNING NULL
--echo #
CREATE TABLE t1(f1 INT) ENGINE=MYISAM;
CREATE TABLE t2(f2 INT) ENGINE=INNODB;
INSERT INTO t2 VALUES (1);
SELECT DISTINCTROW f1 FROM t1 NATURAL RIGHT OUTER JOIN t2 PROCEDURE ANALYSE();
SELECT * FROM t2 LIMIT 1 PROCEDURE ANALYSE();
DROP TABLE t1, t2;
--echo End of 5.1 tests --echo End of 5.1 tests

View File

@ -1127,6 +1127,18 @@ INSERT INTO t1 VALUES (18446668621106209655);
SELECT MAX(LENGTH(a)), LENGTH(MAX(a)), MIN(a), MAX(a), CONCAT(MIN(a)), CONCAT(MAX(a)) FROM t1; SELECT MAX(LENGTH(a)), LENGTH(MAX(a)), MIN(a), MAX(a), CONCAT(MIN(a)), CONCAT(MAX(a)) FROM t1;
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # Bug #11766270 59343: YEAR(4): INCORRECT RESULT AND VALGRIND WARNINGS WITH MIN/MAX, UNION
--echo #
CREATE TABLE t1(f1 YEAR(4));
INSERT INTO t1 VALUES (0000),(2001);
--enable_metadata
(SELECT MAX(f1) FROM t1) UNION (SELECT MAX(f1) FROM t1);
--disable_metadata
DROP TABLE t1;
--echo # --echo #
--echo End of 5.1 tests --echo End of 5.1 tests

View File

@ -554,6 +554,12 @@ SELECT CASE a WHEN a THEN a END FROM t1 GROUP BY a WITH ROLLUP;
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # Bug #11766212 59270: NOT IN (YEAR( ... ), ... ) PRODUCES MANY VALGRIND WARNINGS
--echo #
SELECT 1 IN (YEAR(FROM_UNIXTIME(NULL)) ,1);
--echo # --echo #
--echo End of 5.1 tests --echo End of 5.1 tests

View File

@ -354,6 +354,22 @@ DROP TABLE t1;
CREATE TABLE t1 SELECT FLOOR(LINESTRINGFROMWKB(1) DIV NULL); CREATE TABLE t1 SELECT FLOOR(LINESTRINGFROMWKB(1) DIV NULL);
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # Bug#11765923 58937: MANY VALGRIND ERRORS AFTER GROUPING BY RESULT OF DECIMAL COLUMN FUNCTION
--echo #
CREATE TABLE t1(f1 DECIMAL(22,1));
INSERT INTO t1 VALUES (0),(1);
SELECT ROUND(f1, f1) FROM t1;
SELECT ROUND(f1, f1) FROM t1 GROUP BY 1;
DROP TABLE t1;
--echo #
--echo # Bug#11764671 57533: UNINITIALISED VALUES IN COPY_AND_CONVERT (SQL_STRING.CC) WITH CERTAIN CHA
--echo #
SELECT ROUND(LEAST(15, -4939092, 0.2704), STDDEV('a'));
--echo End of 5.1 tests --echo End of 5.1 tests
--echo # --echo #

View File

@ -894,6 +894,14 @@ SELECT CAST((MONTH(FROM_UNIXTIME(@@GLOBAL.SQL_MODE))) AS BINARY(1025));
SELECT ADDDATE(MONTH(FROM_UNIXTIME(NULL)),INTERVAL 1 HOUR); SELECT ADDDATE(MONTH(FROM_UNIXTIME(NULL)),INTERVAL 1 HOUR);
--echo #
--echo # Bug#11889186 60503: CRASH IN MAKE_DATE_TIME WITH DATE_FORMAT / STR_TO_DATE COMBINATION
--echo #
SELECT DATE_FORMAT('0000-00-11', '%W');
SELECT DATE_FORMAT('0000-00-11', '%a');
SELECT DATE_FORMAT('0000-00-11', '%w');
--echo End of 5.1 tests --echo End of 5.1 tests
--echo # --echo #

Some files were not shown because too many files have changed in this diff Show More