weave merge of mysql-5.5->mysql-5.5-security
This commit is contained in:
commit
712f2d3833
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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)
|
||||||
|
@ -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*/
|
||||||
|
@ -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})
|
||||||
|
@ -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()
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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 "")
|
||||||
|
@ -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
|
||||||
|
@ -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():
|
||||||
|
@ -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@"
|
||||||
|
@ -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
|
||||||
|
@ -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*/
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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);
|
|
||||||
|
@ -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)
|
||||||
|
33
libmysql/authentication_win/CMakeLists.txt
Normal file
33
libmysql/authentication_win/CMakeLists.txt
Normal 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$")
|
492
libmysql/authentication_win/common.cc
Normal file
492
libmysql/authentication_win/common.cc
Normal 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;
|
||||||
|
}
|
324
libmysql/authentication_win/common.h
Normal file
324
libmysql/authentication_win/common.h
Normal 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
|
289
libmysql/authentication_win/handshake.cc
Normal file
289
libmysql/authentication_win/handshake.cc
Normal 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;
|
||||||
|
}
|
181
libmysql/authentication_win/handshake.h
Normal file
181
libmysql/authentication_win/handshake.h
Normal 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
|
378
libmysql/authentication_win/handshake_client.cc
Normal file
378
libmysql/authentication_win/handshake_client.cc
Normal 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);
|
||||||
|
}
|
55
libmysql/authentication_win/log_client.cc
Normal file
55
libmysql/authentication_win/log_client.cc
Normal 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);
|
||||||
|
}
|
58
libmysql/authentication_win/plugin_client.cc
Normal file
58
libmysql/authentication_win/plugin_client.cc
Normal 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
|
||||||
|
};
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
||||||
|
@ -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 #
|
||||||
|
@ -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 {
|
||||||
|
@ -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){
|
||||||
|
@ -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");
|
||||||
|
@ -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";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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(),
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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.
|
||||||
#
|
#
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
15
mysql-test/suite/binlog/r/binlog_bug23533.result
Normal file
15
mysql-test/suite/binlog/r/binlog_bug23533.result
Normal 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;
|
10
mysql-test/suite/binlog/r/binlog_bug36391.result
Normal file
10
mysql-test/suite/binlog/r/binlog_bug36391.result
Normal 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;
|
@ -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);
|
@ -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
|
|
@ -1,8 +0,0 @@
|
|||||||
[row]
|
|
||||||
binlog-format=row
|
|
||||||
|
|
||||||
[stmt]
|
|
||||||
binlog-format=statement
|
|
||||||
|
|
||||||
[mix]
|
|
||||||
binlog-format=mixed
|
|
@ -1,3 +0,0 @@
|
|||||||
a
|
|
||||||
b
|
|
||||||
c
|
|
@ -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;
|
|
@ -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;
|
|
@ -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
|
|
@ -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;
|
|
@ -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;
|
|
@ -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
|
|
@ -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;
|
|
@ -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
|
|
@ -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;
|
|
@ -1,2 +0,0 @@
|
|||||||
--defaults-file=std_data/bug57108.cnf
|
|
||||||
$EXAMPLE_PLUGIN_OPT
|
|
@ -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;
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
17
mysql-test/suite/innodb/r/innodb_bug59410.result
Normal file
17
mysql-test/suite/innodb/r/innodb_bug59410.result
Normal 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;
|
57
mysql-test/suite/innodb/r/innodb_bug59641.result
Normal file
57
mysql-test/suite/innodb/r/innodb_bug59641.result
Normal 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;
|
@ -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;
|
||||||
|
24
mysql-test/suite/innodb/t/innodb_bug59410.test
Normal file
24
mysql-test/suite/innodb/t/innodb_bug59410.test
Normal 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;
|
68
mysql-test/suite/innodb/t/innodb_bug59641.test
Normal file
68
mysql-test/suite/innodb/t/innodb_bug59641.test
Normal 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;
|
@ -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;
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
12
mysql-test/suite/rpl/r/rpl_bug37426.result
Normal file
12
mysql-test/suite/rpl/r/rpl_bug37426.result
Normal 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
|
@ -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
|
||||||
|
@ -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
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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 #
|
||||||
|
@ -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
Loading…
x
Reference in New Issue
Block a user