summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgluh@gluh.mysql.r18.ru <>2005-02-07 11:57:14 +0300
committergluh@gluh.mysql.r18.ru <>2005-02-07 11:57:14 +0300
commit15273035cecff433e2d0dde7044db43f025a1a34 (patch)
treeb781287b8eacad029c1a729fa23cb8786b5ce69f
parent11435fdfad67b25f438ebc53cbd205a5986b9d18 (diff)
parente17b57d5c089bf2c2752ea640ce2b4f54d60043c (diff)
downloadmariadb-git-15273035cecff433e2d0dde7044db43f025a1a34.tar.gz
Merge sgluhov@bk-internal.mysql.com:/home/bk/mysql-5.0
into gluh.mysql.r18.ru:/home/gluh/MySQL/mysql-5.0
-rwxr-xr-xBUILD/compile-pentium-debug2
-rwxr-xr-xBUILD/compile-pentium-debug-max2
-rw-r--r--BitKeeper/etc/logging_ok3
-rw-r--r--Build-tools/Do-solaris-pkg181
-rw-r--r--client/mysqlcheck.c2
-rw-r--r--configure.in16
-rw-r--r--include/ft_global.h2
-rw-r--r--include/mysql.h11
-rw-r--r--innobase/page/page0cur.c6
-rw-r--r--myisam/ft_boolean_search.c7
-rw-r--r--myisam/ft_static.c5
-rw-r--r--myisam/ftdefs.h2
-rw-r--r--mysql-test/include/have_multi_ndb.inc28
-rw-r--r--mysql-test/include/have_ndb.inc4
-rw-r--r--mysql-test/lib/mtr_cases.pl270
-rw-r--r--mysql-test/mysql-test-run.sh4
-rw-r--r--mysql-test/r/drop_temp_table.result16
-rw-r--r--mysql-test/r/func_group.result12
-rw-r--r--mysql-test/r/func_misc.result21
-rw-r--r--mysql-test/r/insert_select.result.es12
-rw-r--r--mysql-test/r/limit.result9
-rw-r--r--mysql-test/r/ndb_basic.result34
-rw-r--r--mysql-test/r/ndb_cache.result182
-rw-r--r--mysql-test/r/ndb_cache2.result193
-rw-r--r--mysql-test/r/ndb_cache_multi.result72
-rw-r--r--mysql-test/r/ndb_cache_multi2.result74
-rw-r--r--mysql-test/r/ndb_multi.result49
-rw-r--r--mysql-test/r/server_id.require2
-rw-r--r--mysql-test/r/server_id1.require2
-rw-r--r--mysql-test/r/subselect.result12
-rw-r--r--mysql-test/r/subselect_innodb.result12
-rw-r--r--mysql-test/r/type_date.result8
-rw-r--r--mysql-test/r/type_float.result.es14
-rw-r--r--mysql-test/r/type_ranges.result.es176
-rw-r--r--mysql-test/r/union.result36
-rw-r--r--mysql-test/r/update.result7
-rw-r--r--mysql-test/t/drop_temp_table.test3
-rw-r--r--mysql-test/t/func_group.test14
-rw-r--r--mysql-test/t/func_misc.test15
-rw-r--r--mysql-test/t/limit.test10
-rw-r--r--mysql-test/t/ndb_basic.test38
-rw-r--r--mysql-test/t/ndb_cache.test108
-rw-r--r--mysql-test/t/ndb_cache2.test126
-rw-r--r--mysql-test/t/ndb_cache_multi.test64
-rw-r--r--mysql-test/t/ndb_cache_multi2.test71
-rw-r--r--mysql-test/t/ndb_multi.test44
-rw-r--r--mysql-test/t/subselect.test14
-rw-r--r--mysql-test/t/subselect_innodb.test14
-rw-r--r--mysql-test/t/type_date.test7
-rw-r--r--mysql-test/t/union.test35
-rw-r--r--mysql-test/t/update.test9
-rw-r--r--mysys/my_alloc.c6
-rw-r--r--ndb/include/ndbapi/NdbDictionary.hpp6
-rw-r--r--ndb/src/common/util/NdbSqlUtil.cpp36
-rw-r--r--ndb/src/kernel/blocks/dbdih/DbdihMain.cpp2
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp5
-rw-r--r--ndb/src/ndbapi/NdbDictionaryImpl.cpp2
-rw-r--r--scripts/Makefile.am3
-rw-r--r--scripts/make_binary_distribution.sh2
-rw-r--r--scripts/mysql_config.sh7
-rw-r--r--sql/field.cc35
-rw-r--r--sql/field.h1
-rw-r--r--sql/ha_innodb.cc3
-rw-r--r--sql/ha_innodb.h20
-rw-r--r--sql/ha_myisam.h8
-rw-r--r--sql/ha_ndbcluster.cc389
-rw-r--r--sql/ha_ndbcluster.h10
-rw-r--r--sql/handler.cc9
-rw-r--r--sql/handler.h15
-rw-r--r--sql/item.cc65
-rw-r--r--sql/item.h4
-rw-r--r--sql/item_cmpfunc.cc4
-rw-r--r--sql/item_func.cc25
-rw-r--r--sql/item_subselect.cc2
-rw-r--r--sql/mysql_priv.h5
-rw-r--r--sql/mysqld.cc7
-rw-r--r--sql/opt_range.cc2
-rw-r--r--sql/set_var.cc3
-rw-r--r--sql/sp_head.cc4
-rw-r--r--sql/sql_base.cc75
-rw-r--r--sql/sql_cache.cc67
-rw-r--r--sql/sql_cache.h12
-rw-r--r--sql/sql_lex.cc14
-rw-r--r--sql/sql_parse.cc14
-rw-r--r--sql/sql_select.cc4
-rw-r--r--sql/sql_string.h10
-rw-r--r--sql/sql_union.cc14
-rw-r--r--sql/sql_yacc.yy9
-rw-r--r--sql/table.h18
-rw-r--r--zlib/Makefile.am2
90 files changed, 2639 insertions, 340 deletions
diff --git a/BUILD/compile-pentium-debug b/BUILD/compile-pentium-debug
index 4a9d0e74599..7957caead29 100755
--- a/BUILD/compile-pentium-debug
+++ b/BUILD/compile-pentium-debug
@@ -1,7 +1,7 @@
#! /bin/sh
path=`dirname $0`
-. "$path/SETUP.sh"
+. "$path/SETUP.sh" $@ --with-debug=full
extra_flags="$pentium_cflags $debug_cflags"
c_warnings="$c_warnings $debug_extra_warnings"
diff --git a/BUILD/compile-pentium-debug-max b/BUILD/compile-pentium-debug-max
index 420657e0b73..7a11ad24c44 100755
--- a/BUILD/compile-pentium-debug-max
+++ b/BUILD/compile-pentium-debug-max
@@ -1,7 +1,7 @@
#! /bin/sh
path=`dirname $0`
-. "$path/SETUP.sh"
+. "$path/SETUP.sh" $@ --with-debug=full
extra_flags="$pentium_cflags $debug_cflags $max_cflags"
c_warnings="$c_warnings $debug_extra_warnings"
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok
index 0cd599d040a..fe4e377918a 100644
--- a/BitKeeper/etc/logging_ok
+++ b/BitKeeper/etc/logging_ok
@@ -153,6 +153,7 @@ mronstrom@build.mysql.com
mronstrom@mysql.com
mskold@mysql.com
msvensson@build.mysql.com
+msvensson@neptunus.homeip.net
mwagner@cash.mwagner.org
mwagner@evoq.mwagner.org
mwagner@here.mwagner.org
@@ -161,6 +162,7 @@ mwagner@work.mysql.com
mydev@mysql.com
mysql@home.(none)
mysql@mc04.(none)
+mysqldev@bk-internal.mysql.com
mysqldev@build.mysql2.com
mysqldev@melody.local
mysqldev@mysql.com
@@ -197,6 +199,7 @@ ram@gw.mysql.r18.ru
ram@gw.udmsearch.izhnet.ru
ram@mysql.r18.ru
ram@ram.(none)
+ramil@mysql.com
ranger@regul.home.lan
rburnett@build.mysql.com
reggie@bob.(none)
diff --git a/Build-tools/Do-solaris-pkg b/Build-tools/Do-solaris-pkg
new file mode 100644
index 00000000000..374113b28a1
--- /dev/null
+++ b/Build-tools/Do-solaris-pkg
@@ -0,0 +1,181 @@
+#!/usr/bin/perl
+#
+# Script to create Solaris packages
+#
+$INTERACTIVE= 0;
+$hostname= `hostname`;
+$find = "/usr/bin/find";
+$pkgproto = "/usr/bin/pkgproto";
+$pkgmk = "/usr/bin/pkgmk -o";
+$pkgtrans = "/usr/bin/pkgtrans";
+$temp = "/tmp/prototype$$";
+$prototype = "prototype";
+$pkginfo = "pkginfo";
+($gid ,$pkg ,$uid ,$userInfo ,$email ,$quota ,$group ,$passwd
+,$category ,$userHome ,$vendor ,$loginShell ,$pstamp ,$basedir)=();
+
+$fullname = shift @ARGV;
+$fullname or die "No package name was specified";
+-d $fullname or die "That directory is not present!";
+
+$fullname =~ s,/+$,,; # Remove ending slash if any
+
+$pkgdir= `cd ../$hostname; pwd`;
+$pwd = `pwd`;
+if ($pwd =~ '\/usr\/local') {
+ $pwd = $`;
+}
+die "Wrong location, please cd to <PKGBASE>/usr/local/ and run again.\n"
+ if ($pwd eq "");
+
+system ("$find . -print | $pkgproto > $temp");
+open (PREPROTO,"<$temp") or die "Unable to read prototype information ($!)\n";
+open (PROTO,">$prototype") or die "Unable to write file prototype ($!)\n";
+print PROTO "i pkginfo=./$pkginfo\n";
+while (<PREPROTO>) {
+ # Read the prototype information from /tmp/prototype$$
+ chomp;
+ $thisline = $_;
+ if ($thisline =~ " prototype "
+ or $thisline =~ " pkginfo ") {
+ # We don't need that line
+ } elsif ($thisline =~ "^[fd] ") {
+ # Change the ownership for files and directories
+ ($dir, $none, $file, $mode, $user, $group) = split / /,$thisline;
+ print PROTO "$dir $none $file $mode bin bin\n";
+ } else {
+ # Symlinks and other stuff should be printed as well ofcourse
+ print PROTO "$thisline\n";
+ }
+}
+close PROTO;
+close PREPROTO;
+
+# Clean up
+unlink $temp or warn "Unable to remove tempfile ($!)\n";
+
+# Now we can start building the package
+#
+# First get some info
+
+$fullname =~ /^((mysql)-.+)-([\d\.]+)-.+$/
+ or die "This name is not what I expected - \"$fullname\"";
+
+$default{"name"}= $2;
+$default{"version"}= $3;
+$default{"pkg"}= $1;
+$default{"arch"} = `uname -m`;
+chomp $default{"arch"};
+$default{"category"}= "application";
+$default{"vendor"}= "MySQL AB";
+$default{"email"}= "build\@mysql.com";
+$default{"pstamp"}= "MySQL AB Build Engineers";
+$os = `uname -r`;
+$os =~ '\.';
+$os = "sol$'";
+chomp $os;
+$default{"basedir"}= "/usr/local";
+$default{"packagename"}= $fullname . '.pkg';
+
+# Check for correctness of guessed values by userinput
+
+%questions = (
+ pkg => "Please give the name for this package",
+ name => "Now enter the real name for this package",
+ arch => "What architecture did you build the package on?",
+ version => "Enter the version number of the package",
+ category => "What category does this package belong to?",
+ vendor => "Who is the vendor of this package?",
+ email => "Enter the email adress for contact",
+ pstamp => "Enter your own name",
+ basedir => "What is the basedir this package will install into?",
+ packagename => "How should I call the packagefile?",
+);
+
+@vars = qw(pkg name arch version category vendor email pstamp basedir
+ packagename);
+foreach $varname (@vars) {
+ getvar_noq($varname);
+}
+
+if ($INTERACTIVE) {
+ while (!&chkvar()) {
+ print "\n";
+ foreach $varname (@vars) {
+ getvar($varname);
+ }
+ @vars = qw(pkg name arch version category vendor email pstamp basedir
+ packagename);
+ }
+}
+$classes = "none";
+
+# Create the pkginfo file
+
+print "\nNow creating $pkginfo file\n";
+open (PKGINFO,">$pkginfo") || die "Unable to open $pkginfo for writing ($!)\n";
+print PKGINFO "PKG=\"$pkg\"\n";
+print PKGINFO "NAME=\"$name\"\n";
+print PKGINFO "ARCH=\"$arch\"\n";
+print PKGINFO "VERSION=\"$version\"\n";
+print PKGINFO "CATEGORY=\"$category\"\n";
+print PKGINFO "VENDOR=\"$vendor\"\n";
+print PKGINFO "EMAIL=\"$email\"\n";
+print PKGINFO "PSTAMP=\"$pstamp\"\n";
+print PKGINFO "BASEDIR=\"$basedir\"\n";
+print PKGINFO "CLASSES=\"$classes\"\n";
+close PKGINFO;
+print "Done.\n";
+
+# Build and zip the package
+
+print "Building package\n";
+system ("$pkgmk -r `pwd`");
+system ("(cd /var/spool/pkg; $pkgtrans -s -o `pwd` /tmp/$packagename $pkg)");
+system ("gzip /tmp/$packagename");
+
+# Clean-up the spool area
+system ("(cd /var/spool/pkg; rm -rf $pkg)");
+unlink $pkginfo;
+unlink $prototype;
+system ("mv /tmp/${packagename}.gz $pkgdir");
+print "Done. (~/$hostname/$packagename.gz)\n";
+# The subroutines
+sub chkvar {
+ print "\n";
+
+ print "PKG=$pkg\n";
+ print "NAME=$name\n";
+ print "ARCH=$arch\n";
+ print "VERSION=$version\n";
+ print "CATEGORY=$category\n";
+ print "VENDOR=$vendor\n";
+ print "EMAIL=$email\n";
+ print "PSTAMP=$pstamp\n";
+ print "BASEDIR=$basedir\n";
+ print "PACKAGENAME=$packagename\n";
+
+
+ print "\nIs this information correct? [Y/n]: ";
+ my $answer= <STDIN>;
+ chomp $answer;
+ $answer= 'Y' if ($answer eq "");
+ $answer= uc $answer;
+ my $res= ($answer eq 'Y')? 1 : 0;
+ return($res);
+}
+
+sub getvar_noq {
+ my $questionname = "@_";
+ $$questionname = $default{$questionname};
+}
+
+sub getvar {
+ my $questionname = "@_";
+ my $ucquestionname= uc $questionname;
+ print "$ucquestionname: $questions{$questionname} [$default{\"$questionname\"}]: ";
+ my $answer = <STDIN>;
+ chomp $answer;
+ $$questionname = $answer;
+ $$questionname = $default{$questionname} if ($$questionname eq "");
+}
diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c
index 980046fe6e6..15be51853cd 100644
--- a/client/mysqlcheck.c
+++ b/client/mysqlcheck.c
@@ -195,7 +195,7 @@ static void usage(void)
puts("and you are welcome to modify and redistribute it under the GPL license.\n");
puts("This program can be used to CHECK (-c,-m,-C), REPAIR (-r), ANALYZE (-a)");
puts("or OPTIMIZE (-o) tables. Some of the options (like -e or -q) can be");
- puts("used at the same time. It works on MyISAM and in some cases on BDB tables.");
+ puts("used at the same time. Not all options are supported by all storage engines.");
puts("Please consult the MySQL manual for latest information about the");
puts("above. The options -c,-r,-a and -o are exclusive to each other, which");
puts("means that the last option will be used, if several was specified.\n");
diff --git a/configure.in b/configure.in
index b2d8d65439d..e6ae8f8f70b 100644
--- a/configure.in
+++ b/configure.in
@@ -918,9 +918,11 @@ if test "$ac_cv_header_termio_h" = "no" -a "$ac_cv_header_termios_h" = "no"
then
AC_CHECK_FUNC(gtty, , AC_CHECK_LIB(compat, gtty))
fi
-# We make a special variable for client library's to avoid including
-# thread libs in the client.
-NON_THREADED_CLIENT_LIBS="$LIBS $ZLIB_LIBS"
+
+# We make a special variable for non-threaded version of LIBS to avoid
+# including thread libs into non-threaded version of MySQL client library.
+# Later in this script LIBS will be augmented with a threads library.
+NON_THREADED_LIBS="$LIBS"
AC_MSG_CHECKING([for int8])
case $SYSTEM_TYPE in
@@ -1497,7 +1499,7 @@ then
if test -f /usr/lib/libxnet.so -a "$SYSTEM_TYPE" = "sni-sysv4"
then
LIBS="-lxnet $LIBS"
- NON_THREADED_CLIENT_LIBS="$NON_THREADED_CLIENT_LIBS -lxnet"
+ NON_THREADED_LIBS="-lxnet $NON_THREADED_LIBS"
with_named_thread="-Kthread $LDFLAGS -lxnet"
LD_FLAGS=""
CFLAGS="-Kthread $CFLAGS"
@@ -2444,7 +2446,7 @@ dnl This probably should be cleaned up more - for now the threaded
dnl client is just using plain-old libs.
sql_client_dirs="libmysql strings regex client"
linked_client_targets="linked_libmysql_sources"
-CLIENT_LIBS=$NON_THREADED_CLIENT_LIBS
+
if test "$THREAD_SAFE_CLIENT" != "no"
then
sql_client_dirs="libmysql_r $sql_client_dirs"
@@ -2452,9 +2454,11 @@ then
AC_DEFINE([THREAD_SAFE_CLIENT], [1], [Should be client be thread safe])
fi
-CLIENT_LIBS="$CLIENT_LIBS $STATIC_NSS_FLAGS"
+CLIENT_LIBS="$NON_THREADED_LIBS $openssl_libs $ZLIB_LIBS $STATIC_NSS_FLAGS"
AC_SUBST(CLIENT_LIBS)
+AC_SUBST(NON_THREADED_LIBS)
+AC_SUBST(STATIC_NSS_FLAGS)
AC_SUBST(sql_client_dirs)
AC_SUBST(linked_client_targets)
diff --git a/include/ft_global.h b/include/ft_global.h
index 94f6ad9ef51..c3f60d13a7a 100644
--- a/include/ft_global.h
+++ b/include/ft_global.h
@@ -62,7 +62,7 @@ void ft_free_stopwords(void);
#define FT_SORTED 2
#define FT_EXPAND 4 /* query expansion */
-FT_INFO *ft_init_search(uint,void *, uint, byte *, uint, byte *);
+FT_INFO *ft_init_search(uint,void *, uint, byte *, uint,CHARSET_INFO *, byte *);
my_bool ft_boolean_check_syntax_string(const byte *);
#ifdef __cplusplus
diff --git a/include/mysql.h b/include/mysql.h
index 58c314207c1..b87b865608e 100644
--- a/include/mysql.h
+++ b/include/mysql.h
@@ -337,6 +337,17 @@ typedef struct st_mysql_parameters
*/
int STDCALL mysql_server_init(int argc, char **argv, char **groups);
void STDCALL mysql_server_end(void);
+/*
+ mysql_server_init/end need to be called when using libmysqld or
+ libmysqlclient (exactly, mysql_server_init() is called by mysql_init() so
+ you don't need to call it explicitely; but you need to call
+ mysql_server_end() to free memory). The names are a bit misleading
+ (mysql_SERVER* to be used when using libmysqlCLIENT). So we add more general
+ names which suit well whether you're using libmysqld or libmysqlclient. We
+ intend to promote these aliases over the mysql_server* ones.
+*/
+#define mysql_library_init mysql_server_init
+#define mysql_library_end mysql_server_end
MYSQL_PARAMETERS *STDCALL mysql_get_parameters(void);
diff --git a/innobase/page/page0cur.c b/innobase/page/page0cur.c
index fc94fc4b1e0..488d2757115 100644
--- a/innobase/page/page0cur.c
+++ b/innobase/page/page0cur.c
@@ -311,9 +311,6 @@ page_cur_search_with_match(
low_matched_bytes = cur_matched_bytes;
} else if (cmp == -1) {
- offsets = rec_get_offsets(mid_rec, index, offsets,
- dtuple_get_n_fields_cmp(tuple), &heap);
-
if (mode == PAGE_CUR_LE_OR_EXTENDS
&& page_cur_rec_field_extends(tuple, mid_rec,
offsets, cur_matched_fields)) {
@@ -366,9 +363,6 @@ page_cur_search_with_match(
low_matched_bytes = cur_matched_bytes;
} else if (cmp == -1) {
- offsets = rec_get_offsets(mid_rec, index, offsets,
- dtuple_get_n_fields_cmp(tuple), &heap);
-
if (mode == PAGE_CUR_LE_OR_EXTENDS
&& page_cur_rec_field_extends(tuple, mid_rec,
offsets, cur_matched_fields)) {
diff --git a/myisam/ft_boolean_search.c b/myisam/ft_boolean_search.c
index 4e66bd92a94..a5b4439a57f 100644
--- a/myisam/ft_boolean_search.c
+++ b/myisam/ft_boolean_search.c
@@ -366,6 +366,7 @@ static void _ftb_init_index_search(FT_INFO *ftb)
reset_tree(& ftb->no_dupes);
}
+ ftbw->off=0; /* in case of reinit */
if (_ft2_search(ftb, ftbw, 1))
return;
}
@@ -374,7 +375,7 @@ static void _ftb_init_index_search(FT_INFO *ftb)
FT_INFO * ft_init_boolean_search(MI_INFO *info, uint keynr, byte *query,
- uint query_len)
+ uint query_len, CHARSET_INFO *cs)
{
FTB *ftb;
FTB_EXPR *ftbe;
@@ -386,8 +387,8 @@ FT_INFO * ft_init_boolean_search(MI_INFO *info, uint keynr, byte *query,
ftb->state=UNINITIALIZED;
ftb->info=info;
ftb->keynr=keynr;
- ftb->charset= ((keynr==NO_SUCH_KEY) ?
- default_charset_info : info->s->keyinfo[keynr].seg->charset);
+ ftb->charset=cs;
+ DBUG_ASSERT(keynr==NO_SUCH_KEY || cs == info->s->keyinfo[keynr].seg->charset);
ftb->with_scan=0;
ftb->lastpos=HA_OFFSET_ERROR;
bzero(& ftb->no_dupes, sizeof(TREE));
diff --git a/myisam/ft_static.c b/myisam/ft_static.c
index cf4a8dd2a73..e221950f445 100644
--- a/myisam/ft_static.c
+++ b/myisam/ft_static.c
@@ -57,11 +57,12 @@ const struct _ft_vft _ft_vft_boolean = {
FT_INFO *ft_init_search(uint flags, void *info, uint keynr,
- byte *query, uint query_len, byte *record)
+ byte *query, uint query_len, CHARSET_INFO *cs,
+ byte *record)
{
FT_INFO *res;
if (flags & FT_BOOL)
- res= ft_init_boolean_search((MI_INFO *)info, keynr, query, query_len);
+ res= ft_init_boolean_search((MI_INFO *)info, keynr, query, query_len,cs);
else
res= ft_init_nlq_search((MI_INFO *)info, keynr, query, query_len, flags,
record);
diff --git a/myisam/ftdefs.h b/myisam/ftdefs.h
index e7a0829e140..ddb9fbfead2 100644
--- a/myisam/ftdefs.h
+++ b/myisam/ftdefs.h
@@ -131,7 +131,7 @@ FT_WORD * _mi_ft_parserecord(MI_INFO *, uint, const byte *);
uint _mi_ft_parse(TREE *, MI_INFO *, uint, const byte *, my_bool);
FT_INFO *ft_init_nlq_search(MI_INFO *, uint, byte *, uint, uint, byte *);
-FT_INFO *ft_init_boolean_search(MI_INFO *, uint, byte *, uint);
+FT_INFO *ft_init_boolean_search(MI_INFO *, uint, byte *, uint, CHARSET_INFO *);
extern const struct _ft_vft _ft_vft_nlq;
int ft_nlq_read_next(FT_INFO *, char *);
diff --git a/mysql-test/include/have_multi_ndb.inc b/mysql-test/include/have_multi_ndb.inc
new file mode 100644
index 00000000000..d0c083cab86
--- /dev/null
+++ b/mysql-test/include/have_multi_ndb.inc
@@ -0,0 +1,28 @@
+# Setup connections to both MySQL Servers connected to the cluster
+connect (server1,127.0.0.1,root,,test,$MASTER_MYPORT,);
+connect (server2,127.0.0.1,root,,test,$MASTER_MYPORT1,);
+
+# Check that server1 has NDB support
+connection server1;
+disable_query_log;
+--disable_warnings
+drop table if exists t1, t2;
+--enable_warnings
+flush tables;
+@r/have_ndb.require show variables like "have_ndbcluster";
+@r/server_id.require show variables like "server_id";
+enable_query_log;
+
+# Check that server2 has NDB support
+connection server2;
+disable_query_log;
+--disable_warnings
+drop table if exists t1, t2;
+--enable_warnings
+flush tables;
+@r/have_ndb.require show variables like "have_ndbcluster";
+@r/server_id1.require show variables like "server_id";
+enable_query_log;
+
+# Set the default connection to 'server1'
+connection server1;
diff --git a/mysql-test/include/have_ndb.inc b/mysql-test/include/have_ndb.inc
index 84e60657876..d000a954733 100644
--- a/mysql-test/include/have_ndb.inc
+++ b/mysql-test/include/have_ndb.inc
@@ -2,6 +2,4 @@
disable_query_log;
show variables like "have_ndbcluster";
enable_query_log;
-#connect (server1,127.0.0.1,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK);
-#connect (server2,127.0.0.1,root,,test,$MASTER_MYPORT1,$MASTER_MYSOCK1);
-#connection server1;
+
diff --git a/mysql-test/lib/mtr_cases.pl b/mysql-test/lib/mtr_cases.pl
new file mode 100644
index 00000000000..5977bb380cf
--- /dev/null
+++ b/mysql-test/lib/mtr_cases.pl
@@ -0,0 +1,270 @@
+# -*- cperl -*-
+
+# This is a library file used by the Perl version of mysql-test-run,
+# and is part of the translation of the Bourne shell script with the
+# same name.
+
+use strict;
+
+sub collect_test_cases ($);
+sub collect_one_test_case ($$$$$);
+
+##############################################################################
+#
+# Collect information about test cases we are to run
+#
+##############################################################################
+
+sub collect_test_cases ($) {
+ my $suite= shift; # Test suite name
+
+ my $testdir;
+ my $resdir;
+
+ if ( $suite eq "main" )
+ {
+ $testdir= "$::glob_mysql_test_dir/t";
+ $resdir= "$::glob_mysql_test_dir/r";
+ }
+ else
+ {
+ $testdir= "$::glob_mysql_test_dir/suite/$suite/t";
+ $resdir= "$::glob_mysql_test_dir/suite/$suite/r";
+ }
+
+ my $cases = []; # Array of hash, will be array of C struct
+
+ opendir(TESTDIR, $testdir) or mtr_error("Can't open dir \"$testdir\": $!");
+
+ if ( @::opt_cases )
+ {
+ foreach my $tname ( @::opt_cases ) { # Run in specified order, no sort
+ my $elem= "$tname.test";
+ if ( ! -f "$testdir/$elem")
+ {
+ mtr_error("Test case $tname ($testdir/$elem) is not found");
+ }
+ collect_one_test_case($testdir,$resdir,$tname,$elem,$cases);
+ }
+ closedir TESTDIR;
+ }
+ else
+ {
+ foreach my $elem ( sort readdir(TESTDIR) ) {
+ my $tname= mtr_match_extension($elem,"test");
+ next if ! defined $tname;
+ next if $::opt_do_test and ! defined mtr_match_prefix($elem,$::opt_do_test);
+
+ collect_one_test_case($testdir,$resdir,$tname,$elem,$cases);
+ }
+ closedir TESTDIR;
+ }
+
+ # To speed things up, we sort first in if the test require a restart
+ # or not, second in alphanumeric order.
+
+# @$cases = sort {
+# if ( $a->{'master_restart'} and $b->{'master_restart'} or
+# ! $a->{'master_restart'} and ! $b->{'master_restart'} )
+# {
+# return $a->{'name'} cmp $b->{'name'};
+# }
+# if ( $a->{'master_restart'} )
+# {
+# return 1; # Is greater
+# }
+# else
+# {
+# return -1; # Is less
+# }
+# } @$cases;
+
+ return $cases;
+}
+
+
+##############################################################################
+#
+# Collect information about a single test case
+#
+##############################################################################
+
+
+sub collect_one_test_case($$$$$) {
+ my $testdir= shift;
+ my $resdir= shift;
+ my $tname= shift;
+ my $elem= shift;
+ my $cases= shift;
+
+ my $path= "$testdir/$elem";
+
+ # ----------------------------------------------------------------------
+ # Skip some tests silently
+ # ----------------------------------------------------------------------
+
+ if ( $::opt_start_from and $tname lt $::opt_start_from )
+ {
+ return;
+ }
+
+ # ----------------------------------------------------------------------
+ # Skip some tests but include in list, just mark them to skip
+ # ----------------------------------------------------------------------
+
+ my $tinfo= {};
+ $tinfo->{'name'}= $tname;
+ $tinfo->{'result_file'}= "$resdir/$tname.result";
+ push(@$cases, $tinfo);
+
+ if ( $::opt_skip_test and defined mtr_match_prefix($tname,$::opt_skip_test) )
+ {
+ $tinfo->{'skip'}= 1;
+ return;
+ }
+
+ # FIXME temporary solution, we have a hard coded list of test cases to
+ # skip if we are using the embedded server
+
+ if ( $::glob_use_embedded_server and
+ mtr_match_any_exact($tname,\@::skip_if_embedded_server) )
+ {
+ $tinfo->{'skip'}= 1;
+ return;
+ }
+
+ # ----------------------------------------------------------------------
+ # Collect information about test case
+ # ----------------------------------------------------------------------
+
+ $tinfo->{'path'}= $path;
+ $tinfo->{'timezone'}= "GMT-3"; # for UNIX_TIMESTAMP tests to work
+
+ if ( defined mtr_match_prefix($tname,"rpl") )
+ {
+ if ( $::opt_skip_rpl )
+ {
+ $tinfo->{'skip'}= 1;
+ return;
+ }
+
+ $tinfo->{'slave_num'}= 1; # Default, use one slave
+
+ # FIXME currently we always restart slaves
+ $tinfo->{'slave_restart'}= 1;
+
+ if ( $tname eq 'rpl_failsafe' or $tname eq 'rpl_chain_temp_table' )
+ {
+# $tinfo->{'slave_num'}= 3; # Not 3 ? Check old code, strange
+ }
+ }
+
+ # FIXME what about embedded_server + ndbcluster, skip ?!
+
+ my $master_opt_file= "$testdir/$tname-master.opt";
+ my $slave_opt_file= "$testdir/$tname-slave.opt";
+ my $slave_mi_file= "$testdir/$tname.slave-mi";
+ my $master_sh= "$testdir/$tname-master.sh";
+ my $slave_sh= "$testdir/$tname-slave.sh";
+ my $disabled= "$testdir/$tname.disabled";
+
+ $tinfo->{'master_opt'}= [];
+ $tinfo->{'slave_opt'}= [];
+ $tinfo->{'slave_mi'}= [];
+
+ if ( -f $master_opt_file )
+ {
+ $tinfo->{'master_restart'}= 1; # We think so for now
+ # This is a dirty hack from old mysql-test-run, we use the opt file
+ # to flag other things as well, it is not a opt list at all
+ my $extra_master_opt= mtr_get_opts_from_file($master_opt_file);
+
+ foreach my $opt (@$extra_master_opt)
+ {
+ my $value;
+
+ $value= mtr_match_prefix($opt, "--timezone=");
+
+ if ( defined $value )
+ {
+ $tinfo->{'timezone'}= $value;
+ $extra_master_opt= [];
+ $tinfo->{'master_restart'}= 0;
+ last;
+ }
+
+ $value= mtr_match_prefix($opt, "--result-file=");
+
+ if ( defined $value )
+ {
+ $tinfo->{'result_file'}= "r/$value.result";
+ if ( $::opt_result_ext and $::opt_record or
+ -f "$tinfo->{'result_file'}$::opt_result_ext")
+ {
+ $tinfo->{'result_file'}.= $::opt_result_ext;
+ }
+ $extra_master_opt= [];
+ $tinfo->{'master_restart'}= 0;
+ last;
+ }
+ }
+
+ $tinfo->{'master_opt'}= $extra_master_opt;
+ }
+
+ if ( -f $slave_opt_file )
+ {
+ $tinfo->{'slave_opt'}= mtr_get_opts_from_file($slave_opt_file);
+ $tinfo->{'slave_restart'}= 1;
+ }
+
+ if ( -f $slave_mi_file )
+ {
+ $tinfo->{'slave_mi'}= mtr_get_opts_from_file($slave_mi_file);
+ $tinfo->{'slave_restart'}= 1;
+ }
+
+ if ( -f $master_sh )
+ {
+ if ( $::glob_win32_perl )
+ {
+ $tinfo->{'skip'}= 1;
+ }
+ else
+ {
+ $tinfo->{'master_sh'}= $master_sh;
+ $tinfo->{'master_restart'}= 1;
+ }
+ }
+
+ if ( -f $slave_sh )
+ {
+ if ( $::glob_win32_perl )
+ {
+ $tinfo->{'skip'}= 1;
+ }
+ else
+ {
+ $tinfo->{'slave_sh'}= $slave_sh;
+ $tinfo->{'slave_restart'}= 1;
+ }
+ }
+
+ if ( -f $disabled )
+ {
+ $tinfo->{'skip'}= 1;
+ $tinfo->{'disable'}= 1; # Sub type of 'skip'
+ $tinfo->{'comment'}= mtr_fromfile($disabled);
+ }
+
+ # We can't restart a running server that may be in use
+
+ if ( $::glob_use_running_server and
+ ( $tinfo->{'master_restart'} or $tinfo->{'slave_restart'} ) )
+ {
+ $tinfo->{'skip'}= 1;
+ }
+}
+
+
+1;
diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh
index fadc14d4e1b..42f96789eef 100644
--- a/mysql-test/mysql-test-run.sh
+++ b/mysql-test/mysql-test-run.sh
@@ -259,13 +259,13 @@ while test $# -gt 0; do
--embedded-server)
USE_EMBEDDED_SERVER=1
USE_MANAGER=0 NO_SLAVE=1
- USE_RUNNING_SERVER=""
+ USE_RUNNING_SERVER=0
RESULT_EXT=".es"
TEST_MODE="$TEST_MODE embedded" ;;
--purify)
USE_PURIFY=1
USE_MANAGER=0
- USE_RUNNING_SERVER=""
+ USE_RUNNING_SERVER=0
TEST_MODE="$TEST_MODE purify" ;;
--user=*) DBUSER=`$ECHO "$1" | $SED -e "s;--user=;;"` ;;
--force) FORCE=1 ;;
diff --git a/mysql-test/r/drop_temp_table.result b/mysql-test/r/drop_temp_table.result
index 8a2a75f1723..163fc845e88 100644
--- a/mysql-test/r/drop_temp_table.result
+++ b/mysql-test/r/drop_temp_table.result
@@ -1,7 +1,9 @@
reset master;
create database `drop-temp+table-test`;
use `drop-temp+table-test`;
+create temporary table shortn1 (a int);
create temporary table `table:name` (a int);
+create temporary table shortn2 (a int);
select get_lock("a",10);
get_lock("a",10)
1
@@ -10,9 +12,13 @@ get_lock("a",10)
1
show binlog events;
Log_name Pos Event_type Server_id End_log_pos Info
-master-bin.000001 4 Format_desc 1 95 Server ver: VERSION, Binlog ver: 4
-master-bin.000001 95 Query 1 213 create database `drop-temp+table-test`
-master-bin.000001 213 Query 1 336 use `drop-temp+table-test`; create temporary table `table:name` (a int)
-master-bin.000001 336 Query 1 494 use `drop-temp+table-test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `drop-temp+table-test`.`table:name`
-master-bin.000001 494 Query 1 594 use `drop-temp+table-test`; DO RELEASE_LOCK("a")
+master-bin.000001 # Format_desc 1 # Server ver: VERSION, Binlog ver: 4
+master-bin.000001 # Query 1 # create database `drop-temp+table-test`
+master-bin.000001 # Query 1 # use `drop-temp+table-test`; create temporary table shortn1 (a int)
+master-bin.000001 # Query 1 # use `drop-temp+table-test`; create temporary table `table:name` (a int)
+master-bin.000001 # Query 1 # use `drop-temp+table-test`; create temporary table shortn2 (a int)
+master-bin.000001 # Query 1 # use `drop-temp+table-test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `drop-temp+table-test`.`shortn2`
+master-bin.000001 # Query 1 # use `drop-temp+table-test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `drop-temp+table-test`.`table:name`
+master-bin.000001 # Query 1 # use `drop-temp+table-test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `drop-temp+table-test`.`shortn1`
+master-bin.000001 # Query 1 # use `drop-temp+table-test`; DO RELEASE_LOCK("a")
drop database `drop-temp+table-test`;
diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result
index df95193043e..fdadd378ceb 100644
--- a/mysql-test/r/func_group.result
+++ b/mysql-test/r/func_group.result
@@ -737,3 +737,15 @@ one 2
two 2
three 1
drop table t1;
+create table t1(f1 datetime);
+insert into t1 values (now());
+create table t2 select f2 from (select max(now()) f2 from t1) a;
+show columns from t2;
+Field Type Null Key Default Extra
+f2 datetime NO 0000-00-00 00:00:00
+drop table t2;
+create table t2 select f2 from (select now() f2 from t1) a;
+show columns from t2;
+Field Type Null Key Default Extra
+f2 datetime NO 0000-00-00 00:00:00
+drop table t2, t1;
diff --git a/mysql-test/r/func_misc.result b/mysql-test/r/func_misc.result
index 5a9f0f68228..2d464c891bf 100644
--- a/mysql-test/r/func_misc.result
+++ b/mysql-test/r/func_misc.result
@@ -28,3 +28,24 @@ length(format('nan', 2)) > 0
select concat("$",format(2500,2));
concat("$",format(2500,2))
$2,500.00
+create table t1 ( a timestamp );
+insert into t1 values ( '2004-01-06 12:34' );
+select a from t1 where left(a+0,6) in ( left(20040106,6) );
+a
+2004-01-06 12:34:00
+select a from t1 where left(a+0,6) = ( left(20040106,6) );
+a
+2004-01-06 12:34:00
+select a from t1 where right(a+0,6) in ( right(20040106123400,6) );
+a
+2004-01-06 12:34:00
+select a from t1 where right(a+0,6) = ( right(20040106123400,6) );
+a
+2004-01-06 12:34:00
+select a from t1 where mid(a+0,6,3) in ( mid(20040106123400,6,3) );
+a
+2004-01-06 12:34:00
+select a from t1 where mid(a+0,6,3) = ( mid(20040106123400,6,3) );
+a
+2004-01-06 12:34:00
+drop table t1;
diff --git a/mysql-test/r/insert_select.result.es b/mysql-test/r/insert_select.result.es
index 9e11402733d..9cac6d31b8f 100644
--- a/mysql-test/r/insert_select.result.es
+++ b/mysql-test/r/insert_select.result.es
@@ -633,3 +633,15 @@ No Field Count
0 1 100
0 2 100
drop table t1, t2;
+CREATE TABLE t1 (
+ID int(11) NOT NULL auto_increment,
+NO int(11) NOT NULL default '0',
+SEQ int(11) NOT NULL default '0',
+PRIMARY KEY (ID),
+KEY t1$NO (SEQ,NO)
+) ENGINE=MyISAM;
+INSERT INTO t1 (SEQ, NO) SELECT "1" AS SEQ, IF(MAX(NO) IS NULL, 0, MAX(NO)) + 1 AS NO FROM t1 WHERE (SEQ = 1);
+select SQL_BUFFER_RESULT * from t1 WHERE (SEQ = 1);
+ID NO SEQ
+1 1 1
+drop table t1;
diff --git a/mysql-test/r/limit.result b/mysql-test/r/limit.result
index c82105e6a49..6a3d2bffab0 100644
--- a/mysql-test/r/limit.result
+++ b/mysql-test/r/limit.result
@@ -67,3 +67,12 @@ SELECT * FROM t1;
id id2
3 0
DROP TABLE t1;
+create table t1 (a integer);
+insert into t1 values (1);
+select 1 as a from t1 union all select 1 from dual limit 1;
+a
+1
+(select 1 as a from t1) union all (select 1 from dual) limit 1;
+a
+1
+drop table t1;
diff --git a/mysql-test/r/ndb_basic.result b/mysql-test/r/ndb_basic.result
index 6ec5338acbe..a6396080ef0 100644
--- a/mysql-test/r/ndb_basic.result
+++ b/mysql-test/r/ndb_basic.result
@@ -573,3 +573,37 @@ select * from t1 where a12345678901234567890123456789a1234567890=2;
a1234567890123456789012345678901234567890 a12345678901234567890123456789a1234567890
5 2
drop table t1;
+create table t1
+(a bigint, b bigint, c bigint, d bigint,
+primary key (a,b,c,d))
+engine=ndb
+max_rows=200000000;
+Warnings:
+Warning 1105 Ndb might have problems storing the max amount of rows specified
+insert into t1 values
+(1,2,3,4),(2,3,4,5),(3,4,5,6),
+(3,2,3,4),(1,3,4,5),(2,4,5,6),
+(1,2,3,5),(2,3,4,8),(3,4,5,9),
+(3,2,3,5),(1,3,4,8),(2,4,5,9),
+(1,2,3,6),(2,3,4,6),(3,4,5,7),
+(3,2,3,6),(1,3,4,6),(2,4,5,7),
+(1,2,3,7),(2,3,4,7),(3,4,5,8),
+(3,2,3,7),(1,3,4,7),(2,4,5,8),
+(1,3,3,4),(2,4,4,5),(3,5,5,6),
+(3,3,3,4),(1,4,4,5),(2,5,5,6),
+(1,3,3,5),(2,4,4,8),(3,5,5,9),
+(3,3,3,5),(1,4,4,8),(2,5,5,9),
+(1,3,3,6),(2,4,4,6),(3,5,5,7),
+(3,3,3,6),(1,4,4,6),(2,5,5,7),
+(1,3,3,7),(2,4,4,7),(3,5,5,8),
+(3,3,3,7),(1,4,4,7),(2,5,5,8);
+select count(*) from t1;
+count(*)
+48
+drop table t1;
+create table t1
+(a bigint, b bigint, c bigint, d bigint,
+primary key (a))
+engine=ndb
+max_rows=1;
+drop table t1;
diff --git a/mysql-test/r/ndb_cache.result b/mysql-test/r/ndb_cache.result
index 714e1831267..478663b1aa1 100644
--- a/mysql-test/r/ndb_cache.result
+++ b/mysql-test/r/ndb_cache.result
@@ -1,43 +1,191 @@
+drop table if exists t1;
+set GLOBAL query_cache_type=on;
set GLOBAL query_cache_size=1355776;
reset query cache;
flush status;
-drop table if exists t1,t2;
-CREATE TABLE t1 (a int) ENGINE=ndbcluster;
-CREATE TABLE t2 (a int);
+CREATE TABLE t1 ( pk int not null primary key,
+a int, b int not null, c varchar(20)) ENGINE=ndbcluster;
+insert into t1 value (1, 2, 3, 'First row');
select * from t1;
-a
+pk a b c
+1 2 3 First row
show status like "Qcache_queries_in_cache";
Variable_name Value
-Qcache_queries_in_cache 0
+Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
-Qcache_inserts 0
+Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 0
-select * from t2;
-a
+select * from t1;
+pk a b c
+1 2 3 First row
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 1
+update t1 set a=3 where pk=1;
+select * from t1;
+pk a b c
+1 3 3 First row
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 2
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 1
+insert into t1 value (2, 7, 8, 'Second row');
+insert into t1 value (4, 5, 6, 'Fourth row');
+select * from t1 order by pk;
+pk a b c
+1 3 3 First row
+2 7 8 Second row
+4 5 6 Fourth row
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 3
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 1
+select * from t1 order by pk;
+pk a b c
+1 3 3 First row
+2 7 8 Second row
+4 5 6 Fourth row
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 2
+select * from t1 where b=3;
+pk a b c
+1 3 3 First row
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 2
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 2
+select * from t1 where b=3;
+pk a b c
+1 3 3 First row
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 3
+delete from t1 where c='Fourth row';
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+select * from t1 where b=3;
+pk a b c
+1 3 3 First row
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 3
+use test;
+select * from t1 order by pk;
+pk a b c
+1 3 3 First row
+2 7 8 Second row
+select * from t1 where b=3;
+pk a b c
+1 3 3 First row
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 4
+update t1 set a=4 where b=3;
+use test;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+select * from t1 order by pk desc;
+pk a b c
+2 7 8 Second row
+1 4 3 First row
+select * from t1 order by pk desc;
+pk a b c
+2 7 8 Second row
+1 4 3 First row
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 7
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 5
+select * from t1 order by pk desc;
+pk a b c
+2 7 8 Second row
+1 4 3 First row
+select * from t1 order by pk desc;
+pk a b c
+2 7 8 Second row
+1 4 3 First row
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
-Qcache_inserts 1
+Qcache_inserts 7
show status like "Qcache_hits";
Variable_name Value
-Qcache_hits 0
-select * from t1;
-a
-select * from t2;
-a
+Qcache_hits 7
+begin;
+update t1 set a=5 where pk=1;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 7
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 7
+select * from t1 order by pk desc;
+pk a b c
+2 7 8 Second row
+1 4 3 First row
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
-Qcache_inserts 1
+Qcache_inserts 8
show status like "Qcache_hits";
Variable_name Value
-Qcache_hits 1
-drop table t1, t2;
+Qcache_hits 7
+commit;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 8
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 7
+select * from t1 order by pk desc;
+pk a b c
+2 7 8 Second row
+1 5 3 First row
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 9
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 7
+select * from t1 order by pk desc;
+pk a b c
+2 7 8 Second row
+1 5 3 First row
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 9
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 8
+drop table t1;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
SET GLOBAL query_cache_size=0;
diff --git a/mysql-test/r/ndb_cache2.result b/mysql-test/r/ndb_cache2.result
new file mode 100644
index 00000000000..de4b3e31874
--- /dev/null
+++ b/mysql-test/r/ndb_cache2.result
@@ -0,0 +1,193 @@
+drop table if exists t1;
+set GLOBAL query_cache_type=on;
+set GLOBAL query_cache_size=1355776;
+set GLOBAL ndb_cache_check_time=5;
+reset query cache;
+flush status;
+CREATE TABLE t1 ( pk int not null primary key,
+a int, b int not null, c varchar(20)) ENGINE=ndbcluster;
+insert into t1 value (1, 2, 3, 'First row');
+select * from t1;
+pk a b c
+1 2 3 First row
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 1
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+select * from t1;
+pk a b c
+1 2 3 First row
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 1
+update t1 set a=3 where pk=1;
+select * from t1;
+pk a b c
+1 3 3 First row
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 2
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 1
+insert into t1 value (2, 7, 8, 'Second row');
+insert into t1 value (4, 5, 6, 'Fourth row');
+select * from t1 order by pk desc;
+pk a b c
+4 5 6 Fourth row
+2 7 8 Second row
+1 3 3 First row
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 3
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 1
+select * from t1 order by pk desc;
+pk a b c
+4 5 6 Fourth row
+2 7 8 Second row
+1 3 3 First row
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 2
+select * from t1 where b=3;
+pk a b c
+1 3 3 First row
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 2
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 2
+select * from t1 where b=3;
+pk a b c
+1 3 3 First row
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 3
+delete from t1 where c='Fourth row';
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+select * from t1 where b=3;
+pk a b c
+1 3 3 First row
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 3
+use test;
+select * from t1 order by pk desc;
+pk a b c
+2 7 8 Second row
+1 3 3 First row
+select * from t1 where b=3;
+pk a b c
+1 3 3 First row
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 4
+update t1 set a=4 where b=3;
+use test;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+select * from t1 order by pk desc;
+pk a b c
+2 7 8 Second row
+1 4 3 First row
+select * from t1 order by pk desc;
+pk a b c
+2 7 8 Second row
+1 4 3 First row
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 7
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 5
+select * from t1 order by pk desc;
+pk a b c
+2 7 8 Second row
+1 4 3 First row
+select * from t1 order by pk desc;
+pk a b c
+2 7 8 Second row
+1 4 3 First row
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 7
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 7
+begin;
+update t1 set a=5 where pk=1;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 7
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 7
+select * from t1 order by pk desc;
+pk a b c
+2 7 8 Second row
+1 4 3 First row
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 8
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 7
+commit;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 8
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 7
+select * from t1 order by pk desc;
+pk a b c
+2 7 8 Second row
+1 5 3 First row
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 9
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 7
+select * from t1 order by pk desc;
+pk a b c
+2 7 8 Second row
+1 5 3 First row
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 9
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 8
+drop table t1;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+SET GLOBAL query_cache_size=0;
+SET GLOBAL ndb_cache_check_time=0;
diff --git a/mysql-test/r/ndb_cache_multi.result b/mysql-test/r/ndb_cache_multi.result
new file mode 100644
index 00000000000..c7135ed9e8a
--- /dev/null
+++ b/mysql-test/r/ndb_cache_multi.result
@@ -0,0 +1,72 @@
+drop table if exists t1, t2;
+set GLOBAL query_cache_type=on;
+set GLOBAL query_cache_size=1355776;
+reset query cache;
+flush status;
+set GLOBAL query_cache_type=on;
+set GLOBAL query_cache_size=1355776;
+reset query cache;
+flush status;
+create table t1 (a int) engine=ndbcluster;
+create table t2 (a int) engine=ndbcluster;
+insert into t1 value (2);
+insert into t2 value (3);
+select * from t1;
+a
+2
+select * from t2;
+a
+3
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 2
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 2
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 0
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+select * from t1;
+a
+2
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 1
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+update t1 set a=3 where a=2;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 2
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 2
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+select * from t1;
+a
+3
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 2
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 3
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+drop table t1, t2;
diff --git a/mysql-test/r/ndb_cache_multi2.result b/mysql-test/r/ndb_cache_multi2.result
new file mode 100644
index 00000000000..6e435c071b5
--- /dev/null
+++ b/mysql-test/r/ndb_cache_multi2.result
@@ -0,0 +1,74 @@
+drop table if exists t1, t2;
+set GLOBAL query_cache_type=on;
+set GLOBAL query_cache_size=1355776;
+set GLOBAL ndb_cache_check_time=1;
+reset query cache;
+flush status;
+set GLOBAL query_cache_type=on;
+set GLOBAL query_cache_size=1355776;
+set GLOBAL ndb_cache_check_time=1;
+reset query cache;
+flush status;
+create table t1 (a int) engine=ndbcluster;
+create table t2 (a int) engine=ndbcluster;
+insert into t1 value (2);
+insert into t2 value (3);
+select * from t1;
+a
+2
+select * from t2;
+a
+3
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 2
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 2
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 0
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+select * from t1;
+a
+2
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 1
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+update t1 set a=3 where a=2;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 2
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 2
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+select * from t1;
+a
+3
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 2
+show status like "Qcache_inserts";
+Variable_name Value
+Qcache_inserts 3
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+drop table t1, t2;
diff --git a/mysql-test/r/ndb_multi.result b/mysql-test/r/ndb_multi.result
new file mode 100644
index 00000000000..4a2389cd1ff
--- /dev/null
+++ b/mysql-test/r/ndb_multi.result
@@ -0,0 +1,49 @@
+drop table if exists t1, t2, t3, t4;
+flush status;
+create table t1 (a int) engine=ndbcluster;
+create table t2 (a int) engine=ndbcluster;
+insert into t1 value (2);
+insert into t2 value (3);
+select * from t1;
+a
+2
+select * from t2;
+a
+3
+show status like 'handler_discover%';
+Variable_name Value
+Handler_discover 0
+flush status;
+select * from t1;
+a
+2
+update t1 set a=3 where a=2;
+show status like 'handler_discover%';
+Variable_name Value
+Handler_discover 1
+create table t3 (a int not null primary key, b varchar(22),
+c int, last_col text) engine=ndb;
+insert into t3 values(1, 'Hi!', 89, 'Longtext column');
+create table t4 (pk int primary key, b int) engine=ndb;
+select * from t1;
+a
+3
+select * from t3;
+a b c last_col
+1 Hi! 89 Longtext column
+show status like 'handler_discover%';
+Variable_name Value
+Handler_discover 1
+show tables like 't4';
+Tables_in_test (t4)
+t4
+show status like 'handler_discover%';
+Variable_name Value
+Handler_discover 2
+show tables;
+Tables_in_test
+t1
+t2
+t3
+t4
+drop table t1, t2, t3, t4;
diff --git a/mysql-test/r/server_id.require b/mysql-test/r/server_id.require
new file mode 100644
index 00000000000..adffcc483b1
--- /dev/null
+++ b/mysql-test/r/server_id.require
@@ -0,0 +1,2 @@
+Variable_name Value
+server_id 1
diff --git a/mysql-test/r/server_id1.require b/mysql-test/r/server_id1.require
new file mode 100644
index 00000000000..666c94ef633
--- /dev/null
+++ b/mysql-test/r/server_id1.require
@@ -0,0 +1,2 @@
+Variable_name Value
+server_id 102
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index 47d69ae5afd..5ca0c9356e6 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -2204,15 +2204,3 @@ ERROR 42S22: Reference 'xx' not supported (forward reference in item list)
select 1 = ALL (select 1 from t1 where 1 = xx ), 1 as xx from DUAL;
ERROR 42S22: Reference 'xx' not supported (forward reference in item list)
drop table t1;
-CREATE TABLE `t1` ( `a` char(3) NOT NULL default '', `b` char(3) NOT NULL default '', `c` char(3) NOT NULL default '', PRIMARY KEY (`a`,`b`,`c`)) ENGINE=InnoDB;
-CREATE TABLE t2 LIKE t1;
-INSERT INTO t1 VALUES (1,1,1);
-INSERT INTO t2 VALUES (1,1,1);
-PREPARE my_stmt FROM "SELECT t1.b, count(*) FROM t1 group by t1.b having
-count(*) > ALL (SELECT COUNT(*) FROM t2 WHERE t2.a=1 GROUP By t2.b)";
-EXECUTE my_stmt;
-b count(*)
-EXECUTE my_stmt;
-b count(*)
-deallocate prepare my_stmt;
-drop table t1,t2;
diff --git a/mysql-test/r/subselect_innodb.result b/mysql-test/r/subselect_innodb.result
index 0b813a07a1d..0666fd76661 100644
--- a/mysql-test/r/subselect_innodb.result
+++ b/mysql-test/r/subselect_innodb.result
@@ -140,3 +140,15 @@ id date1 coworkerid description sum_used sum_remaining comments
6 2004-01-01 1 test 22 33 comment
7 2004-01-01 1 test 22 33 comment
drop table t1;
+CREATE TABLE `t1` ( `a` char(3) NOT NULL default '', `b` char(3) NOT NULL default '', `c` char(3) NOT NULL default '', PRIMARY KEY (`a`,`b`,`c`)) ENGINE=InnoDB;
+CREATE TABLE t2 LIKE t1;
+INSERT INTO t1 VALUES (1,1,1);
+INSERT INTO t2 VALUES (1,1,1);
+PREPARE my_stmt FROM "SELECT t1.b, count(*) FROM t1 group by t1.b having
+count(*) > ALL (SELECT COUNT(*) FROM t2 WHERE t2.a=1 GROUP By t2.b)";
+EXECUTE my_stmt;
+b count(*)
+EXECUTE my_stmt;
+b count(*)
+deallocate prepare my_stmt;
+drop table t1,t2;
diff --git a/mysql-test/r/type_date.result b/mysql-test/r/type_date.result
index 71d1b9ad381..e88eebffb55 100644
--- a/mysql-test/r/type_date.result
+++ b/mysql-test/r/type_date.result
@@ -96,3 +96,11 @@ f2
19781126
19781126
DROP TABLE t1, t2, t3;
+CREATE TABLE t1 (y YEAR);
+INSERT INTO t1 VALUES ('abc');
+Warnings:
+Warning 1264 Out of range value adjusted for column 'y' at row 1
+SELECT * FROM t1;
+y
+0000
+DROP TABLE t1;
diff --git a/mysql-test/r/type_float.result.es b/mysql-test/r/type_float.result.es
index 2751e6cb33b..f2639ef545a 100644
--- a/mysql-test/r/type_float.result.es
+++ b/mysql-test/r/type_float.result.es
@@ -1,4 +1,4 @@
-drop table if exists t1;
+drop table if exists t1,t2;
SELECT 10,10.0,10.,.1e+2,100.0e-1;
10 10.0 10. .1e+2 100.0e-1
10 10.0 10 10 10
@@ -8,6 +8,9 @@ SELECT 6e-05, -6e-05, --6e-05, -6e-05+1.000000;
SELECT 1e1,1.e1,1.0e1,1e+1,1.e+1,1.0e+1,1e-1,1.e-1,1.0e-1;
1e1 1.e1 1.0e1 1e+1 1.e+1 1.0e+1 1e-1 1.e-1 1.0e-1
10 10 10 10 10 10 0.1 0.1 0.1
+SELECT 0.001e+1,0.001e-1, -0.001e+01,-0.001e-01;
+0.001e+1 0.001e-1 -0.001e+01 -0.001e-01
+0.01 0.0001 -0.01 -0.0001
create table t1 (f1 float(24),f2 float(52));
show full columns from t1;
Field Type Collation Null Key Default Extra Privileges Comment
@@ -143,6 +146,15 @@ drop table t1;
create table t1 (f float(54));
ERROR 42000: Incorrect column specifier for column 'f'
drop table if exists t1;
+create table t1 (d1 double, d2 double unsigned);
+insert into t1 set d1 = -1.0;
+update t1 set d2 = d1;
+Warnings:
+Warning 1264 Out of range value adjusted for column 'd2' at row 1
+select * from t1;
+d1 d2
+-1 0
+drop table t1;
create table t1 (f float(4,3));
insert into t1 values (-11.0),(-11),("-11"),(11.0),(11),("11");
Warnings:
diff --git a/mysql-test/r/type_ranges.result.es b/mysql-test/r/type_ranges.result.es
index c1f6d2453e9..5e2ea2aebbc 100644
--- a/mysql-test/r/type_ranges.result.es
+++ b/mysql-test/r/type_ranges.result.es
@@ -40,30 +40,30 @@ KEY (options,flags)
);
show full fields from t1;
Field Type Collation Null Key Default Extra Privileges Comment
-auto int(5) unsigned NULL PRI NULL auto_increment
-string varchar(10) latin1_swedish_ci YES hello
-tiny tinyint(4) NULL MUL 0
-short smallint(6) NULL MUL 1
-medium mediumint(8) NULL MUL 0
-long_int int(11) NULL 0
-longlong bigint(13) NULL MUL 0
-real_float float(13,1) NULL MUL 0.0
+auto int(5) unsigned NULL NO PRI NULL auto_increment
+string char(10) latin1_swedish_ci YES hello
+tiny tinyint(4) NULL NO MUL 0
+short smallint(6) NULL NO MUL 1
+medium mediumint(8) NULL NO MUL 0
+long_int int(11) NULL NO 0
+longlong bigint(13) NULL NO MUL 0
+real_float float(13,1) NULL NO MUL 0.0
real_double double(16,4) NULL YES NULL
-utiny tinyint(3) unsigned NULL MUL 0
-ushort smallint(5) unsigned zerofill NULL MUL 00000
-umedium mediumint(8) unsigned NULL MUL 0
-ulong int(11) unsigned NULL MUL 0
-ulonglong bigint(13) unsigned NULL MUL 0
+utiny tinyint(3) unsigned NULL NO MUL 0
+ushort smallint(5) unsigned zerofill NULL NO MUL 00000
+umedium mediumint(8) unsigned NULL NO MUL 0
+ulong int(11) unsigned NULL NO MUL 0
+ulonglong bigint(13) unsigned NULL NO MUL 0
time_stamp timestamp NULL YES CURRENT_TIMESTAMP
date_field date NULL YES NULL
time_field time NULL YES NULL
date_time datetime NULL YES NULL
blob_col blob NULL YES NULL
tinyblob_col tinyblob NULL YES NULL
-mediumblob_col mediumblob NULL
-longblob_col longblob NULL
-options enum('one','two','tree') latin1_swedish_ci MUL one
-flags set('one','two','tree') latin1_swedish_ci
+mediumblob_col mediumblob NULL NO
+longblob_col longblob NULL NO
+options enum('one','two','tree') latin1_swedish_ci NO MUL one
+flags set('one','two','tree') latin1_swedish_ci NO
show keys from t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
t1 0 PRIMARY 1 auto A 0 NULL NULL BTREE
@@ -89,33 +89,33 @@ insert into t1 values (NULL,2,2,2,2,2,2,2,2,2,2,2,2,2,NULL,NULL,NULL,NULL,NULL,N
insert into t1 values (0,1/3,3,3,3,3,3,3,3,3,3,3,3,3,NULL,'19970303','10:10:10','19970303101010','','','','3',3,3);
insert into t1 values (0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,NULL,19970807,080706,19970403090807,-1,-1,-1,'-1',-1,-1);
Warnings:
-Warning 1264 Data truncated; out of range for column 'utiny' at row 1
-Warning 1264 Data truncated; out of range for column 'ushort' at row 1
-Warning 1264 Data truncated; out of range for column 'umedium' at row 1
-Warning 1264 Data truncated; out of range for column 'ulong' at row 1
+Warning 1264 Out of range value adjusted for column 'utiny' at row 1
+Warning 1264 Out of range value adjusted for column 'ushort' at row 1
+Warning 1264 Out of range value adjusted for column 'umedium' at row 1
+Warning 1264 Out of range value adjusted for column 'ulong' at row 1
Warning 1265 Data truncated for column 'options' at row 1
Warning 1265 Data truncated for column 'flags' at row 1
insert into t1 values (0,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,-4294967295,NULL,0,0,0,-4294967295,-4294967295,-4294967295,'-4294967295',0,"one,two,tree");
Warnings:
Warning 1265 Data truncated for column 'string' at row 1
-Warning 1264 Data truncated; out of range for column 'tiny' at row 1
-Warning 1264 Data truncated; out of range for column 'short' at row 1
-Warning 1264 Data truncated; out of range for column 'medium' at row 1
-Warning 1264 Data truncated; out of range for column 'long_int' at row 1
-Warning 1264 Data truncated; out of range for column 'utiny' at row 1
-Warning 1264 Data truncated; out of range for column 'ushort' at row 1
-Warning 1264 Data truncated; out of range for column 'umedium' at row 1
-Warning 1264 Data truncated; out of range for column 'ulong' at row 1
+Warning 1264 Out of range value adjusted for column 'tiny' at row 1
+Warning 1264 Out of range value adjusted for column 'short' at row 1
+Warning 1264 Out of range value adjusted for column 'medium' at row 1
+Warning 1264 Out of range value adjusted for column 'long_int' at row 1
+Warning 1264 Out of range value adjusted for column 'utiny' at row 1
+Warning 1264 Out of range value adjusted for column 'ushort' at row 1
+Warning 1264 Out of range value adjusted for column 'umedium' at row 1
+Warning 1264 Out of range value adjusted for column 'ulong' at row 1
Warning 1265 Data truncated for column 'options' at row 1
insert into t1 values (0,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,NULL,0,0,0,4294967295,4294967295,4294967295,'4294967295',0,0);
Warnings:
-Warning 1264 Data truncated; out of range for column 'tiny' at row 1
-Warning 1264 Data truncated; out of range for column 'short' at row 1
-Warning 1264 Data truncated; out of range for column 'medium' at row 1
-Warning 1264 Data truncated; out of range for column 'long_int' at row 1
-Warning 1264 Data truncated; out of range for column 'utiny' at row 1
-Warning 1264 Data truncated; out of range for column 'ushort' at row 1
-Warning 1264 Data truncated; out of range for column 'umedium' at row 1
+Warning 1264 Out of range value adjusted for column 'tiny' at row 1
+Warning 1264 Out of range value adjusted for column 'short' at row 1
+Warning 1264 Out of range value adjusted for column 'medium' at row 1
+Warning 1264 Out of range value adjusted for column 'long_int' at row 1
+Warning 1264 Out of range value adjusted for column 'utiny' at row 1
+Warning 1264 Out of range value adjusted for column 'ushort' at row 1
+Warning 1264 Out of range value adjusted for column 'umedium' at row 1
Warning 1265 Data truncated for column 'options' at row 1
insert into t1 (tiny) values (1);
select auto,string,tiny,short,medium,long_int,longlong,real_float,real_double,utiny,ushort,umedium,ulong,ulonglong,mod(floor(time_stamp/1000000),1000000)-mod(curdate(),1000000),date_field,time_field,date_time,blob_col,tinyblob_col,mediumblob_col,longblob_col from t1;
@@ -208,56 +208,56 @@ Warning 1265 Data truncated for column 'options' at row 6
update t2 set string="changed" where auto=16;
show full columns from t1;
Field Type Collation Null Key Default Extra Privileges Comment
-auto int(5) unsigned NULL MUL NULL auto_increment
-string varchar(10) latin1_swedish_ci YES new defaul
-tiny tinyint(4) NULL MUL 0
-short smallint(6) NULL MUL 0
-medium mediumint(8) NULL MUL 0
-long_int int(11) NULL 0
-longlong bigint(13) NULL MUL 0
-real_float float(13,1) NULL MUL 0.0
+auto int(5) unsigned NULL NO MUL NULL auto_increment
+string char(10) latin1_swedish_ci YES new defaul
+tiny tinyint(4) NULL NO MUL 0
+short smallint(6) NULL NO MUL 0
+medium mediumint(8) NULL NO MUL 0
+long_int int(11) NULL NO 0
+longlong bigint(13) NULL NO MUL 0
+real_float float(13,1) NULL NO MUL 0.0
real_double double(16,4) NULL YES NULL
-utiny tinyint(3) unsigned NULL 0
-ushort smallint(5) unsigned zerofill NULL 00000
-umedium mediumint(8) unsigned NULL MUL 0
-ulong int(11) unsigned NULL MUL 0
-ulonglong bigint(13) unsigned NULL MUL 0
+utiny tinyint(3) unsigned NULL NO 0
+ushort smallint(5) unsigned zerofill NULL NO 00000
+umedium mediumint(8) unsigned NULL NO MUL 0
+ulong int(11) unsigned NULL NO MUL 0
+ulonglong bigint(13) unsigned NULL NO MUL 0
time_stamp timestamp NULL YES CURRENT_TIMESTAMP
date_field char(10) latin1_swedish_ci YES NULL
time_field time NULL YES NULL
date_time datetime NULL YES NULL
new_blob_col varchar(20) latin1_swedish_ci YES NULL
tinyblob_col tinyblob NULL YES NULL
-mediumblob_col mediumblob NULL
-options enum('one','two','tree') latin1_swedish_ci MUL one
-flags set('one','two','tree') latin1_swedish_ci
-new_field char(10) latin1_swedish_ci new
+mediumblob_col mediumblob NULL NO
+options enum('one','two','tree') latin1_swedish_ci NO MUL one
+flags set('one','two','tree') latin1_swedish_ci NO
+new_field char(10) latin1_swedish_ci NO new
show full columns from t2;
Field Type Collation Null Key Default Extra Privileges Comment
-auto int(5) unsigned NULL 0
-string varchar(10) latin1_swedish_ci YES new defaul
-tiny tinyint(4) NULL 0
-short smallint(6) NULL 0
-medium mediumint(8) NULL 0
-long_int int(11) NULL 0
-longlong bigint(13) NULL 0
-real_float float(13,1) NULL 0.0
+auto int(5) unsigned NULL NO 0
+string char(10) latin1_swedish_ci YES new defaul
+tiny tinyint(4) NULL NO 0
+short smallint(6) NULL NO 0
+medium mediumint(8) NULL NO 0
+long_int int(11) NULL NO 0
+longlong bigint(13) NULL NO 0
+real_float float(13,1) NULL NO 0.0
real_double double(16,4) NULL YES NULL
-utiny tinyint(3) unsigned NULL 0
-ushort smallint(5) unsigned zerofill NULL 00000
-umedium mediumint(8) unsigned NULL 0
-ulong int(11) unsigned NULL 0
-ulonglong bigint(13) unsigned NULL 0
+utiny tinyint(3) unsigned NULL NO 0
+ushort smallint(5) unsigned zerofill NULL NO 00000
+umedium mediumint(8) unsigned NULL NO 0
+ulong int(11) unsigned NULL NO 0
+ulonglong bigint(13) unsigned NULL NO 0
time_stamp timestamp NULL YES 0000-00-00 00:00:00
date_field char(10) latin1_swedish_ci YES NULL
time_field time NULL YES NULL
date_time datetime NULL YES NULL
new_blob_col varchar(20) latin1_swedish_ci YES NULL
tinyblob_col tinyblob NULL YES NULL
-mediumblob_col mediumblob NULL
-options enum('one','two','tree') latin1_swedish_ci one
-flags set('one','two','tree') latin1_swedish_ci
-new_field char(10) latin1_swedish_ci new
+mediumblob_col mediumblob NULL NO
+options enum('one','two','tree') latin1_swedish_ci NO one
+flags set('one','two','tree') latin1_swedish_ci NO
+new_field char(10) latin1_swedish_ci NO new
select t1.auto,t2.auto from t1,t2 where t1.auto=t2.auto and ((t1.string<>t2.string and (t1.string is not null or t2.string is not null)) or (t1.tiny<>t2.tiny and (t1.tiny is not null or t2.tiny is not null)) or (t1.short<>t2.short and (t1.short is not null or t2.short is not null)) or (t1.medium<>t2.medium and (t1.medium is not null or t2.medium is not null)) or (t1.long_int<>t2.long_int and (t1.long_int is not null or t2.long_int is not null)) or (t1.longlong<>t2.longlong and (t1.longlong is not null or t2.longlong is not null)) or (t1.real_float<>t2.real_float and (t1.real_float is not null or t2.real_float is not null)) or (t1.real_double<>t2.real_double and (t1.real_double is not null or t2.real_double is not null)) or (t1.utiny<>t2.utiny and (t1.utiny is not null or t2.utiny is not null)) or (t1.ushort<>t2.ushort and (t1.ushort is not null or t2.ushort is not null)) or (t1.umedium<>t2.umedium and (t1.umedium is not null or t2.umedium is not null)) or (t1.ulong<>t2.ulong and (t1.ulong is not null or t2.ulong is not null)) or (t1.ulonglong<>t2.ulonglong and (t1.ulonglong is not null or t2.ulonglong is not null)) or (t1.time_stamp<>t2.time_stamp and (t1.time_stamp is not null or t2.time_stamp is not null)) or (t1.date_field<>t2.date_field and (t1.date_field is not null or t2.date_field is not null)) or (t1.time_field<>t2.time_field and (t1.time_field is not null or t2.time_field is not null)) or (t1.date_time<>t2.date_time and (t1.date_time is not null or t2.date_time is not null)) or (t1.new_blob_col<>t2.new_blob_col and (t1.new_blob_col is not null or t2.new_blob_col is not null)) or (t1.tinyblob_col<>t2.tinyblob_col and (t1.tinyblob_col is not null or t2.tinyblob_col is not null)) or (t1.mediumblob_col<>t2.mediumblob_col and (t1.mediumblob_col is not null or t2.mediumblob_col is not null)) or (t1.options<>t2.options and (t1.options is not null or t2.options is not null)) or (t1.flags<>t2.flags and (t1.flags is not null or t2.flags is not null)) or (t1.new_field<>t2.new_field and (t1.new_field is not null or t2.new_field is not null)));
auto auto
16 16
@@ -265,23 +265,27 @@ select t1.auto,t2.auto from t1,t2 where t1.auto=t2.auto and not (t1.string<=>t2.
auto auto
16 16
drop table t2;
-create table t2 (primary key (auto)) select auto+1 as auto,1 as t1, "a" as t2, repeat("a",256) as t3, binary repeat("b",256) as t4 from t1;
+create table t2 (primary key (auto)) select auto+1 as auto,1 as t1, 'a' as t2, repeat('a',256) as t3, binary repeat('b',256) as t4, repeat('a',4096) as t5, binary repeat('b',4096) as t6, '' as t7, binary '' as t8 from t1;
show full columns from t2;
Field Type Collation Null Key Default Extra Privileges Comment
-auto bigint(17) unsigned NULL PRI 0
-t1 bigint(1) NULL 0
-t2 char(1) latin1_swedish_ci
-t3 longtext latin1_swedish_ci
-t4 longblob NULL
-select * from t2;
-auto t1 t2 t3 t4
-11 1 a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
-12 1 a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
-13 1 a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
-14 1 a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
-15 1 a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
-16 1 a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
-17 1 a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+auto bigint(17) unsigned NULL NO PRI 0
+t1 bigint(1) NULL NO 0
+t2 varchar(1) latin1_swedish_ci NO
+t3 varchar(256) latin1_swedish_ci NO
+t4 varbinary(256) NULL NO
+t5 longtext latin1_swedish_ci NO
+t6 longblob NULL NO
+t7 char(0) latin1_swedish_ci NO
+t8 binary(0) NULL NO
+select t1,t2,length(t3),length(t4),length(t5),length(t6),t7,t8 from t2;
+t1 t2 length(t3) length(t4) length(t5) length(t6) t7 t8
+1 a 256 256 4096 4096
+1 a 256 256 4096 4096
+1 a 256 256 4096 4096
+1 a 256 256 4096 4096
+1 a 256 256 4096 4096
+1 a 256 256 4096 4096
+1 a 256 256 4096 4096
drop table t1,t2;
create table t1 (c int);
insert into t1 values(1),(2);
@@ -293,7 +297,7 @@ show full columns from t3;
Field Type Collation Null Key Default Extra Privileges Comment
c1 int(11) NULL YES NULL
c2 int(11) NULL YES NULL
-const bigint(1) NULL 0
+const bigint(1) NULL NO 0
drop table t1,t2,t3;
create table t1 ( myfield INT NOT NULL, UNIQUE INDEX (myfield), unique (myfield), index(myfield));
drop table t1;
diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result
index a63358ff2bc..cdae2cd1bcf 100644
--- a/mysql-test/r/union.result
+++ b/mysql-test/r/union.result
@@ -1137,3 +1137,39 @@ t1 CREATE TABLE `t1` (
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
drop table t2;
+create table t1(a1 int, f1 char(10));
+create table t2
+select f2,a1 from (select a1, CAST('2004-12-31' AS DATE) f2 from t1) a
+union
+select f2,a1 from (select a1, CAST('2004-12-31' AS DATE) f2 from t1) a
+order by f2, a1;
+show columns from t2;
+Field Type Null Key Default Extra
+f2 date YES NULL
+a1 int(11) YES NULL
+drop table t1, t2;
+create table t1 (f1 int);
+create table t2 (f1 int, f2 int ,f3 date);
+create table t3 (f1 int, f2 char(10));
+create table t4
+(
+select t2.f3 as sdate
+from t1
+left outer join t2 on (t1.f1 = t2.f1)
+inner join t3 on (t2.f2 = t3.f1)
+order by t1.f1, t3.f1, t2.f3
+)
+union
+(
+select cast('2004-12-31' as date) as sdate
+from t1
+left outer join t2 on (t1.f1 = t2.f1)
+inner join t3 on (t2.f2 = t3.f1)
+group by t1.f1
+order by t1.f1, t3.f1, t2.f3
+)
+order by sdate;
+show columns from t4;
+Field Type Null Key Default Extra
+sdate date YES NULL
+drop table t1, t2, t3, t4;
diff --git a/mysql-test/r/update.result b/mysql-test/r/update.result
index beab6105f79..ac370db9ecc 100644
--- a/mysql-test/r/update.result
+++ b/mysql-test/r/update.result
@@ -212,3 +212,10 @@ insert into t1 values (1, "t1c2-1", 10), (2, "t1c2-2", 20);
update t1 left join t2 on t1.c1 = t2.c1 set t2.c2 = "t2c2-1";
update t1 left join t2 on t1.c1 = t2.c1 set t2.c2 = "t2c2-1" where t1.c3 = 10;
drop table t1, t2;
+create table t1 (id int not null auto_increment primary key, id_str varchar(32));
+insert into t1 (id_str) values ("test");
+update t1 set id_str = concat(id_str, id) where id = last_insert_id();
+select * from t1;
+id id_str
+1 test1
+drop table t1;
diff --git a/mysql-test/t/drop_temp_table.test b/mysql-test/t/drop_temp_table.test
index 1a7d8796bb3..dcd95721179 100644
--- a/mysql-test/t/drop_temp_table.test
+++ b/mysql-test/t/drop_temp_table.test
@@ -4,7 +4,9 @@ connection con1;
reset master;
create database `drop-temp+table-test`;
use `drop-temp+table-test`;
+create temporary table shortn1 (a int);
create temporary table `table:name` (a int);
+create temporary table shortn2 (a int);
select get_lock("a",10);
disconnect con1;
@@ -15,5 +17,6 @@ connection con2;
select get_lock("a",10);
let $VERSION=`select version()`;
--replace_result $VERSION VERSION
+--replace_column 2 # 5 #
show binlog events;
drop database `drop-temp+table-test`;
diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test
index 65ef9f2535c..a47218e5c01 100644
--- a/mysql-test/t/func_group.test
+++ b/mysql-test/t/func_group.test
@@ -473,3 +473,17 @@ INSERT INTO t1 VALUES
select val, count(*) from t1 group by val;
drop table t1;
+
+
+#
+# Bug 7833: Wrong datatype of aggregate column is returned
+#
+
+create table t1(f1 datetime);
+insert into t1 values (now());
+create table t2 select f2 from (select max(now()) f2 from t1) a;
+show columns from t2;
+drop table t2;
+create table t2 select f2 from (select now() f2 from t1) a;
+show columns from t2;
+drop table t2, t1;
diff --git a/mysql-test/t/func_misc.test b/mysql-test/t/func_misc.test
index e73f2a1b26c..89aba7ee583 100644
--- a/mysql-test/t/func_misc.test
+++ b/mysql-test/t/func_misc.test
@@ -23,3 +23,18 @@ select length(format('nan', 2)) > 0;
# Test for bug #628
#
select concat("$",format(2500,2));
+
+# Test for BUG#7716
+create table t1 ( a timestamp );
+insert into t1 values ( '2004-01-06 12:34' );
+select a from t1 where left(a+0,6) in ( left(20040106,6) );
+select a from t1 where left(a+0,6) = ( left(20040106,6) );
+
+select a from t1 where right(a+0,6) in ( right(20040106123400,6) );
+select a from t1 where right(a+0,6) = ( right(20040106123400,6) );
+
+select a from t1 where mid(a+0,6,3) in ( mid(20040106123400,6,3) );
+select a from t1 where mid(a+0,6,3) = ( mid(20040106123400,6,3) );
+
+drop table t1;
+
diff --git a/mysql-test/t/limit.test b/mysql-test/t/limit.test
index 61c57c9b468..28b287a5d4a 100644
--- a/mysql-test/t/limit.test
+++ b/mysql-test/t/limit.test
@@ -49,3 +49,13 @@ SELECT * FROM t1;
DELETE FROM t1 WHERE id2 = 0 ORDER BY id desc LIMIT 1;
SELECT * FROM t1;
DROP TABLE t1;
+
+#
+# Bug#8023 - limit on UNION with from DUAL, causes syntax error
+#
+create table t1 (a integer);
+insert into t1 values (1);
+# both queries must return one row
+select 1 as a from t1 union all select 1 from dual limit 1;
+(select 1 as a from t1) union all (select 1 from dual) limit 1;
+drop table t1;
diff --git a/mysql-test/t/ndb_basic.test b/mysql-test/t/ndb_basic.test
index 2671223ada8..f460c573a9d 100644
--- a/mysql-test/t/ndb_basic.test
+++ b/mysql-test/t/ndb_basic.test
@@ -539,3 +539,41 @@ insert into t1 values (1,1),(2,1),(3,1),(4,1),(5,2),(6,1),(7,1);
explain select * from t1 where a12345678901234567890123456789a1234567890=2;
select * from t1 where a12345678901234567890123456789a1234567890=2;
drop table t1;
+
+#
+# test fragment creation
+#
+# first a table with _many_ fragments per node group
+# then a table with just one fragment per node group
+#
+create table t1
+ (a bigint, b bigint, c bigint, d bigint,
+ primary key (a,b,c,d))
+ engine=ndb
+ max_rows=200000000;
+insert into t1 values
+ (1,2,3,4),(2,3,4,5),(3,4,5,6),
+ (3,2,3,4),(1,3,4,5),(2,4,5,6),
+ (1,2,3,5),(2,3,4,8),(3,4,5,9),
+ (3,2,3,5),(1,3,4,8),(2,4,5,9),
+ (1,2,3,6),(2,3,4,6),(3,4,5,7),
+ (3,2,3,6),(1,3,4,6),(2,4,5,7),
+ (1,2,3,7),(2,3,4,7),(3,4,5,8),
+ (3,2,3,7),(1,3,4,7),(2,4,5,8),
+ (1,3,3,4),(2,4,4,5),(3,5,5,6),
+ (3,3,3,4),(1,4,4,5),(2,5,5,6),
+ (1,3,3,5),(2,4,4,8),(3,5,5,9),
+ (3,3,3,5),(1,4,4,8),(2,5,5,9),
+ (1,3,3,6),(2,4,4,6),(3,5,5,7),
+ (3,3,3,6),(1,4,4,6),(2,5,5,7),
+ (1,3,3,7),(2,4,4,7),(3,5,5,8),
+ (3,3,3,7),(1,4,4,7),(2,5,5,8);
+select count(*) from t1;
+drop table t1;
+
+create table t1
+ (a bigint, b bigint, c bigint, d bigint,
+ primary key (a))
+ engine=ndb
+ max_rows=1;
+drop table t1;
diff --git a/mysql-test/t/ndb_cache.test b/mysql-test/t/ndb_cache.test
index abd09424f64..e899e94e4ac 100644
--- a/mysql-test/t/ndb_cache.test
+++ b/mysql-test/t/ndb_cache.test
@@ -1,31 +1,121 @@
-- source include/have_query_cache.inc
-- source include/have_ndb.inc
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+# Turn on and reset query cache
+set GLOBAL query_cache_type=on;
set GLOBAL query_cache_size=1355776;
reset query cache;
flush status;
---disable_warnings
-drop table if exists t1,t2;
---enable_warnings
+# Create test table in NDB
+CREATE TABLE t1 ( pk int not null primary key,
+ a int, b int not null, c varchar(20)) ENGINE=ndbcluster;
+insert into t1 value (1, 2, 3, 'First row');
+
+# Perform one query which should be inerted in query cache
+select * from t1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
-CREATE TABLE t1 (a int) ENGINE=ndbcluster;
-CREATE TABLE t2 (a int);
+# Perform the same query and make sure the query cache is hit
+select * from t1;
+show status like "Qcache_hits";
+# Update the table and make sure the correct data is returned
+update t1 set a=3 where pk=1;
select * from t1;
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+
+# Insert a new record and make sure the correct data is returned
+insert into t1 value (2, 7, 8, 'Second row');
+insert into t1 value (4, 5, 6, 'Fourth row');
+select * from t1 order by pk;
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+select * from t1 order by pk;
+show status like "Qcache_hits";
+
+# Perform a "new" query and make sure the query cache is not hit
+select * from t1 where b=3;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_hits";
+
+# Same query again...
+select * from t1 where b=3;
+show status like "Qcache_hits";
+
+# Delete from the table
+delete from t1 where c='Fourth row';
+show status like "Qcache_queries_in_cache";
+select * from t1 where b=3;
+show status like "Qcache_hits";
+
+# Start another connection and check that the query cache is hit
+connect (con1,localhost,root,,);
+connection con1;
+use test;
+select * from t1 order by pk;
+select * from t1 where b=3;
+show status like "Qcache_hits";
+
+# Update the table and switch to other connection
+update t1 set a=4 where b=3;
+connect (con2,localhost,root,,);
+connection con2;
+use test;
show status like "Qcache_queries_in_cache";
+select * from t1 order by pk desc;
+select * from t1 order by pk desc;
show status like "Qcache_inserts";
show status like "Qcache_hits";
-select * from t2;
+connection con1;
+select * from t1 order by pk desc;
+select * from t1 order by pk desc;
show status like "Qcache_queries_in_cache";
show status like "Qcache_inserts";
show status like "Qcache_hits";
-select * from t1;
-select * from t2;
+
+# Use transactions and make sure the query cache is not updated until
+# transaction is commited
+begin;
+update t1 set a=5 where pk=1;
+# Note!! the below test shows that table is invalidated
+# before transaction is committed
+# TODO Fix so that cache is not invalidated HERE!
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+connection con2;
+select * from t1 order by pk desc;
show status like "Qcache_queries_in_cache";
show status like "Qcache_inserts";
show status like "Qcache_hits";
+connection con1;
+commit;
+# TODO Here query is invalidated once again, commit count in NDB has changed
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+connection con2;
+select * from t1 order by pk desc;
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+connection con1;
+select * from t1 order by pk desc;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+
+drop table t1;
-drop table t1, t2;
+show status like "Qcache_queries_in_cache";
SET GLOBAL query_cache_size=0;
+
+
diff --git a/mysql-test/t/ndb_cache2.test b/mysql-test/t/ndb_cache2.test
new file mode 100644
index 00000000000..c46935e8601
--- /dev/null
+++ b/mysql-test/t/ndb_cache2.test
@@ -0,0 +1,126 @@
+-- source include/have_query_cache.inc
+-- source include/have_ndb.inc
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+
+# Turn on and reset query cache
+set GLOBAL query_cache_type=on;
+set GLOBAL query_cache_size=1355776;
+# Turn on thread that will fetch commit count for open tables
+set GLOBAL ndb_cache_check_time=5;
+reset query cache;
+flush status;
+
+# Wait for thread to wake up and start "working"
+sleep 20;
+
+# Create test table in NDB
+CREATE TABLE t1 ( pk int not null primary key,
+ a int, b int not null, c varchar(20)) ENGINE=ndbcluster;
+insert into t1 value (1, 2, 3, 'First row');
+
+# Perform one query which should be inerted in query cache
+select * from t1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+
+# Perform the same query and make sure the query cache is hit
+select * from t1;
+show status like "Qcache_hits";
+
+# Update the table and make sure the correct data is returned
+update t1 set a=3 where pk=1;
+select * from t1;
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+
+# Insert a new record and make sure the correct data is returned
+insert into t1 value (2, 7, 8, 'Second row');
+insert into t1 value (4, 5, 6, 'Fourth row');
+select * from t1 order by pk desc;
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+select * from t1 order by pk desc;
+show status like "Qcache_hits";
+
+# Perform a "new" query and make sure the query cache is not hit
+select * from t1 where b=3;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_hits";
+
+# Same query again...
+select * from t1 where b=3;
+show status like "Qcache_hits";
+
+# Delete from the table
+delete from t1 where c='Fourth row';
+show status like "Qcache_queries_in_cache";
+select * from t1 where b=3;
+show status like "Qcache_hits";
+
+# Start another connection and check that the query cache is hit
+connect (con1,localhost,root,,);
+connection con1;
+use test;
+select * from t1 order by pk desc;
+select * from t1 where b=3;
+show status like "Qcache_hits";
+
+# Update the table and switch to other connection
+update t1 set a=4 where b=3;
+connect (con2,localhost,root,,);
+connection con2;
+use test;
+show status like "Qcache_queries_in_cache";
+select * from t1 order by pk desc;
+select * from t1 order by pk desc;
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+connection con1;
+select * from t1 order by pk desc;
+select * from t1 order by pk desc;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+
+# Use transactions and make sure the query cache is not updated until
+# transaction is commited
+begin;
+update t1 set a=5 where pk=1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+connection con2;
+select * from t1 order by pk desc;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+connection con1;
+commit;
+# Sleep to let the query cache thread update commit count
+sleep 10;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+connection con2;
+select * from t1 order by pk desc;
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+connection con1;
+select * from t1 order by pk desc;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+
+drop table t1;
+
+show status like "Qcache_queries_in_cache";
+
+SET GLOBAL query_cache_size=0;
+SET GLOBAL ndb_cache_check_time=0;
+
+
diff --git a/mysql-test/t/ndb_cache_multi.test b/mysql-test/t/ndb_cache_multi.test
new file mode 100644
index 00000000000..7202b5f8558
--- /dev/null
+++ b/mysql-test/t/ndb_cache_multi.test
@@ -0,0 +1,64 @@
+-- source include/have_query_cache.inc
+-- source include/have_ndb.inc
+-- source include/have_multi_ndb.inc
+
+--disable_warnings
+drop table if exists t1, t2;
+--enable_warnings
+
+
+# Turn on and reset query cache on server1
+connection server1;
+set GLOBAL query_cache_type=on;
+set GLOBAL query_cache_size=1355776;
+reset query cache;
+flush status;
+
+# Turn on and reset query cache on server2
+connection server2;
+set GLOBAL query_cache_type=on;
+set GLOBAL query_cache_size=1355776;
+reset query cache;
+flush status;
+
+
+
+# Create test tables in NDB and load them into cache
+# on server1
+connection server1;
+create table t1 (a int) engine=ndbcluster;
+create table t2 (a int) engine=ndbcluster;
+insert into t1 value (2);
+insert into t2 value (3);
+select * from t1;
+select * from t2;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+
+
+# Connect server2, load table in to cache, then update the table
+connection server2;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+select * from t1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+update t1 set a=3 where a=2;
+
+# Connect to server1 and check that cache is invalidated
+# and correct data is returned
+connection server1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+select * from t1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+
+drop table t1, t2;
+
+
diff --git a/mysql-test/t/ndb_cache_multi2.test b/mysql-test/t/ndb_cache_multi2.test
new file mode 100644
index 00000000000..a9d008dba7c
--- /dev/null
+++ b/mysql-test/t/ndb_cache_multi2.test
@@ -0,0 +1,71 @@
+-- source include/have_query_cache.inc
+-- source include/have_ndb.inc
+-- source include/have_multi_ndb.inc
+
+--disable_warnings
+drop table if exists t1, t2;
+--enable_warnings
+
+
+# Turn on and reset query cache on server1
+connection server1;
+set GLOBAL query_cache_type=on;
+set GLOBAL query_cache_size=1355776;
+set GLOBAL ndb_cache_check_time=1;
+reset query cache;
+flush status;
+
+# Turn on and reset query cache on server2
+connection server2;
+set GLOBAL query_cache_type=on;
+set GLOBAL query_cache_size=1355776;
+set GLOBAL ndb_cache_check_time=1;
+reset query cache;
+flush status;
+
+# Sleep so that the query cache check thread has time to start
+sleep 15;
+
+
+# Create test tables in NDB and load them into cache
+# on server1
+connection server1;
+create table t1 (a int) engine=ndbcluster;
+create table t2 (a int) engine=ndbcluster;
+insert into t1 value (2);
+insert into t2 value (3);
+select * from t1;
+select * from t2;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+
+
+# Connect server2, load table in to cache, then update the table
+connection server2;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+select * from t1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+update t1 set a=3 where a=2;
+
+# Sleep so that the query cache check thread has time to run
+sleep 5;
+
+# Connect to server1 and check that cache is invalidated
+# and correct data is returned
+connection server1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+select * from t1;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_inserts";
+show status like "Qcache_hits";
+
+drop table t1, t2;
+
+
diff --git a/mysql-test/t/ndb_multi.test b/mysql-test/t/ndb_multi.test
new file mode 100644
index 00000000000..9286721b677
--- /dev/null
+++ b/mysql-test/t/ndb_multi.test
@@ -0,0 +1,44 @@
+-- source include/have_ndb.inc
+-- source include/have_multi_ndb.inc
+
+
+--disable_warnings
+drop table if exists t1, t2, t3, t4;
+--enable_warnings
+
+flush status;
+
+# Create test tables on server1
+create table t1 (a int) engine=ndbcluster;
+create table t2 (a int) engine=ndbcluster;
+insert into t1 value (2);
+insert into t2 value (3);
+select * from t1;
+select * from t2;
+show status like 'handler_discover%';
+
+# Connect to server2 and use the tables from there
+connection server2;
+flush status;
+select * from t1;
+update t1 set a=3 where a=2;
+show status like 'handler_discover%';
+
+# Create a new table on server2
+create table t3 (a int not null primary key, b varchar(22),
+c int, last_col text) engine=ndb;
+insert into t3 values(1, 'Hi!', 89, 'Longtext column');
+create table t4 (pk int primary key, b int) engine=ndb;
+
+# Check that the tables are accessible from server1
+connection server1;
+select * from t1;
+select * from t3;
+show status like 'handler_discover%';
+show tables like 't4';
+show status like 'handler_discover%';
+show tables;
+
+drop table t1, t2, t3, t4;
+
+
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 08d77941dfe..9baf082487f 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -1470,17 +1470,3 @@ select 1 = ALL (select 1 from t1 where 1 = xx ), 1 as xx;
-- error 1247
select 1 = ALL (select 1 from t1 where 1 = xx ), 1 as xx from DUAL;
drop table t1;
-
-#
-# cleaning up of results of subselects (BUG#8125)
-#
-CREATE TABLE `t1` ( `a` char(3) NOT NULL default '', `b` char(3) NOT NULL default '', `c` char(3) NOT NULL default '', PRIMARY KEY (`a`,`b`,`c`)) ENGINE=InnoDB;
-CREATE TABLE t2 LIKE t1;
-INSERT INTO t1 VALUES (1,1,1);
-INSERT INTO t2 VALUES (1,1,1);
-PREPARE my_stmt FROM "SELECT t1.b, count(*) FROM t1 group by t1.b having
-count(*) > ALL (SELECT COUNT(*) FROM t2 WHERE t2.a=1 GROUP By t2.b)";
-EXECUTE my_stmt;
-EXECUTE my_stmt;
-deallocate prepare my_stmt;
-drop table t1,t2;
diff --git a/mysql-test/t/subselect_innodb.test b/mysql-test/t/subselect_innodb.test
index aa7fe138876..5d796988178 100644
--- a/mysql-test/t/subselect_innodb.test
+++ b/mysql-test/t/subselect_innodb.test
@@ -145,3 +145,17 @@ SELECT DISTINCT
FROM t1;
select * from t1;
drop table t1;
+
+#
+# cleaning up of results of subselects (BUG#8125)
+#
+CREATE TABLE `t1` ( `a` char(3) NOT NULL default '', `b` char(3) NOT NULL default '', `c` char(3) NOT NULL default '', PRIMARY KEY (`a`,`b`,`c`)) ENGINE=InnoDB;
+CREATE TABLE t2 LIKE t1;
+INSERT INTO t1 VALUES (1,1,1);
+INSERT INTO t2 VALUES (1,1,1);
+PREPARE my_stmt FROM "SELECT t1.b, count(*) FROM t1 group by t1.b having
+count(*) > ALL (SELECT COUNT(*) FROM t2 WHERE t2.a=1 GROUP By t2.b)";
+EXECUTE my_stmt;
+EXECUTE my_stmt;
+deallocate prepare my_stmt;
+drop table t1,t2;
diff --git a/mysql-test/t/type_date.test b/mysql-test/t/type_date.test
index 64420a85189..304ed19b971 100644
--- a/mysql-test/t/type_date.test
+++ b/mysql-test/t/type_date.test
@@ -107,3 +107,10 @@ SELECT * FROM t2;
SELECT * FROM t3;
DROP TABLE t1, t2, t3;
+
+# Test that setting YEAR to invalid string results in default value, not
+# 2000. (Bug #6067)
+CREATE TABLE t1 (y YEAR);
+INSERT INTO t1 VALUES ('abc');
+SELECT * FROM t1;
+DROP TABLE t1;
diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test
index 6045d8e3c30..be6bc7a48d8 100644
--- a/mysql-test/t/union.test
+++ b/mysql-test/t/union.test
@@ -682,3 +682,38 @@ show create table t1;
drop table t1;
drop table t2;
+#
+# Bug 6931: Date Type column problem when using UNION-Table.
+#
+create table t1(a1 int, f1 char(10));
+create table t2
+select f2,a1 from (select a1, CAST('2004-12-31' AS DATE) f2 from t1) a
+union
+select f2,a1 from (select a1, CAST('2004-12-31' AS DATE) f2 from t1) a
+order by f2, a1;
+show columns from t2;
+drop table t1, t2;
+
+create table t1 (f1 int);
+create table t2 (f1 int, f2 int ,f3 date);
+create table t3 (f1 int, f2 char(10));
+create table t4
+(
+ select t2.f3 as sdate
+ from t1
+ left outer join t2 on (t1.f1 = t2.f1)
+ inner join t3 on (t2.f2 = t3.f1)
+ order by t1.f1, t3.f1, t2.f3
+)
+union
+(
+ select cast('2004-12-31' as date) as sdate
+ from t1
+ left outer join t2 on (t1.f1 = t2.f1)
+ inner join t3 on (t2.f2 = t3.f1)
+ group by t1.f1
+ order by t1.f1, t3.f1, t2.f3
+)
+order by sdate;
+show columns from t4;
+drop table t1, t2, t3, t4;
diff --git a/mysql-test/t/update.test b/mysql-test/t/update.test
index 704263b1216..04192f25ac8 100644
--- a/mysql-test/t/update.test
+++ b/mysql-test/t/update.test
@@ -170,3 +170,12 @@ insert into t1 values (1, "t1c2-1", 10), (2, "t1c2-2", 20);
update t1 left join t2 on t1.c1 = t2.c1 set t2.c2 = "t2c2-1";
update t1 left join t2 on t1.c1 = t2.c1 set t2.c2 = "t2c2-1" where t1.c3 = 10;
drop table t1, t2;
+
+#
+# Bug #8057
+#
+create table t1 (id int not null auto_increment primary key, id_str varchar(32));
+insert into t1 (id_str) values ("test");
+update t1 set id_str = concat(id_str, id) where id = last_insert_id();
+select * from t1;
+drop table t1;
diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c
index c14b2899b4b..e0d6288f76b 100644
--- a/mysys/my_alloc.c
+++ b/mysys/my_alloc.c
@@ -166,7 +166,8 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size)
gptr point;
reg1 USED_MEM *next= 0;
reg2 USED_MEM **prev;
-
+ DBUG_ENTER("alloc_root");
+ DBUG_PRINT("enter",("root: 0x%lx", mem_root));
DBUG_ASSERT(alloc_root_inited(mem_root));
Size= ALIGN_SIZE(Size);
@@ -213,7 +214,8 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size)
mem_root->used= next;
mem_root->first_block_usage= 0;
}
- return(point);
+ DBUG_PRINT("exit",("ptr: 0x%lx", (ulong) point));
+ DBUG_RETURN(point);
#endif
}
diff --git a/ndb/include/ndbapi/NdbDictionary.hpp b/ndb/include/ndbapi/NdbDictionary.hpp
index 91cfc0cb22a..6b9085fbdca 100644
--- a/ndb/include/ndbapi/NdbDictionary.hpp
+++ b/ndb/include/ndbapi/NdbDictionary.hpp
@@ -140,9 +140,9 @@ public:
enum FragmentType {
FragUndefined = 0, ///< Fragmentation type undefined or default
FragSingle = 1, ///< Only one fragment
- FragAllSmall = 2, ///< One fragment per node group
- FragAllMedium = 3, ///< Default value. Two fragments per node group.
- FragAllLarge = 4 ///< Eight fragments per node group.
+ FragAllSmall = 2, ///< One fragment per node, default
+ FragAllMedium = 3, ///< two fragments per node
+ FragAllLarge = 4 ///< Four fragments per node.
};
};
diff --git a/ndb/src/common/util/NdbSqlUtil.cpp b/ndb/src/common/util/NdbSqlUtil.cpp
index d5f06f119ee..b691b4cb512 100644
--- a/ndb/src/common/util/NdbSqlUtil.cpp
+++ b/ndb/src/common/util/NdbSqlUtil.cpp
@@ -550,8 +550,6 @@ NdbSqlUtil::cmpDate(const void* info, const void* p1, unsigned n1, const void* p
return +1;
return 0;
}
- assert(! full);
- return CmpUnknown;
#else
char t1[4], t2[4];
if (n1 == 3 && n2 == 3)
@@ -562,6 +560,7 @@ NdbSqlUtil::cmpDate(const void* info, const void* p1, unsigned n1, const void* p
p2 = t2;
n1 = n2 = 4;
}
+#ifdef ndb_date_sol9x86_cc_xO3_madness
if (n2 >= 4) { // may access 4-th byte
const uchar* v1 = (const uchar*)p1;
const uchar* v2 = (const uchar*)p2;
@@ -576,9 +575,40 @@ NdbSqlUtil::cmpDate(const void* info, const void* p1, unsigned n1, const void* p
return +1;
return 0;
}
+#else
+ if (n2 >= 4) {
+ const uchar* v1 = (const uchar*)p1;
+ const uchar* v2 = (const uchar*)p2;
+ uint j1 = uint3korr(v1);
+ uint j2 = uint3korr(v2);
+ uint d1 = (j1 & 31);
+ uint d2 = (j2 & 31);
+ j1 = (j1 >> 5);
+ j2 = (j2 >> 5);
+ uint m1 = (j1 & 15);
+ uint m2 = (j2 & 15);
+ j1 = (j1 >> 4);
+ j2 = (j2 >> 4);
+ uint y1 = j1;
+ uint y2 = j2;
+ if (y1 < y2)
+ return -1;
+ if (y1 > y2)
+ return +1;
+ if (m1 < m2)
+ return -1;
+ if (m1 > m2)
+ return +1;
+ if (d1 < d2)
+ return -1;
+ if (d1 > d2)
+ return +1;
+ return 0;
+ }
+#endif
+#endif
assert(! full);
return CmpUnknown;
-#endif
}
// not supported
diff --git a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
index cf0b1419697..af75707560a 100644
--- a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
+++ b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
@@ -6178,7 +6178,7 @@ void Dbdih::execCREATE_FRAGMENTATION_REQ(Signal * signal){
break;
case DictTabInfo::AllNodesMediumTable:
jam();
- noOfFragments = csystemnodes;
+ noOfFragments = 2 * csystemnodes;
break;
case DictTabInfo::AllNodesLargeTable:
jam();
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp b/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
index 9778c938e0f..bc1700c12ad 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
@@ -1865,6 +1865,11 @@ int Dbtup::interpreterNextLab(Signal* signal,
}
else
{
+ /* --------------------------------------------------------- */
+ // If length of argument rounded to nearest word is
+ // the same as attribute size, use that as argument size
+ /* --------------------------------------------------------- */
+ if ((((argLen + 3) >> 2) << 2) == attrLen) argLen= attrLen;
res = (*sqlType.m_cmp)(cs, s1, attrLen, s2, argLen, true);
}
diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/ndb/src/ndbapi/NdbDictionaryImpl.cpp
index ca118cd0994..f917fcce18b 100644
--- a/ndb/src/ndbapi/NdbDictionaryImpl.cpp
+++ b/ndb/src/ndbapi/NdbDictionaryImpl.cpp
@@ -295,7 +295,7 @@ void
NdbTableImpl::init(){
clearNewProperties();
m_frm.clear();
- m_fragmentType = NdbDictionary::Object::FragAllMedium;
+ m_fragmentType = NdbDictionary::Object::FragAllSmall;
m_logging = true;
m_kvalue = 6;
m_minLoadFactor = 78;
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index 221fab13635..c26cc8afedb 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -140,6 +140,9 @@ SUFFIXES = .sh
-e 's!@''IS_LINUX''@!@IS_LINUX@!' \
-e "s!@""CONF_COMMAND""@!@CONF_COMMAND@!" \
-e 's!@''MYSQLD_USER''@!@MYSQLD_USER@!' \
+ -e 's!@''STATIC_NSS_FLAGS''@!@STATIC_NSS_FLAGS@!' \
+ -e 's!@''NON_THREADED_LIBS''@!@NON_THREADED_LIBS@!' \
+ -e 's!@''ZLIB_DEPS''@!@ZLIB_DEPS@!' \
-e "s!@MAKE@!$(MAKE)!" \
$< > $@-t
@CHMOD@ +x $@-t
diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh
index 4743b37a098..4c339b063d9 100644
--- a/scripts/make_binary_distribution.sh
+++ b/scripts/make_binary_distribution.sh
@@ -221,7 +221,7 @@ $CP mysql-test/std_data/*.dat mysql-test/std_data/*.frm \
mysql-test/std_data/des_key_file mysql-test/std_data/*.*001 \
$BASE/mysql-test/std_data
$CP mysql-test/t/*test mysql-test/t/*.opt mysql-test/t/*.slave-mi mysql-test/t/*.sh $BASE/mysql-test/t
-$CP mysql-test/r/*result mysql-test/r/*.require $BASE/mysql-test/r
+$CP mysql-test/r/*result mysql-test/r/*result.es mysql-test/r/*.require $BASE/mysql-test/r
if [ $BASE_SYSTEM != "netware" ] ; then
chmod a+x $BASE/bin/*
diff --git a/scripts/mysql_config.sh b/scripts/mysql_config.sh
index 90418de3d1d..a5c8af5ecb2 100644
--- a/scripts/mysql_config.sh
+++ b/scripts/mysql_config.sh
@@ -82,13 +82,14 @@ version='@VERSION@'
socket='@MYSQL_UNIX_ADDR@'
port='@MYSQL_TCP_PORT@'
ldflags='@LDFLAGS@'
-client_libs='@CLIENT_LIBS@'
# Create options
-libs="$ldflags -L$pkglibdir -lmysqlclient $client_libs"
+libs="$ldflags -L$pkglibdir -lmysqlclient @ZLIB_DEPS@ @NON_THREADED_LIBS@"
+libs="$libs @openssl_libs@ @STATIC_NSS_FLAGS@"
libs=`echo "$libs" | sed -e 's; \+; ;g' | sed -e 's;^ *;;' | sed -e 's; *\$;;'`
-libs_r="$ldflags -L$pkglibdir -lmysqlclient_r @LIBS@ @ZLIB_LIBS@ @openssl_libs@"
+
+libs_r="$ldflags -L$pkglibdir -lmysqlclient_r @ZLIB_DEPS@ @LIBS@ @openssl_libs@"
libs_r=`echo "$libs_r" | sed -e 's; \+; ;g' | sed -e 's;^ *;;' | sed -e 's; *\$;;'`
cflags="-I$pkgincludedir @CFLAGS@ " #note: end space!
include="-I$pkgincludedir"
diff --git a/sql/field.cc b/sql/field.cc
index aa2c5805bfe..f95eaaba5df 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -261,6 +261,7 @@ static Field::field_cast_enum field_cast_date[]=
Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP};
static Field::field_cast_enum field_cast_newdate[]=
{Field::FIELD_CAST_NEWDATE,
+ Field::FIELD_CAST_DATE,
Field::FIELD_CAST_DATETIME,
Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING,
Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP};
@@ -6834,6 +6835,40 @@ Field *make_field(char *ptr, uint32 field_length,
}
+/*
+ Check if field_type is appropriate field type
+ to create field for tmp table using
+ item->tmp_table_field() method
+
+ SYNOPSIS
+ field_types_to_be_kept()
+ field_type - field type
+
+ NOTE
+ it is used in function get_holder_example_field()
+ from item.cc
+
+ RETURN
+ 1 - can use item->tmp_table_field() method
+ 0 - can not use item->tmp_table_field() method
+
+*/
+
+bool field_types_to_be_kept(enum_field_types field_type)
+{
+ switch (field_type)
+ {
+ case FIELD_TYPE_DATE:
+ case FIELD_TYPE_NEWDATE:
+ case FIELD_TYPE_TIME:
+ case FIELD_TYPE_DATETIME:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+
/* Create a field suitable for create of table */
create_field::create_field(Field *old_field,Field *orig_field)
diff --git a/sql/field.h b/sql/field.h
index af300c8d471..756fa713707 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -1333,6 +1333,7 @@ enum_field_types get_blob_type_from_length(ulong length);
uint32 calc_pack_length(enum_field_types type,uint32 length);
int set_field_to_null(Field *field);
int set_field_to_null_with_conversions(Field *field, bool no_conversions);
+bool field_types_to_be_kept(enum_field_types field_type);
/*
The following are for the interface with the .frm file
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 04ae0211970..b4f3f9e9dfd 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -787,8 +787,9 @@ innobase_query_caching_of_table_permitted(
char* full_name, /* in: concatenation of database name,
the null character '\0', and the table
name */
- uint full_name_len) /* in: length of the full name, i.e.
+ uint full_name_len, /* in: length of the full name, i.e.
len(dbname) + len(tablename) + 1 */
+ ulonglong *unused) /* unused for this engine */
{
ibool is_autocommit;
trx_t* trx;
diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h
index 7a48de52422..cca33cbbe1c 100644
--- a/sql/ha_innodb.h
+++ b/sql/ha_innodb.h
@@ -33,6 +33,10 @@ typedef struct st_innobase_share {
} INNOBASE_SHARE;
+my_bool innobase_query_caching_of_table_permitted(THD* thd, char* full_name,
+ uint full_name_len,
+ ulonglong *unused);
+
/* The class defining a handle to an Innodb table */
class ha_innobase: public handler
{
@@ -173,6 +177,20 @@ class ha_innobase: public handler
void init_table_handle_for_HANDLER();
ulonglong get_auto_increment();
uint8 table_cache_type() { return HA_CACHE_TBL_ASKTRANSACT; }
+ /*
+ ask handler about permission to cache table during query registration
+ */
+ my_bool register_query_cache_table(THD *thd, char *table_key,
+ uint key_length,
+ qc_engine_callback *call_back,
+ ulonglong *engine_data)
+ {
+ *call_back= innobase_query_caching_of_table_permitted;
+ *engine_data= 0;
+ return innobase_query_caching_of_table_permitted(thd, table_key,
+ key_length,
+ engine_data);
+ }
static char *get_mysql_bin_log_name();
static ulonglong get_mysql_bin_log_pos();
bool primary_key_is_clustered() { return true; }
@@ -253,8 +271,6 @@ bool innodb_show_status(THD* thd);
bool innodb_mutex_show_status(THD* thd);
void innodb_export_status(void);
-my_bool innobase_query_caching_of_table_permitted(THD* thd, char* full_name,
- uint full_name_len);
void innobase_release_temporary_latches(void* innobase_tid);
void innobase_store_binlog_offset_and_flush_log(char *binlog_name,longlong offset);
diff --git a/sql/ha_myisam.h b/sql/ha_myisam.h
index d2fe36c8357..7e14a3b7941 100644
--- a/sql/ha_myisam.h
+++ b/sql/ha_myisam.h
@@ -88,8 +88,12 @@ class ha_myisam: public handler
ft_handler->please->reinit_search(ft_handler);
return 0;
}
- FT_INFO *ft_init_ext(uint flags, uint inx,const byte *key, uint keylen)
- { return ft_init_search(flags,file,inx,(byte*) key,keylen, table->record[0]); }
+ FT_INFO *ft_init_ext(uint flags, uint inx,String *key)
+ {
+ return ft_init_search(flags,file,inx,
+ (byte *)key->ptr(), key->length(), key->charset(),
+ table->record[0]);
+ }
int ft_read(byte *buf);
int rnd_init(bool scan);
int rnd_next(byte *buf);
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index f2b159353e3..890addf0c5b 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -87,6 +87,12 @@ static int unpackfrm(const void **data, uint *len,
static int ndb_get_table_statistics(Ndb*, const char *,
struct Ndb_statistics *);
+// Util thread variables
+static pthread_t ndb_util_thread;
+pthread_mutex_t LOCK_ndb_util_thread;
+pthread_cond_t COND_ndb_util_thread;
+extern "C" pthread_handler_decl(ndb_util_thread_func, arg);
+ulong ndb_cache_check_time;
/*
Dummy buffer to read zero pack_length fields
@@ -3053,9 +3059,13 @@ int ha_ndbcluster::reset()
DBUG_RETURN(1);
}
+static const char *ha_ndb_bas_ext[]= { ha_ndb_ext, NullS };
-const char **ha_ndbcluster::bas_ext() const
-{ static const char *ext[]= { ha_ndb_ext, NullS }; return ext; }
+const char**
+ha_ndbcluster::bas_ext() const
+{
+ return ha_ndb_bas_ext;
+}
/*
@@ -3223,7 +3233,6 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
m_transaction_on= FALSE;
else
m_transaction_on= thd->variables.ndb_use_transactions;
- // m_use_local_query_cache= thd->variables.ndb_use_local_query_cache;
m_active_trans= thd->transaction.all.ndb_tid ?
(NdbTransaction*)thd->transaction.all.ndb_tid:
@@ -3650,6 +3659,47 @@ static int create_ndb_column(NDBCOL &col,
Create a table in NDB Cluster
*/
+static void ndb_set_fragmentation(NDBTAB &tab, TABLE *form, uint pk_length)
+{
+ if (form->s->max_rows == 0) /* default setting, don't set fragmentation */
+ return;
+ /**
+ * get the number of fragments right
+ */
+ uint no_fragments;
+ {
+#if MYSQL_VERSION_ID >= 50000
+ uint acc_row_size= 25+2;
+#else
+ uint acc_row_size= pk_length*4;
+ /* add acc overhead */
+ if (pk_length <= 8)
+ acc_row_size+= 25+2; /* main page will set the limit */
+ else
+ acc_row_size+= 4+4; /* overflow page will set the limit */
+#endif
+ ulonglong acc_fragment_size= 512*1024*1024;
+ ulonglong max_rows= form->s->max_rows;
+ no_fragments= (max_rows*acc_row_size)/acc_fragment_size+1;
+ }
+ {
+ uint no_nodes= g_ndb_cluster_connection->no_db_nodes();
+ NDBTAB::FragmentType ftype;
+ if (no_fragments > 2*no_nodes)
+ {
+ ftype= NDBTAB::FragAllLarge;
+ if (no_fragments > 4*no_nodes)
+ push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
+ "Ndb might have problems storing the max amount of rows specified");
+ }
+ else if (no_fragments > no_nodes)
+ ftype= NDBTAB::FragAllMedium;
+ else
+ ftype= NDBTAB::FragAllSmall;
+ tab.setFragmentType(ftype);
+ }
+}
+
int ha_ndbcluster::create(const char *name,
TABLE *form,
HA_CREATE_INFO *info)
@@ -3751,7 +3801,9 @@ int ha_ndbcluster::create(const char *name,
break;
}
}
-
+
+ ndb_set_fragmentation(tab, form, pk_length);
+
if ((my_errno= check_ndb_connection()))
DBUG_RETURN(my_errno);
@@ -4017,7 +4069,6 @@ ha_ndbcluster::ha_ndbcluster(TABLE *table_arg):
m_force_send(TRUE),
m_autoincrement_prefetch(32),
m_transaction_on(TRUE),
- m_use_local_query_cache(FALSE),
m_multi_cursor(NULL)
{
int i;
@@ -4068,6 +4119,7 @@ ha_ndbcluster::~ha_ndbcluster()
}
+
/*
Open a table for further use
- fetch metadata for this table from NDB
@@ -4168,16 +4220,14 @@ void ha_ndbcluster::release_thd_ndb(Thd_ndb* thd_ndb)
Ndb* check_ndb_in_thd(THD* thd)
{
- DBUG_ENTER("check_ndb_in_thd");
- Thd_ndb *thd_ndb= (Thd_ndb*)thd->transaction.thd_ndb;
-
+ Thd_ndb *thd_ndb= (Thd_ndb*)thd->transaction.thd_ndb;
if (!thd_ndb)
{
if (!(thd_ndb= ha_ndbcluster::seize_thd_ndb()))
- DBUG_RETURN(NULL);
+ return NULL;
thd->transaction.thd_ndb= thd_ndb;
}
- DBUG_RETURN(thd_ndb->ndb);
+ return thd_ndb->ndb;
}
@@ -4530,13 +4580,21 @@ bool ndbcluster_init()
(void) hash_init(&ndbcluster_open_tables,system_charset_info,32,0,0,
(hash_get_key) ndbcluster_get_key,0,0);
pthread_mutex_init(&ndbcluster_mutex,MY_MUTEX_INIT_FAST);
+ pthread_mutex_init(&LOCK_ndb_util_thread, MY_MUTEX_INIT_FAST);
+ pthread_cond_init(&COND_ndb_util_thread, NULL);
+
+ // Create utility thread
+ pthread_t tmp;
+ if (pthread_create(&tmp, &connection_attrib, ndb_util_thread_func, 0))
+ {
+ DBUG_PRINT("error", ("Could not create ndb utility thread"));
+ goto ndbcluster_init_error;
+ }
+
ndbcluster_inited= 1;
-#ifdef USE_DISCOVER_ON_STARTUP
- if (ndb_discover_tables() != 0)
- goto ndbcluster_init_error;
-#endif
DBUG_RETURN(FALSE);
+
ndbcluster_init_error:
ndbcluster_end();
DBUG_RETURN(TRUE);
@@ -4546,12 +4604,19 @@ bool ndbcluster_init()
/*
End use of the NDB Cluster table handler
- free all global variables allocated by
- ndcluster_init()
+ ndbcluster_init()
*/
bool ndbcluster_end()
{
DBUG_ENTER("ndbcluster_end");
+
+ // Kill ndb utility thread
+ (void) pthread_mutex_lock(&LOCK_ndb_util_thread);
+ DBUG_PRINT("exit",("killing ndb util thread: %lx", ndb_util_thread));
+ (void) pthread_cond_signal(&COND_ndb_util_thread);
+ (void) pthread_mutex_unlock(&LOCK_ndb_util_thread);
+
if(g_ndb)
delete g_ndb;
g_ndb= NULL;
@@ -4562,6 +4627,8 @@ bool ndbcluster_end()
DBUG_RETURN(0);
hash_free(&ndbcluster_open_tables);
pthread_mutex_destroy(&ndbcluster_mutex);
+ pthread_mutex_destroy(&LOCK_ndb_util_thread);
+ pthread_cond_destroy(&COND_ndb_util_thread);
ndbcluster_inited= 0;
DBUG_RETURN(0);
}
@@ -4754,12 +4821,170 @@ const char* ha_ndbcluster::index_type(uint key_number)
return "HASH";
}
}
+
uint8 ha_ndbcluster::table_cache_type()
{
- if (m_use_local_query_cache)
- return HA_CACHE_TBL_TRANSACT;
- else
- return HA_CACHE_TBL_NOCACHE;
+ DBUG_ENTER("ha_ndbcluster::table_cache_type=HA_CACHE_TBL_ASKTRANSACT");
+ DBUG_RETURN(HA_CACHE_TBL_ASKTRANSACT);
+}
+
+
+uint ndb_get_commitcount(THD* thd, char* dbname, char* tabname,
+ Uint64* commit_count)
+{
+ DBUG_ENTER("ndb_get_commitcount");
+
+ if (ndb_cache_check_time > 0)
+ {
+ // Use cached commit_count from share
+ char name[FN_REFLEN];
+ NDB_SHARE* share;
+ (void)strxnmov(name, FN_REFLEN,
+ "./",dbname,"/",tabname,NullS);
+ DBUG_PRINT("info", ("name: %s", name));
+ pthread_mutex_lock(&ndbcluster_mutex);
+ if (!(share=(NDB_SHARE*) hash_search(&ndbcluster_open_tables,
+ (byte*) name,
+ strlen(name))))
+ {
+ pthread_mutex_unlock(&ndbcluster_mutex);
+ DBUG_RETURN(1);
+ }
+ *commit_count= share->commit_count;
+ DBUG_PRINT("info", ("commit_count: %d", *commit_count));
+ pthread_mutex_unlock(&ndbcluster_mutex);
+ DBUG_RETURN(0);
+ }
+
+ // Get commit_count from NDB
+ Ndb *ndb;
+ if (!(ndb= check_ndb_in_thd(thd)))
+ DBUG_RETURN(1);
+ ndb->setDatabaseName(dbname);
+
+ struct Ndb_statistics stat;
+ if (ndb_get_table_statistics(ndb, tabname, &stat))
+ DBUG_RETURN(1);
+ *commit_count= stat.commit_count;
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Check if a cached query can be used.
+ This is done by comparing the supplied engine_data to commit_count of
+ the table.
+ The commit_count is either retrieved from the share for the table, where
+ it has been cached by the util thread. If the util thread is not started,
+ NDB has to be contacetd to retrieve the commit_count, this will introduce
+ a small delay while waiting for NDB to answer.
+
+
+ SYNOPSIS
+ ndbcluster_cache_retrieval_allowed
+ thd thread handle
+ full_name concatenation of database name,
+ the null character '\0', and the table
+ name
+ full_name_len length of the full name,
+ i.e. len(dbname) + len(tablename) + 1
+
+ engine_data parameter retrieved when query was first inserted into
+ the cache. If the value of engine_data is changed,
+ all queries for this table should be invalidated.
+
+ RETURN VALUE
+ TRUE Yes, use the query from cache
+ FALSE No, don't use the cached query, and if engine_data
+ has changed, all queries for this table should be invalidated
+
+*/
+
+static my_bool
+ndbcluster_cache_retrieval_allowed(THD* thd,
+ char* full_name, uint full_name_len,
+ ulonglong *engine_data)
+{
+ DBUG_ENTER("ndbcluster_cache_retrieval_allowed");
+
+ Uint64 commit_count;
+ bool is_autocommit= !(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN));
+ char* dbname= full_name;
+ char* tabname= dbname+strlen(dbname)+1;
+
+ DBUG_PRINT("enter",("dbname=%s, tabname=%s, autocommit=%d",
+ dbname, tabname, is_autocommit));
+
+ if (!is_autocommit)
+ DBUG_RETURN(FALSE);
+
+ if (ndb_get_commitcount(thd, dbname, tabname, &commit_count))
+ {
+ *engine_data+= 1; // invalidate
+ DBUG_RETURN(FALSE);
+ }
+ DBUG_PRINT("info", ("*engine_data=%llu, commit_count=%llu",
+ *engine_data, commit_count));
+ if (*engine_data != commit_count)
+ {
+ *engine_data= commit_count; // invalidate
+ DBUG_PRINT("exit",("Do not use cache, commit_count has changed"));
+ DBUG_RETURN(FALSE);
+ }
+
+ DBUG_PRINT("exit",("OK to use cache, *engine_data=%llu",*engine_data));
+ DBUG_RETURN(TRUE);
+}
+
+
+/**
+ Register a table for use in the query cache. Fetch the commit_count
+ for the table and return it in engine_data, this will later be used
+ to check if the table has changed, before the cached query is reused.
+
+ SYNOPSIS
+ ha_ndbcluster::can_query_cache_table
+ thd thread handle
+ full_name concatenation of database name,
+ the null character '\0', and the table
+ name
+ full_name_len length of the full name,
+ i.e. len(dbname) + len(tablename) + 1
+ qc_engine_callback function to be called before using cache on this table
+ engine_data out, commit_count for this table
+
+ RETURN VALUE
+ TRUE Yes, it's ok to cahce this query
+ FALSE No, don't cach the query
+
+*/
+
+my_bool
+ha_ndbcluster::register_query_cache_table(THD* thd,
+ char* full_name, uint full_name_len,
+ qc_engine_callback *engine_callback,
+ ulonglong *engine_data)
+{
+ DBUG_ENTER("ha_ndbcluster::register_query_cache_table");
+
+ bool is_autocommit= !(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN));
+ DBUG_PRINT("enter",("dbname=%s, tabname=%s, is_autocommit=%d",
+ m_dbname,m_tabname,is_autocommit));
+ if (!is_autocommit)
+ DBUG_RETURN(FALSE);
+
+
+ Uint64 commit_count;
+ if (ndb_get_commitcount(thd, m_dbname, m_tabname, &commit_count))
+ {
+ *engine_data= 0;
+ DBUG_PRINT("error", ("Could not get commitcount"))
+ DBUG_RETURN(FALSE);
+ }
+ *engine_data= commit_count;
+ *engine_callback= ndbcluster_cache_retrieval_allowed;
+ DBUG_PRINT("exit",("*engine_data=%llu", *engine_data));
+ DBUG_RETURN(TRUE);
}
/*
@@ -4800,8 +5025,14 @@ static NDB_SHARE* get_share(const char *table_name)
}
thr_lock_init(&share->lock);
pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST);
+ share->commit_count= 0;
}
}
+ DBUG_PRINT("share",
+ ("table_name: %s, length: %d, use_count: %d, commit_count: %d",
+ share->table_name, share->table_name_length, share->use_count,
+ share->commit_count));
+
share->use_count++;
pthread_mutex_unlock(&ndbcluster_mutex);
return share;
@@ -5407,4 +5638,124 @@ ha_ndbcluster::update_table_comment(
return str;
}
+
+// Utility thread main loop
+extern "C" pthread_handler_decl(ndb_util_thread_func,
+ arg __attribute__((unused)))
+{
+ THD *thd; // needs to be first for thread_stack
+ int error = 0;
+ struct timespec abstime;
+
+ my_thread_init();
+ DBUG_ENTER("ndb_util_thread");
+ DBUG_PRINT("enter", ("ndb_cache_check_time: %d", ndb_cache_check_time));
+
+ thd= new THD; // note that contructor of THD uses DBUG_ !
+ THD_CHECK_SENTRY(thd);
+
+ pthread_detach_this_thread();
+ ndb_util_thread = pthread_self();
+
+ thd->thread_stack = (char*)&thd; // remember where our stack is
+ if (thd->store_globals())
+ {
+ thd->cleanup();
+ delete thd;
+ DBUG_RETURN(NULL);
+ }
+
+ List<NDB_SHARE> util_open_tables;
+ set_timespec(abstime, ndb_cache_check_time);
+ for (;;)
+ {
+
+ pthread_mutex_lock(&LOCK_ndb_util_thread);
+ error= pthread_cond_timedwait(&COND_ndb_util_thread,
+ &LOCK_ndb_util_thread,
+ &abstime);
+ pthread_mutex_unlock(&LOCK_ndb_util_thread);
+
+ DBUG_PRINT("ndb_util_thread", ("Started, ndb_cache_check_time: %d",
+ ndb_cache_check_time));
+
+ if (abort_loop)
+ break; // Shutting down server
+
+ if (ndb_cache_check_time == 0)
+ {
+ set_timespec(abstime, 10);
+ continue;
+ }
+
+ // Set new time to wake up
+ set_timespec(abstime, ndb_cache_check_time);
+
+ // Lock mutex and fill list with pointers to all open tables
+ NDB_SHARE *share;
+ pthread_mutex_lock(&ndbcluster_mutex);
+ for (uint i= 0; i < ndbcluster_open_tables.records; i++)
+ {
+ share= (NDB_SHARE *)hash_element(&ndbcluster_open_tables, i);
+ share->use_count++; // Make sure the table can't be closed
+
+ DBUG_PRINT("ndb_util_thread",
+ ("Found open table[%d]: %s, use_count: %d",
+ i, share->table_name, share->use_count));
+
+ // Store pointer to table
+ util_open_tables.push_back(share);
+ }
+ pthread_mutex_unlock(&ndbcluster_mutex);
+
+
+ // Iterate through the open files list
+ List_iterator_fast<NDB_SHARE> it(util_open_tables);
+ while (share=it++)
+ {
+ // Split tab- and dbname
+ char buf[FN_REFLEN];
+ char *tabname, *db;
+ uint length= dirname_length(share->table_name);
+ tabname= share->table_name+length;
+ memcpy(buf, share->table_name, length-1);
+ buf[length-1]= 0;
+ db= buf+dirname_length(buf);
+ DBUG_PRINT("ndb_util_thread",
+ ("Fetching commit count for: %s, db: %s, tab: %s",
+ share->table_name, db, tabname));
+
+ // Contact NDB to get commit count for table
+ g_ndb->setDatabaseName(db);
+ struct Ndb_statistics stat;;
+ if(ndb_get_table_statistics(g_ndb, tabname, &stat) == 0){
+ DBUG_PRINT("ndb_util_thread",
+ ("Table: %s, rows: %llu, commit_count: %llu",
+ share->table_name, stat.row_count, stat.commit_count));
+ share->commit_count= stat.commit_count;
+ }
+ else
+ {
+ DBUG_PRINT("ndb_util_thread",
+ ("Error: Could not get commit count for table %s",
+ share->table_name));
+ share->commit_count++; // Invalidate
+ }
+ // Decrease the use count and possibly free share
+ free_share(share);
+ }
+
+ // Clear the list of open tables
+ util_open_tables.empty();
+
+ }
+
+ thd->cleanup();
+ delete thd;
+ DBUG_PRINT("exit", ("ndb_util_thread"));
+ my_thread_end();
+ DBUG_RETURN(NULL);
+}
+
+
#endif /* HAVE_NDBCLUSTER_DB */
diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h
index 942a4988252..fb624353491 100644
--- a/sql/ha_ndbcluster.h
+++ b/sql/ha_ndbcluster.h
@@ -37,6 +37,7 @@ class NdbBlob;
// connectstring to cluster if given by mysqld
extern const char *ndbcluster_connectstring;
+extern ulong ndb_cache_check_time;
typedef enum ndb_index_type {
UNDEFINED_INDEX = 0,
@@ -59,6 +60,7 @@ typedef struct st_ndbcluster_share {
pthread_mutex_t mutex;
char *table_name;
uint table_name_length,use_count;
+ uint commit_count;
} NDB_SHARE;
/*
@@ -155,8 +157,11 @@ class ha_ndbcluster: public handler
static Thd_ndb* seize_thd_ndb();
static void release_thd_ndb(Thd_ndb* thd_ndb);
uint8 table_cache_type();
-
- private:
+ my_bool register_query_cache_table(THD *thd, char *table_key,
+ uint key_length,
+ qc_engine_callback *engine_callback,
+ ulonglong *engine_data);
+private:
int alter_table_name(const char *to);
int drop_table();
int create_index(const char *name, KEY *key_info, bool unique);
@@ -256,7 +261,6 @@ class ha_ndbcluster: public handler
bool m_force_send;
ha_rows m_autoincrement_prefetch;
bool m_transaction_on;
- bool m_use_local_query_cache;
bool m_disable_multi_read;
byte *m_multi_range_result_ptr;
diff --git a/sql/handler.cc b/sql/handler.cc
index a9bb19158dd..b4fed363e87 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -234,15 +234,6 @@ handler *get_new_handler(TABLE *table, enum db_type db_type)
}
}
-bool ha_caching_allowed(THD* thd, char* table_key,
- uint key_length, uint8 cache_type)
-{
-#ifdef HAVE_INNOBASE_DB
- if (cache_type == HA_CACHE_TBL_ASKTRANSACT)
- return innobase_query_caching_of_table_permitted(thd, table_key, key_length);
-#endif
- return 1;
-}
/*
diff --git a/sql/handler.h b/sql/handler.h
index 2b5c66fd886..8ad49456bf6 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -455,8 +455,7 @@ public:
int compare_key(key_range *range);
virtual int ft_init() { return HA_ERR_WRONG_COMMAND; }
void ft_end() { ft_handler=NULL; }
- virtual FT_INFO *ft_init_ext(uint flags,uint inx,const byte *key,
- uint keylen)
+ virtual FT_INFO *ft_init_ext(uint flags, uint inx,String *key)
{ return NULL; }
virtual int ft_read(byte *buf) { return HA_ERR_WRONG_COMMAND; }
virtual int rnd_next(byte *buf)=0;
@@ -592,6 +591,16 @@ public:
/* Type of table for caching query */
virtual uint8 table_cache_type() { return HA_CACHE_TBL_NONTRANSACT; }
+ /* ask handler about permission to cache table when query is to be cached */
+ virtual my_bool register_query_cache_table(THD *thd, char *table_key,
+ uint key_length,
+ qc_engine_callback
+ *engine_callback,
+ ulonglong *engine_data)
+ {
+ *engine_callback= 0;
+ return 1;
+ }
/*
RETURN
@@ -622,8 +631,6 @@ extern TYPELIB tx_isolation_typelib;
T != DB_TYPE_BERKELEY_DB && \
T != DB_TYPE_NDBCLUSTER)
-bool ha_caching_allowed(THD* thd, char* table_key,
- uint key_length, uint8 cache_type);
enum db_type ha_resolve_by_name(const char *name, uint namelen);
const char *ha_get_storage_engine(enum db_type db_type);
handler *get_new_handler(TABLE *table, enum db_type db_type);
diff --git a/sql/item.cc b/sql/item.cc
index 08de3889ae6..a0d1d8cbacf 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -3633,7 +3633,53 @@ void Item_cache_row::bring_value()
}
-Item_type_holder::Item_type_holder(THD *thd, Item *item)
+/*
+ Returns field for temporary table dependind on item type
+
+ SYNOPSIS
+ get_holder_example_field()
+ thd - thread handler
+ item - pointer to item
+ table - empty table object
+
+ NOTE
+ It is possible to return field for Item_func
+ items only if field type of this item is
+ date or time or datetime type.
+ also see function field_types_to_be_kept() from
+ field.cc
+
+ RETURN
+ # - field
+ 0 - no field
+*/
+
+Field *get_holder_example_field(THD *thd, Item *item, TABLE *table)
+{
+ DBUG_ASSERT(table);
+
+ Item_func *tmp_item= 0;
+ if (item->type() == Item::FIELD_ITEM)
+ return (((Item_field*) item)->field);
+ if (item->type() == Item::FUNC_ITEM)
+ tmp_item= (Item_func *) item;
+ else if (item->type() == Item::SUM_FUNC_ITEM)
+ {
+ Item_sum *item_sum= (Item_sum *) item;
+ if (item_sum->keep_field_type())
+ {
+ if (item_sum->args[0]->type() == Item::FIELD_ITEM)
+ return (((Item_field*) item_sum->args[0])->field);
+ if (item_sum->args[0]->type() == Item::FUNC_ITEM)
+ tmp_item= (Item_func *) item_sum->args[0];
+ }
+ }
+ return (tmp_item && field_types_to_be_kept(tmp_item->field_type()) ?
+ tmp_item->tmp_table_field(table) : 0);
+}
+
+
+Item_type_holder::Item_type_holder(THD *thd, Item *item, TABLE *table)
:Item(thd, item), item_type(item->result_type()),
orig_type(item_type)
{
@@ -3643,10 +3689,7 @@ Item_type_holder::Item_type_holder(THD *thd, Item *item)
It is safe assign pointer on field, because it will be used just after
all JOIN::prepare calls and before any SELECT execution
*/
- if (item->type() == Item::FIELD_ITEM)
- field_example= ((Item_field*) item)->field;
- else
- field_example= 0;
+ field_example= get_holder_example_field(thd, item, table);
max_length= real_length(item);
maybe_null= item->maybe_null;
collation.set(item->collation);
@@ -3686,25 +3729,23 @@ inline bool is_attr_compatible(Item *from, Item *to)
(to->maybe_null || !from->maybe_null) &&
(to->result_type() != STRING_RESULT ||
from->result_type() != STRING_RESULT ||
- my_charset_same(from->collation.collation,
- to->collation.collation)));
+ (from->collation.collation == to->collation.collation)));
}
-bool Item_type_holder::join_types(THD *thd, Item *item)
+bool Item_type_holder::join_types(THD *thd, Item *item, TABLE *table)
{
uint32 new_length= real_length(item);
bool use_new_field= 0, use_expression_type= 0;
Item_result new_result_type= type_convertor[item_type][item->result_type()];
- bool item_is_a_field= item->type() == Item::FIELD_ITEM;
-
+ Field *field= get_holder_example_field(thd, item, table);
+ bool item_is_a_field= field;
/*
Check if both items point to fields: in this case we
can adjust column types of result table in the union smartly.
*/
if (field_example && item_is_a_field)
{
- Field *field= ((Item_field *)item)->field;
/* Can 'field_example' field store data of the column? */
if ((use_new_field=
(!field->field_cast_compatible(field_example->field_cast_type()) ||
@@ -3745,7 +3786,7 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
It is safe to assign a pointer to field here, because it will be used
before any table is closed.
*/
- field_example= ((Item_field*) item)->field;
+ field_example= field;
}
old_cs= collation.collation->name;
diff --git a/sql/item.h b/sql/item.h
index 6857b4acf82..8209c566025 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1579,14 +1579,14 @@ protected:
Item_result orig_type;
Field *field_example;
public:
- Item_type_holder(THD*, Item*);
+ Item_type_holder(THD*, Item*, TABLE *);
Item_result result_type () const { return item_type; }
enum Type type() const { return TYPE_HOLDER; }
double val_real();
longlong val_int();
String *val_str(String*);
- bool join_types(THD *thd, Item *);
+ bool join_types(THD *thd, Item *, TABLE *);
Field *example() { return field_example; }
static uint32 real_length(Item *item);
void cleanup()
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 96689bd0ac2..e63bafe4811 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -1530,7 +1530,11 @@ void in_string::set(uint pos,Item *item)
String *str=((String*) base)+pos;
String *res=item->val_str(str);
if (res && res != str)
+ {
+ if (res->uses_buffer_owned_by(str))
+ res->copy();
*str= *res;
+ }
if (!str->charset())
{
CHARSET_INFO *cs;
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 3d5a73dd2a0..7731ccee773 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -2377,20 +2377,17 @@ longlong Item_func_release_lock::val_int()
longlong Item_func_last_insert_id::val_int()
{
+ THD *thd= current_thd;
DBUG_ASSERT(fixed == 1);
if (arg_count)
{
- longlong value=args[0]->val_int();
- current_thd->insert_id(value);
- null_value=args[0]->null_value;
- return value;
- }
- else
- {
- Item *it= get_system_var(current_thd, OPT_SESSION, "last_insert_id", 14,
- "last_insert_id()");
- return it->val_int();
+ longlong value= args[0]->val_int();
+ thd->insert_id(value);
+ null_value= args[0]->null_value;
+ return value; // Avoid side effect of insert_id()
}
+ thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
+ return thd->insert_id();
}
/* This function is just used to test speed of different functions */
@@ -3142,9 +3139,7 @@ void Item_func_match::init_search(bool no_order)
if (join_key && !no_order)
flags|=FT_SORTED;
- ft_handler=table->file->ft_init_ext(flags, key,
- (byte*) ft_tmp->ptr(),
- ft_tmp->length());
+ ft_handler=table->file->ft_init_ext(flags, key, ft_tmp);
if (join_key)
table->file->ft_handler=ft_handler;
@@ -3186,12 +3181,12 @@ bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
}
/*
Check that all columns come from the same table.
- We've already checked that columns in MATCH are fields so
+ We've already checked that columns in MATCH are fields so
PARAM_TABLE_BIT can only appear from AGAINST argument.
*/
if ((used_tables_cache & ~PARAM_TABLE_BIT) != item->used_tables())
key=NO_SUCH_KEY;
-
+
if (key == NO_SUCH_KEY && !(flags & FT_BOOL))
{
my_error(ER_WRONG_ARGUMENTS,MYF(0),"MATCH");
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 3ac75bfdd30..b5cb01494fa 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -53,7 +53,7 @@ void Item_subselect::init(st_select_lex *select_lex,
{
DBUG_ENTER("Item_subselect::init");
- DBUG_PRINT("subs", ("select_lex 0x%xl", (ulong) select_lex));
+ DBUG_PRINT("enter", ("select_lex: 0x%x", (ulong) select_lex));
unit= select_lex->master_unit();
if (unit->item)
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 6311b2d5f52..2cabcb6d49c 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -407,6 +407,9 @@ inline THD *_current_thd(void)
}
#define current_thd _current_thd()
+typedef my_bool (*qc_engine_callback)(THD *thd, char *table_key,
+ uint key_length,
+ ulonglong *engine_data);
#include "sql_string.h"
#include "sql_list.h"
#include "sql_map.h"
@@ -1329,7 +1332,7 @@ inline void setup_table_map(TABLE *table, TABLE_LIST *table_list, uint tablenr)
table->null_row= 0;
table->status= STATUS_NO_RECORD;
table->keys_in_use_for_query= table->s->keys_in_use;
- table->maybe_null= test(table->outer_join= table_list->outer_join);
+ table->maybe_null= table_list->outer_join;
table->tablenr= tablenr;
table->map= (table_map) 1 << tablenr;
table->force_index= table_list->force_index;
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 97c150cd42b..1167e5688ab 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -291,6 +291,7 @@ my_bool opt_console= 0, opt_bdb, opt_innodb, opt_isam, opt_ndbcluster;
#ifdef HAVE_NDBCLUSTER_DB
const char *opt_ndbcluster_connectstring= 0;
my_bool opt_ndb_shm, opt_ndb_optimized_node_selection;
+ulong opt_ndb_cache_check_time= 0;
#endif
my_bool opt_readonly, use_temp_pool, relay_log_purge;
my_bool opt_sync_bdb_logs, opt_sync_frm;
@@ -4174,7 +4175,7 @@ enum options_mysqld
OPT_INNODB, OPT_ISAM,
OPT_NDBCLUSTER, OPT_NDB_CONNECTSTRING, OPT_NDB_USE_EXACT_COUNT,
OPT_NDB_FORCE_SEND, OPT_NDB_AUTOINCREMENT_PREFETCH_SZ,
- OPT_NDB_SHM, OPT_NDB_OPTIMIZED_NODE_SELECTION,
+ OPT_NDB_SHM, OPT_NDB_OPTIMIZED_NODE_SELECTION, OPT_NDB_CACHE_CHECK_TIME,
OPT_SKIP_SAFEMALLOC,
OPT_TEMP_POOL, OPT_TX_ISOLATION, OPT_COMPLETION_TYPE,
OPT_SKIP_STACK_TRACE, OPT_SKIP_SYMLINKS,
@@ -4706,6 +4707,10 @@ Disable with --skip-ndbcluster (will save memory).",
(gptr*) &opt_ndb_optimized_node_selection,
(gptr*) &opt_ndb_optimized_node_selection,
0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
+ { "ndb_cache_check_time", OPT_NDB_CACHE_CHECK_TIME,
+ "A dedicated thread is created to update cached commit count value at the given interval.",
+ (gptr*) &opt_ndb_cache_check_time, (gptr*) &opt_ndb_cache_check_time, 0, GET_ULONG, REQUIRED_ARG,
+ 0, 0, LONG_TIMEOUT, 0, 1, 0},
#endif
{"new", 'n', "Use very new possible 'unsafe' functions.",
(gptr*) &global_system_variables.new_mode,
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index e5799bfd509..ceb9f97bbbc 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -3611,7 +3611,7 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
if (!value) // IS NULL or IS NOT NULL
{
- if (field->table->outer_join) // Can't use a key on this
+ if (field->table->maybe_null) // Can't use a key on this
DBUG_RETURN(0);
if (!maybe_null) // Not null field
DBUG_RETURN(type == Item_func::ISNULL_FUNC ? &null_element : 0);
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 142ef64a41f..04bb2c5e78f 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -413,6 +413,7 @@ sys_var_thd_bool
sys_ndb_use_exact_count("ndb_use_exact_count", &SV::ndb_use_exact_count);
sys_var_thd_bool
sys_ndb_use_transactions("ndb_use_transactions", &SV::ndb_use_transactions);
+sys_var_long_ptr sys_ndb_cache_check_time("ndb_cache_check_time", &ndb_cache_check_time);
#endif
/* Time/date/datetime formats */
@@ -688,6 +689,7 @@ sys_var *sys_variables[]=
&sys_ndb_force_send,
&sys_ndb_use_exact_count,
&sys_ndb_use_transactions,
+ &sys_ndb_cache_check_time,
#endif
&sys_unique_checks,
&sys_updatable_views_with_limit,
@@ -868,6 +870,7 @@ struct show_var_st init_vars[]= {
{sys_ndb_force_send.name, (char*) &sys_ndb_force_send, SHOW_SYS},
{sys_ndb_use_exact_count.name,(char*) &sys_ndb_use_exact_count, SHOW_SYS},
{sys_ndb_use_transactions.name,(char*) &sys_ndb_use_transactions, SHOW_SYS},
+ {sys_ndb_cache_check_time.name,(char*) &sys_ndb_cache_check_time, SHOW_SYS},
#endif
{sys_net_buffer_length.name,(char*) &sys_net_buffer_length, SHOW_SYS},
{sys_net_read_timeout.name, (char*) &sys_net_read_timeout, SHOW_SYS},
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 3f2969768c5..d52474998a8 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -424,10 +424,10 @@ sp_head::~sp_head()
void
sp_head::destroy()
{
- DBUG_ENTER("sp_head::destroy");
- DBUG_PRINT("info", ("name: %s", m_name.str));
sp_instr *i;
LEX *lex;
+ DBUG_ENTER("sp_head::destroy");
+ DBUG_PRINT("info", ("name: %s", m_name.str));
for (uint ip = 0 ; (i = get_instr(ip)) ; ip++)
delete i;
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 9827e6d3f0c..0a57c0f6bc9 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -497,58 +497,58 @@ void close_temporary(TABLE *table,bool delete_table)
void close_temporary_tables(THD *thd)
{
TABLE *table,*next;
- char *query, *end;
- uint query_buf_size;
- bool found_user_tables = 0;
+ char *query, *name_in_query, *end;
+ uint greatest_key_length= 0;
if (!thd->temporary_tables)
return;
+ /*
+ We write a DROP TEMPORARY TABLE for each temp table left, so that our
+ replication slave can clean them up. Not one multi-table DROP TABLE binlog
+ event: this would cause problems if slave uses --replicate-*-table.
+ */
LINT_INIT(end);
- query_buf_size= 50; // Enough for DROP ... TABLE IF EXISTS
+ /* We'll re-use always same buffer so make it big enough for longest name */
for (table=thd->temporary_tables ; table ; table=table->next)
- /*
- We are going to add 4 ` around the db/table names, so 1 does not look
- enough; indeed it is enough, because table->key_length is greater (by 8,
- because of server_id and thread_id) than db||table.
- */
- query_buf_size+= table->s->key_length+1;
+ greatest_key_length= max(greatest_key_length, table->s->key_length);
- if ((query = alloc_root(thd->mem_root, query_buf_size)))
+ if ((query = alloc_root(thd->mem_root, greatest_key_length+50)))
// Better add "if exists", in case a RESET MASTER has been done
- end=strmov(query, "DROP /*!40005 TEMPORARY */ TABLE IF EXISTS ");
+ name_in_query= strmov(query, "DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `");
for (table=thd->temporary_tables ; table ; table=next)
{
- if (query) // we might be out of memory, but this is not fatal
+ /*
+ In we are OOM for 'query' this is not fatal. We skip temporary tables
+ not created directly by the user.
+ */
+ if (query && mysql_bin_log.is_open() && (table->s->table_name[0] != '#'))
{
- // skip temporary tables not created directly by the user
- if (table->s->table_name[0] != '#')
- found_user_tables = 1;
- end = strxmov(end,"`",table->s->db,"`.`",
- table->s->table_name,"`,", NullS);
+ /*
+ Here we assume table_cache_key always starts
+ with \0 terminated db name
+ */
+ end = strxmov(name_in_query, table->s->db, "`.`",
+ table->s->table_name, "`", NullS);
+ Query_log_event qinfo(thd, query, (ulong)(end-query), 0, FALSE);
+ /*
+ Imagine the thread had created a temp table, then was doing a SELECT, and
+ the SELECT was killed. Then it's not clever to mark the statement above as
+ "killed", because it's not really a statement updating data, and there
+ are 99.99% chances it will succeed on slave. And, if thread is
+ killed now, it's not clever either.
+ If a real update (one updating a persistent table) was killed on the
+ master, then this real update will be logged with error_code=killed,
+ rightfully causing the slave to stop.
+ */
+ qinfo.error_code= 0;
+ mysql_bin_log.write(&qinfo);
}
next=table->next;
close_temporary(table);
}
- if (query && found_user_tables && mysql_bin_log.is_open())
- {
- /* The -1 is to remove last ',' */
- thd->clear_error();
- Query_log_event qinfo(thd, query, (ulong)(end-query)-1, 0, FALSE);
- /*
- Imagine the thread had created a temp table, then was doing a SELECT, and
- the SELECT was killed. Then it's not clever to mark the statement above as
- "killed", because it's not really a statement updating data, and there
- are 99.99% chances it will succeed on slave.
- If a real update (one updating a persistent table) was killed on the
- master, then this real update will be logged with error_code=killed,
- rightfully causing the slave to stop.
- */
- qinfo.error_code= 0;
- mysql_bin_log.write(&qinfo);
- }
thd->temporary_tables=0;
}
@@ -854,7 +854,7 @@ TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list)
table->tablenr=thd->current_tablenr++;
table->used_fields=0;
table->const_table=0;
- table->outer_join= table->null_row= table->maybe_null= table->force_index= 0;
+ table->null_row= table->maybe_null= table->force_index= 0;
table->status=STATUS_NO_RECORD;
table->keys_in_use_for_query= share->keys_in_use;
table->used_keys= share->keys_for_keyread;
@@ -1078,7 +1078,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
table->tablenr=thd->current_tablenr++;
table->used_fields=0;
table->const_table=0;
- table->outer_join= table->null_row= table->maybe_null= table->force_index= 0;
+ table->null_row= table->maybe_null= table->force_index= 0;
table->status=STATUS_NO_RECORD;
table->keys_in_use_for_query= table->s->keys_in_use;
table->insert_values= 0;
@@ -1150,7 +1150,6 @@ bool reopen_table(TABLE *table,bool locked)
tmp.tablenr= table->tablenr;
tmp.used_fields= table->used_fields;
tmp.const_table= table->const_table;
- tmp.outer_join= table->outer_join;
tmp.null_row= table->null_row;
tmp.maybe_null= table->maybe_null;
tmp.status= table->status;
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index d63877dc755..e38e417e6df 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -914,12 +914,12 @@ end:
int
Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
{
+ ulonglong engine_data;
Query_cache_query *query;
Query_cache_block *first_result_block, *result_block;
Query_cache_block_table *block_table, *block_table_end;
ulong tot_length;
Query_cache_query_flags flags;
- bool check_tables;
DBUG_ENTER("Query_cache::send_result_to_client");
if (query_cache_size == 0 || thd->variables.query_cache_type == 0)
@@ -1027,7 +1027,6 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
goto err_unlock;
}
- check_tables= query->tables_type() & HA_CACHE_TBL_ASKTRANSACT;
// Check access;
block_table= query_block->table(0);
block_table_end= block_table+query_block->n_tables;
@@ -1088,19 +1087,30 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
goto err_unlock; // Parse query
}
#endif /*!NO_EMBEDDED_ACCESS_CHECKS*/
- if (check_tables && !ha_caching_allowed(thd, table->db(),
- table->key_length(),
- table->type()))
+ engine_data= table->engine_data();
+ if (table->callback() &&
+ !(*table->callback())(thd, table->db(),
+ table->key_length(),
+ &engine_data))
{
DBUG_PRINT("qcache", ("Handler does not allow caching for %s.%s",
table_list.db, table_list.alias));
BLOCK_UNLOCK_RD(query_block);
- thd->lex->safe_to_cache_query= 0; // Don't try to cache this
+ if (engine_data != table->engine_data())
+ {
+ DBUG_PRINT("qcache",
+ ("Handler require invalidation queries of %s.%s %lld-%lld",
+ table_list.db, table_list.alias,
+ engine_data, table->engine_data()));
+ invalidate_table(table->db(), table->key_length());
+ }
+ else
+ thd->lex->safe_to_cache_query= 0; // Don't try to cache this
goto err_unlock; // Parse query
}
else
- DBUG_PRINT("qcache", ("handler allow caching (%d) %s,%s",
- check_tables, table_list.db, table_list.alias));
+ DBUG_PRINT("qcache", ("handler allow caching %s,%s",
+ table_list.db, table_list.alias));
}
move_to_query_list_end(query_block);
hits++;
@@ -2128,7 +2138,9 @@ my_bool Query_cache::register_all_tables(Query_cache_block *block,
if (!insert_table(tables_used->table->s->key_length,
tables_used->table->s->table_cache_key, block_table,
tables_used->db_length,
- tables_used->table->file->table_cache_type()))
+ tables_used->table->file->table_cache_type(),
+ tables_used->callback_func,
+ tables_used->engine_data))
break;
if (tables_used->table->s->db_type == DB_TYPE_MRG_MYISAM)
@@ -2144,9 +2156,13 @@ my_bool Query_cache::register_all_tables(Query_cache_block *block,
uint key_length= filename_2_table_key(key, table->table->filename,
&db_length);
(++block_table)->n= ++n;
+ /*
+ There are not callback function for for MyISAM, and engine data
+ */
if (!insert_table(key_length, key, block_table,
db_length,
- tables_used->table->file->table_cache_type()))
+ tables_used->table->file->table_cache_type(),
+ 0, 0))
goto err;
}
}
@@ -2173,7 +2189,9 @@ err:
my_bool
Query_cache::insert_table(uint key_len, char *key,
Query_cache_block_table *node,
- uint32 db_length, uint8 cache_type)
+ uint32 db_length, uint8 cache_type,
+ qc_engine_callback callback,
+ ulonglong engine_data)
{
DBUG_ENTER("Query_cache::insert_table");
DBUG_PRINT("qcache", ("insert table node 0x%lx, len %d",
@@ -2183,6 +2201,23 @@ Query_cache::insert_table(uint key_len, char *key,
hash_search(&tables, (byte*) key,
key_len));
+ if (table_block &&
+ table_block->table()->engine_data() != engine_data)
+ {
+ DBUG_PRINT("qcache",
+ ("Handler require invalidation queries of %s.%s %lld-%lld",
+ table_block->table()->db(),
+ table_block->table()->table(),
+ engine_data,
+ table_block->table()->engine_data()));
+ /*
+ as far as we delete all queries with this table, table block will be
+ deleted, too
+ */
+ invalidate_table(table_block);
+ table_block= 0;
+ }
+
if (table_block == 0)
{
DBUG_PRINT("qcache", ("new table block from 0x%lx (%u)",
@@ -2213,6 +2248,8 @@ Query_cache::insert_table(uint key_len, char *key,
header->table(db + db_length + 1);
header->key_length(key_len);
header->type(cache_type);
+ header->callback(callback);
+ header->engine_data(engine_data);
}
Query_cache_block_table *list_root = table_block->table(0);
@@ -2733,9 +2770,11 @@ my_bool Query_cache::ask_handler_allowance(THD *thd,
for (; tables_used; tables_used= tables_used->next_global)
{
TABLE *table= tables_used->table;
- if (!ha_caching_allowed(thd, table->s->table_cache_key,
- table->s->key_length,
- table->file->table_cache_type()))
+ handler *handler= table->file;
+ if (!handler->register_query_cache_table(thd, table->s->table_cache_key,
+ table->s->key_length,
+ &tables_used->callback_func,
+ &tables_used->engine_data))
{
DBUG_PRINT("qcache", ("Handler does not allow caching for %s.%s",
tables_used->db, tables_used->alias));
diff --git a/sql/sql_cache.h b/sql/sql_cache.h
index 93d89aeae4f..e7116c7718a 100644
--- a/sql/sql_cache.h
+++ b/sql/sql_cache.h
@@ -146,6 +146,10 @@ struct Query_cache_table
char *tbl;
uint32 key_len;
uint8 table_type;
+ /* unique for every engine reference */
+ qc_engine_callback callback_func;
+ /* data need by some engines */
+ ulonglong engine_data_buff;
inline char *db() { return (char *) data(); }
inline char *table() { return tbl; }
@@ -154,6 +158,10 @@ struct Query_cache_table
inline void key_length(uint32 len) { key_len= len; }
inline uint8 type() { return table_type; }
inline void type(uint8 t) { table_type= t; }
+ inline qc_engine_callback callback() { return callback_func; }
+ inline void callback(qc_engine_callback fn){ callback_func= fn; }
+ inline ulonglong engine_data() { return engine_data_buff; }
+ inline void engine_data(ulonglong data) { engine_data_buff= data; }
inline gptr data()
{
return (gptr)(((byte*)this)+
@@ -282,7 +290,9 @@ protected:
TABLE_COUNTER_TYPE tables);
my_bool insert_table(uint key_len, char *key,
Query_cache_block_table *node,
- uint32 db_length, uint8 cache_type);
+ uint32 db_length, uint8 cache_type,
+ qc_engine_callback callback,
+ ulonglong engine_data);
void unlink_table(Query_cache_block_table *node);
Query_cache_block *get_free_block (ulong len, my_bool not_less,
ulong min);
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 06e271333bf..0644ca5af68 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -115,9 +115,14 @@ void lex_free(void)
void lex_start(THD *thd, uchar *buf,uint length)
{
LEX *lex= thd->lex;
+ DBUG_ENTER("lex_start");
+
+ lex->thd= lex->unit.thd= thd;
+ lex->buf= lex->ptr= buf;
+ lex->end_of_query= buf+length;
+
lex->unit.init_query();
lex->unit.init_select();
- lex->thd= lex->unit.thd= thd;
lex->select_lex.init_query();
lex->value_list.empty();
lex->update_list.empty();
@@ -150,8 +155,6 @@ void lex_start(THD *thd, uchar *buf,uint length)
lex->empty_field_list_on_rset= 0;
lex->select_lex.select_number= 1;
lex->next_state=MY_LEX_START;
- lex->buf= lex->ptr= buf;
- lex->end_of_query=buf+length;
lex->yylineno = 1;
lex->in_comment=0;
lex->length=0;
@@ -173,14 +176,11 @@ void lex_start(THD *thd, uchar *buf,uint length)
if (lex->spfuns.records)
my_hash_reset(&lex->spfuns);
+ DBUG_VOID_RETURN;
}
void lex_end(LEX *lex)
{
- for (SELECT_LEX *sl= lex->all_selects_list;
- sl;
- sl= sl->next_select_in_list())
- sl->expr_list.delete_elements(); // If error when parsing sql-varargs
x_free(lex->yacc_yyss);
x_free(lex->yacc_yyvs);
}
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index bcc317dc1a3..5981a8b2d4d 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -4720,19 +4720,21 @@ bool
mysql_new_select(LEX *lex, bool move_down)
{
SELECT_LEX *select_lex;
+ DBUG_ENTER("mysql_new_select");
+
if (!(select_lex= new(lex->thd->mem_root) SELECT_LEX()))
- return 1;
+ DBUG_RETURN(1);
select_lex->select_number= ++lex->thd->select_number;
select_lex->init_query();
select_lex->init_select();
select_lex->parent_lex= lex;
if (move_down)
{
+ SELECT_LEX_UNIT *unit;
lex->subqueries= TRUE;
/* first select_lex of subselect or derived table */
- SELECT_LEX_UNIT *unit;
if (!(unit= new(lex->thd->mem_root) SELECT_LEX_UNIT()))
- return 1;
+ DBUG_RETURN(1);
unit->init_query();
unit->init_select();
@@ -4749,7 +4751,7 @@ mysql_new_select(LEX *lex, bool move_down)
if (lex->current_select->order_list.first && !lex->current_select->braces)
{
my_error(ER_WRONG_USAGE, MYF(0), "UNION", "ORDER BY");
- return 1;
+ DBUG_RETURN(1);
}
select_lex->include_neighbour(lex->current_select);
SELECT_LEX_UNIT *unit= select_lex->master_unit();
@@ -4761,7 +4763,7 @@ mysql_new_select(LEX *lex, bool move_down)
fake SELECT_LEX for UNION processing
*/
if (!(fake= unit->fake_select_lex= new(lex->thd->mem_root) SELECT_LEX()))
- return 1;
+ DBUG_RETURN(1);
fake->include_standalone(unit,
(SELECT_LEX_NODE**)&unit->fake_select_lex);
fake->select_number= INT_MAX;
@@ -4775,7 +4777,7 @@ mysql_new_select(LEX *lex, bool move_down)
select_lex->include_global((st_select_lex_node**)&lex->all_selects_list);
lex->current_select= select_lex;
select_lex->resolve_mode= SELECT_LEX::SELECT_MODE;
- return 0;
+ DBUG_RETURN(0);
}
/*
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 89b84f40eb6..68438f7a785 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -9181,7 +9181,7 @@ join_read_const_table(JOIN_TAB *tab, POSITION *pos)
tab->info="const row not found";
/* Mark for EXPLAIN that the row was not found */
pos->records_read=0.0;
- if (!table->outer_join || error > 0)
+ if (!table->maybe_null || error > 0)
DBUG_RETURN(error);
}
}
@@ -9200,7 +9200,7 @@ join_read_const_table(JOIN_TAB *tab, POSITION *pos)
tab->info="unique row not found";
/* Mark for EXPLAIN that the row was not found */
pos->records_read=0.0;
- if (!table->outer_join || error > 0)
+ if (!table->maybe_null || error > 0)
DBUG_RETURN(error);
}
if (table->key_read)
diff --git a/sql/sql_string.h b/sql/sql_string.h
index cb9db52c830..a5c7cf77630 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -210,6 +210,11 @@ public:
{
if (&s != this)
{
+ /*
+ It is forbidden to do assignments like
+ some_string = substring_of_that_string
+ */
+ DBUG_ASSERT(!s.uses_buffer_owned_by(this));
free();
Ptr=s.Ptr ; str_length=s.str_length ; Alloced_length=s.Alloced_length;
alloced=0;
@@ -343,4 +348,9 @@ public:
/* Swap two string objects. Efficient way to exchange data without memcpy. */
void swap(String &s);
+
+ inline bool uses_buffer_owned_by(const String *s) const
+ {
+ return (s->alloced && Ptr >= s->Ptr && Ptr < s->Ptr + s->str_length);
+ }
};
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 0a91eb4c0e1..29897c70023 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -153,6 +153,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
SELECT_LEX *sl, *first_select;
select_result *tmp_result;
bool is_union;
+ TABLE *empty_table= 0;
DBUG_ENTER("st_select_lex_unit::prepare");
describe= test(additional_options & SELECT_DESCRIBE);
@@ -249,13 +250,21 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
goto err;
if (sl == first_select)
{
+ /*
+ We need to create an empty table object. It is used
+ to create tmp_table fields in Item_type_holder.
+ The main reason of this is that we can't create
+ field object without table.
+ */
+ DBUG_ASSERT(!empty_table);
+ empty_table= (TABLE*) thd->calloc(sizeof(TABLE));
types.empty();
List_iterator_fast<Item> it(sl->item_list);
Item *item_tmp;
while ((item_tmp= it++))
{
/* Error's in 'new' will be detected after loop */
- types.push_back(new Item_type_holder(thd_arg, item_tmp));
+ types.push_back(new Item_type_holder(thd_arg, item_tmp, empty_table));
}
if (thd_arg->is_fatal_error)
@@ -274,7 +283,8 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
Item *type, *item_tmp;
while ((type= tp++, item_tmp= it++))
{
- if (((Item_type_holder*)type)->join_types(thd_arg, item_tmp))
+ if (((Item_type_holder*)type)->join_types(thd_arg, item_tmp,
+ empty_table))
DBUG_RETURN(TRUE);
}
}
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index a94fb31580c..1402a85229b 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -3895,10 +3895,11 @@ select_into:
select_from:
FROM join_table_list where_clause group_clause having_clause
opt_order_clause opt_limit_clause procedure_clause
- | FROM DUAL_SYM /* oracle compatibility: oracle always requires FROM
- clause, and DUAL is system table without fields.
- Is "SELECT 1 FROM DUAL" any better than
- "SELECT 1" ? Hmmm :) */
+ | FROM DUAL_SYM opt_limit_clause
+ /* oracle compatibility: oracle always requires FROM clause,
+ and DUAL is system table without fields.
+ Is "SELECT 1 FROM DUAL" any better than "SELECT 1" ?
+ Hmmm :) */
;
select_options:
diff --git a/sql/table.h b/sql/table.h
index 3b1f8244e1d..5ab1f900195 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -217,14 +217,18 @@ struct st_table {
uint derived_select_number;
int current_lock; /* Type of lock on table */
my_bool copy_blobs; /* copy_blobs when storing */
+
+ /*
+ 0 or JOIN_TYPE_{LEFT|RIGHT}. Currently this is only compared to 0.
+ If maybe_null !=0, this table is inner w.r.t. some outer join operation,
+ and null_row may be true.
+ */
+ uint maybe_null;
/*
- Used in outer joins: if true, all columns are considered to have NULL
- values, including columns declared as "not null".
+ If true, the current table row is considered to have all columns set to
+ NULL, including columns declared as "not null" (see maybe_null).
*/
my_bool null_row;
- /* 0 or JOIN_TYPE_{LEFT|RIGHT}, same as TABLE_LIST::outer_join */
- my_bool outer_join;
- my_bool maybe_null; /* true if (outer_join != 0) */
my_bool force_index;
my_bool distinct,const_table,no_rows;
my_bool key_read, no_keyread;
@@ -388,6 +392,10 @@ typedef struct st_table_list
uint effective_algorithm; /* which algorithm was really used */
uint privilege_backup; /* place for saving privileges */
GRANT_INFO grant;
+ /* data need by some engines in query cache*/
+ ulonglong engine_data;
+ /* call back function for asking handler about caching in query cache */
+ qc_engine_callback callback_func;
thr_lock_type lock_type;
uint outer_join; /* Which join type */
uint shared; /* Used in multi-upd */
diff --git a/zlib/Makefile.am b/zlib/Makefile.am
index 58d3811cd7c..e94d184a841 100644
--- a/zlib/Makefile.am
+++ b/zlib/Makefile.am
@@ -16,7 +16,7 @@
# Process this file with automake to create Makefile.in
-noinst_LTLIBRARIES=libz.la
+pkglib_LTLIBRARIES=libz.la
noinst_HEADERS= crc32.h deflate.h inffast.h inffixed.h inflate.h \
inftrees.h trees.h zconf.h zlib.h zutil.h