mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
auto-merge
This commit is contained in:
18
.bzrignore
18
.bzrignore
@ -9,6 +9,7 @@
|
||||
*.core
|
||||
*.d
|
||||
*.da
|
||||
*.dir
|
||||
*.dll
|
||||
*.dylib
|
||||
*.exe
|
||||
@ -31,6 +32,7 @@
|
||||
*.pdb
|
||||
*.reject
|
||||
*.res
|
||||
*.rule
|
||||
*.sbr
|
||||
*.so
|
||||
*.so.*
|
||||
@ -38,7 +40,13 @@
|
||||
*.user
|
||||
*.vcproj
|
||||
*.vcproj.cmake
|
||||
*.vcxproj
|
||||
*.vcxproj.filters
|
||||
*/*.dir/*
|
||||
*.dir
|
||||
Debug
|
||||
MySql.sdf
|
||||
Win32
|
||||
*/*_pure_*warnings
|
||||
*/.deps
|
||||
*/.libs/*
|
||||
@ -46,7 +54,7 @@
|
||||
*/debug/*
|
||||
*/minsizerel/*
|
||||
*/release/*
|
||||
*/relwithdebinfo/*
|
||||
RelWithDebInfo
|
||||
*~
|
||||
.*.swp
|
||||
./CMakeCache.txt
|
||||
@ -611,6 +619,7 @@ include/mysql_h.ic
|
||||
include/mysql_version.h
|
||||
include/mysqld_ername.h
|
||||
include/mysqld_error.h
|
||||
include/mysqld_error.h.rule
|
||||
include/openssl
|
||||
include/probes_mysql_dtrace.h
|
||||
include/readline
|
||||
@ -1893,7 +1902,9 @@ scripts/mysql_find_rows
|
||||
scripts/mysql_fix_extensions
|
||||
scripts/mysql_fix_privilege_tables
|
||||
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.rule
|
||||
scripts/mysql_install_db
|
||||
scripts/mysql_secure_installation
|
||||
scripts/mysql_setpermission
|
||||
@ -2133,6 +2144,7 @@ sql/handlerton.cc
|
||||
sql/html
|
||||
sql/latex
|
||||
sql/lex_hash.h
|
||||
sql/lex_hash.h.rule
|
||||
sql/link_sources
|
||||
sql/max/*
|
||||
sql/message.h
|
||||
@ -2164,6 +2176,7 @@ sql/sql_builtin.cc
|
||||
sql/sql_select.cc.orig
|
||||
sql/sql_yacc.cc
|
||||
sql/sql_yacc.h
|
||||
sql/sql_yacc.h.rule
|
||||
sql/sql_yacc.output
|
||||
sql/sql_yacc.yy.orig
|
||||
sql/test_time
|
||||
@ -3116,3 +3129,6 @@ libmysqld/examples/mysql_embedded
|
||||
sql/.empty
|
||||
mysys/thr_lock
|
||||
VERSION.dep
|
||||
info_macros.cmake
|
||||
Docs/INFO_BIN
|
||||
Docs/INFO_SRC
|
||||
|
@ -31,6 +31,7 @@ Usage: $0 [-h|-n] [configure-options]
|
||||
-h, --help Show this help message.
|
||||
-n, --just-print Don't actually run any commands; just print them.
|
||||
-c, --just-configure Stop after running configure.
|
||||
--with-debug=full Build with full debug(no optimizations, keep call stack).
|
||||
--warning-mode=[old|pedantic|maintainer]
|
||||
Influences the debug flags. Old is default.
|
||||
--prefix=path Build with prefix 'path'.
|
||||
@ -46,6 +47,8 @@ parse_options()
|
||||
case "$1" in
|
||||
--prefix=*)
|
||||
prefix=`get_key_value "$1"`;;
|
||||
--with-debug=full)
|
||||
full_debug="=full";;
|
||||
--warning-mode=*)
|
||||
warning_mode=`get_key_value "$1"`;;
|
||||
-c | --just-configure)
|
||||
@ -76,6 +79,7 @@ just_print=
|
||||
just_configure=
|
||||
warning_mode=
|
||||
maintainer_mode=
|
||||
full_debug=
|
||||
|
||||
parse_options "$@"
|
||||
|
||||
@ -154,7 +158,11 @@ base_cxxflags="-felide-constructors -fno-exceptions -fno-rtti"
|
||||
fast_cflags="-O3 -fno-omit-frame-pointer"
|
||||
|
||||
debug_configs="--with-debug"
|
||||
if [ -z "$full_debug" ]
|
||||
then
|
||||
debug_cflags="$debug_cflags $debug_extra_cflags"
|
||||
fi
|
||||
|
||||
|
||||
#
|
||||
# Configuration options.
|
||||
|
2
VERSION
2
VERSION
@ -1,4 +1,4 @@
|
||||
MYSQL_VERSION_MAJOR=5
|
||||
MYSQL_VERSION_MINOR=5
|
||||
MYSQL_VERSION_PATCH=11
|
||||
MYSQL_VERSION_PATCH=15
|
||||
MYSQL_VERSION_EXTRA=
|
||||
|
@ -75,6 +75,7 @@ enum options_client
|
||||
OPT_SLAP_POST_SYSTEM,
|
||||
OPT_SLAP_COMMIT,
|
||||
OPT_SLAP_DETACH,
|
||||
OPT_SLAP_NO_DROP,
|
||||
OPT_MYSQL_REPLACE_INTO, OPT_BASE64_OUTPUT_MODE, OPT_SERVER_ID,
|
||||
OPT_FIX_TABLE_NAMES, OPT_FIX_DB_NAMES, OPT_SSL_VERIFY_SERVER_CERT,
|
||||
OPT_AUTO_VERTICAL_OUTPUT,
|
||||
|
@ -714,10 +714,18 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
|
||||
*/
|
||||
start_datetime= 0;
|
||||
offset= 0; // print everything and protect against cycling rec_count
|
||||
}
|
||||
if (server_id && (server_id != ev->server_id))
|
||||
/* skip just this event, continue processing the log. */
|
||||
/*
|
||||
Skip events according to the --server-id flag. However, don't
|
||||
skip format_description or rotate events, because they they
|
||||
are really "global" events that are relevant for the entire
|
||||
binlog, even if they have a server_id. Also, we have to read
|
||||
the format_description event so that we can parse subsequent
|
||||
events.
|
||||
*/
|
||||
if (ev_type != ROTATE_EVENT &&
|
||||
server_id && (server_id != ev->server_id))
|
||||
goto end;
|
||||
}
|
||||
if (((my_time_t)(ev->when) >= stop_datetime)
|
||||
|| (pos >= stop_position_mot))
|
||||
{
|
||||
@ -958,7 +966,8 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
|
||||
passed --short-form, because --short-form disables printing
|
||||
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();
|
||||
if (opt_base64_output_mode == BASE64_OUTPUT_NEVER)
|
||||
|
@ -128,7 +128,7 @@ const char *delimiter= "\n";
|
||||
|
||||
const char *create_schema_string= "mysqlslap";
|
||||
|
||||
static my_bool opt_preserve= TRUE;
|
||||
static my_bool opt_preserve= TRUE, opt_no_drop= FALSE;
|
||||
static my_bool debug_info_flag= 0, debug_check_flag= 0;
|
||||
static my_bool opt_only_print= FALSE;
|
||||
static my_bool opt_compress= FALSE, tty_password= FALSE,
|
||||
@ -607,6 +607,8 @@ static struct my_option my_long_options[] =
|
||||
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"iterations", 'i', "Number of times to run the tests.", &iterations,
|
||||
&iterations, 0, GET_UINT, REQUIRED_ARG, 1, 0, 0, 0, 0, 0},
|
||||
{"no-drop", OPT_SLAP_NO_DROP, "Do not drop the schema after the test.",
|
||||
&opt_no_drop, &opt_no_drop, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"number-char-cols", 'x',
|
||||
"Number of VARCHAR columns to create in table if specifying --auto-generate-sql.",
|
||||
&num_char_cols_opt, &num_char_cols_opt, 0, GET_STR, REQUIRED_ARG,
|
||||
@ -1149,8 +1151,11 @@ get_options(int *argc,char ***argv)
|
||||
if (!user)
|
||||
user= (char *)"root";
|
||||
|
||||
/* If something is created we clean it up, otherwise we leave schemas alone */
|
||||
if (create_string || auto_generate_sql)
|
||||
/*
|
||||
If something is created and --no-drop is not specified, we drop the
|
||||
schema.
|
||||
*/
|
||||
if (!opt_no_drop && (create_string || auto_generate_sql))
|
||||
opt_preserve= FALSE;
|
||||
|
||||
if (auto_generate_sql && (create_string || user_supplied_query))
|
||||
|
@ -4598,13 +4598,14 @@ static int my_kill(int pid, int sig)
|
||||
command called command
|
||||
|
||||
DESCRIPTION
|
||||
shutdown [<timeout>]
|
||||
shutdown_server [<timeout>]
|
||||
|
||||
*/
|
||||
|
||||
void do_shutdown_server(struct st_command *command)
|
||||
{
|
||||
int timeout=60, pid;
|
||||
long timeout=60;
|
||||
int pid;
|
||||
DYNAMIC_STRING ds_pidfile_name;
|
||||
MYSQL* mysql = &cur_con->mysql;
|
||||
static DYNAMIC_STRING ds_timeout;
|
||||
@ -4619,8 +4620,9 @@ void do_shutdown_server(struct st_command *command)
|
||||
|
||||
if (ds_timeout.length)
|
||||
{
|
||||
timeout= atoi(ds_timeout.str);
|
||||
if (timeout == 0)
|
||||
char* endptr;
|
||||
timeout= strtol(ds_timeout.str, &endptr, 10);
|
||||
if (*endptr != '\0')
|
||||
die("Illegal argument for timeout: '%s'", ds_timeout.str);
|
||||
}
|
||||
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_VOID_RETURN;
|
||||
}
|
||||
DBUG_PRINT("info", ("Sleeping, timeout: %d", timeout));
|
||||
DBUG_PRINT("info", ("Sleeping, timeout: %ld", timeout));
|
||||
my_sleep(1000000L);
|
||||
}
|
||||
|
||||
@ -8334,13 +8336,15 @@ int main(int argc, char **argv)
|
||||
}
|
||||
var_set_string("MYSQLTEST_FILE", cur_file->file_name);
|
||||
init_re();
|
||||
|
||||
/* Cursor protcol implies ps protocol */
|
||||
if (cursor_protocol)
|
||||
ps_protocol= 1;
|
||||
|
||||
ps_protocol_enabled= ps_protocol;
|
||||
sp_protocol_enabled= sp_protocol;
|
||||
view_protocol_enabled= view_protocol;
|
||||
cursor_protocol_enabled= cursor_protocol;
|
||||
/* Cursor protcol implies ps protocol */
|
||||
if (cursor_protocol_enabled)
|
||||
ps_protocol_enabled= 1;
|
||||
|
||||
st_connection *con= connections;
|
||||
#ifdef EMBEDDED_LIBRARY
|
||||
@ -10067,7 +10071,7 @@ int find_set(REP_SETS *sets,REP_SET *find)
|
||||
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
|
||||
@ -10087,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].found_offset=found_offset;
|
||||
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*/
|
||||
|
@ -19,8 +19,16 @@
|
||||
# plugin_audit.h and plugin_ftparser.h.
|
||||
#
|
||||
# We use gcc specific preprocessing command and sed/diff, so it will
|
||||
# only be run on Unix and only if gcc is used.
|
||||
IF(CMAKE_COMPILER_IS_GNUCC AND CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
# only be run on Unix and only if gcc is used. On some Unixes,
|
||||
# (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$")
|
||||
SET(COMPILER ${CMAKE_C_COMPILER_ARG1})
|
||||
STRING(REGEX REPLACE "^ " "" COMPILER ${COMPILER})
|
||||
|
@ -35,7 +35,7 @@ ENDMACRO()
|
||||
# Setup G++ (GNU C++ compiler) warning options.
|
||||
MACRO(SET_MYSQL_MAINTAINER_GNU_CXX_OPTIONS)
|
||||
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.")
|
||||
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
|
||||
# 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()
|
||||
|
||||
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_GETCWD 1 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_GETLINE 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_ISNAN 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_LDIV 1 CACHE INTERNAL "")
|
||||
SET(HAVE_LIMITS_H 1 CACHE INTERNAL "")
|
||||
|
@ -478,7 +478,13 @@ el_source(EditLine *el, const char *fname)
|
||||
|
||||
fp = 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";
|
||||
/* XXXMYSQL: Portability fix (for which platforms?) */
|
||||
#ifdef MAXPATHLEN
|
||||
@ -486,9 +492,13 @@ el_source(EditLine *el, const char *fname)
|
||||
#else
|
||||
char path[4096];
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ISSETUGID
|
||||
if (issetugid())
|
||||
return (-1);
|
||||
#elif defined(HAVE_IDENTITY_FUNCS)
|
||||
if (getuid() != geteuid() || getgid() != getegid())
|
||||
return (-1);
|
||||
#endif
|
||||
if ((ptr = getenv("HOME")) == NULL)
|
||||
return (-1);
|
||||
if (strlcpy(path, ptr, sizeof(path)) >= sizeof(path))
|
||||
@ -498,9 +508,10 @@ el_source(EditLine *el, const char *fname)
|
||||
fname = path;
|
||||
#else
|
||||
/*
|
||||
* If issetugid() is missing, always return an error, in order
|
||||
* to keep from inadvertently opening up the user to a security
|
||||
* hole.
|
||||
* If issetugid() or the above mentioned get[e][u|g]id()
|
||||
* functions are missing, always return an error, in order
|
||||
* to keep from inadvertently opening up the user to a
|
||||
* security hole.
|
||||
*/
|
||||
return (-1);
|
||||
#endif
|
||||
|
@ -1012,8 +1012,10 @@ vi_histedit(EditLine *el, int c __attribute__((__unused__)))
|
||||
if (fd < 0)
|
||||
return CC_ERROR;
|
||||
cp = el->el_line.buffer;
|
||||
write(fd, cp, el->el_line.lastchar - cp +0u);
|
||||
write(fd, "\n", 1);
|
||||
if (write(fd, cp, el->el_line.lastchar - cp +0u) == -1)
|
||||
goto error;
|
||||
if (write(fd, "\n", 1) == -1)
|
||||
goto error;
|
||||
pid = fork();
|
||||
switch (pid) {
|
||||
case -1:
|
||||
@ -1041,6 +1043,12 @@ vi_histedit(EditLine *el, int c __attribute__((__unused__)))
|
||||
unlink(tempfile);
|
||||
/* return CC_REFRESH; */
|
||||
return ed_newline(el, 0);
|
||||
|
||||
/* XXXMYSQL: Avoid compiler warnings. */
|
||||
error:
|
||||
close(fd);
|
||||
unlink(tempfile);
|
||||
return CC_ERROR;
|
||||
}
|
||||
|
||||
/* vi_history_word():
|
||||
|
@ -125,6 +125,7 @@
|
||||
#cmakedefine FIONREAD_IN_SYS_IOCTL 1
|
||||
#cmakedefine GWINSZ_IN_SYS_IOCTL 1
|
||||
#cmakedefine TIOCSTAT_IN_SYS_IOCTL 1
|
||||
#cmakedefine FIONREAD_IN_SYS_FILIO 1
|
||||
|
||||
/* Functions we may want to use. */
|
||||
#cmakedefine HAVE_AIOWAIT 1
|
||||
@ -157,7 +158,6 @@
|
||||
#cmakedefine HAVE_GETADDRINFO 1
|
||||
#cmakedefine HAVE_GETCWD 1
|
||||
#cmakedefine HAVE_GETHOSTBYADDR_R 1
|
||||
#cmakedefine HAVE_GETHOSTBYNAME_R 1
|
||||
#cmakedefine HAVE_GETHRTIME 1
|
||||
#cmakedefine HAVE_GETLINE 1
|
||||
#cmakedefine HAVE_GETNAMEINFO 1
|
||||
@ -174,6 +174,10 @@
|
||||
#cmakedefine gmtime_r @gmtime_r@
|
||||
#cmakedefine HAVE_INITGROUPS 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_ISINF 1
|
||||
#cmakedefine HAVE_LARGE_PAGE_OPTION 1
|
||||
@ -448,8 +452,6 @@
|
||||
|
||||
|
||||
#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_RWLOCKS 1
|
||||
@ -513,6 +515,7 @@
|
||||
#cmakedefine EXTRA_DEBUG 1
|
||||
#cmakedefine BACKUP_TEST 1
|
||||
#cmakedefine CYBOZU 1
|
||||
#cmakedefine USE_SYMDIR 1
|
||||
|
||||
/* Character sets and collations */
|
||||
#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 (getcwd HAVE_GETCWD)
|
||||
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 (getnameinfo HAVE_GETNAMEINFO)
|
||||
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 (initgroups HAVE_INITGROUPS)
|
||||
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 (localtime_r HAVE_LOCALTIME_R)
|
||||
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(FIONREAD "sys/ioctl.h" FIONREAD_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(finite "math.h" HAVE_FINITE_IN_MATH_H)
|
||||
@ -921,44 +925,6 @@ CHECK_CXX_SOURCE_COMPILES("
|
||||
"
|
||||
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
|
||||
#
|
||||
# This feature makes use of a mutex and is a scalability hog we
|
||||
|
@ -32,7 +32,7 @@ static my_bool verbose, print_all_codes;
|
||||
|
||||
#include "../include/my_base.h"
|
||||
#include "../mysys/my_handler_errors.h"
|
||||
#include "../include/my_handler.h"
|
||||
// #include "../include/my_compare.h"
|
||||
|
||||
#ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
|
||||
static my_bool ndb_code;
|
||||
@ -240,7 +240,39 @@ static my_bool print_win_error_msg(DWORD error, my_bool verbose)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
Register handler error messages for usage with my_error()
|
||||
|
||||
NOTES
|
||||
This is safe to call multiple times as my_error_register()
|
||||
will ignore calls to register already registered error numbers.
|
||||
*/
|
||||
|
||||
static const char **get_handler_error_messages()
|
||||
{
|
||||
return handler_error_messages;
|
||||
}
|
||||
|
||||
void my_handler_error_register(void)
|
||||
{
|
||||
/*
|
||||
If you got compilation error here about compile_time_assert array, check
|
||||
that every HA_ERR_xxx constant has a corresponding error message in
|
||||
handler_error_messages[] list (check mysys/ma_handler_errors.h and
|
||||
include/my_base.h).
|
||||
*/
|
||||
compile_time_assert(HA_ERR_FIRST + array_elements(handler_error_messages) ==
|
||||
HA_ERR_LAST + 1);
|
||||
my_error_register(get_handler_error_messages, HA_ERR_FIRST,
|
||||
HA_ERR_FIRST+ array_elements(handler_error_messages)-1);
|
||||
}
|
||||
|
||||
|
||||
void my_handler_error_unregister(void)
|
||||
{
|
||||
my_error_unregister(HA_ERR_FIRST,
|
||||
HA_ERR_FIRST+ array_elements(handler_error_messages)-1);
|
||||
}
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
|
@ -1,8 +1,9 @@
|
||||
/* 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
|
||||
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 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
|
||||
@ -11,7 +12,8 @@
|
||||
|
||||
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 */
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
02110-1301 USA */
|
||||
|
||||
/*
|
||||
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 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].found_offset=found_offset;
|
||||
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*/
|
||||
|
@ -29,14 +29,14 @@ typedef struct st_decimal_t {
|
||||
|
||||
int internal_str2dec(const char *from, decimal_t *to, char **end,
|
||||
my_bool fixed);
|
||||
int decimal2string(decimal_t *from, char *to, int *to_len,
|
||||
int decimal2string(const decimal_t *from, char *to, int *to_len,
|
||||
int fixed_precision, int fixed_decimals,
|
||||
char filler);
|
||||
int decimal2ulonglong(decimal_t *from, ulonglong *to);
|
||||
int ulonglong2decimal(ulonglong from, decimal_t *to);
|
||||
int decimal2longlong(decimal_t *from, longlong *to);
|
||||
int longlong2decimal(longlong from, decimal_t *to);
|
||||
int decimal2double(decimal_t *from, double *to);
|
||||
int decimal2double(const decimal_t *from, double *to);
|
||||
int double2decimal(double from, decimal_t *to);
|
||||
int decimal_actual_fraction(decimal_t *from);
|
||||
int decimal2bin(decimal_t *from, uchar *to, int precision, int scale);
|
||||
@ -47,17 +47,17 @@ int decimal_bin_size(int precision, int scale);
|
||||
int decimal_result_size(decimal_t *from1, decimal_t *from2, char op,
|
||||
int param);
|
||||
|
||||
int decimal_intg(decimal_t *from);
|
||||
int decimal_add(decimal_t *from1, decimal_t *from2, decimal_t *to);
|
||||
int decimal_sub(decimal_t *from1, decimal_t *from2, decimal_t *to);
|
||||
int decimal_cmp(decimal_t *from1, decimal_t *from2);
|
||||
int decimal_mul(decimal_t *from1, decimal_t *from2, decimal_t *to);
|
||||
int decimal_div(decimal_t *from1, decimal_t *from2, decimal_t *to,
|
||||
int decimal_intg(const decimal_t *from);
|
||||
int decimal_add(const decimal_t *from1, const decimal_t *from2, decimal_t *to);
|
||||
int decimal_sub(const decimal_t *from1, const decimal_t *from2, decimal_t *to);
|
||||
int decimal_cmp(const decimal_t *from1, const decimal_t *from2);
|
||||
int decimal_mul(const decimal_t *from1, const decimal_t *from2, decimal_t *to);
|
||||
int decimal_div(const decimal_t *from1, const decimal_t *from2, decimal_t *to,
|
||||
int scale_incr);
|
||||
int decimal_mod(decimal_t *from1, decimal_t *from2, decimal_t *to);
|
||||
int decimal_round(decimal_t *from, decimal_t *to, int new_scale,
|
||||
int decimal_mod(const decimal_t *from1, const decimal_t *from2, decimal_t *to);
|
||||
int decimal_round(const decimal_t *from, decimal_t *to, int new_scale,
|
||||
decimal_round_mode mode);
|
||||
int decimal_is_zero(decimal_t *from);
|
||||
int decimal_is_zero(const decimal_t *from);
|
||||
void max_decimal(int precision, int frac, decimal_t *to);
|
||||
|
||||
#define string2decimal(A,B,C) internal_str2dec((A), (B), (C), 0)
|
||||
|
@ -30,7 +30,7 @@ extern "C" {
|
||||
#include <my_pthread.h>
|
||||
#include <thr_lock.h>
|
||||
|
||||
#include "my_handler.h"
|
||||
#include "my_compare.h"
|
||||
#include "my_tree.h"
|
||||
|
||||
/* defines used by heap-funktions */
|
||||
|
@ -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_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_bin;
|
||||
extern CHARSET_INFO my_charset_utf8mb4_bin;
|
||||
|
@ -1,22 +1,20 @@
|
||||
/* Copyright (C) 2002-2006 MySQL AB
|
||||
/* 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 Library General Public
|
||||
License as published by the Free Software Foundation; version 2
|
||||
of the License.
|
||||
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
|
||||
Library General Public License for more details.
|
||||
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 Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
MA 02111-1307, USA */
|
||||
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 _my_handler_h
|
||||
#define _my_handler_h
|
||||
#ifndef _my_compare_h
|
||||
#define _my_compare_h
|
||||
|
||||
#include "myisampack.h"
|
||||
#ifdef __cplusplus
|
||||
@ -114,9 +112,6 @@ extern int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
|
||||
register uchar *b, uint key_length, uint nextflag,
|
||||
uint *diff_pos);
|
||||
|
||||
extern HA_KEYSEG *ha_find_null(HA_KEYSEG *keyseg, uchar *a);
|
||||
extern void my_handler_error_register(void);
|
||||
extern void my_handler_error_unregister(void);
|
||||
/*
|
||||
Inside an in-memory data record, memory pointers to pieces of the
|
||||
record (like BLOBs) are stored in their native byte order and in
|
||||
@ -127,4 +122,4 @@ extern void my_handler_error_unregister(void);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _my_handler_h */
|
||||
#endif /* _my_compare_h */
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2000-2003 MySQL AB, 2009 Sun Microsystems, Inc
|
||||
/* Copyright (c) 2000, 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
|
||||
@ -285,7 +285,7 @@ C_MODE_END
|
||||
#define ulonglong2double(A) my_ulonglong2double(A)
|
||||
#define my_off_t2double(A) my_ulonglong2double(A)
|
||||
C_MODE_START
|
||||
double my_ulonglong2double(unsigned long long A);
|
||||
inline double my_ulonglong2double(unsigned long long A) { return (double A); }
|
||||
C_MODE_END
|
||||
#endif /* _AIX */
|
||||
|
||||
@ -301,9 +301,6 @@ C_MODE_END
|
||||
#undef HAVE_PWRITE
|
||||
#endif
|
||||
|
||||
#ifdef UNDEF_HAVE_GETHOSTBYNAME_R /* For OSF4.x */
|
||||
#undef HAVE_GETHOSTBYNAME_R
|
||||
#endif
|
||||
#ifdef UNDEF_HAVE_INITGROUPS /* For AIX 4.3 */
|
||||
#undef HAVE_INITGROUPS
|
||||
#endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* 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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -73,38 +73,6 @@ C_MODE_START
|
||||
#define in_addr_t uint32
|
||||
#endif
|
||||
|
||||
/*
|
||||
Handling of gethostbyname_r()
|
||||
*/
|
||||
|
||||
#if !defined(HAVE_GETHOSTBYNAME_R)
|
||||
struct hostent *my_gethostbyname_r(const char *name,
|
||||
struct hostent *result, char *buffer,
|
||||
int buflen, int *h_errnop);
|
||||
void my_gethostbyname_r_free();
|
||||
#elif defined(HAVE_PTHREAD_ATTR_CREATE) || defined(_AIX) || defined(HAVE_GETHOSTBYNAME_R_GLIBC2_STYLE)
|
||||
struct hostent *my_gethostbyname_r(const char *name,
|
||||
struct hostent *result, char *buffer,
|
||||
int buflen, int *h_errnop);
|
||||
#define my_gethostbyname_r_free()
|
||||
#if !defined(HAVE_GETHOSTBYNAME_R_GLIBC2_STYLE) && !defined(HPUX10)
|
||||
#define GETHOSTBYNAME_BUFF_SIZE sizeof(struct hostent_data)
|
||||
#endif /* !defined(HAVE_GETHOSTBYNAME_R_GLIBC2_STYLE) */
|
||||
|
||||
#elif defined(HAVE_GETHOSTBYNAME_R_RETURN_INT)
|
||||
#define GETHOSTBYNAME_BUFF_SIZE sizeof(struct hostent_data)
|
||||
struct hostent *my_gethostbyname_r(const char *name,
|
||||
struct hostent *result, char *buffer,
|
||||
int buflen, int *h_errnop);
|
||||
#define my_gethostbyname_r_free()
|
||||
#else
|
||||
#define my_gethostbyname_r(A,B,C,D,E) gethostbyname_r((A),(B),(C),(D),(E))
|
||||
#define my_gethostbyname_r_free()
|
||||
#endif /* !defined(HAVE_GETHOSTBYNAME_R) */
|
||||
|
||||
#ifndef GETHOSTBYNAME_BUFF_SIZE
|
||||
#define GETHOSTBYNAME_BUFF_SIZE 2048
|
||||
#endif
|
||||
|
||||
C_MODE_END
|
||||
#endif
|
||||
|
@ -1,4 +1,5 @@
|
||||
/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc
|
||||
/* Copyright (C) 2000, 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
|
||||
@ -30,7 +31,7 @@ extern "C" {
|
||||
#ifndef _keycache_h
|
||||
#include "keycache.h"
|
||||
#endif
|
||||
#include "my_handler.h"
|
||||
#include "my_compare.h"
|
||||
#include <mysql/plugin.h>
|
||||
|
||||
/*
|
||||
|
@ -573,6 +573,8 @@ typedef struct st_mysql_bind
|
||||
} MYSQL_BIND;
|
||||
|
||||
|
||||
struct st_mysql_stmt_extension;
|
||||
|
||||
/* statement handler */
|
||||
typedef struct st_mysql_stmt
|
||||
{
|
||||
@ -618,7 +620,7 @@ typedef struct st_mysql_stmt
|
||||
metadata fields when doing mysql_stmt_store_result.
|
||||
*/
|
||||
my_bool update_max_length;
|
||||
void *extension;
|
||||
struct st_mysql_stmt_extension *extension;
|
||||
} MYSQL_STMT;
|
||||
|
||||
enum enum_stmt_attr_type
|
||||
|
@ -512,6 +512,7 @@ typedef struct st_mysql_bind
|
||||
my_bool is_null_value;
|
||||
void *extension;
|
||||
} MYSQL_BIND;
|
||||
struct st_mysql_stmt_extension;
|
||||
typedef struct st_mysql_stmt
|
||||
{
|
||||
MEM_ROOT mem_root;
|
||||
@ -541,7 +542,7 @@ typedef struct st_mysql_stmt
|
||||
unsigned char bind_result_done;
|
||||
my_bool unbuffered_fetch_cancelled;
|
||||
my_bool update_max_length;
|
||||
void *extension;
|
||||
struct st_mysql_stmt_extension *extension;
|
||||
} MYSQL_STMT;
|
||||
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
|
||||
**/
|
||||
int STDCALL mysql_plugin_options(struct st_mysql_client_plugin *plugin,
|
||||
const char *option,
|
||||
const void *value);
|
||||
int mysql_plugin_options(struct st_mysql_client_plugin *plugin,
|
||||
const char *option, const void *value);
|
||||
#endif
|
||||
|
||||
|
@ -35,6 +35,5 @@ mysql_client_find_plugin(struct st_mysql *mysql, const char *name, int type);
|
||||
struct st_mysql_client_plugin *
|
||||
mysql_client_register_plugin(struct st_mysql *mysql,
|
||||
struct st_mysql_client_plugin *plugin);
|
||||
int STDCALL mysql_plugin_options(struct st_mysql_client_plugin *plugin,
|
||||
const char *option,
|
||||
const void *value);
|
||||
int mysql_plugin_options(struct st_mysql_client_plugin *plugin,
|
||||
const char *option, const void *value);
|
||||
|
@ -114,6 +114,10 @@ enum enum_server_command
|
||||
#define FIELD_IN_PART_FUNC_FLAG (1 << 19)/* Field part of partition func */
|
||||
#define FIELD_IN_ADD_INDEX (1<< 20) /* Intern: Field used in ADD INDEX */
|
||||
#define FIELD_IS_RENAMED (1<< 21) /* Intern: Field is being renamed */
|
||||
#define FIELD_FLAGS_STORAGE_MEDIA 22 /* Field storage media, bit 22-23,
|
||||
reserved by MySQL Cluster */
|
||||
#define FIELD_FLAGS_COLUMN_FORMAT 24 /* Field column format, bit 24-25,
|
||||
reserved by MySQL Cluster */
|
||||
|
||||
#define REFRESH_GRANT 1 /* Refresh grant tables */
|
||||
#define REFRESH_LOG 2 /* Start on new log file */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* 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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -93,6 +93,8 @@ ssize_t vio_pending(Vio *vio);
|
||||
my_bool vio_get_normalized_ip_string(const struct sockaddr *addr, int addr_length,
|
||||
char *ip_string, size_t ip_string_size);
|
||||
|
||||
my_bool vio_is_no_name_error(int err_code);
|
||||
|
||||
int vio_getnameinfo(const struct sockaddr *sa,
|
||||
char *hostname, size_t hostname_size,
|
||||
char *port, size_t port_size,
|
||||
|
@ -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
|
||||
# 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
|
||||
get_password.c
|
||||
libmysql.c
|
||||
@ -151,6 +157,10 @@ ADD_DEPENDENCIES(clientlib GenError)
|
||||
|
||||
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
|
||||
# and link them together into shared library.
|
||||
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 org_my_init_done= 0;
|
||||
|
||||
typedef struct st_mysql_stmt_extension
|
||||
{
|
||||
MEM_ROOT fields_mem_root;
|
||||
} MYSQL_STMT_EXT;
|
||||
|
||||
|
||||
/*
|
||||
Initialize the MySQL client library
|
||||
@ -1480,11 +1485,16 @@ mysql_stmt_init(MYSQL *mysql)
|
||||
MYSQL_STMT *stmt;
|
||||
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))))
|
||||
{
|
||||
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);
|
||||
@ -1499,6 +1509,8 @@ mysql_stmt_init(MYSQL *mysql)
|
||||
strmov(stmt->sqlstate, not_error_sqlstate);
|
||||
/* The rest of statement members was bzeroed inside malloc */
|
||||
|
||||
init_alloc_root(&stmt->extension->fields_mem_root, 2048, 0);
|
||||
|
||||
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->param_count= stmt->field_count= 0;
|
||||
free_root(&stmt->mem_root, MYF(MY_KEEP_PREALLOC));
|
||||
free_root(&stmt->extension->fields_mem_root, MYF(0));
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
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
|
||||
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) *
|
||||
stmt->field_count)) ||
|
||||
!(stmt->bind= (MYSQL_BIND *) alloc_root(alloc,
|
||||
!(stmt->bind= (MYSQL_BIND *) alloc_root(fields_mem_root,
|
||||
sizeof(MYSQL_BIND) *
|
||||
stmt->field_count)))
|
||||
{
|
||||
@ -1658,18 +1671,36 @@ static void alloc_stmt_fields(MYSQL_STMT *stmt)
|
||||
field && fields < end; fields++, field++)
|
||||
{
|
||||
*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);
|
||||
field->db= strmake_root(alloc, fields->db, fields->db_length);
|
||||
field->table= strmake_root(alloc, fields->table, fields->table_length);
|
||||
field->org_table= strmake_root(alloc, fields->org_table,
|
||||
field->db= strmake_root(fields_mem_root,
|
||||
fields->db,
|
||||
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);
|
||||
field->name= strmake_root(alloc, fields->name, fields->name_length);
|
||||
field->org_name= strmake_root(alloc, fields->org_name,
|
||||
field->name= strmake_root(fields_mem_root,
|
||||
fields->name,
|
||||
fields->name_length);
|
||||
field->org_name= strmake_root(fields_mem_root,
|
||||
fields->org_name,
|
||||
fields->org_name_length);
|
||||
field->def= fields->def ? strmake_root(alloc, fields->def,
|
||||
fields->def_length) : 0;
|
||||
field->def_length= field->def ? fields->def_length : 0;
|
||||
if (fields->def)
|
||||
{
|
||||
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->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
|
||||
on prepare stage. Read it now.
|
||||
*/
|
||||
|
||||
stmt->field_count= stmt->mysql->field_count;
|
||||
|
||||
alloc_stmt_fields(stmt);
|
||||
}
|
||||
else
|
||||
@ -4605,6 +4639,7 @@ my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
|
||||
|
||||
free_root(&stmt->result.alloc, MYF(0));
|
||||
free_root(&stmt->mem_root, MYF(0));
|
||||
free_root(&stmt->extension->fields_mem_root, MYF(0));
|
||||
|
||||
if (mysql)
|
||||
{
|
||||
@ -4639,6 +4674,7 @@ my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
|
||||
}
|
||||
}
|
||||
|
||||
my_free(stmt->extension);
|
||||
my_free(stmt);
|
||||
|
||||
DBUG_RETURN(test(rc));
|
||||
@ -4805,16 +4841,13 @@ int STDCALL mysql_stmt_next_result(MYSQL_STMT *stmt)
|
||||
|
||||
stmt->state= MYSQL_STMT_EXECUTE_DONE;
|
||||
stmt->bind_result_done= FALSE;
|
||||
stmt->field_count= mysql->field_count;
|
||||
|
||||
if (mysql->field_count)
|
||||
{
|
||||
alloc_stmt_fields(stmt);
|
||||
prepare_to_fetch_result(stmt);
|
||||
}
|
||||
else
|
||||
{
|
||||
stmt->field_count= mysql->field_count;
|
||||
}
|
||||
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
@ -104,4 +104,3 @@ EXPORTS
|
||||
mysql_server_end
|
||||
mysql_set_character_set
|
||||
mysql_get_character_set_info
|
||||
mysql_plugin_options
|
||||
|
@ -2,6 +2,7 @@
|
||||
# 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_bug23533 # skozlov: BUG#12371924
|
||||
|
||||
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.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_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.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.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
|
||||
# Leaving the sys_vars tests for now. sys_vars.all_vars.test fails on removing ndb tests
|
||||
|
@ -11,18 +11,28 @@
|
||||
# on the slave)
|
||||
# $can_convert True if conversion shall work, false if it
|
||||
# shall generate an error
|
||||
# $engine_type The storage engine to be used for storing table
|
||||
# on both master and slave
|
||||
|
||||
if (!$engine_type)
|
||||
{
|
||||
# Use the default storage engine
|
||||
let $engine_type=`SELECT @@storage_engine`;
|
||||
}
|
||||
|
||||
connection master;
|
||||
disable_warnings;
|
||||
DROP TABLE IF EXISTS t1;
|
||||
enable_warnings;
|
||||
eval CREATE TABLE t1 (a $source_type);
|
||||
eval CREATE TABLE t1(
|
||||
pk INT NOT NULL PRIMARY KEY,
|
||||
a $source_type
|
||||
) ENGINE=$engine_type;
|
||||
sync_slave_with_master;
|
||||
eval ALTER TABLE t1 MODIFY a $target_type;
|
||||
|
||||
connection master;
|
||||
eval INSERT INTO t1 VALUES($source_value);
|
||||
eval INSERT INTO t1 VALUES(1, $source_value);
|
||||
if ($can_convert) {
|
||||
sync_slave_with_master;
|
||||
eval SELECT a = $target_value into @compare FROM t1;
|
||||
|
@ -122,11 +122,13 @@ SELECT f1,f2,f3,f4,f5,f6,f7,f8,f9,
|
||||
|
||||
#connection slave;
|
||||
|
||||
--disable_query_log
|
||||
call mtr.add_suppression("Slave SQL.*Table definition on master and slave does not match: Column 2 type mismatch.* 1535");
|
||||
call mtr.add_suppression("Slave SQL.*Error .Can.t DROP .c7.; check that column.key exists. on query.* 1091");
|
||||
call mtr.add_suppression("Slave SQL.*Error .Unknown column .c7. in .t15.. on query.* 1054");
|
||||
call mtr.add_suppression("Slave SQL.*Error .Key column .c6. doesn.t exist in table. on query.* 1072");
|
||||
call mtr.add_suppression("Slave.*Can.t DROP .c7.; check that column.key exists.* Error_code: 1091");
|
||||
call mtr.add_suppression("Slave.*Unknown column .c7. in .t15.* Error_code: 1054");
|
||||
call mtr.add_suppression("Slave.*Key column .c6. doesn.t exist in table.* Error_code: 1072");
|
||||
call mtr.add_suppression("Slave SQL.*Column 2 of table .test.t1.. cannot be converted from type.* Error_code: 1677");
|
||||
--enable_query_log
|
||||
|
||||
sync_slave_with_master;
|
||||
--echo
|
||||
|
@ -396,7 +396,7 @@ sync_slave_with_master;
|
||||
# Error reaction is up to sql_mode of the slave sql (bug#38173)
|
||||
#--echo *** Create t9 on slave ***
|
||||
# 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;
|
||||
RESET SLAVE;
|
||||
@ -440,13 +440,14 @@ if ($engine_type != NDB)
|
||||
#--let $slave_skip_counter= 2
|
||||
#--let $show_slave_sql_error= 1
|
||||
#--source include/wait_for_slave_sql_error_and_skip.inc
|
||||
}
|
||||
|
||||
#--echo *** Drop t9 ***
|
||||
connection master;
|
||||
DROP TABLE t9;
|
||||
sync_slave_with_master;
|
||||
|
||||
}
|
||||
|
||||
############################################
|
||||
# More columns in slave at middle of table #
|
||||
# Expect: Proper error message #
|
||||
|
@ -62,4 +62,24 @@ UPDATE t1 SET c1= 0;
|
||||
DROP TABLE t1;
|
||||
-- sync_slave_with_master
|
||||
|
||||
#
|
||||
# BUG#11766865: 60091: RBR + NO PK + UPDATE NULL VALUE --> SLAVE BREAK WITH ERROR HA_ERR_END_OF_
|
||||
#
|
||||
|
||||
--connection master
|
||||
--source include/rpl_reset.inc
|
||||
--connection master
|
||||
|
||||
--eval CREATE TABLE t1 (c1 int(11) NOT NULL, c2 int(11) NOT NULL, c3 int(11) DEFAULT '-1') ENGINE=$engine DEFAULT CHARSET=latin1
|
||||
|
||||
INSERT INTO t1 VALUES (1,2,NULL);
|
||||
UPDATE t1 SET c1=1, c2=2, c3=-1 WHERE c1=1 AND c2=2 AND ISNULL(c3);
|
||||
|
||||
--sync_slave_with_master
|
||||
|
||||
--let $diff_tables=master:test.t1, slave:test.t1
|
||||
--source include/diff_tables.inc
|
||||
|
||||
--connection master
|
||||
DROP TABLE t1;
|
||||
--sync_slave_with_master
|
||||
|
@ -23,8 +23,8 @@ insert into tm set a=null; # to simulate killed status on the slave
|
||||
commit;
|
||||
|
||||
connection slave;
|
||||
call mtr.add_suppression("Slave SQL.*slave SQL thread is being stopped in the middle of applying of a group having updated a non-transaction table");
|
||||
call mtr.add_suppression("Slave SQL.*The slave SQL is stopped, leaving the current group of events unfinished with a non-transaction table changed.");
|
||||
call mtr.add_suppression("Slave SQL.*Request to stop slave SQL Thread received while applying a group that has non-transactional changes; waiting for completion of the group");
|
||||
call mtr.add_suppression("Slave SQL.*Slave SQL Thread stopped with incomplete event group having non-transactional changes");
|
||||
|
||||
# slave will catch the killed status but won't shut down immediately
|
||||
# only after the whole group has done (commit)
|
||||
|
@ -1765,6 +1765,22 @@ SELECT
|
||||
HEX(DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY)) AS field_date,
|
||||
HEX(DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE)) AS field_datetime;
|
||||
|
||||
--echo #
|
||||
--echo # Bug#11926811 / Bug#60625 Illegal mix of collations
|
||||
--echo #
|
||||
SELECT @@collation_connection;
|
||||
DELIMITER //;
|
||||
CREATE PROCEDURE p1()
|
||||
BEGIN
|
||||
DECLARE v_LastPaymentDate DATETIME DEFAULT NULL;
|
||||
SELECT v_LastPaymentDate < NOW();
|
||||
EXPLAIN EXTENDED SELECT v_LastPaymentDate < NOW();
|
||||
SHOW WARNINGS;
|
||||
EXPLAIN EXTENDED SELECT CONCAT(v_LastPaymentDate, NOW());
|
||||
END//
|
||||
DELIMITER ;//
|
||||
CALL p1;
|
||||
DROP PROCEDURE p1;
|
||||
|
||||
--echo #
|
||||
--echo # Bug#52159 returning time type from function and empty left join causes debug assertion
|
||||
|
@ -2,3 +2,4 @@ disable_query_log;
|
||||
--require r/true.require
|
||||
select (PLUGIN_LIBRARY LIKE 'auth_test_plugin%') as `TRUE` FROM INFORMATION_SCHEMA.PLUGINS
|
||||
WHERE PLUGIN_NAME='test_plugin_server';
|
||||
enable_query_log;
|
||||
|
@ -634,6 +634,10 @@ drop table t1;
|
||||
drop table bug29807;
|
||||
create table bug29807 (a int);
|
||||
drop table bug29807;
|
||||
--disable_query_log
|
||||
call mtr.add_suppression("InnoDB: Error: table .test...bug29807. does not exist in the InnoDB internal");
|
||||
call mtr.add_suppression("Cannot find or open table test\/bug29807 from");
|
||||
--enable_query_log
|
||||
|
||||
|
||||
#
|
||||
|
@ -71,7 +71,7 @@ SET @@collation_connection = @collation_connection_saved||
|
||||
-- Insert patterns that should always be suppressed
|
||||
--
|
||||
INSERT INTO global_suppressions VALUES
|
||||
("'SELECT UNIX_TIMESTAMP\\(\\)' failed on master"),
|
||||
(".SELECT UNIX_TIMESTAMP... failed on master"),
|
||||
("Aborted connection"),
|
||||
("Client requested master to start replication from impossible position"),
|
||||
("Could not find first log file name in binary log"),
|
||||
@ -128,7 +128,6 @@ INSERT INTO global_suppressions VALUES
|
||||
("Sort aborted"),
|
||||
("Time-out in NDB"),
|
||||
("Warning:\s+One can only use the --user.*root"),
|
||||
("Warning:\s+Setting lower_case_table_names=2"),
|
||||
("Warning:\s+Table:.* on (delete|rename)"),
|
||||
("You have an error in your SQL syntax"),
|
||||
("deprecated"),
|
||||
@ -141,53 +140,20 @@ INSERT INTO global_suppressions VALUES
|
||||
("slave SQL thread aborted"),
|
||||
("Slave: .*Duplicate entry"),
|
||||
|
||||
/*
|
||||
Special case, made as specific as possible, for:
|
||||
Bug #28436: Incorrect position in SHOW BINLOG EVENTS causes
|
||||
server coredump
|
||||
*/
|
||||
|
||||
("Error in Log_event::read_log_event\\\(\\\): 'Sanity check failed', data_len: 258, event_type: 49"),
|
||||
|
||||
("Statement may not be safe to log in statement format"),
|
||||
|
||||
/* test case for Bug#bug29807 copies a stray frm into database */
|
||||
("InnoDB: Error: table `test`.`bug29807` does not exist in the InnoDB internal"),
|
||||
("Cannot find or open table test\/bug29807 from"),
|
||||
|
||||
/* innodb foreign key tests that fail in ALTER or RENAME produce this */
|
||||
("InnoDB: Error: in ALTER TABLE `test`.`t[123]`"),
|
||||
("InnoDB: Error: in RENAME TABLE table `test`.`t1`"),
|
||||
("InnoDB: Error: table `test`.`t[123]` does not exist in the InnoDB internal"),
|
||||
|
||||
/* Test case for Bug#14233 produces the following warnings: */
|
||||
("Stored routine 'test'.'bug14233_1': invalid value in column mysql.proc"),
|
||||
("Stored routine 'test'.'bug14233_2': invalid value in column mysql.proc"),
|
||||
("Stored routine 'test'.'bug14233_3': invalid value in column mysql.proc"),
|
||||
|
||||
/*
|
||||
BUG#32080 - Excessive warnings on Solaris: setrlimit could not
|
||||
change the size of core files
|
||||
*/
|
||||
("setrlimit could not change the size of core files to 'infinity'"),
|
||||
|
||||
/*
|
||||
rpl_extrColmaster_*.test, the slave thread produces warnings
|
||||
when it get updates to a table that has more columns on the
|
||||
master
|
||||
*/
|
||||
("Slave: Unknown column 'c7' in 't15' Error_code: 1054"),
|
||||
("Slave: Can't DROP 'c7'.* 1091"),
|
||||
("Slave: Key column 'c6'.* 1072"),
|
||||
("The slave I.O thread stops because a fatal error is encountered when it try to get the value of SERVER_ID variable from master."),
|
||||
(".SELECT UNIX_TIMESTAMP... failed on master, do not trust column Seconds_Behind_Master of SHOW SLAVE STATUS"),
|
||||
|
||||
/* Special case for Bug #26402 in show_check.test
|
||||
- Question marks are not valid file name parts on Windows. Ignore
|
||||
this error message.
|
||||
*/
|
||||
("Can't find file: '.\\\\test\\\\\\?{8}.frm'"),
|
||||
("Slave: Unknown table 't1' Error_code: 1051"),
|
||||
|
||||
/* Added 2009-08-XX after fixing Bug #42408 */
|
||||
|
||||
@ -215,14 +181,6 @@ INSERT INTO global_suppressions VALUES
|
||||
("==[0-9]*== Warning: invalid file descriptor -1 in syscall write()"),
|
||||
("==[0-9]*== Warning: invalid file descriptor -1 in syscall read()"),
|
||||
|
||||
/*
|
||||
Transient network failures that cause warnings on reconnect.
|
||||
BUG#47743 and BUG#47983.
|
||||
*/
|
||||
("Slave I/O: Get master SERVER_ID failed with error:.*"),
|
||||
("Slave I/O: Get master clock failed with error:.*"),
|
||||
("Slave I/O: Get master COLLATION_SERVER failed with error:.*"),
|
||||
("Slave I/O: Get master TIME_ZONE failed with error:.*"),
|
||||
/*
|
||||
BUG#42147 - Concurrent DML and LOCK TABLE ... READ for InnoDB
|
||||
table cause warnings in errlog
|
||||
|
24
mysql-test/include/not_crashrep.inc
Normal file
24
mysql-test/include/not_crashrep.inc
Normal file
@ -0,0 +1,24 @@
|
||||
# Check if CrashReporter is enabled and would open a window
|
||||
|
||||
perl;
|
||||
sub skip_test {
|
||||
# Only relevant on Mac OS X
|
||||
return 0 unless $^O eq 'darwin';
|
||||
my $crep= `defaults read com.apple.CrashReporter DialogType`;
|
||||
return 0 if $?;
|
||||
chomp ($crep);
|
||||
$crep= lc $crep;
|
||||
return ($crep eq 'basic' || $crep eq 'developer');
|
||||
}
|
||||
my $skip= skip_test();
|
||||
open (F, ">" . $ENV{'MYSQL_TMP_DIR'} . "/crashrep.inc");
|
||||
print F "let \$crashrep= $skip;\n";
|
||||
close F;
|
||||
EOF
|
||||
|
||||
--source $MYSQL_TMP_DIR/crashrep.inc
|
||||
--remove_file $MYSQL_TMP_DIR/crashrep.inc
|
||||
|
||||
if ($crashrep) {
|
||||
--skip CrashReporter would popup a window
|
||||
}
|
@ -31,6 +31,21 @@
|
||||
# Created: 2009-02-18 mleich
|
||||
#
|
||||
|
||||
if (!$condition)
|
||||
{
|
||||
--die ERROR IN TEST: the "condition" variable must be set
|
||||
}
|
||||
|
||||
if (!$field)
|
||||
{
|
||||
--die ERROR IN TEST: the "field" variable must be set
|
||||
}
|
||||
|
||||
if (!$show_statement)
|
||||
{
|
||||
--die ERROR IN TEST: the "show_statement" variable must be set
|
||||
}
|
||||
|
||||
let $max_run_time= 30;
|
||||
if ($wait_timeout)
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
# -*- 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
|
||||
# modify it under the terms of the GNU Library General Public
|
||||
@ -150,8 +150,12 @@ sub fix_tmpdir {
|
||||
sub fix_log_error {
|
||||
my ($self, $config, $group_name, $group)= @_;
|
||||
my $dir= $self->{ARGS}->{vardir};
|
||||
if ( $::opt_valgrind and $::opt_debug ) {
|
||||
return "$dir/log/$group_name.trace";
|
||||
} else {
|
||||
return "$dir/log/$group_name.err";
|
||||
}
|
||||
}
|
||||
|
||||
sub fix_log {
|
||||
my ($self, $config, $group_name, $group)= @_;
|
||||
|
@ -1,5 +1,5 @@
|
||||
# -*- 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
|
||||
# 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
|
||||
# which is a subdirectory of any of the paths
|
||||
my @extra_dirs;
|
||||
my $build_dir= $::opt_config_dir || $ENV{MTR_VS_CONFIG}
|
||||
|| $ENV{MTR_BUILD_DIR};
|
||||
my $build_dir= $::opt_vs_config || $ENV{MTR_VS_CONFIG} || $ENV{MTR_BUILD_DIR};
|
||||
push(@extra_dirs, $build_dir) if defined $build_dir;
|
||||
|
||||
if (defined $extension){
|
||||
|
@ -94,7 +94,7 @@ eval {
|
||||
local $SIG{INT}= \&handle_signal;
|
||||
local $SIG{CHLD}= sub {
|
||||
message("Got signal @_");
|
||||
kill(9, -$child_pid);
|
||||
kill('KILL', -$child_pid);
|
||||
my $ret= waitpid($child_pid, 0);
|
||||
if ($? & 127){
|
||||
exit(65); # Killed by signal
|
||||
@ -134,7 +134,7 @@ if ( $@ ) {
|
||||
# Use negative pid in order to kill the whole
|
||||
# process group
|
||||
#
|
||||
my $ret= kill(9, -$child_pid);
|
||||
my $ret= kill('KILL', -$child_pid);
|
||||
message("Killed child: $child_pid, ret: $ret");
|
||||
if ($ret > 0) {
|
||||
message("Killed child: $child_pid");
|
||||
|
@ -1,5 +1,5 @@
|
||||
# -*- 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
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -31,7 +31,7 @@ sub gcov_prepare ($) {
|
||||
#
|
||||
# Collect gcov statistics.
|
||||
# Arguments:
|
||||
# $dir basedir, normally source directory
|
||||
# $dir basedir, normally build directory
|
||||
# $gcov gcov utility program [path] name
|
||||
# $gcov_msg message file name
|
||||
# $gcov_err error file name
|
||||
@ -43,29 +43,25 @@ sub gcov_collect ($$$) {
|
||||
my $start_dir= cwd();
|
||||
|
||||
print "Collecting source coverage info using '$gcov'...\n";
|
||||
-f "$start_dir/$gcov_msg" and unlink("$start_dir/$gcov_msg");
|
||||
-f "$start_dir/$gcov_err" and unlink("$start_dir/$gcov_err");
|
||||
-f "$dir/$gcov_msg" and unlink("$dir/$gcov_msg");
|
||||
-f "$dir/$gcov_err" and unlink("$dir/$gcov_err");
|
||||
|
||||
my @dirs= `find "$dir" -type d -print | sort`;
|
||||
#print "List of directories:\n@dirs\n";
|
||||
|
||||
foreach my $d ( @dirs ) {
|
||||
my $dir_reported= 0;
|
||||
chomp($d);
|
||||
chdir($d) or next;
|
||||
|
||||
foreach my $f ( (glob("*.h"), glob("*.cc"), glob("*.c")) ) {
|
||||
$f =~ /(.*)\.[ch]c?/;
|
||||
-f "$1.gcno" or next;
|
||||
if (!$dir_reported) {
|
||||
print "Collecting in '$d'...\n";
|
||||
$dir_reported= 1;
|
||||
}
|
||||
system("$gcov $f 2>>$start_dir/$gcov_err >>$start_dir/$gcov_msg");
|
||||
my @flist= glob("*.*.gcno");
|
||||
print ("Collecting in '$d'...\n") if @flist;
|
||||
|
||||
foreach my $f (@flist) {
|
||||
system("$gcov $f 2>>$dir/$gcov_err >>$dir/$gcov_msg");
|
||||
}
|
||||
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";
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
# -*- cperl -*-
|
||||
# Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2004, 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 Library General Public
|
||||
@ -36,6 +36,7 @@ sub start_timer($);
|
||||
sub has_expired($);
|
||||
sub init_timers();
|
||||
sub mark_time_used($);
|
||||
sub mark_time_idle();
|
||||
sub add_total_times($);
|
||||
sub print_times_used($$);
|
||||
sub print_total_times($);
|
||||
@ -224,6 +225,7 @@ my %time_used= (
|
||||
'ch-warn' => 0,
|
||||
'test' => 0,
|
||||
'init' => 0,
|
||||
'admin' => 0,
|
||||
);
|
||||
|
||||
my %time_text= (
|
||||
@ -232,7 +234,8 @@ my %time_text= (
|
||||
'check' => "Check-testcase",
|
||||
'ch-warn' => "Check for warnings",
|
||||
'test' => "Test execution",
|
||||
'init' => "Initialization etc.",
|
||||
'init' => "Initialization/cleanup",
|
||||
'admin' => "Test administration",
|
||||
);
|
||||
|
||||
# Counts number of reports from workers
|
||||
@ -255,6 +258,10 @@ sub mark_time_used($) {
|
||||
$last_timer_set= $curr_time;
|
||||
}
|
||||
|
||||
sub mark_time_idle() {
|
||||
$last_timer_set= gettimeofday() if $opt_report_times;
|
||||
}
|
||||
|
||||
sub add_total_times($) {
|
||||
my ($dummy, $num, @line)= split (" ", $_[0]);
|
||||
|
||||
|
@ -210,8 +210,8 @@ our $opt_clean_vardir= $ENV{'MTR_CLEAN_VARDIR'};
|
||||
|
||||
our $opt_gcov;
|
||||
our $opt_gcov_exe= "gcov";
|
||||
our $opt_gcov_err= "mysql-test-gcov.msg";
|
||||
our $opt_gcov_msg= "mysql-test-gcov.err";
|
||||
our $opt_gcov_err= "mysql-test-gcov.err";
|
||||
our $opt_gcov_msg= "mysql-test-gcov.msg";
|
||||
|
||||
our $opt_gprof;
|
||||
our %gprof_dirs;
|
||||
@ -219,9 +219,12 @@ our %gprof_dirs;
|
||||
our $glob_debugger= 0;
|
||||
our $opt_gdb;
|
||||
our $opt_client_gdb;
|
||||
our $opt_dbx;
|
||||
our $opt_client_dbx;
|
||||
our $opt_ddd;
|
||||
our $opt_client_ddd;
|
||||
our $opt_manual_gdb;
|
||||
our $opt_manual_dbx;
|
||||
our $opt_manual_ddd;
|
||||
our $opt_manual_debug;
|
||||
our $opt_debugger;
|
||||
@ -271,12 +274,13 @@ my $opt_strace_client;
|
||||
|
||||
our $opt_user = "root";
|
||||
|
||||
my $opt_valgrind= 0;
|
||||
our $opt_valgrind= 0;
|
||||
my $opt_valgrind_mysqld= 0;
|
||||
my $opt_valgrind_mysqltest= 0;
|
||||
my @default_valgrind_args= ("--show-reachable=yes");
|
||||
my @valgrind_args;
|
||||
my $opt_valgrind_path;
|
||||
my $valgrind_reports= 0;
|
||||
my $opt_callgrind;
|
||||
my %mysqld_logs;
|
||||
my $opt_debug_sync_timeout= 300; # Default timeout for WAIT_FOR actions.
|
||||
@ -501,10 +505,29 @@ sub main {
|
||||
|
||||
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();
|
||||
|
||||
if ( $opt_gcov ) {
|
||||
gcov_collect($basedir, $opt_gcov_exe,
|
||||
gcov_collect($bindir, $opt_gcov_exe,
|
||||
$opt_gcov_msg, $opt_gcov_err);
|
||||
}
|
||||
|
||||
@ -546,7 +569,9 @@ sub run_test_server ($$$) {
|
||||
my $s= IO::Select->new();
|
||||
$s->add($server);
|
||||
while (1) {
|
||||
mark_time_used('admin');
|
||||
my @ready = $s->can_read(1); # Wake up once every second
|
||||
mark_time_idle();
|
||||
foreach my $sock (@ready) {
|
||||
if ($sock == $server) {
|
||||
# New client connected
|
||||
@ -699,6 +724,9 @@ sub run_test_server ($$$) {
|
||||
elsif ($line =~ /^SPENT/) {
|
||||
add_total_times($line);
|
||||
}
|
||||
elsif ($line eq 'VALGREP' && $opt_valgrind) {
|
||||
$valgrind_reports= 1;
|
||||
}
|
||||
else {
|
||||
mtr_error("Unknown response: '$line' from client");
|
||||
}
|
||||
@ -884,11 +912,12 @@ sub run_worker ($) {
|
||||
my $valgrind_reports= 0;
|
||||
if ($opt_valgrind_mysqld) {
|
||||
$valgrind_reports= valgrind_exit_reports();
|
||||
print $server "VALGREP\n" if $valgrind_reports;
|
||||
}
|
||||
if ( $opt_gprof ) {
|
||||
gprof_collect (find_mysqld($basedir), keys %gprof_dirs);
|
||||
}
|
||||
mark_time_used('init');
|
||||
mark_time_used('admin');
|
||||
print_times_used($server, $thread_num);
|
||||
exit($valgrind_reports);
|
||||
}
|
||||
@ -1001,6 +1030,9 @@ sub command_line_setup {
|
||||
'ddd' => \$opt_ddd,
|
||||
'client-ddd' => \$opt_client_ddd,
|
||||
'manual-ddd' => \$opt_manual_ddd,
|
||||
'dbx' => \$opt_dbx,
|
||||
'client-dbx' => \$opt_client_dbx,
|
||||
'manual-dbx' => \$opt_manual_dbx,
|
||||
'debugger=s' => \$opt_debugger,
|
||||
'client-debugger=s' => \$opt_client_debugger,
|
||||
'strace-client:s' => \$opt_strace_client,
|
||||
@ -1190,7 +1222,7 @@ sub command_line_setup {
|
||||
chomp;
|
||||
# remove comments (# foo) at the beginning of the line, or after a
|
||||
# blank at the end of the line
|
||||
s/( +|^)#.*$//;
|
||||
s/(\s+|^)#.*$//;
|
||||
# If @ platform specifier given, use this entry only if it contains
|
||||
# @<platform> or @!<xxx> where xxx != platform
|
||||
if (/\@.*/)
|
||||
@ -1201,8 +1233,8 @@ sub command_line_setup {
|
||||
s/\@.*$//;
|
||||
}
|
||||
# remove whitespace
|
||||
s/^ +//;
|
||||
s/ +$//;
|
||||
s/^\s+//;
|
||||
s/\s+$//;
|
||||
# if nothing left, don't need to remember this line
|
||||
if ( $_ eq "" ) {
|
||||
next;
|
||||
@ -1426,6 +1458,12 @@ sub command_line_setup {
|
||||
$opt_ddd= undef;
|
||||
}
|
||||
|
||||
if ($opt_dbx) {
|
||||
mtr_warning("Silently converting --dbx to --client-dbx in embedded mode");
|
||||
$opt_client_dbx= $opt_dbx;
|
||||
$opt_dbx= undef;
|
||||
}
|
||||
|
||||
if ($opt_debugger)
|
||||
{
|
||||
mtr_warning("Silently converting --debugger to --client-debugger in embedded mode");
|
||||
@ -1434,7 +1472,7 @@ sub command_line_setup {
|
||||
}
|
||||
|
||||
if ( $opt_gdb || $opt_ddd || $opt_manual_gdb || $opt_manual_ddd ||
|
||||
$opt_manual_debug || $opt_debugger )
|
||||
$opt_manual_debug || $opt_debugger || $opt_dbx || $opt_manual_dbx)
|
||||
{
|
||||
mtr_error("You need to use the client debug options for the",
|
||||
"embedded server. Ex: --client-gdb");
|
||||
@ -1462,6 +1500,7 @@ sub command_line_setup {
|
||||
# --------------------------------------------------------------------------
|
||||
if ( $opt_gdb || $opt_client_gdb || $opt_ddd || $opt_client_ddd ||
|
||||
$opt_manual_gdb || $opt_manual_ddd || $opt_manual_debug ||
|
||||
$opt_dbx || $opt_client_dbx || $opt_manual_dbx ||
|
||||
$opt_debugger || $opt_client_debugger )
|
||||
{
|
||||
# Indicate that we are using debugger
|
||||
@ -2181,7 +2220,12 @@ sub environment_setup {
|
||||
$ENV{'DEFAULT_MASTER_PORT'}= $mysqld_variables{'port'};
|
||||
$ENV{'MYSQL_TMP_DIR'}= $opt_tmpdir;
|
||||
$ENV{'MYSQLTEST_VARDIR'}= $opt_vardir;
|
||||
# Used for guessing default plugin dir, we can't really know for sure
|
||||
$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_SHAREDIR'}= $path_language;
|
||||
$ENV{'MYSQL_CHARSETSDIR'}= $path_charsetsdir;
|
||||
@ -3762,7 +3806,7 @@ sub run_testcase ($) {
|
||||
|
||||
do_before_run_mysqltest($tinfo);
|
||||
|
||||
mark_time_used('init');
|
||||
mark_time_used('admin');
|
||||
|
||||
if ( $opt_check_testcases and check_testcase($tinfo, "before") ){
|
||||
# Failed to record state of server or server crashed
|
||||
@ -4077,6 +4121,9 @@ sub extract_warning_lines ($$) {
|
||||
);
|
||||
my $skip_valgrind= 0;
|
||||
|
||||
my $last_pat= "";
|
||||
my $num_rep= 0;
|
||||
|
||||
foreach my $line ( @lines )
|
||||
{
|
||||
if ($opt_valgrind_mysqld) {
|
||||
@ -4091,11 +4138,29 @@ sub extract_warning_lines ($$) {
|
||||
{
|
||||
if ( $line =~ /$pat/ )
|
||||
{
|
||||
# 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
# Catch the case of last warning being repeated
|
||||
if ($num_rep) {
|
||||
print $Fwarn ".... repeated $num_rep times: $last_pat";
|
||||
}
|
||||
|
||||
$Fwarn = undef; # Close file
|
||||
|
||||
}
|
||||
@ -4704,6 +4769,9 @@ sub mysqld_start ($$) {
|
||||
{
|
||||
ddd_arguments(\$args, \$exe, $mysqld->name());
|
||||
}
|
||||
if ( $opt_dbx || $opt_manual_dbx ) {
|
||||
dbx_arguments(\$args, \$exe, $mysqld->name());
|
||||
}
|
||||
elsif ( $opt_debugger )
|
||||
{
|
||||
debugger_arguments(\$args, \$exe, $mysqld->name());
|
||||
@ -4729,13 +4797,6 @@ sub mysqld_start ($$) {
|
||||
unlink($mysqld->value('pid-file'));
|
||||
|
||||
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
|
||||
$mysqld_logs{$output}= 1 if $opt_valgrind;
|
||||
# Remember data dir for gmon.out files if using gprof
|
||||
@ -5232,7 +5293,7 @@ sub start_mysqltest ($) {
|
||||
my $exe= $exe_mysqltest;
|
||||
my $args;
|
||||
|
||||
mark_time_used('init');
|
||||
mark_time_used('admin');
|
||||
|
||||
mtr_init_args(\$args);
|
||||
|
||||
@ -5374,6 +5435,9 @@ sub start_mysqltest ($) {
|
||||
{
|
||||
ddd_arguments(\$args, \$exe, "client");
|
||||
}
|
||||
if ( $opt_client_dbx ) {
|
||||
dbx_arguments(\$args, \$exe, "client");
|
||||
}
|
||||
elsif ( $opt_client_debugger )
|
||||
{
|
||||
debugger_arguments(\$args, \$exe, "client");
|
||||
@ -5408,23 +5472,11 @@ sub gdb_arguments {
|
||||
# Remove the old gdbinit file
|
||||
unlink($gdb_init_file);
|
||||
|
||||
if ( $type eq "client" )
|
||||
{
|
||||
# write init file for client
|
||||
# write init file for mysqld or client
|
||||
mtr_tofile($gdb_init_file,
|
||||
"set args $str\n" .
|
||||
"break main\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
# write init file for mysqld
|
||||
mtr_tofile($gdb_init_file,
|
||||
"set args $str\n" .
|
||||
"break mysql_parse\n" .
|
||||
"commands 1\n" .
|
||||
"disable 1\n" .
|
||||
"end\n");
|
||||
}
|
||||
"break main\n" .
|
||||
"run");
|
||||
|
||||
if ( $opt_manual_gdb )
|
||||
{
|
||||
@ -5471,24 +5523,12 @@ sub ddd_arguments {
|
||||
# Remove the old gdbinit file
|
||||
unlink($gdb_init_file);
|
||||
|
||||
if ( $type eq "client" )
|
||||
{
|
||||
# write init file for client
|
||||
mtr_tofile($gdb_init_file,
|
||||
"set args $str\n" .
|
||||
"break main\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
# write init file for mysqld
|
||||
# write init file for mysqld or client
|
||||
mtr_tofile($gdb_init_file,
|
||||
"file $$exe\n" .
|
||||
"set args $str\n" .
|
||||
"break mysql_parse\n" .
|
||||
"commands 1\n" .
|
||||
"disable 1\n" .
|
||||
"end");
|
||||
}
|
||||
"break main\n" .
|
||||
"run");
|
||||
|
||||
if ( $opt_manual_ddd )
|
||||
{
|
||||
@ -5517,6 +5557,46 @@ sub ddd_arguments {
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Modify the exe and args so that program is run in dbx in xterm
|
||||
#
|
||||
sub dbx_arguments {
|
||||
my $args= shift;
|
||||
my $exe= shift;
|
||||
my $type= shift;
|
||||
|
||||
# Put $args into a single string
|
||||
my $str= join " ", @$$args;
|
||||
|
||||
if ( $opt_manual_dbx ) {
|
||||
print "\nTo start dbx for $type, type in another window:\n";
|
||||
print "cd $glob_mysql_test_dir; dbx -c \"stop in main; " .
|
||||
"run $str\" $$exe\n";
|
||||
|
||||
# Indicate the exe should not be started
|
||||
$$exe= undef;
|
||||
return;
|
||||
}
|
||||
|
||||
$$args= [];
|
||||
mtr_add_arg($$args, "-title");
|
||||
mtr_add_arg($$args, "$type");
|
||||
mtr_add_arg($$args, "-e");
|
||||
|
||||
if ( $exe_libtool ) {
|
||||
mtr_add_arg($$args, $exe_libtool);
|
||||
mtr_add_arg($$args, "--mode=execute");
|
||||
}
|
||||
|
||||
mtr_add_arg($$args, "dbx");
|
||||
mtr_add_arg($$args, "-c");
|
||||
mtr_add_arg($$args, "stop in main; run $str");
|
||||
mtr_add_arg($$args, "$$exe");
|
||||
|
||||
$$exe= "xterm";
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Modify the exe and args so that program is run in the selected debugger
|
||||
#
|
||||
@ -5547,18 +5627,6 @@ sub debugger_arguments {
|
||||
# Set exe to debuggername
|
||||
$$exe= $debugger;
|
||||
|
||||
}
|
||||
elsif ( $debugger eq "dbx" )
|
||||
{
|
||||
# xterm -e dbx -r exe arg1 .. argn
|
||||
|
||||
unshift(@$$args, $$exe);
|
||||
unshift(@$$args, "-r");
|
||||
unshift(@$$args, $debugger);
|
||||
unshift(@$$args, "-e");
|
||||
|
||||
$$exe= "xterm";
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -5635,6 +5703,7 @@ sub valgrind_exit_reports() {
|
||||
@culprits);
|
||||
mtr_print_line();
|
||||
print ("$valgrind_rep\n");
|
||||
$found_err= 1;
|
||||
$err_in_report= 0;
|
||||
}
|
||||
# Make ready to collect new report
|
||||
@ -5860,6 +5929,7 @@ Options for debugging the product
|
||||
client-ddd Start mysqltest client in ddd
|
||||
client-debugger=NAME Start mysqltest in the selected debugger
|
||||
client-gdb Start mysqltest client in gdb
|
||||
client-dbx Start mysqltest client in dbx
|
||||
ddd Start mysqld in ddd
|
||||
debug Dump trace output for all servers and client programs
|
||||
debug-common Same as debug, but sets 'd' debug flags to
|
||||
@ -5868,12 +5938,15 @@ Options for debugging the product
|
||||
tracing
|
||||
debugger=NAME Start mysqld in the selected debugger
|
||||
gdb Start the mysqld(s) in gdb
|
||||
dbx Start the mysqld(s) in dbx
|
||||
manual-debug Let user manually start mysqld in debugger, before
|
||||
running test(s)
|
||||
manual-gdb Let user manually start mysqld in gdb, before running
|
||||
test(s)
|
||||
manual-ddd Let user manually start mysqld in ddd, before running
|
||||
test(s)
|
||||
manual-dbx Let user manually start mysqld in dbx, before running
|
||||
test(s)
|
||||
strace-client[=path] Create strace output for mysqltest client, optionally
|
||||
specifying name and path to the trace program to use.
|
||||
Example: $0 --strace-client=ktrace
|
||||
|
@ -1391,3 +1391,16 @@ CREATE DATABASE db1 CHARACTER SET utf8;
|
||||
CREATE TABLE db1.t1 (bar TINYTEXT, KEY (bar(100)));
|
||||
ALTER TABLE db1.t1 ADD baz INT;
|
||||
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;
|
||||
|
@ -12807,3 +12807,19 @@ DROP TABLE t1;
|
||||
#
|
||||
CREATE TABLE `a/../`(a INT) ENGINE=ARCHIVE;
|
||||
DROP TABLE `a/../`;
|
||||
#
|
||||
# BUG#57162 - valgrind errors, random data when returning
|
||||
# ordered data from archive tables
|
||||
#
|
||||
SET sort_buffer_size=32804;
|
||||
CREATE TABLE t1(a INT, b CHAR(255), c CHAR(255), d CHAR(255),
|
||||
e CHAR(255), f INT) ENGINE=ARCHIVE DEFAULT CHARSET utf8;
|
||||
INSERT INTO t1 VALUES(-1,'b','c','d','e',1);
|
||||
INSERT INTO t1 SELECT * FROM t1;
|
||||
INSERT INTO t1 SELECT * FROM t1;
|
||||
INSERT INTO t1 SELECT t1.* FROM t1,t1 t2,t1 t3,t1 t4,t1 t5,t1 t6;
|
||||
SELECT * FROM t1 ORDER BY f LIMIT 1;
|
||||
a b c d e f
|
||||
-1 b c d e 1
|
||||
DROP TABLE t1;
|
||||
SET sort_buffer_size=DEFAULT;
|
||||
|
@ -6,3 +6,15 @@ set @my_max_allowed_packet= @@max_allowed_packet;
|
||||
set global max_allowed_packet=100*@@max_allowed_packet;
|
||||
set global max_allowed_packet=@my_max_allowed_packet;
|
||||
drop table t1;
|
||||
End of 5.1 tests
|
||||
#
|
||||
# Bug #11766306: 59393: HAVE_INNODB=YES WHEN MYSQLD
|
||||
# STARTED WITH --SKIP-INNODB
|
||||
#
|
||||
SHOW VARIABLES LIKE 'have_innodb';
|
||||
Variable_name Value
|
||||
have_innodb DISABLED
|
||||
SELECT SUPPORT FROM INFORMATION_SCHEMA.ENGINES WHERE engine='innodb';
|
||||
SUPPORT
|
||||
NO
|
||||
End of 5.5 tests
|
||||
|
@ -451,4 +451,21 @@ SELECT CONVERT(t2.a USING UTF8) FROM t1, t1 t2 LIMIT 1
|
||||
1
|
||||
1
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Bug #11765023: 57934: DOS POSSIBLE SINCE BINARY CASTING
|
||||
# DOESN'T ADHERE TO MAX_ALLOWED_PACKET
|
||||
SET @@GLOBAL.max_allowed_packet=2048;
|
||||
Warnings:
|
||||
Warning 1708 The value of 'max_allowed_packet' should be no less than the value of 'net_buffer_length'
|
||||
SELECT CONVERT('a', BINARY(2049));
|
||||
CONVERT('a', BINARY(2049))
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 1301 Result of cast_as_binary() was larger than max_allowed_packet (2048) - truncated
|
||||
SELECT CONVERT('a', CHAR(2049));
|
||||
CONVERT('a', CHAR(2049))
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 1301 Result of cast_as_char() was larger than max_allowed_packet (2048) - truncated
|
||||
SET @@GLOBAL.max_allowed_packet=default;
|
||||
End of 5.1 tests
|
||||
|
@ -2046,7 +2046,7 @@ create table t2 as select concat(a) from t1;
|
||||
show create table t2;
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`concat(a)` varbinary(2) DEFAULT NULL
|
||||
`concat(a)` varbinary(4) DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
drop table t1, t2;
|
||||
create table t1 (a year);
|
||||
@ -2355,7 +2355,7 @@ insert into t1 values (1);
|
||||
create view v1(a) as select concat(a) from t1;
|
||||
show columns from v1;
|
||||
Field Type Null Key Default Extra
|
||||
a varbinary(2) YES NULL
|
||||
a varbinary(4) YES NULL
|
||||
select hex(a) from v1;
|
||||
hex(a)
|
||||
3031
|
||||
@ -2807,6 +2807,32 @@ HEX(DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE)) AS fie
|
||||
field_str1 field1_str2 field_date field_datetime
|
||||
323030372D30382D30322032333A35393A3030 323030372D30382D30332031373A33323A3030 323030372D30382D3032 323030372D30382D30332031373A33323A3030
|
||||
#
|
||||
# Bug#11926811 / Bug#60625 Illegal mix of collations
|
||||
#
|
||||
SELECT @@collation_connection;
|
||||
@@collation_connection
|
||||
binary
|
||||
CREATE PROCEDURE p1()
|
||||
BEGIN
|
||||
DECLARE v_LastPaymentDate DATETIME DEFAULT NULL;
|
||||
SELECT v_LastPaymentDate < NOW();
|
||||
EXPLAIN EXTENDED SELECT v_LastPaymentDate < NOW();
|
||||
SHOW WARNINGS;
|
||||
EXPLAIN EXTENDED SELECT CONCAT(v_LastPaymentDate, NOW());
|
||||
END//
|
||||
CALL p1;
|
||||
v_LastPaymentDate < NOW()
|
||||
NULL
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||
Level Code Message
|
||||
Note 1003 select (v_LastPaymentDate@0 < now()) AS `v_LastPaymentDate < NOW()`
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||
Warnings:
|
||||
Note 1003 select concat(v_LastPaymentDate@0,now()) AS `CONCAT(v_LastPaymentDate, NOW())`
|
||||
DROP PROCEDURE p1;
|
||||
#
|
||||
# Bug#52159 returning time type from function and empty left join causes debug assertion
|
||||
#
|
||||
CREATE FUNCTION f1() RETURNS TIME RETURN 1;
|
||||
|
@ -2438,7 +2438,7 @@ create table t2 as select concat(a) from t1;
|
||||
show create table t2;
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`concat(a)` varchar(2) CHARACTER SET cp1251 DEFAULT NULL
|
||||
`concat(a)` varchar(4) CHARACTER SET cp1251 DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
drop table t1, t2;
|
||||
create table t1 (a year);
|
||||
@ -2747,7 +2747,7 @@ insert into t1 values (1);
|
||||
create view v1(a) as select concat(a) from t1;
|
||||
show columns from v1;
|
||||
Field Type Null Key Default Extra
|
||||
a varchar(2) YES NULL
|
||||
a varchar(4) YES NULL
|
||||
select hex(a) from v1;
|
||||
hex(a)
|
||||
3031
|
||||
@ -3199,6 +3199,32 @@ HEX(DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE)) AS fie
|
||||
field_str1 field1_str2 field_date field_datetime
|
||||
323030372D30382D30322032333A35393A3030 323030372D30382D30332031373A33323A3030 323030372D30382D3032 323030372D30382D30332031373A33323A3030
|
||||
#
|
||||
# Bug#11926811 / Bug#60625 Illegal mix of collations
|
||||
#
|
||||
SELECT @@collation_connection;
|
||||
@@collation_connection
|
||||
cp1251_general_ci
|
||||
CREATE PROCEDURE p1()
|
||||
BEGIN
|
||||
DECLARE v_LastPaymentDate DATETIME DEFAULT NULL;
|
||||
SELECT v_LastPaymentDate < NOW();
|
||||
EXPLAIN EXTENDED SELECT v_LastPaymentDate < NOW();
|
||||
SHOW WARNINGS;
|
||||
EXPLAIN EXTENDED SELECT CONCAT(v_LastPaymentDate, NOW());
|
||||
END//
|
||||
CALL p1;
|
||||
v_LastPaymentDate < NOW()
|
||||
NULL
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||
Level Code Message
|
||||
Note 1003 select (v_LastPaymentDate@0 < now()) AS `v_LastPaymentDate < NOW()`
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||
Warnings:
|
||||
Note 1003 select concat(convert(v_LastPaymentDate@0 using cp1251),now()) AS `CONCAT(v_LastPaymentDate, NOW())`
|
||||
DROP PROCEDURE p1;
|
||||
#
|
||||
# Bug#52159 returning time type from function and empty left join causes debug assertion
|
||||
#
|
||||
CREATE FUNCTION f1() RETURNS TIME RETURN 1;
|
||||
|
@ -2465,7 +2465,7 @@ create table t2 as select concat(a) from t1;
|
||||
show create table t2;
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`concat(a)` varchar(2) DEFAULT NULL
|
||||
`concat(a)` varchar(4) DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
drop table t1, t2;
|
||||
create table t1 (a year);
|
||||
@ -2774,7 +2774,7 @@ insert into t1 values (1);
|
||||
create view v1(a) as select concat(a) from t1;
|
||||
show columns from v1;
|
||||
Field Type Null Key Default Extra
|
||||
a varchar(2) YES NULL
|
||||
a varchar(4) YES NULL
|
||||
select hex(a) from v1;
|
||||
hex(a)
|
||||
3031
|
||||
@ -3226,6 +3226,32 @@ HEX(DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE)) AS fie
|
||||
field_str1 field1_str2 field_date field_datetime
|
||||
323030372D30382D30322032333A35393A3030 323030372D30382D30332031373A33323A3030 323030372D30382D3032 323030372D30382D30332031373A33323A3030
|
||||
#
|
||||
# Bug#11926811 / Bug#60625 Illegal mix of collations
|
||||
#
|
||||
SELECT @@collation_connection;
|
||||
@@collation_connection
|
||||
latin1_swedish_ci
|
||||
CREATE PROCEDURE p1()
|
||||
BEGIN
|
||||
DECLARE v_LastPaymentDate DATETIME DEFAULT NULL;
|
||||
SELECT v_LastPaymentDate < NOW();
|
||||
EXPLAIN EXTENDED SELECT v_LastPaymentDate < NOW();
|
||||
SHOW WARNINGS;
|
||||
EXPLAIN EXTENDED SELECT CONCAT(v_LastPaymentDate, NOW());
|
||||
END//
|
||||
CALL p1;
|
||||
v_LastPaymentDate < NOW()
|
||||
NULL
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||
Level Code Message
|
||||
Note 1003 select (v_LastPaymentDate@0 < now()) AS `v_LastPaymentDate < NOW()`
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||
Warnings:
|
||||
Note 1003 select concat(v_LastPaymentDate@0,now()) AS `CONCAT(v_LastPaymentDate, NOW())`
|
||||
DROP PROCEDURE p1;
|
||||
#
|
||||
# Bug#52159 returning time type from function and empty left join causes debug assertion
|
||||
#
|
||||
CREATE FUNCTION f1() RETURNS TIME RETURN 1;
|
||||
|
@ -3299,7 +3299,7 @@ create table t2 as select concat(a) from t1;
|
||||
show create table t2;
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`concat(a)` varchar(2) CHARACTER SET ucs2 DEFAULT NULL
|
||||
`concat(a)` varchar(4) CHARACTER SET ucs2 DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
drop table t1, t2;
|
||||
create table t1 (a year);
|
||||
@ -3608,7 +3608,7 @@ insert into t1 values (1);
|
||||
create view v1(a) as select concat(a) from t1;
|
||||
show columns from v1;
|
||||
Field Type Null Key Default Extra
|
||||
a varchar(2) YES NULL
|
||||
a varchar(4) YES NULL
|
||||
select hex(a) from v1;
|
||||
hex(a)
|
||||
00300031
|
||||
@ -4060,6 +4060,32 @@ HEX(DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE)) AS fie
|
||||
field_str1 field1_str2 field_date field_datetime
|
||||
0032003000300037002D00300038002D00300032002000320033003A00350039003A00300030 0032003000300037002D00300038002D00300033002000310037003A00330032003A00300030 323030372D30382D3032 323030372D30382D30332031373A33323A3030
|
||||
#
|
||||
# Bug#11926811 / Bug#60625 Illegal mix of collations
|
||||
#
|
||||
SELECT @@collation_connection;
|
||||
@@collation_connection
|
||||
ucs2_general_ci
|
||||
CREATE PROCEDURE p1()
|
||||
BEGIN
|
||||
DECLARE v_LastPaymentDate DATETIME DEFAULT NULL;
|
||||
SELECT v_LastPaymentDate < NOW();
|
||||
EXPLAIN EXTENDED SELECT v_LastPaymentDate < NOW();
|
||||
SHOW WARNINGS;
|
||||
EXPLAIN EXTENDED SELECT CONCAT(v_LastPaymentDate, NOW());
|
||||
END//
|
||||
CALL p1;
|
||||
v_LastPaymentDate < NOW()
|
||||
NULL
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||
Level Code Message
|
||||
Note 1003 select (v_LastPaymentDate@0 < now()) AS `v_LastPaymentDate < NOW()`
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||
Warnings:
|
||||
Note 1003 select concat(convert(v_LastPaymentDate@0 using ucs2),convert(now() using ucs2)) AS `CONCAT(v_LastPaymentDate, NOW())`
|
||||
DROP PROCEDURE p1;
|
||||
#
|
||||
# Bug#52159 returning time type from function and empty left join causes debug assertion
|
||||
#
|
||||
CREATE FUNCTION f1() RETURNS TIME RETURN 1;
|
||||
|
@ -4177,7 +4177,7 @@ create table t2 as select concat(a) from t1;
|
||||
show create table t2;
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`concat(a)` varchar(2) CHARACTER SET utf8 DEFAULT NULL
|
||||
`concat(a)` varchar(4) CHARACTER SET utf8 DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
drop table t1, t2;
|
||||
create table t1 (a year);
|
||||
@ -4486,7 +4486,7 @@ insert into t1 values (1);
|
||||
create view v1(a) as select concat(a) from t1;
|
||||
show columns from v1;
|
||||
Field Type Null Key Default Extra
|
||||
a varchar(2) YES NULL
|
||||
a varchar(4) YES NULL
|
||||
select hex(a) from v1;
|
||||
hex(a)
|
||||
3031
|
||||
@ -4938,6 +4938,32 @@ HEX(DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE)) AS fie
|
||||
field_str1 field1_str2 field_date field_datetime
|
||||
323030372D30382D30322032333A35393A3030 323030372D30382D30332031373A33323A3030 323030372D30382D3032 323030372D30382D30332031373A33323A3030
|
||||
#
|
||||
# Bug#11926811 / Bug#60625 Illegal mix of collations
|
||||
#
|
||||
SELECT @@collation_connection;
|
||||
@@collation_connection
|
||||
utf8_general_ci
|
||||
CREATE PROCEDURE p1()
|
||||
BEGIN
|
||||
DECLARE v_LastPaymentDate DATETIME DEFAULT NULL;
|
||||
SELECT v_LastPaymentDate < NOW();
|
||||
EXPLAIN EXTENDED SELECT v_LastPaymentDate < NOW();
|
||||
SHOW WARNINGS;
|
||||
EXPLAIN EXTENDED SELECT CONCAT(v_LastPaymentDate, NOW());
|
||||
END//
|
||||
CALL p1;
|
||||
v_LastPaymentDate < NOW()
|
||||
NULL
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||
Level Code Message
|
||||
Note 1003 select (v_LastPaymentDate@0 < now()) AS `v_LastPaymentDate < NOW()`
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||
Warnings:
|
||||
Note 1003 select concat(convert(v_LastPaymentDate@0 using utf8),now()) AS `CONCAT(v_LastPaymentDate, NOW())`
|
||||
DROP PROCEDURE p1;
|
||||
#
|
||||
# Bug#52159 returning time type from function and empty left join causes debug assertion
|
||||
#
|
||||
CREATE FUNCTION f1() RETURNS TIME RETURN 1;
|
||||
|
@ -794,3 +794,14 @@ DROP TABLE t1;
|
||||
SET @@sort_buffer_size = @old_sort_buffer_size;
|
||||
SET @@max_heap_table_size = @old_max_heap_table_size;
|
||||
End of 5.1 tests
|
||||
#
|
||||
# Bug #11744875: 4082: integer lengths cause truncation with distinct concat and innodb
|
||||
#
|
||||
CREATE TABLE t1 (a INT(1), b INT(1));
|
||||
INSERT INTO t1 VALUES (1111, 2222), (3333, 4444);
|
||||
SELECT DISTINCT CONCAT(a,b) AS c FROM t1 ORDER BY 1;
|
||||
c
|
||||
11112222
|
||||
33334444
|
||||
DROP TABLE t1;
|
||||
End of 5.5 tests
|
||||
|
@ -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 db_x;
|
||||
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
|
||||
event information after mysql.event was tampered with.
|
||||
|
||||
First, let's add a column to the end and make sure everything
|
||||
works as before
|
||||
First, let's add a column to the end and check the error is emitted.
|
||||
|
||||
ALTER TABLE mysql.event ADD dummy INT;
|
||||
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
|
||||
events_test intact_check root@localhost SYSTEM RECURRING NULL 10 # # NULL ENABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci
|
||||
ERROR HY000: Failed to open mysql.event
|
||||
SELECT event_name FROM INFORMATION_SCHEMA.events;
|
||||
event_name
|
||||
intact_check
|
||||
ERROR HY000: Failed to open mysql.event
|
||||
SHOW CREATE EVENT intact_check;
|
||||
Event sql_mode time_zone Create Event character_set_client collation_connection Database Collation
|
||||
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
|
||||
ERROR HY000: Failed to open mysql.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;
|
||||
ERROR HY000: Failed to open mysql.event
|
||||
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;
|
||||
ERROR HY000: Failed to open mysql.event
|
||||
DROP EVENT intact_check_1;
|
||||
ERROR HY000: Unknown event 'intact_check_1'
|
||||
ERROR HY000: Failed to open mysql.event
|
||||
DROP EVENT intact_check_2;
|
||||
ERROR HY000: Failed to open mysql.event
|
||||
DROP EVENT intact_check;
|
||||
ERROR HY000: Failed to open mysql.event
|
||||
DROP DATABASE IF EXISTS mysqltest_no_such_database;
|
||||
Warnings:
|
||||
Note 1008 Can't drop database 'mysqltest_no_such_database'; database doesn't exist
|
||||
CREATE DATABASE mysqltest_db2;
|
||||
DROP DATABASE mysqltest_db2;
|
||||
Warnings:
|
||||
Error 1545 Failed to open mysql.event
|
||||
SELECT @@event_scheduler;
|
||||
@@event_scheduler
|
||||
OFF
|
||||
@ -294,6 +298,7 @@ Variable_name Value
|
||||
event_scheduler OFF
|
||||
SET GLOBAL event_scheduler=OFF;
|
||||
ALTER TABLE mysql.event DROP dummy;
|
||||
DROP EVENT intact_check;
|
||||
CREATE EVENT intact_check ON SCHEDULE EVERY 10 HOUR DO SELECT "nothing";
|
||||
|
||||
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;
|
||||
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;
|
||||
ERROR HY000: Cannot load from mysql.event. The table is probably corrupted
|
||||
ERROR HY000: Failed to open mysql.event
|
||||
SHOW CREATE EVENT intact_check;
|
||||
ERROR HY000: Unknown event 'intact_check'
|
||||
ERROR HY000: Failed to open mysql.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;
|
||||
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;
|
||||
ERROR HY000: Unknown event 'intact_check_1'
|
||||
ERROR HY000: Failed to open mysql.event
|
||||
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;
|
||||
ERROR HY000: Unknown event 'intact_check_1'
|
||||
ERROR HY000: Failed to open mysql.event
|
||||
DROP EVENT intact_check_2;
|
||||
ERROR HY000: Unknown event 'intact_check_2'
|
||||
ERROR HY000: Failed to open mysql.event
|
||||
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;
|
||||
Warnings:
|
||||
Note 1008 Can't drop database 'mysqltest_no_such_database'; database doesn't exist
|
||||
CREATE DATABASE mysqltest_db2;
|
||||
DROP DATABASE mysqltest_db2;
|
||||
Warnings:
|
||||
Error 1545 Failed to open mysql.event
|
||||
SELECT @@event_scheduler;
|
||||
@@event_scheduler
|
||||
OFF
|
||||
@ -345,29 +352,32 @@ Drop some columns and try more checks.
|
||||
|
||||
ALTER TABLE mysql.event DROP comment, DROP starts;
|
||||
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;
|
||||
ERROR HY000: Cannot load from mysql.event. The table is probably corrupted
|
||||
ERROR HY000: Failed to open mysql.event
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
ERROR HY000: Unknown event 'intact_check_1'
|
||||
ERROR HY000: Failed to open mysql.event
|
||||
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;
|
||||
ERROR HY000: Unknown event 'intact_check_1'
|
||||
ERROR HY000: Failed to open mysql.event
|
||||
DROP EVENT intact_check_2;
|
||||
ERROR HY000: Unknown event 'intact_check_2'
|
||||
ERROR HY000: Failed to open mysql.event
|
||||
DROP EVENT intact_check;
|
||||
ERROR HY000: Failed to open mysql.event
|
||||
DROP DATABASE IF EXISTS mysqltest_no_such_database;
|
||||
Warnings:
|
||||
Note 1008 Can't drop database 'mysqltest_no_such_database'; database doesn't exist
|
||||
CREATE DATABASE mysqltest_db2;
|
||||
DROP DATABASE mysqltest_db2;
|
||||
Warnings:
|
||||
Error 1545 Failed to open mysql.event
|
||||
SELECT @@event_scheduler;
|
||||
@@event_scheduler
|
||||
OFF
|
||||
@ -425,4 +435,42 @@ CREATE TABLE mysql.event like event_like;
|
||||
DROP TABLE event_like;
|
||||
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
|
||||
|
||||
#
|
||||
# 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;
|
||||
|
@ -747,6 +747,15 @@ event_name originator
|
||||
ev1 4294967295
|
||||
DROP EVENT ev1;
|
||||
SET GLOBAL server_id = @old_server_id;
|
||||
CREATE DATABASE event_test12;
|
||||
USE event_test12;
|
||||
CREATE EVENT ev1 ON SCHEDULE EVERY 1 DAY DO SELECT 1;
|
||||
CREATE DATABASE event_test1;
|
||||
USE event_test1;
|
||||
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
|
||||
DROP DATABASE event_test1;
|
||||
DROP DATABASE event_test12;
|
||||
DROP DATABASE events_test;
|
||||
SET GLOBAL event_scheduler= 'ON';
|
||||
SET @@global.concurrent_insert= @concurrent_insert;
|
||||
|
@ -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;
|
||||
drop database if exists 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
|
||||
create database mysqltest_db1;
|
||||
drop database mysqltest_db1;
|
||||
Warnings:
|
||||
Error 1545 Failed to open mysql.event
|
||||
Restore the original mysql.event table
|
||||
drop table mysql.event;
|
||||
rename table event_like to mysql.event;
|
||||
|
@ -180,7 +180,6 @@ ERROR 42000: Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP col
|
||||
SHOW WARNINGS;
|
||||
Level Code Message
|
||||
Error 1140 Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause
|
||||
Note 1003 select 1 AS `1` from `test`.`t1` where <not>(<exists>(...))
|
||||
SET SESSION sql_mode=@old_sql_mode;
|
||||
DROP TABLE t1;
|
||||
End of 5.0 tests.
|
||||
@ -318,3 +317,17 @@ id select_type table type possible_keys key key_len ref rows Extra
|
||||
DEALLOCATE PREPARE stmt;
|
||||
DROP TABLE t1;
|
||||
End of 5.1 tests.
|
||||
#
|
||||
# Bug#11829785 EXPLAIN EXTENDED CRASH WITH RIGHT OUTER JOIN, SUBQUERIES
|
||||
#
|
||||
CREATE TABLE t1(a INT);
|
||||
INSERT INTO t1 VALUES (0), (0);
|
||||
PREPARE s FROM
|
||||
'EXPLAIN EXTENDED
|
||||
SELECT SUBSTRING(1, (SELECT 1 FROM t1 a1 RIGHT OUTER JOIN t1 ON 0)) AS d
|
||||
FROM t1 WHERE 0 > ANY (SELECT @a FROM t1)';
|
||||
EXECUTE s;
|
||||
ERROR 21000: Subquery returns more than 1 row
|
||||
DEALLOCATE PREPARE s;
|
||||
DROP TABLE t1;
|
||||
#
|
||||
|
@ -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
|
||||
test.t1.a e e- 1 2 0 0 1.3333 NULL ENUM('e','e-') NOT NULL
|
||||
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
|
||||
|
@ -1056,7 +1056,6 @@ ERROR HY000: Only constant XPATH queries are supported
|
||||
SHOW WARNINGS;
|
||||
Level Code Message
|
||||
Error 1105 Only constant XPATH queries are supported
|
||||
Note 1003 select updatexml('1',`test`.`t1`.`a`,'1') AS `UPDATEXML('1', a, '1')` from `test`.`t1` order by (select group_concat(1 separator ',') from `test`.`t1`)
|
||||
DROP TABLE t1;
|
||||
End of 5.1 tests
|
||||
DROP TABLE IF EXISTS t1, t2;
|
||||
|
@ -1737,6 +1737,26 @@ SELECT MIN(GET_LOCK('aaaaaaaaaaaaaaaaa',0) / '0b11111111111111111111111111111111
|
||||
SELECT MIN(GET_LOCK('aaaaaaaaaaaaaaaaa',0) / '0b1111111111111111111111111111111111111111111111111111111111111111111111111' ^ (RAND()));
|
||||
SELECT RELEASE_LOCK('aaaaaaaaaaaaaaaaa');
|
||||
#
|
||||
# Bug #11766094 - 59132: MIN() AND MAX() REMOVE UNSIGNEDNESS
|
||||
#
|
||||
CREATE TABLE t1 (a BIGINT UNSIGNED);
|
||||
INSERT INTO t1 VALUES (18446668621106209655);
|
||||
SELECT MAX(LENGTH(a)), LENGTH(MAX(a)), MIN(a), MAX(a), CONCAT(MIN(a)), CONCAT(MAX(a)) FROM t1;
|
||||
MAX(LENGTH(a)) LENGTH(MAX(a)) MIN(a) MAX(a) CONCAT(MIN(a)) CONCAT(MAX(a))
|
||||
20 20 18446668621106209655 18446668621106209655 18446668621106209655 18446668621106209655
|
||||
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
|
||||
#
|
||||
# Bug#52123 Assertion failed: aggregator == aggr->Aggrtype(),
|
||||
|
@ -770,4 +770,10 @@ CASE a WHEN a THEN a END
|
||||
NULL
|
||||
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
|
||||
|
@ -514,6 +514,35 @@ t1 CREATE TABLE `t1` (
|
||||
`C` varchar(23) DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Bug#11764994 57900: CREATE TABLE .. SELECT ASSERTS SCALE >= 0 && PRECISION > 0 && SCALE <= PR
|
||||
#
|
||||
CREATE TABLE t1 SELECT CEIL(LINESTRINGFROMWKB(1) DIV NULL);
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 SELECT FLOOR(LINESTRINGFROMWKB(1) DIV NULL);
|
||||
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
|
||||
#
|
||||
# Bug #8433: Overflow must be an error
|
||||
@ -656,3 +685,11 @@ Warning 1366 Incorrect decimal value: '' for column '' at row -1
|
||||
SELECT 1 div null;
|
||||
1 div null
|
||||
NULL
|
||||
#
|
||||
# Bug #11792200 - DIVIDING LARGE NUMBERS CAUSES STACK CORRUPTIONS
|
||||
#
|
||||
select (1.175494351E-37 div 1.7976931348623157E+308);
|
||||
(1.175494351E-37 div 1.7976931348623157E+308)
|
||||
0
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect DECIMAL value: ''
|
||||
|
@ -1347,6 +1347,48 @@ Warning 1292 Truncated incorrect time value: ''
|
||||
Warning 1292 Truncated incorrect time value: ''
|
||||
Warning 1292 Truncated incorrect time value: ''
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Bug#11766112 59151:UNINITIALIZED VALUES IN EXTRACT_DATE_TIME WITH STR_TO_DATE(SPACE(..) ...
|
||||
#
|
||||
SELECT STR_TO_DATE(SPACE(2),'1');
|
||||
STR_TO_DATE(SPACE(2),'1')
|
||||
0000-00-00
|
||||
#
|
||||
# Bug#11765216 58154: UNINITIALIZED VARIABLE FORMAT IN STR_TO_DATE FUNCTION
|
||||
#
|
||||
SET GLOBAL SQL_MODE='';
|
||||
DO STR_TO_DATE((''), FROM_DAYS(@@GLOBAL.SQL_MODE));
|
||||
SET GLOBAL SQL_MODE=DEFAULT;
|
||||
#
|
||||
# Bug#11766087 59125: VALGRIND UNINITIALISED VALUE WARNING IN ULL2DEC, LONGLONG2DECIMAL
|
||||
#
|
||||
SELECT FORMAT(YEAR(STR_TO_DATE('',GET_FORMAT(TIME,''))),1);
|
||||
FORMAT(YEAR(STR_TO_DATE('',GET_FORMAT(TIME,''))),1)
|
||||
NULL
|
||||
#
|
||||
# Bug#11766126 59166: ANOTHER DATETIME VALGRIND UNINITIALIZED WARNING
|
||||
#
|
||||
SELECT CAST((MONTH(FROM_UNIXTIME(@@GLOBAL.SQL_MODE))) AS BINARY(1025));
|
||||
CAST((MONTH(FROM_UNIXTIME(@@GLOBAL.SQL_MODE))) AS BINARY(1025))
|
||||
NULL
|
||||
#
|
||||
# Bug#11766124 59164: VALGRIND: UNINITIALIZED VALUE IN NUMBER_TO_DATETIME
|
||||
#
|
||||
SELECT ADDDATE(MONTH(FROM_UNIXTIME(NULL)),INTERVAL 1 HOUR);
|
||||
ADDDATE(MONTH(FROM_UNIXTIME(NULL)),INTERVAL 1 HOUR)
|
||||
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
|
||||
#
|
||||
# Bug#57039: constant subtime expression returns incorrect result.
|
||||
|
@ -1043,6 +1043,10 @@ create spatial index i on t1 (a);
|
||||
ERROR 42000: A SPATIAL index may only contain a geometrical type column
|
||||
drop table t1;
|
||||
End of 5.1 tests
|
||||
CREATE TABLE t0 (a BINARY(32) NOT NULL);
|
||||
CREATE SPATIAL INDEX i on t0 (a);
|
||||
ERROR 42000: A SPATIAL index may only contain a geometrical type column
|
||||
INSERT INTO t0 VALUES (1);
|
||||
CREATE TABLE t1(
|
||||
col0 BINARY NOT NULL,
|
||||
col2 TIMESTAMP,
|
||||
@ -1071,5 +1075,5 @@ col2 LINESTRING,
|
||||
SPATIAL INDEX i1 (col1, col2)
|
||||
);
|
||||
ERROR HY000: Incorrect arguments to SPATIAL INDEX
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t2;
|
||||
DROP TABLE t0, t1, t2;
|
||||
End of 5.5 tests
|
||||
|
@ -54,7 +54,7 @@ max_updates 0
|
||||
max_connections 0
|
||||
max_user_connections 0
|
||||
plugin
|
||||
authentication_string
|
||||
authentication_string NULL
|
||||
show grants for mysqltest_1@localhost;
|
||||
Grants for mysqltest_1@localhost
|
||||
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' REQUIRE CIPHER 'EDH-RSA-DES-CBC3-SHA'
|
||||
@ -125,7 +125,7 @@ max_updates 0
|
||||
max_connections 0
|
||||
max_user_connections 0
|
||||
plugin
|
||||
authentication_string
|
||||
authentication_string NULL
|
||||
show grants for mysqltest_1@localhost;
|
||||
Grants for mysqltest_1@localhost
|
||||
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' WITH MAX_QUERIES_PER_HOUR 10
|
||||
@ -172,7 +172,7 @@ max_updates 20
|
||||
max_connections 30
|
||||
max_user_connections 0
|
||||
plugin
|
||||
authentication_string
|
||||
authentication_string NULL
|
||||
show grants for mysqltest_1@localhost;
|
||||
Grants for mysqltest_1@localhost
|
||||
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' WITH MAX_QUERIES_PER_HOUR 10 MAX_UPDATES_PER_HOUR 20 MAX_CONNECTIONS_PER_HOUR 30
|
||||
@ -284,7 +284,6 @@ Warnings:
|
||||
Warning 1364 Field 'ssl_cipher' doesn't have a default value
|
||||
Warning 1364 Field 'x509_issuer' doesn't have a default value
|
||||
Warning 1364 Field 'x509_subject' doesn't have a default value
|
||||
Warning 1364 Field 'authentication_string' doesn't have a default value
|
||||
insert into mysql.db (host, db, user, select_priv) values
|
||||
('localhost', 'a%', 'test11', 'Y'), ('localhost', 'ab%', 'test11', 'Y');
|
||||
alter table mysql.db order by db asc;
|
||||
|
@ -287,7 +287,6 @@ Warnings:
|
||||
Warning 1364 Field 'ssl_cipher' doesn't have a default value
|
||||
Warning 1364 Field 'x509_issuer' doesn't have a default value
|
||||
Warning 1364 Field 'x509_subject' doesn't have a default value
|
||||
Warning 1364 Field 'authentication_string' doesn't have a default value
|
||||
create user mysqltest_A@'%';
|
||||
rename user mysqltest_B@'%' to mysqltest_C@'%';
|
||||
drop user mysqltest_C@'%';
|
||||
@ -355,7 +354,6 @@ Warnings:
|
||||
Warning 1364 Field 'ssl_cipher' doesn't have a default value
|
||||
Warning 1364 Field 'x509_issuer' doesn't have a default value
|
||||
Warning 1364 Field 'x509_subject' doesn't have a default value
|
||||
Warning 1364 Field 'authentication_string' doesn't have a default value
|
||||
INSERT INTO mysql.db (host, db, user, select_priv) VALUES
|
||||
('%','TESTDB','mysqltest_1','Y');
|
||||
FLUSH PRIVILEGES;
|
||||
|
@ -547,4 +547,26 @@ FROM t1 JOIN t2 ON t2.f2 LIKE 'x'
|
||||
HAVING field1 < 7;
|
||||
field1
|
||||
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
|
||||
|
@ -148,3 +148,25 @@ COMMIT;
|
||||
# Connection default
|
||||
DROP TABLE t1, t2;
|
||||
DROP VIEW v1;
|
||||
#
|
||||
# Bug#11815600 [ERROR] INNODB COULD NOT FIND INDEX PRIMARY
|
||||
# KEY NO 0 FOR TABLE IN ERROR LOG
|
||||
#
|
||||
DROP TABLE IF EXISTS t1;
|
||||
# Connection default
|
||||
CREATE TABLE t1 (id INT PRIMARY KEY, value INT) ENGINE = InnoDB;
|
||||
INSERT INTO t1 VALUES (1, 12345);
|
||||
START TRANSACTION;
|
||||
SELECT * FROM t1;
|
||||
id value
|
||||
1 12345
|
||||
# Connection con1
|
||||
SET lock_wait_timeout=1;
|
||||
ALTER TABLE t1 ADD INDEX idx(value);
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
# Connection default
|
||||
SELECT * FROM t1;
|
||||
id value
|
||||
1 12345
|
||||
COMMIT;
|
||||
DROP TABLE t1;
|
||||
|
@ -94,74 +94,6 @@ SET DEBUG_SYNC= 'RESET';
|
||||
# Bug#42230 during add index, cannot do queries on storage engines
|
||||
# that implement add_index
|
||||
#
|
||||
DROP DATABASE IF EXISTS db1;
|
||||
DROP TABLE IF EXISTS t1;
|
||||
# Test 1: Secondary index, should not block reads (original test case).
|
||||
# Connection default
|
||||
CREATE DATABASE db1;
|
||||
CREATE TABLE db1.t1(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, value INT) engine=innodb;
|
||||
INSERT INTO db1.t1(value) VALUES (1), (2);
|
||||
SET DEBUG_SYNC= "alter_table_manage_keys SIGNAL manage WAIT_FOR query";
|
||||
# Sending:
|
||||
ALTER TABLE db1.t1 ADD INDEX(value);
|
||||
# Connection con1
|
||||
SET DEBUG_SYNC= "now WAIT_FOR manage";
|
||||
USE db1;
|
||||
SELECT * FROM t1;
|
||||
id value
|
||||
1 1
|
||||
2 2
|
||||
SET DEBUG_SYNC= "now SIGNAL query";
|
||||
# Connection default
|
||||
# Reaping: ALTER TABLE db1.t1 ADD INDEX(value)
|
||||
DROP DATABASE db1;
|
||||
# Test 2: Primary index (implicit), should block reads.
|
||||
CREATE TABLE t1(a INT NOT NULL, b INT NOT NULL) engine=innodb;
|
||||
SET DEBUG_SYNC= "alter_table_manage_keys SIGNAL manage WAIT_FOR query";
|
||||
# Sending:
|
||||
ALTER TABLE t1 ADD UNIQUE INDEX(a);
|
||||
# Connection con1
|
||||
SET DEBUG_SYNC= "now WAIT_FOR manage";
|
||||
USE test;
|
||||
# Sending:
|
||||
SELECT * FROM t1;
|
||||
# Connection con2
|
||||
# Waiting for SELECT to be blocked by the metadata lock on t1
|
||||
SET DEBUG_SYNC= "now SIGNAL query";
|
||||
# Connection default
|
||||
# Reaping: ALTER TABLE t1 ADD UNIQUE INDEX(a)
|
||||
# Connection con1
|
||||
# Reaping: SELECT * FROM t1
|
||||
a b
|
||||
# Test 3: Primary index (explicit), should block reads.
|
||||
# Connection default
|
||||
ALTER TABLE t1 DROP INDEX a;
|
||||
SET DEBUG_SYNC= "alter_table_manage_keys SIGNAL manage WAIT_FOR query";
|
||||
# Sending:
|
||||
ALTER TABLE t1 ADD PRIMARY KEY (a);
|
||||
# Connection con1
|
||||
SET DEBUG_SYNC= "now WAIT_FOR manage";
|
||||
# Sending:
|
||||
SELECT * FROM t1;
|
||||
# Connection con2
|
||||
# Waiting for SELECT to be blocked by the metadata lock on t1
|
||||
SET DEBUG_SYNC= "now SIGNAL query";
|
||||
# Connection default
|
||||
# Reaping: ALTER TABLE t1 ADD PRIMARY KEY (a)
|
||||
# Connection con1
|
||||
# Reaping: SELECT * FROM t1
|
||||
a b
|
||||
# Test 4: Secondary unique index, should not block reads.
|
||||
# Connection default
|
||||
SET DEBUG_SYNC= "alter_table_manage_keys SIGNAL manage WAIT_FOR query";
|
||||
# Sending:
|
||||
ALTER TABLE t1 ADD UNIQUE (b);
|
||||
# Connection con1
|
||||
SET DEBUG_SYNC= "now WAIT_FOR manage";
|
||||
SELECT * FROM t1;
|
||||
a b
|
||||
SET DEBUG_SYNC= "now SIGNAL query";
|
||||
# Connection default
|
||||
# Reaping: ALTER TABLE t1 ADD UNIQUE (b)
|
||||
SET DEBUG_SYNC= "RESET";
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# DISABLED due to Bug#11815600
|
||||
#
|
||||
|
@ -532,4 +532,20 @@ a
|
||||
0
|
||||
1
|
||||
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
|
||||
|
@ -175,6 +175,35 @@ TABLE_SCHEMA TABLE_NAME
|
||||
mysqltest_lc2 myUC
|
||||
use test;
|
||||
drop database mysqltest_LC2;
|
||||
#
|
||||
# Bug #11758687: 50924: object names not resolved correctly
|
||||
# on lctn2 systems
|
||||
#
|
||||
CREATE DATABASE BUP_XPFM_COMPAT_DB2;
|
||||
CREATE TABLE BUP_XPFM_COMPAT_DB2.TABLE2 (c13 INT) DEFAULT CHARSET latin1;
|
||||
CREATE TABLE BUP_XPFM_COMPAT_DB2.table1 (c13 INT) DEFAULT CHARSET latin1;
|
||||
CREATE TABLE bup_xpfm_compat_db2.table3 (c13 INT) DEFAULT CHARSET latin1;
|
||||
CREATE TRIGGER BUP_XPFM_COMPAT_DB2.trigger1 AFTER INSERT
|
||||
ON BUP_XPFM_COMPAT_DB2.table1 FOR EACH ROW
|
||||
update BUP_XPFM_COMPAT_DB2.table1 set c13=12;
|
||||
|
|
||||
CREATE TRIGGER BUP_XPFM_COMPAT_DB2.TRIGGER2 AFTER INSERT
|
||||
ON BUP_XPFM_COMPAT_DB2.TABLE2 FOR EACH ROW
|
||||
update BUP_XPFM_COMPAT_DB2.table1 set c13=12;
|
||||
|
|
||||
CREATE TRIGGER BUP_XPFM_COMPAT_DB2.TrigGer3 AFTER INSERT
|
||||
ON BUP_XPFM_COMPAT_DB2.TaBle3 FOR EACH ROW
|
||||
update BUP_XPFM_COMPAT_DB2.table1 set c13=12;
|
||||
|
|
||||
SELECT trigger_schema, trigger_name, event_object_table FROM
|
||||
INFORMATION_SCHEMA.TRIGGERS
|
||||
WHERE trigger_schema COLLATE utf8_bin = 'BUP_XPFM_COMPAT_DB2'
|
||||
ORDER BY trigger_schema, trigger_name;
|
||||
trigger_schema trigger_name event_object_table
|
||||
BUP_XPFM_COMPAT_DB2 trigger1 table1
|
||||
BUP_XPFM_COMPAT_DB2 TRIGGER2 TABLE2
|
||||
BUP_XPFM_COMPAT_DB2 TrigGer3 table3
|
||||
DROP DATABASE BUP_XPFM_COMPAT_DB2;
|
||||
# End of 5.1 tests
|
||||
#
|
||||
# Test for bug #44738 "fill_schema_table_from_frm() opens tables without
|
||||
|
@ -126,7 +126,7 @@ renamed
|
||||
1
|
||||
select * from v3 where renamed=1 group by renamed;
|
||||
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
|
||||
def v3 v3 renamed renamed 8 11 0 Y 32896 0 63
|
||||
def v3 v3 renamed renamed 8 12 0 Y 32896 0 63
|
||||
renamed
|
||||
drop table t1;
|
||||
drop view v1,v2,v3;
|
||||
|
@ -10,3 +10,10 @@ mysqld is alive
|
||||
# Displaying the output :
|
||||
mysqld is alive
|
||||
mysqld is alive
|
||||
#
|
||||
# BUG#11766184 - 59234: cmdline clients crash --defaults-extra-file
|
||||
# with no .cnf or .ini extension.
|
||||
#
|
||||
# Creating an empty file 'cnf_file'
|
||||
# Using --defaults-extra-file option with 'cnf_file'.
|
||||
mysqld is alive
|
||||
|
@ -903,3 +903,15 @@ master-bin.000002 # Query # # CREATE DATABASE test1
|
||||
master-bin.000002 # Query # # use `test1`; CREATE TABLE t1(id int)
|
||||
master-bin.000002 # Query # # use `test1`; DROP TABLE `t1` /* generated by server */
|
||||
master-bin.000002 # Query # # DROP DATABASE test1
|
||||
RESET MASTER;
|
||||
USE test;
|
||||
CREATE TABLE t1 (a INT);
|
||||
SET GLOBAL SERVER_ID = 2;
|
||||
DROP TABLE t1;
|
||||
FLUSH LOGS;
|
||||
SHOW TABLES IN test;
|
||||
Tables_in_test
|
||||
t1
|
||||
SHOW TABLES IN test;
|
||||
Tables_in_test
|
||||
SET GLOBAL SERVER_ID = 1;
|
||||
|
@ -109,3 +109,13 @@ count(*)
|
||||
35840
|
||||
drop table t1;
|
||||
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;
|
||||
|
@ -4626,6 +4626,7 @@ DELIMITER ;
|
||||
/*!50003 SET collation_connection = @saved_col_connection */ ;
|
||||
ALTER DATABASE `test-database` CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
|
||||
DROP DATABASE `test-database`;
|
||||
USE test;
|
||||
#
|
||||
# End of 5.1 tests
|
||||
#
|
||||
|
@ -225,3 +225,25 @@ DROP SCHEMA IF EXISTS `mysqlslap`;
|
||||
DROP PROCEDURE IF EXISTS p1;
|
||||
CREATE PROCEDURE p1() SELECT 1;
|
||||
DROP PROCEDURE p1;
|
||||
#
|
||||
# Bug #11765157 - 58090: mysqlslap drops schema specified in
|
||||
# create_schema if auto-generate-sql also set.
|
||||
#
|
||||
# 'bug58090' database should not be present.
|
||||
SHOW DATABASES;
|
||||
Database
|
||||
information_schema
|
||||
mtr
|
||||
mysql
|
||||
performance_schema
|
||||
test
|
||||
# 'bug58090' database should be present.
|
||||
SHOW DATABASES;
|
||||
Database
|
||||
information_schema
|
||||
bug58090
|
||||
mtr
|
||||
mysql
|
||||
performance_schema
|
||||
test
|
||||
DROP DATABASE bug58090;
|
||||
|
@ -1429,6 +1429,7 @@ CALL mtr.add_suppression("Out of sort memory");
|
||||
select * from t1 order by b;
|
||||
ERROR HY001: Out of sort memory, consider increasing server sort buffer size
|
||||
drop table t1;
|
||||
call mtr.add_suppression("Out of sort memory; increase server sort buffer size");
|
||||
#
|
||||
# Bug #39844: Query Crash Mysql Server 5.0.67
|
||||
#
|
||||
|
@ -3,6 +3,7 @@ set @net_buffer_length=@@global.net_buffer_length;
|
||||
set global max_allowed_packet=100;
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect max_allowed_packet value: '100'
|
||||
Warning 1708 The value of 'max_allowed_packet' should be no less than the value of 'net_buffer_length'
|
||||
set global net_buffer_length=100;
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect net_buffer_length value: '100'
|
||||
|
@ -710,95 +710,8 @@ DROP TABLE t1;
|
||||
CREATE TABLE t1 (c TIMESTAMP)
|
||||
PARTITION BY HASH (c) PARTITIONS 4;
|
||||
ERROR HY000: Field 'c' is of a not allowed type for this type of partitioning
|
||||
# Moved to partition_myisam, since it was MyISAM specific
|
||||
# Added test with existing TIMESTAMP partitioning (when it was allowed).
|
||||
CREATE TABLE t1 (a TIMESTAMP)
|
||||
PARTITION BY HASH (UNIX_TIMESTAMP(a));
|
||||
INSERT INTO t1 VALUES ('2000-01-02 03:04:05');
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
2000-01-02 03:04:05
|
||||
FLUSH TABLES;
|
||||
# replacing t1.frm with TO_DAYS(a) which was allowed earlier.
|
||||
# Disable warnings, since the result would differ when running with
|
||||
# --ps-protocol (only for the 'SELECT * FROM t1' statement).
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
2000-01-02 03:04:05
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
/*!50100 PARTITION BY HASH (TO_DAYS(a)) */
|
||||
INSERT INTO t1 VALUES ('2001-02-03 04:05:06');
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
2000-01-02 03:04:05
|
||||
2001-02-03 04:05:06
|
||||
ALTER TABLE t1 ADD PARTITION PARTITIONS 2;
|
||||
Warnings:
|
||||
Warning 1486 Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed
|
||||
ALTER TABLE t1
|
||||
PARTITION BY RANGE (TO_DAYS(a))
|
||||
(PARTITION p0 VALUES LESS THAN (10000),
|
||||
PARTITION p1 VALUES LESS THAN (MAXVALUE));
|
||||
ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
/*!50100 PARTITION BY HASH (TO_DAYS(a))
|
||||
PARTITIONS 3 */
|
||||
CREATE TABLE t2 LIKE t1;
|
||||
SHOW CREATE TABLE t2;
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
/*!50100 PARTITION BY HASH (TO_DAYS(a))
|
||||
PARTITIONS 3 */
|
||||
Warnings:
|
||||
Warning 1486 Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed
|
||||
DROP TABLE t2;
|
||||
CREATE TABLE t2 SELECT * FROM t1;
|
||||
DROP TABLE t2;
|
||||
ALTER TABLE t1 PARTITION BY HASH (UNIX_TIMESTAMP(a));
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
/*!50100 PARTITION BY HASH (UNIX_TIMESTAMP(a)) */
|
||||
ALTER TABLE t1 ADD PARTITION PARTITIONS 2;
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
/*!50100 PARTITION BY HASH (UNIX_TIMESTAMP(a))
|
||||
PARTITIONS 3 */
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
2000-01-02 03:04:05
|
||||
2001-02-03 04:05:06
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Bug#49161: Out of memory; restart server and try again (needed 2 bytes)
|
||||
#
|
||||
CREATE TABLE t1 (a INT) PARTITION BY HASH (a);
|
||||
FLUSH TABLES;
|
||||
CHECK TABLE t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 check Error Failed to read from the .par file
|
||||
test.t1 check Error Incorrect information in file: './test/t1.frm'
|
||||
test.t1 check error Corrupt
|
||||
SELECT * FROM t1;
|
||||
ERROR HY000: Failed to read from the .par file
|
||||
# Note that it is currently impossible to drop a partitioned table
|
||||
# without the .par file
|
||||
DROP TABLE t1;
|
||||
ERROR 42S02: Unknown table 't1'
|
||||
#
|
||||
# Bug#49477: Assertion `0' failed in ha_partition.cc:5530
|
||||
# with temporary table and partitions
|
||||
@ -831,10 +744,10 @@ Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`id` int(11) DEFAULT NULL,
|
||||
`purchased` date DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
) ENGINE=<curr_engine> DEFAULT CHARSET=latin1
|
||||
/*!50100 PARTITION BY RANGE (YEAR(purchased))
|
||||
SUBPARTITION BY HASH (TO_DAYS(purchased))
|
||||
(PARTITION p0 VALUES LESS THAN MAXVALUE ENGINE = MyISAM) */
|
||||
(PARTITION p0 VALUES LESS THAN MAXVALUE ENGINE = <curr_engine>) */
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (id INT, purchased DATE)
|
||||
PARTITION BY RANGE(YEAR(purchased))
|
||||
@ -852,12 +765,12 @@ Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`id` int(11) DEFAULT NULL,
|
||||
`purchased` date DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
) ENGINE=<curr_engine> DEFAULT CHARSET=latin1
|
||||
/*!50100 PARTITION BY RANGE (YEAR(purchased))
|
||||
SUBPARTITION BY HASH (TO_DAYS(purchased))
|
||||
(PARTITION p0 VALUES LESS THAN MAXVALUE
|
||||
(SUBPARTITION sp0 ENGINE = MyISAM,
|
||||
SUBPARTITION sp1 ENGINE = MyISAM)) */
|
||||
(SUBPARTITION sp0 ENGINE = <curr_engine>,
|
||||
SUBPARTITION sp1 ENGINE = <curr_engine>)) */
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (id INT, purchased DATE)
|
||||
PARTITION BY RANGE(YEAR(purchased))
|
||||
@ -872,53 +785,11 @@ Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`id` int(11) DEFAULT NULL,
|
||||
`purchased` date DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
) ENGINE=<curr_engine> DEFAULT CHARSET=latin1
|
||||
/*!50100 PARTITION BY RANGE (YEAR(purchased))
|
||||
(PARTITION p0 VALUES LESS THAN MAXVALUE ENGINE = MyISAM) */
|
||||
(PARTITION p0 VALUES LESS THAN MAXVALUE ENGINE = <curr_engine>) */
|
||||
DROP TABLE t1;
|
||||
SET @@sql_mode= @org_mode;
|
||||
#
|
||||
# Bug#50392: insert_id is not reset for partitioned tables
|
||||
# auto_increment on duplicate entry
|
||||
CREATE TABLE t1 (a INT AUTO_INCREMENT PRIMARY KEY);
|
||||
SET INSERT_ID= 13;
|
||||
INSERT INTO t1 VALUES (NULL);
|
||||
SET INSERT_ID= 12;
|
||||
INSERT INTO t1 VALUES (NULL), (NULL), (NULL);
|
||||
ERROR 23000: Duplicate entry '13' for key 'PRIMARY'
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` int(11) NOT NULL AUTO_INCREMENT,
|
||||
PRIMARY KEY (`a`)
|
||||
) ENGINE=MyISAM AUTO_INCREMENT=14 DEFAULT CHARSET=latin1
|
||||
INSERT INTO t1 VALUES (NULL);
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
12
|
||||
13
|
||||
14
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a INT AUTO_INCREMENT PRIMARY KEY) PARTITION BY KEY(a);
|
||||
SET INSERT_ID= 13;
|
||||
INSERT INTO t1 VALUES (NULL);
|
||||
SET INSERT_ID= 12;
|
||||
INSERT INTO t1 VALUES (NULL), (NULL), (NULL);
|
||||
ERROR 23000: Duplicate entry '13' for key 'PRIMARY'
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` int(11) NOT NULL AUTO_INCREMENT,
|
||||
PRIMARY KEY (`a`)
|
||||
) ENGINE=MyISAM AUTO_INCREMENT=14 DEFAULT CHARSET=latin1
|
||||
/*!50100 PARTITION BY KEY (a) */
|
||||
INSERT INTO t1 VALUES (NULL);
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
12
|
||||
13
|
||||
14
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a INTEGER NOT NULL, PRIMARY KEY (a));
|
||||
INSERT INTO t1 VALUES (1),(1);
|
||||
ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
|
||||
@ -928,19 +799,6 @@ PARTITION BY KEY (a) PARTITIONS 2;
|
||||
INSERT INTO t1 VALUES (1),(1);
|
||||
ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a INT)
|
||||
PARTITION BY HASH (a)
|
||||
( PARTITION p0 ENGINE=MyISAM,
|
||||
PARTITION p1);
|
||||
ERROR HY000: The mix of handlers in the partitions is not allowed in this version of MySQL
|
||||
CREATE TABLE t1 (a INT)
|
||||
PARTITION BY LIST (a)
|
||||
SUBPARTITION BY HASH (a)
|
||||
( PARTITION p0 VALUES IN (0)
|
||||
( SUBPARTITION s0, SUBPARTITION s1 ENGINE=MyISAM, SUBPARTITION s2),
|
||||
PARTITION p1 VALUES IN (1)
|
||||
( SUBPARTITION s3 ENGINE=MyISAM, SUBPARTITION s4, SUBPARTITION s5 ENGINE=MyISAM));
|
||||
ERROR HY000: The mix of handlers in the partitions is not allowed in this version of MySQL
|
||||
CREATE TABLE t1 (
|
||||
a int
|
||||
)
|
||||
|
250
mysql-test/r/partition_myisam.result
Normal file
250
mysql-test/r/partition_myisam.result
Normal file
@ -0,0 +1,250 @@
|
||||
DROP TABLE IF EXISTS t1, t2;
|
||||
#
|
||||
# Bug#50036: Inconsistent errors when using TIMESTAMP
|
||||
# columns/expressions
|
||||
# Added test with existing TIMESTAMP partitioning (when it was allowed).
|
||||
CREATE TABLE t1 (a TIMESTAMP)
|
||||
ENGINE = MyISAM
|
||||
PARTITION BY HASH (UNIX_TIMESTAMP(a));
|
||||
INSERT INTO t1 VALUES ('2000-01-02 03:04:05');
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
2000-01-02 03:04:05
|
||||
FLUSH TABLES;
|
||||
# replacing t1.frm with TO_DAYS(a) which was allowed earlier.
|
||||
# Disable warnings, since the result would differ when running with
|
||||
# --ps-protocol (only for the 'SELECT * FROM t1' statement).
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
2000-01-02 03:04:05
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
) ENGINE=<curr_engine> DEFAULT CHARSET=latin1
|
||||
/*!50100 PARTITION BY HASH (TO_DAYS(a)) */
|
||||
INSERT INTO t1 VALUES ('2001-02-03 04:05:06');
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
2000-01-02 03:04:05
|
||||
2001-02-03 04:05:06
|
||||
ALTER TABLE t1 ADD PARTITION PARTITIONS 2;
|
||||
Warnings:
|
||||
Warning 1486 Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed
|
||||
ALTER TABLE t1
|
||||
PARTITION BY RANGE (TO_DAYS(a))
|
||||
(PARTITION p0 VALUES LESS THAN (10000),
|
||||
PARTITION p1 VALUES LESS THAN (MAXVALUE));
|
||||
ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
/*!50100 PARTITION BY HASH (TO_DAYS(a))
|
||||
PARTITIONS 3 */
|
||||
CREATE TABLE t2 LIKE t1;
|
||||
SHOW CREATE TABLE t2;
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
/*!50100 PARTITION BY HASH (TO_DAYS(a))
|
||||
PARTITIONS 3 */
|
||||
Warnings:
|
||||
Warning 1486 Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed
|
||||
DROP TABLE t2;
|
||||
CREATE TABLE t2 SELECT * FROM t1;
|
||||
DROP TABLE t2;
|
||||
ALTER TABLE t1 PARTITION BY HASH (UNIX_TIMESTAMP(a));
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
/*!50100 PARTITION BY HASH (UNIX_TIMESTAMP(a)) */
|
||||
ALTER TABLE t1 ADD PARTITION PARTITIONS 2;
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
/*!50100 PARTITION BY HASH (UNIX_TIMESTAMP(a))
|
||||
PARTITIONS 3 */
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
2000-01-02 03:04:05
|
||||
2001-02-03 04:05:06
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Bug#31931: Mix of handlers error message
|
||||
#
|
||||
CREATE TABLE t1 (a INT)
|
||||
PARTITION BY HASH (a)
|
||||
( PARTITION p0 ENGINE=MyISAM,
|
||||
PARTITION p1);
|
||||
ERROR HY000: The mix of handlers in the partitions is not allowed in this version of MySQL
|
||||
CREATE TABLE t1 (a INT)
|
||||
PARTITION BY LIST (a)
|
||||
SUBPARTITION BY HASH (a)
|
||||
( PARTITION p0 VALUES IN (0)
|
||||
( SUBPARTITION s0, SUBPARTITION s1 ENGINE=MyISAM, SUBPARTITION s2),
|
||||
PARTITION p1 VALUES IN (1)
|
||||
( SUBPARTITION s3 ENGINE=MyISAM, SUBPARTITION s4, SUBPARTITION s5 ENGINE=MyISAM));
|
||||
ERROR HY000: The mix of handlers in the partitions is not allowed in this version of MySQL
|
||||
#
|
||||
# Bug#49161: Out of memory; restart server and try again (needed 2 bytes)
|
||||
#
|
||||
CREATE TABLE t1 (a INT)
|
||||
ENGINE = MyISAM
|
||||
PARTITION BY HASH (a);
|
||||
FLUSH TABLES;
|
||||
CHECK TABLE t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 check Error Failed to read from the .par file
|
||||
test.t1 check Error Incorrect information in file: './test/t1.frm'
|
||||
test.t1 check error Corrupt
|
||||
SELECT * FROM t1;
|
||||
ERROR HY000: Failed to read from the .par file
|
||||
# Note that it is currently impossible to drop a partitioned table
|
||||
# without the .par file
|
||||
DROP TABLE t1;
|
||||
ERROR 42S02: Unknown table 't1'
|
||||
#
|
||||
# Bug#50392: insert_id is not reset for partitioned tables
|
||||
# auto_increment on duplicate entry
|
||||
CREATE TABLE t1 (a INT AUTO_INCREMENT PRIMARY KEY)
|
||||
ENGINE = MyISAM;
|
||||
SET INSERT_ID= 13;
|
||||
INSERT INTO t1 VALUES (NULL);
|
||||
SET INSERT_ID= 12;
|
||||
# For transactional engines, 12 will not be inserted, since the failing
|
||||
# statement is rolled back.
|
||||
INSERT INTO t1 VALUES (NULL), (NULL), (NULL);
|
||||
ERROR 23000: Duplicate entry '13' for key 'PRIMARY'
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` int(11) NOT NULL AUTO_INCREMENT,
|
||||
PRIMARY KEY (`a`)
|
||||
) ENGINE=MyISAM AUTO_INCREMENT=14 DEFAULT CHARSET=latin1
|
||||
INSERT INTO t1 VALUES (NULL);
|
||||
# NOTE: 12 exists only in non transactional engines!
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
12
|
||||
13
|
||||
14
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a INT AUTO_INCREMENT PRIMARY KEY)
|
||||
ENGINE = MyISAM
|
||||
PARTITION BY KEY(a);
|
||||
SET INSERT_ID= 13;
|
||||
INSERT INTO t1 VALUES (NULL);
|
||||
SET INSERT_ID= 12;
|
||||
INSERT INTO t1 VALUES (NULL), (NULL), (NULL);
|
||||
ERROR 23000: Duplicate entry '13' for key 'PRIMARY'
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` int(11) NOT NULL AUTO_INCREMENT,
|
||||
PRIMARY KEY (`a`)
|
||||
) ENGINE=MyISAM AUTO_INCREMENT=14 DEFAULT CHARSET=latin1
|
||||
/*!50100 PARTITION BY KEY (a) */
|
||||
INSERT INTO t1 VALUES (NULL);
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
12
|
||||
13
|
||||
14
|
||||
DROP TABLE t1;
|
||||
# Bug#30102 test
|
||||
CREATE TABLE t1 (a INT)
|
||||
ENGINE = MyISAM
|
||||
PARTITION BY RANGE (a)
|
||||
(PARTITION p0 VALUES LESS THAN (6),
|
||||
PARTITION `p1....................` VALUES LESS THAN (9),
|
||||
PARTITION p2 VALUES LESS THAN MAXVALUE);
|
||||
# List of files in database `test`, all original t1-files here
|
||||
t1#P#p0.MYD
|
||||
t1#P#p0.MYI
|
||||
t1#P#p1@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e.MYD
|
||||
t1#P#p1@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e.MYI
|
||||
t1#P#p2.MYD
|
||||
t1#P#p2.MYI
|
||||
t1.frm
|
||||
t1.par
|
||||
INSERT INTO t1 VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
|
||||
# Renaming to a file name where the first partition is 250 chars
|
||||
# and the second partition is 350 chars
|
||||
RENAME TABLE t1 TO `t2_new..............................................end`;
|
||||
Got one of the listed errors
|
||||
# List of files in database `test`, should not be any t2-files here
|
||||
# List of files in database `test`, should be all t1-files here
|
||||
t1#P#p0.MYD
|
||||
t1#P#p0.MYI
|
||||
t1#P#p1@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e.MYD
|
||||
t1#P#p1@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e.MYI
|
||||
t1#P#p2.MYD
|
||||
t1#P#p2.MYI
|
||||
t1.frm
|
||||
t1.par
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
1
|
||||
10
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
# List of files in database `test`, should be all t1-files here
|
||||
t1#P#p0.MYD
|
||||
t1#P#p0.MYI
|
||||
t1#P#p1@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e.MYD
|
||||
t1#P#p1@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e.MYI
|
||||
t1#P#p2.MYD
|
||||
t1#P#p2.MYI
|
||||
t1.frm
|
||||
t1.par
|
||||
# Renaming to a file name where the first partition is 156 chars
|
||||
# and the second partition is 256 chars
|
||||
RENAME TABLE t1 TO `t2_............................_end`;
|
||||
Got one of the listed errors
|
||||
# List of files in database `test`, should not be any t2-files here
|
||||
# List of files in database `test`, should be all t1-files here
|
||||
t1#P#p0.MYD
|
||||
t1#P#p0.MYI
|
||||
t1#P#p1@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e.MYD
|
||||
t1#P#p1@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e.MYI
|
||||
t1#P#p2.MYD
|
||||
t1#P#p2.MYI
|
||||
t1.frm
|
||||
t1.par
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
1
|
||||
10
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
DROP TABLE t1;
|
||||
# Should not be any files left here
|
||||
# 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;
|
@ -1,81 +0,0 @@
|
||||
DROP TABLE IF EXISTS t1, t2;
|
||||
# Bug#30102 test
|
||||
CREATE TABLE t1 (a INT)
|
||||
PARTITION BY RANGE (a)
|
||||
(PARTITION p0 VALUES LESS THAN (6),
|
||||
PARTITION `p1....................` VALUES LESS THAN (9),
|
||||
PARTITION p2 VALUES LESS THAN MAXVALUE);
|
||||
# List of files in database `test`, all original t1-files here
|
||||
t1#P#p0.MYD
|
||||
t1#P#p0.MYI
|
||||
t1#P#p1@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e.MYD
|
||||
t1#P#p1@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e.MYI
|
||||
t1#P#p2.MYD
|
||||
t1#P#p2.MYI
|
||||
t1.frm
|
||||
t1.par
|
||||
INSERT INTO t1 VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
|
||||
# Renaming to a file name where the first partition is 250 chars
|
||||
# and the second partition is 350 chars
|
||||
RENAME TABLE t1 TO `t2_new..............................................end`;
|
||||
Got one of the listed errors
|
||||
# List of files in database `test`, should not be any t2-files here
|
||||
# List of files in database `test`, should be all t1-files here
|
||||
t1#P#p0.MYD
|
||||
t1#P#p0.MYI
|
||||
t1#P#p1@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e.MYD
|
||||
t1#P#p1@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e.MYI
|
||||
t1#P#p2.MYD
|
||||
t1#P#p2.MYI
|
||||
t1.frm
|
||||
t1.par
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
1
|
||||
10
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
# List of files in database `test`, should be all t1-files here
|
||||
t1#P#p0.MYD
|
||||
t1#P#p0.MYI
|
||||
t1#P#p1@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e.MYD
|
||||
t1#P#p1@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e.MYI
|
||||
t1#P#p2.MYD
|
||||
t1#P#p2.MYI
|
||||
t1.frm
|
||||
t1.par
|
||||
# Renaming to a file name where the first partition is 156 chars
|
||||
# and the second partition is 256 chars
|
||||
RENAME TABLE t1 TO `t2_............................_end`;
|
||||
Got one of the listed errors
|
||||
# List of files in database `test`, should not be any t2-files here
|
||||
# List of files in database `test`, should be all t1-files here
|
||||
t1#P#p0.MYD
|
||||
t1#P#p0.MYI
|
||||
t1#P#p1@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e.MYD
|
||||
t1#P#p1@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e@002e.MYI
|
||||
t1#P#p2.MYD
|
||||
t1#P#p2.MYI
|
||||
t1.frm
|
||||
t1.par
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
1
|
||||
10
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
DROP TABLE t1;
|
||||
# Should not be any files left here
|
||||
# End of bug#30102 test.
|
@ -6,11 +6,12 @@ DROP DATABASE IF EXISTS mysqltest2;
|
||||
CREATE USER mysqltest_1@localhost;
|
||||
CREATE DATABASE mysqltest2;
|
||||
USE mysqltest2;
|
||||
CREATE TABLE t1 (a INT);
|
||||
CREATE TABLE t1 (a INT) ENGINE = MyISAM;
|
||||
INSERT INTO t1 VALUES (0);
|
||||
# user mysqltest_1:
|
||||
USE test;
|
||||
CREATE TABLE t1 (a INT)
|
||||
ENGINE = MyISAM
|
||||
PARTITION BY LIST (a) (
|
||||
PARTITION p0 VALUES IN (0)
|
||||
DATA DIRECTORY 'MYSQLTEST_VARDIR/tmp'
|
||||
@ -47,6 +48,7 @@ DROP DATABASE mysqltest2;
|
||||
CREATE DATABASE mysqltest2;
|
||||
USE mysqltest2;
|
||||
CREATE TABLE t1 (a INT)
|
||||
ENGINE = MyISAM
|
||||
PARTITION BY LIST (a) (
|
||||
PARTITION p0 VALUES IN (0)
|
||||
DATA DIRECTORY 'MYSQLTEST_VARDIR/tmp'
|
||||
@ -58,6 +60,7 @@ DATA DIRECTORY 'MYSQLTEST_VARDIR/tmp'
|
||||
# user mysqltest_1:
|
||||
USE test;
|
||||
CREATE TABLE t1 (a INT)
|
||||
ENGINE = MyISAM
|
||||
PARTITION BY LIST (a) (
|
||||
PARTITION p0 VALUES IN (0)
|
||||
DATA DIRECTORY 'MYSQLTEST_VARDIR/tmp'
|
||||
@ -68,6 +71,7 @@ DATA DIRECTORY 'MYSQLTEST_VARDIR/tmp'
|
||||
);
|
||||
Got one of the listed errors
|
||||
CREATE TABLE t1 (a INT)
|
||||
ENGINE = MyISAM
|
||||
PARTITION BY LIST (a) (
|
||||
PARTITION p0 VALUES IN (0)
|
||||
DATA DIRECTORY 'MYSQLTEST_VARDIR/tmp'
|
||||
@ -82,6 +86,7 @@ DROP DATABASE mysqltest2;
|
||||
USE test;
|
||||
DROP USER mysqltest_1@localhost;
|
||||
create table t2 (i int )
|
||||
ENGINE = MyISAM
|
||||
partition by range (i)
|
||||
(
|
||||
partition p01 values less than (1000)
|
||||
@ -94,6 +99,7 @@ select @@sql_mode;
|
||||
@@sql_mode
|
||||
NO_DIR_IN_CREATE
|
||||
create table t1 (i int )
|
||||
ENGINE = MyISAM
|
||||
partition by range (i)
|
||||
(
|
||||
partition p01 values less than (1000)
|
||||
@ -113,10 +119,12 @@ t2 CREATE TABLE `t2` (
|
||||
DROP TABLE t1, t2;
|
||||
set @@sql_mode=@org_mode;
|
||||
create table t1 (a int)
|
||||
ENGINE = MyISAM
|
||||
partition by key (a)
|
||||
(partition p0 DATA DIRECTORY 'part-data' INDEX DIRECTORY 'part-data');
|
||||
Got one of the listed errors
|
||||
create table t1 (a int)
|
||||
ENGINE = MyISAM
|
||||
partition by key (a)
|
||||
(partition p0,
|
||||
partition p1 DATA DIRECTORY 'part-data' INDEX DIRECTORY 'part-data');
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user