From a8a5e98ec6a1170173d897b0da0d39866c79c7ba Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 30 Aug 2005 19:19:28 +0400 Subject: [PATCH 01/18] Fixes bug #5588. vio_was_interrupted() function was added to detect read timeout properly on win32. include/my_global.h: Added win32 specific socket timeout error code. include/violite.h: Added vio_was_interrupted function that returns true if operation was not completed due to timeout. sql/mini_client.cc: added a check that replication read was not completed due to timeout. sql/net_serv.cc: net->last_errno should be equal to ER_NET_READ_INTERRUPTED in case if read operation was not completed due to timeout. vio/vio.c: added initialization code for vio_was_interrupted() function. vio/viosocket.c: Added vio_was_interrupted function that returns true if operation was not completed due to timeout. --- include/my_global.h | 3 +++ include/violite.h | 4 ++++ sql/mini_client.cc | 2 +- sql/net_serv.cc | 2 +- vio/vio.c | 2 ++ vio/viosocket.c | 9 +++++++++ 6 files changed, 20 insertions(+), 2 deletions(-) diff --git a/include/my_global.h b/include/my_global.h index e2a97667a1f..4b2e27aa3f6 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -760,6 +760,7 @@ typedef off_t os_off_t; #define socket_errno WSAGetLastError() #define SOCKET_EINTR WSAEINTR #define SOCKET_EAGAIN WSAEINPROGRESS +#define SOCKET_ETIMEDOUT WSAETIMEDOUT #define SOCKET_EWOULDBLOCK WSAEINPROGRESS #define SOCKET_ENFILE ENFILE #define SOCKET_EMFILE EMFILE @@ -767,6 +768,7 @@ typedef off_t os_off_t; #define socket_errno sock_errno() #define SOCKET_EINTR SOCEINTR #define SOCKET_EAGAIN SOCEINPROGRESS +#define SOCKET_ETIMEDOUT SOCKET_EINTR #define SOCKET_EWOULDBLOCK SOCEWOULDBLOCK #define SOCKET_ENFILE SOCENFILE #define SOCKET_EMFILE SOCEMFILE @@ -776,6 +778,7 @@ typedef off_t os_off_t; #define closesocket(A) close(A) #define SOCKET_EINTR EINTR #define SOCKET_EAGAIN EAGAIN +#define SOCKET_ETIMEDOUT SOCKET_EINTR #define SOCKET_EWOULDBLOCK EWOULDBLOCK #define SOCKET_ENFILE ENFILE #define SOCKET_EMFILE EMFILE diff --git a/include/violite.h b/include/violite.h index 6c4a42b1a53..23fd694d355 100644 --- a/include/violite.h +++ b/include/violite.h @@ -62,6 +62,8 @@ int vio_fastsend(Vio *vio); int vio_keepalive(Vio *vio, my_bool onoff); /* Whenever we should retry the last read/write operation. */ my_bool vio_should_retry(Vio *vio); +/* Check that operation was timed out */ +my_bool vio_was_interrupted(Vio *vio); /* Short text description of the socket for those, who are curious.. */ const char* vio_description(Vio *vio); /* Return the type of the connection */ @@ -134,6 +136,7 @@ Vio *new_VioSSL(struct st_VioSSLAcceptorFd *fd, Vio *sd, int state); #define vio_fastsend(vio) (vio)->fastsend(vio) #define vio_keepalive(vio, set_keep_alive) (vio)->viokeepalive(vio, set_keep_alive) #define vio_should_retry(vio) (vio)->should_retry(vio) +#define vio_was_interrupted(vio) (vio)->was_interrupted(vio) #define vio_close(vio) ((vio)->vioclose)(vio) #define vio_peer_addr(vio, buf, prt) (vio)->peer_addr(vio, buf, prt) #define vio_in_addr(vio, in) (vio)->in_addr(vio, in) @@ -175,6 +178,7 @@ struct st_vio my_bool (*peer_addr)(Vio*, char *, uint16*); void (*in_addr)(Vio*, struct in_addr*); my_bool (*should_retry)(Vio*); + my_bool (*was_interrupted)(Vio*); int (*vioclose)(Vio*); void (*timeout)(Vio*, unsigned int timeout); void *ssl_arg; diff --git a/sql/mini_client.cc b/sql/mini_client.cc index 86d50dc9a0e..cd00db5c7df 100644 --- a/sql/mini_client.cc +++ b/sql/mini_client.cc @@ -399,7 +399,7 @@ mc_net_safe_read(MYSQL *mysql) { DBUG_PRINT("error",("Wrong connection or packet. fd: %s len: %d", vio_description(net->vio),len)); - if (socket_errno != SOCKET_EINTR) + if (!vio_was_interrupted(net->vio)) { mc_end_server(mysql); if (net->last_errno != ER_NET_PACKET_TOO_LARGE) diff --git a/sql/net_serv.cc b/sql/net_serv.cc index c527ee1eb76..1e66bfc3e19 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -700,7 +700,7 @@ my_real_read(NET *net, ulong *complen) len= packet_error; net->error=2; /* Close socket */ #ifdef MYSQL_SERVER - net->last_errno= (interrupted ? ER_NET_READ_INTERRUPTED : + net->last_errno= (vio_was_interrupted(net->vio) ? ER_NET_READ_INTERRUPTED : ER_NET_READ_ERROR); #endif goto end; diff --git a/vio/vio.c b/vio/vio.c index 2b745ab3ec6..6f0587ad272 100644 --- a/vio/vio.c +++ b/vio/vio.c @@ -50,6 +50,7 @@ void vio_reset(Vio* vio, enum enum_vio_type type, vio->fastsend =vio_ssl_fastsend; vio->viokeepalive =vio_ssl_keepalive; vio->should_retry =vio_ssl_should_retry; + vio->was_interrupted=vio_was_interrupted; vio->vioclose =vio_ssl_close; vio->peer_addr =vio_ssl_peer_addr; vio->in_addr =vio_ssl_in_addr; @@ -67,6 +68,7 @@ void vio_reset(Vio* vio, enum enum_vio_type type, vio->fastsend =vio_fastsend; vio->viokeepalive =vio_keepalive; vio->should_retry =vio_should_retry; + vio->was_interrupted=vio_was_interrupted; vio->vioclose =vio_close; vio->peer_addr =vio_peer_addr; vio->in_addr =vio_in_addr; diff --git a/vio/viosocket.c b/vio/viosocket.c index f45c9dd98c4..7ea130c9949 100644 --- a/vio/viosocket.c +++ b/vio/viosocket.c @@ -216,6 +216,15 @@ vio_should_retry(Vio * vio __attribute__((unused))) } +my_bool +vio_was_interrupted(Vio * vio __attribute__((unused))) +{ + int en = socket_errno; + return (en == SOCKET_EAGAIN || en == SOCKET_EINTR || + en == SOCKET_EWOULDBLOCK || en == SOCKET_ETIMEDOUT); +} + + int vio_close(Vio * vio) { int r; From 1f776a5a45f84dfb4c4e28ef618d7edf1ab048de Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 6 Sep 2005 22:56:16 +0400 Subject: [PATCH 02/18] Fixes a problem with patch 1.2140, that prevented libmysqld to be built successfully. libmysqld/lib_vio.c: Added a copy of vio_was_interrupted() from viosocket.c, for successful build of libmysqld that uses own set of vio*() functions. --- libmysqld/lib_vio.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libmysqld/lib_vio.c b/libmysqld/lib_vio.c index ccad6ac8b7e..0f5f7fda550 100644 --- a/libmysqld/lib_vio.c +++ b/libmysqld/lib_vio.c @@ -181,6 +181,15 @@ vio_should_retry(Vio * vio __attribute__((unused))) } +my_bool +vio_was_interrupted(Vio * vio __attribute__((unused))) +{ + int en = socket_errno; + return (en == SOCKET_EAGAIN || en == SOCKET_EINTR || + en == SOCKET_EWOULDBLOCK || en == SOCKET_ETIMEDOUT); +} + + int vio_close(Vio * vio) { return(0); From 22b3e6f8823f78e40363d48ae44b7a57d06d2554 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 7 Sep 2005 15:57:14 +0400 Subject: [PATCH 03/18] Fixes bug #5588. Additions after merge from 4.0. sql-common/client.c: Fixes bug #5588. checks if operation was timed out. vio/vio.c: Added vio_was_interrupted() function references to detect timed out operation properly on win32. vio/vio_priv.h: Added vio_ssl_was_interrupted() function that detects timed out operation properly on win32. vio/viosocket.c: Minor changes to follow up the coding standard. vio/viossl.c: Added vio_ssl_was_interrupted() function that detects timed out operation properly on win32. --- sql-common/client.c | 2 +- vio/vio.c | 4 +++- vio/vio_priv.h | 2 ++ vio/viosocket.c | 4 ++-- vio/viossl.c | 9 +++++++++ 5 files changed, 17 insertions(+), 4 deletions(-) diff --git a/sql-common/client.c b/sql-common/client.c index 73e136f7366..3979b9304f7 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -602,7 +602,7 @@ net_safe_read(MYSQL *mysql) DBUG_PRINT("error",("Wrong connection or packet. fd: %s len: %d", vio_description(net->vio),len)); #ifdef MYSQL_SERVER - if (vio_errno(net->vio) == SOCKET_EINTR) + if (vio_was_interrupted(net->vio)) return (packet_error); #endif /*MYSQL_SERVER*/ end_server(mysql); diff --git a/vio/vio.c b/vio/vio.c index 2d5cb711ffc..45572b93ed6 100644 --- a/vio/vio.c +++ b/vio/vio.c @@ -50,6 +50,7 @@ void vio_reset(Vio* vio, enum enum_vio_type type, vio->fastsend =vio_fastsend; vio->viokeepalive =vio_keepalive; vio->should_retry =vio_should_retry; + vio->was_interrupted=vio_was_interrupted; vio->vioclose =vio_close_pipe; vio->peer_addr =vio_peer_addr; vio->in_addr =vio_in_addr; @@ -69,6 +70,7 @@ void vio_reset(Vio* vio, enum enum_vio_type type, vio->fastsend =vio_fastsend; vio->viokeepalive =vio_keepalive; vio->should_retry =vio_should_retry; + vio->was_interrupted=vio_was_interrupted; vio->vioclose =vio_close_shared_memory; vio->peer_addr =vio_peer_addr; vio->in_addr =vio_in_addr; @@ -88,7 +90,7 @@ void vio_reset(Vio* vio, enum enum_vio_type type, vio->fastsend =vio_ssl_fastsend; vio->viokeepalive =vio_ssl_keepalive; vio->should_retry =vio_ssl_should_retry; - vio->was_interrupted=vio_was_interrupted; + vio->was_interrupted=vio_ssl_was_interrupted; vio->vioclose =vio_ssl_close; vio->peer_addr =vio_ssl_peer_addr; vio->in_addr =vio_ssl_in_addr; diff --git a/vio/vio_priv.h b/vio/vio_priv.h index 3a75a08021d..c1c78cc6efa 100644 --- a/vio/vio_priv.h +++ b/vio/vio_priv.h @@ -39,6 +39,8 @@ int vio_ssl_fastsend(Vio *vio); int vio_ssl_keepalive(Vio *vio, my_bool onoff); /* Whenever we should retry the last read/write operation. */ my_bool vio_ssl_should_retry(Vio *vio); +/* Check that operation was timed out */ +my_bool vio_ssl_was_interrupted(Vio *vio); /* When the workday is over... */ int vio_ssl_close(Vio *vio); /* Return last error number */ diff --git a/vio/viosocket.c b/vio/viosocket.c index ca384a57967..0f1abfeea46 100644 --- a/vio/viosocket.c +++ b/vio/viosocket.c @@ -197,9 +197,9 @@ vio_should_retry(Vio * vio __attribute__((unused))) my_bool -vio_was_interrupted(Vio * vio __attribute__((unused))) +vio_was_interrupted(Vio *vio __attribute__((unused))) { - int en = socket_errno; + int en= socket_errno; return (en == SOCKET_EAGAIN || en == SOCKET_EINTR || en == SOCKET_EWOULDBLOCK || en == SOCKET_ETIMEDOUT); } diff --git a/vio/viossl.c b/vio/viossl.c index 2f608209a53..a3a2e7190bd 100644 --- a/vio/viossl.c +++ b/vio/viossl.c @@ -184,6 +184,15 @@ vio_ssl_should_retry(Vio * vio __attribute__((unused))) } +my_bool +vio_ssl_was_interrupted(Vio *vio __attribute__((unused))) +{ + int en= socket_errno; + return (en == SOCKET_EAGAIN || en == SOCKET_EINTR || + en == SOCKET_EWOULDBLOCK || en == SOCKET_ETIMEDOUT); +} + + int vio_ssl_close(Vio * vio) { int r; From d65a24bb7c07537298bd3520d7c9b0fc0f3035e6 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 7 Sep 2005 20:23:07 +0200 Subject: [PATCH 04/18] Port to SCO OpenServer 6. May require running ./configure with --build=i686-unknown-sysv5SCO_SV6.0.0 include/my_pthread.h: Remove unnecessary define -- configure should define HAVE_NONPOSIX_SIGWAIT configure.in: Update checks for SCO threading libraries to handle OpenServer 6 Remove redundant OpenUNIX 8 checks Pass --build option through to bdb's configure --- configure.in | 94 +++++++++++--------------------------------- include/my_pthread.h | 5 --- 2 files changed, 23 insertions(+), 76 deletions(-) diff --git a/configure.in b/configure.in index 60b91f5cc60..71f0a1711bb 100644 --- a/configure.in +++ b/configure.in @@ -359,19 +359,19 @@ case "$target_os" in ;; esac ;; - sysv5UnixWare*) + sysv5UnixWare* | sysv5OpenUNIX8*) if test "$GCC" != "yes"; then - # We are using built-in inline function + # Use the built-in alloca() CFLAGS="$CFLAGS -Kalloca" fi CXXFLAGS="$CXXFLAGS -DNO_CPLUSPLUS_ALLOCA" ;; - sysv5OpenUNIX8*) + sysv5SCO_SV6.0.0*) if test "$GCC" != "yes"; then - # We are using built-in inline function + # Use the built-in alloca() CFLAGS="$CFLAGS -Kalloca" + CXXFLAGS="$CFLAGS -Kalloca" fi - CXXFLAGS="$CXXFLAGS -DNO_CPLUSPLUS_ALLOCA" ;; esac AC_SUBST(CC) @@ -1386,8 +1386,6 @@ then if expr "$SYSTEM_TYPE" : ".*unixware7.0.0" > /dev/null then AC_DEFINE(HAVE_UNIXWARE7_THREADS, [1]) - else - AC_DEFINE(HAVE_UNIXWARE7_POSIX, [1]) fi AC_MSG_RESULT("yes") # We must have cc @@ -1413,87 +1411,41 @@ then AC_MSG_RESULT("no") fi fi -# Hack for SCO UnixWare7 + +# +# Check for SCO threading libraries # if test "$with_named_thread" = "no" then - AC_MSG_CHECKING("SCO UnixWare7 native threads") - if expr "$SYSTEM_TYPE" : ".*UnixWare*" > /dev/null + AC_MSG_CHECKING([SCO OpenServer 6, UnixWare 7 or OpenUNIX 8 native threads]) + if expr "$SYSTEM_TYPE" : ".*UnixWare.*" > /dev/null || \ + expr "$SYSTEM_TYPE" : ".*SCO_SV6.*" > /dev/null || \ + expr "$SYSTEM_TYPE" : ".*OpenUNIX.*" > /dev/null then if test -f /usr/lib/libthread.so -o -f /usr/lib/libthreadT.so then MYSQL_REMOVE_SOCKET_FROM_LIBS_HACK - if expr "$CC" : ".*gcc.*" - then - with_named_thread="-pthread -lsocket -lnsl" - else - with_named_thread="-Kthread -lsocket -lnsl" - fi - if expr "$SYSTEM_TYPE" : ".*unixware7.0.0" > /dev/null - then - AC_DEFINE(HAVE_UNIXWARE7_THREADS, [1]) - else - AC_DEFINE(HAVE_UNIXWARE7_POSIX, [1]) - fi - # We must have cc - AC_MSG_CHECKING("for gcc") - if expr "$CC" : ".*gcc.*" + if expr "$CC" : ".*gcc.*" > /dev/null then + with_named_thread="-pthread -lsocket -lnsl" CC="$CC -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"; CXX="$CXX -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"; else + with_named_thread="-Kthread -lsocket -lnsl" CC="$CC -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"; CXX="$CXX -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"; fi - AC_MSG_RESULT("yes") + if expr "$SYSTEM_TYPE" : ".*unixware7.0.0" > /dev/null + then + AC_DEFINE(HAVE_UNIXWARE7_THREADS, [1], [Have UnixWare 7 (or similar) almost-POSIX threading library]) + fi + AC_MSG_RESULT(yes) else + AC_MSG_RESULT(failed) { echo "configure: error: Can't find thread libs on SCO UnixWare7. See the Installation chapter in the Reference Manual." 1>&2; exit 1; }; fi else - AC_MSG_RESULT("no") - fi -fi - -# Hack for Caldera OpenUNIX8 -# -if test "$with_named_thread" = "no" -then - AC_MSG_CHECKING("OpenUNIX8 native threads") - if expr "$SYSTEM_TYPE" : ".*OpenUNIX*" > /dev/null - then - if test -f /usr/lib/libthread.so -o -f /usr/lib/libthreadT.so - then - MYSQL_REMOVE_SOCKET_FROM_LIBS_HACK - if expr "$CC" : ".*gcc.*" - then - with_named_thread="-pthread -lsocket -lnsl" - else - with_named_thread="-Kthread -lsocket -lnsl" - fi - if expr "$SYSTEM_TYPE" : ".*unixware7.0.0" > /dev/null - then - AC_DEFINE([HAVE_UNIXWARE7_THREADS], [1], - [UNIXWARE7 threads are not posix]) - else - AC_DEFINE([HAVE_UNIXWARE7_POSIX], [1], - [new UNIXWARE7 threads that are not yet posix]) - fi - # We must have cc - AC_MSG_CHECKING("for gcc") - if expr "$CC" : ".*gcc.*" - then - CC="$CC -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"; - CXX="$CXX -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"; - else - CC="$CC -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"; - CXX="$CXX -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"; - fi - AC_MSG_RESULT("yes") - else - { echo "configure: error: Can't find thread libs on Caldera OpenUNIX 8. See the Installation chapter in the Reference Manual." 1>&2; exit 1; }; - fi - else - AC_MSG_RESULT("no") + AC_MSG_RESULT(no) fi fi @@ -2889,7 +2841,7 @@ then AC_CONFIG_FILES(bdb/Makefile) echo "CONFIGURING FOR BERKELEY DB" - bdb_conf_flags="--disable-shared" + bdb_conf_flags="--disable-shared --build=$build_alias" if test $with_debug = "yes" then bdb_conf_flags="$bdb_conf_flags --enable-debug --enable-diagnostic" diff --git a/include/my_pthread.h b/include/my_pthread.h index f8cd3e0de71..02f451cffd2 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -298,11 +298,6 @@ extern int my_pthread_create_detached; int sigwait(sigset_t *set, int *sig); #endif -#if defined(HAVE_UNIXWARE7_POSIX) -#undef HAVE_NONPOSIX_SIGWAIT -#define HAVE_NONPOSIX_SIGWAIT /* sigwait takes only 1 argument */ -#endif - #ifndef HAVE_NONPOSIX_SIGWAIT #define my_sigwait(A,B) sigwait((A),(B)) #else From a12efb04ddeba5c62a5d49a695f296bc373ca97a Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 8 Sep 2005 03:06:49 +0200 Subject: [PATCH 05/18] configure.in: Flag -DHAVE_DARWIN_THREADS not needed for darwin9 configure.in: Flag -DHAVE_DARWIN_THREADS not needed for darwin9 --- configure.in | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/configure.in b/configure.in index c473fb21dbd..d294d537031 100644 --- a/configure.in +++ b/configure.in @@ -1062,6 +1062,15 @@ case $SYSTEM_TYPE in MAX_C_OPTIMIZE="-O" fi ;; + *darwin9*) + if test "$ac_cv_prog_gcc" = "yes" + then + FLAGS="-D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DIGNORE_SIGHUP_SIGQUIT" + CFLAGS="$CFLAGS $FLAGS" + CXXFLAGS="$CXXFLAGS $FLAGS" + MAX_C_OPTIMIZE="-O" + fi + ;; *freebsd*) echo "Adding fix for interrupted reads" OSVERSION=`sysctl -a | grep osreldate | awk '{ print $2 }'` From da5a9926e1747b482fa7236bf794b4b605b21bf6 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 8 Sep 2005 21:40:59 +0200 Subject: [PATCH 06/18] When first creating the ARZ file for an archive table, use "wb" as the mode for gzdopen() because the file itself was only opened for writing (and truncated), and some libc implementations (like SCO) don't like to do a fdopen(..., "a") on a fd that was not opened using O_APPEND. sql/examples/ha_archive.cc: Use "wb" instead of "ab" since we just opened this file for writing --- sql/examples/ha_archive.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/examples/ha_archive.cc b/sql/examples/ha_archive.cc index bc4af0c7dc7..30b107aa627 100644 --- a/sql/examples/ha_archive.cc +++ b/sql/examples/ha_archive.cc @@ -520,7 +520,7 @@ int ha_archive::create(const char *name, TABLE *table_arg, error= my_errno; goto error; } - if ((archive= gzdopen(create_file, "ab")) == NULL) + if ((archive= gzdopen(create_file, "wb")) == NULL) { error= errno; goto error2; From 0dec682f39d3e97d72b7d0620db218ba715dd13a Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 10 Sep 2005 15:01:54 +0300 Subject: [PATCH 07/18] Fix for BUG#12943. The problem was that in the first production in rule 'join_table', that processes simple cross joins, the parser was processing the second join operand before the first one due to unspecified priorities of JOINs. As a result in the case of cross joins the parser constructed a tree with incorrect nesting: the expression "t1 join t2 join t3 on some_cond" was interpreted as "t1 join (t2 join t3 on some_cond)" instead of "(t1 join t2) join t3 on some_cond". Because of this incorrect nesting the method make_join_on_context picked an incorrect table as the first table of the name resolution context. The solution assignes correct priorities to the related production. mysql-test/r/select.result: Added test for BUG#12943. mysql-test/t/select.test: Added test for BUG#12943. sql/sql_parse.cc: Fixed typo. sql/sql_yacc.yy: Provide explicit priorities of the JOIN operator and the 'table_ref' rule, to enforce left-associativity of [INNER | CROSS] JOIN. --- mysql-test/r/select.result | 20 ++++++++++++++++++++ mysql-test/t/select.test | 23 +++++++++++++++++++++++ sql/sql_parse.cc | 2 +- sql/sql_yacc.yy | 11 ++++++++++- 4 files changed, 54 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 0d5c1aed485..2b8ef07636f 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2897,3 +2897,23 @@ select * from t1 natural join t2 where a = 'b'; a b drop table t1, t2; +create table t1 (a int, c int); +create table t2 (b int); +create table t3 (b int, a int); +create table t4 (c int); +insert into t1 values (1,1); +insert into t2 values (1); +insert into t3 values (1,1); +insert into t4 values (1); +select * from t1 join t2 join t3 on (t2.b = t3.b and t1.a = t3.a); +a c b b a +1 1 1 1 1 +select * from t1, t2 join t3 on (t2.b = t3.b and t1.a = t3.a); +ERROR 42S22: Unknown column 't1.a' in 'on clause' +select * from t1 join t2 join t3 join t4 on (t1.a = t4.c and t2.b = t4.c); +a c b b a c +1 1 1 1 1 1 +select * from t1 join t2 join t4 using (c); +c a b +1 1 1 +drop table t1, t2, t3, t4; diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index fad01ac9acf..37fbd7a296e 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -2465,3 +2465,26 @@ insert into t2 values ('b'),('c'),('d'); select a from t1 natural join t2; select * from t1 natural join t2 where a = 'b'; drop table t1, t2; + +# +# Bug #12943 Incorrect nesting of [INNER| CROSS] JOIN due to unspecified +# associativity in the parser. +# + +create table t1 (a int, c int); +create table t2 (b int); +create table t3 (b int, a int); +create table t4 (c int); +insert into t1 values (1,1); +insert into t2 values (1); +insert into t3 values (1,1); +insert into t4 values (1); + +select * from t1 join t2 join t3 on (t2.b = t3.b and t1.a = t3.a); +# Notice that ',' has lower priority than 'join', thus we have that: +# t1, t2 join t3 <==> t1, (t2 join t3). +-- error 1054 +select * from t1, t2 join t3 on (t2.b = t3.b and t1.a = t3.a); +select * from t1 join t2 join t3 join t4 on (t1.a = t4.c and t2.b = t4.c); +select * from t1 join t2 join t4 using (c); +drop table t1, t2, t3, t4; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index e3f9c0dc148..d7d3da8288b 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -6354,7 +6354,7 @@ void st_select_lex::set_lock_for_tables(thr_lock_type lock_type) SYNOPSIS make_join_on_context() thd pointer to current thread - left_op lefto operand of the JOIN + left_op left operand of the JOIN right_op rigth operand of the JOIN DESCRIPTION diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index a39ee7c82aa..520b6190410 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -660,6 +660,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token YEAR_SYM %token ZEROFILL +%left JOIN_SYM +/* A dummy token to force the priority of table_ref production in a join. */ +%left TABLE_REF_PRIORITY %left SET_VAR %left OR_OR_SYM OR_SYM OR2_SYM XOR %left AND_SYM AND_AND_SYM @@ -5189,7 +5192,13 @@ derived_table_list: ; join_table: - table_ref normal_join table_ref { YYERROR_UNLESS($1 && ($$=$3)); } + /* + Evaluate production 'table_ref' before 'normal_join' so that + [INNER | CROSS] JOIN is properly nested as other left-associative + joins. + */ + table_ref %prec TABLE_REF_PRIORITY normal_join table_ref + { YYERROR_UNLESS($1 && ($$=$3)); } | table_ref STRAIGHT_JOIN table_factor { YYERROR_UNLESS($1 && ($$=$3)); $3->straight=1; } | table_ref normal_join table_ref From 63080dc200d8b497500422aa484f72e712b04d5f Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 12 Sep 2005 17:09:19 +0500 Subject: [PATCH 08/18] Fix for bug #6008: MySQL does not create warnings when creating database and using IF NOT EXISTS produce warning for 'create database if not exists' if database exists do not update database options in this case produce warning for 'create table if not exists' if table exists mysql-test/r/create.result: Fix for bug #6008: MySQL does not create warnings when creating database and using IF NOT EXISTS updated test case result mysql-test/r/temp_table.result: Fix for bug #6008: MySQL does not create warnings when creating database and using IF NOT EXISTS updated test case result mysql-test/r/warnings.result: Fix for bug #6008: MySQL does not create warnings when creating database and using IF NOT EXISTS updated test case result mysql-test/t/create.test: Fix for bug #6008: MySQL does not create warnings when creating database and using IF NOT EXISTS test case sql/sql_db.cc: Fix for bug #6008: MySQL does not create warnings when creating database and using IF NOT EXISTS produce warning for 'create database if not exists' if database exists do not update database options in this case sql/sql_table.cc: Fix for bug #6008: MySQL does not create warnings when creating database and using IF NOT EXISTS produce warning for 'create table if not exists' if table exists --- mysql-test/r/create.result | 28 ++++++++++++++++++++++++++++ mysql-test/r/temp_table.result | 2 ++ mysql-test/r/warnings.result | 4 +++- mysql-test/t/create.test | 13 +++++++++++++ sql/sql_db.cc | 6 +++++- sql/sql_table.cc | 28 ++++++++++++++++------------ 6 files changed, 67 insertions(+), 14 deletions(-) diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index 95757fbd7dc..6edd4cbc48f 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -9,6 +9,8 @@ NULL drop table if exists t1; create table t1 (b char(0) not null); create table if not exists t1 (b char(0) not null); +Warnings: +Note 1050 Table 't1' already exists insert into t1 values (""),(null); Warnings: Warning 1263 Data truncated; NULL supplied to NOT NULL column 'b' at row 2 @@ -232,9 +234,13 @@ create table t1 select x'4132'; drop table t1; create table t1 select 1,2,3; create table if not exists t1 select 1,2; +Warnings: +Note 1050 Table 't1' already exists create table if not exists t1 select 1,2,3,4; ERROR 21S01: Column count doesn't match value count at row 1 create table if not exists t1 select 1; +Warnings: +Note 1050 Table 't1' already exists select * from t1; 1 2 3 1 2 3 @@ -243,9 +249,13 @@ select * from t1; drop table t1; create table t1 select 1,2,3; create table if not exists t1 select 1,2; +Warnings: +Note 1050 Table 't1' already exists create table if not exists t1 select 1,2,3,4; ERROR 21S01: Column count doesn't match value count at row 1 create table if not exists t1 select 1; +Warnings: +Note 1050 Table 't1' already exists select * from t1; 1 2 3 1 2 3 @@ -255,11 +265,15 @@ drop table t1; create table t1 (a int not null, b int, primary key (a)); insert into t1 values (1,1); create table if not exists t1 select 2; +Warnings: +Note 1050 Table 't1' already exists select * from t1; a b 1 1 0 2 create table if not exists t1 select 3 as 'a',4 as 'b'; +Warnings: +Note 1050 Table 't1' already exists create table if not exists t1 select 3 as 'a',3 as 'b'; ERROR 23000: Duplicate entry '3' for key 1 select * from t1; @@ -593,3 +607,17 @@ drop database mysqltest; create table test.t1 like x; ERROR 42000: Incorrect database name 'NULL' drop table if exists test.t1; +create database mysqltest; +create database if not exists mysqltest character set latin2; +Warnings: +Note 1007 Can't create database 'mysqltest'; database exists +show create database mysqltest; +Database Create Database +mysqltest CREATE DATABASE `mysqltest` /*!40100 DEFAULT CHARACTER SET latin1 */ +drop database mysqltest; +use test; +create table t1 (a int); +create table if not exists t1 (a int); +Warnings: +Note 1050 Table 't1' already exists +drop table t1; diff --git a/mysql-test/r/temp_table.result b/mysql-test/r/temp_table.result index f08fe6ddd0f..0b6bc48c350 100644 --- a/mysql-test/r/temp_table.result +++ b/mysql-test/r/temp_table.result @@ -23,6 +23,8 @@ a b 6 g create TEMPORARY TABLE t2 engine=heap select * from t1; create TEMPORARY TABLE IF NOT EXISTS t2 (a int) engine=heap; +Warnings: +Note 1050 Table 't2' already exists CREATE TEMPORARY TABLE t1 (a int not null, b char (10) not null); ERROR 42S01: Table 't1' already exists ALTER TABLE t1 RENAME t2; diff --git a/mysql-test/r/warnings.result b/mysql-test/r/warnings.result index e97b309547a..b9c05bc388c 100644 --- a/mysql-test/r/warnings.result +++ b/mysql-test/r/warnings.result @@ -63,9 +63,11 @@ show count(*) warnings; 1 create table t1(id int); create table if not exists t1(id int); +Warnings: +Note 1050 Table 't1' already exists select @@warning_count; @@warning_count -0 +1 drop table t1; create table t1(a tinyint, b int not null, c date, d char(5)); load data infile '../../std_data/warnings_loaddata.dat' into table t1 fields terminated by ','; diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index 9ea810aaf7d..73184853d1a 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -513,4 +513,17 @@ create table test.t1 like x; drop table if exists test.t1; --enable_warnings +# +# Bug #6008 MySQL does not create warnings when +# creating database and using IF NOT EXISTS +# +create database mysqltest; +create database if not exists mysqltest character set latin2; +show create database mysqltest; +drop database mysqltest; +use test; +create table t1 (a int); +create table if not exists t1 (a int); +drop table t1; + # End of 4.1 tests diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 7635774e3ac..7c834c91183 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -427,7 +427,11 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, error= -1; goto exit; } - result= 0; + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, + ER_DB_CREATE_EXISTS, ER(ER_DB_CREATE_EXISTS), db); + error= 0; + send_ok(thd); + goto exit; } else { diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 92db0143980..01126043764 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1360,6 +1360,9 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS) { create_info->table_existed= 1; // Mark that table existed + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, + ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR), + alias); DBUG_RETURN(0); } my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias); @@ -1373,12 +1376,8 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, if (!access(path,F_OK)) { if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS) - { - create_info->table_existed= 1; // Mark that table existed - error= 0; - } - else - my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name); + goto warn; + my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name); goto end; } } @@ -1401,12 +1400,8 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, DBUG_PRINT("info", ("Table with same name already existed in handler")); if (create_if_not_exists) - { - create_info->table_existed= 1; // Mark that table existed - error= 0; - } - else - my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name); + goto warn; + my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name); goto end; } } @@ -1447,6 +1442,15 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, } } error=0; + goto end; + +warn: + error= 0; + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, + ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR), + alias); + create_info->table_existed= 1; // Mark that table existed + end: VOID(pthread_mutex_unlock(&LOCK_open)); start_waiting_global_read_lock(thd); From 95fecf34e2117f459c987db83352f1f29270e531 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 12 Sep 2005 19:35:50 +0500 Subject: [PATCH 09/18] Many files: Adding esperanto collation strings/ctype-uca.c: Adding esperanto collation mysys/charset-def.c: Adding esperanto collation mysql-test/t/ctype_uca.test: Adding esperanto collation mysql-test/r/ctype_uca.result: Adding esperanto collation config/ac-macros/character_sets.m4: Adding esperanto collation --- config/ac-macros/character_sets.m4 | 4 +- mysql-test/r/ctype_uca.result | 110 +++++++++++++++++++++++++++++ mysql-test/t/ctype_uca.test | 1 + mysys/charset-def.c | 4 ++ strings/ctype-uca.c | 75 ++++++++++++++++++++ 5 files changed, 192 insertions(+), 2 deletions(-) diff --git a/config/ac-macros/character_sets.m4 b/config/ac-macros/character_sets.m4 index 3ecc4bb5a03..1ab6e7dd780 100644 --- a/config/ac-macros/character_sets.m4 +++ b/config/ac-macros/character_sets.m4 @@ -343,7 +343,7 @@ case $default_charset in default_charset_default_collation="ucs2_general_ci" define(UCSC1, ucs2_general_ci ucs2_bin) define(UCSC2, ucs2_czech_ci ucs2_danish_ci) - define(UCSC3, ucs2_estonian_ci ucs2_icelandic_ci) + define(UCSC3, ucs2_esperanto_ci ucs2_estonian_ci ucs2_icelandic_ci) define(UCSC4, ucs2_latvian_ci ucs2_lithuanian_ci) define(UCSC5, ucs2_persian_ci ucs2_polish_ci ucs2_romanian_ci) define(UCSC6, ucs2_slovak_ci ucs2_slovenian_ci) @@ -367,7 +367,7 @@ case $default_charset in else define(UTFC1, utf8_general_ci utf8_bin) define(UTFC2, utf8_czech_ci utf8_danish_ci) - define(UTFC3, utf8_estonian_ci utf8_icelandic_ci) + define(UTFC3, utf8_esperanto_ci utf8_estonian_ci utf8_icelandic_ci) define(UTFC4, utf8_latvian_ci utf8_lithuanian_ci) define(UTFC5, utf8_persian_ci utf8_polish_ci utf8_romanian_ci) define(UTFC6, utf8_slovak_ci utf8_slovenian_ci) diff --git a/mysql-test/r/ctype_uca.result b/mysql-test/r/ctype_uca.result index 3803dd932d7..e2805e41f3a 100644 --- a/mysql-test/r/ctype_uca.result +++ b/mysql-test/r/ctype_uca.result @@ -1905,6 +1905,116 @@ Z,z,Ź,ź,Ż,ż,Ž,ž ǁ ǂ ǃ +select group_concat(c1 order by c1) from t1 group by c1 collate utf8_esperanto_ci; +group_concat(c1 order by c1) +÷ +× +A,a,À,Á,Â,Ã,Ä,Å,à,á,â,ã,ä,å,Ā,ā,Ă,ă,Ą,ą,Ǎ,ǎ,Ǟ,ǟ,Ǡ,ǡ,Ǻ,ǻ +AA,Aa,aA,aa +Æ,æ,Ǣ,ǣ,Ǽ,ǽ +B,b +ƀ +Ɓ +Ƃ,ƃ +C,c,Ç,ç,Ć,ć,Ċ,ċ,Č,č +CH,Ch,cH,ch +Ĉ,ĉ +Ƈ,ƈ +D,d,Ď,ď +DZ,Dz,dZ,dz,DŽ,Dž,dž,DZ,Dz,dz +Đ,đ +Ɖ +Ɗ +Ƌ,ƌ +Ð,ð +E,e,È,É,Ê,Ë,è,é,ê,ë,Ē,ē,Ĕ,ĕ,Ė,ė,Ę,ę,Ě,ě +Ǝ,ǝ +Ə +Ɛ +F,f +Ƒ,ƒ +G,g,Ğ,ğ,Ġ,ġ,Ģ,ģ,Ǧ,ǧ,Ǵ,ǵ +Ĝ,ĝ +Ǥ,ǥ +Ɠ +Ɣ +Ƣ,ƣ +H,h +Ĥ,ĥ +ƕ,Ƕ +Ħ,ħ +I,i,Ì,Í,Î,Ï,ì,í,î,ï,Ĩ,ĩ,Ī,ī,Ĭ,ĭ,Į,į,İ,Ǐ,ǐ +IJ,Ij,iJ,ij,IJ,ij +ı +Ɨ +Ɩ +J,j,ǰ +Ĵ,ĵ +K,k,Ķ,ķ,Ǩ,ǩ +Ƙ,ƙ +L,l,Ĺ,ĺ,Ļ,ļ,Ľ,ľ +Ŀ,ŀ +LJ,Lj,lJ,lj,LJ,Lj,lj +LL,Ll,lL,ll +Ł,ł +ƚ +ƛ +M,m +N,n,Ñ,ñ,Ń,ń,Ņ,ņ,Ň,ň,Ǹ,ǹ +NJ,Nj,nJ,nj,NJ,Nj,nj +Ɲ +ƞ +Ŋ,ŋ +O,o,Ò,Ó,Ô,Õ,Ö,ò,ó,ô,õ,ö,Ō,ō,Ŏ,ŏ,Ő,ő,Ơ,ơ,Ǒ,ǒ,Ǫ,ǫ,Ǭ,ǭ +OE,Oe,oE,oe,Œ,œ +Ø,ø,Ǿ,ǿ +Ɔ +Ɵ +P,p +Ƥ,ƥ +Q,q +ĸ +R,r,Ŕ,ŕ,Ŗ,ŗ,Ř,ř +RR,Rr,rR,rr +Ʀ +S,s,Ś,ś,Ş,ş,Š,š,ſ +SS,Ss,sS,ss,ß +Ŝ,ŝ +Ʃ +ƪ +T,t,Ţ,ţ,Ť,ť +ƾ +Ŧ,ŧ +ƫ +Ƭ,ƭ +Ʈ +U,u,Ù,Ú,Û,Ü,ù,ú,û,ü,Ũ,ũ,Ū,ū,Ů,ů,Ű,ű,Ų,ų,Ư,ư,Ǔ,ǔ,Ǖ,ǖ,Ǘ,ǘ,Ǚ,ǚ,Ǜ,ǜ +Ŭ,ŭ +Ɯ +Ʊ +V,v +Ʋ +W,w,Ŵ,ŵ +X,x +Y,y,Ý,ý,ÿ,Ŷ,ŷ,Ÿ +Ƴ,ƴ +Z,z,Ź,ź,Ż,ż,Ž,ž +ƍ +Ƶ,ƶ +Ʒ,Ǯ,ǯ +Ƹ,ƹ +ƺ +Þ,þ +ƿ,Ƿ +ƻ +Ƨ,ƨ +Ƽ,ƽ +Ƅ,ƅ +ʼn +ǀ +ǁ +ǂ +ǃ drop table t1; SET NAMES utf8; CREATE TABLE t1 (c varchar(255) NOT NULL COLLATE utf8_general_ci, INDEX (c)); diff --git a/mysql-test/t/ctype_uca.test b/mysql-test/t/ctype_uca.test index 098ea33c6b2..43ef0cc8755 100644 --- a/mysql-test/t/ctype_uca.test +++ b/mysql-test/t/ctype_uca.test @@ -211,6 +211,7 @@ select group_concat(c1 order by c1) from t1 group by c1 collate utf8_lithuanian_ select group_concat(c1 order by c1) from t1 group by c1 collate utf8_slovak_ci; select group_concat(c1 order by c1) from t1 group by c1 collate utf8_spanish2_ci; select group_concat(c1 order by c1) from t1 group by c1 collate utf8_roman_ci; +select group_concat(c1 order by c1) from t1 group by c1 collate utf8_esperanto_ci; drop table t1; diff --git a/mysys/charset-def.c b/mysys/charset-def.c index 0464ba893fb..5b30d1ee135 100644 --- a/mysys/charset-def.c +++ b/mysys/charset-def.c @@ -42,6 +42,7 @@ extern CHARSET_INFO my_charset_ucs2_slovak_uca_ci; extern CHARSET_INFO my_charset_ucs2_spanish2_uca_ci; extern CHARSET_INFO my_charset_ucs2_roman_uca_ci; extern CHARSET_INFO my_charset_ucs2_persian_uca_ci; +extern CHARSET_INFO my_charset_ucs2_esperanto_uca_ci; #endif #ifdef HAVE_CHARSET_utf8 @@ -62,6 +63,7 @@ extern CHARSET_INFO my_charset_utf8_slovak_uca_ci; extern CHARSET_INFO my_charset_utf8_spanish2_uca_ci; extern CHARSET_INFO my_charset_utf8_roman_uca_ci; extern CHARSET_INFO my_charset_utf8_persian_uca_ci; +extern CHARSET_INFO my_charset_utf8_esperanto_uca_ci; #ifdef HAVE_UTF8_GENERAL_CS extern CHARSET_INFO my_charset_utf8_general_cs; #endif @@ -148,6 +150,7 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused))) add_compiled_collation(&my_charset_ucs2_spanish2_uca_ci); add_compiled_collation(&my_charset_ucs2_roman_uca_ci); add_compiled_collation(&my_charset_ucs2_persian_uca_ci); + add_compiled_collation(&my_charset_ucs2_esperanto_uca_ci); #endif #endif @@ -180,6 +183,7 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused))) add_compiled_collation(&my_charset_utf8_spanish2_uca_ci); add_compiled_collation(&my_charset_utf8_roman_uca_ci); add_compiled_collation(&my_charset_utf8_persian_uca_ci); + add_compiled_collation(&my_charset_utf8_esperanto_uca_ci); #endif #endif diff --git a/strings/ctype-uca.c b/strings/ctype-uca.c index dcf1c07113e..a280ed59352 100644 --- a/strings/ctype-uca.c +++ b/strings/ctype-uca.c @@ -6692,6 +6692,18 @@ static const char persian[]= " < \\uFEF5 < \\uFEF6 < \\uFEF7 < \\uFEF8 < \\uFEF9 < \\uFEFA" " < \\uFEFB < \\uFEFC"; +/* + Esperanto tailoring. + Contributed by Bertilo Wennergren + September 1, 2005 +*/ +static const char esperanto[]= + "& C < \\u0109 <<< \\u0108" + "& G < \\u011D <<< \\u011C" + "& H < \\u0125 <<< \\u0124" + "& J < \\u0135 <<< \\u0134" + "& S < \\u015d <<< \\u015c" + "& U < \\u016d <<< \\u016c"; /* Unicode Collation Algorithm: @@ -8564,6 +8576,38 @@ CHARSET_INFO my_charset_ucs2_persian_uca_ci= }; +CHARSET_INFO my_charset_ucs2_esperanto_uca_ci= +{ + 145,0,0, /* number */ + MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE, + "ucs2", /* cs name */ + "ucs2_esperanto_ci",/* name */ + "", /* comment */ + esperanto, /* tailoring */ + NULL, /* ctype */ + NULL, /* to_lower */ + NULL, /* to_upper */ + NULL, /* sort_order */ + NULL, /* contractions */ + NULL, /* sort_order_big*/ + NULL, /* tab_to_uni */ + NULL, /* tab_from_uni */ + my_unicase_default, /* caseinfo */ + NULL, /* state_map */ + NULL, /* ident_map */ + 8, /* strxfrm_multiply */ + 1, /* caseup_multiply */ + 1, /* casedn_multiply */ + 2, /* mbminlen */ + 2, /* mbmaxlen */ + 9, /* min_sort_char */ + 0xFFFF, /* max_sort_char */ + 0, /* escape_with_backslash_is_dangerous */ + &my_charset_ucs2_handler, + &my_collation_ucs2_uca_handler +}; + + #endif @@ -9140,6 +9184,37 @@ CHARSET_INFO my_charset_utf8_persian_uca_ci= &my_collation_any_uca_handler }; +CHARSET_INFO my_charset_utf8_esperanto_uca_ci= +{ + 209,0,0, /* number */ + MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE, + "utf8", /* cs name */ + "utf8_esperanto_ci",/* name */ + "", /* comment */ + esperanto, /* tailoring */ + ctype_utf8, /* ctype */ + NULL, /* to_lower */ + NULL, /* to_upper */ + NULL, /* sort_order */ + NULL, /* contractions */ + NULL, /* sort_order_big*/ + NULL, /* tab_to_uni */ + NULL, /* tab_from_uni */ + my_unicase_default, /* caseinfo */ + NULL, /* state_map */ + NULL, /* ident_map */ + 8, /* strxfrm_multiply */ + 1, /* caseup_multiply */ + 1, /* casedn_multiply */ + 1, /* mbminlen */ + 3, /* mbmaxlen */ + 9, /* min_sort_char */ + 0xFFFF, /* max_sort_char */ + 0, /* escape_with_backslash_is_dangerous */ + &my_charset_utf8_handler, + &my_collation_any_uca_handler +}; + #endif /* HAVE_CHARSET_utf8 */ #endif /* HAVE_UCA_COLLATIONS */ From 90ca6d15b3c560672c8ea8963d57c6bac48978f2 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 12 Sep 2005 18:48:17 +0300 Subject: [PATCH 10/18] Review fixes since last pull Fix for bug #13025; Server crash in filesort because wrong call to handler::position() client/mysqltest.c: Code cleanup during review mysql-test/r/innodb.result: Added test case for bug #13025; Server crash in filesort because wrong call to handler::position() mysql-test/t/innodb.test: Added test case for bug #13025; Server crash in filesort because wrong call to handler::position() sql/filesort.cc: Don't call handler::position() if row was not found sql/item_cmpfunc.cc: Indentation changes sql/sql_select.cc: Moved variable to outer level --- client/mysqltest.c | 3 ++- mysql-test/r/innodb.result | 11 +++++++++++ mysql-test/t/innodb.test | 10 ++++++++++ sql/filesort.cc | 2 +- sql/item_cmpfunc.cc | 16 +++++++++------- sql/sql_select.cc | 12 ++++++------ 6 files changed, 39 insertions(+), 15 deletions(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index 3e2cde92aa9..374f0cb1336 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -2170,7 +2170,8 @@ int read_line(char *buf, int size) if (feof(cur_file->file)) { found_eof: - if (cur_file->file != stdin){ + if (cur_file->file != stdin) + { my_fclose(cur_file->file, MYF(0)); cur_file->file= 0; } diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 858daacffe9..f47c78c9768 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -1674,3 +1674,14 @@ select * from t1; a 42 drop table t1; +create table t1 (a int not null, b int not null, c blob not null, d int not null, e int, primary key (a,b,c(255),d)) engine=innodb; +insert into t1 values (2,2,"b",2,2),(1,1,"a",1,1),(3,3,"ab",3,3); +select * from t1 order by a,b,c,d; +a b c d e +1 1 a 1 1 +2 2 b 2 2 +3 3 ab 3 3 +explain select * from t1 order by a,b,c,d; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using filesort +drop table t1; diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index 33432209e65..a14370c6543 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -1220,4 +1220,14 @@ insert into t1 values (42); select * from t1; drop table t1; +# +# Bug #13025 Server crash during filesort +# + +create table t1 (a int not null, b int not null, c blob not null, d int not null, e int, primary key (a,b,c(255),d)) engine=innodb; +insert into t1 values (2,2,"b",2,2),(1,1,"a",1,1),(3,3,"ab",3,3); +select * from t1 order by a,b,c,d; +explain select * from t1 order by a,b,c,d; +drop table t1; + # End of 4.1 tests diff --git a/sql/filesort.cc b/sql/filesort.cc index 75b114fc140..63a8515020b 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -443,7 +443,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, ha_store_ptr(ref_pos,ref_length,record); // Position to row record+=sort_form->db_record_offset; } - else + else if (!error) file->position(sort_form->record[0]); } if (error && error != HA_ERR_RECORD_DELETED) diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index f547a8a50a8..74eed7fa41a 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -51,7 +51,8 @@ static void agg_cmp_type(Item_result *type, Item **items, uint nitems) type[0]= item_cmp_type(type[0], items[i]->result_type()); } -static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, const char *fname) +static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, + const char *fname) { my_error(ER_CANT_AGGREGATE_2COLLATIONS,MYF(0), c1.collation->name,c1.derivation_name(), @@ -850,8 +851,8 @@ longlong Item_func_interval::val_int() 1 got error */ -bool -Item_func_between::fix_fields(THD *thd, struct st_table_list *tables, Item **ref) +bool Item_func_between::fix_fields(THD *thd, struct st_table_list *tables, + Item **ref) { if (Item_func_opt_neg::fix_fields(thd, tables, ref)) return 1; @@ -861,8 +862,9 @@ Item_func_between::fix_fields(THD *thd, struct st_table_list *tables, Item **ref return 0; /* not_null_tables_cache == union(T1(e), intersection(T1(e1),T1(e2))) */ - not_null_tables_cache= args[0]->not_null_tables() | - (args[1]->not_null_tables() & args[2]->not_null_tables()); + not_null_tables_cache= (args[0]->not_null_tables() | + (args[1]->not_null_tables() & + args[2]->not_null_tables())); return 0; } @@ -1106,8 +1108,8 @@ Item_func_if::fix_fields(THD *thd, struct st_table_list *tlist, Item **ref) if (Item_func::fix_fields(thd, tlist, ref)) return 1; - not_null_tables_cache= (args[1]->not_null_tables() - & args[2]->not_null_tables()); + not_null_tables_cache= (args[1]->not_null_tables() & + args[2]->not_null_tables()); return 0; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 3de546fd619..f702e531a4d 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -9307,12 +9307,12 @@ static bool change_group_ref(THD *thd, Item_func *expr, ORDER *group_list, if (expr->arg_count) { Item **arg,**arg_end; + bool arg_changed= FALSE; for (arg= expr->arguments(), arg_end= expr->arguments()+expr->arg_count; arg != arg_end; arg++) { Item *item= *arg; - bool arg_changed= FALSE; if (item->type() == Item::FIELD_ITEM || item->type() == Item::REF_ITEM) { ORDER *group_tmp; @@ -9333,11 +9333,11 @@ static bool change_group_ref(THD *thd, Item_func *expr, ORDER *group_list, if (change_group_ref(thd, (Item_func *) item, group_list, &arg_changed)) return 1; } - if (arg_changed) - { - expr->maybe_null= 1; - *changed= TRUE; - } + } + if (arg_changed) + { + expr->maybe_null= 1; + *changed= TRUE; } } return 0; From 3f40506633c87c93a3606ebd9a3c60cd3dca7368 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 12 Sep 2005 17:49:48 +0200 Subject: [PATCH 11/18] Corrected construct of faked Node fail signals in ndb SignalSender --- ndb/src/mgmsrv/MgmtSrvr.cpp | 5 +---- ndb/src/ndbapi/SignalSender.cpp | 10 +++++++++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/ndb/src/mgmsrv/MgmtSrvr.cpp b/ndb/src/mgmsrv/MgmtSrvr.cpp index 011643237f8..56c24e5f862 100644 --- a/ndb/src/mgmsrv/MgmtSrvr.cpp +++ b/ndb/src/mgmsrv/MgmtSrvr.cpp @@ -2501,10 +2501,7 @@ MgmtSrvr::startBackup(Uint32& backupId, int waitCompleted) case GSN_NODE_FAILREP:{ const NodeFailRep * const rep = CAST_CONSTPTR(NodeFailRep, signal->getDataPtr()); -#ifdef VM_TRACE - ndbout_c("Node %d failed", rep->failNo); -#endif - if (rep->failNo == nodeId || + if (NodeBitmask::get(rep->theNodes,nodeId) || waitCompleted == 1) return 1326; // wait for next signal diff --git a/ndb/src/ndbapi/SignalSender.cpp b/ndb/src/ndbapi/SignalSender.cpp index a1c80f22041..327f34f178a 100644 --- a/ndb/src/ndbapi/SignalSender.cpp +++ b/ndb/src/ndbapi/SignalSender.cpp @@ -250,14 +250,22 @@ SignalSender::execNodeStatus(void* signalSender, // node shutdown complete s->header.theVerId_signalNumber = GSN_NF_COMPLETEREP; NFCompleteRep *rep = (NFCompleteRep *)s->getDataPtrSend(); + rep->blockNo = 0; + rep->nodeId = 0; rep->failedNodeId = nodeId; + rep->unused = 0; + rep->from = 0; } else { // node failure s->header.theVerId_signalNumber = GSN_NODE_FAILREP; NodeFailRep *rep = (NodeFailRep *)s->getDataPtrSend(); - rep->failNo = nodeId; + rep->failNo = 0; + rep->masterNodeId = 0; + rep->noOfNodes = 1; + NodeBitmask::clear(rep->theNodes); + NodeBitmask::set(rep->theNodes,nodeId); } ss->m_jobBuffer.push_back(s); From 3462573fa8e2c21b22013a4f4f7c1f4e8efb3618 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 12 Sep 2005 19:18:17 +0300 Subject: [PATCH 12/18] BUG#12943 - post-merge fix mysql-test/r/select.result: post-merge fix mysql-test/t/select.test: post-merge fix --- mysql-test/r/select.result | 1 + mysql-test/t/select.test | 3 +++ 2 files changed, 4 insertions(+) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 327bce2de4d..d7de9b6509b 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2922,6 +2922,7 @@ a b b select * from t1 inner join t2 using (a); a b b 1 10 10 +drop table t1, t2; create table t1 (a int, c int); create table t2 (b int); create table t3 (b int, a int); diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index accbc0d273b..61242b3d96e 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -2499,6 +2499,9 @@ insert into t2 values (1,10); # both queries should produce the same result select * from t1 inner join t2 using (A); select * from t1 inner join t2 using (a); +drop table t1, t2; + +# # Bug #12943 Incorrect nesting of [INNER| CROSS] JOIN due to unspecified # associativity in the parser. # From d262a6e0a0c2bfc583588480d1743fb2df06a391 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 12 Sep 2005 12:44:13 -0500 Subject: [PATCH 13/18] README: Update README (2nd try) README: Update README (2nd try) --- README | 65 ++++++++++++++++++++++------------------------------------ 1 file changed, 24 insertions(+), 41 deletions(-) diff --git a/README b/README index 29851358765..88cdaaf67d4 100644 --- a/README +++ b/README @@ -1,52 +1,35 @@ -This is a release of MySQL, a GPL (free) SQL database server (more -licence information in the PUBLIC file and in the reference manual). +This is a release of MySQL, a dual-license SQL database server. +MySQL is brought to you by the MySQL team at MySQL AB. -Please read the "Upgrading from..." section in the manual first, if you are -migrating from older versions of MySQL! +License information can be found in these files: +- For GPL (free) distributions, see the COPYING file. +- For commercial distributions, see the MySQLEULA.txt file. -The latest information about MySQL can be found at: -http://www.mysql.com -To see what it can do take a look at the features section in the -manual. +For further information about MySQL or additional documentation, see: +- The latest information about MySQL: http://www.mysql.com +- The current MySQL documentation: http:/dev.mysql.com/doc -For installation instructions see the Installation chapter in the -manual. +Some manual sections of special interest: -For future plans see the TODO appendix in the manual. +- If you are migrating from an older version of MySQL, please read the + "Upgrading from..." section first! +- To see what MySQL can do, take a look at the features section. +- For installation instructions, see the Installation chapter. +- For future plans, see the TODO appendix. +- For the new features/bugfix history, see the News appendix. +- For the currently known bugs/misfeatures (known errors) see the problems + appendix. +- For a list of developers and other contributors, see the Credits + appendix. -New features/bug fixes history is in the news appendix in the manual. - -For the currently known bugs/misfeatures (known errors) see the bugs -appendix in the manual. - -For examples of SQL and benchmarking information see the bench -directory. - -The manual mentioned above can be found in the Docs directory. The -manual is available in the following formats: as plain ASCII text in -Docs/manual.txt, in HTML format in Docs/manual_toc.html, as GNU Info in -Docs/mysql.info and as PostScript in Docs/manual.ps. - -MySQL is brought to you by the MySQL team at MySQL AB - -For a list of developers and other contributors, see the Credits appendix -in the manual. +A local copy of the MySQL Reference Manual can be found in the Docs +directory in GNU Info format. You can also browse the manual online or +download it in any of several formats at the URL given earlier in this +file. ************************************************************ IMPORTANT: -Send bug (error) reports, questions and comments to the mailing list -at mysql@lists.mysql.com - -Please use the 'mysqlbug' script when posting bug reports or questions -about MySQL. mysqlbug will gather some information about your system -and start your editor with a form in which you can describe your -problem. Bug reports might be silently ignored by the MySQL -maintainers if there is not a good reason included in the report as to -why mysqlbug has not been used. A report that says 'MySQL does not -work for me. Why?' is not considered a valid bug report. - -The mysqlbug script can be found in the 'scripts' directory of the -distribution, that is '/scripts'. +Bug or error reports should be sent to http://bugs.mysql.com. From 38b2cd733b4884d961d2186c052a0f3bcb1bb41b Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 12 Sep 2005 12:45:03 -0700 Subject: [PATCH 14/18] Update test result mysql-test/r/ndb_autodiscover.result: Update results --- mysql-test/r/ndb_autodiscover.result | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mysql-test/r/ndb_autodiscover.result b/mysql-test/r/ndb_autodiscover.result index 5a1a82832fa..c61270c02a8 100644 --- a/mysql-test/r/ndb_autodiscover.result +++ b/mysql-test/r/ndb_autodiscover.result @@ -99,6 +99,8 @@ id int not null primary key, id2 int not null, name char(20) ) engine=ndb; +Warnings: +Note 1050 Table 't3' already exists show status like 'handler_discover%'; Variable_name Value Handler_discover 0 From 3d1658f71337aeb6ba235d7b0a4cf2198e1888bc Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 12 Sep 2005 22:47:15 +0200 Subject: [PATCH 15/18] Adding comment for force manual merge 5.0 -> wl1012 --- mysql-test/t/rpl_error_ignored_table.test | 1 + mysql-test/t/rpl_flush_tables.test | 1 + mysql-test/t/rpl_loaddata_rule_m.test | 1 + mysql-test/t/rpl_log.test | 1 + mysql-test/t/rpl_max_relay_size.test | 1 + mysql-test/t/rpl_multi_query.test | 1 + mysql-test/t/rpl_reset_slave.test | 1 + 7 files changed, 7 insertions(+) diff --git a/mysql-test/t/rpl_error_ignored_table.test b/mysql-test/t/rpl_error_ignored_table.test index a854c3621ab..cb4137c49e0 100644 --- a/mysql-test/t/rpl_error_ignored_table.test +++ b/mysql-test/t/rpl_error_ignored_table.test @@ -57,3 +57,4 @@ connection slave; sync_with_master; # End of 4.1 tests +# Adding comment for force manual merge 5.0 -> wl1012. delete me if needed diff --git a/mysql-test/t/rpl_flush_tables.test b/mysql-test/t/rpl_flush_tables.test index 48fda818890..4411d6ea1c9 100644 --- a/mysql-test/t/rpl_flush_tables.test +++ b/mysql-test/t/rpl_flush_tables.test @@ -40,3 +40,4 @@ select * from t3; # in the .err files; these are not fatal and are not reported by mysql-test-run. # End of 4.1 tests +# Adding comment for force manual merge 5.0 -> wl1012. Delete me if needed. diff --git a/mysql-test/t/rpl_loaddata_rule_m.test b/mysql-test/t/rpl_loaddata_rule_m.test index 68024c340a8..c956f2c7720 100644 --- a/mysql-test/t/rpl_loaddata_rule_m.test +++ b/mysql-test/t/rpl_loaddata_rule_m.test @@ -27,3 +27,4 @@ show binlog events from 98; drop database mysqltest; # End of 4.1 tests +# Adding comment for force manual merge 5.0 -> wl1012: Delete me diff --git a/mysql-test/t/rpl_log.test b/mysql-test/t/rpl_log.test index 899f812535a..1f71d2981c5 100644 --- a/mysql-test/t/rpl_log.test +++ b/mysql-test/t/rpl_log.test @@ -110,3 +110,4 @@ show slave status; show binlog events in 'slave-bin.000005' from 4; # End of 4.1 tests +# Adding comment for force manual merge 5.0 -> wl1012: Delete me diff --git a/mysql-test/t/rpl_max_relay_size.test b/mysql-test/t/rpl_max_relay_size.test index 8b54cf5ab7f..9b6b06e0b14 100644 --- a/mysql-test/t/rpl_max_relay_size.test +++ b/mysql-test/t/rpl_max_relay_size.test @@ -93,3 +93,4 @@ flush logs; show master status; # End of 4.1 tests +# diff --git a/mysql-test/t/rpl_multi_query.test b/mysql-test/t/rpl_multi_query.test index fa94928e13a..b4cd88f756e 100644 --- a/mysql-test/t/rpl_multi_query.test +++ b/mysql-test/t/rpl_multi_query.test @@ -29,3 +29,4 @@ drop database mysqltest; sync_slave_with_master; # End of 4.1 tests +# diff --git a/mysql-test/t/rpl_reset_slave.test b/mysql-test/t/rpl_reset_slave.test index aeac1b50110..00b1cf68294 100644 --- a/mysql-test/t/rpl_reset_slave.test +++ b/mysql-test/t/rpl_reset_slave.test @@ -48,3 +48,4 @@ sync_with_master; show status like 'slave_open_temp_tables'; # End of 4.1 tests +# From 4d29b85d1415f693e20215d159cb3513eba84aad Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 13 Sep 2005 01:44:50 +0300 Subject: [PATCH 16/18] Merged from 4.1 to 5.0. --- mysql-test/r/create.result | 17 +++++++++-------- mysql-test/r/innodb.result | 2 +- sql/item_cmpfunc.cc | 3 +-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index a463fb309f9..3e7c9d6eb4a 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -278,16 +278,16 @@ create table t1 (a int not null, b int, primary key (a)); insert into t1 values (1,1); create table if not exists t1 select 2; Warnings: -Warning 1364 Field 'a' doesn't have a default value Note 1050 Table 't1' already exists +Warning 1364 Field 'a' doesn't have a default value select * from t1; a b 1 1 0 2 create table if not exists t1 select 3 as 'a',4 as 'b'; Warnings: -Warning 1364 Field 'a' doesn't have a default value Note 1050 Table 't1' already exists +Warning 1364 Field 'a' doesn't have a default value create table if not exists t1 select 3 as 'a',3 as 'b'; ERROR 23000: Duplicate entry '3' for key 1 select * from t1; @@ -621,6 +621,13 @@ create table test.t1 like x; ERROR 42000: Incorrect database name 'NULL' drop table if exists test.t1; create database mysqltest; +use mysqltest; +create view v1 as select 'foo' from dual; +create table t1 like v1; +ERROR HY000: 'mysqltest.v1' is not BASE TABLE +drop view v1; +drop database mysqltest; +create database mysqltest; create database if not exists mysqltest character set latin2; Warnings: Note 1007 Can't create database 'mysqltest'; database exists @@ -634,9 +641,3 @@ create table if not exists t1 (a int); Warnings: Note 1050 Table 't1' already exists drop table t1; -use mysqltest; -create view v1 as select 'foo' from dual; -create table t1 like v1; -ERROR HY000: 'mysqltest.v1' is not BASE TABLE -drop view v1; -drop database mysqltest; diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 21397fade5d..559e88aad46 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -1776,7 +1776,7 @@ Variable_name Value Innodb_rows_deleted 2070 show status like "Innodb_rows_inserted"; Variable_name Value -Innodb_rows_inserted 31722 +Innodb_rows_inserted 31725 show status like "Innodb_rows_updated"; Variable_name Value Innodb_rows_updated 29530 diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 1f56e02f1cb..48839abcb10 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1017,8 +1017,7 @@ longlong Item_func_interval::val_int() 1 got error */ -bool Item_func_between::fix_fields(THD *thd, struct st_table_list *tables, - Item **ref) +bool Item_func_between::fix_fields(THD *thd, Item **ref) { if (Item_func_opt_neg::fix_fields(thd, ref)) return 1; From 74aeffda533697d88f19dabc86ffd8fcc19a8f7f Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 13 Sep 2005 01:41:15 +0200 Subject: [PATCH 17/18] mysql-test-run.pl: Corrected typo mysql-test/mysql-test-run.pl: Corrected typo --- mysql-test/mysql-test-run.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 3ef878c9854..651aa37fc7e 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -891,7 +891,7 @@ sub executable_setup () { mtr_script_exists("$path_client_bindir/mysql_fix_privilege_tables", "$glob_basedir/scripts/mysql_fix_privilege_tables"); $exe_my_print_defaults= - mtr_script_exists("path_client_bindir/my_print_defaults"); + mtr_script_exists("$path_client_bindir/my_print_defaults"); $path_language= mtr_path_exists("$glob_basedir/share/mysql/english/", "$glob_basedir/share/english/"); From 276e9f82b380d0f7c0cb2661c2cf86bac981b276 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 13 Sep 2005 02:31:47 +0200 Subject: [PATCH 18/18] innochecksum.c: Changed from C++ comments to C comments Did some adaption to MySQL Coding Style extra/innochecksum.c: Changed from C++ comments to C comments Did some adaption to MySQL Coding Style --- extra/innochecksum.c | 392 +++++++++++++++++++++++-------------------- 1 file changed, 207 insertions(+), 185 deletions(-) diff --git a/extra/innochecksum.c b/extra/innochecksum.c index bbeb96224c9..739953298af 100644 --- a/extra/innochecksum.c +++ b/extra/innochecksum.c @@ -24,7 +24,7 @@ Published with a permission. */ -// needed to have access to 64 bit file functions +/* needed to have access to 64 bit file functions */ #define _LARGEFILE_SOURCE #define _LARGEFILE64_SOURCE @@ -35,7 +35,7 @@ #include #include -// all of these ripped from InnoDB code from MySQL 4.0.22 +/* all of these ripped from InnoDB code from MySQL 4.0.22 */ #define UT_HASH_RANDOM_MASK 1463735687 #define UT_HASH_RANDOM_MASK2 1653893711 #define FIL_PAGE_LSN 16 @@ -46,18 +46,19 @@ #define FIL_PAGE_SPACE_OR_CHKSUM 0 #define UNIV_PAGE_SIZE (2 * 8192) -// command line argument to do page checks (that's it) -// another argument to specify page ranges... seek to right spot and go from there +/* command line argument to do page checks (that's it) */ +/* another argument to specify page ranges... seek to right spot and go from there */ typedef unsigned long int ulint; typedef unsigned char byte; /* innodb function in name; modified slightly to not have the ASM version (lots of #ifs that didn't apply) */ -ulint mach_read_from_4(byte *b) { - return( ((ulint)(b[0]) << 24) - + ((ulint)(b[1]) << 16) - + ((ulint)(b[2]) << 8) - + (ulint)(b[3]) +ulint mach_read_from_4(byte *b) +{ + return( ((ulint)(b[0]) << 24) + + ((ulint)(b[1]) << 16) + + ((ulint)(b[2]) << 8) + + (ulint)(b[3]) ); } @@ -80,12 +81,13 @@ ut_fold_binary( ulint len) /* in: length */ { ulint i; - ulint fold = 0; + ulint fold= 0; - for (i = 0; i < len; i++) { - fold = ut_fold_ulint_pair(fold, (ulint)(*str)); + for (i= 0; i < len; i++) + { + fold= ut_fold_ulint_pair(fold, (ulint)(*str)); - str++; + str++; } return(fold); @@ -106,12 +108,12 @@ buf_calc_page_new_checksum( checksum is stored, and also the last 8 bytes of page because there we store the old formula checksum. */ - checksum = ut_fold_binary(page + FIL_PAGE_OFFSET, - FIL_PAGE_FILE_FLUSH_LSN - FIL_PAGE_OFFSET) - + ut_fold_binary(page + FIL_PAGE_DATA, - UNIV_PAGE_SIZE - FIL_PAGE_DATA - - FIL_PAGE_END_LSN_OLD_CHKSUM); - checksum = checksum & 0xFFFFFFFF; + checksum= ut_fold_binary(page + FIL_PAGE_OFFSET, + FIL_PAGE_FILE_FLUSH_LSN - FIL_PAGE_OFFSET) + + ut_fold_binary(page + FIL_PAGE_DATA, + UNIV_PAGE_SIZE - FIL_PAGE_DATA + - FIL_PAGE_END_LSN_OLD_CHKSUM); + checksum= checksum & 0xFFFFFFFF; return(checksum); } @@ -124,183 +126,203 @@ buf_calc_page_old_checksum( { ulint checksum; - checksum = ut_fold_binary(page, FIL_PAGE_FILE_FLUSH_LSN); + checksum= ut_fold_binary(page, FIL_PAGE_FILE_FLUSH_LSN); - checksum = checksum & 0xFFFFFFFF; + checksum= checksum & 0xFFFFFFFF; return(checksum); } -int main(int argc, char **argv) { - FILE *f; // our input file - byte *p; // storage of pages read - int bytes; // bytes read count - ulint ct; // current page number (0 based) - int now; // current time - int lastt; // last time - ulint oldcsum, oldcsumfield, csum, csumfield, logseq, logseqfield; // ulints for checksum storage - struct stat st; // for stat, if you couldn't guess - unsigned long long int size; // size of file (has to be 64 bits) - ulint pages; // number of pages in file - ulint start_page = 0, end_page = 0, use_end_page = 0; // for starting and ending at certain pages - off_t offset = 0; - int just_count = 0; // if true, just print page count - int verbose = 0; - int debug = 0; - int c; - int fd; +int main(int argc, char **argv) +{ + FILE *f; /* our input file */ + byte *p; /* storage of pages read */ + int bytes; /* bytes read count */ + ulint ct; /* current page number (0 based) */ + int now; /* current time */ + int lastt; /* last time */ + ulint oldcsum, oldcsumfield, csum, csumfield, logseq, logseqfield; /* ulints for checksum storage */ + struct stat st; /* for stat, if you couldn't guess */ + unsigned long long int size; /* size of file (has to be 64 bits) */ + ulint pages; /* number of pages in file */ + ulint start_page= 0, end_page= 0, use_end_page= 0; /* for starting and ending at certain pages */ + off_t offset= 0; + int just_count= 0; /* if true, just print page count */ + int verbose= 0; + int debug= 0; + int c; + int fd; - // remove arguments - while ((c = getopt(argc, argv, "cvds:e:p:")) != -1) { - switch (c) { - case 'v': - verbose = 1; - break; - case 'c': - just_count = 1; - break; - case 's': - start_page = atoi(optarg); - break; - case 'e': - end_page = atoi(optarg); - use_end_page = 1; - break; - case 'p': - start_page = atoi(optarg); - end_page = atoi(optarg); - use_end_page = 1; - break; - case 'd': - debug = 1; - break; - case ':': - fprintf(stderr, "option -%c requires an argument\n", optopt); - return 1; - break; - case '?': - fprintf(stderr, "unrecognized option: -%c\n", optopt); - return 1; - break; - } + /* remove arguments */ + while ((c= getopt(argc, argv, "cvds:e:p:")) != -1) + { + switch (c) + { + case 'v': + verbose= 1; + break; + case 'c': + just_count= 1; + break; + case 's': + start_page= atoi(optarg); + break; + case 'e': + end_page= atoi(optarg); + use_end_page= 1; + break; + case 'p': + start_page= atoi(optarg); + end_page= atoi(optarg); + use_end_page= 1; + break; + case 'd': + debug= 1; + break; + case ':': + fprintf(stderr, "option -%c requires an argument\n", optopt); + return 1; + break; + case '?': + fprintf(stderr, "unrecognized option: -%c\n", optopt); + return 1; + break; } + } - // debug implies verbose... - if (debug) verbose = 1; + /* debug implies verbose... */ + if (debug) verbose= 1; - // make sure we have the right arguments - if (optind >= argc) { - printf("InnoDB offline file checksum utility.\n"); - printf("usage: %s [-c] [-s ] [-e ] [-p ] [-v] [-d] \n", argv[0]); - printf("\t-c\tprint the count of pages in the file\n"); - printf("\t-s n\tstart on this page number (0 based)\n"); - printf("\t-e n\tend at this page number (0 based)\n"); - printf("\t-p n\tcheck only this page (0 based)\n"); - printf("\t-v\tverbose (prints progress every 5 seconds)\n"); - printf("\t-d\tdebug mode (prints checksums for each page)\n"); - return 1; - } + /* make sure we have the right arguments */ + if (optind >= argc) + { + printf("InnoDB offline file checksum utility.\n"); + printf("usage: %s [-c] [-s ] [-e ] [-p ] [-v] [-d] \n", argv[0]); + printf("\t-c\tprint the count of pages in the file\n"); + printf("\t-s n\tstart on this page number (0 based)\n"); + printf("\t-e n\tend at this page number (0 based)\n"); + printf("\t-p n\tcheck only this page (0 based)\n"); + printf("\t-v\tverbose (prints progress every 5 seconds)\n"); + printf("\t-d\tdebug mode (prints checksums for each page)\n"); + return 1; + } - // stat the file to get size and page count - if (stat(argv[optind], &st)) { - perror("error statting file"); - return 1; - } - size = st.st_size; - pages = size / UNIV_PAGE_SIZE; - if (just_count) { - printf("%lu\n", pages); - return 0; - } else if (verbose) { - printf("file %s = %llu bytes (%lu pages)...\n", argv[1], size, pages); - printf("checking pages in range %lu to %lu\n", start_page, use_end_page ? end_page : (pages - 1)); - } - - // open the file for reading - f = fopen(argv[optind], "r"); - if (!f) { - perror("error opening file"); - return 1; - } - - // seek to the necessary position - if (start_page) { - fd = fileno(f); - if (!fd) { - perror("unable to obtain file descriptor number"); - return 1; - } - - offset = (off_t)start_page * (off_t)UNIV_PAGE_SIZE; - - if (lseek(fd, offset, SEEK_SET) != offset) { - perror("unable to seek to necessary offset"); - return 1; - } - } - - // allocate buffer for reading (so we don't realloc every time) - p = (byte *)malloc(UNIV_PAGE_SIZE); - - // main checksumming loop - ct = start_page; - lastt = 0; - while (!feof(f)) { - bytes = fread(p, 1, UNIV_PAGE_SIZE, f); - if (!bytes && feof(f)) return 0; - if (bytes != UNIV_PAGE_SIZE) { - fprintf(stderr, "bytes read (%d) doesn't match universal page size (%d)\n", bytes, UNIV_PAGE_SIZE); - return 1; - } - - // check the "stored log sequence numbers" - logseq = mach_read_from_4(p + FIL_PAGE_LSN + 4); - logseqfield = mach_read_from_4(p + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM + 4); - if (debug) - printf("page %lu: log sequence number: first = %lu; second = %lu\n", ct, logseq, logseqfield); - if (logseq != logseqfield) { - fprintf(stderr, "page %lu invalid (fails log sequence number check)\n", ct); - return 1; - } - - // check old method of checksumming - oldcsum = buf_calc_page_old_checksum(p); - oldcsumfield = mach_read_from_4(p + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM); - if (debug) - printf("page %lu: old style: calculated = %lu; recorded = %lu\n", ct, oldcsum, oldcsumfield); - if (oldcsumfield != mach_read_from_4(p + FIL_PAGE_LSN) && oldcsumfield != oldcsum) { - fprintf(stderr, "page %lu invalid (fails old style checksum)\n", ct); - return 1; - } - - // now check the new method - csum = buf_calc_page_new_checksum(p); - csumfield = mach_read_from_4(p + FIL_PAGE_SPACE_OR_CHKSUM); - if (debug) - printf("page %lu: new style: calculated = %lu; recorded = %lu\n", ct, csum, csumfield); - if (csumfield != 0 && csum != csumfield) { - fprintf(stderr, "page %lu invalid (fails new style checksum)\n", ct); - return 1; - } - - // end if this was the last page we were supposed to check - if (use_end_page && (ct >= end_page)) - return 0; - - // do counter increase and progress printing - ct++; - if (verbose) { - if (ct % 64 == 0) { - now = time(0); - if (!lastt) lastt = now; - if (now - lastt >= 1) { - printf("page %lu okay: %.3f%% done\n", (ct - 1), (float) ct / pages * 100); - lastt = now; - } - } - } - } + /* stat the file to get size and page count */ + if (stat(argv[optind], &st)) + { + perror("error statting file"); + return 1; + } + size= st.st_size; + pages= size / UNIV_PAGE_SIZE; + if (just_count) + { + printf("%lu\n", pages); return 0; + } + else if (verbose) + { + printf("file %s= %llu bytes (%lu pages)...\n", argv[1], size, pages); + printf("checking pages in range %lu to %lu\n", start_page, use_end_page ? end_page : (pages - 1)); + } + + /* open the file for reading */ + f= fopen(argv[optind], "r"); + if (!f) + { + perror("error opening file"); + return 1; + } + + /* seek to the necessary position */ + if (start_page) + { + fd= fileno(f); + if (!fd) + { + perror("unable to obtain file descriptor number"); + return 1; + } + + offset= (off_t)start_page * (off_t)UNIV_PAGE_SIZE; + + if (lseek(fd, offset, SEEK_SET) != offset) + { + perror("unable to seek to necessary offset"); + return 1; + } + } + + /* allocate buffer for reading (so we don't realloc every time) */ + p= (byte *)malloc(UNIV_PAGE_SIZE); + + /* main checksumming loop */ + ct= start_page; + lastt= 0; + while (!feof(f)) + { + bytes= fread(p, 1, UNIV_PAGE_SIZE, f); + if (!bytes && feof(f)) return 0; + if (bytes != UNIV_PAGE_SIZE) + { + fprintf(stderr, "bytes read (%d) doesn't match universal page size (%d)\n", bytes, UNIV_PAGE_SIZE); + return 1; + } + + /* check the "stored log sequence numbers" */ + logseq= mach_read_from_4(p + FIL_PAGE_LSN + 4); + logseqfield= mach_read_from_4(p + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM + 4); + if (debug) + printf("page %lu: log sequence number: first = %lu; second = %lu\n", ct, logseq, logseqfield); + if (logseq != logseqfield) + { + fprintf(stderr, "page %lu invalid (fails log sequence number check)\n", ct); + return 1; + } + + /* check old method of checksumming */ + oldcsum= buf_calc_page_old_checksum(p); + oldcsumfield= mach_read_from_4(p + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM); + if (debug) + printf("page %lu: old style: calculated = %lu; recorded = %lu\n", ct, oldcsum, oldcsumfield); + if (oldcsumfield != mach_read_from_4(p + FIL_PAGE_LSN) && oldcsumfield != oldcsum) + { + fprintf(stderr, "page %lu invalid (fails old style checksum)\n", ct); + return 1; + } + + /* now check the new method */ + csum= buf_calc_page_new_checksum(p); + csumfield= mach_read_from_4(p + FIL_PAGE_SPACE_OR_CHKSUM); + if (debug) + printf("page %lu: new style: calculated = %lu; recorded = %lu\n", ct, csum, csumfield); + if (csumfield != 0 && csum != csumfield) + { + fprintf(stderr, "page %lu invalid (fails new style checksum)\n", ct); + return 1; + } + + /* end if this was the last page we were supposed to check */ + if (use_end_page && (ct >= end_page)) + return 0; + + /* do counter increase and progress printing */ + ct++; + if (verbose) + { + if (ct % 64 == 0) + { + now= time(0); + if (!lastt) lastt= now; + if (now - lastt >= 1) + { + printf("page %lu okay: %.3f%% done\n", (ct - 1), (float) ct / pages * 100); + lastt= now; + } + } + } + } + return 0; }