summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <lenz@mysql.com>2004-10-07 14:43:09 +0200
committerunknown <lenz@mysql.com>2004-10-07 14:43:09 +0200
commit81edee8100fb13835c648835b1e6ca0b51710522 (patch)
treeb0a2946923849f8d0eb0cf0a30cd8a6fdebdacbd
parent02ce88ca8ba354a215e8d8313be5d1be69f029af (diff)
parent57fedc40708ed3266d79347cd71e829297352409 (diff)
downloadmariadb-git-81edee8100fb13835c648835b1e6ca0b51710522.tar.gz
Merge mysql.com:/space/my/mysql-4.1
into mysql.com:/space/my/mysql-4.1-build
-rw-r--r--BitKeeper/etc/logging_ok2
-rwxr-xr-xBuild-tools/mysql-copyright115
-rwxr-xr-xBuild-tools/mysql-copyright-21
-rw-r--r--Makefile.am2
-rw-r--r--acinclude.m423
-rw-r--r--client/mysqladmin.c21
-rw-r--r--client/mysqlimport.c8
-rw-r--r--configure.in15
-rw-r--r--include/config-win.h8
-rw-r--r--include/hash.h1
-rw-r--r--include/my_global.h8
-rw-r--r--include/myisam.h1
-rw-r--r--innobase/btr/btr0btr.c4
-rw-r--r--innobase/buf/buf0buf.c6
-rw-r--r--innobase/dict/dict0dict.c41
-rw-r--r--innobase/fsp/fsp0fsp.c6
-rw-r--r--innobase/include/dict0dict.h6
-rw-r--r--innobase/include/dict0mem.h16
-rw-r--r--innobase/include/row0mysql.h8
-rw-r--r--innobase/lock/lock0lock.c54
-rw-r--r--innobase/log/log0log.c5
-rw-r--r--innobase/log/log0recv.c6
-rw-r--r--innobase/os/os0file.c44
-rw-r--r--innobase/pars/pars0opt.c13
-rw-r--r--innobase/row/row0mysql.c39
-rw-r--r--innobase/row/row0row.c34
-rw-r--r--innobase/sync/sync0arr.c5
-rw-r--r--innobase/ut/ut0dbg.c5
-rw-r--r--ltmain.sh3
-rw-r--r--myisam/mi_check.c2
-rw-r--r--myisam/mi_close.c6
-rw-r--r--myisam/mi_create.c13
-rw-r--r--myisam/mi_locking.c60
-rw-r--r--myisam/myisampack.c6
-rw-r--r--mysql-test/include/ps_query.inc54
-rw-r--r--mysql-test/r/auto_increment.result52
-rw-r--r--mysql-test/r/bdb.result24
-rw-r--r--mysql-test/r/ctype_latin1_de.result14
-rw-r--r--mysql-test/r/ctype_utf8.result24
-rw-r--r--mysql-test/r/delete.result11
-rw-r--r--mysql-test/r/flush_table.result49
-rw-r--r--mysql-test/r/func_if.result3
-rw-r--r--mysql-test/r/func_str.result6
-rw-r--r--mysql-test/r/handler.result240
-rw-r--r--mysql-test/r/lock_multi.result12
-rw-r--r--mysql-test/r/multi_update.result4
-rw-r--r--mysql-test/r/ndb_subquery.result42
-rw-r--r--mysql-test/r/ps_2myisam.result82
-rw-r--r--mysql-test/r/ps_3innodb.result82
-rw-r--r--mysql-test/r/ps_4heap.result82
-rw-r--r--mysql-test/r/ps_5merge.result164
-rw-r--r--mysql-test/r/ps_6bdb.result82
-rw-r--r--mysql-test/r/ps_7ndb.result244
-rw-r--r--mysql-test/r/rename.result2
-rw-r--r--mysql-test/r/select.result1
-rw-r--r--mysql-test/r/show_check.result3
-rw-r--r--mysql-test/r/type_timestamp.result29
-rw-r--r--mysql-test/r/update.result37
-rw-r--r--mysql-test/t/auto_increment.test38
-rw-r--r--mysql-test/t/bdb.test20
-rw-r--r--mysql-test/t/ctype_latin1_de.test17
-rw-r--r--mysql-test/t/ctype_utf8.test20
-rw-r--r--mysql-test/t/delete.test10
-rw-r--r--mysql-test/t/derived.test2
-rw-r--r--mysql-test/t/flush_table.test30
-rw-r--r--mysql-test/t/func_if.test4
-rw-r--r--mysql-test/t/func_str.test7
-rw-r--r--mysql-test/t/handler.test208
-rw-r--r--mysql-test/t/lock_multi.test24
-rw-r--r--mysql-test/t/multi_update.test13
-rw-r--r--mysql-test/t/ndb_subquery.test38
-rw-r--r--mysql-test/t/ps_7ndb.test6
-rw-r--r--mysql-test/t/range.test3
-rw-r--r--mysql-test/t/rename.test2
-rw-r--r--mysql-test/t/select.test2
-rw-r--r--mysql-test/t/show_check.test4
-rw-r--r--mysql-test/t/type_timestamp.test27
-rw-r--r--mysql-test/t/update.test33
-rw-r--r--mysys/errors.c2
-rw-r--r--mysys/my_fstream.c14
-rw-r--r--mysys/my_pread.c9
-rw-r--r--mysys/my_write.c5
-rw-r--r--mysys/mysys_priv.h7
-rw-r--r--ndb/src/kernel/blocks/dbtc/DbtcMain.cpp24
-rwxr-xr-xndb/test/run-test/atrt-mysql-test-run2
-rw-r--r--scripts/mysqlhotcopy.sh2
-rw-r--r--sql/examples/ha_archive.cc520
-rw-r--r--sql/examples/ha_archive.h13
-rw-r--r--sql/field.cc18
-rw-r--r--sql/field_conv.cc25
-rw-r--r--sql/ha_innodb.cc68
-rw-r--r--sql/ha_myisam.cc2
-rw-r--r--sql/ha_ndbcluster.cc44
-rw-r--r--sql/handler.cc2
-rw-r--r--sql/item_cmpfunc.cc9
-rw-r--r--sql/item_cmpfunc.h1
-rw-r--r--sql/item_func.cc2
-rw-r--r--sql/item_strfunc.cc6
-rw-r--r--sql/mysql_priv.h12
-rw-r--r--sql/mysqld.cc23
-rw-r--r--sql/protocol.cc4
-rw-r--r--sql/records.cc30
-rw-r--r--sql/repl_failsafe.cc2
-rw-r--r--sql/repl_failsafe.h19
-rw-r--r--sql/slave.h16
-rw-r--r--sql/sql_acl.cc7
-rw-r--r--sql/sql_base.cc50
-rw-r--r--sql/sql_cache.cc75
-rw-r--r--sql/sql_class.cc9
-rw-r--r--sql/sql_class.h1
-rw-r--r--sql/sql_delete.cc2
-rw-r--r--sql/sql_handler.cc641
-rw-r--r--sql/sql_lex.h2
-rw-r--r--sql/sql_repl.cc2
-rw-r--r--sql/sql_repl.h16
-rw-r--r--sql/sql_select.cc2
-rw-r--r--sql/sql_show.cc16
-rw-r--r--sql/sql_table.cc75
-rw-r--r--sql/sql_union.cc5
-rw-r--r--sql/sql_update.cc248
-rw-r--r--sql/sql_yacc.yy9
-rw-r--r--sql/stacktrace.c2
-rw-r--r--sql/table.h8
123 files changed, 3303 insertions, 1186 deletions
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok
index e3aefbf3efc..ac45466be22 100644
--- a/BitKeeper/etc/logging_ok
+++ b/BitKeeper/etc/logging_ok
@@ -52,6 +52,7 @@ gweir@build.mysql.com
gweir@work.mysql.com
harrison@mysql.com
harry@corona.lordblink.com
+hartmut@mysql.com
heikki@donna.mysql.fi
heikki@hundin.mysql.fi
heikki@rescue.
@@ -96,6 +97,7 @@ lenz@mysql.com
magnus@neptunus.(none)
magnus@shellback.(none)
marko@hundin.mysql.fi
+matt@mysql.com
miguel@hegel.(none)
miguel@hegel.br
miguel@hegel.local
diff --git a/Build-tools/mysql-copyright b/Build-tools/mysql-copyright
index 0c091890e72..dbb18e4e866 100755
--- a/Build-tools/mysql-copyright
+++ b/Build-tools/mysql-copyright
@@ -1,9 +1,9 @@
-#!/usr/bin/perl -i
+#!/usr/bin/perl -wi
# Untar a MySQL distribution, change the copyright texts,
# pack it up again to a given directory
-$VER="1.3";
+$VER="1.4";
use Cwd;
use File::Basename;
@@ -104,7 +104,7 @@ sub main
unlink("$destdir/COPYING", "$destdir/EXCEPTIONS-CLIENT");
copy("$WD/Docs/MySQLEULA.txt", "$destdir");
- # remove readline, bdb subdirs and update 'configure'
+ # remove subdirectories 'bdb', 'cmd-line-utils/readline'
my @extra_fat= ('bdb', 'cmd-line-utils/readline');
foreach my $fat (@extra_fat)
@@ -118,7 +118,10 @@ sub main
# fix LICENSE tag in include/mysql_version.h
&fix_mysql_version();
-
+
+ # apply "autotools" - must be last to ensure proper timestamps
+ &run_autotools();
+
# rename the directory with new distribution name
chdir("$WD/$dir");
print "renaming $destdir $newdistname\n" if $opt_verbose;
@@ -142,7 +145,7 @@ sub main
}
}
exit(0);
-}
+}
####
#### This function will s/GPL/Commercial/ in include/mysql_version.h for the
@@ -150,6 +153,7 @@ sub main
####
sub fix_mysql_version
{
+ my $cwd= getcwd();
chdir("$destdir");
my $header_file= (-f 'include/mysql_version.h.in')? 'include/mysql_version.h.in' : 'include/mysql_version.h';
@@ -170,44 +174,73 @@ sub fix_mysql_version
#### This function will remove unwanted parts of a src tree for the mysqlcom
#### distributions.
####
+
sub trim_the_fat
{
- my $the_fat= shift;
- my $cwd= getcwd();
-
- system("rm -rf $destdir/${the_fat}");
- if (!$win_flag)
- {
- chdir("$destdir");
- unlink ("configure") or die "Can't delete $destdir/configure: $!\n";
- open(CONFIGURE,"<configure.in") or die "Unable to open configure.in for read: $!\n";
- undef $/;
- my $configure= <CONFIGURE>;
- close(CONFIGURE);
-
- #
- # If $the_fat Makefile line closes the parenthesis, then
- # replace that line with just the closing parenthesis.
- #
- if ($configure=~ m|${the_fat}/Makefile\)\n?|)
- {
- $configure=~ s|${the_fat}/Makefile(\)\n?)|$1|;
- }
- #
- # Else just delete the line
- #
- else
- {
- $configure=~ s|${the_fat}/Makefile dnl\n?||;
- }
-
- open(CONFIGURE,">configure.in") or die "Unable to open configure.in for write: $!\n";
- print CONFIGURE $configure;
- close(CONFIGURE);
- `aclocal && autoheader && aclocal && automake && autoconf`;
- die "'./configure' was not produced!" unless (-f "configure");
- chdir("$cwd");
- }
+ my $the_fat= shift;
+ my $cwd= getcwd();
+
+ chdir("$destdir");
+ if ( -d "${the_fat}" )
+ {
+ system("rm -rf ${the_fat}");
+ if (!$win_flag)
+ {
+ open(CONFIG_IN,"<configure.in") or die "Unable to open configure.in for read: $!\n";
+ undef $/;
+ my $config_in= <CONFIG_IN>;
+ close(CONFIG_IN);
+
+ #
+ # If $the_fat Makefile line closes the parenthesis, then
+ # replace that line with just the closing parenthesis.
+ #
+ if ($config_in=~ m|${the_fat}/Makefile\)\n?|)
+ {
+ $config_in=~ s|${the_fat}/Makefile(\)\n?)|$1|;
+ }
+ #
+ # Else just delete the line
+ #
+ else
+ {
+ $config_in=~ s|${the_fat}/Makefile dnl\n?||;
+ }
+
+ open(CONFIG_IN,">configure.in") or die "Unable to open configure.in for write: $!\n";
+ print CONFIG_IN $config_in;
+ close(CONFIG_IN);
+ }
+ }
+ chdir("$cwd");
+}
+
+
+####
+#### This function will run the autotools on the reduced source tree.
+####
+
+sub run_autotools
+{
+ my $cwd= getcwd();
+
+ if (!$win_flag)
+ {
+ chdir("$destdir");
+ unlink ("configure") or die "Can't delete $destdir/configure: $!\n";
+
+ # File "configure.in" has already been modified by "trim_the_fat()"
+
+ `aclocal && autoheader && aclocal && automake && autoconf`;
+ die "'./configure' was not produced!" unless (-f "configure");
+
+ if (-d "autom4te.cache") {
+ print "Trying to delete autom4te.cache dir\n" if $opt_verbose;
+ system("rm -rf autom4te.cache") or print "Unable to delete autom4te.cache dir: $!\n";
+ }
+
+ chdir("$cwd");
+ }
}
diff --git a/Build-tools/mysql-copyright-2 b/Build-tools/mysql-copyright-2
index a1a870526da..2ea2e8ef441 100755
--- a/Build-tools/mysql-copyright-2
+++ b/Build-tools/mysql-copyright-2
@@ -90,6 +90,7 @@ sub add_copyright
$ARGV =~ /\.cc$/ ||
$ARGV =~ /\.h$/ ||
$ARGV =~ /\.cpp$/ ||
+ $ARGV =~ /\.txt$/ ||
$ARGV =~ /\.yy$/)
{
$start_copyright="/* ";
diff --git a/Makefile.am b/Makefile.am
index 7c2ed820a23..0dbb5032e15 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -30,7 +30,7 @@ SUBDIRS = . include @docs_dirs@ @zlib_dir@ \
DIST_SUBDIRS = . include @docs_dirs@ zlib \
@readline_topdir@ sql-common \
@thread_dirs@ pstack @sql_client_dirs@ \
- @sql_server_dirs@ scripts man tests SSL\
+ @sql_server_dirs@ scripts @man_dirs@ tests SSL\
BUILD netware os2 @libmysqld_dirs@ \
@bench_dirs@ support-files @fs_dirs@ @tools_dirs@
diff --git a/acinclude.m4 b/acinclude.m4
index c7d7ba0e9c9..7f25b447f10 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -976,7 +976,7 @@ AC_DEFUN([MYSQL_FIND_OPENSSL], [
AC_DEFUN([MYSQL_CHECK_OPENSSL], [
AC_MSG_CHECKING(for OpenSSL)
AC_ARG_WITH([openssl],
- [ --with-openssl Include the OpenSSL support],
+ [ --with-openssl[=DIR] Include the OpenSSL support],
[openssl="$withval"],
[openssl=no])
@@ -994,8 +994,19 @@ AC_MSG_CHECKING(for OpenSSL)
[openssl_libs="$withval"],
[openssl_libs=""])
- if test "$openssl" = "yes"
+ if test "$openssl" != "no"
then
+ if test "$openssl" != "yes"
+ then
+ if test -z "$openssl_includes"
+ then
+ openssl_includes="$openssl/include"
+ fi
+ if test -z "$openssl_libs"
+ then
+ openssl_libs="$openssl/lib"
+ fi
+ fi
MYSQL_FIND_OPENSSL([$openssl_includes], [$openssl_libs])
#force VIO use
vio_dir="vio"
@@ -1031,6 +1042,14 @@ AC_MSG_CHECKING(for OpenSSL)
NON_THREADED_CLIENT_LIBS="$NON_THREADED_CLIENT_LIBS $openssl_libs"
else
AC_MSG_RESULT(no)
+ if test ! -z "$openssl_includes"
+ then
+ AC_MSG_ERROR(Can't have --with-openssl-includes without --with-openssl);
+ fi
+ if test ! -z "$openssl_libs"
+ then
+ AC_MSG_ERROR(Can't have --with-openssl-libs without --with-openssl);
+ fi
fi
AC_SUBST(openssl_libs)
AC_SUBST(openssl_includes)
diff --git a/client/mysqladmin.c b/client/mysqladmin.c
index df3e8dfed62..e21db53b470 100644
--- a/client/mysqladmin.c
+++ b/client/mysqladmin.c
@@ -268,7 +268,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
int main(int argc,char *argv[])
{
- int error, ho_error;
+ int error= 0, ho_error;
MYSQL mysql;
char **commands, **save_argv;
@@ -313,10 +313,25 @@ int main(int argc,char *argv[])
mysql_options(&mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
#endif
if (sql_connect(&mysql, option_wait))
- error = 1;
+ {
+ unsigned int err= mysql_errno(&mysql);
+ if (err >= CR_MIN_ERROR && err <= CR_MAX_ERROR)
+ error= 1;
+ else
+ {
+ /* Return 0 if all commands are PING */
+ for (; argc > 0; argv++, argc--)
+ {
+ if (find_type(argv[0], &command_typelib, 2) != ADMIN_PING)
+ {
+ error= 1;
+ break;
+ }
+ }
+ }
+ }
else
{
- error = 0;
while (!interrupted && (!opt_count_iterations || nr_iterations))
{
new_line = 0;
diff --git a/client/mysqlimport.c b/client/mysqlimport.c
index c68d2d9f724..aaf04b1bc3e 100644
--- a/client/mysqlimport.c
+++ b/client/mysqlimport.c
@@ -267,10 +267,8 @@ static int write_to_table(char *filename, MYSQL *sock)
DBUG_ENTER("write_to_table");
DBUG_PRINT("enter",("filename: %s",filename));
- local_file= sock->unix_socket == 0 || opt_local_file;
-
fn_format(tablename, filename, "", "", 1 | 2); /* removes path & ext. */
- if (local_file)
+ if (! opt_local_file)
strmov(hard_path,filename);
else
my_load_path(hard_path, filename, NULL); /* filename includes the path */
@@ -289,7 +287,7 @@ static int write_to_table(char *filename, MYSQL *sock)
to_unix_path(hard_path);
if (verbose)
{
- if (local_file)
+ if (opt_local_file)
fprintf(stdout, "Loading data from LOCAL file: %s into %s\n",
hard_path, tablename);
else
@@ -298,7 +296,7 @@ static int write_to_table(char *filename, MYSQL *sock)
}
sprintf(sql_statement, "LOAD DATA %s %s INFILE '%s'",
opt_low_priority ? "LOW_PRIORITY" : "",
- local_file ? "LOCAL" : "", hard_path);
+ opt_local_file ? "LOCAL" : "", hard_path);
end= strend(sql_statement);
if (replace)
end= strmov(end, " REPLACE");
diff --git a/configure.in b/configure.in
index 2df5155ecbb..d81a50b9367 100644
--- a/configure.in
+++ b/configure.in
@@ -2282,6 +2282,21 @@ else
fi
AC_SUBST(docs_dirs)
+# Shall we build the man pages?
+AC_ARG_WITH(man,
+ [ --without-man Skip building of the man pages.],
+ [with_man=$withval],
+ [with_man=yes]
+)
+
+if test "$with_man" = "yes"
+then
+ man_dirs="man"
+else
+ man_dirs=""
+fi
+AC_SUBST(man_dirs)
+
# Shall we build the bench code?
AC_ARG_WITH(bench,
[ --without-bench Skip building of the benchmark suite.],
diff --git a/include/config-win.h b/include/config-win.h
index 0ba8dd2cf43..d28bb25cd09 100644
--- a/include/config-win.h
+++ b/include/config-win.h
@@ -229,7 +229,13 @@ inline double ulonglong2double(ulonglong value)
((uint32) (uchar) (A)[0])))
#define sint4korr(A) (*((long *) (A)))
#define uint2korr(A) (*((uint16 *) (A)))
-#define uint3korr(A) (long) (*((unsigned long *) (A)) & 0xFFFFFF)
+/*
+ ATTENTION !
+
+ Please, note, uint3korr reads 4 bytes (not 3) !
+ It means, that you have to provide enough allocated space !
+*/
+#define uint3korr(A) (long) (*((unsigned int *) (A)) & 0xFFFFFF)
#define uint4korr(A) (*((unsigned long *) (A)))
#define uint5korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) +\
(((uint32) ((uchar) (A)[1])) << 8) +\
diff --git a/include/hash.h b/include/hash.h
index 6e6db27cd40..cd7210a290c 100644
--- a/include/hash.h
+++ b/include/hash.h
@@ -57,6 +57,7 @@ my_bool hash_update(HASH *hash,byte *record,byte *old_key,uint old_key_length);
void hash_replace(HASH *hash, uint idx, byte *new_row);
my_bool hash_check(HASH *hash); /* Only in debug library */
+#define hash_clear(H) bzero((char*) (H),sizeof(*(H)))
#define hash_inited(H) ((H)->array.buffer != 0)
#ifdef __cplusplus
diff --git a/include/my_global.h b/include/my_global.h
index 89a5363dc4b..8e2e8e0eb6a 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -919,7 +919,13 @@ typedef char bool; /* Ordinary boolean values 0 1 */
(((uint32) ((uchar) (A)[1])) << 8) +\
(((uint32) ((uchar) (A)[2])) << 16))
#else
-#define uint3korr(A) (long) (*((unsigned long *) (A)) & 0xFFFFFF)
+/*
+ ATTENTION !
+
+ Please, note, uint3korr reads 4 bytes (not 3) !
+ It means, that you have to provide enough allocated space !
+*/
+#define uint3korr(A) (long) (*((unsigned int *) (A)) & 0xFFFFFF)
#endif
#define uint4korr(A) (*((unsigned long *) (A)))
#define uint5korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) +\
diff --git a/include/myisam.h b/include/myisam.h
index 02c56115dfd..6d097770646 100644
--- a/include/myisam.h
+++ b/include/myisam.h
@@ -98,6 +98,7 @@ typedef struct st_mi_create_info
ha_rows reloc_rows;
ulonglong auto_increment;
ulonglong data_file_length;
+ ulonglong key_file_length;
uint raid_type,raid_chunks;
ulong raid_chunksize;
uint old_options;
diff --git a/innobase/btr/btr0btr.c b/innobase/btr/btr0btr.c
index ff389ede06e..ae967e0525e 100644
--- a/innobase/btr/btr0btr.c
+++ b/innobase/btr/btr0btr.c
@@ -610,8 +610,8 @@ btr_page_get_father_for_rec(
fputs(
"InnoDB: You should dump + drop + reimport the table to fix the\n"
"InnoDB: corruption. If the crash happens at the database startup, see\n"
-"InnoDB: section 6.1 of http://www.innodb.com/ibman.php about forcing\n"
-"InnoDB: recovery. Then dump + drop + reimport.\n", stderr);
+"InnoDB: http://dev.mysql.com/doc/mysql/en/Forcing_recovery.html about\n"
+"InnoDB: forcing recovery. Then dump + drop + reimport.\n", stderr);
}
ut_a(btr_node_ptr_get_child_page_no(node_ptr) ==
diff --git a/innobase/buf/buf0buf.c b/innobase/buf/buf0buf.c
index e039ff4f81f..adb69f3c3a7 100644
--- a/innobase/buf/buf0buf.c
+++ b/innobase/buf/buf0buf.c
@@ -1835,9 +1835,9 @@ buf_page_io_complete(
"InnoDB: by dumping, dropping, and reimporting\n"
"InnoDB: the corrupt table. You can use CHECK\n"
"InnoDB: TABLE to scan your table for corruption.\n"
- "InnoDB: Look also at section 6.1 of\n"
- "InnoDB: http://www.innodb.com/ibman.php about\n"
- "InnoDB: forcing recovery.\n", stderr);
+ "InnoDB: See also "
+ "http://dev.mysql.com/doc/mysql/en/Forcing_recovery.html\n"
+ "InnoDB: about forcing recovery.\n", stderr);
if (srv_force_recovery < SRV_FORCE_IGNORE_CORRUPT) {
fputs(
diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c
index b5dd06b1bf1..aa7e90700f8 100644
--- a/innobase/dict/dict0dict.c
+++ b/innobase/dict/dict0dict.c
@@ -527,8 +527,10 @@ dict_index_contains_col_or_prefix(
}
/************************************************************************
-Looks for a matching field in an index. The column and the prefix len have
-to be the same. */
+Looks for a matching field in an index. The column has to be the same. The
+column in index must be complete, or must contain a prefix longer than the
+column in index2. That is, we must be able to construct the prefix in index2
+from the prefix in index. */
ulint
dict_index_get_nth_field_pos(
@@ -556,7 +558,9 @@ dict_index_get_nth_field_pos(
field = dict_index_get_nth_field(index, pos);
if (field->col == field2->col
- && field->prefix_len == field2->prefix_len) {
+ && (field->prefix_len == 0
+ || (field->prefix_len >= field2->prefix_len
+ && field2->prefix_len != 0))) {
return(pos);
}
@@ -2114,7 +2118,8 @@ dict_foreign_error_report(
fputs("\nThe index in the foreign key in table is ", file);
ut_print_name(file, NULL, fk->foreign_index->name);
fputs(
-"See http://www.innodb.com/ibman.php for correct foreign key definition.\n",
+"\nSee http://dev.mysql.com/doc/mysql/en/InnoDB_foreign_key_constraints.html\n"
+"for correct foreign key definition.\n",
file);
}
mutex_exit(&dict_foreign_err_mutex);
@@ -2589,7 +2594,9 @@ dict_strip_comments(
char* str;
const char* sptr;
char* ptr;
-
+ /* unclosed quote character (0 if none) */
+ char quote = 0;
+
str = mem_alloc(strlen(sql_string) + 1);
sptr = sql_string;
@@ -2604,8 +2611,18 @@ scan_more:
return(str);
}
-
- if (*sptr == '#'
+
+ if (*sptr == quote) {
+ /* Closing quote character: do not look for
+ starting quote or comments. */
+ quote = 0;
+ } else if (quote) {
+ /* Within quotes: do not look for
+ starting quotes or comments. */
+ } else if (*sptr == '"' || *sptr == '`') {
+ /* Starting quote: remember the quote character. */
+ quote = *sptr;
+ } else if (*sptr == '#'
|| (0 == memcmp("-- ", sptr, 3))) {
for (;;) {
/* In Unix a newline is 0x0A while in Windows
@@ -2620,9 +2637,7 @@ scan_more:
sptr++;
}
- }
-
- if (*sptr == '/' && *(sptr + 1) == '*') {
+ } else if (!quote && *sptr == '/' && *(sptr + 1) == '*') {
for (;;) {
if (*sptr == '*' && *(sptr + 1) == '/') {
@@ -2950,7 +2965,8 @@ col_loop1:
ut_print_name(ef, NULL, name);
fprintf(ef, " where the columns appear\n"
"as the first columns. Constraint:\n%s\n"
-"See http://www.innodb.com/ibman.php for correct foreign key definition.\n",
+"See http://dev.mysql.com/doc/mysql/en/InnoDB_foreign_key_constraints.html\n"
+"for correct foreign key definition.\n",
start_of_latest_foreign);
mutex_exit(&dict_foreign_err_mutex);
@@ -3215,7 +3231,8 @@ try_find_index:
"Cannot find an index in the referenced table where the\n"
"referenced columns appear as the first columns, or column types\n"
"in the table and the referenced table do not match for constraint.\n"
-"See http://www.innodb.com/ibman.php for correct foreign key definition.\n",
+"See http://dev.mysql.com/doc/mysql/en/InnoDB_foreign_key_constraints.html\n"
+"for correct foreign key definition.\n",
start_of_latest_foreign);
mutex_exit(&dict_foreign_err_mutex);
diff --git a/innobase/fsp/fsp0fsp.c b/innobase/fsp/fsp0fsp.c
index 34b6de76ff4..e1621cc2765 100644
--- a/innobase/fsp/fsp0fsp.c
+++ b/innobase/fsp/fsp0fsp.c
@@ -2972,9 +2972,9 @@ fseg_free_page_low(
"InnoDB: database!\n", (ulong) page);
crash:
fputs(
-"InnoDB: If the InnoDB recovery crashes here, see section 6.1\n"
-"InnoDB: of http://www.innodb.com/ibman.php about forcing recovery.\n",
- stderr);
+"InnoDB: Please refer to\n"
+"InnoDB: http://dev.mysql.com/doc/mysql/en/Forcing_recovery.html\n"
+"InnoDB: about forcing recovery.\n", stderr);
ut_error;
}
diff --git a/innobase/include/dict0dict.h b/innobase/include/dict0dict.h
index a1a1ebdfe08..4dbbd5b4886 100644
--- a/innobase/include/dict0dict.h
+++ b/innobase/include/dict0dict.h
@@ -604,8 +604,10 @@ dict_index_contains_col_or_prefix(
dict_index_t* index, /* in: index */
ulint n); /* in: column number */
/************************************************************************
-Looks for a matching field in an index. The column and the prefix len has
-to be the same. */
+Looks for a matching field in an index. The column has to be the same. The
+column in index must be complete, or must contain a prefix longer than the
+column in index2. That is, we must be able to construct the prefix in index2
+from the prefix in index. */
ulint
dict_index_get_nth_field_pos(
diff --git a/innobase/include/dict0mem.h b/innobase/include/dict0mem.h
index 3fc3e850987..944fad1a8c8 100644
--- a/innobase/include/dict0mem.h
+++ b/innobase/include/dict0mem.h
@@ -151,7 +151,12 @@ struct dict_col_struct{
in some of the functions below */
};
-#define DICT_MAX_COL_PREFIX_LEN 512
+/* DICT_MAX_COL_PREFIX_LEN is measured in bytes. Starting from 4.1.6, we
+set max col prefix len to < 3 * 256, so that one can create a column prefix
+index on 255 characters of a TEXT field also in the UTF-8 charset. In that
+charset, a character may take at most 3 bytes. */
+
+#define DICT_MAX_COL_PREFIX_LEN 768
/* Data structure for a field in an index */
struct dict_field_struct{
@@ -160,9 +165,12 @@ struct dict_field_struct{
ulint order; /* flags for ordering this field:
DICT_DESCEND, ... */
ulint prefix_len; /* 0 or the length of the column
- prefix in a MySQL index of type, e.g.,
- INDEX (textcol(25)); must be smaller
- than DICT_MAX_COL_PREFIX_LEN */
+ prefix in bytes in a MySQL index of
+ type, e.g., INDEX (textcol(25));
+ must be smaller than
+ DICT_MAX_COL_PREFIX_LEN; NOTE that
+ in the UTF-8 charset, MySQL sets this
+ to 3 * the prefix len in UTF-8 chars */
};
/* Data structure for an index tree */
diff --git a/innobase/include/row0mysql.h b/innobase/include/row0mysql.h
index 8f6264944ce..9437ed4b6ee 100644
--- a/innobase/include/row0mysql.h
+++ b/innobase/include/row0mysql.h
@@ -559,9 +559,11 @@ struct row_prebuilt_struct {
dtuple_t* clust_ref; /* prebuilt dtuple used in
sel/upd/del */
ulint select_lock_type;/* LOCK_NONE, LOCK_S, or LOCK_X */
- ulint stored_select_lock_type;/* inside LOCK TABLES, either
- LOCK_S or LOCK_X depending on the lock
- type */
+ ulint stored_select_lock_type;/* this field is used to
+ remember the original select_lock_type
+ that was decided in ha_innodb.cc,
+ ::store_lock(), ::external_lock(),
+ etc. */
ulint mysql_row_len; /* length in bytes of a row in the
MySQL format */
ulint n_rows_fetched; /* number of rows fetched after
diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c
index e6d478070b0..68073647248 100644
--- a/innobase/lock/lock0lock.c
+++ b/innobase/lock/lock0lock.c
@@ -373,7 +373,29 @@ lock_rec_get_nth_bit(
/*=================*/
/* out: TRUE if bit set */
lock_t* lock, /* in: record lock */
- ulint i); /* in: index of the bit */
+ ulint i) /* in: index of the bit */
+{
+ ulint byte_index;
+ ulint bit_index;
+ ulint b;
+
+ ut_ad(lock);
+ ut_ad(lock_get_type(lock) == LOCK_REC);
+
+ if (i >= lock->un_member.rec_lock.n_bits) {
+
+ return(FALSE);
+ }
+
+ byte_index = i / 8;
+ bit_index = i % 8;
+
+ b = (ulint)*((byte*)lock + sizeof(lock_t) + byte_index);
+
+ return(ut_bit_get_nth(b, bit_index));
+}
+
+/*************************************************************************/
#define lock_mutex_enter_kernel() mutex_enter(&kernel_mutex)
#define lock_mutex_exit_kernel() mutex_exit(&kernel_mutex)
@@ -883,36 +905,6 @@ lock_rec_get_n_bits(
return(lock->un_member.rec_lock.n_bits);
}
-/*************************************************************************
-Gets the nth bit of a record lock. */
-UNIV_INLINE
-ibool
-lock_rec_get_nth_bit(
-/*=================*/
- /* out: TRUE if bit set */
- lock_t* lock, /* in: record lock */
- ulint i) /* in: index of the bit */
-{
- ulint byte_index;
- ulint bit_index;
- ulint b;
-
- ut_ad(lock);
- ut_ad(lock_get_type(lock) == LOCK_REC);
-
- if (i >= lock->un_member.rec_lock.n_bits) {
-
- return(FALSE);
- }
-
- byte_index = i / 8;
- bit_index = i % 8;
-
- b = (ulint)*((byte*)lock + sizeof(lock_t) + byte_index);
-
- return(ut_bit_get_nth(b, bit_index));
-}
-
/**************************************************************************
Sets the nth bit of a record lock to TRUE. */
UNIV_INLINE
diff --git a/innobase/log/log0log.c b/innobase/log/log0log.c
index 923ab448e07..b6357fa2c76 100644
--- a/innobase/log/log0log.c
+++ b/innobase/log/log0log.c
@@ -689,10 +689,9 @@ failure:
"InnoDB: To get mysqld to start up, set innodb_thread_concurrency in my.cnf\n"
"InnoDB: to a lower value, for example, to 8. After an ERROR-FREE shutdown\n"
"InnoDB: of mysqld you can adjust the size of ib_logfiles, as explained in\n"
-"InnoDB: section 5 of http://www.innodb.com/ibman.php",
+"InnoDB: http://dev.mysql.com/doc/mysql/en/Adding_and_removing.html\n"
+"InnoDB: Cannot continue operation. Calling exit(1).\n",
(ulong)srv_thread_concurrency);
- fprintf(stderr,
-"InnoDB: Cannot continue operation. Calling exit(1).\n");
exit(1);
}
diff --git a/innobase/log/log0recv.c b/innobase/log/log0recv.c
index e5b0300239a..10f921bb1f0 100644
--- a/innobase/log/log0recv.c
+++ b/innobase/log/log0recv.c
@@ -538,8 +538,8 @@ recv_find_max_checkpoint(
"InnoDB: If this error appears when you are creating an InnoDB database,\n"
"InnoDB: the problem may be that during an earlier attempt you managed\n"
"InnoDB: to create the InnoDB data files, but log file creation failed.\n"
-"InnoDB: If that is the case, please refer to section 3.1 of\n"
-"InnoDB: http://www.innodb.com/ibman.php\n");
+"InnoDB: If that is the case, please refer to\n"
+"InnoDB: http://dev.mysql.com/doc/mysql/en/Error_creating_InnoDB.html\n");
return(DB_ERROR);
}
@@ -1884,7 +1884,7 @@ recv_report_corrupt_log(
"InnoDB: far enough in recovery! Please run CHECK TABLE\n"
"InnoDB: on your InnoDB tables to check that they are ok!\n"
"InnoDB: If mysqld crashes after this recovery, look at\n"
- "InnoDB: section 6.1 of http://www.innodb.com/ibman.php\n"
+ "InnoDB: http://dev.mysql.com/doc/mysql/en/Forcing_recovery.html\n"
"InnoDB: about forcing recovery.\n", stderr);
fflush(stderr);
diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c
index 392580eb570..1040283f85e 100644
--- a/innobase/os/os0file.c
+++ b/innobase/os/os0file.c
@@ -234,8 +234,9 @@ os_file_get_last_error(
"InnoDB: of the same name as a data file.\n");
} else {
fprintf(stderr,
- "InnoDB: See section 13.2 at http://www.innodb.com/ibman.php\n"
- "InnoDB: about operating system error numbers.\n");
+ "InnoDB: Some operating system error numbers are described at\n"
+ "InnoDB: "
+ "http://dev.mysql.com/doc/mysql/en/Operating_System_error_codes.html\n");
}
}
@@ -280,8 +281,9 @@ os_file_get_last_error(
}
fprintf(stderr,
- "InnoDB: See also section 13.2 at http://www.innodb.com/ibman.php\n"
- "InnoDB: about operating system error numbers.\n");
+ "InnoDB: Some operating system error numbers are described at\n"
+ "InnoDB: "
+ "http://dev.mysql.com/doc/mysql/en/Operating_System_error_codes.html\n");
}
}
@@ -2174,8 +2176,9 @@ retry:
fprintf(stderr,
" InnoDB: Error: File pointer positioning to file %s failed at\n"
"InnoDB: offset %lu %lu. Operating system error number %lu.\n"
-"InnoDB: Look from section 13.2 at http://www.innodb.com/ibman.php\n"
-"InnoDB: what the error number means.\n",
+"InnoDB: Some operating system error numbers are described at\n"
+"InnoDB: "
+"http://dev.mysql.com/doc/mysql/en/Operating_System_error_codes.html\n",
name, (ulong) offset_high, (ulong) offset,
(ulong) GetLastError());
@@ -2232,8 +2235,9 @@ retry:
}
fprintf(stderr,
-"InnoDB: See also section 13.2 at http://www.innodb.com/ibman.php\n"
-"InnoDB: about operating system error numbers.\n");
+"InnoDB: Some operating system error numbers are described at\n"
+"InnoDB: "
+"http://dev.mysql.com/doc/mysql/en/Operating_System_error_codes.html\n");
os_has_said_disk_full = TRUE;
}
@@ -2267,8 +2271,9 @@ retry:
}
fprintf(stderr,
-"InnoDB: See also section 13.2 at http://www.innodb.com/ibman.php\n"
-"InnoDB: about operating system error numbers.\n");
+"InnoDB: Some operating system error numbers are described at\n"
+"InnoDB: "
+"http://dev.mysql.com/doc/mysql/en/Operating_System_error_codes.html\n");
os_has_said_disk_full = TRUE;
}
@@ -3466,6 +3471,8 @@ restart:
/* NOTE! We only access constant fields in os_aio_array. Therefore
we do not have to acquire the protecting mutex yet */
+ srv_set_io_thread_op_info(global_segment,
+ "looking for i/o requests (a)");
ut_ad(os_aio_validate());
ut_ad(segment < array->n_segments);
@@ -3484,6 +3491,9 @@ restart:
os_mutex_enter(array->mutex);
+ srv_set_io_thread_op_info(global_segment,
+ "looking for i/o requests (b)");
+
/* Check if there is a slot for which the i/o has already been
done */
@@ -3596,6 +3606,8 @@ consecutive_loop:
}
}
+ srv_set_io_thread_op_info(global_segment, "consecutive i/o requests");
+
/* We have now collected n_consecutive i/o requests in the array;
allocate a single buffer which can hold all data, and perform the
i/o */
@@ -3741,6 +3753,8 @@ slot_io_done:
return(ret);
wait_for_io:
+ srv_set_io_thread_op_info(global_segment, "resetting wait event");
+
/* We wait here until there again can be i/os in the segment
of this thread */
@@ -3832,9 +3846,17 @@ os_aio_print(
ulint i;
for (i = 0; i < srv_n_file_io_threads; i++) {
- fprintf(file, "I/O thread %lu state: %s (%s)\n", (ulong) i,
+ fprintf(file, "I/O thread %lu state: %s (%s)", (ulong) i,
srv_io_thread_op_info[i],
srv_io_thread_function[i]);
+
+#ifndef __WIN__
+ if (os_aio_segment_wait_events[i]->is_set) {
+ fprintf(file, " ev set");
+ }
+#endif
+
+ fprintf(file, "\n");
}
fputs("Pending normal aio reads:", file);
diff --git a/innobase/pars/pars0opt.c b/innobase/pars/pars0opt.c
index 0d487f6e54a..88022e2efe1 100644
--- a/innobase/pars/pars0opt.c
+++ b/innobase/pars/pars0opt.c
@@ -1094,6 +1094,19 @@ opt_clust_access(
for (i = 0; i < n_fields; i++) {
pos = dict_index_get_nth_field_pos(index, clust_index, i);
+ ut_a(pos != ULINT_UNDEFINED);
+
+ /* We optimize here only queries to InnoDB's internal system
+ tables, and they should not contain column prefix indexes. */
+
+ if (dict_index_get_nth_field(index, pos)->prefix_len != 0
+ || dict_index_get_nth_field(clust_index, i)
+ ->prefix_len != 0) {
+ fprintf(stderr,
+"InnoDB: Error in pars0opt.c: table %s has prefix_len != 0\n",
+ index->table_name);
+ }
+
*(plan->clust_map + i) = pos;
ut_ad((pos != ULINT_UNDEFINED)
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index c796646fc37..88227d61f1d 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -339,8 +339,9 @@ handle_new_error:
"InnoDB: a case of widespread corruption, dump all InnoDB\n"
"InnoDB: tables and recreate the whole InnoDB tablespace.\n"
"InnoDB: If the mysqld server crashes after the startup or when\n"
- "InnoDB: you dump the tables, look at section 6.1 of\n"
- "InnoDB: http://www.innodb.com/ibman.html for help.\n", stderr);
+ "InnoDB: you dump the tables, look at\n"
+ "InnoDB: http://dev.mysql.com/doc/mysql/en/Forcing_recovery.html"
+ " for help.\n", stderr);
} else {
fprintf(stderr, "InnoDB: unknown error code %lu\n",
@@ -1587,8 +1588,9 @@ row_create_table_for_mysql(
"InnoDB: database and moving the .frm file to the current database.\n"
"InnoDB: Then MySQL thinks the table exists, and DROP TABLE will\n"
"InnoDB: succeed.\n"
- "InnoDB: You can look for further help from section 15.1 of\n"
- "InnoDB: http://www.innodb.com/ibman.php\n", stderr);
+ "InnoDB: You can look for further help from\n"
+ "InnoDB: http://dev.mysql.com/doc/mysql/en/"
+ "InnoDB_troubleshooting_datadict.html\n", stderr);
}
/* We may also get err == DB_ERROR if the .ibd file for the
@@ -1630,6 +1632,8 @@ row_create_index_for_mysql(
trx->op_info = "creating index";
+ trx_start_if_not_started(trx);
+
/* Check that the same column does not appear twice in the index.
Starting from 4.0.14, InnoDB should be able to cope with that, but
safer not to allow them. */
@@ -1656,9 +1660,16 @@ row_create_index_for_mysql(
goto error_handling;
}
}
- }
+
+ /* Check also that prefix_len < DICT_MAX_COL_PREFIX_LEN */
- trx_start_if_not_started(trx);
+ if (dict_index_get_nth_field(index, i)->prefix_len
+ >= DICT_MAX_COL_PREFIX_LEN) {
+ err = DB_TOO_BIG_RECORD;
+
+ goto error_handling;
+ }
+ }
if (row_mysql_is_recovered_tmp_table(index->table_name)) {
@@ -2360,6 +2371,7 @@ row_drop_table_for_mysql(
memcpy(sql, str1, (sizeof str1) - 1);
memcpy(sql + (sizeof str1) - 1, quoted_name, namelen);
memcpy(sql + (sizeof str1) - 1 + namelen, str2, sizeof str2);
+ mem_free(quoted_name);
/* Serialize data dictionary operations with dictionary mutex:
no deadlocks can occur then in these operations */
@@ -2400,8 +2412,9 @@ row_drop_table_for_mysql(
"InnoDB: data dictionary though MySQL is trying to drop it.\n"
"InnoDB: Have you copied the .frm file of the table to the\n"
"InnoDB: MySQL database directory from another database?\n"
- "InnoDB: You can look for further help from section 15.1 of\n"
- "InnoDB: http://www.innodb.com/ibman.php\n", stderr);
+ "InnoDB: You can look for further help from\n"
+ "InnoDB: http://dev.mysql.com/doc/mysql/en/"
+ "InnoDB_troubleshooting_datadict.html\n", stderr);
goto funct_exit;
}
@@ -2946,11 +2959,13 @@ row_rename_table_for_mysql(
ut_print_name(stderr, trx, old_name);
fputs(" to it.\n"
"InnoDB: Have you deleted the .frm file and not used DROP TABLE?\n"
- "InnoDB: You can look for further help from section 15.1 of\n"
- "InnoDB: http://www.innodb.com/ibman.php\n"
+ "InnoDB: You can look for further help from\n"
+ "InnoDB: http://dev.mysql.com/doc/mysql/en/"
+ "InnoDB_troubleshooting_datadict.html\n"
"InnoDB: If table ", stderr);
- ut_print_name(stderr, trx, new_name);
- fputs(" is a temporary table #sql..., then it can be that\n"
+ ut_print_name(stderr, trx, new_name);
+ fputs(
+ " is a temporary table #sql..., then it can be that\n"
"InnoDB: there are still queries running on the table, and it will be\n"
"InnoDB: dropped automatically when the queries end.\n"
"InnoDB: You can drop the orphaned table inside InnoDB by\n"
diff --git a/innobase/row/row0row.c b/innobase/row/row0row.c
index e7b39f0fe52..2de7ffc79c0 100644
--- a/innobase/row/row0row.c
+++ b/innobase/row/row0row.c
@@ -343,6 +343,7 @@ row_build_row_ref(
ulint ref_len;
ulint pos;
byte* buf;
+ ulint clust_col_prefix_len;
ulint i;
ut_ad(index && rec && heap);
@@ -375,6 +376,22 @@ row_build_row_ref(
field = rec_get_nth_field(rec, pos, &len);
dfield_set_data(dfield, field, len);
+
+ /* If the primary key contains a column prefix, then the
+ secondary index may contain a longer prefix of the same
+ column, or the full column, and we must adjust the length
+ accordingly. */
+
+ clust_col_prefix_len =
+ dict_index_get_nth_field(clust_index, i)->prefix_len;
+
+ if (clust_col_prefix_len > 0) {
+ if (len != UNIV_SQL_NULL
+ && len > clust_col_prefix_len) {
+
+ dfield_set_len(dfield, clust_col_prefix_len);
+ }
+ }
}
ut_ad(dtuple_check_typed(ref));
@@ -406,6 +423,7 @@ row_build_row_ref_in_tuple(
ulint len;
ulint ref_len;
ulint pos;
+ ulint clust_col_prefix_len;
ulint i;
ut_a(ref && index && rec);
@@ -443,6 +461,22 @@ row_build_row_ref_in_tuple(
field = rec_get_nth_field(rec, pos, &len);
dfield_set_data(dfield, field, len);
+
+ /* If the primary key contains a column prefix, then the
+ secondary index may contain a longer prefix of the same
+ column, or the full column, and we must adjust the length
+ accordingly. */
+
+ clust_col_prefix_len =
+ dict_index_get_nth_field(clust_index, i)->prefix_len;
+
+ if (clust_col_prefix_len > 0) {
+ if (len != UNIV_SQL_NULL
+ && len > clust_col_prefix_len) {
+
+ dfield_set_len(dfield, clust_col_prefix_len);
+ }
+ }
}
ut_ad(dtuple_check_typed(ref));
diff --git a/innobase/sync/sync0arr.c b/innobase/sync/sync0arr.c
index 7cd221df6a5..e5285cb7ebf 100644
--- a/innobase/sync/sync0arr.c
+++ b/innobase/sync/sync0arr.c
@@ -61,10 +61,7 @@ struct sync_cell_struct {
thread */
ibool waiting; /* TRUE if the thread has already
called sync_array_event_wait
- on this cell but not yet
- sync_array_free_cell (which
- actually resets wait_object and thus
- whole cell) */
+ on this cell */
ibool event_set; /* TRUE if the event is set */
os_event_t event; /* operating system event
semaphore handle */
diff --git a/innobase/ut/ut0dbg.c b/innobase/ut/ut0dbg.c
index 2a0cfe1f13a..0f6a27d35d9 100644
--- a/innobase/ut/ut0dbg.c
+++ b/innobase/ut/ut0dbg.c
@@ -31,8 +31,9 @@ const char* ut_dbg_msg_trap =
"InnoDB: Submit a detailed bug report to http://bugs.mysql.com.\n"
"InnoDB: If you get repeated assertion failures or crashes, even\n"
"InnoDB: immediately after the mysqld startup, there may be\n"
-"InnoDB: corruption in the InnoDB tablespace. See section 6.1 of\n"
-"InnoDB: http://www.innodb.com/ibman.php about forcing recovery.\n";
+"InnoDB: corruption in the InnoDB tablespace. Please refer to\n"
+"InnoDB: http://dev.mysql.com/doc/mysql/en/Forcing_recovery.html\n"
+"InnoDB: about forcing recovery.\n";
const char* ut_dbg_msg_stop =
"InnoDB: Thread %lu stopped in file %s line %lu\n";
diff --git a/ltmain.sh b/ltmain.sh
index b28d160431c..c2c73cad224 100644
--- a/ltmain.sh
+++ b/ltmain.sh
@@ -51,6 +51,9 @@ fi
# libtool 1.4.2 workaround
SED=${SED:-sed}
+# workaround against unset 'max_cmd_len': assume at least 4 kB
+max_cmd_len=${max_cmd_len:-4096}
+
# The name of this program.
progname=`$echo "$0" | ${SED} 's%^.*/%%'`
modename="$progname"
diff --git a/myisam/mi_check.c b/myisam/mi_check.c
index 1f6089d0a3c..4da388af1c7 100644
--- a/myisam/mi_check.c
+++ b/myisam/mi_check.c
@@ -3743,7 +3743,7 @@ int recreate_table(MI_CHECK *param, MI_INFO **org_info, char *filename)
create_info.raid_chunksize= share.base.raid_chunksize;
create_info.language = (param->language ? param->language :
share.state.header.language);
-
+ create_info.key_file_length= status_info.key_file_length;
/* We don't have to handle symlinks here because we are using
HA_DONT_TOUCH_DATA */
if (mi_create(filename,
diff --git a/myisam/mi_close.c b/myisam/mi_close.c
index deb0ccee8f3..62f5617de1a 100644
--- a/myisam/mi_close.c
+++ b/myisam/mi_close.c
@@ -70,6 +70,12 @@ int mi_close(register MI_INFO *info)
error=my_errno;
if (share->kfile >= 0)
{
+ /*
+ If we are crashed, we can safely flush the current state as it will
+ not change the crashed state.
+ We can NOT write the state in other cases as other threads
+ may be using the file at this point
+ */
if (share->mode != O_RDONLY && mi_is_crashed(info))
mi_state_info_write(share->kfile, &share->state, 1);
if (my_close(share->kfile,MYF(0)))
diff --git a/myisam/mi_create.c b/myisam/mi_create.c
index 683640630f6..7fc7cc4edf1 100644
--- a/myisam/mi_create.c
+++ b/myisam/mi_create.c
@@ -48,7 +48,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
ulong reclength, real_reclength,min_pack_length;
char filename[FN_REFLEN],linkname[FN_REFLEN], *linkname_ptr;
ulong pack_reclength;
- ulonglong tot_length,max_rows;
+ ulonglong tot_length,max_rows, tmp;
enum en_fieldtype type;
MYISAM_SHARE share;
MI_KEYDEF *keydef,tmp_keydef;
@@ -464,10 +464,15 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
share.state.auto_increment=ci->auto_increment;
share.options=options;
share.base.rec_reflength=pointer;
+ /* Get estimate for index file length (this may be wrong for FT keys) */
+ tmp= (tot_length + max_key_block_length * keys *
+ MI_INDEX_BLOCK_MARGIN) / MI_MIN_KEY_BLOCK_LENGTH;
+ /*
+ use maximum of key_file_length we calculated and key_file_length value we
+ got from MYI file header (see also myisampack.c:save_state)
+ */
share.base.key_reflength=
- mi_get_pointer_length((tot_length + max_key_block_length * keys *
- MI_INDEX_BLOCK_MARGIN) / MI_MIN_KEY_BLOCK_LENGTH,
- 3);
+ mi_get_pointer_length(max(ci->key_file_length,tmp),3);
share.base.keys= share.state.header.keys= keys;
share.state.header.uniques= uniques;
share.state.header.fulltext_keys= fulltext_keys;
diff --git a/myisam/mi_locking.c b/myisam/mi_locking.c
index b13ebfb4cad..66950f62321 100644
--- a/myisam/mi_locking.c
+++ b/myisam/mi_locking.c
@@ -19,7 +19,7 @@
reads info from a isam-table. Must be first request before doing any furter
calls to any isamfunktion. Is used to allow many process use the same
isamdatabase.
- */
+*/
#include "myisamdef.h"
@@ -32,12 +32,17 @@ int mi_lock_database(MI_INFO *info, int lock_type)
MYISAM_SHARE *share=info->s;
uint flag;
DBUG_ENTER("mi_lock_database");
- DBUG_PRINT("info",("lock_type: %d", lock_type));
+ DBUG_PRINT("enter",("lock_type: %d old lock %d r_locks: %u w_locks: %u "
+ "global_changed: %d open_count: %u name: '%s'",
+ lock_type, info->lock_type, share->r_locks,
+ share->w_locks,
+ share->global_changed, share->state.open_count,
+ share->index_file_name));
if (share->options & HA_OPTION_READ_ONLY_DATA ||
info->lock_type == lock_type)
DBUG_RETURN(0);
- if (lock_type == F_EXTRA_LCK)
+ if (lock_type == F_EXTRA_LCK) /* Used by TMP tables */
{
++share->w_locks;
++share->tot_locks;
@@ -51,7 +56,6 @@ int mi_lock_database(MI_INFO *info, int lock_type)
{
switch (lock_type) {
case F_UNLCK:
- DBUG_PRINT("info", ("old lock: %d", info->lock_type));
if (info->lock_type == F_RDLCK)
count= --share->r_locks;
else
@@ -81,7 +85,7 @@ int mi_lock_database(MI_INFO *info, int lock_type)
share->state.process= share->last_process=share->this_process;
share->state.unique= info->last_unique= info->this_unique;
share->state.update_count= info->last_loop= ++info->this_loop;
- if (mi_state_info_write(share->kfile, &share->state, 1))
+ if (mi_state_info_write(share->kfile, &share->state, 1))
error=my_errno;
share->changed=0;
if (myisam_flush)
@@ -119,11 +123,17 @@ int mi_lock_database(MI_INFO *info, int lock_type)
break;
case F_RDLCK:
if (info->lock_type == F_WRLCK)
- { /* Change RW to READONLY */
+ {
+ /*
+ Change RW to READONLY
+
+ mysqld does not turn write locks to read locks,
+ so we're never here in mysqld.
+ */
if (share->w_locks == 1)
{
flag=1;
- if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,
+ if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,
MYF(MY_SEEK_NOT_DONE)))
{
error=my_errno;
@@ -346,9 +356,10 @@ int _mi_readinfo(register MI_INFO *info, int lock_type, int check_keybuffer)
} /* _mi_readinfo */
- /* Every isam-function that uppdates the isam-database must! end */
- /* with this request */
- /* ARGSUSED */
+/*
+ Every isam-function that uppdates the isam-database MUST end with this
+ request
+*/
int _mi_writeinfo(register MI_INFO *info, uint operation)
{
@@ -415,12 +426,31 @@ int _mi_test_if_changed(register MI_INFO *info)
} /* _mi_test_if_changed */
-/* Put a mark in the .MYI file that someone is updating the table */
+/*
+ Put a mark in the .MYI file that someone is updating the table
+
+
+ DOCUMENTATION
+
+ state.open_count in the .MYI file is used the following way:
+ - For the first change of the .MYI file in this process open_count is
+ incremented by mi_mark_file_change(). (We have a write lock on the file
+ when this happens)
+ - In mi_close() it's decremented by _mi_decrement_open_count() if it
+ was incremented in the same process.
+
+ This mean that if we are the only process using the file, the open_count
+ tells us if the MYISAM file wasn't properly closed. (This is true if
+ my_disable_locking is set).
+*/
+
int _mi_mark_file_changed(MI_INFO *info)
{
char buff[3];
register MYISAM_SHARE *share=info->s;
+ DBUG_ENTER("_mi_mark_file_changed");
+
if (!(share->state.changed & STATE_CHANGED) || ! share->global_changed)
{
share->state.changed|=(STATE_CHANGED | STATE_NOT_ANALYZED |
@@ -434,12 +464,12 @@ int _mi_mark_file_changed(MI_INFO *info)
{
mi_int2store(buff,share->state.open_count);
buff[2]=1; /* Mark that it's changed */
- return (my_pwrite(share->kfile,buff,sizeof(buff),
- sizeof(share->state.header),
- MYF(MY_NABP)));
+ DBUG_RETURN(my_pwrite(share->kfile,buff,sizeof(buff),
+ sizeof(share->state.header),
+ MYF(MY_NABP)));
}
}
- return 0;
+ DBUG_RETURN(0);
}
diff --git a/myisam/myisampack.c b/myisam/myisampack.c
index de4bd80805a..0bbf2721cb3 100644
--- a/myisam/myisampack.c
+++ b/myisam/myisampack.c
@@ -2044,7 +2044,11 @@ static int save_state(MI_INFO *isam_file,PACK_MRG_INFO *mrg,my_off_t new_length,
share->state.split=(ha_rows) mrg->records;
share->state.version=(ulong) time((time_t*) 0);
share->state.key_map=0;
- share->state.state.key_file_length=share->base.keystart;
+ /*
+ Don't save key_file_length here, keep key_file_length of original file
+ so "myisamchk -rq" can use this value (this is necessary because index
+ size cannot be easily calculated for fulltext keys)
+ */
for (key=0 ; key < share->base.keys ; key++)
share->state.key_root[key]= HA_OFFSET_ERROR;
for (key=0 ; key < share->state.header.max_block_size ; key++)
diff --git a/mysql-test/include/ps_query.inc b/mysql-test/include/ps_query.inc
index e02d0d5bf96..e807e897161 100644
--- a/mysql-test/include/ps_query.inc
+++ b/mysql-test/include/ps_query.inc
@@ -104,26 +104,26 @@ prepare stmt1 from ' select substr(''MySQL'',1,?) from t1 where a=1 ' ;
execute stmt1 using @arg00 ;
# variations on 'concat'
set @arg00='MySQL' ;
-select a , concat(@arg00,b) from t1 ;
+select a , concat(@arg00,b) from t1 order by a;
# BUG#3796 Prepared statement, select concat(<parameter>,<column>),wrong result
-prepare stmt1 from ' select a , concat(?,b) from t1 ' ;
+prepare stmt1 from ' select a , concat(?,b) from t1 order by a ' ;
execute stmt1 using @arg00;
#
-select a , concat(b,@arg00) from t1 ;
-prepare stmt1 from ' select a , concat(b,?) from t1 ' ;
+select a , concat(b,@arg00) from t1 order by a ;
+prepare stmt1 from ' select a , concat(b,?) from t1 order by a ' ;
execute stmt1 using @arg00;
# variations on 'group_concat'
set @arg00='MySQL' ;
-select group_concat(@arg00,b) from t1
+select group_concat(@arg00,b order by a) from t1
group by 'a' ;
-prepare stmt1 from ' select group_concat(?,b) from t1
+prepare stmt1 from ' select group_concat(?,b order by a) from t1
group by ''a'' ' ;
execute stmt1 using @arg00;
#
-select group_concat(b,@arg00) from t1
+select group_concat(b,@arg00 order by a) from t1
group by 'a' ;
-prepare stmt1 from ' select group_concat(b,?) from t1
+prepare stmt1 from ' select group_concat(b,? order by a) from t1
group by ''a'' ' ;
execute stmt1 using @arg00;
@@ -147,7 +147,7 @@ create table t5 (id1 int(11) not null default '0',
value2 varchar(100), value1 varchar(100)) ;
insert into t5 values (1,'hh','hh'),(2,'hh','hh'),
(1,'ii','ii'),(2,'ii','ii') ;
-prepare stmt1 from ' select id1,value1 from t5 where id1=? or value1=? ' ;
+prepare stmt1 from ' select id1,value1 from t5 where id1=? or value1=? order by id1,value1 ' ;
set @arg00=1 ;
set @arg01='hh' ;
execute stmt1 using @arg00, @arg01 ;
@@ -216,14 +216,14 @@ execute stmt1 using @arg00 ;
# parameter in IN
set @arg00=2 ;
set @arg01=3 ;
-select a FROM t1 where a in (@arg00,@arg01);
-prepare stmt1 from ' select a FROM t1 where a in (?,?) ';
+select a FROM t1 where a in (@arg00,@arg01) order by a;
+prepare stmt1 from ' select a FROM t1 where a in (?,?) order by a ';
execute stmt1 using @arg00, @arg01;
# case derived from client_test.c: test_bug1500()
set @arg00= 'one' ;
set @arg01= 'two' ;
set @arg02= 'five' ;
-prepare stmt1 from ' select b FROM t1 where b in (?,?,?) ' ;
+prepare stmt1 from ' select b FROM t1 where b in (?,?,?) order by b ' ;
execute stmt1 using @arg00, @arg01, @arg02 ;
# parameter in LIKE
prepare stmt1 from ' select b FROM t1 where b like ? ';
@@ -270,9 +270,9 @@ execute stmt1 using @arg00 ;
##### parameter used in having clause
set @arg00='two' ;
select a,b FROM t1 where a is not NULL
-AND b is not NULL having b <> @arg00 ;
+AND b is not NULL having b <> @arg00 order by a ;
prepare stmt1 from ' select a,b FROM t1 where a is not NULL
-AND b is not NULL having b <> ? ' ;
+AND b is not NULL having b <> ? order by a ' ;
execute stmt1 using @arg00 ;
##### parameter used in order clause
@@ -297,7 +297,7 @@ execute stmt1 using @arg00;
##### parameter used in limit clause
set @arg00=1;
-prepare stmt1 from ' select a,b from t1
+prepare stmt1 from ' select a,b from t1 order by a
limit 1 ';
execute stmt1 ;
# currently (May 2004, Version 4.1) it is impossible
@@ -327,10 +327,10 @@ select '------ join tests ------' as test_sequence ;
# no parameter
select first.a as a1, second.a as a2
from t1 first, t1 second
-where first.a = second.a ;
+where first.a = second.a order by a1 ;
prepare stmt1 from ' select first.a as a1, second.a as a2
from t1 first, t1 second
- where first.a = second.a ';
+ where first.a = second.a order by a1 ';
execute stmt1 ;
# some parameters
@@ -350,15 +350,15 @@ execute stmt1 using @arg00, @arg01, @arg02;
drop table if exists t2 ;
--enable_warnings
create table t2 as select * from t1 ;
-set @query1= 'SELECT * FROM t2 join t1 on (t1.a=t2.a) ' ;
-set @query2= 'SELECT * FROM t2 natural join t1 ' ;
-set @query3= 'SELECT * FROM t2 join t1 using(a) ' ;
-set @query4= 'SELECT * FROM t2 left join t1 on(t1.a=t2.a) ' ;
-set @query5= 'SELECT * FROM t2 natural left join t1 ' ;
-set @query6= 'SELECT * FROM t2 left join t1 using(a) ' ;
-set @query7= 'SELECT * FROM t2 right join t1 on(t1.a=t2.a) ' ;
-set @query8= 'SELECT * FROM t2 natural right join t1 ' ;
-set @query9= 'SELECT * FROM t2 right join t1 using(a) ' ;
+set @query1= 'SELECT * FROM t2 join t1 on (t1.a=t2.a) order by t2.a ' ;
+set @query2= 'SELECT * FROM t2 natural join t1 order by t2.a ' ;
+set @query3= 'SELECT * FROM t2 join t1 using(a) order by t2.a ' ;
+set @query4= 'SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a ' ;
+set @query5= 'SELECT * FROM t2 natural left join t1 order by t2.a ' ;
+set @query6= 'SELECT * FROM t2 left join t1 using(a) order by t2.a ' ;
+set @query7= 'SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a ' ;
+set @query8= 'SELECT * FROM t2 natural right join t1 order by t2.a ' ;
+set @query9= 'SELECT * FROM t2 right join t1 using(a) order by t2.a ' ;
let $1= 9 ;
while ($1)
{
@@ -424,7 +424,7 @@ execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
######## correlated subquery
# no parameter
prepare stmt1 from ' select a, b FROM t1 outer_table where
- a = (select a from t1 where b = outer_table.b ) ';
+ a = (select a from t1 where b = outer_table.b ) order by a ';
# also Bug#4000 (only BDB tables)
# Bug#4106 : ndb table, query with correlated subquery, wrong result
execute stmt1 ;
diff --git a/mysql-test/r/auto_increment.result b/mysql-test/r/auto_increment.result
index f5ec5f1f852..428b2769fdb 100644
--- a/mysql-test/r/auto_increment.result
+++ b/mysql-test/r/auto_increment.result
@@ -289,3 +289,55 @@ a b
0 13
500 14
drop table t1;
+create table t1 (a bigint);
+insert into t1 values (1), (2), (3), (NULL), (NULL);
+alter table t1 modify a bigint not null auto_increment primary key;
+select * from t1;
+a
+1
+2
+3
+4
+5
+drop table t1;
+create table t1 (a bigint);
+insert into t1 values (1), (2), (3), (0), (0);
+alter table t1 modify a bigint not null auto_increment primary key;
+select * from t1;
+a
+1
+2
+3
+4
+5
+drop table t1;
+create table t1 (a bigint);
+insert into t1 values (0), (1), (2), (3);
+set sql_mode=NO_AUTO_VALUE_ON_ZERO;
+alter table t1 modify a bigint not null auto_increment primary key;
+set sql_mode= '';
+select * from t1;
+a
+0
+1
+2
+3
+drop table t1;
+create table t1 (a int auto_increment primary key , b int null);
+set sql_mode=NO_AUTO_VALUE_ON_ZERO;
+insert into t1 values (0,1),(1,2),(2,3);
+select * from t1;
+a b
+0 1
+1 2
+2 3
+set sql_mode= '';
+alter table t1 modify b varchar(255);
+insert into t1 values (0,4);
+select * from t1;
+a b
+0 1
+1 2
+2 3
+3 4
+drop table t1;
diff --git a/mysql-test/r/bdb.result b/mysql-test/r/bdb.result
index 846adaf53ef..6da3dbb929d 100644
--- a/mysql-test/r/bdb.result
+++ b/mysql-test/r/bdb.result
@@ -1260,3 +1260,27 @@ a length(a) char_length(a)
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 510 255
drop table t1;
SET NAMES latin1;
+CREATE TABLE t1 (
+id int unsigned NOT NULL auto_increment,
+list_id smallint unsigned NOT NULL,
+term TEXT NOT NULL,
+PRIMARY KEY(id),
+INDEX(list_id, term(4))
+) ENGINE=BDB CHARSET=utf8;
+INSERT INTO t1 SET list_id = 1, term = "letterc";
+INSERT INTO t1 SET list_id = 1, term = "letterb";
+INSERT INTO t1 SET list_id = 1, term = "lettera";
+INSERT INTO t1 SET list_id = 1, term = "letterd";
+SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterc");
+id
+1
+SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterb");
+id
+2
+SELECT id FROM t1 WHERE (list_id = 1) AND (term = "lettera");
+id
+3
+SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterd");
+id
+4
+DROP TABLE t1;
diff --git a/mysql-test/r/ctype_latin1_de.result b/mysql-test/r/ctype_latin1_de.result
index c500019042f..50af5464f54 100644
--- a/mysql-test/r/ctype_latin1_de.result
+++ b/mysql-test/r/ctype_latin1_de.result
@@ -280,6 +280,20 @@ word word2
ß ß
drop table t1;
CREATE TABLE t1 (
+autor varchar(80) NOT NULL default '',
+PRIMARY KEY (autor)
+);
+INSERT INTO t1 VALUES ('Powell, B.'),('Powell, Bud.'),('Powell, L. H.'),('Power, H.'),
+('Poynter, M. A. L. Lane'),('Poynting, J. H. und J. J. Thomson.'),('Pozzi, S(amuel-Jean).'),
+('Pozzi, Samuel-Jean.'),('Pozzo, A.'),('Pozzoli, Serge.');
+SELECT * FROM t1 WHERE autor LIKE 'Poz%' ORDER BY autor;
+autor
+Pozzi, S(amuel-Jean).
+Pozzi, Samuel-Jean.
+Pozzo, A.
+Pozzoli, Serge.
+DROP TABLE t1;
+CREATE TABLE t1 (
s1 CHAR(5) CHARACTER SET latin1 COLLATE latin1_german2_ci
);
show create table t1;
diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result
index 0c9ea42a0f1..0b98d9432ae 100644
--- a/mysql-test/r/ctype_utf8.result
+++ b/mysql-test/r/ctype_utf8.result
@@ -726,3 +726,27 @@ length(subject)
3
432
DROP TABLE t1;
+CREATE TABLE t1 (
+id int unsigned NOT NULL auto_increment,
+list_id smallint unsigned NOT NULL,
+term TEXT NOT NULL,
+PRIMARY KEY(id),
+INDEX(list_id, term(4))
+) ENGINE=MYISAM CHARSET=utf8;
+INSERT INTO t1 SET list_id = 1, term = "letterc";
+INSERT INTO t1 SET list_id = 1, term = "letterb";
+INSERT INTO t1 SET list_id = 1, term = "lettera";
+INSERT INTO t1 SET list_id = 1, term = "letterd";
+SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterc");
+id
+1
+SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterb");
+id
+2
+SELECT id FROM t1 WHERE (list_id = 1) AND (term = "lettera");
+id
+3
+SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterd");
+id
+4
+DROP TABLE t1;
diff --git a/mysql-test/r/delete.result b/mysql-test/r/delete.result
index c6b7a40214d..5575ee1bf98 100644
--- a/mysql-test/r/delete.result
+++ b/mysql-test/r/delete.result
@@ -58,6 +58,17 @@ select count(*) from t1;
count(*)
0
drop table t1;
+create table t1 (a int not null auto_increment primary key, b char(32));
+insert into t1 (b) values ('apple'), ('apple');
+select * from t1;
+a b
+1 apple
+2 apple
+delete t1 from t1, t1 as t2 where t1.b = t2.b and t1.a > t2.a;
+select * from t1;
+a b
+1 apple
+drop table t1;
create table t11 (a int NOT NULL, b int, primary key (a));
create table t12 (a int NOT NULL, b int, primary key (a));
create table t2 (a int NOT NULL, b int, primary key (a));
diff --git a/mysql-test/r/flush_table.result b/mysql-test/r/flush_table.result
index 257f69fa6d9..2ef4ab5b52b 100644
--- a/mysql-test/r/flush_table.result
+++ b/mysql-test/r/flush_table.result
@@ -30,14 +30,23 @@ test.t2
flush tables;
handler a1 read first limit 9;
-ERROR 42S02: Unknown table 'a1' in HANDLER
+table_id
+test.t1
+
handler a2 read first limit 9;
-ERROR 42S02: Unknown table 'a2' in HANDLER
+table_id
+test.t1
+
handler t2 read first limit 9;
-ERROR 42S02: Unknown table 't2' in HANDLER
+table_id
+test.t2
+
handler t1 open as a1;
+ERROR 42000: Not unique table/alias: 'a1'
handler t1 open as a2;
+ERROR 42000: Not unique table/alias: 'a2'
handler t2 open;
+ERROR 42000: Not unique table/alias: 't2'
handler a1 read first limit 9;
table_id
test.t1
@@ -52,15 +61,43 @@ test.t2
flush table t1;
handler a1 read first limit 9;
-ERROR 42S02: Unknown table 'a1' in HANDLER
+table_id
+test.t1
+
handler a2 read first limit 9;
-ERROR 42S02: Unknown table 'a2' in HANDLER
+table_id
+test.t1
+
handler t2 read first limit 9;
table_id
test.t2
flush table t2;
handler t2 close;
-ERROR 42S02: Unknown table 't2' in HANDLER
drop table t1;
drop table t2;
+create table t1(table_id char(20) primary key);
+insert into t1 values ('Record-01');
+insert into t1 values ('Record-02');
+insert into t1 values ('Record-03');
+insert into t1 values ('Record-04');
+insert into t1 values ('Record-05');
+handler t1 open;
+handler t1 read first limit 1;
+table_id
+Record-01
+handler t1 read next limit 1;
+table_id
+Record-02
+handler t1 read next limit 1;
+table_id
+Record-03
+flush table t1;
+handler t1 read next limit 1;
+table_id
+Record-01
+handler t1 read next limit 1;
+table_id
+Record-02
+handler t1 close;
+drop table t1;
diff --git a/mysql-test/r/func_if.result b/mysql-test/r/func_if.result
index dd916d06372..508a50caf02 100644
--- a/mysql-test/r/func_if.result
+++ b/mysql-test/r/func_if.result
@@ -83,3 +83,6 @@ select if(1>2,a,avg(a)) from t1;
if(1>2,a,avg(a))
1.5000
drop table t1;
+SELECT NULLIF(5,5) IS NULL, NULLIF(5,5) IS NOT NULL;
+NULLIF(5,5) IS NULL NULLIF(5,5) IS NOT NULL
+1 0
diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result
index 7b2fc4b21a5..4a3a70274fd 100644
--- a/mysql-test/r/func_str.result
+++ b/mysql-test/r/func_str.result
@@ -316,6 +316,12 @@ NULL NULL 1 1 n
two 'two' 0 0 'two'
four 'four' 0 0 'four'
drop table t1;
+select trim(trailing 'foo' from 'foo');
+trim(trailing 'foo' from 'foo')
+
+select trim(leading 'foo' from 'foo');
+trim(leading 'foo' from 'foo')
+
select 1=_latin1'1';
1=_latin1'1'
1
diff --git a/mysql-test/r/handler.result b/mysql-test/r/handler.result
index f66e9f1759d..072d4582cbc 100644
--- a/mysql-test/r/handler.result
+++ b/mysql-test/r/handler.result
@@ -205,3 +205,243 @@ handler t1 read a=(1) where b=1;
a b
handler t1 close;
drop table t1;
+drop database if exists test_test;
+create database test_test;
+use test_test;
+create table t1(table_id char(20) primary key);
+insert into t1 values ('test_test.t1');
+insert into t1 values ('');
+handler t1 open;
+handler t1 read first limit 9;
+table_id
+test_test.t1
+
+create table t2(table_id char(20) primary key);
+insert into t2 values ('test_test.t2');
+insert into t2 values ('');
+handler t2 open;
+handler t2 read first limit 9;
+table_id
+test_test.t2
+
+use test;
+drop table if exists t1;
+create table t1(table_id char(20) primary key);
+insert into t1 values ('test.t1');
+insert into t1 values ('');
+handler t1 open;
+ERROR 42000: Not unique table/alias: 't1'
+use test;
+handler test.t1 read first limit 9;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'read first limit 9' at line 1
+handler test_test.t1 read first limit 9;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'read first limit 9' at line 1
+handler t1 read first limit 9;
+table_id
+test_test.t1
+
+handler test_test.t2 read first limit 9;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'read first limit 9' at line 1
+handler t2 read first limit 9;
+table_id
+test_test.t2
+
+handler test_test.t1 close;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'close' at line 1
+handler t1 close;
+drop table test_test.t1;
+handler test_test.t2 close;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'close' at line 1
+handler t2 close;
+drop table test_test.t2;
+drop database test_test;
+use test;
+handler test.t1 close;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'close' at line 1
+handler t1 close;
+ERROR 42S02: Unknown table 't1' in HANDLER
+drop table test.t1;
+drop database if exists test_test;
+drop table if exists t1;
+drop table if exists t2;
+drop table if exists t3;
+create database test_test;
+use test_test;
+create table t1 (c1 char(20));
+insert into t1 values ('test_test.t1');
+create table t3 (c1 char(20));
+insert into t3 values ('test_test.t3');
+handler t1 open;
+handler t1 read first limit 9;
+c1
+test_test.t1
+handler t1 open h1;
+handler h1 read first limit 9;
+c1
+test_test.t1
+use test;
+create table t1 (c1 char(20));
+create table t2 (c1 char(20));
+create table t3 (c1 char(20));
+insert into t1 values ('t1');
+insert into t2 values ('t2');
+insert into t3 values ('t3');
+handler t1 open;
+ERROR 42000: Not unique table/alias: 't1'
+handler t2 open t1;
+ERROR 42000: Not unique table/alias: 't1'
+handler t3 open t1;
+ERROR 42000: Not unique table/alias: 't1'
+handler t1 read first limit 9;
+c1
+test_test.t1
+handler test.t1 close;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'close' at line 1
+handler test.t1 open h1;
+ERROR 42000: Not unique table/alias: 'h1'
+handler test_test.t1 open h1;
+ERROR 42000: Not unique table/alias: 'h1'
+handler test_test.t3 open h3;
+handler test.t1 open h2;
+handler t1 read first limit 9;
+c1
+test_test.t1
+handler h1 read first limit 9;
+c1
+test_test.t1
+handler h2 read first limit 9;
+c1
+t1
+handler h3 read first limit 9;
+c1
+test_test.t3
+handler h2 read first limit 9;
+c1
+t1
+handler test.h1 close;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'close' at line 1
+handler t1 close;
+handler h1 close;
+handler h2 close;
+handler t1 read first limit 9;
+ERROR 42S02: Unknown table 't1' in HANDLER
+handler h1 read first limit 9;
+ERROR 42S02: Unknown table 'h1' in HANDLER
+handler h2 read first limit 9;
+ERROR 42S02: Unknown table 'h2' in HANDLER
+handler h3 read first limit 9;
+c1
+test_test.t3
+handler h3 read first limit 9;
+c1
+test_test.t3
+use test_test;
+handler h3 read first limit 9;
+c1
+test_test.t3
+handler test.h3 read first limit 9;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'read first limit 9' at line 1
+handler h3 close;
+use test;
+drop table t3;
+drop table t2;
+drop table t1;
+drop database test_test;
+create table t1 (c1 char(20));
+insert into t1 values ("t1");
+handler t1 open as h1;
+handler h1 read first limit 9;
+c1
+t1
+create table t2 (c1 char(20));
+insert into t2 values ("t2");
+handler t2 open as h2;
+handler h2 read first limit 9;
+c1
+t2
+create table t3 (c1 char(20));
+insert into t3 values ("t3");
+handler t3 open as h3;
+handler h3 read first limit 9;
+c1
+t3
+create table t4 (c1 char(20));
+insert into t4 values ("t4");
+handler t4 open as h4;
+handler h4 read first limit 9;
+c1
+t4
+create table t5 (c1 char(20));
+insert into t5 values ("t5");
+handler t5 open as h5;
+handler h5 read first limit 9;
+c1
+t5
+alter table t1 engine=MyISAM;
+handler h1 read first limit 9;
+ERROR 42S02: Unknown table 'h1' in HANDLER
+handler h2 read first limit 9;
+c1
+t2
+handler h3 read first limit 9;
+c1
+t3
+handler h4 read first limit 9;
+c1
+t4
+handler h5 read first limit 9;
+c1
+t5
+alter table t5 engine=MyISAM;
+handler h1 read first limit 9;
+ERROR 42S02: Unknown table 'h1' in HANDLER
+handler h2 read first limit 9;
+c1
+t2
+handler h3 read first limit 9;
+c1
+t3
+handler h4 read first limit 9;
+c1
+t4
+handler h5 read first limit 9;
+ERROR 42S02: Unknown table 'h5' in HANDLER
+alter table t3 engine=MyISAM;
+handler h1 read first limit 9;
+ERROR 42S02: Unknown table 'h1' in HANDLER
+handler h2 read first limit 9;
+c1
+t2
+handler h3 read first limit 9;
+ERROR 42S02: Unknown table 'h3' in HANDLER
+handler h4 read first limit 9;
+c1
+t4
+handler h5 read first limit 9;
+ERROR 42S02: Unknown table 'h5' in HANDLER
+handler h2 close;
+handler h4 close;
+handler t1 open as h1_1;
+handler t1 open as h1_2;
+handler t1 open as h1_3;
+handler h1_1 read first limit 9;
+c1
+t1
+handler h1_2 read first limit 9;
+c1
+t1
+handler h1_3 read first limit 9;
+c1
+t1
+alter table t1 engine=MyISAM;
+handler h1_1 read first limit 9;
+ERROR 42S02: Unknown table 'h1_1' in HANDLER
+handler h1_2 read first limit 9;
+ERROR 42S02: Unknown table 'h1_2' in HANDLER
+handler h1_3 read first limit 9;
+ERROR 42S02: Unknown table 'h1_3' in HANDLER
+drop table t1;
+drop table t2;
+drop table t3;
+drop table t4;
+drop table t5;
diff --git a/mysql-test/r/lock_multi.result b/mysql-test/r/lock_multi.result
index a0efce727d3..9eedbf50064 100644
--- a/mysql-test/r/lock_multi.result
+++ b/mysql-test/r/lock_multi.result
@@ -17,6 +17,18 @@ unlock tables;
n
1
drop table t1;
+create table t1 (a int, b int);
+create table t2 (c int, d int);
+insert into t1 values(1,1);
+insert into t1 values(2,2);
+insert into t2 values(1,2);
+lock table t1 read;
+ update t1,t2 set c=a where b=d;
+select c from t2;
+c
+2
+drop table t1;
+drop table t2;
create table t1 (a int);
create table t2 (a int);
lock table t1 write, t2 write;
diff --git a/mysql-test/r/multi_update.result b/mysql-test/r/multi_update.result
index 780ceb36ad6..045a1b05e47 100644
--- a/mysql-test/r/multi_update.result
+++ b/mysql-test/r/multi_update.result
@@ -1,5 +1,8 @@
drop table if exists t1,t2,t3;
drop database if exists mysqltest;
+revoke all privileges on mysqltest.t1 from mysqltest_1@localhost;
+revoke all privileges on mysqltest.* from mysqltest_1@localhost;
+delete from mysql.user where user=_binary'mysqltest_1';
create table t1(id1 int not null auto_increment primary key, t char(12));
create table t2(id2 int not null, t char(12));
create table t3(id3 int not null, t char(12), index(id3));
@@ -152,7 +155,6 @@ ERROR HY000: Table 't2' was locked with a READ lock and can't be updated
UPDATE t1,t2 SET t1.d=t2.d,t2.d=30 WHERE t1.n=t2.n;
ERROR HY000: Table 't2' was locked with a READ lock and can't be updated
UPDATE t1,t2 SET t1.d=t2.d WHERE t1.n=t2.n;
-ERROR HY000: Table 't2' was locked with a READ lock and can't be updated
unlock tables;
LOCK TABLES t1 write, t2 write;
UPDATE t1,t2 SET t1.d=t2.d WHERE t1.n=t2.n;
diff --git a/mysql-test/r/ndb_subquery.result b/mysql-test/r/ndb_subquery.result
new file mode 100644
index 00000000000..f65f09b71b3
--- /dev/null
+++ b/mysql-test/r/ndb_subquery.result
@@ -0,0 +1,42 @@
+drop table if exists t1;
+drop table if exists t2;
+create table t1 (p int not null primary key, u int not null, o int not null,
+unique (u), key(o)) engine=ndb;
+create table t2 (p int not null primary key, u int not null, o int not null,
+unique (u), key(o)) engine=ndb;
+insert into t1 values (1,1,1),(2,2,2),(3,3,3);
+insert into t2 values (1,1,1),(2,2,2),(3,3,3), (4,4,4), (5,5,5);
+explain select * from t2 where p NOT IN (select p from t1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using where
+2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 Using index
+select * from t2 where p NOT IN (select p from t1) order by p;
+p u o
+4 4 4
+5 5 5
+explain select * from t2 where p NOT IN (select u from t1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using where
+2 DEPENDENT SUBQUERY t1 unique_subquery u u 4 func 1 Using index
+select * from t2 where p NOT IN (select u from t1) order by p;
+p u o
+4 4 4
+5 5 5
+explain select * from t2 where p NOT IN (select o from t1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using where
+2 DEPENDENT SUBQUERY t1 index_subquery o o 4 func 1 Using index
+select * from t2 where p NOT IN (select o from t1) order by p;
+p u o
+4 4 4
+5 5 5
+explain select * from t2 where p NOT IN (select p+0 from t1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using where
+2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 Using where
+select * from t2 where p NOT IN (select p+0 from t1) order by p;
+p u o
+4 4 4
+5 5 5
+drop table t1;
+drop table t2;
diff --git a/mysql-test/r/ps_2myisam.result b/mysql-test/r/ps_2myisam.result
index 68e0a53fdba..7abac3bfb48 100644
--- a/mysql-test/r/ps_2myisam.result
+++ b/mysql-test/r/ps_2myisam.result
@@ -165,26 +165,26 @@ execute stmt1 using @arg00 ;
substr('MySQL',1,?)
MyS
set @arg00='MySQL' ;
-select a , concat(@arg00,b) from t1 ;
+select a , concat(@arg00,b) from t1 order by a;
a concat(@arg00,b)
1 MySQLone
2 MySQLtwo
3 MySQLthree
4 MySQLfour
-prepare stmt1 from ' select a , concat(?,b) from t1 ' ;
+prepare stmt1 from ' select a , concat(?,b) from t1 order by a ' ;
execute stmt1 using @arg00;
a concat(?,b)
1 MySQLone
2 MySQLtwo
3 MySQLthree
4 MySQLfour
-select a , concat(b,@arg00) from t1 ;
+select a , concat(b,@arg00) from t1 order by a ;
a concat(b,@arg00)
1 oneMySQL
2 twoMySQL
3 threeMySQL
4 fourMySQL
-prepare stmt1 from ' select a , concat(b,?) from t1 ' ;
+prepare stmt1 from ' select a , concat(b,?) from t1 order by a ' ;
execute stmt1 using @arg00;
a concat(b,?)
1 oneMySQL
@@ -192,23 +192,23 @@ a concat(b,?)
3 threeMySQL
4 fourMySQL
set @arg00='MySQL' ;
-select group_concat(@arg00,b) from t1
+select group_concat(@arg00,b order by a) from t1
group by 'a' ;
-group_concat(@arg00,b)
+group_concat(@arg00,b order by a)
MySQLone,MySQLtwo,MySQLthree,MySQLfour
-prepare stmt1 from ' select group_concat(?,b) from t1
+prepare stmt1 from ' select group_concat(?,b order by a) from t1
group by ''a'' ' ;
execute stmt1 using @arg00;
-group_concat(?,b)
+group_concat(?,b order by a)
MySQLone,MySQLtwo,MySQLthree,MySQLfour
-select group_concat(b,@arg00) from t1
+select group_concat(b,@arg00 order by a) from t1
group by 'a' ;
-group_concat(b,@arg00)
+group_concat(b,@arg00 order by a)
oneMySQL,twoMySQL,threeMySQL,fourMySQL
-prepare stmt1 from ' select group_concat(b,?) from t1
+prepare stmt1 from ' select group_concat(b,? order by a) from t1
group by ''a'' ' ;
execute stmt1 using @arg00;
-group_concat(b,?)
+group_concat(b,? order by a)
oneMySQL,twoMySQL,threeMySQL,fourMySQL
set @arg00='first' ;
set @arg01='second' ;
@@ -234,14 +234,14 @@ create table t5 (id1 int(11) not null default '0',
value2 varchar(100), value1 varchar(100)) ;
insert into t5 values (1,'hh','hh'),(2,'hh','hh'),
(1,'ii','ii'),(2,'ii','ii') ;
-prepare stmt1 from ' select id1,value1 from t5 where id1=? or value1=? ' ;
+prepare stmt1 from ' select id1,value1 from t5 where id1=? or value1=? order by id1,value1 ' ;
set @arg00=1 ;
set @arg01='hh' ;
execute stmt1 using @arg00, @arg01 ;
id1 value1
1 hh
-2 hh
1 ii
+2 hh
drop table t5 ;
drop table if exists t5 ;
create table t5(session_id char(9) not null) ;
@@ -307,11 +307,11 @@ execute stmt1 using @arg00 ;
a
set @arg00=2 ;
set @arg01=3 ;
-select a FROM t1 where a in (@arg00,@arg01);
+select a FROM t1 where a in (@arg00,@arg01) order by a;
a
2
3
-prepare stmt1 from ' select a FROM t1 where a in (?,?) ';
+prepare stmt1 from ' select a FROM t1 where a in (?,?) order by a ';
execute stmt1 using @arg00, @arg01;
a
2
@@ -319,7 +319,7 @@ a
set @arg00= 'one' ;
set @arg01= 'two' ;
set @arg02= 'five' ;
-prepare stmt1 from ' select b FROM t1 where b in (?,?,?) ' ;
+prepare stmt1 from ' select b FROM t1 where b in (?,?,?) order by b ' ;
execute stmt1 using @arg00, @arg01, @arg02 ;
b
one
@@ -385,13 +385,13 @@ a b
4 four
set @arg00='two' ;
select a,b FROM t1 where a is not NULL
-AND b is not NULL having b <> @arg00 ;
+AND b is not NULL having b <> @arg00 order by a ;
a b
1 one
3 three
4 four
prepare stmt1 from ' select a,b FROM t1 where a is not NULL
-AND b is not NULL having b <> ? ' ;
+AND b is not NULL having b <> ? order by a ' ;
execute stmt1 using @arg00 ;
a b
1 one
@@ -439,7 +439,7 @@ set @arg00=0 ;
execute stmt1 using @arg00;
ERROR 42S22: Unknown column '?' in 'order clause'
set @arg00=1;
-prepare stmt1 from ' select a,b from t1
+prepare stmt1 from ' select a,b from t1 order by a
limit 1 ';
execute stmt1 ;
a b
@@ -470,7 +470,7 @@ test_sequence
------ join tests ------
select first.a as a1, second.a as a2
from t1 first, t1 second
-where first.a = second.a ;
+where first.a = second.a order by a1 ;
a1 a2
1 1
2 2
@@ -478,7 +478,7 @@ a1 a2
4 4
prepare stmt1 from ' select first.a as a1, second.a as a2
from t1 first, t1 second
- where first.a = second.a ';
+ where first.a = second.a order by a1 ';
execute stmt1 ;
a1 a2
1 1
@@ -517,17 +517,17 @@ a ? a
4 ABC 4
drop table if exists t2 ;
create table t2 as select * from t1 ;
-set @query1= 'SELECT * FROM t2 join t1 on (t1.a=t2.a) ' ;
-set @query2= 'SELECT * FROM t2 natural join t1 ' ;
-set @query3= 'SELECT * FROM t2 join t1 using(a) ' ;
-set @query4= 'SELECT * FROM t2 left join t1 on(t1.a=t2.a) ' ;
-set @query5= 'SELECT * FROM t2 natural left join t1 ' ;
-set @query6= 'SELECT * FROM t2 left join t1 using(a) ' ;
-set @query7= 'SELECT * FROM t2 right join t1 on(t1.a=t2.a) ' ;
-set @query8= 'SELECT * FROM t2 natural right join t1 ' ;
-set @query9= 'SELECT * FROM t2 right join t1 using(a) ' ;
+set @query1= 'SELECT * FROM t2 join t1 on (t1.a=t2.a) order by t2.a ' ;
+set @query2= 'SELECT * FROM t2 natural join t1 order by t2.a ' ;
+set @query3= 'SELECT * FROM t2 join t1 using(a) order by t2.a ' ;
+set @query4= 'SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a ' ;
+set @query5= 'SELECT * FROM t2 natural left join t1 order by t2.a ' ;
+set @query6= 'SELECT * FROM t2 left join t1 using(a) order by t2.a ' ;
+set @query7= 'SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a ' ;
+set @query8= 'SELECT * FROM t2 natural right join t1 order by t2.a ' ;
+set @query9= 'SELECT * FROM t2 right join t1 using(a) order by t2.a ' ;
the join statement is:
-SELECT * FROM t2 right join t1 using(a)
+SELECT * FROM t2 right join t1 using(a) order by t2.a
prepare stmt1 from @query9 ;
execute stmt1 ;
a b a b
@@ -548,7 +548,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 natural right join t1
+SELECT * FROM t2 natural right join t1 order by t2.a
prepare stmt1 from @query8 ;
execute stmt1 ;
a b a b
@@ -569,7 +569,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 right join t1 on(t1.a=t2.a)
+SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a
prepare stmt1 from @query7 ;
execute stmt1 ;
a b a b
@@ -590,7 +590,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 left join t1 using(a)
+SELECT * FROM t2 left join t1 using(a) order by t2.a
prepare stmt1 from @query6 ;
execute stmt1 ;
a b a b
@@ -611,7 +611,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 natural left join t1
+SELECT * FROM t2 natural left join t1 order by t2.a
prepare stmt1 from @query5 ;
execute stmt1 ;
a b a b
@@ -632,7 +632,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 left join t1 on(t1.a=t2.a)
+SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a
prepare stmt1 from @query4 ;
execute stmt1 ;
a b a b
@@ -653,7 +653,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 join t1 using(a)
+SELECT * FROM t2 join t1 using(a) order by t2.a
prepare stmt1 from @query3 ;
execute stmt1 ;
a b a b
@@ -674,7 +674,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 natural join t1
+SELECT * FROM t2 natural join t1 order by t2.a
prepare stmt1 from @query2 ;
execute stmt1 ;
a b
@@ -695,7 +695,7 @@ a b
3 three
4 four
the join statement is:
-SELECT * FROM t2 join t1 on (t1.a=t2.a)
+SELECT * FROM t2 join t1 on (t1.a=t2.a) order by t2.a
prepare stmt1 from @query1 ;
execute stmt1 ;
a b a b
@@ -769,7 +769,7 @@ execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
a ? b
2 1 two
prepare stmt1 from ' select a, b FROM t1 outer_table where
- a = (select a from t1 where b = outer_table.b ) ';
+ a = (select a from t1 where b = outer_table.b ) order by a ';
execute stmt1 ;
a b
1 one
diff --git a/mysql-test/r/ps_3innodb.result b/mysql-test/r/ps_3innodb.result
index 90cd5e39f9c..e404eb7e97b 100644
--- a/mysql-test/r/ps_3innodb.result
+++ b/mysql-test/r/ps_3innodb.result
@@ -165,26 +165,26 @@ execute stmt1 using @arg00 ;
substr('MySQL',1,?)
MyS
set @arg00='MySQL' ;
-select a , concat(@arg00,b) from t1 ;
+select a , concat(@arg00,b) from t1 order by a;
a concat(@arg00,b)
1 MySQLone
2 MySQLtwo
3 MySQLthree
4 MySQLfour
-prepare stmt1 from ' select a , concat(?,b) from t1 ' ;
+prepare stmt1 from ' select a , concat(?,b) from t1 order by a ' ;
execute stmt1 using @arg00;
a concat(?,b)
1 MySQLone
2 MySQLtwo
3 MySQLthree
4 MySQLfour
-select a , concat(b,@arg00) from t1 ;
+select a , concat(b,@arg00) from t1 order by a ;
a concat(b,@arg00)
1 oneMySQL
2 twoMySQL
3 threeMySQL
4 fourMySQL
-prepare stmt1 from ' select a , concat(b,?) from t1 ' ;
+prepare stmt1 from ' select a , concat(b,?) from t1 order by a ' ;
execute stmt1 using @arg00;
a concat(b,?)
1 oneMySQL
@@ -192,23 +192,23 @@ a concat(b,?)
3 threeMySQL
4 fourMySQL
set @arg00='MySQL' ;
-select group_concat(@arg00,b) from t1
+select group_concat(@arg00,b order by a) from t1
group by 'a' ;
-group_concat(@arg00,b)
+group_concat(@arg00,b order by a)
MySQLone,MySQLtwo,MySQLthree,MySQLfour
-prepare stmt1 from ' select group_concat(?,b) from t1
+prepare stmt1 from ' select group_concat(?,b order by a) from t1
group by ''a'' ' ;
execute stmt1 using @arg00;
-group_concat(?,b)
+group_concat(?,b order by a)
MySQLone,MySQLtwo,MySQLthree,MySQLfour
-select group_concat(b,@arg00) from t1
+select group_concat(b,@arg00 order by a) from t1
group by 'a' ;
-group_concat(b,@arg00)
+group_concat(b,@arg00 order by a)
oneMySQL,twoMySQL,threeMySQL,fourMySQL
-prepare stmt1 from ' select group_concat(b,?) from t1
+prepare stmt1 from ' select group_concat(b,? order by a) from t1
group by ''a'' ' ;
execute stmt1 using @arg00;
-group_concat(b,?)
+group_concat(b,? order by a)
oneMySQL,twoMySQL,threeMySQL,fourMySQL
set @arg00='first' ;
set @arg01='second' ;
@@ -234,14 +234,14 @@ create table t5 (id1 int(11) not null default '0',
value2 varchar(100), value1 varchar(100)) ;
insert into t5 values (1,'hh','hh'),(2,'hh','hh'),
(1,'ii','ii'),(2,'ii','ii') ;
-prepare stmt1 from ' select id1,value1 from t5 where id1=? or value1=? ' ;
+prepare stmt1 from ' select id1,value1 from t5 where id1=? or value1=? order by id1,value1 ' ;
set @arg00=1 ;
set @arg01='hh' ;
execute stmt1 using @arg00, @arg01 ;
id1 value1
1 hh
-2 hh
1 ii
+2 hh
drop table t5 ;
drop table if exists t5 ;
create table t5(session_id char(9) not null) ;
@@ -307,11 +307,11 @@ execute stmt1 using @arg00 ;
a
set @arg00=2 ;
set @arg01=3 ;
-select a FROM t1 where a in (@arg00,@arg01);
+select a FROM t1 where a in (@arg00,@arg01) order by a;
a
2
3
-prepare stmt1 from ' select a FROM t1 where a in (?,?) ';
+prepare stmt1 from ' select a FROM t1 where a in (?,?) order by a ';
execute stmt1 using @arg00, @arg01;
a
2
@@ -319,7 +319,7 @@ a
set @arg00= 'one' ;
set @arg01= 'two' ;
set @arg02= 'five' ;
-prepare stmt1 from ' select b FROM t1 where b in (?,?,?) ' ;
+prepare stmt1 from ' select b FROM t1 where b in (?,?,?) order by b ' ;
execute stmt1 using @arg00, @arg01, @arg02 ;
b
one
@@ -385,13 +385,13 @@ a b
4 four
set @arg00='two' ;
select a,b FROM t1 where a is not NULL
-AND b is not NULL having b <> @arg00 ;
+AND b is not NULL having b <> @arg00 order by a ;
a b
1 one
3 three
4 four
prepare stmt1 from ' select a,b FROM t1 where a is not NULL
-AND b is not NULL having b <> ? ' ;
+AND b is not NULL having b <> ? order by a ' ;
execute stmt1 using @arg00 ;
a b
1 one
@@ -439,7 +439,7 @@ set @arg00=0 ;
execute stmt1 using @arg00;
ERROR 42S22: Unknown column '?' in 'order clause'
set @arg00=1;
-prepare stmt1 from ' select a,b from t1
+prepare stmt1 from ' select a,b from t1 order by a
limit 1 ';
execute stmt1 ;
a b
@@ -470,7 +470,7 @@ test_sequence
------ join tests ------
select first.a as a1, second.a as a2
from t1 first, t1 second
-where first.a = second.a ;
+where first.a = second.a order by a1 ;
a1 a2
1 1
2 2
@@ -478,7 +478,7 @@ a1 a2
4 4
prepare stmt1 from ' select first.a as a1, second.a as a2
from t1 first, t1 second
- where first.a = second.a ';
+ where first.a = second.a order by a1 ';
execute stmt1 ;
a1 a2
1 1
@@ -517,17 +517,17 @@ a ? a
4 ABC 4
drop table if exists t2 ;
create table t2 as select * from t1 ;
-set @query1= 'SELECT * FROM t2 join t1 on (t1.a=t2.a) ' ;
-set @query2= 'SELECT * FROM t2 natural join t1 ' ;
-set @query3= 'SELECT * FROM t2 join t1 using(a) ' ;
-set @query4= 'SELECT * FROM t2 left join t1 on(t1.a=t2.a) ' ;
-set @query5= 'SELECT * FROM t2 natural left join t1 ' ;
-set @query6= 'SELECT * FROM t2 left join t1 using(a) ' ;
-set @query7= 'SELECT * FROM t2 right join t1 on(t1.a=t2.a) ' ;
-set @query8= 'SELECT * FROM t2 natural right join t1 ' ;
-set @query9= 'SELECT * FROM t2 right join t1 using(a) ' ;
+set @query1= 'SELECT * FROM t2 join t1 on (t1.a=t2.a) order by t2.a ' ;
+set @query2= 'SELECT * FROM t2 natural join t1 order by t2.a ' ;
+set @query3= 'SELECT * FROM t2 join t1 using(a) order by t2.a ' ;
+set @query4= 'SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a ' ;
+set @query5= 'SELECT * FROM t2 natural left join t1 order by t2.a ' ;
+set @query6= 'SELECT * FROM t2 left join t1 using(a) order by t2.a ' ;
+set @query7= 'SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a ' ;
+set @query8= 'SELECT * FROM t2 natural right join t1 order by t2.a ' ;
+set @query9= 'SELECT * FROM t2 right join t1 using(a) order by t2.a ' ;
the join statement is:
-SELECT * FROM t2 right join t1 using(a)
+SELECT * FROM t2 right join t1 using(a) order by t2.a
prepare stmt1 from @query9 ;
execute stmt1 ;
a b a b
@@ -548,7 +548,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 natural right join t1
+SELECT * FROM t2 natural right join t1 order by t2.a
prepare stmt1 from @query8 ;
execute stmt1 ;
a b a b
@@ -569,7 +569,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 right join t1 on(t1.a=t2.a)
+SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a
prepare stmt1 from @query7 ;
execute stmt1 ;
a b a b
@@ -590,7 +590,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 left join t1 using(a)
+SELECT * FROM t2 left join t1 using(a) order by t2.a
prepare stmt1 from @query6 ;
execute stmt1 ;
a b a b
@@ -611,7 +611,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 natural left join t1
+SELECT * FROM t2 natural left join t1 order by t2.a
prepare stmt1 from @query5 ;
execute stmt1 ;
a b a b
@@ -632,7 +632,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 left join t1 on(t1.a=t2.a)
+SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a
prepare stmt1 from @query4 ;
execute stmt1 ;
a b a b
@@ -653,7 +653,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 join t1 using(a)
+SELECT * FROM t2 join t1 using(a) order by t2.a
prepare stmt1 from @query3 ;
execute stmt1 ;
a b a b
@@ -674,7 +674,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 natural join t1
+SELECT * FROM t2 natural join t1 order by t2.a
prepare stmt1 from @query2 ;
execute stmt1 ;
a b
@@ -695,7 +695,7 @@ a b
3 three
4 four
the join statement is:
-SELECT * FROM t2 join t1 on (t1.a=t2.a)
+SELECT * FROM t2 join t1 on (t1.a=t2.a) order by t2.a
prepare stmt1 from @query1 ;
execute stmt1 ;
a b a b
@@ -769,7 +769,7 @@ execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
a ? b
2 1 two
prepare stmt1 from ' select a, b FROM t1 outer_table where
- a = (select a from t1 where b = outer_table.b ) ';
+ a = (select a from t1 where b = outer_table.b ) order by a ';
execute stmt1 ;
a b
1 one
diff --git a/mysql-test/r/ps_4heap.result b/mysql-test/r/ps_4heap.result
index feef6bcf83e..94c9b2c357a 100644
--- a/mysql-test/r/ps_4heap.result
+++ b/mysql-test/r/ps_4heap.result
@@ -166,26 +166,26 @@ execute stmt1 using @arg00 ;
substr('MySQL',1,?)
MyS
set @arg00='MySQL' ;
-select a , concat(@arg00,b) from t1 ;
+select a , concat(@arg00,b) from t1 order by a;
a concat(@arg00,b)
1 MySQLone
2 MySQLtwo
3 MySQLthree
4 MySQLfour
-prepare stmt1 from ' select a , concat(?,b) from t1 ' ;
+prepare stmt1 from ' select a , concat(?,b) from t1 order by a ' ;
execute stmt1 using @arg00;
a concat(?,b)
1 MySQLone
2 MySQLtwo
3 MySQLthree
4 MySQLfour
-select a , concat(b,@arg00) from t1 ;
+select a , concat(b,@arg00) from t1 order by a ;
a concat(b,@arg00)
1 oneMySQL
2 twoMySQL
3 threeMySQL
4 fourMySQL
-prepare stmt1 from ' select a , concat(b,?) from t1 ' ;
+prepare stmt1 from ' select a , concat(b,?) from t1 order by a ' ;
execute stmt1 using @arg00;
a concat(b,?)
1 oneMySQL
@@ -193,23 +193,23 @@ a concat(b,?)
3 threeMySQL
4 fourMySQL
set @arg00='MySQL' ;
-select group_concat(@arg00,b) from t1
+select group_concat(@arg00,b order by a) from t1
group by 'a' ;
-group_concat(@arg00,b)
+group_concat(@arg00,b order by a)
MySQLone,MySQLtwo,MySQLthree,MySQLfour
-prepare stmt1 from ' select group_concat(?,b) from t1
+prepare stmt1 from ' select group_concat(?,b order by a) from t1
group by ''a'' ' ;
execute stmt1 using @arg00;
-group_concat(?,b)
+group_concat(?,b order by a)
MySQLone,MySQLtwo,MySQLthree,MySQLfour
-select group_concat(b,@arg00) from t1
+select group_concat(b,@arg00 order by a) from t1
group by 'a' ;
-group_concat(b,@arg00)
+group_concat(b,@arg00 order by a)
oneMySQL,twoMySQL,threeMySQL,fourMySQL
-prepare stmt1 from ' select group_concat(b,?) from t1
+prepare stmt1 from ' select group_concat(b,? order by a) from t1
group by ''a'' ' ;
execute stmt1 using @arg00;
-group_concat(b,?)
+group_concat(b,? order by a)
oneMySQL,twoMySQL,threeMySQL,fourMySQL
set @arg00='first' ;
set @arg01='second' ;
@@ -235,14 +235,14 @@ create table t5 (id1 int(11) not null default '0',
value2 varchar(100), value1 varchar(100)) ;
insert into t5 values (1,'hh','hh'),(2,'hh','hh'),
(1,'ii','ii'),(2,'ii','ii') ;
-prepare stmt1 from ' select id1,value1 from t5 where id1=? or value1=? ' ;
+prepare stmt1 from ' select id1,value1 from t5 where id1=? or value1=? order by id1,value1 ' ;
set @arg00=1 ;
set @arg01='hh' ;
execute stmt1 using @arg00, @arg01 ;
id1 value1
1 hh
-2 hh
1 ii
+2 hh
drop table t5 ;
drop table if exists t5 ;
create table t5(session_id char(9) not null) ;
@@ -308,11 +308,11 @@ execute stmt1 using @arg00 ;
a
set @arg00=2 ;
set @arg01=3 ;
-select a FROM t1 where a in (@arg00,@arg01);
+select a FROM t1 where a in (@arg00,@arg01) order by a;
a
2
3
-prepare stmt1 from ' select a FROM t1 where a in (?,?) ';
+prepare stmt1 from ' select a FROM t1 where a in (?,?) order by a ';
execute stmt1 using @arg00, @arg01;
a
2
@@ -320,7 +320,7 @@ a
set @arg00= 'one' ;
set @arg01= 'two' ;
set @arg02= 'five' ;
-prepare stmt1 from ' select b FROM t1 where b in (?,?,?) ' ;
+prepare stmt1 from ' select b FROM t1 where b in (?,?,?) order by b ' ;
execute stmt1 using @arg00, @arg01, @arg02 ;
b
one
@@ -386,13 +386,13 @@ a b
4 four
set @arg00='two' ;
select a,b FROM t1 where a is not NULL
-AND b is not NULL having b <> @arg00 ;
+AND b is not NULL having b <> @arg00 order by a ;
a b
1 one
3 three
4 four
prepare stmt1 from ' select a,b FROM t1 where a is not NULL
-AND b is not NULL having b <> ? ' ;
+AND b is not NULL having b <> ? order by a ' ;
execute stmt1 using @arg00 ;
a b
1 one
@@ -440,7 +440,7 @@ set @arg00=0 ;
execute stmt1 using @arg00;
ERROR 42S22: Unknown column '?' in 'order clause'
set @arg00=1;
-prepare stmt1 from ' select a,b from t1
+prepare stmt1 from ' select a,b from t1 order by a
limit 1 ';
execute stmt1 ;
a b
@@ -471,7 +471,7 @@ test_sequence
------ join tests ------
select first.a as a1, second.a as a2
from t1 first, t1 second
-where first.a = second.a ;
+where first.a = second.a order by a1 ;
a1 a2
1 1
2 2
@@ -479,7 +479,7 @@ a1 a2
4 4
prepare stmt1 from ' select first.a as a1, second.a as a2
from t1 first, t1 second
- where first.a = second.a ';
+ where first.a = second.a order by a1 ';
execute stmt1 ;
a1 a2
1 1
@@ -518,17 +518,17 @@ a ? a
4 ABC 4
drop table if exists t2 ;
create table t2 as select * from t1 ;
-set @query1= 'SELECT * FROM t2 join t1 on (t1.a=t2.a) ' ;
-set @query2= 'SELECT * FROM t2 natural join t1 ' ;
-set @query3= 'SELECT * FROM t2 join t1 using(a) ' ;
-set @query4= 'SELECT * FROM t2 left join t1 on(t1.a=t2.a) ' ;
-set @query5= 'SELECT * FROM t2 natural left join t1 ' ;
-set @query6= 'SELECT * FROM t2 left join t1 using(a) ' ;
-set @query7= 'SELECT * FROM t2 right join t1 on(t1.a=t2.a) ' ;
-set @query8= 'SELECT * FROM t2 natural right join t1 ' ;
-set @query9= 'SELECT * FROM t2 right join t1 using(a) ' ;
+set @query1= 'SELECT * FROM t2 join t1 on (t1.a=t2.a) order by t2.a ' ;
+set @query2= 'SELECT * FROM t2 natural join t1 order by t2.a ' ;
+set @query3= 'SELECT * FROM t2 join t1 using(a) order by t2.a ' ;
+set @query4= 'SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a ' ;
+set @query5= 'SELECT * FROM t2 natural left join t1 order by t2.a ' ;
+set @query6= 'SELECT * FROM t2 left join t1 using(a) order by t2.a ' ;
+set @query7= 'SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a ' ;
+set @query8= 'SELECT * FROM t2 natural right join t1 order by t2.a ' ;
+set @query9= 'SELECT * FROM t2 right join t1 using(a) order by t2.a ' ;
the join statement is:
-SELECT * FROM t2 right join t1 using(a)
+SELECT * FROM t2 right join t1 using(a) order by t2.a
prepare stmt1 from @query9 ;
execute stmt1 ;
a b a b
@@ -549,7 +549,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 natural right join t1
+SELECT * FROM t2 natural right join t1 order by t2.a
prepare stmt1 from @query8 ;
execute stmt1 ;
a b a b
@@ -570,7 +570,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 right join t1 on(t1.a=t2.a)
+SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a
prepare stmt1 from @query7 ;
execute stmt1 ;
a b a b
@@ -591,7 +591,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 left join t1 using(a)
+SELECT * FROM t2 left join t1 using(a) order by t2.a
prepare stmt1 from @query6 ;
execute stmt1 ;
a b a b
@@ -612,7 +612,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 natural left join t1
+SELECT * FROM t2 natural left join t1 order by t2.a
prepare stmt1 from @query5 ;
execute stmt1 ;
a b a b
@@ -633,7 +633,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 left join t1 on(t1.a=t2.a)
+SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a
prepare stmt1 from @query4 ;
execute stmt1 ;
a b a b
@@ -654,7 +654,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 join t1 using(a)
+SELECT * FROM t2 join t1 using(a) order by t2.a
prepare stmt1 from @query3 ;
execute stmt1 ;
a b a b
@@ -675,7 +675,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 natural join t1
+SELECT * FROM t2 natural join t1 order by t2.a
prepare stmt1 from @query2 ;
execute stmt1 ;
a b
@@ -696,7 +696,7 @@ a b
3 three
4 four
the join statement is:
-SELECT * FROM t2 join t1 on (t1.a=t2.a)
+SELECT * FROM t2 join t1 on (t1.a=t2.a) order by t2.a
prepare stmt1 from @query1 ;
execute stmt1 ;
a b a b
@@ -770,7 +770,7 @@ execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
a ? b
2 1 two
prepare stmt1 from ' select a, b FROM t1 outer_table where
- a = (select a from t1 where b = outer_table.b ) ';
+ a = (select a from t1 where b = outer_table.b ) order by a ';
execute stmt1 ;
a b
1 one
diff --git a/mysql-test/r/ps_5merge.result b/mysql-test/r/ps_5merge.result
index 8f87343c894..f4903baf979 100644
--- a/mysql-test/r/ps_5merge.result
+++ b/mysql-test/r/ps_5merge.result
@@ -208,26 +208,26 @@ execute stmt1 using @arg00 ;
substr('MySQL',1,?)
MyS
set @arg00='MySQL' ;
-select a , concat(@arg00,b) from t1 ;
+select a , concat(@arg00,b) from t1 order by a;
a concat(@arg00,b)
1 MySQLone
2 MySQLtwo
3 MySQLthree
4 MySQLfour
-prepare stmt1 from ' select a , concat(?,b) from t1 ' ;
+prepare stmt1 from ' select a , concat(?,b) from t1 order by a ' ;
execute stmt1 using @arg00;
a concat(?,b)
1 MySQLone
2 MySQLtwo
3 MySQLthree
4 MySQLfour
-select a , concat(b,@arg00) from t1 ;
+select a , concat(b,@arg00) from t1 order by a ;
a concat(b,@arg00)
1 oneMySQL
2 twoMySQL
3 threeMySQL
4 fourMySQL
-prepare stmt1 from ' select a , concat(b,?) from t1 ' ;
+prepare stmt1 from ' select a , concat(b,?) from t1 order by a ' ;
execute stmt1 using @arg00;
a concat(b,?)
1 oneMySQL
@@ -235,23 +235,23 @@ a concat(b,?)
3 threeMySQL
4 fourMySQL
set @arg00='MySQL' ;
-select group_concat(@arg00,b) from t1
+select group_concat(@arg00,b order by a) from t1
group by 'a' ;
-group_concat(@arg00,b)
+group_concat(@arg00,b order by a)
MySQLone,MySQLtwo,MySQLthree,MySQLfour
-prepare stmt1 from ' select group_concat(?,b) from t1
+prepare stmt1 from ' select group_concat(?,b order by a) from t1
group by ''a'' ' ;
execute stmt1 using @arg00;
-group_concat(?,b)
+group_concat(?,b order by a)
MySQLone,MySQLtwo,MySQLthree,MySQLfour
-select group_concat(b,@arg00) from t1
+select group_concat(b,@arg00 order by a) from t1
group by 'a' ;
-group_concat(b,@arg00)
+group_concat(b,@arg00 order by a)
oneMySQL,twoMySQL,threeMySQL,fourMySQL
-prepare stmt1 from ' select group_concat(b,?) from t1
+prepare stmt1 from ' select group_concat(b,? order by a) from t1
group by ''a'' ' ;
execute stmt1 using @arg00;
-group_concat(b,?)
+group_concat(b,? order by a)
oneMySQL,twoMySQL,threeMySQL,fourMySQL
set @arg00='first' ;
set @arg01='second' ;
@@ -277,14 +277,14 @@ create table t5 (id1 int(11) not null default '0',
value2 varchar(100), value1 varchar(100)) ;
insert into t5 values (1,'hh','hh'),(2,'hh','hh'),
(1,'ii','ii'),(2,'ii','ii') ;
-prepare stmt1 from ' select id1,value1 from t5 where id1=? or value1=? ' ;
+prepare stmt1 from ' select id1,value1 from t5 where id1=? or value1=? order by id1,value1 ' ;
set @arg00=1 ;
set @arg01='hh' ;
execute stmt1 using @arg00, @arg01 ;
id1 value1
1 hh
-2 hh
1 ii
+2 hh
drop table t5 ;
drop table if exists t5 ;
create table t5(session_id char(9) not null) ;
@@ -350,11 +350,11 @@ execute stmt1 using @arg00 ;
a
set @arg00=2 ;
set @arg01=3 ;
-select a FROM t1 where a in (@arg00,@arg01);
+select a FROM t1 where a in (@arg00,@arg01) order by a;
a
2
3
-prepare stmt1 from ' select a FROM t1 where a in (?,?) ';
+prepare stmt1 from ' select a FROM t1 where a in (?,?) order by a ';
execute stmt1 using @arg00, @arg01;
a
2
@@ -362,7 +362,7 @@ a
set @arg00= 'one' ;
set @arg01= 'two' ;
set @arg02= 'five' ;
-prepare stmt1 from ' select b FROM t1 where b in (?,?,?) ' ;
+prepare stmt1 from ' select b FROM t1 where b in (?,?,?) order by b ' ;
execute stmt1 using @arg00, @arg01, @arg02 ;
b
one
@@ -428,13 +428,13 @@ a b
4 four
set @arg00='two' ;
select a,b FROM t1 where a is not NULL
-AND b is not NULL having b <> @arg00 ;
+AND b is not NULL having b <> @arg00 order by a ;
a b
1 one
3 three
4 four
prepare stmt1 from ' select a,b FROM t1 where a is not NULL
-AND b is not NULL having b <> ? ' ;
+AND b is not NULL having b <> ? order by a ' ;
execute stmt1 using @arg00 ;
a b
1 one
@@ -482,7 +482,7 @@ set @arg00=0 ;
execute stmt1 using @arg00;
ERROR 42S22: Unknown column '?' in 'order clause'
set @arg00=1;
-prepare stmt1 from ' select a,b from t1
+prepare stmt1 from ' select a,b from t1 order by a
limit 1 ';
execute stmt1 ;
a b
@@ -513,7 +513,7 @@ test_sequence
------ join tests ------
select first.a as a1, second.a as a2
from t1 first, t1 second
-where first.a = second.a ;
+where first.a = second.a order by a1 ;
a1 a2
1 1
2 2
@@ -521,7 +521,7 @@ a1 a2
4 4
prepare stmt1 from ' select first.a as a1, second.a as a2
from t1 first, t1 second
- where first.a = second.a ';
+ where first.a = second.a order by a1 ';
execute stmt1 ;
a1 a2
1 1
@@ -560,17 +560,17 @@ a ? a
4 ABC 4
drop table if exists t2 ;
create table t2 as select * from t1 ;
-set @query1= 'SELECT * FROM t2 join t1 on (t1.a=t2.a) ' ;
-set @query2= 'SELECT * FROM t2 natural join t1 ' ;
-set @query3= 'SELECT * FROM t2 join t1 using(a) ' ;
-set @query4= 'SELECT * FROM t2 left join t1 on(t1.a=t2.a) ' ;
-set @query5= 'SELECT * FROM t2 natural left join t1 ' ;
-set @query6= 'SELECT * FROM t2 left join t1 using(a) ' ;
-set @query7= 'SELECT * FROM t2 right join t1 on(t1.a=t2.a) ' ;
-set @query8= 'SELECT * FROM t2 natural right join t1 ' ;
-set @query9= 'SELECT * FROM t2 right join t1 using(a) ' ;
+set @query1= 'SELECT * FROM t2 join t1 on (t1.a=t2.a) order by t2.a ' ;
+set @query2= 'SELECT * FROM t2 natural join t1 order by t2.a ' ;
+set @query3= 'SELECT * FROM t2 join t1 using(a) order by t2.a ' ;
+set @query4= 'SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a ' ;
+set @query5= 'SELECT * FROM t2 natural left join t1 order by t2.a ' ;
+set @query6= 'SELECT * FROM t2 left join t1 using(a) order by t2.a ' ;
+set @query7= 'SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a ' ;
+set @query8= 'SELECT * FROM t2 natural right join t1 order by t2.a ' ;
+set @query9= 'SELECT * FROM t2 right join t1 using(a) order by t2.a ' ;
the join statement is:
-SELECT * FROM t2 right join t1 using(a)
+SELECT * FROM t2 right join t1 using(a) order by t2.a
prepare stmt1 from @query9 ;
execute stmt1 ;
a b a b
@@ -591,7 +591,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 natural right join t1
+SELECT * FROM t2 natural right join t1 order by t2.a
prepare stmt1 from @query8 ;
execute stmt1 ;
a b a b
@@ -612,7 +612,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 right join t1 on(t1.a=t2.a)
+SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a
prepare stmt1 from @query7 ;
execute stmt1 ;
a b a b
@@ -633,7 +633,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 left join t1 using(a)
+SELECT * FROM t2 left join t1 using(a) order by t2.a
prepare stmt1 from @query6 ;
execute stmt1 ;
a b a b
@@ -654,7 +654,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 natural left join t1
+SELECT * FROM t2 natural left join t1 order by t2.a
prepare stmt1 from @query5 ;
execute stmt1 ;
a b a b
@@ -675,7 +675,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 left join t1 on(t1.a=t2.a)
+SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a
prepare stmt1 from @query4 ;
execute stmt1 ;
a b a b
@@ -696,7 +696,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 join t1 using(a)
+SELECT * FROM t2 join t1 using(a) order by t2.a
prepare stmt1 from @query3 ;
execute stmt1 ;
a b a b
@@ -717,7 +717,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 natural join t1
+SELECT * FROM t2 natural join t1 order by t2.a
prepare stmt1 from @query2 ;
execute stmt1 ;
a b
@@ -738,7 +738,7 @@ a b
3 three
4 four
the join statement is:
-SELECT * FROM t2 join t1 on (t1.a=t2.a)
+SELECT * FROM t2 join t1 on (t1.a=t2.a) order by t2.a
prepare stmt1 from @query1 ;
execute stmt1 ;
a b a b
@@ -812,7 +812,7 @@ execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
a ? b
2 1 two
prepare stmt1 from ' select a, b FROM t1 outer_table where
- a = (select a from t1 where b = outer_table.b ) ';
+ a = (select a from t1 where b = outer_table.b ) order by a ';
execute stmt1 ;
a b
1 one
@@ -3216,26 +3216,26 @@ execute stmt1 using @arg00 ;
substr('MySQL',1,?)
MyS
set @arg00='MySQL' ;
-select a , concat(@arg00,b) from t1 ;
+select a , concat(@arg00,b) from t1 order by a;
a concat(@arg00,b)
1 MySQLone
2 MySQLtwo
3 MySQLthree
4 MySQLfour
-prepare stmt1 from ' select a , concat(?,b) from t1 ' ;
+prepare stmt1 from ' select a , concat(?,b) from t1 order by a ' ;
execute stmt1 using @arg00;
a concat(?,b)
1 MySQLone
2 MySQLtwo
3 MySQLthree
4 MySQLfour
-select a , concat(b,@arg00) from t1 ;
+select a , concat(b,@arg00) from t1 order by a ;
a concat(b,@arg00)
1 oneMySQL
2 twoMySQL
3 threeMySQL
4 fourMySQL
-prepare stmt1 from ' select a , concat(b,?) from t1 ' ;
+prepare stmt1 from ' select a , concat(b,?) from t1 order by a ' ;
execute stmt1 using @arg00;
a concat(b,?)
1 oneMySQL
@@ -3243,23 +3243,23 @@ a concat(b,?)
3 threeMySQL
4 fourMySQL
set @arg00='MySQL' ;
-select group_concat(@arg00,b) from t1
+select group_concat(@arg00,b order by a) from t1
group by 'a' ;
-group_concat(@arg00,b)
+group_concat(@arg00,b order by a)
MySQLone,MySQLtwo,MySQLthree,MySQLfour
-prepare stmt1 from ' select group_concat(?,b) from t1
+prepare stmt1 from ' select group_concat(?,b order by a) from t1
group by ''a'' ' ;
execute stmt1 using @arg00;
-group_concat(?,b)
+group_concat(?,b order by a)
MySQLone,MySQLtwo,MySQLthree,MySQLfour
-select group_concat(b,@arg00) from t1
+select group_concat(b,@arg00 order by a) from t1
group by 'a' ;
-group_concat(b,@arg00)
+group_concat(b,@arg00 order by a)
oneMySQL,twoMySQL,threeMySQL,fourMySQL
-prepare stmt1 from ' select group_concat(b,?) from t1
+prepare stmt1 from ' select group_concat(b,? order by a) from t1
group by ''a'' ' ;
execute stmt1 using @arg00;
-group_concat(b,?)
+group_concat(b,? order by a)
oneMySQL,twoMySQL,threeMySQL,fourMySQL
set @arg00='first' ;
set @arg01='second' ;
@@ -3285,14 +3285,14 @@ create table t5 (id1 int(11) not null default '0',
value2 varchar(100), value1 varchar(100)) ;
insert into t5 values (1,'hh','hh'),(2,'hh','hh'),
(1,'ii','ii'),(2,'ii','ii') ;
-prepare stmt1 from ' select id1,value1 from t5 where id1=? or value1=? ' ;
+prepare stmt1 from ' select id1,value1 from t5 where id1=? or value1=? order by id1,value1 ' ;
set @arg00=1 ;
set @arg01='hh' ;
execute stmt1 using @arg00, @arg01 ;
id1 value1
1 hh
-2 hh
1 ii
+2 hh
drop table t5 ;
drop table if exists t5 ;
create table t5(session_id char(9) not null) ;
@@ -3358,11 +3358,11 @@ execute stmt1 using @arg00 ;
a
set @arg00=2 ;
set @arg01=3 ;
-select a FROM t1 where a in (@arg00,@arg01);
+select a FROM t1 where a in (@arg00,@arg01) order by a;
a
2
3
-prepare stmt1 from ' select a FROM t1 where a in (?,?) ';
+prepare stmt1 from ' select a FROM t1 where a in (?,?) order by a ';
execute stmt1 using @arg00, @arg01;
a
2
@@ -3370,7 +3370,7 @@ a
set @arg00= 'one' ;
set @arg01= 'two' ;
set @arg02= 'five' ;
-prepare stmt1 from ' select b FROM t1 where b in (?,?,?) ' ;
+prepare stmt1 from ' select b FROM t1 where b in (?,?,?) order by b ' ;
execute stmt1 using @arg00, @arg01, @arg02 ;
b
one
@@ -3436,13 +3436,13 @@ a b
4 four
set @arg00='two' ;
select a,b FROM t1 where a is not NULL
-AND b is not NULL having b <> @arg00 ;
+AND b is not NULL having b <> @arg00 order by a ;
a b
1 one
3 three
4 four
prepare stmt1 from ' select a,b FROM t1 where a is not NULL
-AND b is not NULL having b <> ? ' ;
+AND b is not NULL having b <> ? order by a ' ;
execute stmt1 using @arg00 ;
a b
1 one
@@ -3490,7 +3490,7 @@ set @arg00=0 ;
execute stmt1 using @arg00;
ERROR 42S22: Unknown column '?' in 'order clause'
set @arg00=1;
-prepare stmt1 from ' select a,b from t1
+prepare stmt1 from ' select a,b from t1 order by a
limit 1 ';
execute stmt1 ;
a b
@@ -3521,7 +3521,7 @@ test_sequence
------ join tests ------
select first.a as a1, second.a as a2
from t1 first, t1 second
-where first.a = second.a ;
+where first.a = second.a order by a1 ;
a1 a2
1 1
2 2
@@ -3529,7 +3529,7 @@ a1 a2
4 4
prepare stmt1 from ' select first.a as a1, second.a as a2
from t1 first, t1 second
- where first.a = second.a ';
+ where first.a = second.a order by a1 ';
execute stmt1 ;
a1 a2
1 1
@@ -3568,17 +3568,17 @@ a ? a
4 ABC 4
drop table if exists t2 ;
create table t2 as select * from t1 ;
-set @query1= 'SELECT * FROM t2 join t1 on (t1.a=t2.a) ' ;
-set @query2= 'SELECT * FROM t2 natural join t1 ' ;
-set @query3= 'SELECT * FROM t2 join t1 using(a) ' ;
-set @query4= 'SELECT * FROM t2 left join t1 on(t1.a=t2.a) ' ;
-set @query5= 'SELECT * FROM t2 natural left join t1 ' ;
-set @query6= 'SELECT * FROM t2 left join t1 using(a) ' ;
-set @query7= 'SELECT * FROM t2 right join t1 on(t1.a=t2.a) ' ;
-set @query8= 'SELECT * FROM t2 natural right join t1 ' ;
-set @query9= 'SELECT * FROM t2 right join t1 using(a) ' ;
+set @query1= 'SELECT * FROM t2 join t1 on (t1.a=t2.a) order by t2.a ' ;
+set @query2= 'SELECT * FROM t2 natural join t1 order by t2.a ' ;
+set @query3= 'SELECT * FROM t2 join t1 using(a) order by t2.a ' ;
+set @query4= 'SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a ' ;
+set @query5= 'SELECT * FROM t2 natural left join t1 order by t2.a ' ;
+set @query6= 'SELECT * FROM t2 left join t1 using(a) order by t2.a ' ;
+set @query7= 'SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a ' ;
+set @query8= 'SELECT * FROM t2 natural right join t1 order by t2.a ' ;
+set @query9= 'SELECT * FROM t2 right join t1 using(a) order by t2.a ' ;
the join statement is:
-SELECT * FROM t2 right join t1 using(a)
+SELECT * FROM t2 right join t1 using(a) order by t2.a
prepare stmt1 from @query9 ;
execute stmt1 ;
a b a b
@@ -3599,7 +3599,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 natural right join t1
+SELECT * FROM t2 natural right join t1 order by t2.a
prepare stmt1 from @query8 ;
execute stmt1 ;
a b a b
@@ -3620,7 +3620,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 right join t1 on(t1.a=t2.a)
+SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a
prepare stmt1 from @query7 ;
execute stmt1 ;
a b a b
@@ -3641,7 +3641,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 left join t1 using(a)
+SELECT * FROM t2 left join t1 using(a) order by t2.a
prepare stmt1 from @query6 ;
execute stmt1 ;
a b a b
@@ -3662,7 +3662,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 natural left join t1
+SELECT * FROM t2 natural left join t1 order by t2.a
prepare stmt1 from @query5 ;
execute stmt1 ;
a b a b
@@ -3683,7 +3683,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 left join t1 on(t1.a=t2.a)
+SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a
prepare stmt1 from @query4 ;
execute stmt1 ;
a b a b
@@ -3704,7 +3704,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 join t1 using(a)
+SELECT * FROM t2 join t1 using(a) order by t2.a
prepare stmt1 from @query3 ;
execute stmt1 ;
a b a b
@@ -3725,7 +3725,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 natural join t1
+SELECT * FROM t2 natural join t1 order by t2.a
prepare stmt1 from @query2 ;
execute stmt1 ;
a b
@@ -3746,7 +3746,7 @@ a b
3 three
4 four
the join statement is:
-SELECT * FROM t2 join t1 on (t1.a=t2.a)
+SELECT * FROM t2 join t1 on (t1.a=t2.a) order by t2.a
prepare stmt1 from @query1 ;
execute stmt1 ;
a b a b
@@ -3820,7 +3820,7 @@ execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
a ? b
2 1 two
prepare stmt1 from ' select a, b FROM t1 outer_table where
- a = (select a from t1 where b = outer_table.b ) ';
+ a = (select a from t1 where b = outer_table.b ) order by a ';
execute stmt1 ;
a b
1 one
diff --git a/mysql-test/r/ps_6bdb.result b/mysql-test/r/ps_6bdb.result
index 52009dcf82a..0d5054dacdc 100644
--- a/mysql-test/r/ps_6bdb.result
+++ b/mysql-test/r/ps_6bdb.result
@@ -165,26 +165,26 @@ execute stmt1 using @arg00 ;
substr('MySQL',1,?)
MyS
set @arg00='MySQL' ;
-select a , concat(@arg00,b) from t1 ;
+select a , concat(@arg00,b) from t1 order by a;
a concat(@arg00,b)
1 MySQLone
2 MySQLtwo
3 MySQLthree
4 MySQLfour
-prepare stmt1 from ' select a , concat(?,b) from t1 ' ;
+prepare stmt1 from ' select a , concat(?,b) from t1 order by a ' ;
execute stmt1 using @arg00;
a concat(?,b)
1 MySQLone
2 MySQLtwo
3 MySQLthree
4 MySQLfour
-select a , concat(b,@arg00) from t1 ;
+select a , concat(b,@arg00) from t1 order by a ;
a concat(b,@arg00)
1 oneMySQL
2 twoMySQL
3 threeMySQL
4 fourMySQL
-prepare stmt1 from ' select a , concat(b,?) from t1 ' ;
+prepare stmt1 from ' select a , concat(b,?) from t1 order by a ' ;
execute stmt1 using @arg00;
a concat(b,?)
1 oneMySQL
@@ -192,23 +192,23 @@ a concat(b,?)
3 threeMySQL
4 fourMySQL
set @arg00='MySQL' ;
-select group_concat(@arg00,b) from t1
+select group_concat(@arg00,b order by a) from t1
group by 'a' ;
-group_concat(@arg00,b)
+group_concat(@arg00,b order by a)
MySQLone,MySQLtwo,MySQLthree,MySQLfour
-prepare stmt1 from ' select group_concat(?,b) from t1
+prepare stmt1 from ' select group_concat(?,b order by a) from t1
group by ''a'' ' ;
execute stmt1 using @arg00;
-group_concat(?,b)
+group_concat(?,b order by a)
MySQLone,MySQLtwo,MySQLthree,MySQLfour
-select group_concat(b,@arg00) from t1
+select group_concat(b,@arg00 order by a) from t1
group by 'a' ;
-group_concat(b,@arg00)
+group_concat(b,@arg00 order by a)
oneMySQL,twoMySQL,threeMySQL,fourMySQL
-prepare stmt1 from ' select group_concat(b,?) from t1
+prepare stmt1 from ' select group_concat(b,? order by a) from t1
group by ''a'' ' ;
execute stmt1 using @arg00;
-group_concat(b,?)
+group_concat(b,? order by a)
oneMySQL,twoMySQL,threeMySQL,fourMySQL
set @arg00='first' ;
set @arg01='second' ;
@@ -234,14 +234,14 @@ create table t5 (id1 int(11) not null default '0',
value2 varchar(100), value1 varchar(100)) ;
insert into t5 values (1,'hh','hh'),(2,'hh','hh'),
(1,'ii','ii'),(2,'ii','ii') ;
-prepare stmt1 from ' select id1,value1 from t5 where id1=? or value1=? ' ;
+prepare stmt1 from ' select id1,value1 from t5 where id1=? or value1=? order by id1,value1 ' ;
set @arg00=1 ;
set @arg01='hh' ;
execute stmt1 using @arg00, @arg01 ;
id1 value1
1 hh
-2 hh
1 ii
+2 hh
drop table t5 ;
drop table if exists t5 ;
create table t5(session_id char(9) not null) ;
@@ -307,11 +307,11 @@ execute stmt1 using @arg00 ;
a
set @arg00=2 ;
set @arg01=3 ;
-select a FROM t1 where a in (@arg00,@arg01);
+select a FROM t1 where a in (@arg00,@arg01) order by a;
a
2
3
-prepare stmt1 from ' select a FROM t1 where a in (?,?) ';
+prepare stmt1 from ' select a FROM t1 where a in (?,?) order by a ';
execute stmt1 using @arg00, @arg01;
a
2
@@ -319,7 +319,7 @@ a
set @arg00= 'one' ;
set @arg01= 'two' ;
set @arg02= 'five' ;
-prepare stmt1 from ' select b FROM t1 where b in (?,?,?) ' ;
+prepare stmt1 from ' select b FROM t1 where b in (?,?,?) order by b ' ;
execute stmt1 using @arg00, @arg01, @arg02 ;
b
one
@@ -385,13 +385,13 @@ a b
4 four
set @arg00='two' ;
select a,b FROM t1 where a is not NULL
-AND b is not NULL having b <> @arg00 ;
+AND b is not NULL having b <> @arg00 order by a ;
a b
1 one
3 three
4 four
prepare stmt1 from ' select a,b FROM t1 where a is not NULL
-AND b is not NULL having b <> ? ' ;
+AND b is not NULL having b <> ? order by a ' ;
execute stmt1 using @arg00 ;
a b
1 one
@@ -439,7 +439,7 @@ set @arg00=0 ;
execute stmt1 using @arg00;
ERROR 42S22: Unknown column '?' in 'order clause'
set @arg00=1;
-prepare stmt1 from ' select a,b from t1
+prepare stmt1 from ' select a,b from t1 order by a
limit 1 ';
execute stmt1 ;
a b
@@ -470,7 +470,7 @@ test_sequence
------ join tests ------
select first.a as a1, second.a as a2
from t1 first, t1 second
-where first.a = second.a ;
+where first.a = second.a order by a1 ;
a1 a2
1 1
2 2
@@ -478,7 +478,7 @@ a1 a2
4 4
prepare stmt1 from ' select first.a as a1, second.a as a2
from t1 first, t1 second
- where first.a = second.a ';
+ where first.a = second.a order by a1 ';
execute stmt1 ;
a1 a2
1 1
@@ -517,17 +517,17 @@ a ? a
4 ABC 4
drop table if exists t2 ;
create table t2 as select * from t1 ;
-set @query1= 'SELECT * FROM t2 join t1 on (t1.a=t2.a) ' ;
-set @query2= 'SELECT * FROM t2 natural join t1 ' ;
-set @query3= 'SELECT * FROM t2 join t1 using(a) ' ;
-set @query4= 'SELECT * FROM t2 left join t1 on(t1.a=t2.a) ' ;
-set @query5= 'SELECT * FROM t2 natural left join t1 ' ;
-set @query6= 'SELECT * FROM t2 left join t1 using(a) ' ;
-set @query7= 'SELECT * FROM t2 right join t1 on(t1.a=t2.a) ' ;
-set @query8= 'SELECT * FROM t2 natural right join t1 ' ;
-set @query9= 'SELECT * FROM t2 right join t1 using(a) ' ;
+set @query1= 'SELECT * FROM t2 join t1 on (t1.a=t2.a) order by t2.a ' ;
+set @query2= 'SELECT * FROM t2 natural join t1 order by t2.a ' ;
+set @query3= 'SELECT * FROM t2 join t1 using(a) order by t2.a ' ;
+set @query4= 'SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a ' ;
+set @query5= 'SELECT * FROM t2 natural left join t1 order by t2.a ' ;
+set @query6= 'SELECT * FROM t2 left join t1 using(a) order by t2.a ' ;
+set @query7= 'SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a ' ;
+set @query8= 'SELECT * FROM t2 natural right join t1 order by t2.a ' ;
+set @query9= 'SELECT * FROM t2 right join t1 using(a) order by t2.a ' ;
the join statement is:
-SELECT * FROM t2 right join t1 using(a)
+SELECT * FROM t2 right join t1 using(a) order by t2.a
prepare stmt1 from @query9 ;
execute stmt1 ;
a b a b
@@ -548,7 +548,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 natural right join t1
+SELECT * FROM t2 natural right join t1 order by t2.a
prepare stmt1 from @query8 ;
execute stmt1 ;
a b a b
@@ -569,7 +569,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 right join t1 on(t1.a=t2.a)
+SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a
prepare stmt1 from @query7 ;
execute stmt1 ;
a b a b
@@ -590,7 +590,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 left join t1 using(a)
+SELECT * FROM t2 left join t1 using(a) order by t2.a
prepare stmt1 from @query6 ;
execute stmt1 ;
a b a b
@@ -611,7 +611,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 natural left join t1
+SELECT * FROM t2 natural left join t1 order by t2.a
prepare stmt1 from @query5 ;
execute stmt1 ;
a b a b
@@ -632,7 +632,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 left join t1 on(t1.a=t2.a)
+SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a
prepare stmt1 from @query4 ;
execute stmt1 ;
a b a b
@@ -653,7 +653,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 join t1 using(a)
+SELECT * FROM t2 join t1 using(a) order by t2.a
prepare stmt1 from @query3 ;
execute stmt1 ;
a b a b
@@ -674,7 +674,7 @@ a b a b
3 three 3 three
4 four 4 four
the join statement is:
-SELECT * FROM t2 natural join t1
+SELECT * FROM t2 natural join t1 order by t2.a
prepare stmt1 from @query2 ;
execute stmt1 ;
a b
@@ -695,7 +695,7 @@ a b
3 three
4 four
the join statement is:
-SELECT * FROM t2 join t1 on (t1.a=t2.a)
+SELECT * FROM t2 join t1 on (t1.a=t2.a) order by t2.a
prepare stmt1 from @query1 ;
execute stmt1 ;
a b a b
@@ -769,7 +769,7 @@ execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
a ? b
2 1 two
prepare stmt1 from ' select a, b FROM t1 outer_table where
- a = (select a from t1 where b = outer_table.b ) ';
+ a = (select a from t1 where b = outer_table.b ) order by a ';
execute stmt1 ;
a b
1 one
diff --git a/mysql-test/r/ps_7ndb.result b/mysql-test/r/ps_7ndb.result
index decfc08b555..2d3fea3236e 100644
--- a/mysql-test/r/ps_7ndb.result
+++ b/mysql-test/r/ps_7ndb.result
@@ -166,51 +166,51 @@ execute stmt1 using @arg00 ;
substr('MySQL',1,?)
MyS
set @arg00='MySQL' ;
-select a , concat(@arg00,b) from t1 ;
+select a , concat(@arg00,b) from t1 order by a;
a concat(@arg00,b)
+1 MySQLone
2 MySQLtwo
-4 MySQLfour
3 MySQLthree
-1 MySQLone
-prepare stmt1 from ' select a , concat(?,b) from t1 ' ;
+4 MySQLfour
+prepare stmt1 from ' select a , concat(?,b) from t1 order by a ' ;
execute stmt1 using @arg00;
a concat(?,b)
+1 MySQLone
2 MySQLtwo
-4 MySQLfour
3 MySQLthree
-1 MySQLone
-select a , concat(b,@arg00) from t1 ;
+4 MySQLfour
+select a , concat(b,@arg00) from t1 order by a ;
a concat(b,@arg00)
+1 oneMySQL
2 twoMySQL
-4 fourMySQL
3 threeMySQL
-1 oneMySQL
-prepare stmt1 from ' select a , concat(b,?) from t1 ' ;
+4 fourMySQL
+prepare stmt1 from ' select a , concat(b,?) from t1 order by a ' ;
execute stmt1 using @arg00;
a concat(b,?)
+1 oneMySQL
2 twoMySQL
-4 fourMySQL
3 threeMySQL
-1 oneMySQL
+4 fourMySQL
set @arg00='MySQL' ;
-select group_concat(@arg00,b) from t1
+select group_concat(@arg00,b order by a) from t1
group by 'a' ;
-group_concat(@arg00,b)
-MySQLtwo,MySQLfour,MySQLthree,MySQLone
-prepare stmt1 from ' select group_concat(?,b) from t1
+group_concat(@arg00,b order by a)
+MySQLone,MySQLtwo,MySQLthree,MySQLfour
+prepare stmt1 from ' select group_concat(?,b order by a) from t1
group by ''a'' ' ;
execute stmt1 using @arg00;
-group_concat(?,b)
-MySQLtwo,MySQLfour,MySQLthree,MySQLone
-select group_concat(b,@arg00) from t1
+group_concat(?,b order by a)
+MySQLone,MySQLtwo,MySQLthree,MySQLfour
+select group_concat(b,@arg00 order by a) from t1
group by 'a' ;
-group_concat(b,@arg00)
-twoMySQL,fourMySQL,threeMySQL,oneMySQL
-prepare stmt1 from ' select group_concat(b,?) from t1
+group_concat(b,@arg00 order by a)
+oneMySQL,twoMySQL,threeMySQL,fourMySQL
+prepare stmt1 from ' select group_concat(b,? order by a) from t1
group by ''a'' ' ;
execute stmt1 using @arg00;
-group_concat(b,?)
-twoMySQL,fourMySQL,threeMySQL,oneMySQL
+group_concat(b,? order by a)
+oneMySQL,twoMySQL,threeMySQL,fourMySQL
set @arg00='first' ;
set @arg01='second' ;
set @arg02=NULL;
@@ -235,14 +235,14 @@ create table t5 (id1 int(11) not null default '0',
value2 varchar(100), value1 varchar(100)) ;
insert into t5 values (1,'hh','hh'),(2,'hh','hh'),
(1,'ii','ii'),(2,'ii','ii') ;
-prepare stmt1 from ' select id1,value1 from t5 where id1=? or value1=? ' ;
+prepare stmt1 from ' select id1,value1 from t5 where id1=? or value1=? order by id1,value1 ' ;
set @arg00=1 ;
set @arg01='hh' ;
execute stmt1 using @arg00, @arg01 ;
id1 value1
1 hh
-2 hh
1 ii
+2 hh
drop table t5 ;
drop table if exists t5 ;
create table t5(session_id char(9) not null) ;
@@ -308,11 +308,11 @@ execute stmt1 using @arg00 ;
a
set @arg00=2 ;
set @arg01=3 ;
-select a FROM t1 where a in (@arg00,@arg01);
+select a FROM t1 where a in (@arg00,@arg01) order by a;
a
2
3
-prepare stmt1 from ' select a FROM t1 where a in (?,?) ';
+prepare stmt1 from ' select a FROM t1 where a in (?,?) order by a ';
execute stmt1 using @arg00, @arg01;
a
2
@@ -320,11 +320,11 @@ a
set @arg00= 'one' ;
set @arg01= 'two' ;
set @arg02= 'five' ;
-prepare stmt1 from ' select b FROM t1 where b in (?,?,?) ' ;
+prepare stmt1 from ' select b FROM t1 where b in (?,?,?) order by b ' ;
execute stmt1 using @arg00, @arg01, @arg02 ;
b
-two
one
+two
prepare stmt1 from ' select b FROM t1 where b like ? ';
set @arg00='two' ;
execute stmt1 using @arg00 ;
@@ -386,18 +386,18 @@ a b
4 four
set @arg00='two' ;
select a,b FROM t1 where a is not NULL
-AND b is not NULL having b <> @arg00 ;
+AND b is not NULL having b <> @arg00 order by a ;
a b
-4 four
-3 three
1 one
+3 three
+4 four
prepare stmt1 from ' select a,b FROM t1 where a is not NULL
-AND b is not NULL having b <> ? ' ;
+AND b is not NULL having b <> ? order by a ' ;
execute stmt1 using @arg00 ;
a b
-4 four
-3 three
1 one
+3 three
+4 four
set @arg00=1 ;
select a,b FROM t1 where a is not NULL
AND b is not NULL order by a - @arg00 ;
@@ -440,11 +440,11 @@ set @arg00=0 ;
execute stmt1 using @arg00;
ERROR 42S22: Unknown column '?' in 'order clause'
set @arg00=1;
-prepare stmt1 from ' select a,b from t1
+prepare stmt1 from ' select a,b from t1 order by a
limit 1 ';
execute stmt1 ;
a b
-2 two
+1 one
prepare stmt1 from ' select a,b from t1
limit ? ';
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 2
@@ -471,21 +471,21 @@ test_sequence
------ join tests ------
select first.a as a1, second.a as a2
from t1 first, t1 second
-where first.a = second.a ;
+where first.a = second.a order by a1 ;
a1 a2
+1 1
2 2
-4 4
3 3
-1 1
+4 4
prepare stmt1 from ' select first.a as a1, second.a as a2
from t1 first, t1 second
- where first.a = second.a ';
+ where first.a = second.a order by a1 ';
execute stmt1 ;
a1 a2
+1 1
2 2
-4 4
3 3
-1 1
+4 4
set @arg00='ABC';
set @arg01='two';
set @arg02='one';
@@ -518,204 +518,204 @@ a ? a
4 ABC 4
drop table if exists t2 ;
create table t2 as select * from t1 ;
-set @query1= 'SELECT * FROM t2 join t1 on (t1.a=t2.a) ' ;
-set @query2= 'SELECT * FROM t2 natural join t1 ' ;
-set @query3= 'SELECT * FROM t2 join t1 using(a) ' ;
-set @query4= 'SELECT * FROM t2 left join t1 on(t1.a=t2.a) ' ;
-set @query5= 'SELECT * FROM t2 natural left join t1 ' ;
-set @query6= 'SELECT * FROM t2 left join t1 using(a) ' ;
-set @query7= 'SELECT * FROM t2 right join t1 on(t1.a=t2.a) ' ;
-set @query8= 'SELECT * FROM t2 natural right join t1 ' ;
-set @query9= 'SELECT * FROM t2 right join t1 using(a) ' ;
+set @query1= 'SELECT * FROM t2 join t1 on (t1.a=t2.a) order by t2.a ' ;
+set @query2= 'SELECT * FROM t2 natural join t1 order by t2.a ' ;
+set @query3= 'SELECT * FROM t2 join t1 using(a) order by t2.a ' ;
+set @query4= 'SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a ' ;
+set @query5= 'SELECT * FROM t2 natural left join t1 order by t2.a ' ;
+set @query6= 'SELECT * FROM t2 left join t1 using(a) order by t2.a ' ;
+set @query7= 'SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a ' ;
+set @query8= 'SELECT * FROM t2 natural right join t1 order by t2.a ' ;
+set @query9= 'SELECT * FROM t2 right join t1 using(a) order by t2.a ' ;
the join statement is:
-SELECT * FROM t2 right join t1 using(a)
+SELECT * FROM t2 right join t1 using(a) order by t2.a
prepare stmt1 from @query9 ;
execute stmt1 ;
a b a b
+1 one 1 one
2 two 2 two
-4 four 4 four
3 three 3 three
-1 one 1 one
+4 four 4 four
execute stmt1 ;
a b a b
+1 one 1 one
2 two 2 two
-4 four 4 four
3 three 3 three
-1 one 1 one
+4 four 4 four
execute stmt1 ;
a b a b
+1 one 1 one
2 two 2 two
-4 four 4 four
3 three 3 three
-1 one 1 one
+4 four 4 four
the join statement is:
-SELECT * FROM t2 natural right join t1
+SELECT * FROM t2 natural right join t1 order by t2.a
prepare stmt1 from @query8 ;
execute stmt1 ;
a b a b
+1 one 1 one
2 two 2 two
-4 four 4 four
3 three 3 three
-1 one 1 one
+4 four 4 four
execute stmt1 ;
a b a b
+1 one 1 one
2 two 2 two
-4 four 4 four
3 three 3 three
-1 one 1 one
+4 four 4 four
execute stmt1 ;
a b a b
+1 one 1 one
2 two 2 two
-4 four 4 four
3 three 3 three
-1 one 1 one
+4 four 4 four
the join statement is:
-SELECT * FROM t2 right join t1 on(t1.a=t2.a)
+SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a
prepare stmt1 from @query7 ;
execute stmt1 ;
a b a b
+1 one 1 one
2 two 2 two
-4 four 4 four
3 three 3 three
-1 one 1 one
+4 four 4 four
execute stmt1 ;
a b a b
+1 one 1 one
2 two 2 two
-4 four 4 four
3 three 3 three
-1 one 1 one
+4 four 4 four
execute stmt1 ;
a b a b
+1 one 1 one
2 two 2 two
-4 four 4 four
3 three 3 three
-1 one 1 one
+4 four 4 four
the join statement is:
-SELECT * FROM t2 left join t1 using(a)
+SELECT * FROM t2 left join t1 using(a) order by t2.a
prepare stmt1 from @query6 ;
execute stmt1 ;
a b a b
+1 one 1 one
2 two 2 two
-4 four 4 four
3 three 3 three
-1 one 1 one
+4 four 4 four
execute stmt1 ;
a b a b
+1 one 1 one
2 two 2 two
-4 four 4 four
3 three 3 three
-1 one 1 one
+4 four 4 four
execute stmt1 ;
a b a b
+1 one 1 one
2 two 2 two
-4 four 4 four
3 three 3 three
-1 one 1 one
+4 four 4 four
the join statement is:
-SELECT * FROM t2 natural left join t1
+SELECT * FROM t2 natural left join t1 order by t2.a
prepare stmt1 from @query5 ;
execute stmt1 ;
a b a b
+1 one 1 one
2 two 2 two
-4 four 4 four
3 three 3 three
-1 one 1 one
+4 four 4 four
execute stmt1 ;
a b a b
+1 one 1 one
2 two 2 two
-4 four 4 four
3 three 3 three
-1 one 1 one
+4 four 4 four
execute stmt1 ;
a b a b
+1 one 1 one
2 two 2 two
-4 four 4 four
3 three 3 three
-1 one 1 one
+4 four 4 four
the join statement is:
-SELECT * FROM t2 left join t1 on(t1.a=t2.a)
+SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a
prepare stmt1 from @query4 ;
execute stmt1 ;
a b a b
+1 one 1 one
2 two 2 two
-4 four 4 four
3 three 3 three
-1 one 1 one
+4 four 4 four
execute stmt1 ;
a b a b
+1 one 1 one
2 two 2 two
-4 four 4 four
3 three 3 three
-1 one 1 one
+4 four 4 four
execute stmt1 ;
a b a b
+1 one 1 one
2 two 2 two
-4 four 4 four
3 three 3 three
-1 one 1 one
+4 four 4 four
the join statement is:
-SELECT * FROM t2 join t1 using(a)
+SELECT * FROM t2 join t1 using(a) order by t2.a
prepare stmt1 from @query3 ;
execute stmt1 ;
a b a b
+1 one 1 one
2 two 2 two
-4 four 4 four
3 three 3 three
-1 one 1 one
+4 four 4 four
execute stmt1 ;
a b a b
+1 one 1 one
2 two 2 two
-4 four 4 four
3 three 3 three
-1 one 1 one
+4 four 4 four
execute stmt1 ;
a b a b
+1 one 1 one
2 two 2 two
-4 four 4 four
3 three 3 three
-1 one 1 one
+4 four 4 four
the join statement is:
-SELECT * FROM t2 natural join t1
+SELECT * FROM t2 natural join t1 order by t2.a
prepare stmt1 from @query2 ;
execute stmt1 ;
a b
+1 one
2 two
-4 four
3 three
-1 one
+4 four
execute stmt1 ;
a b
+1 one
2 two
-4 four
3 three
-1 one
+4 four
execute stmt1 ;
a b
+1 one
2 two
-4 four
3 three
-1 one
+4 four
the join statement is:
-SELECT * FROM t2 join t1 on (t1.a=t2.a)
+SELECT * FROM t2 join t1 on (t1.a=t2.a) order by t2.a
prepare stmt1 from @query1 ;
execute stmt1 ;
a b a b
+1 one 1 one
2 two 2 two
-4 four 4 four
3 three 3 three
-1 one 1 one
+4 four 4 four
execute stmt1 ;
a b a b
+1 one 1 one
2 two 2 two
-4 four 4 four
3 three 3 three
-1 one 1 one
+4 four 4 four
execute stmt1 ;
a b a b
+1 one 1 one
2 two 2 two
-4 four 4 four
3 three 3 three
-1 one 1 one
+4 four 4 four
drop table t2 ;
test_sequence
------ subquery tests ------
@@ -770,13 +770,13 @@ execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
a ? b
2 1 two
prepare stmt1 from ' select a, b FROM t1 outer_table where
- a = (select a from t1 where b = outer_table.b ) ';
+ a = (select a from t1 where b = outer_table.b ) order by a ';
execute stmt1 ;
a b
+1 one
2 two
-4 four
3 three
-1 one
+4 four
prepare stmt1 from ' SELECT a as ccc from t1 where a+1=
(SELECT 1+ccc from t1 where ccc+1=a+1 and a=1) ';
execute stmt1 ;
@@ -1188,7 +1188,7 @@ c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
commit ;
prepare stmt1 from 'delete from t1 where a=2' ;
execute stmt1;
-select a,b from t1 where a=2;
+select a,b from t1 where a=2 order by b;
a b
execute stmt1;
insert into t1 values(0,NULL);
@@ -1334,7 +1334,7 @@ prepare stmt1 from 'update t1 set a=? where b=?
execute stmt1 using @arg04, @arg01, @arg02, @arg03, @arg00 ;
affected rows: 0
info: Rows matched: 0 Changed: 0 Warnings: 0
-select a,b from t1 order by a;
+select a,b from t1 order by a ;
a b
1 one
2 two
@@ -1474,7 +1474,7 @@ set @arg02=82 ;
set @arg03='8-2' ;
prepare stmt1 from 'insert into t1 values(?,?),(?,?)';
execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
-select a,b from t1 where a in (@arg00,@arg02) ;
+select a,b from t1 where a in (@arg00,@arg02) order by a ;
a b
81 8-1
82 8-2
diff --git a/mysql-test/r/rename.result b/mysql-test/r/rename.result
index ec36f015412..76c0f4422fe 100644
--- a/mysql-test/r/rename.result
+++ b/mysql-test/r/rename.result
@@ -1,5 +1,5 @@
drop table if exists t0,t1,t2,t3,t4;
-drop table if exists t0,t5,t6,t7,t8,t9;
+drop table if exists t0,t5,t6,t7,t8,t9,t1_1,t1_2,t9_1,t9_2;
create table t0 SELECT 1,"table 1";
create table t2 SELECT 2,"table 2";
create table t3 SELECT 3,"table 3";
diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result
index f0618c0f153..ba0a80331b1 100644
--- a/mysql-test/r/select.result
+++ b/mysql-test/r/select.result
@@ -1,4 +1,5 @@
drop table if exists t1,t2,t3,t4;
+drop table if exists t1_1,t1_2,t9_1,t9_2;
CREATE TABLE t1 (
Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL,
Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL
diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result
index 8b52e6efedc..8256c8d692a 100644
--- a/mysql-test/r/show_check.result
+++ b/mysql-test/r/show_check.result
@@ -1,5 +1,8 @@
drop table if exists t1,t2;
drop database if exists mysqltest;
+delete from mysql.user where user='mysqltest_1' || user='mysqltest_2' || user='mysqltest_3';
+delete from mysql.db where user='mysqltest_1' || user='mysqltest_2' || user='mysqltest_3';
+flush privileges;
create table t1 (a int not null primary key, b int not null,c int not null, key(b,c));
insert into t1 values (1,2,2),(2,2,3),(3,2,4),(4,2,4);
check table t1 fast;
diff --git a/mysql-test/r/type_timestamp.result b/mysql-test/r/type_timestamp.result
index 6a7cecdd460..42fdc7e50c6 100644
--- a/mysql-test/r/type_timestamp.result
+++ b/mysql-test/r/type_timestamp.result
@@ -92,9 +92,6 @@ date date_time time_stamp
2005-01-01 2005-01-01 00:00:00 2005-01-01 00:00:00
2030-01-01 2030-01-01 00:00:00 2030-01-01 00:00:00
drop table t1;
-show variables like 'new';
-Variable_name Value
-new OFF
create table t1 (t2 timestamp(2), t4 timestamp(4), t6 timestamp(6),
t8 timestamp(8), t10 timestamp(10), t12 timestamp(12),
t14 timestamp(14));
@@ -106,7 +103,6 @@ select * from t1;
t2 t4 t6 t8 t10 t12 t14
0000-00-00 00:00:00 0000-00-00 00:00:00 0000-00-00 00:00:00 0000-00-00 00:00:00 0000-00-00 00:00:00 0000-00-00 00:00:00 0000-00-00 00:00:00
1997-12-31 23:47:59 1997-12-31 23:47:59 1997-12-31 23:47:59 1997-12-31 23:47:59 1997-12-31 23:47:59 1997-12-31 23:47:59 1997-12-31 23:47:59
-set new=1;
select * from t1;
t2 t4 t6 t8 t10 t12 t14
0000-00-00 00:00:00 0000-00-00 00:00:00 0000-00-00 00:00:00 0000-00-00 00:00:00 0000-00-00 00:00:00 0000-00-00 00:00:00 0000-00-00 00:00:00
@@ -409,15 +405,20 @@ a b
NULL NULL
NULL 2003-01-01 00:00:00
drop table t1;
-create table t1 (ts timestamp(19));
-show create table t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `ts` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP
-) ENGINE=MyISAM DEFAULT CHARSET=latin1
-set TIMESTAMP=1000000000;
-insert into t1 values ();
+create table t1 (a bigint, b bigint);
+insert into t1 values (NULL, NULL), (20030101000000, 20030102000000);
+set timestamp=1000000019;
+alter table t1 modify a timestamp, modify b timestamp;
select * from t1;
-ts
-2001-09-09 04:46:40
+a b
+2001-09-09 04:46:59 2001-09-09 04:46:59
+2003-01-01 00:00:00 2003-01-02 00:00:00
+drop table t1;
+create table t1 (a char(2), t timestamp);
+insert into t1 values ('a', '2004-01-01 00:00:00'), ('a', '2004-01-01 01:00:00'),
+('b', '2004-02-01 00:00:00');
+select max(t) from t1 group by a;
+max(t)
+2004-01-01 01:00:00
+2004-02-01 00:00:00
drop table t1;
diff --git a/mysql-test/r/update.result b/mysql-test/r/update.result
index 0037fb9ea95..6d2e623a6fb 100644
--- a/mysql-test/r/update.result
+++ b/mysql-test/r/update.result
@@ -169,3 +169,40 @@ F1 F2 F3 cnt groupid
2 0 1 2 4
2 2 0 1 7
drop table t1;
+CREATE TABLE t1 (
+`colA` int(10) unsigned NOT NULL auto_increment,
+`colB` int(11) NOT NULL default '0',
+PRIMARY KEY (`colA`)
+);
+INSERT INTO t1 VALUES (4433,5424);
+CREATE TABLE t2 (
+`colC` int(10) unsigned NOT NULL default '0',
+`colA` int(10) unsigned NOT NULL default '0',
+`colD` int(10) unsigned NOT NULL default '0',
+`colE` int(10) unsigned NOT NULL default '0',
+`colF` int(10) unsigned NOT NULL default '0',
+PRIMARY KEY (`colC`,`colA`,`colD`,`colE`)
+);
+INSERT INTO t2 VALUES (3,4433,10005,495,500);
+INSERT INTO t2 VALUES (3,4433,10005,496,500);
+INSERT INTO t2 VALUES (3,4433,10009,494,500);
+INSERT INTO t2 VALUES (3,4433,10011,494,500);
+INSERT INTO t2 VALUES (3,4433,10005,497,500);
+INSERT INTO t2 VALUES (3,4433,10013,489,500);
+INSERT INTO t2 VALUES (3,4433,10005,494,500);
+INSERT INTO t2 VALUES (3,4433,10005,493,500);
+INSERT INTO t2 VALUES (3,4433,10005,492,500);
+UPDATE IGNORE t2,t1 set t2.colE = t2.colE + 1,colF=0 WHERE t1.colA = t2.colA AND (t1.colB & 4096) > 0 AND (colE + 1) < colF;
+SELECT * FROM t2;
+colC colA colD colE colF
+3 4433 10005 495 500
+3 4433 10005 496 500
+3 4433 10009 495 0
+3 4433 10011 495 0
+3 4433 10005 498 0
+3 4433 10013 490 0
+3 4433 10005 494 500
+3 4433 10005 493 500
+3 4433 10005 492 500
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/t/auto_increment.test b/mysql-test/t/auto_increment.test
index e5986e6755d..8e11a3d68a5 100644
--- a/mysql-test/t/auto_increment.test
+++ b/mysql-test/t/auto_increment.test
@@ -168,3 +168,41 @@ update t1 set a=NULL where b=13;
update t1 set a=500 where b=14;
select * from t1 order by b;
drop table t1;
+
+#
+# Test of behavior of ALTER TABLE when coulmn containing NULL or zeroes is
+# converted to AUTO_INCREMENT column
+#
+create table t1 (a bigint);
+insert into t1 values (1), (2), (3), (NULL), (NULL);
+alter table t1 modify a bigint not null auto_increment primary key;
+select * from t1;
+drop table t1;
+
+create table t1 (a bigint);
+insert into t1 values (1), (2), (3), (0), (0);
+alter table t1 modify a bigint not null auto_increment primary key;
+select * from t1;
+drop table t1;
+
+# We still should be able to preserve zero in NO_AUTO_VALUE_ON_ZERO mode
+create table t1 (a bigint);
+insert into t1 values (0), (1), (2), (3);
+set sql_mode=NO_AUTO_VALUE_ON_ZERO;
+alter table t1 modify a bigint not null auto_increment primary key;
+set sql_mode= '';
+select * from t1;
+drop table t1;
+
+# It also sensible to preserve zeroes if we are converting auto_increment
+# column to auto_increment column (or not touching it at all, which is more
+# common case probably)
+create table t1 (a int auto_increment primary key , b int null);
+set sql_mode=NO_AUTO_VALUE_ON_ZERO;
+insert into t1 values (0,1),(1,2),(2,3);
+select * from t1;
+set sql_mode= '';
+alter table t1 modify b varchar(255);
+insert into t1 values (0,4);
+select * from t1;
+drop table t1;
diff --git a/mysql-test/t/bdb.test b/mysql-test/t/bdb.test
index 86214ecd5a8..069ec758ba2 100644
--- a/mysql-test/t/bdb.test
+++ b/mysql-test/t/bdb.test
@@ -909,3 +909,23 @@ insert into t1 values (@a);
select a, length(a), char_length(a) from t1;
drop table t1;
SET NAMES latin1;
+
+#
+# Bug #5832 SELECT doesn't return records in some cases
+#
+CREATE TABLE t1 (
+ id int unsigned NOT NULL auto_increment,
+ list_id smallint unsigned NOT NULL,
+ term TEXT NOT NULL,
+ PRIMARY KEY(id),
+ INDEX(list_id, term(4))
+) ENGINE=BDB CHARSET=utf8;
+INSERT INTO t1 SET list_id = 1, term = "letterc";
+INSERT INTO t1 SET list_id = 1, term = "letterb";
+INSERT INTO t1 SET list_id = 1, term = "lettera";
+INSERT INTO t1 SET list_id = 1, term = "letterd";
+SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterc");
+SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterb");
+SELECT id FROM t1 WHERE (list_id = 1) AND (term = "lettera");
+SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterd");
+DROP TABLE t1;
diff --git a/mysql-test/t/ctype_latin1_de.test b/mysql-test/t/ctype_latin1_de.test
index e29e43496af..1c9576c1c56 100644
--- a/mysql-test/t/ctype_latin1_de.test
+++ b/mysql-test/t/ctype_latin1_de.test
@@ -86,6 +86,23 @@ select * from t1 where word like binary 0xDF;
select * from t1 where word like CAST(0xDF as CHAR);
drop table t1;
+#
+# Bug #5447 Select does not find records
+#
+CREATE TABLE t1 (
+ autor varchar(80) NOT NULL default '',
+ PRIMARY KEY (autor)
+);
+INSERT INTO t1 VALUES ('Powell, B.'),('Powell, Bud.'),('Powell, L. H.'),('Power, H.'),
+('Poynter, M. A. L. Lane'),('Poynting, J. H. und J. J. Thomson.'),('Pozzi, S(amuel-Jean).'),
+('Pozzi, Samuel-Jean.'),('Pozzo, A.'),('Pozzoli, Serge.');
+SELECT * FROM t1 WHERE autor LIKE 'Poz%' ORDER BY autor;
+DROP TABLE t1;
+
+#
+# Test of special character in german collation
+#
+
CREATE TABLE t1 (
s1 CHAR(5) CHARACTER SET latin1 COLLATE latin1_german2_ci
);
diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test
index 40709443d62..4a8eb63ed36 100644
--- a/mysql-test/t/ctype_utf8.test
+++ b/mysql-test/t/ctype_utf8.test
@@ -572,3 +572,23 @@ INSERT INTO t1 VALUES ('aaa','bbb');
SELECT length(subject) FROM t1;
SELECT length(subject) FROM t1 ORDER BY 1;
DROP TABLE t1;
+
+#
+# Bug #5832 SELECT doesn't return records in some cases
+#
+CREATE TABLE t1 (
+ id int unsigned NOT NULL auto_increment,
+ list_id smallint unsigned NOT NULL,
+ term TEXT NOT NULL,
+ PRIMARY KEY(id),
+ INDEX(list_id, term(4))
+) ENGINE=MYISAM CHARSET=utf8;
+INSERT INTO t1 SET list_id = 1, term = "letterc";
+INSERT INTO t1 SET list_id = 1, term = "letterb";
+INSERT INTO t1 SET list_id = 1, term = "lettera";
+INSERT INTO t1 SET list_id = 1, term = "letterd";
+SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterc");
+SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterb");
+SELECT id FROM t1 WHERE (list_id = 1) AND (term = "lettera");
+SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterd");
+DROP TABLE t1;
diff --git a/mysql-test/t/delete.test b/mysql-test/t/delete.test
index 56c8ce77627..5f60445d765 100644
--- a/mysql-test/t/delete.test
+++ b/mysql-test/t/delete.test
@@ -71,6 +71,16 @@ delete from t1 where 3 > 2;
select count(*) from t1;
drop table t1;
+#
+# Bug #5733: Table handler error with self-join multi-table DELETE
+#
+
+create table t1 (a int not null auto_increment primary key, b char(32));
+insert into t1 (b) values ('apple'), ('apple');
+select * from t1;
+delete t1 from t1, t1 as t2 where t1.b = t2.b and t1.a > t2.a;
+select * from t1;
+drop table t1;
#
# IGNORE option
diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test
index fbfd3ccdef1..64e3fe8929b 100644
--- a/mysql-test/t/derived.test
+++ b/mysql-test/t/derived.test
@@ -101,7 +101,7 @@ SELECT a.x FROM (SELECT 1 AS x) AS a HAVING a.x = 1;
#
# Connect without a database
create table t1 select 1 as a;
-connect (con1,localhost,mysqltest_1,,*NO-ONE*,$MASTER_MYPORT,master.sock);
+connect (con1,localhost,mysqltest_1,,*NO-ONE*,$MASTER_MYPORT,$MASTER_MYSOCK);
connection con1;
--error 1046
select 2 as a from (select * from t1) b;
diff --git a/mysql-test/t/flush_table.test b/mysql-test/t/flush_table.test
index 8bee94cf21f..afb30d21da7 100644
--- a/mysql-test/t/flush_table.test
+++ b/mysql-test/t/flush_table.test
@@ -16,7 +16,8 @@ drop table t1;
#
# In the following test FLUSH TABLES produces a deadlock
-# (hang forever) if the fix for bug#3565 is missing.
+# (hang forever) if the fix for BUG #3565 is missing.
+# And it shows that handler tables are re-opened after flush (BUG #4286).
#
create table t1(table_id char(20) primary key);
create table t2(table_id char(20) primary key);
@@ -31,28 +32,43 @@ handler a1 read first limit 9;
handler a2 read first limit 9;
handler t2 read first limit 9;
flush tables;
---error 1109;
handler a1 read first limit 9;
---error 1109;
handler a2 read first limit 9;
---error 1109;
handler t2 read first limit 9;
#
+--error 1066
handler t1 open as a1;
+--error 1066
handler t1 open as a2;
+--error 1066
handler t2 open;
handler a1 read first limit 9;
handler a2 read first limit 9;
handler t2 read first limit 9;
flush table t1;
---error 1109;
handler a1 read first limit 9;
---error 1109;
handler a2 read first limit 9;
handler t2 read first limit 9;
flush table t2;
---error 1109;
handler t2 close;
drop table t1;
drop table t2;
+#
+# The fix for BUG #4286 cannot restore the position after a flush.
+#
+create table t1(table_id char(20) primary key);
+insert into t1 values ('Record-01');
+insert into t1 values ('Record-02');
+insert into t1 values ('Record-03');
+insert into t1 values ('Record-04');
+insert into t1 values ('Record-05');
+handler t1 open;
+handler t1 read first limit 1;
+handler t1 read next limit 1;
+handler t1 read next limit 1;
+flush table t1;
+handler t1 read next limit 1;
+handler t1 read next limit 1;
+handler t1 close;
+drop table t1;
diff --git a/mysql-test/t/func_if.test b/mysql-test/t/func_if.test
index 7048d188604..693773b18c8 100644
--- a/mysql-test/t/func_if.test
+++ b/mysql-test/t/func_if.test
@@ -56,3 +56,7 @@ insert t1 values (1),(2);
select if(1>2,a,avg(a)) from t1;
drop table t1;
+#
+# Bug #5595 NULLIF() IS NULL returns false if NULLIF() returns NULL
+#
+SELECT NULLIF(5,5) IS NULL, NULLIF(5,5) IS NOT NULL;
diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test
index e7852df40b3..3eab694ee05 100644
--- a/mysql-test/t/func_str.test
+++ b/mysql-test/t/func_str.test
@@ -182,6 +182,13 @@ select a, quote(a), isnull(quote(a)), quote(a) is null, ifnull(quote(a), 'n') fr
drop table t1;
#
+# Bug #5498: TRIM fails with LEADING or TRAILING if remstr = str
+#
+
+select trim(trailing 'foo' from 'foo');
+select trim(leading 'foo' from 'foo');
+
+#
# Test collation and coercibility
#
diff --git a/mysql-test/t/handler.test b/mysql-test/t/handler.test
index 685f438712c..3de8e8ae784 100644
--- a/mysql-test/t/handler.test
+++ b/mysql-test/t/handler.test
@@ -138,3 +138,211 @@ handler t1 read a=(1) where b=1;
handler t1 close;
drop table t1;
+#
+# Check if two database names beginning the same are seen as different.
+#
+# This database begins like the usual 'test' database.
+#
+--disable_warnings
+drop database if exists test_test;
+--enable_warnings
+create database test_test;
+use test_test;
+create table t1(table_id char(20) primary key);
+insert into t1 values ('test_test.t1');
+insert into t1 values ('');
+handler t1 open;
+handler t1 read first limit 9;
+create table t2(table_id char(20) primary key);
+insert into t2 values ('test_test.t2');
+insert into t2 values ('');
+handler t2 open;
+handler t2 read first limit 9;
+#
+# This is the usual 'test' database.
+#
+use test;
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+create table t1(table_id char(20) primary key);
+insert into t1 values ('test.t1');
+insert into t1 values ('');
+--error 1066
+handler t1 open;
+#
+# Check accesibility of all the tables.
+#
+use test;
+--error 1064
+handler test.t1 read first limit 9;
+--error 1064
+handler test_test.t1 read first limit 9;
+handler t1 read first limit 9;
+--error 1064
+handler test_test.t2 read first limit 9;
+handler t2 read first limit 9;
+
+#
+# Cleanup.
+#
+
+--error 1064
+handler test_test.t1 close;
+handler t1 close;
+drop table test_test.t1;
+--error 1064
+handler test_test.t2 close;
+handler t2 close;
+drop table test_test.t2;
+drop database test_test;
+
+#
+use test;
+--error 1064
+handler test.t1 close;
+--error 1109
+handler t1 close;
+drop table test.t1;
+
+#
+# BUG#4335
+#
+--disable_warnings
+drop database if exists test_test;
+drop table if exists t1;
+drop table if exists t2;
+drop table if exists t3;
+--enable_warnings
+create database test_test;
+use test_test;
+create table t1 (c1 char(20));
+insert into t1 values ('test_test.t1');
+create table t3 (c1 char(20));
+insert into t3 values ('test_test.t3');
+handler t1 open;
+handler t1 read first limit 9;
+handler t1 open h1;
+handler h1 read first limit 9;
+use test;
+create table t1 (c1 char(20));
+create table t2 (c1 char(20));
+create table t3 (c1 char(20));
+insert into t1 values ('t1');
+insert into t2 values ('t2');
+insert into t3 values ('t3');
+--error 1066
+handler t1 open;
+--error 1066
+handler t2 open t1;
+--error 1066
+handler t3 open t1;
+handler t1 read first limit 9;
+--error 1064
+handler test.t1 close;
+--error 1066
+handler test.t1 open h1;
+--error 1066
+handler test_test.t1 open h1;
+handler test_test.t3 open h3;
+handler test.t1 open h2;
+handler t1 read first limit 9;
+handler h1 read first limit 9;
+handler h2 read first limit 9;
+handler h3 read first limit 9;
+handler h2 read first limit 9;
+--error 1064
+handler test.h1 close;
+handler t1 close;
+handler h1 close;
+handler h2 close;
+--error 1109
+handler t1 read first limit 9;
+--error 1109
+handler h1 read first limit 9;
+--error 1109
+handler h2 read first limit 9;
+handler h3 read first limit 9;
+handler h3 read first limit 9;
+use test_test;
+handler h3 read first limit 9;
+--error 1064
+handler test.h3 read first limit 9;
+handler h3 close;
+use test;
+drop table t3;
+drop table t2;
+drop table t1;
+drop database test_test;
+
+#
+# Test if fix for BUG#4286 correctly closes handler tables.
+#
+create table t1 (c1 char(20));
+insert into t1 values ("t1");
+handler t1 open as h1;
+handler h1 read first limit 9;
+create table t2 (c1 char(20));
+insert into t2 values ("t2");
+handler t2 open as h2;
+handler h2 read first limit 9;
+create table t3 (c1 char(20));
+insert into t3 values ("t3");
+handler t3 open as h3;
+handler h3 read first limit 9;
+create table t4 (c1 char(20));
+insert into t4 values ("t4");
+handler t4 open as h4;
+handler h4 read first limit 9;
+create table t5 (c1 char(20));
+insert into t5 values ("t5");
+handler t5 open as h5;
+handler h5 read first limit 9;
+# close first
+alter table t1 engine=MyISAM;
+--error 1109;
+handler h1 read first limit 9;
+handler h2 read first limit 9;
+handler h3 read first limit 9;
+handler h4 read first limit 9;
+handler h5 read first limit 9;
+# close last
+alter table t5 engine=MyISAM;
+--error 1109;
+handler h1 read first limit 9;
+handler h2 read first limit 9;
+handler h3 read first limit 9;
+handler h4 read first limit 9;
+--error 1109;
+handler h5 read first limit 9;
+# close middle
+alter table t3 engine=MyISAM;
+--error 1109;
+handler h1 read first limit 9;
+handler h2 read first limit 9;
+--error 1109;
+handler h3 read first limit 9;
+handler h4 read first limit 9;
+--error 1109;
+handler h5 read first limit 9;
+handler h2 close;
+handler h4 close;
+# close all depending handler tables
+handler t1 open as h1_1;
+handler t1 open as h1_2;
+handler t1 open as h1_3;
+handler h1_1 read first limit 9;
+handler h1_2 read first limit 9;
+handler h1_3 read first limit 9;
+alter table t1 engine=MyISAM;
+--error 1109;
+handler h1_1 read first limit 9;
+--error 1109;
+handler h1_2 read first limit 9;
+--error 1109;
+handler h1_3 read first limit 9;
+drop table t1;
+drop table t2;
+drop table t3;
+drop table t4;
+drop table t5;
diff --git a/mysql-test/t/lock_multi.test b/mysql-test/t/lock_multi.test
index fa095275182..cbda47ac864 100644
--- a/mysql-test/t/lock_multi.test
+++ b/mysql-test/t/lock_multi.test
@@ -53,6 +53,30 @@ reap;
drop table t1;
#
+# Test problem when using locks with multi-updates
+# It should not block when multi-update is reading on a read-locked table
+#
+
+connection locker;
+create table t1 (a int, b int);
+create table t2 (c int, d int);
+insert into t1 values(1,1);
+insert into t1 values(2,2);
+insert into t2 values(1,2);
+lock table t1 read;
+connection writer;
+--sleep 2
+send update t1,t2 set c=a where b=d;
+connection reader;
+--sleep 2
+select c from t2;
+connection writer;
+reap;
+connection locker;
+drop table t1;
+drop table t2;
+
+#
# Test problem when using locks on many tables and droping a table that
# is to-be-locked by another thread
#
diff --git a/mysql-test/t/multi_update.test b/mysql-test/t/multi_update.test
index 40e742679f8..e2aebd014f8 100644
--- a/mysql-test/t/multi_update.test
+++ b/mysql-test/t/multi_update.test
@@ -5,6 +5,11 @@
--disable_warnings
drop table if exists t1,t2,t3;
drop database if exists mysqltest;
+--error 0,1141
+revoke all privileges on mysqltest.t1 from mysqltest_1@localhost;
+--error 0,1141
+revoke all privileges on mysqltest.* from mysqltest_1@localhost;
+delete from mysql.user where user=_binary'mysqltest_1';
--enable_warnings
create table t1(id1 int not null auto_increment primary key, t char(12));
@@ -154,8 +159,6 @@ LOCK TABLES t1 write, t2 read;
DELETE t1.*, t2.* FROM t1,t2 where t1.n=t2.n;
--error 1099
UPDATE t1,t2 SET t1.d=t2.d,t2.d=30 WHERE t1.n=t2.n;
-# The following should be fixed to not give an error
---error 1099
UPDATE t1,t2 SET t1.d=t2.d WHERE t1.n=t2.n;
unlock tables;
LOCK TABLES t1 write, t2 write;
@@ -385,10 +388,10 @@ select * from t2;
drop table t1, t2;
#
-# prevelege chexk for multiupdate with other tables
+# privilege check for multiupdate with other tables
#
-connect (root,localhost,root,,test,$MASTER_MYPORT,master.sock);
+connect (root,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK);
connection root;
--disable_warnings
create database mysqltest;
@@ -398,7 +401,7 @@ create table mysqltest.t2 (a int, b int, primary key (a));
create table mysqltest.t3 (a int, b int, primary key (a));
grant select on mysqltest.* to mysqltest_1@localhost;
grant update on mysqltest.t1 to mysqltest_1@localhost;
-connect (user1,localhost,mysqltest_1,,mysqltest,$MASTER_MYPORT,master.sock);
+connect (user1,localhost,mysqltest_1,,mysqltest,$MASTER_MYPORT,$MASTER_MYSOCK);
connection user1;
update t1, t2 set t1.b=1 where t1.a=t2.a;
update t1, t2 set t1.b=(select t3.b from t3 where t1.a=t3.a) where t1.a=t2.a;
diff --git a/mysql-test/t/ndb_subquery.test b/mysql-test/t/ndb_subquery.test
new file mode 100644
index 00000000000..cebc1920eaa
--- /dev/null
+++ b/mysql-test/t/ndb_subquery.test
@@ -0,0 +1,38 @@
+-- source include/have_ndb.inc
+
+--disable_warnings
+drop table if exists t1;
+drop table if exists t2;
+--enable_warnings
+
+##########
+# bug#5367
+create table t1 (p int not null primary key, u int not null, o int not null,
+unique (u), key(o)) engine=ndb;
+
+create table t2 (p int not null primary key, u int not null, o int not null,
+unique (u), key(o)) engine=ndb;
+
+insert into t1 values (1,1,1),(2,2,2),(3,3,3);
+insert into t2 values (1,1,1),(2,2,2),(3,3,3), (4,4,4), (5,5,5);
+
+# Use pk
+explain select * from t2 where p NOT IN (select p from t1);
+select * from t2 where p NOT IN (select p from t1) order by p;
+
+# Use unique index
+explain select * from t2 where p NOT IN (select u from t1);
+select * from t2 where p NOT IN (select u from t1) order by p;
+
+# Use ordered index
+explain select * from t2 where p NOT IN (select o from t1);
+select * from t2 where p NOT IN (select o from t1) order by p;
+
+# Use scan
+explain select * from t2 where p NOT IN (select p+0 from t1);
+select * from t2 where p NOT IN (select p+0 from t1) order by p;
+
+drop table t1;
+drop table t2;
+# bug#5367
+##########
diff --git a/mysql-test/t/ps_7ndb.test b/mysql-test/t/ps_7ndb.test
index 848eac0080a..af669a26400 100644
--- a/mysql-test/t/ps_7ndb.test
+++ b/mysql-test/t/ps_7ndb.test
@@ -55,7 +55,7 @@ select '------ delete tests ------' as test_sequence ;
## delete without parameter
prepare stmt1 from 'delete from t1 where a=2' ;
execute stmt1;
-select a,b from t1 where a=2;
+select a,b from t1 where a=2 order by b;
# delete with row not found
execute stmt1;
@@ -177,7 +177,7 @@ prepare stmt1 from 'update t1 set a=? where b=?
--enable_info
execute stmt1 using @arg04, @arg01, @arg02, @arg03, @arg00 ;
--disable_info
-select a,b from t1 order by a;
+select a,b from t1 order by a ;
drop table t2 ;
## update with parameters in limit
@@ -270,7 +270,7 @@ set @arg02=82 ;
set @arg03='8-2' ;
prepare stmt1 from 'insert into t1 values(?,?),(?,?)';
execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
-select a,b from t1 where a in (@arg00,@arg02) ;
+select a,b from t1 where a in (@arg00,@arg02) order by a ;
## insert with two parameter in the set part
set @arg00=9 ;
diff --git a/mysql-test/t/range.test b/mysql-test/t/range.test
index 61886221fcf..cd6620f7126 100644
--- a/mysql-test/t/range.test
+++ b/mysql-test/t/range.test
@@ -423,6 +423,9 @@ select count(*) from t1 where x=0;
select count(*) from t1 where x<0;
select count(*) from t1 where x < -16;
select count(*) from t1 where x = -16;
+# The following query returns wrong value because the range optimizer can't
+# handle search on a signed value for an unsigned parameter. This will be fixed in
+# 5.0
select count(*) from t1 where x > -16;
select count(*) from t1 where x = 18446744073709551601;
diff --git a/mysql-test/t/rename.test b/mysql-test/t/rename.test
index e6dc6ce9456..497ff721c99 100644
--- a/mysql-test/t/rename.test
+++ b/mysql-test/t/rename.test
@@ -5,7 +5,7 @@
--disable_warnings
drop table if exists t0,t1,t2,t3,t4;
# Clear up from other tests (to ensure that SHOW TABLES below is right)
-drop table if exists t0,t5,t6,t7,t8,t9;
+drop table if exists t0,t5,t6,t7,t8,t9,t1_1,t1_2,t9_1,t9_2;
--enable_warnings
create table t0 SELECT 1,"table 1";
diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test
index 4490f97765b..c260c7777e2 100644
--- a/mysql-test/t/select.test
+++ b/mysql-test/t/select.test
@@ -8,6 +8,8 @@
--disable_warnings
drop table if exists t1,t2,t3,t4;
+# The following may be left from older tests
+drop table if exists t1_1,t1_2,t9_1,t9_2;
--enable_warnings
CREATE TABLE t1 (
diff --git a/mysql-test/t/show_check.test b/mysql-test/t/show_check.test
index 759ed7d22b3..681127eab5e 100644
--- a/mysql-test/t/show_check.test
+++ b/mysql-test/t/show_check.test
@@ -5,6 +5,10 @@
--disable_warnings
drop table if exists t1,t2;
drop database if exists mysqltest;
+
+delete from mysql.user where user='mysqltest_1' || user='mysqltest_2' || user='mysqltest_3';
+delete from mysql.db where user='mysqltest_1' || user='mysqltest_2' || user='mysqltest_3';
+flush privileges;
--enable_warnings
create table t1 (a int not null primary key, b int not null,c int not null, key(b,c));
diff --git a/mysql-test/t/type_timestamp.test b/mysql-test/t/type_timestamp.test
index 3f0b41d7221..a8a0cf8703c 100644
--- a/mysql-test/t/type_timestamp.test
+++ b/mysql-test/t/type_timestamp.test
@@ -62,7 +62,6 @@ INSERT INTO t1 VALUES ("2030-01-01","2030-01-01 00:00:00",20300101000000);
SELECT * FROM t1;
drop table t1;
-show variables like 'new';
create table t1 (t2 timestamp(2), t4 timestamp(4), t6 timestamp(6),
t8 timestamp(8), t10 timestamp(10), t12 timestamp(12),
t14 timestamp(14));
@@ -71,7 +70,6 @@ insert t1 values (0,0,0,0,0,0,0),
"1997-12-31 23:47:59", "1997-12-31 23:47:59", "1997-12-31 23:47:59",
"1997-12-31 23:47:59");
select * from t1;
-set new=1;
select * from t1;
drop table t1;
@@ -258,6 +256,9 @@ select * from t1;
drop table t1;
# It is also OK to specify NULL as default explicitly for such fields.
+# This is also a test for bug #2464, DEFAULT keyword in INSERT statement
+# should return default value for column.
+
create table t1 (a timestamp null default null, b timestamp null default '2003-01-01 00:00:00');
show create table t1;
insert into t1 values (NULL, NULL);
@@ -266,12 +267,22 @@ select * from t1;
drop table t1;
#
-# Test for bug #4491, TIMESTAMP(19) should be possible to create and not
-# only read in 4.0
+# Let us test behavior of ALTER TABLE when it converts columns
+# containing NULL to TIMESTAMP columns.
#
-create table t1 (ts timestamp(19));
-show create table t1;
-set TIMESTAMP=1000000000;
-insert into t1 values ();
+create table t1 (a bigint, b bigint);
+insert into t1 values (NULL, NULL), (20030101000000, 20030102000000);
+set timestamp=1000000019;
+alter table t1 modify a timestamp, modify b timestamp;
select * from t1;
drop table t1;
+
+#
+# Test for bug #4131, TIMESTAMP columns missing minutes and seconds when
+# using GROUP BY in @@new=1 mode.
+#
+create table t1 (a char(2), t timestamp);
+insert into t1 values ('a', '2004-01-01 00:00:00'), ('a', '2004-01-01 01:00:00'),
+ ('b', '2004-02-01 00:00:00');
+select max(t) from t1 group by a;
+drop table t1;
diff --git a/mysql-test/t/update.test b/mysql-test/t/update.test
index 6ca75cf0c26..aeefa3c33f5 100644
--- a/mysql-test/t/update.test
+++ b/mysql-test/t/update.test
@@ -128,3 +128,36 @@ insert into t1 (F1,F2,F3,cnt,groupid) values ('0','0','0',1,6),
delete from m1 using t1 m1,t1 m2 where m1.groupid=m2.groupid and (m1.cnt < m2.cnt or m1.cnt=m2.cnt and m1.F3>m2.F3);
select * from t1;
drop table t1;
+
+#
+# Bug#5553 - Multi table UPDATE IGNORE fails on duplicate keys
+#
+
+CREATE TABLE t1 (
+ `colA` int(10) unsigned NOT NULL auto_increment,
+ `colB` int(11) NOT NULL default '0',
+ PRIMARY KEY (`colA`)
+);
+INSERT INTO t1 VALUES (4433,5424);
+CREATE TABLE t2 (
+ `colC` int(10) unsigned NOT NULL default '0',
+ `colA` int(10) unsigned NOT NULL default '0',
+ `colD` int(10) unsigned NOT NULL default '0',
+ `colE` int(10) unsigned NOT NULL default '0',
+ `colF` int(10) unsigned NOT NULL default '0',
+ PRIMARY KEY (`colC`,`colA`,`colD`,`colE`)
+);
+INSERT INTO t2 VALUES (3,4433,10005,495,500);
+INSERT INTO t2 VALUES (3,4433,10005,496,500);
+INSERT INTO t2 VALUES (3,4433,10009,494,500);
+INSERT INTO t2 VALUES (3,4433,10011,494,500);
+INSERT INTO t2 VALUES (3,4433,10005,497,500);
+INSERT INTO t2 VALUES (3,4433,10013,489,500);
+INSERT INTO t2 VALUES (3,4433,10005,494,500);
+INSERT INTO t2 VALUES (3,4433,10005,493,500);
+INSERT INTO t2 VALUES (3,4433,10005,492,500);
+UPDATE IGNORE t2,t1 set t2.colE = t2.colE + 1,colF=0 WHERE t1.colA = t2.colA AND (t1.colB & 4096) > 0 AND (colE + 1) < colF;
+SELECT * FROM t2;
+DROP TABLE t1;
+DROP TABLE t2;
+
diff --git a/mysys/errors.c b/mysys/errors.c
index 255b6893c73..5401c2b3cc6 100644
--- a/mysys/errors.c
+++ b/mysys/errors.c
@@ -41,7 +41,7 @@ const char * NEAR globerrs[GLOBERRS]=
"Can't change dir to '%s' (Errcode: %d)",
"Warning: '%s' had %d links",
"%d files and %d streams is left open\n",
- "Disk is full writing '%s'. Waiting for someone to free space...",
+ "Disk is full writing '%s' (Errcode: %d). Waiting for someone to free space... Retry in %d secs",
"Can't create directory '%s' (Errcode: %d)",
"Character set '%s' is not a compiled character set and is not specified in the '%s' file",
"Out of resources when opening file '%s' (Errcode: %d)",
diff --git a/mysys/my_fstream.c b/mysys/my_fstream.c
index 00fe5c7a009..5b17e3ff51c 100644
--- a/mysys/my_fstream.c
+++ b/mysys/my_fstream.c
@@ -114,13 +114,15 @@ uint my_fwrite(FILE *stream, const byte *Buffer, uint Count, myf MyFlags)
if (my_thread_var->abort)
MyFlags&= ~ MY_WAIT_IF_FULL; /* End if aborted by user */
#endif
- if (errno == ENOSPC && (MyFlags & MY_WAIT_IF_FULL))
+ if ((errno == ENOSPC || errno == EDQUOT) &&
+ (MyFlags & MY_WAIT_IF_FULL))
{
- if (!(errors++ % MY_WAIT_GIVE_USER_A_MESSAGE))
- my_error(EE_DISK_FULL,MYF(ME_BELL | ME_NOREFRESH));
- sleep(MY_WAIT_FOR_USER_TO_FIX_PANIC);
- VOID(my_fseek(stream,seekptr,MY_SEEK_SET,MYF(0)));
- continue;
+ if (!(errors++ % MY_WAIT_GIVE_USER_A_MESSAGE))
+ my_error(EE_DISK_FULL,MYF(ME_BELL | ME_NOREFRESH),
+ "[stream]",my_errno,MY_WAIT_FOR_USER_TO_FIX_PANIC);
+ VOID(sleep(MY_WAIT_FOR_USER_TO_FIX_PANIC));
+ VOID(my_fseek(stream,seekptr,MY_SEEK_SET,MYF(0)));
+ continue;
}
#endif
if (ferror(stream) || (MyFlags & (MY_NABP | MY_FNABP)))
diff --git a/mysys/my_pread.c b/mysys/my_pread.c
index 6a55a3cd8de..3d02e368720 100644
--- a/mysys/my_pread.c
+++ b/mysys/my_pread.c
@@ -115,11 +115,12 @@ uint my_pwrite(int Filedes, const byte *Buffer, uint Count, my_off_t offset,
if (my_thread_var->abort)
MyFlags&= ~ MY_WAIT_IF_FULL; /* End if aborted by user */
#endif
- if (my_errno == ENOSPC && (MyFlags & MY_WAIT_IF_FULL))
+ if ((my_errno == ENOSPC || my_errno == EDQUOT) &&
+ (MyFlags & MY_WAIT_IF_FULL))
{
if (!(errors++ % MY_WAIT_GIVE_USER_A_MESSAGE))
my_error(EE_DISK_FULL,MYF(ME_BELL | ME_NOREFRESH),
- my_filename(Filedes));
+ my_filename(Filedes),my_errno,MY_WAIT_FOR_USER_TO_FIX_PANIC);
VOID(sleep(MY_WAIT_FOR_USER_TO_FIX_PANIC));
continue;
}
@@ -131,7 +132,7 @@ uint my_pwrite(int Filedes, const byte *Buffer, uint Count, my_off_t offset,
{
if (MyFlags & (MY_WME | MY_FAE | MY_FNABP))
{
- my_error(EE_WRITE, MYF(ME_BELL+ME_WAITTANG),
+ my_error(EE_WRITE, MYF(ME_BELL | ME_WAITTANG),
my_filename(Filedes),my_errno);
}
DBUG_RETURN(MY_FILE_ERROR); /* Error on read */
@@ -142,4 +143,4 @@ uint my_pwrite(int Filedes, const byte *Buffer, uint Count, my_off_t offset,
if (MyFlags & (MY_NABP | MY_FNABP))
DBUG_RETURN(0); /* Want only errors */
DBUG_RETURN(writenbytes+written); /* purecov: inspected */
-} /* my_write */
+} /* my_pwrite */
diff --git a/mysys/my_write.c b/mysys/my_write.c
index 37d885f04cd..2df3a31e774 100644
--- a/mysys/my_write.c
+++ b/mysys/my_write.c
@@ -48,12 +48,13 @@ uint my_write(int Filedes, const byte *Buffer, uint Count, myf MyFlags)
if (my_thread_var->abort)
MyFlags&= ~ MY_WAIT_IF_FULL; /* End if aborted by user */
#endif
- if (my_errno == ENOSPC && (MyFlags & MY_WAIT_IF_FULL) &&
+ if ((my_errno == ENOSPC || my_errno == EDQUOT) &&
+ (MyFlags & MY_WAIT_IF_FULL) &&
(uint) writenbytes != (uint) -1)
{
if (!(errors++ % MY_WAIT_GIVE_USER_A_MESSAGE))
my_error(EE_DISK_FULL,MYF(ME_BELL | ME_NOREFRESH),
- my_filename(Filedes));
+ my_filename(Filedes),my_errno,MY_WAIT_FOR_USER_TO_FIX_PANIC);
VOID(sleep(MY_WAIT_FOR_USER_TO_FIX_PANIC));
continue;
}
diff --git a/mysys/mysys_priv.h b/mysys/mysys_priv.h
index 6abadd48aeb..89a6d8aa2a7 100644
--- a/mysys/mysys_priv.h
+++ b/mysys/mysys_priv.h
@@ -34,3 +34,10 @@ extern pthread_mutex_t THR_LOCK_charset;
#include <my_no_pthread.h>
#endif
+/*
+ EDQUOT is used only in 3 C files only in mysys/. If it does not exist on
+ system, we set it to some value which can never happen.
+*/
+#ifndef EDQUOT
+#define EDQUOT (-1)
+#endif
diff --git a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
index 5b5578cb579..d270c6acc61 100644
--- a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
+++ b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
@@ -1249,7 +1249,8 @@ void Dbtc::execTCRELEASEREQ(Signal* signal)
jam();
signal->theData[0] = tuserpointer;
signal->theData[1] = ZINVALID_CONNECTION;
- sendSignal(tapiBlockref, GSN_TCRELEASEREF, signal, 2, JBB);
+ signal->theData[2] = __LINE__;
+ sendSignal(tapiBlockref, GSN_TCRELEASEREF, signal, 3, JBB);
return;
} else {
jam();
@@ -1262,7 +1263,9 @@ void Dbtc::execTCRELEASEREQ(Signal* signal)
sendSignal(tapiBlockref, GSN_TCRELEASECONF, signal, 1, JBB);
} else {
if (tapiBlockref == apiConnectptr.p->ndbapiBlockref) {
- if (apiConnectptr.p->apiConnectstate == CS_CONNECTED) {
+ if (apiConnectptr.p->apiConnectstate == CS_CONNECTED ||
+ (apiConnectptr.p->apiConnectstate == CS_ABORTING &&
+ apiConnectptr.p->abortState == AS_IDLE)){
jam(); /* JUST REPLY OK */
releaseApiCon(signal, apiConnectptr.i);
signal->theData[0] = tuserpointer;
@@ -1272,14 +1275,19 @@ void Dbtc::execTCRELEASEREQ(Signal* signal)
jam();
signal->theData[0] = tuserpointer;
signal->theData[1] = ZINVALID_CONNECTION;
+ signal->theData[2] = __LINE__;
+ signal->theData[3] = apiConnectptr.p->apiConnectstate;
sendSignal(tapiBlockref,
- GSN_TCRELEASEREF, signal, 2, JBB);
+ GSN_TCRELEASEREF, signal, 4, JBB);
}
} else {
jam();
signal->theData[0] = tuserpointer;
signal->theData[1] = ZINVALID_CONNECTION;
- sendSignal(tapiBlockref, GSN_TCRELEASEREF, signal, 2, JBB);
+ signal->theData[2] = __LINE__;
+ signal->theData[3] = tapiBlockref;
+ signal->theData[4] = apiConnectptr.p->ndbapiBlockref;
+ sendSignal(tapiBlockref, GSN_TCRELEASEREF, signal, 5, JBB);
}//if
}//if
}//Dbtc::execTCRELEASEREQ()
@@ -11359,6 +11367,7 @@ void Dbtc::execTCKEYCONF(Signal* signal)
Uint32 Ttcindxrec = regApiPtr->tcindxrec;
// Copy reply from TcKeyConf
+ ndbassert(regApiPtr->noIndexOp);
regApiPtr->noIndexOp--; // Decrease count
regApiPtr->tcIndxSendArray[Ttcindxrec] = indexOp->tcIndxReq.senderData;
regApiPtr->tcIndxSendArray[Ttcindxrec + 1] =
@@ -11417,6 +11426,12 @@ void Dbtc::execTCKEYREF(Signal* signal)
abortErrorLab(signal);
break;
}
+ /**
+ * Increase count as it will be decreased below...
+ * (and the code is written to handle failing lookup on "real" table
+ * not lookup on index table)
+ */
+ regApiPtr->noIndexOp++;
// else continue
}
case(IOS_INDEX_OPERATION): {
@@ -11426,6 +11441,7 @@ void Dbtc::execTCKEYREF(Signal* signal)
TcIndxReq * const tcIndxReq = &indexOp->tcIndxReq;
TcIndxRef * const tcIndxRef = (TcIndxRef *)signal->getDataPtrSend();
+ ndbassert(regApiPtr->noIndexOp);
regApiPtr->noIndexOp--; // Decrease count
tcIndxRef->connectPtr = tcIndxReq->senderData;
tcIndxRef->transId[0] = tcKeyRef->transId[0];
diff --git a/ndb/test/run-test/atrt-mysql-test-run b/ndb/test/run-test/atrt-mysql-test-run
index 7657140d0fa..dd7b709bd06 100755
--- a/ndb/test/run-test/atrt-mysql-test-run
+++ b/ndb/test/run-test/atrt-mysql-test-run
@@ -3,7 +3,7 @@
set -x
p=`pwd`
cd $MYSQL_BASE_DIR/mysql-test
-./mysql-test-run --with-ndbcluster --ndbconnectstring=$NDB_CONNECTSTRING $* | tee $p/output.txt
+./mysql-test-run --with-ndbcluster --ndb-connectstring=$NDB_CONNECTSTRING $* | tee $p/output.txt
f=`grep -c fail $p/output.txt`
o=`grep -c pass $p/output.txt`
diff --git a/scripts/mysqlhotcopy.sh b/scripts/mysqlhotcopy.sh
index fe93aa5a1bc..b8494727975 100644
--- a/scripts/mysqlhotcopy.sh
+++ b/scripts/mysqlhotcopy.sh
@@ -77,7 +77,7 @@ Usage: $0 db_name[./table_regex/] [new_db_name | directory]
--record_log_pos=# record slave and master status in specified db.table
--chroot=# base directory of chroot jail in which mysqld operates
- Try \'perldoc $0 for more complete documentation\'
+ Try \'perldoc $0\' for more complete documentation
_OPTIONS
sub usage {
diff --git a/sql/examples/ha_archive.cc b/sql/examples/ha_archive.cc
index 55b6455f7ad..c7d08772109 100644
--- a/sql/examples/ha_archive.cc
+++ b/sql/examples/ha_archive.cc
@@ -42,7 +42,18 @@
handle bulk inserts as well (that is if someone was trying to read at
the same time since we would want to flush).
- No attempts at durability are made. You can corrupt your data.
+ A "meta" file is kept. All this file does is contain information on
+ the number of rows.
+
+ No attempts at durability are made. You can corrupt your data. A repair
+ method was added to repair the meta file that stores row information,
+ but if your data file gets corrupted I haven't solved that. I could
+ create a repair that would solve this, but do you want to take a
+ chance of loosing your data?
+
+ Locks are row level, and you will get a consistant read. Transactions
+ will be added later (they are not that hard to add at this
+ stage).
For performance as far as table scans go it is quite fast. I don't have
good numbers but locally it has out performed both Innodb and MyISAM. For
@@ -71,14 +82,35 @@
Add truncate table command.
Implement versioning, should be easy.
Allow for errors, find a way to mark bad rows.
- See if during an optimize you can make the table smaller.
Talk to the gzip guys, come up with a writable format so that updates are doable
without switching to a block method.
Add optional feature so that rows can be flushed at interval (which will cause less
- compression but may speed up ordered searches).
+ compression but may speed up ordered searches).
+ Checkpoint the meta file to allow for faster rebuilds.
+ Dirty open (right now the meta file is repaired if a crash occured).
+ Transactions.
+ Option to allow for dirty reads, this would lower the sync calls, which would make
+ inserts a lot faster, but would mean highly arbitrary reads.
-Brian
*/
+/*
+ Notes on file formats.
+ The Meta file is layed out as:
+ check - Just an int of 254 to make sure that the the file we are opening was
+ never corrupted.
+ version - The current version of the file format.
+ rows - This is an unsigned long long which is the number of rows in the data
+ file.
+ check point - Reserved for future use
+ dirty - Status of the file, whether or not its values are the latest. This flag
+ is what causes a repair to occur
+
+ The data file:
+ check - Just an int of 254 to make sure that the the file we are opening was
+ never corrupted.
+ version - The current version of the file format.
+ data - The data is stored in a "row +blobs" format.
/* Variables for archive share methods */
pthread_mutex_t archive_mutex;
@@ -86,8 +118,18 @@ static HASH archive_open_tables;
static int archive_init= 0;
/* The file extension */
-#define ARZ ".ARZ"
-#define ARN ".ARN"
+#define ARZ ".ARZ" // The data file
+#define ARN ".ARN" // Files used during an optimize call
+#define ARM ".ARM" // Meta file
+/*
+ uchar + uchar + ulonglong + ulonglong + uchar
+*/
+#define META_BUFFER_SIZE 19 // Size of the data used in the meta file
+/*
+ uchar + uchar
+*/
+#define DATA_BUFFER_SIZE 2 // Size of the data used in the data file
+#define ARCHIVE_CHECK_HEADER 254 // The number we use to determine corruption
/*
Used for hash table that tracks open tables.
@@ -99,14 +141,130 @@ static byte* archive_get_key(ARCHIVE_SHARE *share,uint *length,
return (byte*) share->table_name;
}
+/*
+ This method reads the header of a datafile and returns whether or not it was successful.
+*/
+int ha_archive::read_data_header(gzFile file_to_read)
+{
+ uchar data_buffer[DATA_BUFFER_SIZE];
+ DBUG_ENTER("ha_archive::read_data_header");
+
+ if (gzrewind(file_to_read) == -1)
+ DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
+
+ if (gzread(file_to_read, data_buffer, DATA_BUFFER_SIZE) != DATA_BUFFER_SIZE)
+ DBUG_RETURN(errno ? errno : -1);
+
+ DBUG_PRINT("ha_archive::read_data_header", ("Check %u", data_buffer[0]));
+ DBUG_PRINT("ha_archive::read_data_header", ("Version %u", data_buffer[1]));
+
+ if ((data_buffer[0] != (uchar)ARCHIVE_CHECK_HEADER) &&
+ (data_buffer[1] != (uchar)ARCHIVE_VERSION))
+ DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
+
+ DBUG_RETURN(0);
+}
/*
- Example of simple lock controls.
- See ha_example.cc for a description.
+ This method writes out the header of a datafile and returns whether or not it was successful.
+*/
+int ha_archive::write_data_header(gzFile file_to_write)
+{
+ uchar data_buffer[DATA_BUFFER_SIZE];
+ DBUG_ENTER("ha_archive::write_data_header");
+
+ data_buffer[0]= (uchar)ARCHIVE_CHECK_HEADER;
+ data_buffer[1]= (uchar)ARCHIVE_VERSION;
+
+ if (gzwrite(file_to_write, &data_buffer, DATA_BUFFER_SIZE) !=
+ sizeof(DATA_BUFFER_SIZE))
+ goto error;
+ DBUG_PRINT("ha_archive::write_data_header", ("Check %u", (uint)data_buffer[0]));
+ DBUG_PRINT("ha_archive::write_data_header", ("Version %u", (uint)data_buffer[1]));
+
+ DBUG_RETURN(0);
+error:
+ DBUG_RETURN(errno);
+}
+
+/*
+ This method reads the header of a meta file and returns whether or not it was successful.
+ *rows will contain the current number of rows in the data file upon success.
+*/
+int ha_archive::read_meta_file(File meta_file, ulonglong *rows)
+{
+ uchar meta_buffer[META_BUFFER_SIZE];
+ ulonglong check_point;
+
+ DBUG_ENTER("ha_archive::read_meta_file");
+
+ VOID(my_seek(meta_file, 0, MY_SEEK_SET, MYF(0)));
+ if (my_read(meta_file, (byte*)meta_buffer, META_BUFFER_SIZE, 0) != META_BUFFER_SIZE)
+ DBUG_RETURN(-1);
+
+ /*
+ Parse out the meta data, we ignore version at the moment
+ */
+ *rows= uint8korr(meta_buffer + 2);
+ check_point= uint8korr(meta_buffer + 10);
+
+ DBUG_PRINT("ha_archive::read_meta_file", ("Check %d", (uint)meta_buffer[0]));
+ DBUG_PRINT("ha_archive::read_meta_file", ("Version %d", (uint)meta_buffer[1]));
+ DBUG_PRINT("ha_archive::read_meta_file", ("Rows %lld", *rows));
+ DBUG_PRINT("ha_archive::read_meta_file", ("Checkpoint %lld", check_point));
+ DBUG_PRINT("ha_archive::read_meta_file", ("Dirty %d", (int)meta_buffer[18]));
+
+ if ((meta_buffer[0] != (uchar)ARCHIVE_CHECK_HEADER) ||
+ ((bool)meta_buffer[18] == TRUE))
+ DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
+
+ my_sync(meta_file, MYF(MY_WME));
+
+ DBUG_RETURN(0);
+}
+
+/*
+ This method writes out the header of a meta file and returns whether or not it was successful.
+ By setting dirty you say whether or not the file represents the actual state of the data file.
+ Upon ::open() we set to dirty, and upon ::close() we set to clean. If we determine during
+ a read that the file was dirty we will force a rebuild of this file.
+*/
+int ha_archive::write_meta_file(File meta_file, ulonglong rows, bool dirty)
+{
+ uchar meta_buffer[META_BUFFER_SIZE];
+ ulonglong check_point= 0; //Reserved for the future
+
+ DBUG_ENTER("ha_archive::write_meta_file");
+
+ meta_buffer[0]= (uchar)ARCHIVE_CHECK_HEADER;
+ meta_buffer[1]= (uchar)ARCHIVE_VERSION;
+ int8store(meta_buffer + 2, rows);
+ int8store(meta_buffer + 10, check_point);
+ *(meta_buffer + 18)= (uchar)dirty;
+ DBUG_PRINT("ha_archive::write_meta_file", ("Check %d", (uint)ARCHIVE_CHECK_HEADER));
+ DBUG_PRINT("ha_archive::write_meta_file", ("Version %d", (uint)ARCHIVE_VERSION));
+ DBUG_PRINT("ha_archive::write_meta_file", ("Rows %llu", rows));
+ DBUG_PRINT("ha_archive::write_meta_file", ("Checkpoint %llu", check_point));
+ DBUG_PRINT("ha_archive::write_meta_file", ("Dirty %d", (uint)dirty));
+
+ VOID(my_seek(meta_file, 0, MY_SEEK_SET, MYF(0)));
+ if (my_write(meta_file, (byte *)meta_buffer, META_BUFFER_SIZE, 0) != META_BUFFER_SIZE)
+ DBUG_RETURN(-1);
+
+ my_sync(meta_file, MYF(MY_WME));
+
+ DBUG_RETURN(0);
+}
+
+
+/*
+ We create the shared memory space that we will use for the open table.
+ See ha_example.cc for a longer description.
*/
-static ARCHIVE_SHARE *get_share(const char *table_name, TABLE *table)
+ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, TABLE *table)
{
ARCHIVE_SHARE *share;
+ char meta_file_name[FN_REFLEN];
uint length;
char *tmp_name;
@@ -143,33 +301,62 @@ static ARCHIVE_SHARE *get_share(const char *table_name, TABLE *table)
return NULL;
}
- share->use_count=0;
- share->table_name_length=length;
- share->table_name=tmp_name;
+ share->use_count= 0;
+ share->table_name_length= length;
+ share->table_name= tmp_name;
fn_format(share->data_file_name,table_name,"",ARZ,MY_REPLACE_EXT|MY_UNPACK_FILENAME);
+ fn_format(meta_file_name,table_name,"",ARM,MY_REPLACE_EXT|MY_UNPACK_FILENAME);
strmov(share->table_name,table_name);
+ /*
+ We will use this lock for rows.
+ */
+ VOID(pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST));
+ if ((share->meta_file= my_open(meta_file_name, O_RDWR, MYF(0))) == -1)
+ goto error;
+
+ if (read_meta_file(share->meta_file, &share->rows_recorded))
+ {
+ /*
+ The problem here is that for some reason, probably a crash, the meta
+ file has been corrupted. So what do we do? Well we try to rebuild it
+ ourself. Once that happens, we reread it, but if that fails we just
+ call it quits and return an error.
+ */
+ if (rebuild_meta_file(share->table_name, share->meta_file))
+ goto error;
+ if (read_meta_file(share->meta_file, &share->rows_recorded))
+ goto error;
+ }
+ /*
+ After we read, we set the file to dirty. When we close, we will do the
+ opposite.
+ */
+ (void)write_meta_file(share->meta_file, share->rows_recorded, TRUE);
/*
It is expensive to open and close the data files and since you can't have
a gzip file that can be both read and written we keep a writer open
that is shared amoung all open tables.
*/
if ((share->archive_write= gzopen(share->data_file_name, "ab")) == NULL)
- goto error;
+ goto error2;
if (my_hash_insert(&archive_open_tables, (byte*) share))
- goto error;
+ goto error2;
thr_lock_init(&share->lock);
if (pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST))
- goto error2;
+ goto error3;
}
share->use_count++;
pthread_mutex_unlock(&archive_mutex);
return share;
-error2:
+error3:
+ VOID(pthread_mutex_destroy(&share->mutex));
thr_lock_delete(&share->lock);
/* We close, but ignore errors since we already have errors */
(void)gzclose(share->archive_write);
+error2:
+ my_close(share->meta_file,MYF(0));
error:
pthread_mutex_unlock(&archive_mutex);
my_free((gptr) share, MYF(0));
@@ -179,10 +366,10 @@ error:
/*
- Free lock controls.
+ Free the share.
See ha_example.cc for a description.
*/
-static int free_share(ARCHIVE_SHARE *share)
+int ha_archive::free_share(ARCHIVE_SHARE *share)
{
int rc= 0;
pthread_mutex_lock(&archive_mutex);
@@ -190,7 +377,8 @@ static int free_share(ARCHIVE_SHARE *share)
{
hash_delete(&archive_open_tables, (byte*) share);
thr_lock_delete(&share->lock);
- pthread_mutex_destroy(&share->mutex);
+ VOID(pthread_mutex_destroy(&share->mutex));
+ (void)write_meta_file(share->meta_file, share->rows_recorded, FALSE);
if (gzclose(share->archive_write) == Z_ERRNO)
rc= 1;
my_free((gptr) share, MYF(0));
@@ -205,7 +393,7 @@ static int free_share(ARCHIVE_SHARE *share)
We just implement one additional file extension.
*/
const char **ha_archive::bas_ext() const
-{ static const char *ext[]= { ARZ, ARN, NullS }; return ext; }
+{ static const char *ext[]= { ARZ, ARN, ARM, NullS }; return ext; }
/*
@@ -213,7 +401,6 @@ const char **ha_archive::bas_ext() const
Create/get our shared structure.
Init out lock.
We open the file we will read from.
- Set the size of ref_length.
*/
int ha_archive::open(const char *name, int mode, uint test_if_locked)
{
@@ -266,54 +453,63 @@ int ha_archive::close(void)
/*
- We create our data file here. The format is pretty simple. The first
- bytes in any file are the version number. Currently we do nothing
- with this, but in the future this gives us the ability to figure out
- version if we change the format at all. After the version we
- starting writing our rows. Unlike other storage engines we do not
- "pack" our data. Since we are about to do a general compression,
- packing would just be a waste of CPU time. If the table has blobs
- they are written after the row in the order of creation.
-
- So to read a row we:
- Read the version
- Read the record and copy it into buf
- Loop through any blobs and read them
+ We create our data file here. The format is pretty simple.
+ You can read about the format of the data file above.
+ Unlike other storage engines we do not "pack" our data. Since we
+ are about to do a general compression, packing would just be a waste of
+ CPU time. If the table has blobs they are written after the row in the order
+ of creation.
*/
int ha_archive::create(const char *name, TABLE *table_arg,
HA_CREATE_INFO *create_info)
{
- File create_file;
+ File create_file; // We use to create the datafile and the metafile
char name_buff[FN_REFLEN];
- size_t written;
int error;
DBUG_ENTER("ha_archive::create");
+ if ((create_file= my_create(fn_format(name_buff,name,"",ARM,
+ MY_REPLACE_EXT|MY_UNPACK_FILENAME),0,
+ O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
+ {
+ error= my_errno;
+ goto error;
+ }
+ write_meta_file(create_file, 0, FALSE);
+ my_close(create_file,MYF(0));
+
+ /*
+ We reuse name_buff since it is available.
+ */
if ((create_file= my_create(fn_format(name_buff,name,"",ARZ,
MY_REPLACE_EXT|MY_UNPACK_FILENAME),0,
O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
{
error= my_errno;
- goto err;
+ goto error;
}
if ((archive= gzdopen(create_file, "ab")) == NULL)
{
error= errno;
delete_table(name);
- goto err;
+ goto error;
}
- version= ARCHIVE_VERSION;
- written= gzwrite(archive, &version, sizeof(version));
- if (gzclose(archive) || written != sizeof(version))
+ if (write_data_header(archive))
{
- error= errno;
- delete_table(name);
- goto err;
+ gzclose(archive);
+ goto error2;
}
+
+ if (gzclose(archive))
+ goto error2;
+
DBUG_RETURN(0);
-err:
+error2:
+ error= errno;
+ delete_table(name);
+error:
/* Return error number, if we got one */
DBUG_RETURN(error ? error : -1);
}
@@ -334,25 +530,38 @@ int ha_archive::write_row(byte * buf)
DBUG_ENTER("ha_archive::write_row");
statistic_increment(ha_write_count,&LOCK_status);
- if (table->timestamp_default_now)
- update_timestamp(buf+table->timestamp_default_now-1);
+ if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
+ table->timestamp_field->set_time();
+ pthread_mutex_lock(&share->mutex);
written= gzwrite(share->archive_write, buf, table->reclength);
+ DBUG_PRINT("ha_archive::get_row", ("Wrote %d bytes expected %d", written, table->reclength));
share->dirty= TRUE;
if (written != table->reclength)
- DBUG_RETURN(errno ? errno : -1);
-
+ goto error;
+ /*
+ We should probably mark the table as damagaged if the record is written
+ but the blob fails.
+ */
for (Field_blob **field=table->blob_field ; *field ; field++)
{
char *ptr;
uint32 size= (*field)->get_length();
- (*field)->get_ptr(&ptr);
- written= gzwrite(share->archive_write, ptr, (unsigned)size);
- if (written != size)
- DBUG_RETURN(errno ? errno : -1);
+ if (size)
+ {
+ (*field)->get_ptr(&ptr);
+ written= gzwrite(share->archive_write, ptr, (unsigned)size);
+ if (written != size)
+ goto error;
+ }
}
+ share->rows_recorded++;
+ pthread_mutex_unlock(&share->mutex);
DBUG_RETURN(0);
+error:
+ pthread_mutex_unlock(&share->mutex);
+ DBUG_RETURN(errno ? errno : -1);
}
@@ -368,37 +577,28 @@ int ha_archive::rnd_init(bool scan)
int read; // gzread() returns int, and we use this to check the header
/* We rewind the file so that we can read from the beginning if scan */
- if(scan)
+ if (scan)
{
+ scan_rows= share->rows_recorded;
records= 0;
- if (gzrewind(archive))
- DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
- }
- /*
- If dirty, we lock, and then reset/flush the data.
- I found that just calling gzflush() doesn't always work.
- */
- if (share->dirty == TRUE)
- {
- pthread_mutex_lock(&share->mutex);
+ /*
+ If dirty, we lock, and then reset/flush the data.
+ I found that just calling gzflush() doesn't always work.
+ */
if (share->dirty == TRUE)
{
- gzflush(share->archive_write, Z_SYNC_FLUSH);
- share->dirty= FALSE;
+ pthread_mutex_lock(&share->mutex);
+ if (share->dirty == TRUE)
+ {
+ gzflush(share->archive_write, Z_SYNC_FLUSH);
+ share->dirty= FALSE;
+ }
+ pthread_mutex_unlock(&share->mutex);
}
- pthread_mutex_unlock(&share->mutex);
- }
-
- /*
- At the moment we just check the size of version to make sure the header is
- intact.
- */
- if (scan)
- {
- read= gzread(archive, &version, sizeof(version));
- if (read != sizeof(version))
- DBUG_RETURN(errno ? errno : -1);
+
+ if (read_data_header(archive))
+ DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
}
DBUG_RETURN(0);
@@ -409,7 +609,7 @@ int ha_archive::rnd_init(bool scan)
This is the method that is used to read a row. It assumes that the row is
positioned where you want it.
*/
-int ha_archive::get_row(byte *buf)
+int ha_archive::get_row(gzFile file_to_read, byte *buf)
{
int read; // Bytes read, gzread() returns int
char *last;
@@ -417,7 +617,11 @@ int ha_archive::get_row(byte *buf)
Field_blob **field;
DBUG_ENTER("ha_archive::get_row");
- read= gzread(archive, buf, table->reclength);
+ read= gzread(file_to_read, buf, table->reclength);
+ DBUG_PRINT("ha_archive::get_row", ("Read %d bytes expected %d", read, table->reclength));
+
+ if (read == Z_STREAM_ERROR)
+ DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
/* If we read nothing we are at the end of the file */
if (read == 0)
@@ -439,11 +643,14 @@ int ha_archive::get_row(byte *buf)
for (field=table->blob_field; *field ; field++)
{
size_t size= (*field)->get_length();
- read= gzread(archive, last, size);
- if ((size_t) read != size)
- DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
- (*field)->set_ptr(size, last);
- last += size;
+ if (size)
+ {
+ read= gzread(file_to_read, last, size);
+ if ((size_t) read != size)
+ DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
+ (*field)->set_ptr(size, last);
+ last += size;
+ }
}
DBUG_RETURN(0);
}
@@ -459,9 +666,15 @@ int ha_archive::rnd_next(byte *buf)
int rc;
DBUG_ENTER("ha_archive::rnd_next");
+ if (!scan_rows)
+ DBUG_RETURN(HA_ERR_END_OF_FILE);
+ scan_rows--;
+
statistic_increment(ha_read_rnd_next_count,&LOCK_status);
current_position= gztell(archive);
- rc= get_row(buf);
+ rc= get_row(archive, buf);
+
+
if (rc != HA_ERR_END_OF_FILE)
records++;
@@ -474,6 +687,7 @@ int ha_archive::rnd_next(byte *buf)
each call to ha_archive::rnd_next() if an ordering of the rows is
needed.
*/
+
void ha_archive::position(const byte *record)
{
DBUG_ENTER("ha_archive::position");
@@ -496,13 +710,70 @@ int ha_archive::rnd_pos(byte * buf, byte *pos)
current_position= ha_get_ptr(pos, ref_length);
z_off_t seek= gzseek(archive, current_position, SEEK_SET);
- DBUG_RETURN(get_row(buf));
+ DBUG_RETURN(get_row(archive, buf));
+}
+
+/*
+ This method rebuilds the meta file. It does this by walking the datafile and
+ rewriting the meta file.
+*/
+int ha_archive::rebuild_meta_file(char *table_name, File meta_file)
+{
+ int rc;
+ byte *buf;
+ ulonglong rows_recorded= 0;
+ gzFile rebuild_file; /* Archive file we are working with */
+ char data_file_name[FN_REFLEN];
+ DBUG_ENTER("ha_archive::rebuild_meta_file");
+
+ /*
+ Open up the meta file to recreate it.
+ */
+ fn_format(data_file_name, table_name, "", ARZ,
+ MY_REPLACE_EXT|MY_UNPACK_FILENAME);
+ if ((rebuild_file= gzopen(data_file_name, "rb")) == NULL)
+ DBUG_RETURN(errno ? errno : -1);
+
+ if (rc= read_data_header(rebuild_file))
+ goto error;
+
+ /*
+ We malloc up the buffer we will use for counting the rows.
+ I know, this malloc'ing memory but this should be a very
+ rare event.
+ */
+ if (!(buf= (byte*) my_malloc(table->rec_buff_length > sizeof(ulonglong) +1 ?
+ table->rec_buff_length : sizeof(ulonglong) +1 ,
+ MYF(MY_WME))))
+ {
+ rc= HA_ERR_CRASHED_ON_USAGE;
+ goto error;
+ }
+
+ while (!(rc= get_row(rebuild_file, buf)))
+ rows_recorded++;
+
+ /*
+ Only if we reach the end of the file do we assume we can rewrite.
+ At this point we reset rc to a non-message state.
+ */
+ if (rc == HA_ERR_END_OF_FILE)
+ {
+ (void)write_meta_file(meta_file, rows_recorded, FALSE);
+ rc= 0;
+ }
+
+ my_free((gptr) buf, MYF(0));
+error:
+ gzclose(rebuild_file);
+
+ DBUG_RETURN(rc);
}
/*
The table can become fragmented if data was inserted, read, and then
inserted again. What we do is open up the file and recompress it completely.
- */
+*/
int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt)
{
DBUG_ENTER("ha_archive::optimize");
@@ -512,7 +783,8 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt)
char writer_filename[FN_REFLEN];
/* Lets create a file to contain the new data */
- fn_format(writer_filename,share->table_name,"",ARN, MY_REPLACE_EXT|MY_UNPACK_FILENAME);
+ fn_format(writer_filename, share->table_name, "", ARN,
+ MY_REPLACE_EXT|MY_UNPACK_FILENAME);
/* Closing will cause all data waiting to be flushed, to be flushed */
gzclose(share->archive_write);
@@ -547,6 +819,57 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt)
DBUG_RETURN(0);
}
+
+/*
+ No transactions yet, so this is pretty dull.
+*/
+int ha_archive::external_lock(THD *thd, int lock_type)
+{
+ DBUG_ENTER("ha_archive::external_lock");
+ DBUG_RETURN(0);
+}
+
+/*
+ Below is an example of how to setup row level locking.
+*/
+THR_LOCK_DATA **ha_archive::store_lock(THD *thd,
+ THR_LOCK_DATA **to,
+ enum thr_lock_type lock_type)
+{
+ if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK)
+ {
+ /*
+ Here is where we get into the guts of a row level lock.
+ If TL_UNLOCK is set
+ If we are not doing a LOCK TABLE or DISCARD/IMPORT
+ TABLESPACE, then allow multiple writers
+ */
+
+ if ((lock_type >= TL_WRITE_CONCURRENT_INSERT &&
+ lock_type <= TL_WRITE) && !thd->in_lock_tables
+ && !thd->tablespace_op)
+ lock_type = TL_WRITE_ALLOW_WRITE;
+
+ /*
+ In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
+ MySQL would use the lock TL_READ_NO_INSERT on t2, and that
+ would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
+ to t2. Convert the lock to a normal read lock to allow
+ concurrent inserts to t2.
+ */
+
+ if (lock_type == TL_READ_NO_INSERT && !thd->in_lock_tables)
+ lock_type = TL_READ;
+
+ lock.type=lock_type;
+ }
+
+ *to++= &lock;
+
+ return to;
+}
+
+
/******************************************************************************
Everything below here is default, please look at ha_example.cc for
@@ -616,8 +939,8 @@ void ha_archive::info(uint flag)
DBUG_ENTER("ha_archive::info");
/* This is a lie, but you don't want the optimizer to see zero or 1 */
- if (records < 2)
- records= 2;
+ records= share->rows_recorded;
+ deleted= 0;
DBUG_VOID_RETURN;
}
@@ -634,23 +957,6 @@ int ha_archive::reset(void)
DBUG_RETURN(0);
}
-
-int ha_archive::external_lock(THD *thd, int lock_type)
-{
- DBUG_ENTER("ha_archive::external_lock");
- DBUG_RETURN(0);
-}
-
-THR_LOCK_DATA **ha_archive::store_lock(THD *thd,
- THR_LOCK_DATA **to,
- enum thr_lock_type lock_type)
-{
- if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK)
- lock.type=lock_type;
- *to++= &lock;
- return to;
-}
-
ha_rows ha_archive::records_in_range(uint inx, key_range *min_key,
key_range *max_key)
{
diff --git a/sql/examples/ha_archive.h b/sql/examples/ha_archive.h
index cf7becc5bc0..b619de5f6c1 100644
--- a/sql/examples/ha_archive.h
+++ b/sql/examples/ha_archive.h
@@ -32,8 +32,10 @@ typedef struct st_archive_share {
uint table_name_length,use_count;
pthread_mutex_t mutex;
THR_LOCK lock;
+ File meta_file; /* Meta file we use */
gzFile archive_write; /* Archive file we are working with */
bool dirty; /* Flag for if a flush should occur */
+ ulonglong rows_recorded; /* Number of rows in tables */
} ARCHIVE_SHARE;
/*
@@ -50,7 +52,7 @@ class ha_archive: public handler
z_off_t current_position; /* The position of the row we just read */
byte byte_buffer[IO_SIZE]; /* Initial buffer for our string */
String buffer; /* Buffer used for blob storage */
- unsigned int version; /* Used for recording version */
+ ulonglong scan_rows; /* Number of rows left in scan */
public:
ha_archive(TABLE *table): handler(table)
@@ -104,7 +106,14 @@ public:
int rnd_init(bool scan=1);
int rnd_next(byte *buf);
int rnd_pos(byte * buf, byte *pos);
- int get_row(byte *buf);
+ int get_row(gzFile file_to_read, byte *buf);
+ int read_meta_file(File meta_file, ulonglong *rows);
+ int write_meta_file(File meta_file, ulonglong rows, bool dirty);
+ ARCHIVE_SHARE *get_share(const char *table_name, TABLE *table);
+ int free_share(ARCHIVE_SHARE *share);
+ int rebuild_meta_file(char *table_name, File meta_file);
+ int read_data_header(gzFile file_to_read);
+ int write_data_header(gzFile file_to_write);
void position(const byte *record);
void info(uint);
int extra(enum ha_extra_function operation);
diff --git a/sql/field.cc b/sql/field.cc
index eaa1ca2bcca..ec3bd72878d 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -2970,6 +2970,14 @@ timestamp_auto_set_type Field_timestamp::get_auto_set_type() const
return TIMESTAMP_AUTO_SET_ON_INSERT;
case TIMESTAMP_UN_FIELD:
return TIMESTAMP_AUTO_SET_ON_UPDATE;
+ case TIMESTAMP_OLD_FIELD:
+ /*
+ Altough we can have several such columns in legacy tables this
+ function should be called only for first of them (i.e. the one
+ having auto-set property).
+ */
+ DBUG_ASSERT(table->timestamp_field == this);
+ /* Fall-through */
case TIMESTAMP_DNUN_FIELD:
return TIMESTAMP_AUTO_SET_ON_BOTH;
default:
@@ -5077,6 +5085,11 @@ void Field_blob::get_key_image(char *buff,uint length,
}
#endif /*HAVE_SPATIAL*/
+ get_ptr(&blob);
+ uint char_length= length / cs->mbmaxlen;
+ char_length= my_charpos(cs, blob, blob + length, char_length);
+ set_if_smaller(length, char_length);
+
if ((uint32) length > blob_length)
{
/*
@@ -5087,7 +5100,6 @@ void Field_blob::get_key_image(char *buff,uint length,
length=(uint) blob_length;
}
int2store(buff,length);
- get_ptr(&blob);
memcpy(buff+HA_KEY_BLOB_LENGTH, blob, length);
}
@@ -5103,6 +5115,10 @@ int Field_blob::key_cmp(const byte *key_ptr, uint max_key_length)
char *blob1;
uint blob_length=get_length(ptr);
memcpy_fixed(&blob1,ptr+packlength,sizeof(char*));
+ CHARSET_INFO *cs= charset();
+ uint char_length= max_key_length / cs->mbmaxlen;
+ char_length= my_charpos(cs, blob1, blob1+blob_length, char_length);
+ set_if_smaller(blob_length, char_length);
return Field_blob::cmp(blob1,min(blob_length, max_key_length),
(char*) key_ptr+HA_KEY_BLOB_LENGTH,
uint2korr(key_ptr));
diff --git a/sql/field_conv.cc b/sql/field_conv.cc
index c9b21b5f96f..890687fc925 100644
--- a/sql/field_conv.cc
+++ b/sql/field_conv.cc
@@ -252,7 +252,8 @@ static void do_copy_timestamp(Copy_field *copy)
{
if (*copy->from_null_ptr & copy->from_bit)
{
- ((Field_timestamp*) copy->to_field)->set_time();// Same as set_field_to_null
+ /* Same as in set_field_to_null_with_conversions() */
+ ((Field_timestamp*) copy->to_field)->set_time();
}
else
(copy->do_copy2)(copy);
@@ -262,7 +263,11 @@ static void do_copy_timestamp(Copy_field *copy)
static void do_copy_next_number(Copy_field *copy)
{
if (*copy->from_null_ptr & copy->from_bit)
- copy->to_field->reset(); // Same as set_field_to_null
+ {
+ /* Same as in set_field_to_null_with_conversions() */
+ copy->to_field->table->auto_increment_field_not_null= FALSE;
+ copy->to_field->reset();
+ }
else
(copy->do_copy2)(copy);
}
@@ -437,18 +442,20 @@ void Copy_field::set(Field *to,Field *from,bool save)
}
}
else
- do_copy=do_copy_not_null;
+ {
+ if (to_field->type() == FIELD_TYPE_TIMESTAMP)
+ do_copy= do_copy_timestamp; // Automatic timestamp
+ else if (to_field == to_field->table->next_number_field)
+ do_copy= do_copy_next_number;
+ else
+ do_copy= do_copy_not_null;
+ }
}
else if (to_field->real_maybe_null())
{
to_null_ptr= to->null_ptr;
to_bit= to->null_bit;
- if (to_field->type() == FIELD_TYPE_TIMESTAMP)
- do_copy=do_copy_timestamp; // Automatic timestamp
- else if (to_field == to_field->table->next_number_field)
- do_copy=do_copy_next_number;
- else
- do_copy=do_copy_maybe_null;
+ do_copy= do_copy_maybe_null;
}
else
do_copy=0;
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 132bb835d82..8ddf00a7568 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -812,6 +812,7 @@ ha_innobase::init_table_handle_for_HANDLER(void)
if the trx isolation level would have been specified as SERIALIZABLE */
prebuilt->select_lock_type = LOCK_NONE;
+ prebuilt->stored_select_lock_type = LOCK_NONE;
/* Always fetch all columns in the index record */
@@ -3171,7 +3172,7 @@ ha_innobase::index_last(
{
int error;
- DBUG_ENTER("index_first");
+ DBUG_ENTER("index_last");
statistic_increment(ha_read_last_count, &LOCK_status);
error = index_read(buf, NULL, 0, HA_READ_BEFORE_KEY);
@@ -3525,10 +3526,6 @@ create_index(
prefix_len = 0;
}
- if (prefix_len >= DICT_MAX_COL_PREFIX_LEN) {
- DBUG_RETURN(-1);
- }
-
/* We assume all fields should be sorted in ascending
order, hence the '0': */
@@ -4259,7 +4256,7 @@ ha_innobase::info(
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
- return;
+ DBUG_VOID_RETURN;
}
/* We do not know if MySQL can call this function before calling
@@ -4820,6 +4817,7 @@ ha_innobase::external_lock(
/* If this is a SELECT, then it is in UPDATE TABLE ...
or SELECT ... FOR UPDATE */
prebuilt->select_lock_type = LOCK_X;
+ prebuilt->stored_select_lock_type = LOCK_X;
}
if (lock_type != F_UNLCK) {
@@ -5071,14 +5069,22 @@ ha_innobase::store_lock(
{
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
- if (lock_type == TL_READ_WITH_SHARED_LOCKS ||
+ if ((lock_type == TL_READ && thd->in_lock_tables) ||
+ (lock_type == TL_READ_HIGH_PRIORITY && thd->in_lock_tables) ||
+ lock_type == TL_READ_WITH_SHARED_LOCKS ||
lock_type == TL_READ_NO_INSERT) {
- /* This is a SELECT ... IN SHARE MODE, or
- we are doing a complex SQL statement like
+ /* The OR cases above are in this order:
+ 1) MySQL is doing LOCK TABLES ... READ LOCAL, or
+ 2) (we do not know when TL_READ_HIGH_PRIORITY is used), or
+ 3) this is a SELECT ... IN SHARE MODE, or
+ 4) we are doing a complex SQL statement like
INSERT INTO ... SELECT ... and the logical logging (MySQL
- binlog) requires the use of a locking read */
+ binlog) requires the use of a locking read, or
+ MySQL is doing LOCK TABLES ... READ. */
prebuilt->select_lock_type = LOCK_S;
+ prebuilt->stored_select_lock_type = LOCK_S;
+
} else if (lock_type != TL_IGNORE) {
/* In ha_berkeley.cc there is a comment that MySQL
@@ -5089,6 +5095,7 @@ ha_innobase::store_lock(
here even if this would be SELECT ... FOR UPDATE */
prebuilt->select_lock_type = LOCK_NONE;
+ prebuilt->stored_select_lock_type = LOCK_NONE;
}
if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) {
@@ -5333,39 +5340,32 @@ innobase_get_at_most_n_mbchars(
/* If the charset is multi-byte, then we must find the length of the
first at most n chars in the string. If the string contains less
characters than n, then we return the length to the end of the last
- full character. */
+ character. */
if (charset->mbmaxlen > 1) {
-/* ulint right_value; */
-
/* my_charpos() returns the byte length of the first n_chars
- characters, or the end of the last full character */
+ characters, or a value bigger than the length of str, if
+ there were not enough full characters in str.
+
+ Why does the code below work:
+ Suppose that we are looking for n UTF-8 characters.
+
+ 1) If the string is long enough, then the prefix contains at
+ least n complete UTF-8 characters + maybe some extra
+ characters + an incomplete UTF-8 character. No problem in
+ this case. The function returns the pointer to the
+ end of the nth character.
+
+ 2) If the string is not long enough, then the string contains
+ the complete value of a column, that is, only complete UTF-8
+ characters, and we can store in the column prefix index the
+ whole string. */
char_length = my_charpos(charset, str,
str + data_len, n_chars);
-
- /*################################################*/
- /* TODO: my_charpos sometimes returns a non-sensical value
- that is BIGGER than data_len: try to fix this bug partly with
- these heuristics. This is NOT a complete bug fix! */
-
if (char_length > data_len) {
char_length = data_len;
}
- /*################################################*/
-
-/* printf("data_len %lu, n_chars %lu, char_len %lu\n",
- data_len, n_chars, char_length);
- if (data_len < n_chars) {
- right_value = data_len;
- } else {
- right_value = n_chars;
- }
-
- if (right_value != char_length) {
- printf("ERRRRRROOORRRRRRRRRRRR!!!!!!!!!\n");
- }
-*/
} else {
if (data_len < prefix_len) {
char_length = data_len;
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index 729ec4c27eb..0b993ebe793 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -1280,6 +1280,7 @@ int ha_myisam::delete_table(const char *name)
return mi_delete_table(name);
}
+
int ha_myisam::external_lock(THD *thd, int lock_type)
{
return mi_lock_database(file, !table->tmp_table ?
@@ -1287,7 +1288,6 @@ int ha_myisam::external_lock(THD *thd, int lock_type)
F_UNLCK : F_EXTRA_LCK));
}
-
THR_LOCK_DATA **ha_myisam::store_lock(THD *thd,
THR_LOCK_DATA **to,
enum thr_lock_type lock_type)
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index 57232778d48..8faa0b33756 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -2135,11 +2135,47 @@ int ha_ndbcluster::index_read(byte *buf,
DBUG_PRINT("enter", ("active_index: %u, key_len: %u, find_flag: %d",
active_index, key_len, find_flag));
+ int error;
+ ndb_index_type type = get_index_type(active_index);
+ const KEY* key_info = table->key_info+active_index;
+ switch (type){
+ case PRIMARY_KEY_ORDERED_INDEX:
+ case PRIMARY_KEY_INDEX:
+ if (find_flag == HA_READ_KEY_EXACT && key_info->key_length == key_len)
+ {
+ DBUG_RETURN(pk_read(key, key_len, buf));
+ }
+ else if (type == PRIMARY_KEY_INDEX)
+ {
+ DBUG_RETURN(1);
+ }
+ break;
+ case UNIQUE_ORDERED_INDEX:
+ case UNIQUE_INDEX:
+ if (find_flag == HA_READ_KEY_EXACT && key_info->key_length == key_len)
+ {
+ DBUG_RETURN(unique_index_read(key, key_len, buf));
+ }
+ else if (type == UNIQUE_INDEX)
+ {
+ DBUG_RETURN(1);
+ }
+ break;
+ case ORDERED_INDEX:
+ break;
+ default:
+ case UNDEFINED_INDEX:
+ DBUG_ASSERT(false);
+ return 1;
+ break;
+ }
+
key_range start_key;
- start_key.key= key;
- start_key.length= key_len;
- start_key.flag= find_flag;
- DBUG_RETURN(read_range_first_to_buf(&start_key, NULL, false, true, buf));
+ start_key.key = key;
+ start_key.length = key_len;
+ start_key.flag = find_flag;
+ error= ordered_index_scan(&start_key, 0, true, buf);
+ DBUG_RETURN(error == HA_ERR_END_OF_FILE ? HA_ERR_KEY_NOT_FOUND : error);
}
diff --git a/sql/handler.cc b/sql/handler.cc
index 23b4fbe4835..e59358d44bf 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -483,7 +483,7 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans)
if (trans == &thd->transaction.all && mysql_bin_log.is_open() &&
my_b_tell(&thd->transaction.trans_log))
{
- if (error= wait_if_global_read_lock(thd, 0, 0))
+ if ((error= wait_if_global_read_lock(thd, 0, 0)))
{
/*
Note that ROLLBACK [TO SAVEPOINT] does not have this test; it's
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index bb1ea09d6bc..8ff479df098 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -1162,6 +1162,15 @@ Item_func_nullif::val_str(String *str)
return res;
}
+
+bool
+Item_func_nullif::is_null()
+{
+ if (!cmp.compare())
+ return (null_value=1);
+ return 0;
+}
+
/*
CASE expression
Return the matching ITEM or NULL if all compares (including else) failed
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index f1a2b11aaa8..ad2b929c19e 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -444,6 +444,7 @@ public:
const char *func_name() const { return "nullif"; }
void print(String *str) { Item_func::print(str); }
table_map not_null_tables() const { return 0; }
+ bool is_null();
};
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 0bddeed14d6..c7cd9d26974 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -2736,6 +2736,8 @@ void Item_func_get_user_var::fix_length_and_dec()
case STRING_RESULT:
max_length= MAX_BLOB_WIDTH;
break;
+ case ROW_RESULT: // Keep compiler happy
+ break;
}
}
else
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 131bd55dc81..78acaafc486 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -1245,7 +1245,7 @@ String *Item_func_ltrim::val_str(String *str)
{
const char *r_ptr=remove_str->ptr();
end-=remove_length;
- while (ptr < end && !memcmp(ptr,r_ptr,remove_length))
+ while (ptr <= end && !memcmp(ptr, r_ptr, remove_length))
ptr+=remove_length;
end+=remove_length;
}
@@ -1317,8 +1317,8 @@ String *Item_func_rtrim::val_str(String *str)
else
#endif /* USE_MB */
{
- while (ptr + remove_length < end &&
- !memcmp(end-remove_length,r_ptr,remove_length))
+ while (ptr + remove_length <= end &&
+ !memcmp(end-remove_length, r_ptr, remove_length))
end-=remove_length;
}
}
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 5d04d145563..314ee07eb1a 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -677,12 +677,15 @@ void mysql_reset_errors(THD *thd);
my_bool mysqld_show_warnings(THD *thd, ulong levels_to_show);
/* sql_handler.cc */
-int mysql_ha_open(THD *thd, TABLE_LIST *tables);
-int mysql_ha_close(THD *thd, TABLE_LIST *tables,
- bool dont_send_ok=0, bool dont_lock=0, bool no_alias=0);
-int mysql_ha_close_list(THD *thd, TABLE_LIST *tables, bool flushed=0);
+int mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen= 0);
+int mysql_ha_close(THD *thd, TABLE_LIST *tables);
int mysql_ha_read(THD *, TABLE_LIST *,enum enum_ha_read_modes,char *,
List<Item> *,enum ha_rkey_function,Item *,ha_rows,ha_rows);
+int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags);
+/* mysql_ha_flush mode_flags bits */
+#define MYSQL_HA_CLOSE_FINAL 0x00
+#define MYSQL_HA_REOPEN_ON_USAGE 0x01
+#define MYSQL_HA_FLUSH_ALL 0x02
/* sql_base.cc */
void set_item_name(Item *item,char *pos,uint length);
@@ -726,6 +729,7 @@ void wait_for_refresh(THD *thd);
int open_tables(THD *thd, TABLE_LIST *tables, uint *counter);
int simple_open_n_lock_tables(THD *thd,TABLE_LIST *tables);
int open_and_lock_tables(THD *thd,TABLE_LIST *tables);
+void relink_tables_for_derived(THD *thd);
int lock_tables(THD *thd, TABLE_LIST *tables, uint counter);
TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
const char *table_name, bool link_in_list);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 5e40398574b..d7d0f637ec2 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -963,7 +963,7 @@ void clean_up(bool print_message)
if (print_message && errmesg)
sql_print_information(ER(ER_SHUTDOWN_COMPLETE),my_progname);
-#if !defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
+#if !defined(EMBEDDED_LIBRARY)
if (!opt_bootstrap)
(void) my_delete(pidfile_name,MYF(0)); // This may not always exist
#endif
@@ -1500,7 +1500,11 @@ static void init_signals(void)
}
static void start_signal_handler(void)
-{}
+{
+ // Save vm id of this process
+ if (!opt_bootstrap)
+ create_pid_file();
+}
static void check_data_home(const char *path)
{}
@@ -2118,8 +2122,7 @@ static void check_data_home(const char *path)
/* ARGSUSED */
-extern "C" int my_message_sql(uint error, const char *str,
- myf MyFlags __attribute__((unused)))
+extern "C" int my_message_sql(uint error, const char *str, myf MyFlags)
{
THD *thd;
DBUG_ENTER("my_message_sql");
@@ -2133,7 +2136,11 @@ extern "C" int my_message_sql(uint error, const char *str,
if (thd->lex->current_select &&
thd->lex->current_select->no_error && !thd->is_fatal_error)
{
- DBUG_PRINT("error", ("above error converted to warning"));
+ DBUG_PRINT("error", ("Error converted to warning: current_select: no_error %d fatal_error: %d",
+ (thd->lex->current_select ?
+ thd->lex->current_select->no_error : 0),
+ (int) thd->is_fatal_error));
+
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, error, str);
}
else
@@ -2147,7 +2154,7 @@ extern "C" int my_message_sql(uint error, const char *str,
}
}
}
- else
+ if (!thd || MyFlags & ME_NOREFRESH)
sql_print_error("%s: %s",my_progname,str); /* purecov: inspected */
DBUG_RETURN(0);
}
@@ -2934,10 +2941,10 @@ we force server id to 2, but this MySQL server will not act as a slave.");
#ifndef __NETWARE__
(void) pthread_kill(signal_thread, MYSQL_KILL_SIGNAL);
#endif /* __NETWARE__ */
-#ifndef __WIN__
+
if (!opt_bootstrap)
(void) my_delete(pidfile_name,MYF(MY_WME)); // Not needed anymore
-#endif
+
if (unix_sock != INVALID_SOCKET)
unlink(mysqld_unix_port);
exit(1);
diff --git a/sql/protocol.cc b/sql/protocol.cc
index da2a285fffc..c2d9117b062 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -209,6 +209,10 @@ net_printf(THD *thd, uint errcode, ...)
format,args);
va_end(args);
+ /* Replication slave relies on net->last_* to see if there was error */
+ net->last_errno= errcode;
+ strmake(net->last_error, text_pos, sizeof(net->last_error)-1);
+
#ifndef EMBEDDED_LIBRARY
if (net->vio == 0)
{
diff --git a/sql/records.cc b/sql/records.cc
index 5a969ef9c20..e5a0d102b10 100644
--- a/sql/records.cc
+++ b/sql/records.cc
@@ -156,17 +156,26 @@ void end_read_record(READ_RECORD *info)
static int rr_quick(READ_RECORD *info)
{
- int tmp=info->select->quick->get_next();
- if (tmp)
+ int tmp;
+ while ((tmp= info->select->quick->get_next()))
{
- if (tmp == HA_ERR_END_OF_FILE)
- tmp= -1;
- else
+ if (info->thd->killed)
{
- if (info->print_error)
- info->file->print_error(tmp,MYF(0));
- if (tmp < 0) // Fix negative BDB errno
- tmp=1;
+ my_error(ER_SERVER_SHUTDOWN, MYF(0));
+ return 1;
+ }
+ if (tmp != HA_ERR_RECORD_DELETED)
+ {
+ if (tmp == HA_ERR_END_OF_FILE)
+ tmp= -1;
+ else
+ {
+ if (info->print_error)
+ info->file->print_error(tmp,MYF(0));
+ if (tmp < 0) // Fix negative BDB errno
+ tmp=1;
+ }
+ break;
}
}
return tmp;
@@ -330,9 +339,10 @@ static int init_rr_cache(READ_RECORD *info)
rec_cache_size=info->cache_records*info->reclength;
info->rec_cache_size=info->cache_records*info->ref_length;
+ // We have to allocate one more byte to use uint3korr (see comments for it)
if (info->cache_records <= 2 ||
!(info->cache=(byte*) my_malloc_lock(rec_cache_size+info->cache_records*
- info->struct_length,
+ info->struct_length+1,
MYF(0))))
DBUG_RETURN(1);
#ifdef HAVE_purify
diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc
index d7b70fe122c..66c6e7c508d 100644
--- a/sql/repl_failsafe.cc
+++ b/sql/repl_failsafe.cc
@@ -14,8 +14,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-// Sasha Pachev <sasha@mysql.com> is currently in charge of this file
-
#include "mysql_priv.h"
#ifdef HAVE_REPLICATION
diff --git a/sql/repl_failsafe.h b/sql/repl_failsafe.h
index a9c504330ab..ad0219bb735 100644
--- a/sql/repl_failsafe.h
+++ b/sql/repl_failsafe.h
@@ -1,6 +1,20 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB & Sasha
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
#ifdef HAVE_REPLICATION
-#ifndef REPL_FAILSAFE_H
-#define REPL_FAILSAFE_H
#include "mysql.h"
#include "my_sys.h"
@@ -35,5 +49,4 @@ void end_slave_list();
int register_slave(THD* thd, uchar* packet, uint packet_length);
void unregister_slave(THD* thd, bool only_mine, bool need_mutex);
-#endif
#endif /* HAVE_REPLICATION */
diff --git a/sql/slave.h b/sql/slave.h
index 384436fdfcc..20167094453 100644
--- a/sql/slave.h
+++ b/sql/slave.h
@@ -1,3 +1,19 @@
+/* Copyright (C) 2000-2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
#ifdef HAVE_REPLICATION
#ifndef SLAVE_H
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index a5284a543e6..fc252c1f5ac 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -2699,10 +2699,11 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
{
TABLE_LIST *table;
char *user = thd->priv_user;
+ DBUG_ENTER("check_grant");
want_access &= ~thd->master_access;
if (!want_access)
- return 0; // ok
+ DBUG_RETURN(0); // ok
rw_rdlock(&LOCK_grant);
for (table= tables; table && number--; table= table->next)
@@ -2739,7 +2740,7 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
}
}
rw_unlock(&LOCK_grant);
- return 0;
+ DBUG_RETURN(0);
err:
rw_unlock(&LOCK_grant);
@@ -2770,7 +2771,7 @@ err:
thd->host_or_ip,
table ? table->real_name : "unknown");
}
- return 1;
+ DBUG_RETURN(1);
}
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 2770d93bf26..3c25d01ced0 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -300,7 +300,7 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
thd->proc_info="Flushing tables";
close_old_data_files(thd,thd->open_tables,1,1);
- mysql_ha_close_list(thd, tables);
+ mysql_ha_flush(thd, tables, MYSQL_HA_REOPEN_ON_USAGE | MYSQL_HA_FLUSH_ALL);
bool found=1;
/* Wait until all threads has closed all the tables we had locked */
DBUG_PRINT("info",
@@ -852,7 +852,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
}
/* close handler tables which are marked for flush */
- mysql_ha_close_list(thd, (TABLE_LIST*) NULL, /*flushed*/ 1);
+ mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE);
for (table=(TABLE*) hash_search(&open_cache,(byte*) key,key_length) ;
table && table->in_use ;
@@ -936,6 +936,31 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
for (uint i=0 ; i < table->fields ; i++)
table->field[i]->table_name=table->table_name;
}
+#if MYSQL_VERSION_ID < 40100
+ /*
+ If per-connection "new" variable (represented by variables.new_mode)
+ is set then we should pretend that the length of TIMESTAMP field is 19.
+ The cheapest (from perfomance viewpoint) way to achieve that is to set
+ field_length of all Field_timestamp objects in a table after opening
+ it (to 19 if new_mode is true or to original field length otherwise).
+ We save value of new_mode variable in TABLE::timestamp_mode to
+ not perform this setup if new_mode value is the same between sequential
+ table opens.
+ */
+ my_bool new_mode= thd->variables.new_mode;
+ if (table->timestamp_mode != new_mode)
+ {
+ for (uint i=0 ; i < table->fields ; i++)
+ {
+ Field *field= table->field[i];
+
+ if (field->type() == FIELD_TYPE_TIMESTAMP)
+ field->field_length= new_mode ? 19 :
+ ((Field_timestamp *)(field))->orig_field_length;
+ }
+ table->timestamp_mode= new_mode;
+ }
+#endif
/* These variables are also set in reopen_table() */
table->tablenr=thd->current_tablenr++;
table->used_fields=0;
@@ -1224,7 +1249,7 @@ bool wait_for_tables(THD *thd)
{
thd->some_tables_deleted=0;
close_old_data_files(thd,thd->open_tables,0,dropping_tables != 0);
- mysql_ha_close_list(thd, (TABLE_LIST*) NULL, /*flushed*/ 1);
+ mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE);
if (!table_is_used(thd->open_tables,1))
break;
(void) pthread_cond_wait(&COND_refresh,&LOCK_open);
@@ -1670,10 +1695,18 @@ int open_and_lock_tables(THD *thd, TABLE_LIST *tables)
uint counter;
if (open_tables(thd, tables, &counter) || lock_tables(thd, tables, counter))
DBUG_RETURN(-1); /* purecov: inspected */
- /*
- Let us propagate pointers to open tables from global table list
- to table lists in particular selects if needed.
- */
+ relink_tables_for_derived(thd);
+ DBUG_RETURN(mysql_handle_derived(thd->lex));
+}
+
+
+/*
+ Let us propagate pointers to open tables from global table list
+ to table lists in particular selects if needed.
+*/
+
+void relink_tables_for_derived(THD *thd)
+{
if (thd->lex->all_selects_list->next_select_in_list() ||
thd->lex->time_zone_tables_used)
{
@@ -1686,7 +1719,6 @@ int open_and_lock_tables(THD *thd, TABLE_LIST *tables)
if (cursor->table_list)
cursor->table= cursor->table_list->table;
}
- DBUG_RETURN(mysql_handle_derived(thd->lex));
}
@@ -1726,7 +1758,7 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count)
if (!table->derived)
*(ptr++)= table->table;
}
- if (!(thd->lock=mysql_lock_tables(thd,start,count)))
+ if (!(thd->lock=mysql_lock_tables(thd,start, (uint) (ptr - start))))
return -1; /* purecov: inspected */
}
else
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 674452192f8..7aa0ef83238 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -1945,7 +1945,6 @@ inline ulong Query_cache::get_min_append_result_data_size()
/*
Allocate one or more blocks to hold data
*/
-
my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block,
ulong data_len,
Query_cache_block *query_block,
@@ -1953,55 +1952,55 @@ my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block,
{
ulong all_headers_len = (ALIGN_SIZE(sizeof(Query_cache_block)) +
ALIGN_SIZE(sizeof(Query_cache_result)));
- ulong len= data_len + all_headers_len;
- ulong align_len= ALIGN_SIZE(len);
- DBUG_ENTER("Query_cache::allocate_data_chain");
- DBUG_PRINT("qcache", ("data_len %lu, all_headers_len %lu",
- data_len, all_headers_len));
-
ulong min_size = (first_block_arg ?
get_min_first_result_data_size():
get_min_append_result_data_size());
- *result_block = allocate_block(max(min_size, align_len),
- min_result_data_size == 0,
- all_headers_len + min_result_data_size,
- 1);
- my_bool success = (*result_block != 0);
- if (success)
+ Query_cache_block *prev_block= NULL;
+ Query_cache_block *new_block;
+ DBUG_ENTER("Query_cache::allocate_data_chain");
+ DBUG_PRINT("qcache", ("data_len %lu, all_headers_len %lu",
+ data_len, all_headers_len));
+
+ do
{
- Query_cache_block *new_block= *result_block;
+ ulong len= data_len + all_headers_len;
+ ulong align_len= ALIGN_SIZE(len);
+
+ if (!(new_block= allocate_block(max(min_size, align_len),
+ min_result_data_size == 0,
+ all_headers_len + min_result_data_size,
+ 1)))
+ {
+ DBUG_PRINT("warning", ("Can't allocate block for results"));
+ DBUG_RETURN(FALSE);
+ }
+
new_block->n_tables = 0;
- new_block->used = 0;
+ new_block->used = min(len, new_block->length);
new_block->type = Query_cache_block::RES_INCOMPLETE;
new_block->next = new_block->prev = new_block;
Query_cache_result *header = new_block->result();
header->parent(query_block);
- if (new_block->length < len)
- {
- /*
- We got less memory then we need (no big memory blocks) =>
- Continue to allocated more blocks until we got everything we need.
- */
- Query_cache_block *next_block;
- if ((success = allocate_data_chain(&next_block,
- len - new_block->length,
- query_block, first_block_arg)))
- double_linked_list_join(new_block, next_block);
- }
- if (success)
- {
- new_block->used = min(len, new_block->length);
-
- DBUG_PRINT("qcache", ("Block len %lu used %lu",
+ DBUG_PRINT("qcache", ("Block len %lu used %lu",
new_block->length, new_block->used));
- }
+
+ if (prev_block)
+ double_linked_list_join(prev_block, new_block);
else
- DBUG_PRINT("warning", ("Can't allocate block for continue"));
- }
- else
- DBUG_PRINT("warning", ("Can't allocate block for results"));
- DBUG_RETURN(success);
+ *result_block= new_block;
+ if (new_block->length >= len)
+ break;
+
+ /*
+ We got less memory then we need (no big memory blocks) =>
+ Continue to allocated more blocks until we got everything we need.
+ */
+ data_len= len - new_block->length;
+ prev_block= new_block;
+ } while(1);
+
+ DBUG_RETURN(TRUE);
}
/*****************************************************************************
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 6cf01896b03..e061340b0e0 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -172,6 +172,7 @@ THD::THD()
query_error= tmp_table_used= 0;
next_insert_id=last_insert_id=0;
open_tables= temporary_tables= handler_tables= derived_tables= 0;
+ hash_clear(&handler_tables_hash);
tmp_table=0;
lock=locked_tables=0;
used_tables=0;
@@ -346,11 +347,9 @@ void THD::cleanup(void)
lock=locked_tables; locked_tables=0;
close_thread_tables(this);
}
- if (handler_tables)
- {
- open_tables=handler_tables; handler_tables=0;
- close_thread_tables(this);
- }
+ mysql_ha_flush(this, (TABLE_LIST*) 0,
+ MYSQL_HA_CLOSE_FINAL | MYSQL_HA_FLUSH_ALL);
+ hash_free(&handler_tables_hash);
close_temporary_tables(this);
my_free((char*) variables.time_format, MYF(MY_ALLOW_ZERO_PTR));
my_free((char*) variables.date_format, MYF(MY_ALLOW_ZERO_PTR));
diff --git a/sql/sql_class.h b/sql/sql_class.h
index fbbb7fc7383..8896b7b658f 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -750,6 +750,7 @@ public:
*/
MYSQL_LOCK *lock; /* Current locks */
MYSQL_LOCK *locked_tables; /* Tables locked with LOCK */
+ HASH handler_tables_hash;
/*
One thread can hold up to one named user-level lock. This variable
points to a lock object if the lock is present. See item_func.cc and
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 5965732d2ce..09893970803 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -338,6 +338,8 @@ multi_delete::initialize_tables(JOIN *join)
walk=walk->next;
/* Don't use KEYREAD optimization on this table */
tbl->no_keyread=1;
+ /* Don't use record cache */
+ tbl->no_cache= 1;
tbl->used_keys.clear_all();
if (tbl->file->has_transactions())
log_delayed= transactional_tables= 1;
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index 56c1b0a1b51..ffd64134182 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -1,5 +1,4 @@
-/* Copyright (C) 2000-2003 MySQL AB
-
+/* Copyright (C) 2000-2004 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
@@ -17,9 +16,6 @@
/* HANDLER ... commands - direct access to ISAM */
-#include "mysql_priv.h"
-#include "sql_select.h"
-
/* TODO:
HANDLER blabla OPEN [ AS foobar ] [ (column-list) ]
@@ -37,190 +33,409 @@
all the sql_alloc'ed memory. It's harder to work around...
*/
+/*
+ There are two containers holding information about open handler tables.
+ The first is 'thd->handler_tables'. It is a linked list of TABLE objects.
+ It is used like 'thd->open_tables' in the table cache. The trick is to
+ exchange these two lists during open and lock of tables. Thus the normal
+ table cache code can be used.
+ The second container is a HASH. It holds objects of the type TABLE_LIST.
+ Despite its name, no lists of tables but only single structs are hashed
+ (the 'next' pointer is always NULL). The reason for theis second container
+ is, that we want handler tables to survive FLUSH TABLE commands. A table
+ affected by FLUSH TABLE must be closed so that other threads are not
+ blocked by handler tables still in use. Since we use the normal table cache
+ functions with 'thd->handler_tables', the closed tables are removed from
+ this list. Hence we need the original open information for the handler
+ table in the case that it is used again. This information is handed over
+ to mysql_ha_open() as a TABLE_LIST. So we store this information in the
+ second container, where it is not affected by FLUSH TABLE. The second
+ container is implemented as a hash for performance reasons. Consequently,
+ we use it not only for re-opening a handler table, but also for the
+ HANDLER ... READ commands. For this purpose, we store a pointer to the
+ TABLE structure (in the first container) in the TBALE_LIST object in the
+ second container. When the table is flushed, the pointer is cleared.
+*/
+
+#include "mysql_priv.h"
+#include "sql_select.h"
+#include <assert.h>
+
+#define HANDLER_TABLES_HASH_SIZE 120
+
+static enum enum_ha_read_modes rkey_to_rnext[]=
+ { RNEXT_SAME, RNEXT, RPREV, RNEXT, RPREV, RNEXT, RPREV, RPREV };
+
#define HANDLER_TABLES_HACK(thd) { \
TABLE *tmp=thd->open_tables; \
thd->open_tables=thd->handler_tables; \
thd->handler_tables=tmp; }
-static TABLE **find_table_ptr_by_name(THD *thd,const char *db,
- const char *table_name,
- bool is_alias, bool dont_lock,
- bool *was_flushed);
+static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, uint mode_flags);
+
+
+/*
+ Get hash key and hash key length.
+
+ SYNOPSIS
+ mysql_ha_hash_get_key()
+ tables Pointer to the hash object.
+ key_len_p (out) Pointer to the result for key length.
+ first Unused.
+
+ DESCRIPTION
+ The hash object is an TABLE_LIST struct.
+ The hash key is the alias name.
+ The hash key length is the alias name length plus one for the
+ terminateing NUL character.
+
+ RETURN
+ Pointer to the TABLE_LIST struct.
+*/
-int mysql_ha_open(THD *thd, TABLE_LIST *tables)
+static char *mysql_ha_hash_get_key(TABLE_LIST *tables, uint *key_len_p,
+ my_bool first __attribute__((unused)))
{
- HANDLER_TABLES_HACK(thd);
- uint counter;
- int err=open_tables(thd, tables, &counter);
- HANDLER_TABLES_HACK(thd);
- if (err)
- return -1;
+ *key_len_p= strlen(tables->alias) + 1 ; /* include '\0' in comparisons */
+ return tables->alias;
+}
- // there can be only one table in *tables
- if (!(tables->table->file->table_flags() & HA_CAN_SQL_HANDLER))
- {
- my_printf_error(ER_ILLEGAL_HA,ER(ER_ILLEGAL_HA),MYF(0), tables->alias);
- mysql_ha_close(thd, tables,1);
- return -1;
- }
- send_ok(thd);
- return 0;
+/*
+ Free an hash object.
+
+ SYNOPSIS
+ mysql_ha_hash_free()
+ tables Pointer to the hash object.
+
+ DESCRIPTION
+ The hash object is an TABLE_LIST struct.
+
+ RETURN
+ Nothing
+*/
+
+static void mysql_ha_hash_free(TABLE_LIST *tables)
+{
+ my_free((char*) tables, MYF(0));
}
/*
- Close a HANDLER table.
+ Open a HANDLER table.
SYNOPSIS
- mysql_ha_close()
+ mysql_ha_open()
thd Thread identifier.
- tables A list of tables with the first entry to close.
- dont_send_ok Suppresses the commands' ok message and
- error message and error return.
- dont_lock Suppresses the normal locking of LOCK_open.
+ tables A list of tables with the first entry to open.
+ reopen Re-open a previously opened handler table.
DESCRIPTION
Though this function takes a list of tables, only the first list entry
- will be closed. Broadcasts a COND_refresh condition.
- If mysql_ha_close() is not called from the parser, 'dont_send_ok'
- must be set.
- If the caller did already lock LOCK_open, it must set 'dont_lock'.
-
- IMPLEMENTATION
- find_table_ptr_by_name() closes the table, if a FLUSH TABLE is outstanding.
- It returns a NULL pointer in this case, but flags the situation in
- 'was_flushed'. In that case the normal ER_UNKNOWN_TABLE error messages
- is suppressed.
+ will be opened.
+ 'reopen' is set when a handler table is to be re-opened. In this case,
+ 'tables' is the pointer to the hashed TABLE_LIST object which has been
+ saved on the original open.
+ 'reopen' is also used to suppress the sending of an 'ok' message or
+ error messages.
RETURN
- 0 ok
- -1 error
+ 0 ok
+ != 0 error
*/
-int mysql_ha_close(THD *thd, TABLE_LIST *tables,
- bool dont_send_ok, bool dont_lock, bool no_alias)
+int mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
{
- TABLE **table_ptr;
- bool was_flushed;
-
- table_ptr= find_table_ptr_by_name(thd, tables->db, tables->alias,
- !no_alias, dont_lock, &was_flushed);
- if (*table_ptr)
+ TABLE_LIST *hash_tables;
+ char *db, *name, *alias;
+ uint dblen, namelen, aliaslen, counter;
+ int err;
+ DBUG_ENTER("mysql_ha_open");
+ DBUG_PRINT("enter",("'%s'.'%s' as '%s' reopen: %d",
+ tables->db, tables->real_name, tables->alias,
+ (int) reopen));
+
+ if (! hash_inited(&thd->handler_tables_hash))
+ {
+ /*
+ HASH entries are of type TABLE_LIST.
+ */
+ if (hash_init(&thd->handler_tables_hash, &my_charset_latin1,
+ HANDLER_TABLES_HASH_SIZE, 0, 0,
+ (hash_get_key) mysql_ha_hash_get_key,
+ (hash_free_key) mysql_ha_hash_free, 0))
+ goto err;
+ }
+ else if (! reopen) /* Otherwise we have 'tables' already. */
{
- (*table_ptr)->file->ha_index_or_rnd_end();
- if (!dont_lock)
- VOID(pthread_mutex_lock(&LOCK_open));
- if (close_thread_table(thd, table_ptr))
+ if (hash_search(&thd->handler_tables_hash, (byte*) tables->alias,
+ strlen(tables->alias) + 1))
{
- /* Tell threads waiting for refresh that something has happened */
- VOID(pthread_cond_broadcast(&COND_refresh));
+ DBUG_PRINT("info",("duplicate '%s'", tables->alias));
+ if (! reopen)
+ my_printf_error(ER_NONUNIQ_TABLE, ER(ER_NONUNIQ_TABLE),
+ MYF(0), tables->alias);
+ goto err;
}
- if (!dont_lock)
- VOID(pthread_mutex_unlock(&LOCK_open));
}
- else if (!was_flushed && !dont_send_ok)
+
+ /*
+ open_tables() will set 'tables->table' if successful.
+ It must be NULL for a real open when calling open_tables().
+ */
+ DBUG_ASSERT(! tables->table);
+ HANDLER_TABLES_HACK(thd);
+ err=open_tables(thd, tables, &counter);
+ HANDLER_TABLES_HACK(thd);
+ if (err)
+ goto err;
+
+ /* There can be only one table in '*tables'. */
+ if (! (tables->table->file->table_flags() & HA_CAN_SQL_HANDLER))
+ {
+ if (! reopen)
+ my_printf_error(ER_ILLEGAL_HA,ER(ER_ILLEGAL_HA),MYF(0), tables->alias);
+ mysql_ha_close(thd, tables);
+ goto err;
+ }
+
+ if (! reopen)
{
- my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0),
- tables->alias, "HANDLER");
- return -1;
+ /* copy the TABLE_LIST struct */
+ dblen= strlen(tables->db) + 1;
+ namelen= strlen(tables->real_name) + 1;
+ aliaslen= strlen(tables->alias) + 1;
+ if (!(my_multi_malloc(MYF(MY_WME),
+ &hash_tables, sizeof(*hash_tables),
+ &db, dblen,
+ &name, namelen,
+ &alias, aliaslen,
+ NullS)))
+ goto err;
+ /* structure copy */
+ *hash_tables= *tables;
+ hash_tables->db= db;
+ hash_tables->real_name= name;
+ hash_tables->alias= alias;
+ memcpy(hash_tables->db, tables->db, dblen);
+ memcpy(hash_tables->real_name, tables->real_name, namelen);
+ memcpy(hash_tables->alias, tables->alias, aliaslen);
+
+ /* add to hash */
+ if (my_hash_insert(&thd->handler_tables_hash, (byte*) hash_tables))
+ {
+ mysql_ha_close(thd, tables);
+ goto err;
+ }
}
- if (!dont_send_ok)
+
+ if (! reopen)
send_ok(thd);
- return 0;
+ DBUG_PRINT("exit",("OK"));
+ DBUG_RETURN(0);
+
+err:
+ DBUG_PRINT("exit",("ERROR"));
+ DBUG_RETURN(-1);
}
/*
- Close a list of HANDLER tables.
+ Close a HANDLER table.
SYNOPSIS
- mysql_ha_close_list()
+ mysql_ha_close()
thd Thread identifier.
- tables The list of tables to close. If NULL,
- close all HANDLER tables.
- flushed Close only tables which are marked flushed.
- Used only if tables is NULL.
+ tables A list of tables with the first entry to close.
DESCRIPTION
- The list of HANDLER tables may be NULL, in which case all HANDLER
- tables are closed. Broadcasts a COND_refresh condition, for
- every table closed. If 'tables' is NULL and 'flushed' is set,
- all HANDLER tables marked for flush are closed.
- The caller must lock LOCK_open.
-
- IMPLEMENTATION
- find_table_ptr_by_name() closes the table, if it is marked for flush.
- It returns a NULL pointer in this case, but flags the situation in
- 'was_flushed'. In that case the normal ER_UNKNOWN_TABLE error messages
- is suppressed.
+ Though this function takes a list of tables, only the first list entry
+ will be closed. Broadcasts a COND_refresh condition.
RETURN
- 0 ok
+ 0 ok
+ != 0 error
*/
-int mysql_ha_close_list(THD *thd, TABLE_LIST *tables, bool flushed)
+int mysql_ha_close(THD *thd, TABLE_LIST *tables)
{
- TABLE_LIST *tl_item;
+ TABLE_LIST *hash_tables;
TABLE **table_ptr;
-
- if (tables)
+ bool was_flushed= FALSE;
+ bool not_opened;
+ DBUG_ENTER("mysql_ha_close");
+ DBUG_PRINT("enter",("'%s'.'%s' as '%s'",
+ tables->db, tables->real_name, tables->alias));
+
+ if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash,
+ (byte*) tables->alias,
+ strlen(tables->alias) + 1)))
{
- for (tl_item= tables ; tl_item; tl_item= tl_item->next)
+ /*
+ Though we could take the table pointer from hash_tables->table,
+ we must follow the thd->handler_tables chain anyway, as we need the
+ address of the 'next' pointer referencing this table
+ for close_thread_table().
+ */
+ for (table_ptr= &(thd->handler_tables);
+ *table_ptr && (*table_ptr != hash_tables->table);
+ table_ptr= &(*table_ptr)->next);
+
+#if MYSQL_VERSION_ID < 40100
+ if (*tables->db && strcmp(hash_tables->db, tables->db))
{
- mysql_ha_close(thd, tl_item, /*dont_send_ok*/ 1,
- /*dont_lock*/ 1, /*no_alias*/ 1);
+ DBUG_PRINT("info",("wrong db"));
+ hash_tables= NULL;
}
- }
- else
- {
- table_ptr= &(thd->handler_tables);
- while (*table_ptr)
+ else
+#endif
{
- if (! flushed || ((*table_ptr)->version != refresh_version))
+ if (*table_ptr)
{
- (*table_ptr)->file->ha_index_or_rnd_end();
+ (*table_ptr)->file->ha_index_or_rnd_end();
+ VOID(pthread_mutex_lock(&LOCK_open));
if (close_thread_table(thd, table_ptr))
{
/* Tell threads waiting for refresh that something has happened */
VOID(pthread_cond_broadcast(&COND_refresh));
}
- continue;
+ VOID(pthread_mutex_unlock(&LOCK_open));
}
- table_ptr= &((*table_ptr)->next);
+
+ hash_delete(&thd->handler_tables_hash, (byte*) hash_tables);
}
}
- return 0;
+
+ if (! hash_tables)
+ {
+#if MYSQL_VERSION_ID < 40100
+ char buff[MAX_DBKEY_LENGTH];
+ if (*tables->db)
+ strxnmov(buff, sizeof(buff), tables->db, ".", tables->real_name, NullS);
+ else
+ strncpy(buff, tables->alias, sizeof(buff));
+ my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0),
+ buff, "HANDLER");
+#else
+ my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0),
+ tables->alias, "HANDLER");
+#endif
+ DBUG_PRINT("exit",("ERROR"));
+ DBUG_RETURN(-1);
+ }
+
+ send_ok(thd);
+ DBUG_PRINT("exit", ("OK"));
+ DBUG_RETURN(0);
}
-static enum enum_ha_read_modes rkey_to_rnext[]=
- { RNEXT_SAME, RNEXT, RPREV, RNEXT, RPREV, RNEXT, RPREV, RPREV };
+/*
+ Read from a HANDLER table.
+
+ SYNOPSIS
+ mysql_ha_read()
+ thd Thread identifier.
+ tables A list of tables with the first entry to read.
+ mode
+ keyname
+ key_expr
+ ha_rkey_mode
+ cond
+ select_limit
+ offset_limit
+ RETURN
+ 0 ok
+ != 0 error
+*/
+
int mysql_ha_read(THD *thd, TABLE_LIST *tables,
enum enum_ha_read_modes mode, char *keyname, List<Item> *key_expr,
enum ha_rkey_function ha_rkey_mode, Item *cond,
ha_rows select_limit,ha_rows offset_limit)
{
- int err, keyno=-1;
- bool was_flushed;
- TABLE *table= *find_table_ptr_by_name(thd, tables->db, tables->alias,
- /*is_alias*/ 1, /*dont_lock*/ 0,
- &was_flushed);
+ TABLE_LIST *hash_tables;
+ TABLE *table;
+ MYSQL_LOCK *lock;
+ List<Item> list;
+ Protocol *protocol= thd->protocol;
+ char buff[MAX_FIELD_WIDTH];
+ String buffer(buff, sizeof(buff), system_charset_info);
+ int err, keyno= -1;
+ uint num_rows;
+ byte *key;
+ uint key_len;
+ bool was_flushed;
+ DBUG_ENTER("mysql_ha_read");
+ DBUG_PRINT("enter",("'%s'.'%s' as '%s'",
+ tables->db, tables->real_name, tables->alias));
+
+ LINT_INIT(key);
+ LINT_INIT(key_len);
+
+ list.push_front(new Item_field(NULL,NULL,"*"));
+ List_iterator<Item> it(list);
+ it++;
+
+ if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash,
+ (byte*) tables->alias,
+ strlen(tables->alias) + 1)))
+ {
+ table= hash_tables->table;
+ DBUG_PRINT("info-in-hash",("'%s'.'%s' as '%s' tab %p",
+ hash_tables->db, hash_tables->real_name,
+ hash_tables->alias, table));
+ if (!table)
+ {
+ /*
+ The handler table has been closed. Re-open it.
+ */
+ if (mysql_ha_open(thd, hash_tables, 1))
+ {
+ DBUG_PRINT("exit",("reopen failed"));
+ goto err0;
+ }
+
+ table= hash_tables->table;
+ DBUG_PRINT("info",("re-opened '%s'.'%s' as '%s' tab %p",
+ hash_tables->db, hash_tables->real_name,
+ hash_tables->alias, table));
+ }
+
+#if MYSQL_VERSION_ID < 40100
+ if (*tables->db && strcmp(table->table_cache_key, tables->db))
+ {
+ DBUG_PRINT("info",("wrong db"));
+ table= NULL;
+ }
+#endif
+ }
+ else
+ table= NULL;
+
if (!table)
{
- my_printf_error(ER_UNKNOWN_TABLE,ER(ER_UNKNOWN_TABLE),MYF(0),
- tables->alias,"HANDLER");
- return -1;
+#if MYSQL_VERSION_ID < 40100
+ char buff[MAX_DBKEY_LENGTH];
+ if (*tables->db)
+ strxnmov(buff, sizeof(buff), tables->db, ".", tables->real_name, NullS);
+ else
+ strncpy(buff, tables->alias, sizeof(buff));
+ my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0),
+ buff, "HANDLER");
+#else
+ my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0),
+ tables->alias, "HANDLER");
+#endif
+ goto err0;
}
tables->table=table;
if (cond && (cond->fix_fields(thd, tables, &cond) || cond->check_cols(1)))
- return -1;
+ goto err0;
- /* InnoDB needs to know that this table handle is used in the HANDLER */
-
- table->file->init_table_handle_for_HANDLER();
+ table->file->init_table_handle_for_HANDLER(); // Only InnoDB requires it
if (keyname)
{
@@ -228,34 +443,22 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
{
my_printf_error(ER_KEY_DOES_NOT_EXITS,ER(ER_KEY_DOES_NOT_EXITS),MYF(0),
keyname,tables->alias);
- return -1;
+ goto err0;
}
table->file->ha_index_or_rnd_end();
table->file->ha_index_init(keyno);
}
- List<Item> list;
- list.push_front(new Item_field(NULL,NULL,"*"));
- List_iterator<Item> it(list);
- Protocol *protocol= thd->protocol;
- char buff[MAX_FIELD_WIDTH];
- String buffer(buff, sizeof(buff), system_charset_info);
- uint num_rows;
- byte *key;
- uint key_len;
- LINT_INIT(key);
- LINT_INIT(key_len);
-
- it++; // Skip first NULL field
-
- insert_fields(thd,tables,tables->db,tables->alias,&it);
+ if (insert_fields(thd,tables,tables->db,tables->alias,&it))
+ goto err0;
select_limit+=offset_limit;
protocol->send_fields(&list,1);
HANDLER_TABLES_HACK(thd);
- MYSQL_LOCK *lock=mysql_lock_tables(thd,&tables->table,1);
+ lock= mysql_lock_tables(thd, &tables->table, 1);
HANDLER_TABLES_HACK(thd);
+
if (!lock)
goto err0; // mysql_lock_tables() printed error message already
@@ -379,83 +582,155 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
ok:
mysql_unlock_tables(thd,lock);
send_eof(thd);
- return 0;
+ DBUG_PRINT("exit",("OK"));
+ DBUG_RETURN(0);
+
err:
mysql_unlock_tables(thd,lock);
err0:
- return -1;
+ DBUG_PRINT("exit",("ERROR"));
+ DBUG_RETURN(-1);
}
/*
- Find a HANDLER table by name.
+ Flush (close) a list of HANDLER tables.
SYNOPSIS
- find_table_ptr_by_name()
+ mysql_ha_flush()
thd Thread identifier.
- db Database (schema) name.
- table_name Table name ;-).
- is_alias Table name may be an alias name.
- dont_lock Suppresses the normal locking of LOCK_open.
+ tables The list of tables to close. If NULL,
+ close all HANDLER tables [marked as flushed].
+ mode_flags MYSQL_HA_CLOSE_FINAL finally close the table.
+ MYSQL_HA_REOPEN_ON_USAGE mark for reopen.
+ MYSQL_HA_FLUSH_ALL flush all tables, not only
+ those marked for flush.
DESCRIPTION
- Find the table 'db'.'table_name' in the list of HANDLER tables of the
- thread 'thd'. If the table has been marked by FLUSH TABLE(S), close it,
- flag this situation in '*was_flushed' and broadcast a COND_refresh
- condition.
- An empty database (schema) name matches all database (schema) names.
- If the caller did already lock LOCK_open, it must set 'dont_lock'.
-
- IMPLEMENTATION
- Just in case that the table is twice in 'thd->handler_tables' (!?!),
- the loop does not break when the table was flushed. If another table
- by that name was found and not flushed, '*was_flushed' is cleared again,
- since a pointer to an open HANDLER table is returned.
+ The list of HANDLER tables may be NULL, in which case all HANDLER
+ tables are closed (if MYSQL_HA_FLUSH_ALL) is set.
+ If 'tables' is NULL and MYSQL_HA_FLUSH_ALL is not set,
+ all HANDLER tables marked for flush are closed.
+ Broadcasts a COND_refresh condition, for every table closed.
+ The caller must lock LOCK_open.
+
+ NOTE
+ Since mysql_ha_flush() is called when the base table has to be closed,
+ we compare real table names, not aliases. Hence, database names matter.
RETURN
- *was_flushed Table has been closed due to FLUSH TABLE.
- NULL A HANDLER Table by that name does not exist (any more).
- != NULL Pointer to the TABLE structure.
+ 0 ok
*/
-static TABLE **find_table_ptr_by_name(THD *thd, const char *db,
- const char *table_name,
- bool is_alias, bool dont_lock,
- bool *was_flushed)
+int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags)
{
- int dblen;
- TABLE **table_ptr;
-
- DBUG_ASSERT(db);
- dblen= strlen(db);
- table_ptr= &(thd->handler_tables);
- *was_flushed= FALSE;
+ TABLE_LIST **tmp_tables_p;
+ TABLE_LIST *tmp_tables;
+ TABLE **table_ptr;
+ bool was_flushed;
+ DBUG_ENTER("mysql_ha_flush");
+ DBUG_PRINT("enter", ("tables: %p mode_flags: 0x%02x", tables, mode_flags));
- for (TABLE *table= *table_ptr; table ; table= *table_ptr)
+ if (tables)
{
- if ((db == any_db || !memcmp(table->table_cache_key, db, dblen)) &&
- !my_strcasecmp(system_charset_info,
- (is_alias ? table->table_name : table->real_name),
- table_name))
+ /* Close all tables in the list. */
+ for (tmp_tables= tables ; tmp_tables; tmp_tables= tmp_tables->next)
{
- if (table->version != refresh_version)
+ DBUG_PRINT("info-in-tables-list",("'%s'.'%s' as '%s'",
+ tmp_tables->db, tmp_tables->real_name,
+ tmp_tables->alias));
+ /* Close all currently open handler tables with the same base table. */
+ table_ptr= &(thd->handler_tables);
+ while (*table_ptr)
{
- if (!dont_lock)
- VOID(pthread_mutex_lock(&LOCK_open));
- if (close_thread_table(thd, table_ptr))
+ if ((! *tmp_tables->db ||
+ ! my_strcasecmp(&my_charset_latin1, (*table_ptr)->table_cache_key,
+ tmp_tables->db)) &&
+ ! my_strcasecmp(&my_charset_latin1, (*table_ptr)->real_name,
+ tmp_tables->real_name))
{
- /* Tell threads waiting for refresh that something has happened */
- VOID(pthread_cond_broadcast(&COND_refresh));
+ DBUG_PRINT("info",("*table_ptr '%s'.'%s' as '%s'",
+ (*table_ptr)->table_cache_key,
+ (*table_ptr)->real_name,
+ (*table_ptr)->table_name));
+ mysql_ha_flush_table(thd, table_ptr, mode_flags);
+ continue;
}
- if (!dont_lock)
- VOID(pthread_mutex_unlock(&LOCK_open));
- *was_flushed= TRUE;
+ table_ptr= &(*table_ptr)->next;
+ }
+ /* end of handler_tables list */
+ }
+ /* end of flush tables list */
+ }
+ else
+ {
+ /* Close all currently open tables [which are marked for flush]. */
+ table_ptr= &(thd->handler_tables);
+ while (*table_ptr)
+ {
+ if ((mode_flags & MYSQL_HA_FLUSH_ALL) ||
+ ((*table_ptr)->version != refresh_version))
+ {
+ mysql_ha_flush_table(thd, table_ptr, mode_flags);
continue;
}
- *was_flushed= FALSE;
- break;
+ table_ptr= &(*table_ptr)->next;
}
- table_ptr= &(table->next);
}
- return table_ptr;
+
+ DBUG_RETURN(0);
+}
+
+/*
+ Flush (close) a table.
+
+ SYNOPSIS
+ mysql_ha_flush_table()
+ thd Thread identifier.
+ table The table to close.
+ mode_flags MYSQL_HA_CLOSE_FINAL finally close the table.
+ MYSQL_HA_REOPEN_ON_USAGE mark for reopen.
+
+ DESCRIPTION
+ Broadcasts a COND_refresh condition, for every table closed.
+ The caller must lock LOCK_open.
+
+ RETURN
+ 0 ok
+*/
+
+static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, uint mode_flags)
+{
+ TABLE_LIST *hash_tables;
+ TABLE *table= *table_ptr;
+ bool was_flushed;
+ DBUG_ENTER("mysql_ha_flush_table");
+ DBUG_PRINT("enter",("'%s'.'%s' as '%s' flags: 0x%02x",
+ table->table_cache_key, table->real_name,
+ table->table_name, mode_flags));
+
+ if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash,
+ (*table_ptr)->table_name,
+ strlen((*table_ptr)->table_name) + 1)))
+ {
+ if (! (mode_flags & MYSQL_HA_REOPEN_ON_USAGE))
+ {
+ /* This is a final close. Remove from hash. */
+ hash_delete(&thd->handler_tables_hash, (byte*) hash_tables);
+ }
+ else
+ {
+ /* Mark table as closed, ready for re-open. */
+ hash_tables->table= NULL;
+ }
+ }
+
+ (*table_ptr)->file->ha_index_or_rnd_end();
+ if (close_thread_table(thd, table_ptr))
+ {
+ /* Tell threads waiting for refresh that something has happened */
+ VOID(pthread_cond_broadcast(&COND_refresh));
+ }
+
+ DBUG_RETURN(0);
}
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index dffe7bcb2b0..d198855a2d3 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -599,7 +599,7 @@ typedef struct st_lex
USER_RESOURCES mqh;
ulong thread_id,type;
enum_sql_command sql_command;
- thr_lock_type lock_option;
+ thr_lock_type lock_option, multi_lock_option;
enum SSL_type ssl_type; /* defined in violite.h */
enum my_lex_states next_state;
enum enum_duplicates duplicates;
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index f71d5a311ab..a84b63c270b 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -14,8 +14,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-// Sasha Pachev <sasha@mysql.com> is currently in charge of this file
-
#include "mysql_priv.h"
#ifdef HAVE_REPLICATION
diff --git a/sql/sql_repl.h b/sql/sql_repl.h
index e7001c1fe1e..3c17540b664 100644
--- a/sql/sql_repl.h
+++ b/sql/sql_repl.h
@@ -1,3 +1,19 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB & Sasha
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
#ifdef HAVE_REPLICATION
#include "slave.h"
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 156c20edc0c..7a389a906c0 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -7188,7 +7188,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
if (keys.is_set(nr))
{
int flag;
- if (flag=test_if_order_by_key(order, table, nr, &not_used))
+ if ((flag= test_if_order_by_key(order, table, nr, &not_used)))
{
if (!no_changes)
{
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index bd145a1de59..c5cd2860e03 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB
+/* Copyright (C) 2000-2004 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -387,27 +387,23 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path,
{ /* Return databases */
#ifdef USE_SYMDIR
char *ext;
+ char buff[FN_REFLEN];
if (my_use_symdir && !strcmp(ext=fn_ext(file->name), ".sym"))
{
/* Only show the sym file if it points to a directory */
- char buff[FN_REFLEN], *end;
- MY_STAT status;
+ char *end;
*ext=0; /* Remove extension */
unpack_dirname(buff, file->name);
end= strend(buff);
if (end != buff && end[-1] == FN_LIBCHAR)
end[-1]= 0; // Remove end FN_LIBCHAR
- if (!my_stat(buff, &status, MYF(0)) ||
- !MY_S_ISDIR(status.st_mode))
- continue;
- }
- else
+ if (!my_stat(buff, file->mystat, MYF(0)))
+ continue;
+ }
#endif
- {
if (file->name[0] == '.' || !MY_S_ISDIR(file->mystat->st_mode) ||
(wild && wild_compare(file->name,wild,0)))
continue;
- }
}
else
{
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 3d5aaf0c2ec..76975bf71c6 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -197,7 +197,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
for (table=tables ; table ; table=table->next)
{
char *db=table->db;
- mysql_ha_close(thd, table, /*dont_send_ok*/ 1, /*dont_lock*/ 1);
+ mysql_ha_flush(thd, table, MYSQL_HA_CLOSE_FINAL);
if (!close_temporary_table(thd, db, table->real_name))
{
tmp_table_deleted=1;
@@ -1762,7 +1762,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
if (protocol->send_fields(&field_list, 1))
DBUG_RETURN(-1);
- mysql_ha_close(thd, tables, /*dont_send_ok*/ 1, /*dont_lock*/ 1);
+ mysql_ha_flush(thd, tables, MYSQL_HA_CLOSE_FINAL);
for (table = tables; table; table = table->next)
{
char table_name[NAME_LEN*2+2];
@@ -2265,31 +2265,32 @@ int mysql_check_table(THD* thd, TABLE_LIST* tables,HA_CHECK_OPT* check_opt)
&handler::check));
}
+
/* table_list should contain just one table */
-int mysql_discard_or_import_tablespace(THD *thd,
- TABLE_LIST *table_list,
- enum tablespace_op_type tablespace_op)
+static int
+mysql_discard_or_import_tablespace(THD *thd,
+ TABLE_LIST *table_list,
+ enum tablespace_op_type tablespace_op)
{
TABLE *table;
my_bool discard;
int error;
DBUG_ENTER("mysql_discard_or_import_tablespace");
- /* Note that DISCARD/IMPORT TABLESPACE always is the only operation in an
- ALTER TABLE */
+ /*
+ Note that DISCARD/IMPORT TABLESPACE always is the only operation in an
+ ALTER TABLE
+ */
thd->proc_info="discard_or_import_tablespace";
- if (tablespace_op == DISCARD_TABLESPACE)
- discard = TRUE;
- else
- discard = FALSE;
-
- thd->tablespace_op=TRUE; /* we set this flag so that ha_innobase::open
- and ::external_lock() do not complain when we
- lock the table */
- mysql_ha_close(thd, table_list, /*dont_send_ok*/ 1, /*dont_lock*/ 1);
+ discard= test(tablespace_op == DISCARD_TABLESPACE);
+ /*
+ We set this flag so that ha_innobase::open and ::external_lock() do
+ not complain when we lock the table
+ */
+ thd->tablespace_op= TRUE;
if (!(table=open_ltable(thd,table_list,TL_WRITE)))
{
thd->tablespace_op=FALSE;
@@ -2303,8 +2304,10 @@ int mysql_discard_or_import_tablespace(THD *thd,
if (error)
goto err;
- /* The 0 in the call below means 'not in a transaction', which means
- immediate invalidation; that is probably what we wish here */
+ /*
+ The 0 in the call below means 'not in a transaction', which means
+ immediate invalidation; that is probably what we wish here
+ */
query_cache_invalidate3(thd, table_list, 0);
/* The ALTER TABLE is always in its own transaction */
@@ -2567,8 +2570,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
new_db= db;
used_fields=create_info->used_fields;
- mysql_ha_close(thd, table_list, /*dont_send_ok*/ 1, /*dont_lock*/ 1);
-
+ mysql_ha_flush(thd, table_list, MYSQL_HA_CLOSE_FINAL);
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */
if (alter_info->tablespace_op != NO_TABLESPACE_OP)
DBUG_RETURN(mysql_discard_or_import_tablespace(thd,table_list,
@@ -3300,17 +3302,19 @@ copy_data_between_tables(TABLE *from,TABLE *to,
List<Item> all_fields;
ha_rows examined_rows;
bool auto_increment_field_copied= 0;
- ulong old_sql_mode;
- bool no_auto_on_zero;
+ ulong save_sql_mode;
DBUG_ENTER("copy_data_between_tables");
if (!(copy= new Copy_field[to->fields]))
DBUG_RETURN(-1); /* purecov: inspected */
- to->file->external_lock(thd,F_WRLCK);
+ if (to->file->external_lock(thd, F_WRLCK))
+ DBUG_RETURN(-1);
from->file->info(HA_STATUS_VARIABLE);
to->file->start_bulk_insert(from->file->records);
+ save_sql_mode= thd->variables.sql_mode;
+
List_iterator<create_field> it(create);
create_field *def;
copy_end=copy;
@@ -3320,7 +3324,17 @@ copy_data_between_tables(TABLE *from,TABLE *to,
if (def->field)
{
if (*ptr == to->next_number_field)
+ {
auto_increment_field_copied= TRUE;
+ /*
+ If we are going to copy contents of one auto_increment column to
+ another auto_increment column it is sensible to preserve zeroes.
+ This condition also covers case when we are don't actually alter
+ auto_increment column.
+ */
+ if (def->field == from->found_next_number_field)
+ thd->variables.sql_mode|= MODE_NO_AUTO_VALUE_ON_ZERO;
+ }
(copy_end++)->set(*ptr,def->field,0);
}
@@ -3360,11 +3374,6 @@ copy_data_between_tables(TABLE *from,TABLE *to,
goto err;
}
- /* Turn on NO_AUTO_VALUE_ON_ZERO if not already on */
- old_sql_mode= thd->variables.sql_mode;
- if (!(no_auto_on_zero= thd->variables.sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO))
- thd->variables.sql_mode|= MODE_NO_AUTO_VALUE_ON_ZERO;
-
/* Handler must be told explicitly to retrieve all columns, because
this function does not set field->query_id in the columns to the
current query id */
@@ -3422,10 +3431,6 @@ copy_data_between_tables(TABLE *from,TABLE *to,
ha_enable_transaction(thd,TRUE);
- /* Turn off NO_AUTO_VALUE_ON_ZERO if it was not already off */
- if (!no_auto_on_zero)
- thd->variables.sql_mode= old_sql_mode;
-
/*
Ensure that the new table is saved properly to disk so that we
can do a rename
@@ -3434,12 +3439,14 @@ copy_data_between_tables(TABLE *from,TABLE *to,
error=1;
if (ha_commit(thd))
error=1;
- if (to->file->external_lock(thd,F_UNLCK))
- error=1;
+
err:
+ thd->variables.sql_mode= save_sql_mode;
free_io_cache(from);
*copied= found_count;
*deleted=delete_count;
+ if (to->file->external_lock(thd,F_UNLCK))
+ error=1;
DBUG_RETURN(error > 0 ? -1 : 0);
}
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 1e8c6576dec..b46cfc05538 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -346,6 +346,7 @@ int st_select_lex_unit::exec()
SELECT_LEX *lex_select_save= thd->lex->current_select;
SELECT_LEX *select_cursor=first_select_in_union();
ulonglong add_rows=0;
+ ha_rows examined_rows= 0;
DBUG_ENTER("st_select_lex_unit::exec");
if (executed && !uncacheable && !describe)
@@ -426,6 +427,7 @@ int st_select_lex_unit::exec()
offset_limit_cnt= sl->offset_limit;
if (!res && union_result->flush())
{
+ examined_rows+= thd->examined_row_count;
thd->lex->current_select= lex_select_save;
DBUG_RETURN(1);
}
@@ -502,7 +504,10 @@ int st_select_lex_unit::exec()
fake_select_lex->table_list.empty();
if (!res)
+ {
thd->limit_found_rows = (ulonglong)table->file->records + add_rows;
+ thd->examined_row_count+= examined_rows;
+ }
/*
Mark for slow query log if any of the union parts didn't use
indexes efficiently
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index c6fb3d6e415..d3597f274dc 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -303,6 +303,7 @@ int mysql_update(THD *thd,
else if (handle_duplicates != DUP_IGNORE ||
error != HA_ERR_FOUND_DUPP_KEY)
{
+ thd->fatal_error(); // Force error message
table->file->print_error(error,MYF(0));
error= 1;
break;
@@ -449,6 +450,24 @@ int mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
***************************************************************************/
/*
+ Get table map for list of Item_field
+*/
+
+static table_map get_table_map(List<Item> *items)
+{
+ List_iterator_fast<Item> item_it(*items);
+ Item_field *item;
+ table_map map= 0;
+
+ while ((item= (Item_field *) item_it++))
+ map|= item->used_tables();
+ DBUG_PRINT("info",("table_map: 0x%08x", map));
+ return map;
+}
+
+
+
+/*
Setup multi-update handling and call SELECT to do the join
*/
@@ -465,107 +484,177 @@ int mysql_multi_update(THD *thd,
multi_update *result;
TABLE_LIST *tl;
TABLE_LIST *update_list= (TABLE_LIST*) thd->lex->select_lex.table_list.first;
- table_map item_tables= 0, derived_tables= 0;
+ List<Item> total_list;
+ const bool using_lock_tables= thd->locked_tables != 0;
+ bool initialized_dervied= 0;
DBUG_ENTER("mysql_multi_update");
- if ((res=open_and_lock_tables(thd,table_list)))
- DBUG_RETURN(res);
-
select_lex->select_limit= HA_POS_ERROR;
/*
- Ensure that we have update privilege for all tables and columns in the
- SET part
+ The following loop is here to to ensure that we only lock tables
+ that we are going to update with a write lock
*/
- for (tl= update_list; tl; tl= tl->next)
+ for (;;)
{
- TABLE *table= tl->table;
- /*
- Update of derived tables is checked later
- We don't check privileges here, becasue then we would get error
- "UPDATE command denided .. for column N" instead of
- "Target table ... is not updatable"
- */
- if (!tl->derived)
- table->grant.want_privilege= (UPDATE_ACL & ~table->grant.privilege);
- }
+ table_map update_tables, derived_tables=0;
+ uint tnr, table_count;
- /* Assign table map values to check updatability of derived tables */
- {
- uint tablenr=0;
- for (TABLE_LIST *table_list= update_list;
- table_list;
- table_list= table_list->next, tablenr++)
+ if ((res=open_tables(thd, table_list, &table_count)))
+ DBUG_RETURN(res);
+
+ /* Only need to call lock_tables if we are not using LOCK TABLES */
+ if (!using_lock_tables &&
+ ((res= lock_tables(thd, table_list, table_count))))
+ DBUG_RETURN(res);
+
+ if (!initialized_dervied)
{
- table_list->table->map= (table_map) 1 << tablenr;
+ initialized_dervied= 1;
+ relink_tables_for_derived(thd);
+ if ((res= mysql_handle_derived(thd->lex)))
+ DBUG_RETURN(res);
}
- }
-
- if (setup_fields(thd, 0, update_list, *fields, 1, 0, 0))
- DBUG_RETURN(-1);
- /* Find tables used in items */
- {
- List_iterator_fast<Item> it(*fields);
- Item *item;
- while ((item= it++))
+ /*
+ Ensure that we have update privilege for all tables and columns in the
+ SET part
+ While we are here, initialize the table->map field to check which
+ tables are updated and updatability of derived tables
+ */
+ for (tl= update_list, tnr=0 ; tl ; tl=tl->next)
{
- item_tables|= item->used_tables();
+ TABLE *table= tl->table;
+ /*
+ Update of derived tables is checked later
+ We don't check privileges here, becasue then we would get error
+ "UPDATE command denided .. for column N" instead of
+ "Target table ... is not updatable"
+ */
+ if (!tl->derived)
+ table->grant.want_privilege= (UPDATE_ACL & ~table->grant.privilege);
+ table->map= (table_map) 1 << (tnr++);
}
- }
- /*
- Count tables and setup timestamp handling
- */
- for (tl= update_list; tl; tl= tl->next)
- {
- TABLE *table= tl->table;
+ if (setup_fields(thd, 0, update_list, *fields, 1, 0, 0))
+ DBUG_RETURN(-1);
- /* We only need SELECT privilege for columns in the values list */
- table->grant.want_privilege= (SELECT_ACL & ~table->grant.privilege);
- // Only set timestamp column if this is not modified
- if (table->timestamp_field &&
- table->timestamp_field->query_id == thd->query_id)
- table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
+ update_tables= get_table_map(fields);
- /* if table will be updated then check that it is unique */
- if (table->map & item_tables)
+ /* Unlock the tables in preparation for relocking */
+ if (!using_lock_tables)
+ {
+ mysql_unlock_tables(thd, thd->lock);
+ thd->lock= 0;
+ }
+
+ /*
+ Count tables and setup timestamp handling
+ Set also the table locking strategy according to the update map
+ */
+ for (tl= update_list; tl; tl= tl->next)
{
- /*
- Multi-update can't be constructed over-union => we always have
- single SELECT on top and have to check underlaying SELECTs of it
- */
- if (select_lex->check_updateable_in_subqueries(tl->db,
- tl->real_name))
+ TABLE *table= tl->table;
+ /* if table will be updated then check that it is unique */
+ if (table->map & update_tables)
+ {
+ /*
+ Multi-update can't be constructed over-union => we always have
+ single SELECT on top and have to check underlaying SELECTs of it
+ */
+ if (select_lex->check_updateable_in_subqueries(tl->db,
+ tl->real_name))
+ {
+ my_error(ER_UPDATE_TABLE_USED, MYF(0),
+ tl->real_name);
+ DBUG_RETURN(-1);
+ }
+ DBUG_PRINT("info",("setting table `%s` for update", tl->alias));
+ tl->lock_type= thd->lex->multi_lock_option;
+ tl->updating= 1;
+ }
+ else
{
- my_error(ER_UPDATE_TABLE_USED, MYF(0),
- tl->real_name);
- DBUG_RETURN(-1);
+ DBUG_PRINT("info",("setting table `%s` for read-only", tl->alias));
+ tl->lock_type= TL_READ;
+ tl->updating= 0;
}
+ if (tl->derived)
+ derived_tables|= table->map;
+ else if (!using_lock_tables)
+ tl->table->reginfo.lock_type= tl->lock_type;
}
- if (tl->derived)
- derived_tables|= table->map;
- }
- if (thd->lex->derived_tables && (item_tables & derived_tables))
- {
- // find derived table which cause error
- for (tl= update_list; tl; tl= tl->next)
+ if (thd->lex->derived_tables && (update_tables & derived_tables))
+ {
+ // find derived table which cause error
+ for (tl= update_list; tl; tl= tl->next)
+ {
+ if (tl->derived && (update_tables & tl->table->map))
+ {
+ my_printf_error(ER_NON_UPDATABLE_TABLE, ER(ER_NON_UPDATABLE_TABLE),
+ MYF(0), tl->alias, "UPDATE");
+ DBUG_RETURN(-1);
+ }
+ }
+ }
+
+ /* Relock the tables with the correct modes */
+ res= lock_tables(thd, table_list, table_count);
+ if (using_lock_tables)
{
- if (tl->derived && (item_tables & tl->table->map))
+ if (res)
+ DBUG_RETURN(res);
+ break; // Don't have to do setup_field()
+ }
+
+ /*
+ We must setup fields again as the file may have been reopened
+ during lock_tables
+ */
+ {
+ List_iterator_fast<Item> field_it(*fields);
+ Item_field *item;
+
+ while ((item= (Item_field *) field_it++))
{
- my_printf_error(ER_NON_UPDATABLE_TABLE, ER(ER_NON_UPDATABLE_TABLE),
- MYF(0), tl->alias, "UPDATE");
- DBUG_RETURN(-1);
+ item->field->query_id= 0;
+ item->cleanup();
}
}
+ if (setup_fields(thd, 0, update_list, *fields, 1, 0, 0))
+ DBUG_RETURN(-1);
+ /*
+ If lock succeded and the table map didn't change since the above lock
+ we can continue.
+ */
+ if (!res && update_tables == get_table_map(fields))
+ break;
+
+ /*
+ There was some very unexpected changes in the table definition between
+ open tables and lock tables. Close tables and try again.
+ */
+ close_thread_tables(thd);
+ }
+
+ /* Setup timestamp handling */
+ for (tl= update_list; tl; tl= tl->next)
+ {
+ TABLE *table= tl->table;
+ /* Only set timestamp column if this is not modified */
+ if (table->timestamp_field &&
+ table->timestamp_field->query_id == thd->query_id)
+ table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
+
+ /* We only need SELECT privilege for columns in the values list */
+ table->grant.want_privilege= (SELECT_ACL & ~table->grant.privilege);
}
if (!(result=new multi_update(thd, update_list, fields, values,
handle_duplicates)))
DBUG_RETURN(-1);
- List<Item> total_list;
res= mysql_select(thd, &select_lex->ref_pointer_array,
select_lex->get_table_list(), select_lex->with_wild,
total_list,
@@ -597,7 +686,7 @@ int multi_update::prepare(List<Item> &not_used_values,
{
TABLE_LIST *table_ref;
SQL_LIST update;
- table_map tables_to_update= 0;
+ table_map tables_to_update;
Item_field *item;
List_iterator_fast<Item> field_it(*fields);
List_iterator_fast<Item> value_it(*values);
@@ -608,8 +697,7 @@ int multi_update::prepare(List<Item> &not_used_values,
thd->cuted_fields=0L;
thd->proc_info="updating main table";
- while ((item= (Item_field *) field_it++))
- tables_to_update|= item->used_tables();
+ tables_to_update= get_table_map(fields);
if (!tables_to_update)
{
@@ -672,7 +760,6 @@ int multi_update::prepare(List<Item> &not_used_values,
/* Split fields into fields_for_table[] and values_by_table[] */
- field_it.rewind();
while ((item= (Item_field *) field_it++))
{
Item *value= value_it++;
@@ -918,9 +1005,14 @@ bool multi_update::send_data(List<Item> &not_used_values)
if ((error=table->file->update_row(table->record[1],
table->record[0])))
{
- table->file->print_error(error,MYF(0));
updated--;
- DBUG_RETURN(1);
+ if (handle_duplicates != DUP_IGNORE ||
+ error != HA_ERR_FOUND_DUPP_KEY)
+ {
+ thd->fatal_error(); // Force error message
+ table->file->print_error(error,MYF(0));
+ DBUG_RETURN(1);
+ }
}
}
}
@@ -986,7 +1078,6 @@ int multi_update::do_updates(bool from_send_error)
TABLE *table, *tmp_table;
DBUG_ENTER("do_updates");
-
do_update= 0; // Don't retry this function
if (!found)
DBUG_RETURN(0);
@@ -1074,7 +1165,10 @@ int multi_update::do_updates(bool from_send_error)
err:
if (!from_send_error)
+ {
+ thd->fatal_error();
table->file->print_error(local_error,MYF(0));
+ }
(void) table->file->ha_rnd_end();
(void) tmp_table->file->ha_rnd_end();
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 0c81c172cf7..7cf24d3972d 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -4163,12 +4163,14 @@ update:
lex->lock_option= TL_UNLOCK; /* Will be set later */
}
opt_low_priority opt_ignore join_table_list
- SET update_list where_clause opt_order_clause delete_limit_clause
+ SET update_list
{
LEX *lex= Lex;
- Select->set_lock_for_tables($3);
if (lex->select_lex.table_list.elements > 1)
+ {
lex->sql_command= SQLCOM_UPDATE_MULTI;
+ lex->multi_lock_option= $3;
+ }
else if (lex->select_lex.get_table_list()->derived)
{
/* it is single table update and it is update of derived table */
@@ -4176,7 +4178,10 @@ update:
lex->select_lex.get_table_list()->alias, "UPDATE");
YYABORT;
}
+ else
+ Select->set_lock_for_tables($3);
}
+ where_clause opt_order_clause delete_limit_clause {}
;
update_list:
diff --git a/sql/stacktrace.c b/sql/stacktrace.c
index d0478052fb1..322d647e741 100644
--- a/sql/stacktrace.c
+++ b/sql/stacktrace.c
@@ -197,7 +197,7 @@ terribly wrong...\n");
fprintf(stderr, "Stack trace seems successful - bottom reached\n");
end:
- fprintf(stderr, "Please read http://www.mysql.com/doc/en/Using_stack_trace.html and follow instructions on how to resolve the stack trace. Resolved\n\
+ fprintf(stderr, "Please read http://dev.mysql.com/doc/mysql/en/Using_stack_trace.html and follow instructions on how to resolve the stack trace. Resolved\n\
stack trace is much more helpful in diagnosing the problem, so please do \n\
resolve it\n");
}
diff --git a/sql/table.h b/sql/table.h
index 904038ad029..f25b172a0d9 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -150,6 +150,14 @@ struct st_table {
*found_next_number_field, /* Set on open */
*rowid_field;
Field_timestamp *timestamp_field;
+#if MYSQL_VERSION_ID < 40100
+ /*
+ Indicates whenever we have to set field_length members of all TIMESTAMP
+ fields to 19 (to honour 'new_mode' variable) or to original
+ field_length values.
+ */
+ my_bool timestamp_mode;
+#endif
my_string comment; /* Comment about table */
CHARSET_INFO *table_charset; /* Default charset of string fields */
REGINFO reginfo; /* field connections */