From 8a8f6be17a583490625f3acce630c60be7adbb81 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Thu, 11 Apr 2002 15:51:01 +0300 Subject: [PATCH 01/17] os0file.h: Make sure Posix aio is never even tried to use --- innobase/include/os0file.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/innobase/include/os0file.h b/innobase/include/os0file.h index 67d76814936..3dba8ba3158 100644 --- a/innobase/include/os0file.h +++ b/innobase/include/os0file.h @@ -25,12 +25,6 @@ extern ibool os_has_said_disk_full; #define UNIV_NON_BUFFERED_IO -#else - -#if defined(HAVE_AIO_H) && defined(HAVE_LIBRT) -#define POSIX_ASYNC_IO -#endif - #endif #ifdef __WIN__ From 3f2c9e408f30b52e04c8ce20cc12d424b1479782 Mon Sep 17 00:00:00 2001 From: "monty@tik.mysql.fi" <> Date: Thu, 11 Apr 2002 21:20:39 +0300 Subject: [PATCH 02/17] Changlog --- Docs/manual.texi | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/Docs/manual.texi b/Docs/manual.texi index f7cee137bc6..5b4fb2932f7 100644 --- a/Docs/manual.texi +++ b/Docs/manual.texi @@ -46768,11 +46768,6 @@ Our TODO section contains what we plan to have in 4.0. @xref{TODO MySQL 4.0}. @itemize @bullet @item -Fixed @code{SIGINT} and @code{SIGQUIT} problems in mysql.cc -@item -Fixed bug in convert.cc, which is caused by having a wrong net_store_length -linked in CONVERT::store method -@item Multi-table @code{DELETE}. @item Don't support old client protocols prior to MySQL 3.21 any more. @@ -46859,6 +46854,7 @@ users use this code as the rest of the code and because of this we are not yet 100% confident in this code. @menu +* News-3.23.51:: * News-3.23.50:: Changes in release 3.23.50 * News-3.23.49:: Changes in release 3.23.49 * News-3.23.48:: Changes in release 3.23.48 @@ -46913,7 +46909,17 @@ not yet 100% confident in this code. * News-3.23.0:: Changes in release 3.23.0 @end menu -@node News-3.23.50, News-3.23.49, News-3.23.x, News-3.23.x +@node News-3.23.51, News-3.23.50, News-3.23.x, News-3.23.x +@appendixsubsec Changes in release 3.23.51 + +@itemize @bullet +@item +Fixed @code{SIGINT} and @code{SIGQUIT} problems in @code{mysql}. +@item +Fixed bug in character table converts when used with big ( > 64K) strings. +@end itemize + +@node News-3.23.50, News-3.23.49, News-3.23.51, News-3.23.x @appendixsubsec Changes in release 3.23.50 @itemize @bullet From 0541b54fb7527396be6139ef24fd085756cf5345 Mon Sep 17 00:00:00 2001 From: "Sinisa@sinisa.nasamreza.org" <> Date: Sat, 13 Apr 2002 13:44:08 +0300 Subject: [PATCH 03/17] libwrap bug fix for Linux only --- BitKeeper/etc/logging_ok | 1 + sql/mysqld.cc | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index bd35c33892e..ebbe3a30696 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -16,3 +16,4 @@ jani@hynda.mysql.fi miguel@hegel.local arjen@fred.bitbike.com sinisa@rhols221.adsl.netsonic.fi +Sinisa@sinisa.nasamreza.org diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 1d108b3f4c2..fa5f6ae395e 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2415,6 +2415,7 @@ pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused))) struct request_info req; signal(SIGCHLD, SIG_DFL); request_init(&req, RQ_DAEMON, libwrapName, RQ_FILE, new_sock, NULL); +#ifndef __linux__ fromhost(&req); if (!hosts_access(&req)) { @@ -2422,6 +2423,12 @@ pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused))) // which we surely don't want... // clean_exit() - same stupid thing ... syslog(deny_severity, "refused connect from %s", eval_client(&req)); +#else + fromhost(); + if (!hosts_access()) + { + syslog(deny_severity, "refused connect from %s", eval_client()); +#endif if (req.sink) ((void (*)(int))req.sink)(req.fd); From 52613c7e40a27ca93a137a609de59e297a61a1a7 Mon Sep 17 00:00:00 2001 From: "monty@hundin.mysql.fi" <> Date: Sun, 14 Apr 2002 09:00:50 +0300 Subject: [PATCH 04/17] Removed C version of longlong2str when using --enable-assembler --- strings/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/strings/Makefile.am b/strings/Makefile.am index 4c42f1ccb96..a3ae5357597 100644 --- a/strings/Makefile.am +++ b/strings/Makefile.am @@ -22,7 +22,7 @@ pkglib_LIBRARIES = libmystrings.a # Exact one of ASSEMBLER_X if ASSEMBLER_x86 ASRCS = strings-x86.s longlong2str-x86.s -CSRCS = bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c atof.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c strxmov.c bmove_upp.c strappend.c strcont.c strend.c strfill.c strcend.c is_prefix.c strstr.c strinstr.c strmake.c strnmov.c strmov.c longlong2str.c llstr.c ctype.c strnlen.c +CSRCS = bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c atof.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c strxmov.c bmove_upp.c strappend.c strcont.c strend.c strfill.c strcend.c is_prefix.c strstr.c strinstr.c strmake.c strnmov.c strmov.c llstr.c ctype.c strnlen.c else if ASSEMBLER_sparc # These file MUST all be on the same line!! Otherwise automake From c0d9954cc79c51702c582f17ea7891ea77e0ee3a Mon Sep 17 00:00:00 2001 From: "monty@tik.mysql.fi" <> Date: Tue, 16 Apr 2002 16:29:14 +0300 Subject: [PATCH 05/17] Fixed pthread_cond_timedwait() for HPUX and DCE threads Cleanup of LIBWRAP handling --- Docs/manual.texi | 16 ++++++-------- include/my_pthread.h | 7 ++++++ mysys/my_pthread.c | 18 ++++++++++++++-- sql/item_func.cc | 2 +- sql/mysqld.cc | 51 +++++++++++++++++++++++++------------------- sql/sql_parse.cc | 2 +- 6 files changed, 61 insertions(+), 35 deletions(-) diff --git a/Docs/manual.texi b/Docs/manual.texi index 5b4fb2932f7..4d12a2689fe 100644 --- a/Docs/manual.texi +++ b/Docs/manual.texi @@ -46854,7 +46854,6 @@ users use this code as the rest of the code and because of this we are not yet 100% confident in this code. @menu -* News-3.23.51:: * News-3.23.50:: Changes in release 3.23.50 * News-3.23.49:: Changes in release 3.23.49 * News-3.23.48:: Changes in release 3.23.48 @@ -46909,20 +46908,19 @@ not yet 100% confident in this code. * News-3.23.0:: Changes in release 3.23.0 @end menu -@node News-3.23.51, News-3.23.50, News-3.23.x, News-3.23.x -@appendixsubsec Changes in release 3.23.51 +@node News-3.23.50, News-3.23.49, News-3.23.x, News-3.23.x +@appendixsubsec Changes in release 3.23.50 @itemize @bullet @item +Fixed timeout for @code{GET_LOCK()} on HPUX with DCE threads. +@item +Fixed memory allocation bug in the glibc library used to build Linux +binaries, which caused mysqld to die in 'free()'. +@item Fixed @code{SIGINT} and @code{SIGQUIT} problems in @code{mysql}. @item Fixed bug in character table converts when used with big ( > 64K) strings. -@end itemize - -@node News-3.23.50, News-3.23.49, News-3.23.51, News-3.23.x -@appendixsubsec Changes in release 3.23.50 - -@itemize @bullet @item @code{InnoDB} now retains foreign key constraints through @code{ALTER TABLE} and @code{CREATE/DROP INDEX}. diff --git a/include/my_pthread.h b/include/my_pthread.h index cd72bcced83..30e9ea95e02 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -349,6 +349,13 @@ extern void my_pthread_attr_setprio(pthread_attr_t *attr, int priority); #undef HAVE_GETHOSTBYADDR_R /* No definition */ #endif +#if defined(HAVE_DEC_THREADS) +extern int my_pthread_cond_timedwait(pthread_cond_t *cond, + pthread_mutex_t *mutex, + struct timespec *abstime); +#define pthread_cond_timedwait(A,B,C) my_pthread_cond_timedwait((A),(B),(C)) +#endif + #if defined(OS2) #define my_pthread_getspecific(T,A) ((T) &(A)) #define pthread_setspecific(A,B) win_pthread_setspecific(&(A),(B),sizeof(A)) diff --git a/mysys/my_pthread.c b/mysys/my_pthread.c index 8bdbc0f7fd8..8c6b366e9b1 100644 --- a/mysys/my_pthread.c +++ b/mysys/my_pthread.c @@ -410,9 +410,23 @@ int my_pthread_cond_init(pthread_cond_t *mp, const pthread_condattr_t *attr) #endif +/* Change functions on HP to work according to POSIX */ + +#ifdef HAVE_DEC_THREADS +#undef pthread_cond_timedwait + +int my_pthread_cond_timedwait(pthread_cond_t *cond, + pthread_mutex_t *mutex, + struct timespec *abstime) +{ + int error=pthread_cond_timedwait(cond,mutex,abstime); + return error == EAGAIN ? ETIMEDOUT : error; +} +#endif /* HAVE_DEC_THREADS */ + /* -** Emulate SOLARIS style calls, not because it's better, but just to make the -** usage of getbostbyname_r simpler. + Emulate SOLARIS style calls, not because it's better, but just to make the + usage of getbostbyname_r simpler. */ #if !defined(my_gethostbyname_r) && defined(HAVE_GETHOSTBYNAME_R) diff --git a/sql/item_func.cc b/sql/item_func.cc index 023b79b3ff7..2e54aa56b4b 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1514,7 +1514,7 @@ longlong Item_func_get_lock::val_int() while (!thd->killed && (error=pthread_cond_timedwait(&ull->cond,&LOCK_user_locks,&abstime)) - != ETIME && error != ETIMEDOUT && ull->locked) ; + != ETIME && error != ETIMEDOUT && error != EINVAL && ull->locked) ; if (thd->killed) error=EINTR; // Return NULL if (ull->locked) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index fa5f6ae395e..16eace54978 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -89,6 +89,16 @@ extern "C" { // Because of SCO 3.2V4.2 #endif /* NEED_SYS_SYSLOG_H */ int allow_severity = LOG_INFO; int deny_severity = LOG_WARNING; + +#ifdef __linux__ +#define my_fromhost(A) fromhost() +#define my_hosts_access(A) hosts_access() +#define my_eval_client(A) eval_client() +#else +#define my_fromhost(A) fromhost(A) +#define my_hosts_access(A) hosts_access(A) +#define my_eval_client(A) eval_client(A) +#endif #endif /* HAVE_LIBWRAP */ #ifdef HAVE_SYS_MMAN_H @@ -2258,7 +2268,6 @@ static void create_new_thread(THD *thd) if (cached_thread_count > wake_thread) { start_cached_thread(thd); - (void) pthread_mutex_unlock(&LOCK_thread_count); } else { @@ -2285,9 +2294,9 @@ static void create_new_thread(THD *thd) (void) pthread_mutex_unlock(&LOCK_thread_count); DBUG_VOID_RETURN; } - - (void) pthread_mutex_unlock(&LOCK_thread_count); } + (void) pthread_mutex_unlock(&LOCK_thread_count); + } DBUG_PRINT("info",("Thread created")); DBUG_VOID_RETURN; @@ -2415,29 +2424,27 @@ pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused))) struct request_info req; signal(SIGCHLD, SIG_DFL); request_init(&req, RQ_DAEMON, libwrapName, RQ_FILE, new_sock, NULL); -#ifndef __linux__ - fromhost(&req); - if (!hosts_access(&req)) + my_fromhost(&req); + if (!my_hosts_access(&req)) { - // This may be stupid but refuse() includes an exit(0) - // which we surely don't want... - // clean_exit() - same stupid thing ... - syslog(deny_severity, "refused connect from %s", eval_client(&req)); -#else - fromhost(); - if (!hosts_access()) - { - syslog(deny_severity, "refused connect from %s", eval_client()); -#endif + /* + This may be stupid but refuse() includes an exit(0) + which we surely don't want... + clean_exit() - same stupid thing ... + */ + syslog(deny_severity, "refused connect from %s", + my_eval_client(&req)); + + /* + C++ sucks (the gibberish in front just translates the supplied + sink function pointer in the req structure from a void (*sink)(); + to a void(*sink)(int) if you omit the cast, the C++ compiler + will cry... + */ if (req.sink) ((void (*)(int))req.sink)(req.fd); - // C++ sucks (the gibberish in front just translates the supplied - // sink function pointer in the req structure from a void (*sink)(); - // to a void(*sink)(int) if you omit the cast, the C++ compiler - // will cry... - - (void) shutdown(new_sock,2); // This looks fine to me... + (void) shutdown(new_sock,2); (void) closesocket(new_sock); continue; } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index fa4a4fd4f3b..4f9140cc3f2 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -530,7 +530,7 @@ pthread_handler_decl(handle_one_connection,arg) if ((error=check_connections(thd))) { // Wrong permissions if (error > 0) - net_printf(net,error,thd->host ? thd->host : thd->ip); + net_printf(net,error,thd->host ? thd->host : (thd->ip ? thd->ip : "")); #ifdef __NT__ if (vio_type(net->vio) == VIO_TYPE_NAMEDPIPE) sleep(1); /* must wait after eof() */ From 9fc82002490184fc5664af7cee3651c05b2f029f Mon Sep 17 00:00:00 2001 From: "Sinisa@sinisa.nasamreza.org" <> Date: Tue, 16 Apr 2002 21:19:00 +0300 Subject: [PATCH 06/17] Small fix for HP-UX 10.20 with DCE threads Also --with-libwrap is tested on Linux just fine. --- configure.in | 1 + include/my_pthread.h | 2 +- mysys/my_pthread.c | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/configure.in b/configure.in index 5e6efe8ea5d..8f31e58e397 100644 --- a/configure.in +++ b/configure.in @@ -853,6 +853,7 @@ case $SYSTEM_TYPE in echo "Using --with-named-thread=-lpthread" with_named_thread="-lcma" fi + AC_DEFINE(HAVE_BROKEN_PTHREAD_COND_TIMEDWAIT) ;; *hpux11.*) echo "Enabling pread/pwrite workaround for hpux 11" diff --git a/include/my_pthread.h b/include/my_pthread.h index 30e9ea95e02..4c90882e76b 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -349,7 +349,7 @@ extern void my_pthread_attr_setprio(pthread_attr_t *attr, int priority); #undef HAVE_GETHOSTBYADDR_R /* No definition */ #endif -#if defined(HAVE_DEC_THREADS) +#if defined(HAVE_BROKEN_PTHREAD_COND_TIMEDWAIT) extern int my_pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, struct timespec *abstime); diff --git a/mysys/my_pthread.c b/mysys/my_pthread.c index 8c6b366e9b1..72409b6aa86 100644 --- a/mysys/my_pthread.c +++ b/mysys/my_pthread.c @@ -412,7 +412,7 @@ int my_pthread_cond_init(pthread_cond_t *mp, const pthread_condattr_t *attr) /* Change functions on HP to work according to POSIX */ -#ifdef HAVE_DEC_THREADS +#ifdef HAVE_BROKEN_PTHREAD_COND_TIMEDWAIT #undef pthread_cond_timedwait int my_pthread_cond_timedwait(pthread_cond_t *cond, @@ -422,7 +422,7 @@ int my_pthread_cond_timedwait(pthread_cond_t *cond, int error=pthread_cond_timedwait(cond,mutex,abstime); return error == EAGAIN ? ETIMEDOUT : error; } -#endif /* HAVE_DEC_THREADS */ +#endif /* HAVE_BROKEN_PTHREAD_COND_TIMEDWAIT */ /* Emulate SOLARIS style calls, not because it's better, but just to make the From 7258bf935795183a6e16ef11545c964cae1d79c6 Mon Sep 17 00:00:00 2001 From: "monty@tik.mysql.fi" <> Date: Wed, 17 Apr 2002 08:59:48 +0300 Subject: [PATCH 07/17] Cleanup of pthread_cond_timedwait for HPUX --- configure.in | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/configure.in b/configure.in index 8f31e58e397..b5c2efcab68 100644 --- a/configure.in +++ b/configure.in @@ -845,9 +845,9 @@ case $SYSTEM_TYPE in CFLAGS="$CFLAGS -DHAVE_BROKEN_GETPASS -DSOLARIS"; ;; *hpux10.20*) - echo "Enabling snprintf workaround for hpux 10.20" - CFLAGS="$CFLAGS -DHAVE_BROKEN_SNPRINTF -DSIGNALS_DONT_BREAK_READ -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHPUX -DSIGNAL_WITH_VIO_CLOSE" - CXXFLAGS="$CXXFLAGS -DHAVE_BROKEN_SNPRINTF -D_INCLUDE_LONGLONG -DSIGNALS_DONT_BREAK_READ -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHPUX -DSIGNAL_WITH_VIO_CLOSE" + echo "Enabling workarounds for hpux 10.20" + CFLAGS="$CFLAGS -DHAVE_BROKEN_SNPRINTF -DSIGNALS_DONT_BREAK_READ -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHPUX -DSIGNAL_WITH_VIO_CLOSE -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT" + CXXFLAGS="$CXXFLAGS -DHAVE_BROKEN_SNPRINTF -D_INCLUDE_LONGLONG -DSIGNALS_DONT_BREAK_READ -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHPUX -DSIGNAL_WITH_VIO_CLOSE -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT" if test "$with_named_thread" = "no" then echo "Using --with-named-thread=-lpthread" @@ -856,9 +856,9 @@ case $SYSTEM_TYPE in AC_DEFINE(HAVE_BROKEN_PTHREAD_COND_TIMEDWAIT) ;; *hpux11.*) - echo "Enabling pread/pwrite workaround for hpux 11" - CFLAGS="$CFLAGS -DHAVE_BROKEN_PREAD -DDONT_USE_FINITE -DHAVE_BROKEN_GETPASS -DNO_FCNTL_NONBLOCK -DDO_NOT_REMOVE_THREAD_WRAPPERS" - CXXFLAGS="$CXXFLAGS -DHAVE_BROKEN_PREAD -DDONT_USE_FINITE -D_INCLUDE_LONGLONG -DNO_FCNTL_NONBLOCK -DDO_NOT_REMOVE_THREAD_WRAPPERS" + echo "Enabling workarounds for hpux 11" + CFLAGS="$CFLAGS -DHAVE_BROKEN_PREAD -DDONT_USE_FINITE -DHAVE_BROKEN_GETPASS -DNO_FCNTL_NONBLOCK -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT" + CXXFLAGS="$CXXFLAGS -DHAVE_BROKEN_PREAD -DDONT_USE_FINITE -D_INCLUDE_LONGLONG -DNO_FCNTL_NONBLOCK -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT" if test "$with_named_thread" = "no" then echo "Using --with-named-thread=-lpthread" From fadcf27995f945d6960809c27cb98a012ca5bb95 Mon Sep 17 00:00:00 2001 From: "monty@hundin.mysql.fi" <> Date: Wed, 17 Apr 2002 09:26:47 +0300 Subject: [PATCH 08/17] Removed wrong configure line from configure.in --- configure.in | 1 - 1 file changed, 1 deletion(-) diff --git a/configure.in b/configure.in index b5c2efcab68..aa9da7d2ca5 100644 --- a/configure.in +++ b/configure.in @@ -853,7 +853,6 @@ case $SYSTEM_TYPE in echo "Using --with-named-thread=-lpthread" with_named_thread="-lcma" fi - AC_DEFINE(HAVE_BROKEN_PTHREAD_COND_TIMEDWAIT) ;; *hpux11.*) echo "Enabling workarounds for hpux 11" From e29bd611f9bd5018e5d067c4c91870471b261713 Mon Sep 17 00:00:00 2001 From: "monty@tik.mysql.fi" <> Date: Wed, 17 Apr 2002 11:45:26 +0300 Subject: [PATCH 09/17] Abort if 'listen()' on TCP/IP fails. --- sql/mysqld.cc | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 16eace54978..ebb7592820b 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -917,21 +917,22 @@ static void server_init(void) IPaddr.sin_addr.s_addr = my_bind_addr; IPaddr.sin_port = (unsigned short) htons((unsigned short) mysql_port); (void) setsockopt(ip_sock,SOL_SOCKET,SO_REUSEADDR,(char*)&arg,sizeof(arg)); - for(;;) + if (bind(ip_sock, my_reinterpret_cast(struct sockaddr *) (&IPaddr), + sizeof(IPaddr)) < 0) { - if (bind(ip_sock, my_reinterpret_cast(struct sockaddr *) (&IPaddr), - sizeof(IPaddr)) >= 0) - break; DBUG_PRINT("error",("Got error: %d from bind",socket_errno)); - sql_perror("Can't start server: Bind on TCP/IP port");/* Had a loop here */ + sql_perror("Can't start server: Bind on TCP/IP port"); sql_print_error("Do you already have another mysqld server running on port: %d ?",mysql_port); unireg_abort(1); } if (listen(ip_sock,(int) back_log) < 0) + { + sql_perror("Can't start server: listen() on TCP/IP port"); sql_print_error("Warning: listen() on TCP/IP failed with error %d", socket_errno); + unireg_abort(1); + } } - if (mysqld_chroot) set_root(mysqld_chroot); From 8da85956dd44282ef38bfff5a51fd962c23f54df Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Thu, 18 Apr 2002 10:40:32 +0300 Subject: [PATCH 10/17] Many files: Implement ON DELETE CASCADE and facilitate switching off of UNIQUE constraints and foreign keys --- innobase/btr/btr0cur.c | 11 +- innobase/dict/dict0crea.c | 3 +- innobase/dict/dict0dict.c | 161 +++++++++++++++----- innobase/dict/dict0load.c | 5 + innobase/dict/dict0mem.c | 4 +- innobase/include/btr0btr.h | 6 + innobase/include/dict0mem.h | 32 ++-- innobase/include/ibuf0ibuf.h | 6 +- innobase/include/ibuf0ibuf.ic | 12 +- innobase/include/os0file.h | 2 + innobase/include/os0sync.h | 5 +- innobase/include/os0sync.ic | 17 +-- innobase/include/row0mysql.h | 21 +++ innobase/include/row0upd.h | 10 ++ innobase/include/sync0sync.h | 9 +- innobase/include/sync0sync.ic | 4 +- innobase/include/trx0sys.h | 2 +- innobase/include/trx0sys.ic | 1 - innobase/include/trx0trx.h | 14 ++ innobase/lock/lock0lock.c | 3 + innobase/pars/pars0opt.c | 3 +- innobase/que/que0que.c | 9 +- innobase/row/row0ins.c | 276 ++++++++++++++++++++++++++++++++-- innobase/row/row0mysql.c | 177 +++++++++++++++++----- innobase/row/row0sel.c | 8 +- innobase/row/row0upd.c | 109 +++++++++----- innobase/srv/srv0srv.c | 20 ++- innobase/sync/sync0sync.c | 6 +- innobase/trx/trx0sys.c | 3 +- innobase/trx/trx0trx.c | 7 +- 30 files changed, 768 insertions(+), 178 deletions(-) diff --git a/innobase/btr/btr0cur.c b/innobase/btr/btr0cur.c index ddcf5e8faf2..daebb8dbbaf 100644 --- a/innobase/btr/btr0cur.c +++ b/innobase/btr/btr0cur.c @@ -228,6 +228,7 @@ btr_cur_search_to_nth_level( ulint insert_planned; ulint buf_mode; ulint estimate; + ulint ignore_sec_unique; ulint root_height; #ifdef BTR_CUR_ADAPT btr_search_t* info; @@ -246,7 +247,9 @@ btr_cur_search_to_nth_level( #endif insert_planned = latch_mode & BTR_INSERT; estimate = latch_mode & BTR_ESTIMATE; - latch_mode = latch_mode & ~(BTR_INSERT | BTR_ESTIMATE); + ignore_sec_unique = latch_mode & BTR_IGNORE_SEC_UNIQUE; + latch_mode = latch_mode & ~(BTR_INSERT | BTR_ESTIMATE + | BTR_IGNORE_SEC_UNIQUE); ut_ad(!insert_planned || (mode == PAGE_CUR_LE)); @@ -343,7 +346,8 @@ btr_cur_search_to_nth_level( rw_latch = latch_mode; - if (insert_planned && ibuf_should_try(index)) { + if (insert_planned && ibuf_should_try(index, + ignore_sec_unique)) { /* Try insert to the insert buffer if the page is not in the buffer pool */ @@ -356,7 +360,6 @@ retry_page_get: buf_mode, IB__FILE__, __LINE__, mtr); - if (page == NULL) { /* This must be a search to perform an insert; try insert to the insert buffer */ @@ -365,7 +368,7 @@ retry_page_get: ut_ad(insert_planned); ut_ad(cursor->thr); - if (ibuf_should_try(index) && + if (ibuf_should_try(index, ignore_sec_unique) && ibuf_insert(tuple, index, space, page_no, cursor->thr)) { /* Insertion to the insert buffer succeeded */ diff --git a/innobase/dict/dict0crea.c b/innobase/dict/dict0crea.c index f15d36251e4..38c09c1011d 100644 --- a/innobase/dict/dict0crea.c +++ b/innobase/dict/dict0crea.c @@ -1201,7 +1201,8 @@ loop: ut_dulint_get_low(id), table->name, foreign->referenced_table_name, - foreign->n_fields); + foreign->n_fields + + (foreign->type << 24)); for (i = 0; i < foreign->n_fields; i++) { diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c index d52483074cd..a6f268c2153 100644 --- a/innobase/dict/dict0dict.c +++ b/innobase/dict/dict0dict.c @@ -1648,7 +1648,7 @@ dict_foreign_find_index( ->col->name; if (ut_strlen(columns[i]) != ut_strlen(col_name) - || 0 != ut_memcmp(columns[i], + || 0 != ut_cmp_in_lower_case(columns[i], col_name, ut_strlen(col_name))) { break; @@ -1853,8 +1853,9 @@ dict_scan_col( ibool* success,/* out: TRUE if success */ dict_table_t* table, /* in: table in which the column is */ dict_col_t** column, /* out: pointer to column if success */ - char** column_name)/* out: pointer to column->name if + char** column_name,/* out: pointer to column->name if success */ + ulint* column_name_len)/* out: column name length */ { dict_col_t* col; char* old_ptr; @@ -1882,20 +1883,28 @@ dict_scan_col( ptr++; } - for (i = 0; i < dict_table_get_n_cols(table); i++) { + *column_name_len = (ulint)(ptr - old_ptr); + + if (table == NULL) { + *success = TRUE; + *column = NULL; + *column_name = old_ptr; + } else { + for (i = 0; i < dict_table_get_n_cols(table); i++) { - col = dict_table_get_nth_col(table, i); + col = dict_table_get_nth_col(table, i); - if (ut_strlen(col->name) == (ulint)(ptr - old_ptr) - && 0 == ut_cmp_in_lower_case(col->name, old_ptr, + if (ut_strlen(col->name) == (ulint)(ptr - old_ptr) + && 0 == ut_cmp_in_lower_case(col->name, old_ptr, (ulint)(ptr - old_ptr))) { - /* Found */ + /* Found */ - *success = TRUE; - *column = col; - *column_name = col->name; + *success = TRUE; + *column = col; + *column_name = col->name; - break; + break; + } } } @@ -1914,14 +1923,18 @@ dict_scan_table_name( /*=================*/ /* out: scanned to */ char* ptr, /* in: scanned to */ - dict_table_t** table, /* out: table object or NULL if error */ - char* name) /* in: foreign key table name */ + dict_table_t** table, /* out: table object or NULL */ + char* name, /* in: foreign key table name */ + ibool* success,/* out: TRUE if ok name found */ + char* second_table_name)/* in/out: buffer where to store + the referenced table name; must be at least + 2500 bytes */ { char* dot_ptr = NULL; char* old_ptr; ulint i; - char second_table_name[10000]; + *success = FALSE; *table = NULL; while (isspace(*ptr)) { @@ -1947,7 +1960,7 @@ dict_scan_table_name( ptr++; } - if (ptr - old_ptr > 9000) { + if (ptr - old_ptr > 2000) { return(old_ptr); } @@ -1978,6 +1991,8 @@ dict_scan_table_name( second_table_name[ptr - old_ptr] = '\0'; } + *success = TRUE; + *table = dict_table_get_low(second_table_name); if (*ptr == '`') { @@ -2043,9 +2058,12 @@ dict_create_foreign_constraints( ibool success; ulint error; ulint i; - dict_col_t* columns[1000]; - char* column_names[1000]; - + ulint j; + dict_col_t* columns[500]; + char* column_names[500]; + ulint column_name_lens[500]; + char referenced_table_name[2500]; + ut_ad(mutex_own(&(dict_sys->mutex))); table = dict_table_get_low(name); @@ -2090,7 +2108,7 @@ loop: /* Scan the columns in the first list */ col_loop1: ptr = dict_scan_col(ptr, &success, table, columns + i, - column_names + i); + column_names + i, column_name_lens + i); if (!success) { return(DB_CANNOT_ADD_CONSTRAINT); } @@ -2141,9 +2159,13 @@ col_loop1: 1 + ut_strlen(columns[i]->name)); } - ptr = dict_scan_table_name(ptr, &referenced_table, name); + ptr = dict_scan_table_name(ptr, &referenced_table, name, + &success, referenced_table_name); - if (!referenced_table) { + /* Note that referenced_table can be NULL if the user has suppressed + checking of foreign key constraints! */ + + if (!success || (!referenced_table && trx->check_foreigns)) { dict_foreign_free(foreign); return(DB_CANNOT_ADD_CONSTRAINT); @@ -2161,7 +2183,7 @@ col_loop1: col_loop2: ptr = dict_scan_col(ptr, &success, referenced_table, columns + i, - column_names + i); + column_names + i, column_name_lens + i); i++; if (!success) { @@ -2183,43 +2205,104 @@ col_loop2: return(DB_CANNOT_ADD_CONSTRAINT); } + ptr = dict_accept(ptr, "ON", &success); + + if (!success) { + + goto try_find_index; + } + + ptr = dict_accept(ptr, "DELETE", &success); + + if (!success) { + + goto try_find_index; + } + + ptr = dict_accept(ptr, "CASCADE", &success); + + if (success) { + + foreign->type = DICT_FOREIGN_ON_DELETE_CASCADE; + + goto try_find_index; + } + + ptr = dict_accept(ptr, "SET", &success); + + if (!success) { + + goto try_find_index; + } + + ptr = dict_accept(ptr, "NULL", &success); + + if (success) { + for (j = 0; j < foreign->n_fields; j++) { + if ((dict_index_get_nth_type( + foreign->foreign_index, j)->prtype) + & DATA_NOT_NULL) { + + /* It is not sensible to define SET NULL + if the column is not allowed to be NULL! */ + + dict_foreign_free(foreign); + return(DB_CANNOT_ADD_CONSTRAINT); + } + } + + foreign->type = DICT_FOREIGN_ON_DELETE_SET_NULL; + + goto try_find_index; + } + +try_find_index: /* Try to find an index which contains the columns as the first fields and in the right order, and the types are the same as in foreign->foreign_index */ - index = dict_foreign_find_index(referenced_table, column_names, i, + if (referenced_table) { + index = dict_foreign_find_index(referenced_table, + column_names, i, foreign->foreign_index); - - if (!index) { - dict_foreign_free(foreign); - return(DB_CANNOT_ADD_CONSTRAINT); + if (!index) { + dict_foreign_free(foreign); + return(DB_CANNOT_ADD_CONSTRAINT); + } + } else { + ut_a(trx->check_foreigns == FALSE); + index = NULL; } foreign->referenced_index = index; foreign->referenced_table = referenced_table; foreign->referenced_table_name = mem_heap_alloc(foreign->heap, - 1 + ut_strlen(referenced_table->name)); + 1 + ut_strlen(referenced_table_name)); - ut_memcpy(foreign->referenced_table_name, referenced_table->name, - 1 + ut_strlen(referenced_table->name)); + ut_memcpy(foreign->referenced_table_name, referenced_table_name, + 1 + ut_strlen(referenced_table_name)); foreign->referenced_col_names = mem_heap_alloc(foreign->heap, i * sizeof(void*)); for (i = 0; i < foreign->n_fields; i++) { foreign->referenced_col_names[i] = mem_heap_alloc(foreign->heap, - 1 + ut_strlen(columns[i]->name)); - ut_memcpy( - foreign->referenced_col_names[i], columns[i]->name, - 1 + ut_strlen(columns[i]->name)); + 1 + column_name_lens[i]); + ut_memcpy(foreign->referenced_col_names[i], column_names[i], + column_name_lens[i]); + (foreign->referenced_col_names[i])[column_name_lens[i]] = '\0'; } /* We found an ok constraint definition: add to the lists */ UT_LIST_ADD_LAST(foreign_list, table->foreign_list, foreign); - UT_LIST_ADD_LAST(referenced_list, referenced_table->referenced_list, + + if (referenced_table) { + UT_LIST_ADD_LAST(referenced_list, + referenced_table->referenced_list, foreign); + } goto loop; } @@ -3034,6 +3117,14 @@ dict_print_info_on_foreign_keys_in_create_format( buf2 += sprintf(buf2, ")"); + if (foreign->type == DICT_FOREIGN_ON_DELETE_CASCADE) { + buf2 += sprintf(buf2, " ON DELETE CASCADE"); + } + + if (foreign->type == DICT_FOREIGN_ON_DELETE_SET_NULL) { + buf2 += sprintf(buf2, " ON DELETE SET NULL"); + } + foreign = UT_LIST_GET_NEXT(foreign_list, foreign); } diff --git a/innobase/dict/dict0load.c b/innobase/dict/dict0load.c index 29c98db4a53..4917359c748 100644 --- a/innobase/dict/dict0load.c +++ b/innobase/dict/dict0load.c @@ -946,6 +946,11 @@ dict_load_foreign( foreign->n_fields = mach_read_from_4(rec_get_nth_field(rec, 5, &len)); ut_a(len == 4); + + /* We store the type to the bits 24-31 of n_fields */ + + foreign->type = foreign->n_fields >> 24; + foreign->n_fields = foreign->n_fields & 0xFFFFFF; foreign->id = mem_heap_alloc(foreign->heap, ut_strlen(id) + 1); diff --git a/innobase/dict/dict0mem.c b/innobase/dict/dict0mem.c index 1f9a44aca35..52f46062065 100644 --- a/innobase/dict/dict0mem.c +++ b/innobase/dict/dict0mem.c @@ -61,7 +61,8 @@ dict_mem_table_create( table->mem_fix = 0; table->n_mysql_handles_opened = 0; - + table->n_foreign_key_checks_running = 0; + table->cached = FALSE; table->cols = mem_heap_alloc(heap, (n_cols + DATA_N_SYS_COLS) @@ -235,6 +236,7 @@ dict_mem_foreign_create(void) foreign->id = NULL; + foreign->type = 0; foreign->foreign_table_name = NULL; foreign->foreign_table = NULL; foreign->foreign_col_names = NULL; diff --git a/innobase/include/btr0btr.h b/innobase/include/btr0btr.h index bea85565125..d22f9d79c1c 100644 --- a/innobase/include/btr0btr.h +++ b/innobase/include/btr0btr.h @@ -49,6 +49,12 @@ inserted to the index, at the searched position */ /* This flag ORed to latch mode says that we do the search in query optimization */ #define BTR_ESTIMATE 1024 + +/* This flag ORed to latch mode says that we can ignore possible +UNIQUE definition on secondary indexes when we decide if we can use the +insert buffer to speed up inserts */ +#define BTR_IGNORE_SEC_UNIQUE 2048 + /****************************************************************** Gets a buffer page and declares its latching order level. */ UNIV_INLINE diff --git a/innobase/include/dict0mem.h b/innobase/include/dict0mem.h index 5ef0103087a..ef15c99fdba 100644 --- a/innobase/include/dict0mem.h +++ b/innobase/include/dict0mem.h @@ -249,6 +249,8 @@ struct dict_foreign_struct{ this memory heap */ char* id; /* id of the constraint as a null-terminated string */ + ulint type; /* 0 or DICT_FOREIGN_ON_DELETE_CASCADE + or DICT_FOREIGN_ON_DELETE_SET_NULL */ char* foreign_table_name;/* foreign table name */ dict_table_t* foreign_table; /* table where the foreign key is */ char** foreign_col_names;/* names of the columns in the @@ -278,6 +280,9 @@ struct dict_foreign_struct{ table */ }; +#define DICT_FOREIGN_ON_DELETE_CASCADE 1 +#define DICT_FOREIGN_ON_DELETE_SET_NULL 2 + #define DICT_INDEX_MAGIC_N 76789786 /* Data structure for a database table */ @@ -313,6 +318,12 @@ struct dict_table_struct{ NOT allowed until this count gets to zero; MySQL does NOT itself check the number of open handles at drop */ + ulint n_foreign_key_checks_running; + /* count of how many foreign key check + operations are currently being performed + on the table: we cannot drop the table while + there are foreign key checks running on + it! */ ibool cached; /* TRUE if the table object has been added to the dictionary cache */ lock_t* auto_inc_lock;/* a buffer for an auto-inc lock @@ -359,17 +370,16 @@ struct dict_table_struct{ after database startup or table creation */ ulint stat_modified_counter; /* when a row is inserted, updated, or deleted, - we add the row length to this number; we - calculate new estimates for the stat_... - values for the table and the indexes at an - interval of 2 GB or when about 1 / 16 of table - has been modified; also - when the estimate operation is called - for MySQL SHOW TABLE STATUS; the counter is - reset to zero at statistics calculation; - this counter - is not protected by any latch, because this - is only used for heuristics */ + we add 1 to this number; we calculate new + estimates for the stat_... values for the + table and the indexes at an interval of 2 GB + or when about 1 / 16 of table has been + modified; also when the estimate operation is + called for MySQL SHOW TABLE STATUS; the + counter is reset to zero at statistics + calculation; this counter is not protected by + any latch, because this is only used for + heuristics */ /*----------------------*/ mutex_t autoinc_mutex; /* mutex protecting the autoincrement diff --git a/innobase/include/ibuf0ibuf.h b/innobase/include/ibuf0ibuf.h index 99fb1595f49..fac28461be4 100644 --- a/innobase/include/ibuf0ibuf.h +++ b/innobase/include/ibuf0ibuf.h @@ -127,7 +127,11 @@ UNIV_INLINE ibool ibuf_should_try( /*============*/ - dict_index_t* index); /* in: index where to insert */ + dict_index_t* index, /* in: index where to insert */ + ulint ignore_sec_unique); /* in: if != 0, we should + ignore UNIQUE constraint on + a secondary index when we + decide */ /********************************************************************** Returns TRUE if the current OS thread is performing an insert buffer routine. */ diff --git a/innobase/include/ibuf0ibuf.ic b/innobase/include/ibuf0ibuf.ic index e969a0550da..0886c8c02cc 100644 --- a/innobase/include/ibuf0ibuf.ic +++ b/innobase/include/ibuf0ibuf.ic @@ -81,10 +81,16 @@ UNIV_INLINE ibool ibuf_should_try( /*============*/ - dict_index_t* index) /* in: index where to insert */ + dict_index_t* index, /* in: index where to insert */ + ulint ignore_sec_unique) /* in: if != 0, we should + ignore UNIQUE constraint on + a secondary index when we + decide */ { - if (!(index->type & (DICT_CLUSTERED | DICT_UNIQUE)) - && ibuf->meter > IBUF_THRESHOLD) { + if (!(index->type & DICT_CLUSTERED) + && (ignore_sec_unique || !(index->type & DICT_UNIQUE)) + && ibuf->meter > IBUF_THRESHOLD) { + ibuf_flush_count++; if (ibuf_flush_count % 8 == 0) { diff --git a/innobase/include/os0file.h b/innobase/include/os0file.h index 3dba8ba3158..01fa12955ff 100644 --- a/innobase/include/os0file.h +++ b/innobase/include/os0file.h @@ -341,6 +341,8 @@ os_aio_windows_handle( void** message2, ulint* type); /* out: OS_FILE_WRITE or ..._READ */ #endif + +/* Currently we do not use Posix async i/o */ #ifdef POSIX_ASYNC_IO /************************************************************************** This function is only used in Posix asynchronous i/o. Waits for an aio diff --git a/innobase/include/os0sync.h b/innobase/include/os0sync.h index 617f6b036fe..b2d613c4619 100644 --- a/innobase/include/os0sync.h +++ b/innobase/include/os0sync.h @@ -149,9 +149,9 @@ void os_mutex_free( /*==========*/ os_mutex_t mutex); /* in: mutex to free */ -#ifndef _WIN32 /************************************************************** -Acquires ownership of a fast mutex. */ +Acquires ownership of a fast mutex. Currently in Windows this is the same +as os_fast_mutex_lock! */ UNIV_INLINE ulint os_fast_mutex_trylock( @@ -160,7 +160,6 @@ os_fast_mutex_trylock( was reserved by another thread */ os_fast_mutex_t* fast_mutex); /* in: mutex to acquire */ -#endif /************************************************************** Releases ownership of a fast mutex. */ diff --git a/innobase/include/os0sync.ic b/innobase/include/os0sync.ic index aa00300dec5..6bff75d8ec6 100644 --- a/innobase/include/os0sync.ic +++ b/innobase/include/os0sync.ic @@ -10,9 +10,9 @@ Created 9/6/1995 Heikki Tuuri #include #endif -#ifndef _WIN32 /************************************************************** -Acquires ownership of a fast mutex. */ +Acquires ownership of a fast mutex. Currently in Windows this is the same +as os_fast_mutex_lock! */ UNIV_INLINE ulint os_fast_mutex_trylock( @@ -23,20 +23,11 @@ os_fast_mutex_trylock( os_fast_mutex_t* fast_mutex) /* in: mutex to acquire */ { #ifdef __WIN__ - int ret; + EnterCriticalSection(fast_mutex); - /* TODO: TryEnterCriticalSection is probably not found from - NT versions < 4! */ - ret = TryEnterCriticalSection(fast_mutex); - - if (ret) { - return(0); - } - - return(1); + return(0); #else return((ulint) pthread_mutex_trylock(fast_mutex)); #endif } -#endif diff --git a/innobase/include/row0mysql.h b/innobase/include/row0mysql.h index 92693319175..13b3dffd874 100644 --- a/innobase/include/row0mysql.h +++ b/innobase/include/row0mysql.h @@ -209,6 +209,27 @@ row_update_for_mysql( row_prebuilt_t* prebuilt); /* in: prebuilt struct in MySQL handle */ /************************************************************************* +Creates an query graph node of 'update' type to be used in the MySQL +interface. */ + +upd_node_t* +row_create_update_node_for_mysql( +/*=============================*/ + /* out, own: update node */ + dict_table_t* table, /* in: table to update */ + mem_heap_t* heap); /* in: mem heap from which allocated */ +/************************************************************************** +Does a cascaded delete or set null in a foreign key operation. */ + +ulint +row_update_cascade_for_mysql( +/*=========================*/ + /* out: error code or DB_SUCCESS */ + que_thr_t* thr, /* in: query thread */ + upd_node_t* node, /* in: update node used in the cascade + or set null operation */ + dict_table_t* table); /* in: table where we do the operation */ +/************************************************************************* Does a table creation operation for MySQL. If the name of the created table ends to characters INNODB_MONITOR, then this also starts printing of monitor output by the master thread. */ diff --git a/innobase/include/row0upd.h b/innobase/include/row0upd.h index 106d3866b25..9a3e2463267 100644 --- a/innobase/include/row0upd.h +++ b/innobase/include/row0upd.h @@ -312,6 +312,11 @@ struct upd_node_struct{ ibool in_mysql_interface; /* TRUE if the update node was created for the MySQL interface */ + upd_node_t* cascade_node;/* NULL or an update node template which + is used to implement ON DELETE CASCADE + or ... SET NULL for foreign keys */ + mem_heap_t* cascade_heap;/* NULL or a mem heap where the cascade + node is created */ sel_node_t* select; /* query graph subtree implementing a base table cursor: the rows returned will be updated */ @@ -322,6 +327,11 @@ struct upd_node_struct{ of the MySQL interface */ dict_table_t* table; /* table where updated */ upd_t* update; /* update vector for the row */ + ulint update_n_fields; + /* when this struct is used to implement + a cascade operation for foreign keys, we store + here the size of the buffer allocated for use + as the update vector */ sym_node_list_t columns;/* symbol table nodes for the columns to retrieve from the table */ ibool has_clust_rec_x_lock; diff --git a/innobase/include/sync0sync.h b/innobase/include/sync0sync.h index 6c3bff66e27..4f55709a5d7 100644 --- a/innobase/include/sync0sync.h +++ b/innobase/include/sync0sync.h @@ -359,12 +359,17 @@ V Memory pool mutex */ /* Latching order levels */ + +/* User transaction locks are higher than any of the latch levels below: +no latches are allowed when a thread goes to wait for a normal table +or row lock! */ +#define SYNC_USER_TRX_LOCK 9999 #define SYNC_NO_ORDER_CHECK 3000 /* this can be used to suppress latching order checking */ #define SYNC_LEVEL_NONE 2000 /* default: level not defined */ +#define SYNC_FOREIGN_KEY_CHECK 1001 #define SYNC_DICT 1000 #define SYNC_DICT_AUTOINC_MUTEX 999 -#define SYNC_FOREIGN_KEY_CHECK 998 #define SYNC_PURGE_IS_RUNNING 997 #define SYNC_DICT_HEADER 995 #define SYNC_IBUF_HEADER 914 @@ -429,7 +434,7 @@ implementation of a mutual exclusion semaphore. */ struct mutex_struct { ulint lock_word; /* This ulint is the target of the atomic test-and-set instruction in Win32 */ -#ifndef _WIN32 +#if !defined(_WIN32) || !defined(UNIV_CAN_USE_X86_ASSEMBLER) os_fast_mutex_t os_fast_mutex; /* In other systems we use this OS mutex in place of lock_word */ diff --git a/innobase/include/sync0sync.ic b/innobase/include/sync0sync.ic index 9531377ce0b..9014eb5fb54 100644 --- a/innobase/include/sync0sync.ic +++ b/innobase/include/sync0sync.ic @@ -53,7 +53,7 @@ mutex_test_and_set( 1 */ mutex_t* mutex) /* in: mutex */ { -#ifdef _WIN32 +#if defined(_WIN32) && defined(UNIV_CAN_USE_X86_ASSEMBLER) ulint res; ulint* lw; /* assembler code is used to ensure that lock_word is loaded from memory */ @@ -120,7 +120,7 @@ mutex_reset_lock_word( /*==================*/ mutex_t* mutex) /* in: mutex */ { -#ifdef _WIN32 +#if defined(_WIN32) && defined(UNIV_CAN_USE_X86_ASSEMBLER) ulint* lw; /* assembler code is used to ensure that lock_word is loaded from memory */ ut_ad(mutex); diff --git a/innobase/include/trx0sys.h b/innobase/include/trx0sys.h index 98c726fb118..60d5adb72d1 100644 --- a/innobase/include/trx0sys.h +++ b/innobase/include/trx0sys.h @@ -259,7 +259,7 @@ therefore 256 */ /* The offset of the transaction system header on the page */ #define TRX_SYS FSEG_PAGE_DATA -/* Transaction system header; protected by trx_sys->mutex */ +/* Transaction system header */ /*-------------------------------------------------------------*/ #define TRX_SYS_TRX_ID_STORE 0 /* the maximum trx id or trx number modulo TRX_SYS_TRX_ID_UPDATE_MARGIN diff --git a/innobase/include/trx0sys.ic b/innobase/include/trx0sys.ic index 786e7905933..ada2d8cb19c 100644 --- a/innobase/include/trx0sys.ic +++ b/innobase/include/trx0sys.ic @@ -93,7 +93,6 @@ trx_sysf_get( { trx_sysf_t* header; - ut_ad(mutex_own(&(kernel_mutex))); ut_ad(mtr); header = TRX_SYS + buf_page_get(TRX_SYS_SPACE, TRX_SYS_PAGE_NO, diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h index 26c9ace08b6..261f33d3dc3 100644 --- a/innobase/include/trx0trx.h +++ b/innobase/include/trx0trx.h @@ -298,6 +298,17 @@ struct trx_struct{ of view of concurrency control: TRX_ACTIVE, TRX_COMMITTED_IN_MEMORY, ... */ + ibool check_foreigns; /* normally TRUE, but if the user + wants to suppress foreign key checks, + (in table imports, for example) we + set this FALSE */ + ibool check_unique_secondary; + /* normally TRUE, but if the user + wants to speed up inserts by + suppressing unique key checks + for secondary indexes when we decide + if we can use the insert buffer for + them, we set this FALSE */ dulint id; /* transaction id */ dulint no; /* transaction serialization number == max trx id when the transaction is @@ -328,6 +339,9 @@ struct trx_struct{ /* how many tables the current SQL statement uses, except those in consistent read */ + ibool has_dict_foreign_key_check_lock; + /* TRUE if the trx currently holds + an s-lock on dict_foreign_... */ ibool has_search_latch; /* TRUE if this trx has latched the search system latch in S-mode */ diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c index 0b2b85d0337..9fd6811d639 100644 --- a/innobase/lock/lock0lock.c +++ b/innobase/lock/lock0lock.c @@ -1534,6 +1534,8 @@ lock_rec_enqueue_waiting( if (que_thr_stop(thr)) { + ut_a(0); + return(DB_QUE_THR_SUSPENDED); } @@ -2918,6 +2920,7 @@ lock_table_enqueue_waiting( stopped anyway */ if (que_thr_stop(thr)) { + ut_a(0); return(DB_QUE_THR_SUSPENDED); } diff --git a/innobase/pars/pars0opt.c b/innobase/pars/pars0opt.c index 6f4957f96ee..9814c4b21cc 100644 --- a/innobase/pars/pars0opt.c +++ b/innobase/pars/pars0opt.c @@ -526,7 +526,8 @@ opt_search_plan_for_table( dict_index_t* best_index; ulint n_fields; ulint goodness; - ulint last_op; + ulint last_op = 75946965; /* Eliminate a Purify + warning */ ulint best_goodness; ulint best_last_op; ulint mix_id_pos; diff --git a/innobase/que/que0que.c b/innobase/que/que0que.c index 97843311d21..41a90a7fb42 100644 --- a/innobase/que/que0que.c +++ b/innobase/que/que0que.c @@ -555,6 +555,12 @@ que_graph_free_recursive( btr_pcur_free_for_mysql(upd->pcur); } + que_graph_free_recursive(upd->cascade_node); + + if (upd->cascade_heap) { + mem_heap_free(upd->cascade_heap); + } + que_graph_free_recursive(upd->select); mem_heap_free(upd->heap); @@ -1110,9 +1116,6 @@ que_thr_move_to_run_state_for_mysql( trx->n_active_thrs++; thr->is_active = TRUE; - - ut_ad((thr->graph)->n_active_thrs == 1); - ut_ad(trx->n_active_thrs == 1); } thr->state = QUE_THR_RUNNING; diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c index 04df66c3bbd..0ba6db39e2a 100644 --- a/innobase/row/row0ins.c +++ b/innobase/row/row0ins.c @@ -355,6 +355,223 @@ row_ins_dupl_error_with_rec( return(FALSE); } +/************************************************************************* +Either deletes or sets the referencing columns SQL NULL in a child row. +Used in ON DELETE ... clause for foreign keys when a parent row is +deleted. */ +static +ulint +row_ins_foreign_delete_or_set_null( +/*===============================*/ + /* out: DB_SUCCESS, DB_LOCK_WAIT, + or error code */ + que_thr_t* thr, /* in: query thread whose run_node + is an update node */ + dict_foreign_t* foreign, /* in: foreign key constraint whose + type is != 0 */ + btr_pcur_t* pcur, /* in: cursor placed on a matching + index record in the child table */ + mtr_t* mtr) /* in: mtr holding the latch of pcur + page */ +{ + upd_node_t* node; + upd_node_t* cascade; + dict_table_t* table = foreign->foreign_table; + dict_index_t* index; + dict_index_t* clust_index; + dtuple_t* ref; + mem_heap_t* tmp_heap; + rec_t* rec; + rec_t* clust_rec; + upd_t* update; + ulint err; + ulint i; + char err_buf[1000]; + + ut_a(thr && foreign && pcur && mtr); + + node = thr->run_node; + + if (node->cascade_node == NULL) { + /* Extend our query graph by creating a child to current + update node. The child is used in the cascade or set null + operation. */ + + node->cascade_heap = mem_heap_create(128); + node->cascade_node = row_create_update_node_for_mysql( + table, node->cascade_heap); + que_node_set_parent(node->cascade_node, node); + } + + /* Initialize cascade_node to do the operation we want. Note that we + use the SAME cascade node to do all foreign key operations of the + SQL DELETE: the table of the cascade node may change if there are + several child tables to the table where the delete is done! */ + + cascade = node->cascade_node; + + cascade->table = table; + + if (foreign->type == DICT_FOREIGN_ON_DELETE_CASCADE ) { + cascade->is_delete = TRUE; + } else { + cascade->is_delete = FALSE; + + if (foreign->n_fields > cascade->update_n_fields) { + /* We have to make the update vector longer */ + + cascade->update = upd_create(foreign->n_fields, + node->cascade_heap); + cascade->update_n_fields = foreign->n_fields; + } + } + + index = btr_pcur_get_btr_cur(pcur)->index; + + rec = btr_pcur_get_rec(pcur); + + if (index->type & DICT_CLUSTERED) { + /* pcur is already positioned in the clustered index of + the child table */ + + clust_index = index; + clust_rec = rec; + } else { + /* We have to look for the record in the clustered index + in the child table */ + + clust_index = dict_table_get_first_index(table); + + tmp_heap = mem_heap_create(256); + + ref = row_build_row_ref(ROW_COPY_POINTERS, index, rec, + tmp_heap); + btr_pcur_open_with_no_init(clust_index, ref, + PAGE_CUR_LE, BTR_SEARCH_LEAF, + cascade->pcur, 0, mtr); + + mem_heap_free(tmp_heap); + + clust_rec = btr_pcur_get_rec(cascade->pcur); + } + + if (!page_rec_is_user_rec(clust_rec)) { + fprintf(stderr, "InnoDB: error in cascade of a foreign key op\n" + "InnoDB: index %s table %s\n", index->name, + index->table->name); + + rec_sprintf(err_buf, 900, rec); + fprintf(stderr, "InnoDB: record %s\n", err_buf); + + rec_sprintf(err_buf, 900, clust_rec); + fprintf(stderr, "InnoDB: clustered record %s\n", err_buf); + + fprintf(stderr, + "InnoDB: Make a detailed bug report and send it\n"); + fprintf(stderr, "InnoDB: to mysql@lists.mysql.com\n"); + + err = DB_SUCCESS; + + goto nonstandard_exit_func; + } + + /* Set an X-lock on the row to delete or update in the child table */ + + err = lock_table(0, table, LOCK_IX, thr); + + if (err == DB_SUCCESS) { + err = lock_clust_rec_read_check_and_lock(0, clust_rec, + clust_index, LOCK_X, thr); + } + + if (err != DB_SUCCESS) { + + goto nonstandard_exit_func; + } + + if (rec_get_deleted_flag(clust_rec)) { + /* This should never happen since we already have an S-lock + on non-delete-marked clust_rec or secondary index record! */ + + fprintf(stderr, + "InnoDB: error 2 in cascade of a foreign key op\n" + "InnoDB: index %s table %s\n", index->name, + index->table->name); + + rec_sprintf(err_buf, 900, rec); + fprintf(stderr, "InnoDB: record %s\n", err_buf); + + rec_sprintf(err_buf, 900, clust_rec); + fprintf(stderr, "InnoDB: clustered record %s\n", err_buf); + + fprintf(stderr, + "InnoDB: Make a detailed bug report and send it\n"); + fprintf(stderr, "InnoDB: to mysql@lists.mysql.com\n"); + + ut_a(0); + + goto nonstandard_exit_func; + } + + if (foreign->type == DICT_FOREIGN_ON_DELETE_SET_NULL) { + /* Build the appropriate update vector which sets + foreign->n_fields first fields in rec to SQL NULL */ + + update = cascade->update; + + update->info_bits = 0; + update->n_fields = foreign->n_fields; + + for (i = 0; i < foreign->n_fields; i++) { + (update->fields + i)->field_no + = dict_table_get_nth_col_pos(table, + dict_index_get_nth_col_no(index, i)); + (update->fields + i)->exp = NULL; + (update->fields + i)->new_val.len = UNIV_SQL_NULL; + (update->fields + i)->new_val.data = NULL; + (update->fields + i)->extern_storage = FALSE; + } + } + + /* Store pcur position and initialize or store the cascade node + pcur stored position */ + + btr_pcur_store_position(pcur, mtr); + + if (index == clust_index) { + btr_pcur_copy_stored_position(cascade->pcur, pcur); + } else { + btr_pcur_store_position(cascade->pcur, mtr); + } + + mtr_commit(mtr); + + ut_a(cascade->pcur->rel_pos == BTR_PCUR_ON); + + cascade->state = UPD_NODE_UPDATE_CLUSTERED; + + err = row_update_cascade_for_mysql(thr, cascade, + foreign->foreign_table); + mtr_start(mtr); + + /* Restore pcur position */ + + btr_pcur_restore_position(BTR_SEARCH_LEAF, pcur, mtr); + + return(err); + +nonstandard_exit_func: + + btr_pcur_store_position(pcur, mtr); + + mtr_commit(mtr); + mtr_start(mtr); + + btr_pcur_restore_position(BTR_SEARCH_LEAF, pcur, mtr); + + return(err); +} + /************************************************************************* Sets a shared lock on a record. Used in locking possible duplicate key records. */ @@ -416,6 +633,13 @@ row_ins_check_foreign_constraint( ut_ad(rw_lock_own(&dict_foreign_key_check_lock, RW_LOCK_SHARED)); + if (thr_get_trx(thr)->check_foreigns == FALSE) { + /* The user has suppressed foreign key checks currently for + this session */ + + return(DB_SUCCESS); + } + /* If any of the foreign key fields in entry is SQL NULL, we suppress the foreign key check: this is compatible with Oracle, for example */ @@ -478,8 +702,8 @@ row_ins_check_foreign_constraint( goto next_rec; } - - /* Try to place a lock on the index record */ + + /* Try to place a lock on the index record */ err = row_ins_set_shared_rec_lock(rec, check_index, thr); @@ -501,11 +725,21 @@ row_ins_check_foreign_constraint( if (check_ref) { err = DB_SUCCESS; + + break; + } else if (foreign->type != 0) { + err = + row_ins_foreign_delete_or_set_null( + thr, foreign, &pcur, &mtr); + + if (err != DB_SUCCESS) { + + break; + } } else { err = DB_ROW_IS_REFERENCED; + break; } - - break; } } @@ -534,6 +768,8 @@ next_rec: } } + btr_pcur_close(&pcur); + mtr_commit(&mtr); /* Restore old value */ @@ -561,6 +797,10 @@ row_ins_check_foreign_constraints( { dict_foreign_t* foreign; ulint err; + trx_t* trx; + ibool got_s_lock = FALSE; + + trx = thr_get_trx(thr); foreign = UT_LIST_GET_FIRST(table->foreign_list); @@ -569,16 +809,26 @@ row_ins_check_foreign_constraints( if (foreign->referenced_table == NULL) { dict_table_get(foreign->referenced_table_name, - thr_get_trx(thr)); + trx); } - rw_lock_s_lock(&dict_foreign_key_check_lock); + if (!trx->has_dict_foreign_key_check_lock) { + got_s_lock = TRUE; + + rw_lock_s_lock(&dict_foreign_key_check_lock); + + trx->has_dict_foreign_key_check_lock = TRUE; + } err = row_ins_check_foreign_constraint(TRUE, foreign, table, index, entry, thr); + if (got_s_lock) { - rw_lock_s_unlock(&dict_foreign_key_check_lock); + rw_lock_s_unlock(&dict_foreign_key_check_lock); + trx->has_dict_foreign_key_check_lock = FALSE; + } + if (err != DB_SUCCESS) { return(err); } @@ -868,13 +1118,14 @@ row_ins_index_entry_low( ulint n_ext_vec,/* in: number of fields in ext_vec */ que_thr_t* thr) /* in: query thread */ { - btr_cur_t cursor; + btr_cur_t cursor; + ulint ignore_sec_unique = 0; ulint modify; rec_t* insert_rec; rec_t* rec; ulint err; ulint n_unique; - big_rec_t* big_rec = NULL; + big_rec_t* big_rec = NULL; mtr_t mtr; log_free_check(); @@ -887,8 +1138,13 @@ row_ins_index_entry_low( the function will return in both low_match and up_match of the cursor sensible values */ + if (!(thr_get_trx(thr)->check_unique_secondary)) { + ignore_sec_unique = BTR_IGNORE_SEC_UNIQUE; + } + btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE, - mode | BTR_INSERT, &cursor, 0, &mtr); + mode | BTR_INSERT | ignore_sec_unique, + &cursor, 0, &mtr); if (cursor.flag == BTR_CUR_INSERT_TO_IBUF) { /* The insertion was made to the insert buffer already during diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index 2aca698eebd..7969394f5e4 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -499,29 +499,24 @@ UNIV_INLINE void row_update_statistics_if_needed( /*============================*/ - row_prebuilt_t* prebuilt) /* in: prebuilt struct */ + dict_table_t* table) /* in: table */ { ulint counter; - counter = prebuilt->table->stat_modified_counter; + counter = table->stat_modified_counter; - /* Since the physical size of an InnoDB row is bigger than the - MySQL row len, we put a safety factor 2 below */ - - counter += 2 * prebuilt->mysql_row_len; - - prebuilt->table->stat_modified_counter = counter; + table->stat_modified_counter = counter + 1; /* Calculate new statistics if 1 / 16 of table has been modified since the last time a statistics batch was run, or if - stat_modified_counter > 2 000 000 000 (to avoid wrap-around) */ + stat_modified_counter > 2 000 000 000 (to avoid wrap-around). + We calculate statistics at most every 16th round, since we may have + a counter table which is very small and updated very often. */ if (counter > 2000000000 - || ((ib_longlong)counter > - (UNIV_PAGE_SIZE * prebuilt->table->stat_clustered_index_size) - / 16)) { + || ((ib_longlong)counter > 16 + table->stat_n_rows / 16)) { - dict_update_statistics(prebuilt->table); + dict_update_statistics(table); } } @@ -712,7 +707,7 @@ run_again: prebuilt->table->stat_n_rows--; } - row_update_statistics_if_needed(prebuilt); + row_update_statistics_if_needed(prebuilt->table); trx->op_info = ""; return((int) err); @@ -745,6 +740,43 @@ row_prebuild_sel_graph( } } +/************************************************************************* +Creates an query graph node of 'update' type to be used in the MySQL +interface. */ + +upd_node_t* +row_create_update_node_for_mysql( +/*=============================*/ + /* out, own: update node */ + dict_table_t* table, /* in: table to update */ + mem_heap_t* heap) /* in: mem heap from which allocated */ +{ + upd_node_t* node; + + node = upd_node_create(heap); + + node->in_mysql_interface = TRUE; + node->is_delete = FALSE; + node->searched_update = FALSE; + node->select_will_do_update = FALSE; + node->select = NULL; + node->pcur = btr_pcur_create_for_mysql(); + node->table = table; + + node->update = upd_create(dict_table_get_n_cols(table), heap); + + node->update_n_fields = dict_table_get_n_cols(table); + + UT_LIST_INIT(node->columns); + node->has_clust_rec_x_lock = TRUE; + node->cmpl_info = 0; + + node->table_sym = NULL; + node->col_assign_list = NULL; + + return(node); +} + /************************************************************************* Gets pointer to a prebuilt update vector used in updates. If the update graph has not yet been built in the prebuilt struct, then this function @@ -767,26 +799,9 @@ row_get_prebuilt_update_vector( /* Not called before for this handle: create an update node and query graph to the prebuilt struct */ - node = upd_node_create(prebuilt->heap); - + node = row_create_update_node_for_mysql(table, prebuilt->heap); + prebuilt->upd_node = node; - - node->in_mysql_interface = TRUE; - node->is_delete = FALSE; - node->searched_update = FALSE; - node->select_will_do_update = FALSE; - node->select = NULL; - node->pcur = btr_pcur_create_for_mysql(); - node->table = table; - - node->update = upd_create(dict_table_get_n_cols(table), - prebuilt->heap); - UT_LIST_INIT(node->columns); - node->has_clust_rec_x_lock = TRUE; - node->cmpl_info = 0; - - node->table_sym = NULL; - node->col_assign_list = NULL; prebuilt->upd_graph = que_node_get_parent( @@ -914,7 +929,7 @@ run_again: que_thr_stop_for_mysql_no_error(thr, trx); - if (prebuilt->upd_node->is_delete) { + if (node->is_delete) { if (prebuilt->table->stat_n_rows > 0) { prebuilt->table->stat_n_rows--; } @@ -924,13 +939,66 @@ run_again: srv_n_rows_updated++; } - row_update_statistics_if_needed(prebuilt); + row_update_statistics_if_needed(prebuilt->table); trx->op_info = ""; return((int) err); } +/************************************************************************** +Does a cascaded delete or set null in a foreign key operation. */ + +ulint +row_update_cascade_for_mysql( +/*=========================*/ + /* out: error code or DB_SUCCESS */ + que_thr_t* thr, /* in: query thread */ + upd_node_t* node, /* in: update node used in the cascade + or set null operation */ + dict_table_t* table) /* in: table where we do the operation */ +{ + ulint err; + trx_t* trx; + + trx = thr_get_trx(thr); + +run_again: + thr->run_node = node; + thr->prev_node = node; + + row_upd_step(thr); + + err = trx->error_state; + + if (err == DB_LOCK_WAIT) { + que_thr_stop_for_mysql(thr); + + row_mysql_handle_errors(&err, trx, thr, NULL); + + goto run_again; + } + + if (err != DB_SUCCESS) { + + return(err); + } + + if (node->is_delete) { + if (table->stat_n_rows > 0) { + table->stat_n_rows--; + } + + srv_n_rows_deleted++; + } else { + srv_n_rows_updated++; + } + + row_update_statistics_if_needed(table); + + return(err); +} + /************************************************************************* Checks if a table is such that we automatically created a clustered index on it (on row id). */ @@ -1169,6 +1237,7 @@ row_create_table_for_mysql( /* Serialize data dictionary operations with dictionary mutex: no deadlocks can occur then in these operations */ + rw_lock_x_lock(&(dict_foreign_key_check_lock)); mutex_enter(&(dict_sys->mutex)); heap = mem_heap_create(512); @@ -1221,6 +1290,8 @@ row_create_table_for_mysql( } mutex_exit(&(dict_sys->mutex)); + rw_lock_x_unlock(&(dict_foreign_key_check_lock)); + que_graph_free((que_t*) que_node_get_parent(thr)); trx->op_info = ""; @@ -1268,6 +1339,7 @@ row_create_index_for_mysql( /* Serialize data dictionary operations with dictionary mutex: no deadlocks can occur then in these operations */ + rw_lock_x_lock(&(dict_foreign_key_check_lock)); mutex_enter(&(dict_sys->mutex)); heap = mem_heap_create(512); @@ -1298,6 +1370,7 @@ row_create_index_for_mysql( } mutex_exit(&(dict_sys->mutex)); + rw_lock_x_unlock(&(dict_foreign_key_check_lock)); que_graph_free((que_t*) que_node_get_parent(thr)); @@ -1353,6 +1426,7 @@ row_table_add_foreign_constraints( /* Serialize data dictionary operations with dictionary mutex: no deadlocks can occur then in these operations */ + rw_lock_x_lock(&(dict_foreign_key_check_lock)); mutex_enter(&(dict_sys->mutex)); trx->dict_operation = TRUE; @@ -1377,6 +1451,7 @@ row_table_add_foreign_constraints( } mutex_exit(&(dict_sys->mutex)); + rw_lock_x_unlock(&(dict_foreign_key_check_lock)); return((int) err); } @@ -1471,7 +1546,8 @@ loop: goto already_dropped; } - if (table->n_mysql_handles_opened > 0) { + if (table->n_mysql_handles_opened > 0 + || table->n_foreign_key_checks_running > 0) { return(n_tables + n_tables_dropped); } @@ -1717,6 +1793,9 @@ row_drop_table_for_mysql( no deadlocks can occur then in these operations */ if (!has_dict_mutex) { + /* Prevent foreign key checks while we are dropping the table */ + rw_lock_x_lock(&(dict_foreign_key_check_lock)); + mutex_enter(&(dict_sys->mutex)); } @@ -1729,9 +1808,6 @@ row_drop_table_for_mysql( graph->fork_type = QUE_FORK_MYSQL_INTERFACE; - /* Prevent foreign key checks while we are dropping the table */ - rw_lock_x_lock(&(dict_foreign_key_check_lock)); - /* Prevent purge from running while we are dropping the table */ rw_lock_s_lock(&(purge_sys->purge_is_running)); @@ -1766,6 +1842,22 @@ row_drop_table_for_mysql( goto funct_exit; } + if (table->n_foreign_key_checks_running > 0) { + + ut_print_timestamp(stderr); + fprintf(stderr, + " InnoDB: You are trying to drop table %s\n" + "InnoDB: though there are foreign key check running on it.\n" + "InnoDB: Adding the table to the background drop queue.\n", + table->name); + + row_add_table_to_background_drop_list(table); + + err = DB_SUCCESS; + + goto funct_exit; + } + /* Remove any locks there are on the table or its records */ lock_reset_all_on_table(table); @@ -1793,10 +1885,9 @@ row_drop_table_for_mysql( funct_exit: rw_lock_s_unlock(&(purge_sys->purge_is_running)); - rw_lock_x_unlock(&(dict_foreign_key_check_lock)); - if (!has_dict_mutex) { mutex_exit(&(dict_sys->mutex)); + rw_lock_x_unlock(&(dict_foreign_key_check_lock)); } que_graph_free(graph); @@ -1832,6 +1923,7 @@ row_drop_database_for_mysql( trx_start_if_not_started(trx); loop: + rw_lock_x_lock(&(dict_foreign_key_check_lock)); mutex_enter(&(dict_sys->mutex)); while (table_name = dict_get_first_table_name_in_db(name)) { @@ -1873,6 +1965,7 @@ loop: } mutex_exit(&(dict_sys->mutex)); + rw_lock_x_unlock(&(dict_foreign_key_check_lock)); trx_commit_for_mysql(trx); @@ -2009,6 +2102,7 @@ row_rename_table_for_mysql( /* Serialize data dictionary operations with dictionary mutex: no deadlocks can occur then in these operations */ + rw_lock_x_lock(&(dict_foreign_key_check_lock)); mutex_enter(&(dict_sys->mutex)); table = dict_table_get_low(old_name); @@ -2090,6 +2184,7 @@ row_rename_table_for_mysql( } funct_exit: mutex_exit(&(dict_sys->mutex)); + rw_lock_x_unlock(&(dict_foreign_key_check_lock)); que_graph_free(graph); diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c index 9ebd47c25bf..a516699edf9 100644 --- a/innobase/row/row0sel.c +++ b/innobase/row/row0sel.c @@ -2115,8 +2115,14 @@ row_sel_store_mysql_rec( extern_field_heap = NULL; } } else { - mysql_rec[templ->mysql_null_byte_offset] |= + if (!templ->mysql_null_bit_mask) { + fprintf(stderr, +"InnoDB: Error: trying to return an SQL NULL field in a non-null\n" +"innoDB: column! Table name %s\n", prebuilt->table->name); + } else { + mysql_rec[templ->mysql_null_byte_offset] |= (byte) (templ->mysql_null_bit_mask); + } } } } diff --git a/innobase/row/row0upd.c b/innobase/row/row0upd.c index a566e29f2c3..457cb72aaad 100644 --- a/innobase/row/row0upd.c +++ b/innobase/row/row0upd.c @@ -73,8 +73,7 @@ steps of query graph execution. */ /************************************************************************* Checks if index currently is mentioned as a referenced index in a foreign -key constraint. This function also loads into the dictionary cache the -possible referencing table. */ +key constraint. */ static ibool row_upd_index_is_referenced( @@ -85,44 +84,28 @@ row_upd_index_is_referenced( the referencing table has been dropped when we leave this function: this function is only for heuristic use! */ - dict_index_t* index) /* in: index */ + dict_index_t* index, /* in: index */ + trx_t* trx) /* in: transaction */ { - dict_table_t* table = index->table; + dict_table_t* table = index->table; dict_foreign_t* foreign; - ulint phase = 1; -try_again: if (!UT_LIST_GET_FIRST(table->referenced_list)) { return(FALSE); } - if (phase == 2) { - mutex_enter(&(dict_sys->mutex)); + if (!trx->has_dict_foreign_key_check_lock) { + rw_lock_s_lock(&dict_foreign_key_check_lock); } - rw_lock_s_lock(&dict_foreign_key_check_lock); - foreign = UT_LIST_GET_FIRST(table->referenced_list); while (foreign) { if (foreign->referenced_index == index) { - if (foreign->foreign_table == NULL) { - if (phase == 2) { - dict_table_get_low(foreign-> - foreign_table_name); - } else { - phase = 2; - rw_lock_s_unlock( - &dict_foreign_key_check_lock); - goto try_again; - } - } - rw_lock_s_unlock(&dict_foreign_key_check_lock); - - if (phase == 2) { - mutex_exit(&(dict_sys->mutex)); + if (!trx->has_dict_foreign_key_check_lock) { + rw_lock_s_unlock(&dict_foreign_key_check_lock); } return(TRUE); @@ -131,10 +114,8 @@ try_again: foreign = UT_LIST_GET_NEXT(referenced_list, foreign); } - rw_lock_s_unlock(&dict_foreign_key_check_lock); - - if (phase == 2) { - mutex_exit(&(dict_sys->mutex)); + if (!trx->has_dict_foreign_key_check_lock) { + rw_lock_s_unlock(&dict_foreign_key_check_lock); } return(FALSE); @@ -160,8 +141,17 @@ row_upd_check_references_constraints( dict_foreign_t* foreign; mem_heap_t* heap; dtuple_t* entry; + trx_t* trx; rec_t* rec; ulint err; + ibool got_s_lock = FALSE; + + if (UT_LIST_GET_FIRST(table->referenced_list) == NULL) { + + return(DB_SUCCESS); + } + + trx = thr_get_trx(thr); rec = btr_pcur_get_rec(pcur); @@ -173,17 +163,61 @@ row_upd_check_references_constraints( mtr_start(mtr); - rw_lock_s_lock(&dict_foreign_key_check_lock); + if (!trx->has_dict_foreign_key_check_lock) { + got_s_lock = TRUE; + rw_lock_s_lock(&dict_foreign_key_check_lock); + + trx->has_dict_foreign_key_check_lock = TRUE; + } + foreign = UT_LIST_GET_FIRST(table->referenced_list); while (foreign) { if (foreign->referenced_index == index) { + if (foreign->foreign_table == NULL) { + dict_table_get(foreign->foreign_table_name, + trx); + } + if (foreign->foreign_table) { + mutex_enter(&(dict_sys->mutex)); + + (foreign->foreign_table + ->n_foreign_key_checks_running)++; + + mutex_exit(&(dict_sys->mutex)); + } + + /* NOTE that if the thread ends up waiting for a lock + we will release dict_foreign_key_check_lock + temporarily! But the counter on the table + protects 'foreign' from being dropped while the check + is running. */ + err = row_ins_check_foreign_constraint(FALSE, foreign, table, index, entry, thr); + + if (foreign->foreign_table) { + mutex_enter(&(dict_sys->mutex)); + + ut_a(foreign->foreign_table + ->n_foreign_key_checks_running > 0); + + (foreign->foreign_table + ->n_foreign_key_checks_running)--; + + mutex_exit(&(dict_sys->mutex)); + } + if (err != DB_SUCCESS) { - rw_lock_s_unlock(&dict_foreign_key_check_lock); + if (got_s_lock) { + rw_lock_s_unlock( + &dict_foreign_key_check_lock); + trx->has_dict_foreign_key_check_lock + = FALSE; + } + mem_heap_free(heap); return(err); @@ -193,7 +227,11 @@ row_upd_check_references_constraints( foreign = UT_LIST_GET_NEXT(referenced_list, foreign); } - rw_lock_s_unlock(&dict_foreign_key_check_lock); + if (got_s_lock) { + rw_lock_s_unlock(&dict_foreign_key_check_lock); + trx->has_dict_foreign_key_check_lock = FALSE; + } + mem_heap_free(heap); return(DB_SUCCESS); @@ -222,6 +260,9 @@ upd_node_create( node->index = NULL; node->update = NULL; + node->cascade_heap = NULL; + node->cascade_node = NULL; + node->select = NULL; node->heap = mem_heap_create(128); @@ -1027,7 +1068,7 @@ row_upd_sec_index_entry( index = node->index; - check_ref = row_upd_index_is_referenced(index); + check_ref = row_upd_index_is_referenced(index, thr_get_trx(thr)); heap = mem_heap_create(1024); @@ -1391,7 +1432,7 @@ row_upd_clust_step( index = dict_table_get_first_index(node->table); - check_ref = row_upd_index_is_referenced(index); + check_ref = row_upd_index_is_referenced(index, thr_get_trx(thr)); pcur = node->pcur; diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index 8afe1396f1b..d4aa085479b 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -2017,15 +2017,18 @@ srv_suspend_mysql_thread( /*=====================*/ /* out: TRUE if the lock wait timeout was exceeded */ - que_thr_t* thr) /* in: query thread associated with - the MySQL OS thread */ + que_thr_t* thr) /* in: query thread associated with the MySQL + OS thread */ { srv_slot_t* slot; os_event_t event; double wait_time; - + trx_t* trx; + ut_ad(!mutex_own(&kernel_mutex)); + trx = thr_get_trx(thr); + os_event_set(srv_lock_timeout_thread_event); mutex_enter(&kernel_mutex); @@ -2061,10 +2064,21 @@ srv_suspend_mysql_thread( srv_conc_force_exit_innodb(thr_get_trx(thr)); + /* Release possible foreign key check latch */ + if (trx->has_dict_foreign_key_check_lock) { + + rw_lock_s_unlock(&dict_foreign_key_check_lock); + } + /* Wait for the release */ os_event_wait(event); + if (trx->has_dict_foreign_key_check_lock) { + + rw_lock_s_lock(&dict_foreign_key_check_lock); + } + /* Return back inside InnoDB */ srv_conc_force_enter_innodb(thr_get_trx(thr)); diff --git a/innobase/sync/sync0sync.c b/innobase/sync/sync0sync.c index 8b2a39e15eb..f5b4e35e8d2 100644 --- a/innobase/sync/sync0sync.c +++ b/innobase/sync/sync0sync.c @@ -220,7 +220,7 @@ mutex_create_func( char* cfile_name, /* in: file name where created */ ulint cline) /* in: file line where created */ { -#ifdef _WIN32 +#if defined(_WIN32) && defined(UNIV_CAN_USE_X86_ASSEMBLER) mutex_reset_lock_word(mutex); #else os_fast_mutex_init(&(mutex->os_fast_mutex)); @@ -273,7 +273,7 @@ mutex_free( mutex_exit(&mutex_list_mutex); -#ifndef _WIN32 +#if !defined(_WIN32) || !defined(UNIV_CAN_USE_X86_ASSEMBLER) os_fast_mutex_free(&(mutex->os_fast_mutex)); #endif /* If we free the mutex protecting the mutex list (freeing is @@ -1009,7 +1009,7 @@ sync_thread_add_level( } else if (level == SYNC_ANY_LATCH) { ut_a(sync_thread_levels_g(array, SYNC_ANY_LATCH)); } else if (level == SYNC_TRX_SYS_HEADER) { - ut_a(sync_thread_levels_contain(array, SYNC_KERNEL)); + ut_a(sync_thread_levels_g(array, SYNC_TRX_SYS_HEADER)); } else if (level == SYNC_DOUBLEWRITE) { ut_a(sync_thread_levels_g(array, SYNC_DOUBLEWRITE)); } else if (level == SYNC_BUF_BLOCK) { diff --git a/innobase/trx/trx0sys.c b/innobase/trx/trx0sys.c index 6c9776560bd..32a1db48488 100644 --- a/innobase/trx/trx0sys.c +++ b/innobase/trx/trx0sys.c @@ -438,7 +438,6 @@ trx_sys_update_mysql_binlog_offset( trx_sysf_t* sys_header; char namebuf[TRX_SYS_MYSQL_LOG_NAME_LEN]; - ut_ad(mutex_own(&kernel_mutex)); ut_ad(trx->mysql_log_file_name); memset(namebuf, ' ', TRX_SYS_MYSQL_LOG_NAME_LEN - 1); @@ -524,7 +523,7 @@ trx_sys_print_mysql_binlog_offset(void) } fprintf(stderr, - "InnoDB: Last MySQL binlog file offset %lu %lu, file name %s\n", + "InnoDB: Last MySQL binlog file position %lu %lu, file name %s\n", mach_read_from_4(sys_header + TRX_SYS_MYSQL_LOG_INFO + TRX_SYS_MYSQL_LOG_OFFSET_HIGH), mach_read_from_4(sys_header + TRX_SYS_MYSQL_LOG_INFO diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c index 6cbf97104b3..ae607c33fbe 100644 --- a/innobase/trx/trx0trx.c +++ b/innobase/trx/trx0trx.c @@ -71,6 +71,9 @@ trx_create( trx->type = TRX_USER; trx->conc_state = TRX_NOT_STARTED; + trx->check_foreigns = TRUE; + trx->check_unique_secondary = TRUE; + trx->dict_operation = FALSE; trx->mysql_thd = NULL; @@ -113,6 +116,7 @@ trx_create( trx->lock_heap = mem_heap_create_in_buffer(256); UT_LIST_INIT(trx->trx_locks); + trx->has_dict_foreign_key_check_lock = FALSE; trx->has_search_latch = FALSE; trx->search_latch_timeout = BTR_SEA_TIMEOUT; @@ -703,8 +707,7 @@ trx_commit_off_kernel( /*-------------------------------------*/ - /* Only in some performance tests the variable srv_flush.. - will be set to FALSE: */ + /* Most MySQL users run with srv_flush.. set to FALSE: */ if (srv_flush_log_at_trx_commit) { From c8b5e417917eedfd44a51723c350909ac36e13d4 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Thu, 18 Apr 2002 10:50:42 +0300 Subject: [PATCH 11/17] univ.i: Make possible switch off X86 assembler usage in Windows: needed for the Itanium port --- innobase/include/univ.i | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/innobase/include/univ.i b/innobase/include/univ.i index a4345babbbe..1269b4a288a 100644 --- a/innobase/include/univ.i +++ b/innobase/include/univ.i @@ -14,6 +14,10 @@ Created 1/20/1994 Heikki Tuuri #include +/* When compiling for Itanium IA64, undefine the flag below to prevent use +of 32-bit assembler */ +#define UNIV_CAN_USE_X86_ASSEMBLER + /* If you want to check for errors with compiler level -W4, comment out the above include of windows.h and let the following defines be defined: @@ -70,13 +74,14 @@ memory is read outside the allocated blocks. */ */ /* Make a non-inline debug version */ + /* #define UNIV_DEBUG #define UNIV_MEM_DEBUG -#define UNIV_SEARCH_DEBUG +#define UNIV_SYNC_DEBUG #define UNIV_IBUF_DEBUG -#define UNIV_SYNC_DEBUG +#define UNIV_SEARCH_DEBUG #define UNIV_SYNC_PERF_STAT #define UNIV_SEARCH_PERF_STAT */ From 626f5bff47e962ba38bdb4ab430cc6d49badbebd Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Thu, 18 Apr 2002 12:03:40 +0300 Subject: [PATCH 12/17] univ.i: Prevent use of X86 assembler when WIN64 defined --- innobase/include/univ.i | 3 +++ 1 file changed, 3 insertions(+) diff --git a/innobase/include/univ.i b/innobase/include/univ.i index 1269b4a288a..b958475e683 100644 --- a/innobase/include/univ.i +++ b/innobase/include/univ.i @@ -16,7 +16,10 @@ Created 1/20/1994 Heikki Tuuri /* When compiling for Itanium IA64, undefine the flag below to prevent use of 32-bit assembler */ + +#ifndef WIN64 #define UNIV_CAN_USE_X86_ASSEMBLER +#endif /* If you want to check for errors with compiler level -W4, comment out the above include of windows.h and let the following defines From f94d84a9ec6903dd153f2336aaa5c9a1b0daddb8 Mon Sep 17 00:00:00 2001 From: "monty@tik.mysql.fi" <> Date: Thu, 18 Apr 2002 18:24:14 +0300 Subject: [PATCH 13/17] SHOW VARIABLES LIKE ... are now case insensitive Fixed stack overflow checking with crash-me with gcc 3.0.4 Using @@unknown_variable doesn't hang client anymore Added @@VERSION variable --- Docs/manual.texi | 8 ++++++++ libmysql/libmysql.c | 2 +- myisam/myisampack.c | 3 +-- mysql-test/r/identity.result | 4 ---- mysql-test/r/show_check.result | 2 ++ mysql-test/r/variables.result | 8 ++++++++ mysql-test/t/identity.test | 2 -- mysql-test/t/show_check.test | 1 + mysql-test/t/variables.test | 11 +++++++++++ sql/item_func.cc | 11 +++++++---- sql/mysql_priv.h | 24 ++++++++++++++++-------- sql/share/czech/errmsg.txt | 2 +- sql/share/danish/errmsg.txt | 2 +- sql/share/dutch/errmsg.txt | 2 +- sql/share/english/errmsg.txt | 2 +- sql/share/estonian/errmsg.txt | 2 +- sql/share/french/errmsg.txt | 2 +- sql/share/german/errmsg.txt | 2 +- sql/share/greek/errmsg.txt | 2 +- sql/share/hungarian/errmsg.txt | 2 +- sql/share/italian/errmsg.txt | 2 +- sql/share/japanese/errmsg.txt | 2 +- sql/share/korean/errmsg.txt | 2 +- sql/share/norwegian-ny/errmsg.txt | 2 +- sql/share/norwegian/errmsg.txt | 2 +- sql/share/polish/errmsg.txt | 2 +- sql/share/portuguese/errmsg.txt | 2 +- sql/share/romanian/errmsg.txt | 2 +- sql/share/russian/errmsg.txt | 2 +- sql/share/slovak/errmsg.txt | 2 +- sql/share/spanish/errmsg.txt | 2 +- sql/share/swedish/errmsg.txt | 2 +- sql/share/ukrainian/errmsg.txt | 2 +- sql/sql_show.cc | 27 ++++++++++++++++++--------- 34 files changed, 95 insertions(+), 52 deletions(-) delete mode 100644 mysql-test/r/identity.result delete mode 100644 mysql-test/t/identity.test diff --git a/Docs/manual.texi b/Docs/manual.texi index 4d12a2689fe..a439b17b847 100644 --- a/Docs/manual.texi +++ b/Docs/manual.texi @@ -46913,6 +46913,14 @@ not yet 100% confident in this code. @itemize @bullet @item +Fixed problem with @code{crash-me} and gcc 3.0.4. +@item +Fixed that @code{@@@@unknown_variable} doesn't hang server. +@item +Added @code{@@@@VERSION} as a synonym for @code{VERSION()}. +@item +@code{SHOW VARIABLES LIKE 'xxx'} is now case insensitive. +@item Fixed timeout for @code{GET_LOCK()} on HPUX with DCE threads. @item Fixed memory allocation bug in the glibc library used to build Linux diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 09a9fc0dd4c..ffce5f6bce7 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -675,7 +675,7 @@ static const char *default_options[]= "port","socket","compress","password","pipe", "timeout", "user", "init-command", "host", "database", "debug", "return-found-rows", "ssl-key" ,"ssl-cert" ,"ssl-ca" ,"ssl-capath", - "character-set-dir", "default-character-set", "interactive-timeout", + "character-sets-dir", "default-character-set", "interactive-timeout", "connect-timeout", "local-infile", "disable-local-infile", NullS }; diff --git a/myisam/myisampack.c b/myisam/myisampack.c index 81ae77738ea..cd18cebbda0 100644 --- a/myisam/myisampack.c +++ b/myisam/myisampack.c @@ -239,7 +239,6 @@ static struct option long_options[] = {"force", no_argument, 0, 'f'}, {"join", required_argument, 0, 'j'}, {"help", no_argument, 0, '?'}, - {"packlength",required_argument, 0, 'p'}, {"silent", no_argument, 0, 's'}, {"tmpdir", required_argument, 0, 'T'}, {"test", no_argument, 0, 't'}, @@ -251,7 +250,7 @@ static struct option long_options[] = static void print_version(void) { - printf("%s Ver 1.12 for %s on %s\n",my_progname,SYSTEM_TYPE,MACHINE_TYPE); + printf("%s Ver 1.13 for %s on %s\n",my_progname,SYSTEM_TYPE,MACHINE_TYPE); } static void usage(void) diff --git a/mysql-test/r/identity.result b/mysql-test/r/identity.result deleted file mode 100644 index 45968248d26..00000000000 --- a/mysql-test/r/identity.result +++ /dev/null @@ -1,4 +0,0 @@ -last_insert_id(345) -345 -@@IDENTITY last_insert_id() -345 345 diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index 099ea2fa109..419b2b4ce7e 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -47,6 +47,8 @@ test.t1 optimize status Table is already up to date Variable_name Value wait_timeout 28800 Variable_name Value +wait_timeout 28800 +Variable_name Value Name Type Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Create_options Comment Database mysql diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index ab60d5042b0..adf8100f052 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -23,3 +23,11 @@ c_id c_name c_country c_id c_name c_country 1 Bozo USA 4 Mr. Floppy GB +@@VERSION=version() +1 +last_insert_id(345) +345 +@@IDENTITY last_insert_id() +345 345 +@@IDENTITY +345 diff --git a/mysql-test/t/identity.test b/mysql-test/t/identity.test deleted file mode 100644 index 37183fd3b35..00000000000 --- a/mysql-test/t/identity.test +++ /dev/null @@ -1,2 +0,0 @@ -select last_insert_id(345); -select @@IDENTITY,last_insert_id(); diff --git a/mysql-test/t/show_check.test b/mysql-test/t/show_check.test index 0f07d577c0c..0981b85c91e 100644 --- a/mysql-test/t/show_check.test +++ b/mysql-test/t/show_check.test @@ -33,6 +33,7 @@ drop table t1; #show variables; show variables like "wait_timeout%"; +show variables like "WAIT_timeout%"; show variables like "this_doesn't_exists%"; show table status from test like "this_doesn't_exists%"; show databases; diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index 0499263467c..b3127402238 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -27,3 +27,14 @@ SELECT * FROM t1 WHERE c_id=@min_cid OR c_id=@max_cid OR c_id=666; ALTER TABLE t1 DROP PRIMARY KEY; select * from t1 where c_id=@min_cid OR c_id=@max_cid; drop table t1; + +# +# Test system variables +# + +select @@VERSION=version(); +select last_insert_id(345); +select @@IDENTITY,last_insert_id(); +select @@identity; +--error 1193 +select @@unknown_variable; diff --git a/sql/item_func.cc b/sql/item_func.cc index 2e54aa56b4b..6579825690f 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -59,7 +59,7 @@ bool Item_func::fix_fields(THD *thd,TABLE_LIST *tables) { Item **arg,**arg_end; - char buff[sizeof(double)]; // Max argument in function + char buff[STACK_BUFF_ALLOC]; // Max argument in function binary=0; used_tables_cache=0; const_item_cache=1; @@ -1058,7 +1058,7 @@ bool udf_handler::fix_fields(THD *thd,TABLE_LIST *tables,Item_result_field *func, uint arg_count, Item **arguments) { - char buff[sizeof(double)]; // Max argument in function + char buff[STACK_BUFF_ALLOC]; // Max argument in function DBUG_ENTER("Item_udf_func::fix_fields"); if (thd) @@ -2161,9 +2161,12 @@ bool Item_func_match::eq(const Item *item, bool binary_cmp) const Item *get_system_var(LEX_STRING name) { - if (!strcmp(name.str,"IDENTITY")) + if (!my_strcasecmp(name.str,"IDENTITY")) return new Item_int((char*) "@@IDENTITY", current_thd->insert_id(),21); - my_error(ER_UNKNOWN_SYSTEM_VARIABLE,MYF(0),name); + if (!my_strcasecmp(name.str,"VERSION")) + return new Item_string("@@VERSION",server_version, + (uint) strlen(server_version)); + net_printf(¤t_thd->net, ER_UNKNOWN_SYSTEM_VARIABLE, name); return 0; } diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 657ca3274cd..4cee7d04ef0 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -73,22 +73,30 @@ void kill_one_thread(THD *thd, ulong id); #define MAX_FIELDS_BEFORE_HASH 32 #define USER_VARS_HASH_SIZE 16 #define STACK_MIN_SIZE 8192 // Abort if less stack during eval. +#define STACK_BUFF_ALLOC 32 // For stack overrun checks #ifndef MYSQLD_NET_RETRY_COUNT #define MYSQLD_NET_RETRY_COUNT 10 // Abort read after this many int. #endif #define TEMP_POOL_SIZE 128 -/* The following parameters is to decide when to use an extra cache to - optimise seeks when reading a big table in sorted order */ +/* + The following parameters is to decide when to use an extra cache to + optimise seeks when reading a big table in sorted order +*/ #define MIN_FILE_LENGTH_TO_USE_ROW_CACHE (16L*1024*1024) #define MIN_ROWS_TO_USE_TABLE_CACHE 100 -// The following is used to decide if MySQL should use table scanning -// instead of reading with keys. The number says how many evaluation of the -// WHERE clause is comparable to reading one extra row from a table. +/* + The following is used to decide if MySQL should use table scanning + instead of reading with keys. The number says how many evaluation of the + WHERE clause is comparable to reading one extra row from a table. +*/ #define TIME_FOR_COMPARE 5 // 5 compares == one read -// Number of rows in a reference table when refereed through a not unique key. -// This value is only used when we don't know anything about the key -// distribution. + +/* + Number of rows in a reference table when refereed through a not unique key. + This value is only used when we don't know anything about the key + distribution. +*/ #define MATCHING_ROWS_IN_OTHER_TABLE 10 /* Don't pack string keys shorter than this (if PACK_KEYS=1 isn't used) */ diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index d1638bee16e..093954c202b 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -203,7 +203,7 @@ "S-Bí»ová chyba pøi zápisu na master",-A "-B®ádný sloupec nemá vytvoøen fulltextový index",-A "Nemohu prov-Bést zadaný pøíkaz, proto¾e existují aktivní zamèené tabulky nebo aktivní transakce",-A -"Nezn-Bámá systémová promìnná '%-.64'",-A +"Nezn-Bámá systémová promìnná '%-.64s'",-A "Tabulka '%-.64s' je ozna-Bèena jako poru¹ená a mìla by být opravena",-A "Tabulka '%-.64s' je ozna-Bèena jako poru¹ená a poslední (automatická?) oprava se nezdaøila",-A "Warning: Some non-transactional changed tables couldn't be rolled back", diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index 6585f717a78..6ee6e23a18e 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -197,7 +197,7 @@ "Netværksfejl ved skrivning til master", "Kan ikke finde en FULLTEXT nøgle som svarer til kolonne listen", "Kan ikke udføre den givne kommando fordi der findes aktive, låste tabeller eller fordi der udføres en transaktion", -"Ukendt systemvariabel '%-.64'", +"Ukendt systemvariabel '%-.64s'", "Tabellen '%-.64s' er markeret med fejl og bør repareres", "Tabellen '%-.64s' er markeret med fejl og sidste (automatiske?) REPAIR fejlede", "Advarsel: Visse data i tabeller der ikke understøtter transaktioner kunne ikke tilbagestilles", diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index d14400edc69..b857eb3104d 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -200,7 +200,7 @@ "Net fout tijdens schrijven naar master", "Kan geen FULLTEXT index vinden passend bij de kolom lijst", "Kan het gegeven commando niet uitvoeren, want u heeft actieve gelockte tabellen of een actieve transactie", -"Onbekende systeem variabele '%-.64'", +"Onbekende systeem variabele '%-.64s'", "Tabel '%-.64s' staat als gecrashed gemarkeerd en dient te worden gerepareerd", "Tabel '%-.64s' staat als gecrashed gemarkeerd en de laatste (automatische?) reparatie poging mislukte", "Waarschuwing: Roll back mislukt voor sommige buiten transacties gewijzigde tabellen", diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index 384d2c846c2..b67c1e1a0df 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -194,7 +194,7 @@ "Net error writing to master", "Can't find FULLTEXT index matching the column list", "Can't execute the given command because you have active locked tables or an active transaction", -"Unknown system variable '%-.64'", +"Unknown system variable '%-.64s'", "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", "Warning: Some non-transactional changed tables couldn't be rolled back", diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index 20891c7b001..d57f6871e12 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -198,7 +198,7 @@ "Net error writing to master", "Can't find FULLTEXT index matching the column list", "Can't execute the given command because you have active locked tables or an active transaction", -"Tundmatu süsteemne muutja '%-.64'", +"Tundmatu süsteemne muutja '%-.64s'", "Tabel '%-.64s' on märgitud vigaseks ja tuleb parandada", "Tabel '%-.64s' on märgitud vigaseks ja viimane (automaatne?) parandamiskatse ebaõnnestus", "Warning: Some non-transactional changed tables couldn't be rolled back", diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index 104e561d642..4848a3266bc 100644 --- a/sql/share/french/errmsg.txt +++ b/sql/share/french/errmsg.txt @@ -194,7 +194,7 @@ "Net error writing to master", "Can't find FULLTEXT index matching the column list", "Can't execute the given command because you have active locked tables or an active transaction", -"Unknown system variable '%-.64'", +"Unknown system variable '%-.64s'", "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", "Warning: Some non-transactional changed tables couldn't be rolled back", diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt index d0a08a1e7a8..fe76c757d11 100644 --- a/sql/share/german/errmsg.txt +++ b/sql/share/german/errmsg.txt @@ -197,7 +197,7 @@ "Netzfehler beim Schreiben zum Master", "Kann keinen FULLTEXT-Index finden der der Spaltenliste entspricht", "Kann das aktuelle Kommando wegen aktiver Tabellensperre oder aktiver Transaktion nicht ausführen", -"Unbekannte System-Variabel '%-.64'", +"Unbekannte System-Variabel '%-.64s'", "Tabelle '%-.64s' ist als defekt makiert und sollte repariert werden", "Tabelle '%-.64s' ist als defekt makiert und der letzte (automatische) Reparaturversuch schlug fehl.", "Warnung: Das Rollback konnte bei einigen Tabellen, die nicht mittels Transaktionen geändert wurden, nicht ausgeführt werden.", diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index f778cb857d7..b491b0ef1f9 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -194,7 +194,7 @@ "Net error writing to master", "Can't find FULLTEXT index matching the column list", "Can't execute the given command because you have active locked tables or an active transaction", -"Unknown system variable '%-.64'", +"Unknown system variable '%-.64s'", "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", "Warning: Some non-transactional changed tables couldn't be rolled back", diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index 6ff12c8b49e..fc6a9ba0643 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -196,7 +196,7 @@ "Net error writing to master", "Can't find FULLTEXT index matching the column list", "Can't execute the given command because you have active locked tables or an active transaction", -"Unknown system variable '%-.64'", +"Unknown system variable '%-.64s'", "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", "Warning: Some non-transactional changed tables couldn't be rolled back", diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt index 7a3daca9a59..3da78e82d99 100644 --- a/sql/share/italian/errmsg.txt +++ b/sql/share/italian/errmsg.txt @@ -194,7 +194,7 @@ "Errore di rete durante l'invio al master", "Impossibile trovare un indice FULLTEXT che corrisponda all'elenco delle colonne", "Impossibile eseguire il comando richiesto: tabelle sotto lock o transazione in atto", -"Variabile di sistema '%-.64' sconosciuta", +"Variabile di sistema '%-.64s' sconosciuta", "La tabella '%-.64s' e` segnalata come corrotta e deve essere riparata", "La tabella '%-.64s' e` segnalata come corrotta e l'ultima ricostruzione (automatica?) e` fallita", "Attenzione: Alcune delle modifiche alle tabelle non transazionali non possono essere ripristinate (roll back impossibile)", diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index fab60948943..dc2299e4336 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -196,7 +196,7 @@ "Net error writing to master", "Can't find FULLTEXT index matching the column list", "Can't execute the given command because you have active locked tables or an active transaction", -"Unknown system variable '%-.64'", +"Unknown system variable '%-.64s'", "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", "Warning: Some non-transactional changed tables couldn't be rolled back", diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index 0dac448e2b2..79bf767a3c8 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -194,7 +194,7 @@ "Net error writing to master", "Can't find FULLTEXT index matching the column list", "Can't execute the given command because you have active locked tables or an active transaction", -"Unknown system variable '%-.64'", +"Unknown system variable '%-.64s'", "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", "Warning: Some non-transactional changed tables couldn't be rolled back", diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index 78075c3990c..a583a541b71 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -196,7 +196,7 @@ "Net error writing to master", "Can't find FULLTEXT index matching the column list", "Can't execute the given command because you have active locked tables or an active transaction", -"Unknown system variable '%-.64'", +"Unknown system variable '%-.64s'", "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", "Warning: Some non-transactional changed tables couldn't be rolled back", diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index 997d667f812..85fa1f04f63 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -196,7 +196,7 @@ "Net error writing to master", "Can't find FULLTEXT index matching the column list", "Can't execute the given command because you have active locked tables or an active transaction", -"Unknown system variable '%-.64'", +"Unknown system variable '%-.64s'", "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", "Warning: Some non-transactional changed tables couldn't be rolled back", diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt index f317d99d48f..af484b4c850 100644 --- a/sql/share/polish/errmsg.txt +++ b/sql/share/polish/errmsg.txt @@ -198,7 +198,7 @@ "Net error writing to master", "Can't find FULLTEXT index matching the column list", "Can't execute the given command because you have active locked tables or an active transaction", -"Unknown system variable '%-.64'", +"Unknown system variable '%-.64s'", "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", "Warning: Some non-transactional changed tables couldn't be rolled back", diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt index a3ae06d193f..7737fe6b1fd 100644 --- a/sql/share/portuguese/errmsg.txt +++ b/sql/share/portuguese/errmsg.txt @@ -194,7 +194,7 @@ "Erro de rede na gravação do 'master'", "Não pode encontrar índice FULLTEXT que combine com a lista de colunas", "Não pode executar o comando dado porque você tem tabelas ativas travadas ou uma 'transaction' ativa", -"Variável de sistema '%-.64' desconhecida", +"Variável de sistema '%-.64s' desconhecida", "Tabela '%-.64s' está marcada como danificada e deve ser reparada", "Tabela '%-.64s' está marcada como danificada e a última reparação (automática?) falhou", "Aviso: Algumas tabelas não-transacionais alteradas não puderam ser reconstituídas ('rolled back')", diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index 26d9f34528a..e8927777b8a 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -198,7 +198,7 @@ "Net error writing to master", "Can't find FULLTEXT index matching the column list", "Can't execute the given command because you have active locked tables or an active transaction", -"Unknown system variable '%-.64'", +"Unknown system variable '%-.64s'", "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", "Warning: Some non-transactional changed tables couldn't be rolled back", diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt index c02c47696b0..5c94f2ee31b 100644 --- a/sql/share/russian/errmsg.txt +++ b/sql/share/russian/errmsg.txt @@ -197,7 +197,7 @@ "óÅÔÅ×ÁÑ ÏÛÉÂËÁ ÐÒÉ ÐÉÓÁÎÉÉ ÍÁÓÔÅÒÕ", "FULLTEXT ÉÎÄÅËÓ, ÓÏÏÔ×ÅÔÓÔ×ÕÀÝÉÊ ÚÁÄÁÎÎÏÍÕ ÓÐÉÓËÕ ÓÔÏÌÂÃÏ×, ÎÅ ÎÁÊÄÅÎ", "îÅ ÍÏÇÕ ×ÙÐÏÌÎÉÔØ ËÏÍÍÁÎÄÕ ÉÚ-ÚÁ ÁËÔÉ×ÎÙÈ locked ÔÁÂÌÉà ÉÌÉ ÁËÔÉ×ÎÏÊ ÔÒÁÎÚÁËÃÉÉ", -"îÅÉÚ×ÅÓÔÎÁÑ ÓÉÓÔÅÍÎÁÑ ÐÅÒÅÍÅÎÎÁÑ '%-.64'", +"îÅÉÚ×ÅÓÔÎÁÑ ÓÉÓÔÅÍÎÁÑ ÐÅÒÅÍÅÎÎÁÑ '%-.64s'", "ôÁÂÌÉÃÁ '%-.64s' ÐÏÍÅÞÅÎÁ ËÁË ÉÓÐÏÒÞÅÎÎÁÑ É ÄÏÌÖÎÁ ÂÙÔØ ÉÓÐÒÁ×ÌÅÎÁ", "ôÁÂÌÉÃÁ '%-.64s' ÐÏÍÅÞÅÎÁ ËÁË ÉÓÐÏÒÞÅÎÎÁÑ É ÐÏÓÌÅÄÎÑÑ ÐÏÐÙÔËÁ ÉÓÐÒÁ×ÌÅÎÉÑ (Á×ÔÏÍÁÔÉÞÅÓËÁÑ?) ÎÅ ÕÄÁÌÁÓØ", "ðÒÅÄÕÐÒÅÖÄÅÎÉÅ: ÎÅËÏÔÏÒÙÅ ÎÅÔÒÁÎÚÁËÃÉÏÎÎÙÅ ÔÁÂÌÉÃÙ ÎÅ ÐÏÄÞÉÎÑÀÔÓÑ ROLLBACK", diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index 189db8a66f8..3f96880bda1 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -202,7 +202,7 @@ "Net error writing to master", "Can't find FULLTEXT index matching the column list", "Can't execute the given command because you have active locked tables or an active transaction", -"Unknown system variable '%-.64'", +"Unknown system variable '%-.64s'", "Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed", "Warning: Some non-transactional changed tables couldn't be rolled back", diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index 57d4ac9646a..c718ac93fc4 100644 --- a/sql/share/spanish/errmsg.txt +++ b/sql/share/spanish/errmsg.txt @@ -195,7 +195,7 @@ "Error de red escribiendo para el master", "No puedo encontrar índice FULLTEXT correspondiendo a la lista de columnas", "No puedo ejecutar el comando dado porque tienes tablas bloqueadas o una transición activa", -"Desconocida variable de sistema '%-.64'", +"Desconocida variable de sistema '%-.64s'", "Tabla '%-.64s' está marcada como crashed y debe ser reparada", "Tabla '%-.64s' está marcada como crashed y la última reparación (automactica?) falló", "Aviso: Algunas tablas no transancionales no pueden tener rolled back", diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index 1b7b6012a39..ce6bb0e80f0 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -194,7 +194,7 @@ "Fick nätverksfel vid skrivning till master", "Hittar inte ett FULLTEXT index i kolumnlistan", "Kan inte exekvera kommandot emedan du har en låst tabell eller an aktiv transaktion", -"Okänd system variabel '%-.64'", +"Okänd system variabel '%-.64s'", "Tabell '%-.64s' är crashad och bör repareras med REPAIR TABLE", "Tabell '%-.64s' är crashad och senast (automatiska?) reparation misslyckades", "Warning: Några icke transaktionella tabeller kunde inte återställas vid ROLLBACK", diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt index 4508fc75c27..b167ebd5f3d 100644 --- a/sql/share/ukrainian/errmsg.txt +++ b/sql/share/ukrainian/errmsg.txt @@ -199,7 +199,7 @@ "íÅÒÅÖÅ×Á ÐÏÍÉÌËÁ ÚÁÐÉÓÕ ÄÏ ÇÏÌÏ×ÎÏÇÏ", "îÅ ÍÏÖÕ ÚÎÁÊÔÉ FULLTEXT ¦ÎÄÅËÓ, ÝÏ ×¦ÄÐÏצÄÁ¤ ÐÅÒÅ̦ËÕ ÓÔÏ×Âæ×", "îÅ ÍÏÖÕ ×ÉËÏÎÁÔÉ ÐÏÄÁÎÕ ËÏÍÁÎÄÕ ÔÏÍÕ, ÝÏ ÔÁÂÌÉÃÑ ÚÁÂÌÏËÏ×ÁÎÁ ÁÂÏ ×ÉËÏÎÕ¤ÔØÓÑ ÔÒÁÎÚÁËæÑ", -"îÅצÄÏÍÁ ÓÉÓÔÅÍÎÁ ÚͦÎÎÁ '%-.64'", +"îÅצÄÏÍÁ ÓÉÓÔÅÍÎÁ ÚͦÎÎÁ '%-.64s'", "ôÁÂÌÉÃÀ '%-.64s' ÍÁÒËÏ×ÁÎÏ ÑË Ú¦ÐÓÏ×ÁÎÕ ÔÁ §§ ÐÏÔÒ¦ÂÎÏ ×¦ÄÎÏ×ÉÔÉ", "ôÁÂÌÉÃÀ '%-.64s' ÍÁÒËÏ×ÁÎÏ ÑË Ú¦ÐÓÏ×ÁÎÕ ÔÁ ÏÓÔÁÎΤ (Á×ÔÏÍÁÔÉÞÎÅ?) צÄÎÏ×ÌÅÎÎÑ ÎÅ ×ÄÁÌÏÓÑ", "úÁÓÔÅÒÅÖÅÎÎÑ: äÅÑ˦ ÎÅÔÒÁÎÚÁËæÊΦ ÚͦÎÉ ÔÁÂÌÉÃØ ÎÅ ÍÏÖÎÁ ÂÕÄÅ ÐÏ×ÅÒÎÕÔÉ", diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 018b43b11c8..8cfac1675b0 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -567,21 +567,30 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) { packet->length(0); net_store_data(packet, table->table_name); - // a hack - we need to reserve some space for the length before - // we know what it is - let's assume that the length of create table - // statement will fit into 3 bytes ( 16 MB max :-) ) + /* + A hack - we need to reserve some space for the length before + we know what it is - let's assume that the length of create table + statement will fit into 3 bytes ( 16 MB max :-) ) + */ ulong store_len_offset = packet->length(); packet->length(store_len_offset + 4); if (store_create_info(thd, table, packet)) DBUG_RETURN(-1); ulong create_len = packet->length() - store_len_offset - 4; if (create_len > 0x00ffffff) // better readable in HEX ... - DBUG_RETURN(1); // just in case somebody manages to create a table - // with *that* much stuff in the definition + { + /* + Just in case somebody manages to create a table + with *that* much stuff in the definition + */ + DBUG_RETURN(1); + } - // now we have to store the length in three bytes, even if it would fit - // into fewer, so we cannot use net_store_data() anymore, - // and do it ourselves + /* + Now we have to store the length in three bytes, even if it would fit + into fewer bytes, so we cannot use net_store_data() anymore, + and do it ourselves + */ char* p = (char*)packet->ptr() + store_len_offset; *p++ = (char) 253; // The client the length is stored using 3-bytes int3store(p, create_len); @@ -1125,7 +1134,7 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables) pthread_mutex_lock(&LOCK_status); for (i=0; variables[i].name; i++) { - if (!(wild && wild[0] && wild_compare(variables[i].name,wild))) + if (!(wild && wild[0] && wild_case_compare(variables[i].name,wild))) { packet2.length(0); net_store_data(&packet2,variables[i].name); From f98bf0a06514fbdefa4f4fe9a8cd98aefb83f266 Mon Sep 17 00:00:00 2001 From: "monty@tik.mysql.fi" <> Date: Fri, 19 Apr 2002 11:38:58 +0300 Subject: [PATCH 14/17] Fixed bug in @@unknown_variable --- sql/item_func.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/item_func.cc b/sql/item_func.cc index 6579825690f..9180cccabcf 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2167,6 +2167,6 @@ Item *get_system_var(LEX_STRING name) if (!my_strcasecmp(name.str,"VERSION")) return new Item_string("@@VERSION",server_version, (uint) strlen(server_version)); - net_printf(¤t_thd->net, ER_UNKNOWN_SYSTEM_VARIABLE, name); + net_printf(¤t_thd->net, ER_UNKNOWN_SYSTEM_VARIABLE, name.str); return 0; } From f6c0b2c4484b97b72467b0e837a44c2654e7fc61 Mon Sep 17 00:00:00 2001 From: "monty@work.mysql.com" <> Date: Sun, 21 Apr 2002 12:06:34 +0200 Subject: [PATCH 15/17] Fixing Innodb test results --- mysql-test/r/innodb.result | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index d13347b7903..0930e3aa5fd 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -135,7 +135,7 @@ test.t1 optimize error The handler for the table doesn't support check/repair Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Comment t1 0 PRIMARY 1 id A 87 NULL NULL t1 1 parent_id 1 parent_id A 43 NULL NULL -t1 1 level 1 level A 8 NULL NULL +t1 1 level 1 level A 6 NULL NULL gesuchnr benutzer_id 1 1 2 1 From 1016a08dc9b1ad075aaa2718707e14e3c5d9c0e2 Mon Sep 17 00:00:00 2001 From: "monty@tik.mysql.fi" <> Date: Mon, 22 Apr 2002 10:34:46 +0300 Subject: [PATCH 16/17] Fixed that IF is case insensitive if 2 and 3 arguments are case insensitive. Added copyright messages to some files that was missing it. --- Docs/manual.texi | 14 ++++++++++++-- dbug/Makefile.am | 7 ++++--- dbug/monty.doc | 8 ++++++++ mysql-test/t/func_test.test | 11 ----------- sql/item_cmpfunc.cc | 4 ++++ strings/bfill.c | 17 +++++++++++++++++ strings/bmove.c | 17 +++++++++++++++++ strings/ctype-ujis.c | 17 +++++++++++++++++ strings/strend.c | 17 +++++++++++++++++ strings/strstr.c | 17 +++++++++++++++++ strings/strxmov.c | 17 +++++++++++++++++ strings/strxnmov.c | 17 +++++++++++++++++ 12 files changed, 147 insertions(+), 16 deletions(-) diff --git a/Docs/manual.texi b/Docs/manual.texi index a439b17b847..bf5bb1a9d3d 100644 --- a/Docs/manual.texi +++ b/Docs/manual.texi @@ -29916,6 +29916,9 @@ stored into a temporary table) is calculated in MySQL Version @item expr2 or expr3 returns an integer @tab integer @end multitable +If expr2 and expr3 are strings, then the result is case sensitive if +both strings are case sensitive. (Starting from 3.23.51) + @findex CASE @item CASE value WHEN [compare-value] THEN result [WHEN [compare-value] THEN result ...] [ELSE result] END @item CASE WHEN [condition] THEN result [WHEN [condition] THEN result ...] [ELSE result] END @@ -46854,6 +46857,7 @@ users use this code as the rest of the code and because of this we are not yet 100% confident in this code. @menu +* News-3.23.51:: * News-3.23.50:: Changes in release 3.23.50 * News-3.23.49:: Changes in release 3.23.49 * News-3.23.48:: Changes in release 3.23.48 @@ -46908,9 +46912,15 @@ not yet 100% confident in this code. * News-3.23.0:: Changes in release 3.23.0 @end menu -@node News-3.23.50, News-3.23.49, News-3.23.x, News-3.23.x -@appendixsubsec Changes in release 3.23.50 +@node News-3.23.51, News-3.23.50, News-3.23.x, News-3.23.x +@appendixsubsec Changes in release 3.23.51 +@itemize @bullet +Fixed the result from @code{IF()} is case in-sensitive if the 2 and +third arguments are case sensitive. +@end itemize +@node News-3.23.50, News-3.23.49, News-3.23.51, News-3.23.x +@appendixsubsec Changes in release 3.23.50 @itemize @bullet @item Fixed problem with @code{crash-me} and gcc 3.0.4. diff --git a/dbug/Makefile.am b/dbug/Makefile.am index 7add2fb6583..c789019cc6b 100644 --- a/dbug/Makefile.am +++ b/dbug/Makefile.am @@ -20,8 +20,9 @@ LDADD = libdbug.a ../strings/libmystrings.a pkglib_LIBRARIES = libdbug.a noinst_HEADERS = dbug_long.h libdbug_a_SOURCES = dbug.c sanity.c -EXTRA_DIST = example1.c example2.c example3.c user.r monty.doc readme.prof \ - main.c factorial.c +EXTRA_DIST = example1.c example2.c example3.c \ + user.r monty.doc readme.prof \ + main.c factorial.c dbug_analyze.c OMIT_DEPENDENCIES = pthread.h stdio.h __stdio.h stdlib.h __stdlib.h math.h\ __math.h time.h __time.h unistd.h __unistd.h types.h \ @@ -32,7 +33,7 @@ OMIT_DEPENDENCIES = pthread.h stdio.h __stdio.h stdlib.h __stdlib.h math.h\ sleep.h specific.h version.h pwd.h timers.h uio.h \ cdefs.h machdep.h signal.h __signal.h util.h -# Must be linked with libs thta are not compiled yet +# Must be linked with libs that are not compiled yet extra_progs: factorial dbug_analyze factorial: main.o factorial.o diff --git a/dbug/monty.doc b/dbug/monty.doc index f6d8bdff9cd..1c102e1c31e 100644 --- a/dbug/monty.doc +++ b/dbug/monty.doc @@ -10,3 +10,11 @@ giving a double ':'. (As in "O,c::\tmp\log") DBUG_DUMP("keyword",memory-position,length) writes a hexdump of the given memory-area to the outputfile. + +All changes that I or other people at MySQL AB have done to all files +in the dbug library (Mainly in dbug.c, dbug_analyze.c, dbug_long.h, +dbug.h) are put in public domain, as the rest of the dbug.c library) + +To my knowledge, all code in dbug library are in public domain. + +Michael Widenius diff --git a/mysql-test/t/func_test.test b/mysql-test/t/func_test.test index 0439a96f077..ec44009b1a6 100644 --- a/mysql-test/t/func_test.test +++ b/mysql-test/t/func_test.test @@ -11,7 +11,6 @@ select 'abc' like '%c','abcabc' like '%c', "ab" like "", "ab" like "a", "ab" li select "Det här är svenska" regexp "h[[:alpha:]]+r", "aba" regexp "^(a|b)*$"; select "aba" regexp concat("^","a"); select !0,NOT 0=1,!(0=0),1 AND 1,1 && 0,0 OR 1,1 || NULL, 1=1 or 1=1 and 1=0; -select IF(0,"ERROR","this"),IF(1,"is","ERROR"),IF(NULL,"ERROR","a"),IF(1,2,3)|0,IF(1,2.0,3.0)+0 ; select 2 between 1 and 3, "monty" between "max" and "my",2=2 and "monty" between "max" and "my" and 3=3; select 'b' between 'a' and 'c', 'B' between 'a' and 'c'; select 2 in (3,2,5,9,5,1),"monty" in ("david","monty","allan"), 1.2 in (1.4,1.2,1.0); @@ -24,13 +23,3 @@ select -1.49 or -1.49,0.6 or 0.6; select 5 between 0 and 10 between 0 and 1,(5 between 0 and 10) between 0 and 1; select 1 and 2 between 2 and 10, 2 between 2 and 10 and 1; select 1 and 0 or 2, 2 or 1 and 0; - -# -# Problem with IF() -# - -drop table if exists t1; -create table t1 (num double(12,2)); -insert into t1 values (144.54); -select sum(if(num is null,0.00,num)) from t1; -drop table t1; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 373aede7b6b..2b7f4cb6c40 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -490,8 +490,12 @@ Item_func_if::fix_length_and_dec() decimals=max(args[1]->decimals,args[2]->decimals); enum Item_result arg1_type=args[1]->result_type(); enum Item_result arg2_type=args[2]->result_type(); + binary=1; if (arg1_type == STRING_RESULT || arg2_type == STRING_RESULT) + { cached_result_type = STRING_RESULT; + binary=args[1]->binary | args[2]->binary; + } else if (arg1_type == REAL_RESULT || arg2_type == REAL_RESULT) cached_result_type = REAL_RESULT; else diff --git a/strings/bfill.c b/strings/bfill.c index ac5d3096b14..9f5db7201d0 100644 --- a/strings/bfill.c +++ b/strings/bfill.c @@ -1,3 +1,20 @@ +/* Copyright (C) 2002 MySQL AB + + This library 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; either + version 2 of the License, or (at your option) any later version. + + This library 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. + + 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 */ + /* File : bfill.c Author : Richard A. O'Keefe. Michael Widenius; ifdef MC68000 diff --git a/strings/bmove.c b/strings/bmove.c index f63ff0bd4f8..466bf74db75 100644 --- a/strings/bmove.c +++ b/strings/bmove.c @@ -1,3 +1,20 @@ +/* Copyright (C) 2002 MySQL AB + + This library 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; either + version 2 of the License, or (at your option) any later version. + + This library 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. + + 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 */ + /* File : bmove.c Author : Richard A. O'Keefe. Michael Widenius; ifdef MC68000 diff --git a/strings/ctype-ujis.c b/strings/ctype-ujis.c index d994a2e5e96..5356978976f 100644 --- a/strings/ctype-ujis.c +++ b/strings/ctype-ujis.c @@ -1,3 +1,20 @@ +/* Copyright (C) 2002 MySQL AB & tommy@valley.ne.jp. + + This library 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; either + version 2 of the License, or (at your option) any later version. + + This library 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. + + 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 */ + /* This file is for Japanese EUC charset, and created by tommy@valley.ne.jp. */ diff --git a/strings/strend.c b/strings/strend.c index 18b9d1fbd0d..3affb9bd5f6 100644 --- a/strings/strend.c +++ b/strings/strend.c @@ -1,3 +1,20 @@ +/* Copyright (C) 2002 MySQL AB + + This library 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; either + version 2 of the License, or (at your option) any later version. + + This library 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. + + 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 */ + /* File : strend.c Author : Richard A. O'Keefe. Updated: 23 April 1984 diff --git a/strings/strstr.c b/strings/strstr.c index 572bf88c95c..01b29db0068 100644 --- a/strings/strstr.c +++ b/strings/strstr.c @@ -1,3 +1,20 @@ +/* Copyright (C) 2002 MySQL AB + + This library 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; either + version 2 of the License, or (at your option) any later version. + + This library 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. + + 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 */ + /* File : strstr.c Author : Monty Updated: 1986.11.24 diff --git a/strings/strxmov.c b/strings/strxmov.c index 7ee1d303ee8..3ef120a691e 100644 --- a/strings/strxmov.c +++ b/strings/strxmov.c @@ -1,3 +1,20 @@ +/* Copyright (C) 2002 MySQL AB + + This library 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; either + version 2 of the License, or (at your option) any later version. + + This library 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. + + 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 */ + /* File : strxmov.c Author : Richard A. O'Keefe. Updated: 25 may 1984 diff --git a/strings/strxnmov.c b/strings/strxnmov.c index b55a2e0ab79..ec3b6fe71e8 100644 --- a/strings/strxnmov.c +++ b/strings/strxnmov.c @@ -1,3 +1,20 @@ +/* Copyright (C) 2002 MySQL AB + + This library 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; either + version 2 of the License, or (at your option) any later version. + + This library 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. + + 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 */ + /* File : strxnmov.c Author : Richard A. O'Keefe. Updated: 2 June 1984 From ecf2c4e15a677a9f33ba8e7d6b2eb6a9da6538e4 Mon Sep 17 00:00:00 2001 From: "monty@tik.mysql.fi" <> Date: Mon, 22 Apr 2002 23:41:55 +0300 Subject: [PATCH 17/17] New if tests --- mysql-test/r/func_if.result | 35 +++++++++++++++++++++++++++++++++++ mysql-test/t/func_if.test | 30 ++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 mysql-test/r/func_if.result create mode 100644 mysql-test/t/func_if.test diff --git a/mysql-test/r/func_if.result b/mysql-test/r/func_if.result new file mode 100644 index 00000000000..64ee8c67def --- /dev/null +++ b/mysql-test/r/func_if.result @@ -0,0 +1,35 @@ +IF(0,"ERROR","this") IF(1,"is","ERROR") IF(NULL,"ERROR","a") IF(1,2,3)|0 IF(1,2.0,3.0)+0 +this is a 2 2.0 +s +a +A +a +aa +AA +aaa +BBB +s +a +A +a +aa +AA +aaa +BBB +s +A +AA +BBB +a +a +aa +aaa +s +A +AA +a +a +aa +aaa +sum(if(num is null,0.00,num)) +nan diff --git a/mysql-test/t/func_if.test b/mysql-test/t/func_if.test new file mode 100644 index 00000000000..c5cc73ecd1f --- /dev/null +++ b/mysql-test/t/func_if.test @@ -0,0 +1,30 @@ +# +# Init section +# +drop table if exists t1; + +# +# Simple IF tests +# + +select IF(0,"ERROR","this"),IF(1,"is","ERROR"),IF(NULL,"ERROR","a"),IF(1,2,3)|0,IF(1,2.0,3.0)+0 ; + +# +# Test of IF and case-sensitiveness +# +CREATE TABLE t1 (st varchar(255) NOT NULL, u int(11) NOT NULL) TYPE=MyISAM; +INSERT INTO t1 VALUES ('a',1),('A',1),('aa',1),('AA',1),('a',1),('aaa',0),('BBB',0); +select if(1,st,st) s from t1 order by s; +select if(u=1,st,st) s from t1 order by s; +select if(u=1,binary st,st) s from t1 order by s; +select if(u=1,st,binary st) s from t1 where st like "%a%" order by s; +drop table t1; + +# +# Problem with IF() +# + +create table t1 (num double(12,2)); +insert into t1 values (144.54); +select sum(if(num is null,0.00,num)) from t1; +drop table t1;