Merge with 4.0 for 4.1 release
Noteworthy: - New HANDLER code - New multi-update-grant-check code - Table lock code in ha_innodb.cc was not applied BitKeeper/etc/logging_ok: auto-union BitKeeper/deleted/.del-ctype-latin1_de.c~c5d8f9208bceb98e: Auto merged Build-tools/mysql-copyright-2: Auto merged acinclude.m4: Auto merged client/mysqladmin.c: Auto merged client/mysqldump.c: Auto merged include/config-win.h: Auto merged include/my_global.h: Auto merged include/myisam.h: Auto merged innobase/btr/btr0btr.c: Auto merged innobase/buf/buf0buf.c: Auto merged ltmain.sh: Auto merged innobase/dict/dict0dict.c: Auto merged innobase/fsp/fsp0fsp.c: Auto merged innobase/include/dict0dict.h: Auto merged innobase/include/row0mysql.h: Auto merged innobase/log/log0log.c: Auto merged innobase/log/log0recv.c: Auto merged innobase/pars/pars0opt.c: Auto merged innobase/row/row0row.c: Auto merged innobase/sync/sync0arr.c: Auto merged innobase/ut/ut0dbg.c: Auto merged myisam/mi_check.c: Auto merged myisam/mi_close.c: Auto merged myisam/mi_create.c: Auto merged myisam/mi_locking.c: Auto merged myisam/myisampack.c: Auto merged mysql-test/r/delete.result: Auto merged mysql-test/r/func_if.result: Auto merged Build-tools/mysql-copyright: Merge with 4.0 (too most of the code from 4.0) Makefile.am: merge client/mysql.cc: Used 4.1 code configure.in: merge innobase/os/os0file.c: merge innobase/row/row0mysql.c: merge mysql-test/r/ctype_latin1_de.result: merge mysql-test/r/flush_table.result: merge mysql-test/r/func_str.result: merge mysql-test/r/handler.result: merge mysql-test/r/multi_update.result: merge mysql-test/r/type_timestamp.result: Removed testing of 'new' mode, as this is only relevant for 4.0 mysql-test/r/update.result: merge mysql-test/t/delete.test: merge mysql-test/t/flush_table.test: merge mysql-test/t/func_str.test: merge mysql-test/t/handler.test: merge mysql-test/t/multi_update.test: merge mysql-test/t/type_timestamp.test: Removed testing of 'new' mode, as this is only relevant for 4.0 mysql-test/t/update.test: merge mysys/errors.c: merge mysys/my_fstream.c: merge mysys/my_pread.c: merge mysys/my_write.c: merge mysys/mysys_priv.h: merge scripts/mysqlhotcopy.sh: merge sql/field.cc: Keep code from 4.1 sql/field.h: Keep code from 4.1 sql/ha_innodb.cc: Don't merge lock code from 4.0; Heikki will look at this sql/ha_myisam.cc: merge sql/handler.cc: merge sql/item_cmpfunc.cc: merge sql/item_cmpfunc.h: merge sql/item_strfunc.cc: merge sql/mysql_priv.h: merge sql/mysqld.cc: merge sql/protocol.cc: merge sql/records.cc: merge sql/repl_failsafe.cc: merge mysql-test/r/lock_multi.result: merge mysql-test/t/ctype_latin1_de.test: merge mysql-test/t/func_if.test: merge mysql-test/t/lock_multi.test: merge sql/repl_failsafe.h: merge Remove unnessessary header protection sql/slave.h: merge sql/sql_acl.cc: merge sql/sql_base.cc: merge sql/sql_cache.cc: auto merge sql/sql_class.cc: merge sql/sql_class.h: merge sql/sql_delete.cc: merge sql/sql_handler.cc: Get new HANDLER code into 4.1 sql/sql_parse.cc: Keep old file sql/sql_repl.cc: merge sql/sql_repl.h: merge sql/sql_show.cc: merge sql/sql_table.cc: merge sql/sql_union.cc: Applied the examine_rows bug fix from 4.0 by hand sql/sql_update.cc: New multi-update-grant-check code from 4.0 sql/sql_yacc.yy: New multi-update-grant-check code from 4.0 sql/stacktrace.c: merge sql/table.h: merge
This commit is contained in:
commit
bbab9ec678
@ -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
|
||||
|
@ -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();
|
||||
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);
|
||||
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 ($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?||;
|
||||
}
|
||||
#
|
||||
# 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(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");
|
||||
}
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -90,6 +90,7 @@ sub add_copyright
|
||||
$ARGV =~ /\.cc$/ ||
|
||||
$ARGV =~ /\.h$/ ||
|
||||
$ARGV =~ /\.cpp$/ ||
|
||||
$ARGV =~ /\.txt$/ ||
|
||||
$ARGV =~ /\.yy$/)
|
||||
{
|
||||
$start_copyright="/* ";
|
||||
|
@ -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@
|
||||
|
||||
|
23
acinclude.m4
23
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)
|
||||
|
@ -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;
|
||||
|
15
configure.in
15
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.],
|
||||
|
@ -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) +\
|
||||
|
@ -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])) +\
|
||||
|
@ -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;
|
||||
|
@ -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) ==
|
||||
|
@ -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(
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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(
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
@ -2369,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 */
|
||||
@ -2409,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;
|
||||
}
|
||||
|
||||
@ -2955,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"
|
||||
|
@ -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));
|
||||
|
@ -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 */
|
||||
|
@ -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";
|
||||
|
@ -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"
|
||||
|
@ -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,
|
||||
|
@ -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)))
|
||||
|
@ -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;
|
||||
|
@ -19,7 +19,20 @@
|
||||
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.
|
||||
*/
|
||||
*/
|
||||
|
||||
/*
|
||||
state.open_count in the .MYI file is used the following way:
|
||||
- For the first change of the file in this process it's incremented with
|
||||
mi_mark_file_change(). (We have a write lock on the file in this case)
|
||||
- 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).
|
||||
*/
|
||||
|
||||
|
||||
#include "myisamdef.h"
|
||||
|
||||
@ -32,12 +45,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 +69,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 +98,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 +136,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 +369,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)
|
||||
{
|
||||
@ -421,6 +445,8 @@ 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 +460,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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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++)
|
||||
|
@ -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;
|
||||
|
@ -130,3 +130,14 @@ select * from t1;
|
||||
a b
|
||||
7 7
|
||||
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;
|
||||
|
@ -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;
|
||||
Not unique table/alias: 'a1'
|
||||
handler t1 open as a2;
|
||||
Not unique table/alias: 'a2'
|
||||
handler t2 open;
|
||||
Not unique table/alias: 't2'
|
||||
handler a1 read first limit 9;
|
||||
table_id
|
||||
test.t1
|
||||
@ -52,9 +61,13 @@ 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
|
||||
@ -64,3 +77,28 @@ 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;
|
||||
|
@ -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
|
||||
|
@ -316,6 +316,11 @@ 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
|
||||
|
@ -205,3 +205,247 @@ 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;
|
||||
Not unique table/alias: 't1'
|
||||
use test;
|
||||
handler test.t1 read first limit 9;
|
||||
Unknown table 'test.t1' in HANDLER
|
||||
handler test_test.t1 read first limit 9;
|
||||
table_id
|
||||
test_test.t1
|
||||
|
||||
handler t1 read first limit 9;
|
||||
table_id
|
||||
test_test.t1
|
||||
|
||||
handler test_test.t2 read first limit 9;
|
||||
table_id
|
||||
test_test.t2
|
||||
|
||||
handler t2 read first limit 9;
|
||||
table_id
|
||||
test_test.t2
|
||||
|
||||
handler test_test.t1 close;
|
||||
handler t1 close;
|
||||
Unknown table 't1' in HANDLER
|
||||
drop table test_test.t1;
|
||||
handler test_test.t2 close;
|
||||
handler t2 close;
|
||||
Unknown table 't2' in HANDLER
|
||||
drop table test_test.t2;
|
||||
drop database test_test;
|
||||
use test;
|
||||
handler test.t1 close;
|
||||
Unknown table 'test.t1' in HANDLER
|
||||
handler t1 close;
|
||||
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;
|
||||
Not unique table/alias: 't1'
|
||||
handler t2 open t1;
|
||||
Not unique table/alias: 't1'
|
||||
handler t3 open t1;
|
||||
Not unique table/alias: 't1'
|
||||
handler t1 read first limit 9;
|
||||
c1
|
||||
test_test.t1
|
||||
handler test.t1 close;
|
||||
Unknown table 'test.t1' in HANDLER
|
||||
handler test.t1 open h1;
|
||||
Not unique table/alias: 'h1'
|
||||
handler test_test.t1 open h1;
|
||||
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 test.h2 read first limit 9;
|
||||
c1
|
||||
t1
|
||||
handler test.h1 close;
|
||||
Unknown table 'test.h1' in HANDLER
|
||||
handler test_test.t1 close;
|
||||
handler test_test.h1 close;
|
||||
handler h2 close;
|
||||
handler t1 read first limit 9;
|
||||
Unknown table 't1' in HANDLER
|
||||
handler h1 read first limit 9;
|
||||
Unknown table 'h1' in HANDLER
|
||||
handler h2 read first limit 9;
|
||||
Unknown table 'h2' in HANDLER
|
||||
handler h3 read first limit 9;
|
||||
c1
|
||||
test_test.t3
|
||||
handler test_test.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;
|
||||
Unknown table 'test.h3' in HANDLER
|
||||
handler test_test.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;
|
||||
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;
|
||||
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;
|
||||
Unknown table 'h5' in HANDLER
|
||||
alter table t3 engine=MyISAM;
|
||||
handler h1 read first limit 9;
|
||||
Unknown table 'h1' in HANDLER
|
||||
handler h2 read first limit 9;
|
||||
c1
|
||||
t2
|
||||
handler h3 read first limit 9;
|
||||
Unknown table 'h3' in HANDLER
|
||||
handler h4 read first limit 9;
|
||||
c1
|
||||
t4
|
||||
handler h5 read first limit 9;
|
||||
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;
|
||||
Unknown table 'h1_1' in HANDLER
|
||||
handler h1_2 read first limit 9;
|
||||
Unknown table 'h1_2' in HANDLER
|
||||
handler h1_3 read first limit 9;
|
||||
Unknown table 'h1_3' in HANDLER
|
||||
drop table t1;
|
||||
drop table t2;
|
||||
drop table t3;
|
||||
drop table t4;
|
||||
drop table t5;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
@ -421,3 +417,11 @@ select * from t1;
|
||||
ts
|
||||
2001-09-09 04:46:40
|
||||
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;
|
||||
|
@ -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;
|
||||
|
@ -86,6 +86,24 @@ 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
|
||||
#
|
||||
DROP TABLE IF EXISTS 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;
|
||||
DROP TABLE t1;
|
||||
|
||||
#
|
||||
# Test of special character in german collation
|
||||
#
|
||||
|
||||
CREATE TABLE t1 (
|
||||
s1 CHAR(5) CHARACTER SET latin1 COLLATE latin1_german2_ci
|
||||
);
|
||||
|
@ -70,6 +70,16 @@ select count(*) from t1;
|
||||
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;
|
||||
|
||||
#
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -181,6 +181,13 @@ insert into t1 values ('one'),(NULL),('two'),('four');
|
||||
select a, quote(a), isnull(quote(a)), quote(a) is null, ifnull(quote(a), 'n') from t1;
|
||||
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
|
||||
#
|
||||
|
@ -138,3 +138,207 @@ 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 1109;
|
||||
handler test.t1 read first limit 9;
|
||||
handler test_test.t1 read first limit 9;
|
||||
handler t1 read first limit 9;
|
||||
handler test_test.t2 read first limit 9;
|
||||
handler t2 read first limit 9;
|
||||
#
|
||||
# Cleanup.
|
||||
#
|
||||
|
||||
handler test_test.t1 close;
|
||||
--error 1109;
|
||||
handler t1 close;
|
||||
drop table test_test.t1;
|
||||
handler test_test.t2 close;
|
||||
--error 1109;
|
||||
handler t2 close;
|
||||
drop table test_test.t2;
|
||||
drop database test_test;
|
||||
#
|
||||
use test;
|
||||
--error 1109;
|
||||
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 1109
|
||||
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 test.h2 read first limit 9;
|
||||
--error 1109
|
||||
handler test.h1 close;
|
||||
handler test_test.t1 close;
|
||||
handler test_test.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 test_test.h3 read first limit 9;
|
||||
use test_test;
|
||||
handler h3 read first limit 9;
|
||||
--error 1109
|
||||
handler test.h3 read first limit 9;
|
||||
handler test_test.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;
|
||||
|
@ -52,6 +52,30 @@ connection reader;
|
||||
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
|
||||
|
@ -154,8 +154,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;
|
||||
|
@ -62,19 +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));
|
||||
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", "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;
|
||||
|
||||
#
|
||||
# Let us check if we properly treat wrong datetimes and produce proper warnings
|
||||
# (for both strings and numbers)
|
||||
@ -258,6 +245,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);
|
||||
@ -275,3 +265,14 @@ set TIMESTAMP=1000000000;
|
||||
insert into t1 values ();
|
||||
select * from t1;
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# Test for bug #4131, TIMESTAMP columns missing minutes and seconds when
|
||||
# using GROUP BY in @@new=1 mode.
|
||||
#
|
||||
set new=1;
|
||||
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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)",
|
||||
|
@ -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)))
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
@ -4255,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
|
||||
@ -4816,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) {
|
||||
@ -5067,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
|
||||
@ -5085,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) {
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -1162,6 +1162,15 @@ Item_func_nullif::val_str(String *str)
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Item_func_nullif::is_null()
|
||||
{
|
||||
if (!(this->*cmp_func)())
|
||||
return null_value=1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
CASE expression
|
||||
Return the matching ITEM or NULL if all compares (including else) failed
|
||||
|
@ -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();
|
||||
};
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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, int 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);
|
||||
|
@ -2118,8 +2118,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");
|
||||
@ -2147,7 +2146,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);
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 */
|
||||
|
16
sql/slave.h
16
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
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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,35 +33,211 @@
|
||||
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, int mode_flags);
|
||||
|
||||
int mysql_ha_open(THD *thd, TABLE_LIST *tables)
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
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))
|
||||
|
||||
/*
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Open a HANDLER table.
|
||||
|
||||
SYNOPSIS
|
||||
mysql_ha_open()
|
||||
thd Thread identifier.
|
||||
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 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
|
||||
!= 0 error
|
||||
*/
|
||||
|
||||
int mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
|
||||
{
|
||||
TABLE_LIST *hash_tables;
|
||||
char *db, *name, *alias;
|
||||
uint dblen, namelen, aliaslen, counter;
|
||||
int err;
|
||||
DBUG_ENTER("mysql_ha_open");
|
||||
DBUG_PRINT("enter",("mysql_ha_open: '%s'.'%s' as '%s' reopen %d",
|
||||
tables->db, tables->real_name, tables->alias, reopen));
|
||||
|
||||
if (! hash_inited(&thd->handler_tables_hash))
|
||||
{
|
||||
my_printf_error(ER_ILLEGAL_HA,ER(ER_ILLEGAL_HA),MYF(0), tables->alias);
|
||||
mysql_ha_close(thd, tables,1);
|
||||
return -1;
|
||||
/*
|
||||
HASH entries are of type TABLE_LIST.
|
||||
*/
|
||||
if (hash_init(&thd->handler_tables_hash, 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. */
|
||||
{
|
||||
if (hash_search(&thd->handler_tables_hash, (byte*) tables->alias,
|
||||
strlen(tables->alias) + 1))
|
||||
{
|
||||
DBUG_PRINT("info",("mysql_ha_open: duplicate '%s'", tables->alias));
|
||||
if (! reopen)
|
||||
my_printf_error(ER_NONUNIQ_TABLE, ER(ER_NONUNIQ_TABLE),
|
||||
MYF(0), tables->alias);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
send_ok(thd);
|
||||
return 0;
|
||||
/*
|
||||
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)
|
||||
{
|
||||
/* 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)))
|
||||
{
|
||||
DBUG_PRINT("exit",("mysql_ha_open: malloc ERROR"));
|
||||
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 (hash_insert(&thd->handler_tables_hash, (byte*) hash_tables))
|
||||
{
|
||||
mysql_ha_close(thd, tables);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (! reopen)
|
||||
send_ok(thd);
|
||||
DBUG_PRINT("exit",("mysql_ha_open: OK"));
|
||||
DBUG_RETURN(0);
|
||||
|
||||
err:
|
||||
DBUG_PRINT("exit",("mysql_ha_open: ERROR"));
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
|
||||
|
||||
@ -76,151 +248,195 @@ int mysql_ha_open(THD *thd, TABLE_LIST *tables)
|
||||
mysql_ha_close()
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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_close(THD *thd, TABLE_LIST *tables)
|
||||
{
|
||||
TABLE_LIST *hash_tables;
|
||||
TABLE **table_ptr;
|
||||
bool was_flushed;
|
||||
bool was_flushed= FALSE;
|
||||
bool not_opened;
|
||||
DBUG_ENTER("mysql_ha_close");
|
||||
DBUG_PRINT("enter",("mysql_ha_close: '%s'.'%s' as '%s'",
|
||||
tables->db, tables->real_name, tables->alias));
|
||||
|
||||
table_ptr= find_table_ptr_by_name(thd, tables->db, tables->alias,
|
||||
!no_alias, dont_lock, &was_flushed);
|
||||
if (*table_ptr)
|
||||
if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash,
|
||||
(byte*) tables->alias,
|
||||
strlen(tables->alias) + 1)))
|
||||
{
|
||||
(*table_ptr)->file->ha_index_or_rnd_end();
|
||||
if (!dont_lock)
|
||||
VOID(pthread_mutex_lock(&LOCK_open));
|
||||
if (close_thread_table(thd, table_ptr))
|
||||
/*
|
||||
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))
|
||||
{
|
||||
/* Tell threads waiting for refresh that something has happened */
|
||||
VOID(pthread_cond_broadcast(&COND_refresh));
|
||||
DBUG_PRINT("info",("mysql_ha_close: wrong db"));
|
||||
hash_tables= NULL;
|
||||
}
|
||||
if (!dont_lock)
|
||||
VOID(pthread_mutex_unlock(&LOCK_open));
|
||||
}
|
||||
else if (!was_flushed && !dont_send_ok)
|
||||
{
|
||||
my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0),
|
||||
tables->alias, "HANDLER");
|
||||
return -1;
|
||||
}
|
||||
if (!dont_send_ok)
|
||||
send_ok(thd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Close a list of HANDLER tables.
|
||||
|
||||
SYNOPSIS
|
||||
mysql_ha_close_list()
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
RETURN
|
||||
0 ok
|
||||
*/
|
||||
|
||||
int mysql_ha_close_list(THD *thd, TABLE_LIST *tables, bool flushed)
|
||||
{
|
||||
TABLE_LIST *tl_item;
|
||||
TABLE **table_ptr;
|
||||
|
||||
if (tables)
|
||||
{
|
||||
for (tl_item= tables ; tl_item; tl_item= tl_item->next)
|
||||
else
|
||||
#endif
|
||||
{
|
||||
mysql_ha_close(thd, tl_item, /*dont_send_ok*/ 1,
|
||||
/*dont_lock*/ 1, /*no_alias*/ 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
table_ptr= &(thd->handler_tables);
|
||||
while (*table_ptr)
|
||||
{
|
||||
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",("mysql_ha_close: ERROR"));
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
|
||||
send_ok(thd);
|
||||
DBUG_PRINT("exit",("mysql_ha_close: 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",("mysql_ha_read: '%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",("mysql_ha_read: found 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",("mysql_ha_read: reopen failed"));
|
||||
goto err0;
|
||||
}
|
||||
|
||||
table= hash_tables->table;
|
||||
DBUG_PRINT("info",("mysql_ha_read: 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",("mysql_ha_read: 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 +444,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
|
||||
|
||||
@ -378,84 +582,156 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
|
||||
}
|
||||
ok:
|
||||
mysql_unlock_tables(thd,lock);
|
||||
send_eof(thd);
|
||||
return 0;
|
||||
send_eof(&thd->net);
|
||||
DBUG_PRINT("exit",("mysql_ha_read: OK"));
|
||||
DBUG_RETURN(0);
|
||||
err:
|
||||
mysql_unlock_tables(thd,lock);
|
||||
err0:
|
||||
return -1;
|
||||
DBUG_PRINT("exit",("mysql_ha_read: 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'.
|
||||
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.
|
||||
|
||||
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.
|
||||
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, int mode_flags)
|
||||
{
|
||||
int dblen;
|
||||
TABLE **table_ptr;
|
||||
TABLE_LIST **tmp_tables_p;
|
||||
TABLE_LIST *tmp_tables;
|
||||
TABLE **table_ptr;
|
||||
bool was_flushed;
|
||||
DBUG_ENTER("mysql_ha_flush");
|
||||
DBUG_PRINT("enter",("mysql_ha_flush: tables %p mode_flags 0x%02x",
|
||||
tables, mode_flags));
|
||||
|
||||
DBUG_ASSERT(db);
|
||||
dblen= strlen(db);
|
||||
table_ptr= &(thd->handler_tables);
|
||||
*was_flushed= FALSE;
|
||||
|
||||
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",("mysql_ha_flush: 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((*table_ptr)->table_cache_key, tmp_tables->db)) &&
|
||||
! my_strcasecmp((*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",("mysql_ha_flush: *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_PRINT("exit",("mysql_ha_flush: OK"));
|
||||
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, int mode_flags)
|
||||
{
|
||||
TABLE_LIST *hash_tables;
|
||||
TABLE *table= *table_ptr;
|
||||
bool was_flushed;
|
||||
DBUG_ENTER("mysql_ha_flush_table");
|
||||
DBUG_PRINT("info",("mysql_ha_flush_table: '%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_PRINT("exit",("mysql_ha_flush_table: OK"));
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
/* Copyright (C) 2000 MySQL AB
|
||||
/* Copyright (C) 2000 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@ -387,27 +388,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
|
||||
{
|
||||
|
@ -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];
|
||||
@ -2567,8 +2567,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,
|
||||
@ -3307,7 +3306,8 @@ copy_data_between_tables(TABLE *from,TABLE *to,
|
||||
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);
|
||||
|
||||
@ -3434,12 +3434,13 @@ 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:
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -448,6 +448,24 @@ int mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
|
||||
Update multiple tables from join
|
||||
***************************************************************************/
|
||||
|
||||
/*
|
||||
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 +483,163 @@ 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;
|
||||
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;
|
||||
table_map update_tables, derived_tables=0;
|
||||
uint tnr, counter;
|
||||
|
||||
if ((res=open_tables(thd,table_list, &counter)))
|
||||
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))))
|
||||
DBUG_RETURN(res);
|
||||
|
||||
/*
|
||||
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"
|
||||
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
|
||||
*/
|
||||
if (!tl->derived)
|
||||
table->grant.want_privilege= (UPDATE_ACL & ~table->grant.privilege);
|
||||
}
|
||||
|
||||
/* 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++)
|
||||
for (tl= update_list, tnr=0 ; tl ; tl=tl->next)
|
||||
{
|
||||
table_list->table->map= (table_map) 1 << tablenr;
|
||||
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++);
|
||||
}
|
||||
}
|
||||
|
||||
if (setup_fields(thd, 0, update_list, *fields, 1, 0, 0))
|
||||
DBUG_RETURN(-1);
|
||||
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++))
|
||||
update_tables= get_table_map(fields);
|
||||
|
||||
/* 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)
|
||||
{
|
||||
item_tables|= item->used_tables();
|
||||
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.lock_option;
|
||||
tl->updating= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
if (using_lock_tables)
|
||||
{
|
||||
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++))
|
||||
{
|
||||
item->field->query_id= 0;
|
||||
item->cleanup();
|
||||
}
|
||||
}
|
||||
if (setup_fields(thd, table_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);
|
||||
}
|
||||
|
||||
/*
|
||||
Count tables and setup timestamp handling
|
||||
Setup timestamp handling
|
||||
*/
|
||||
for (tl= update_list; tl; tl= tl->next)
|
||||
{
|
||||
TABLE *table= tl->table;
|
||||
|
||||
/* 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
|
||||
/* 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;
|
||||
|
||||
/* if table will be updated then check that it is unique */
|
||||
if (table->map & item_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);
|
||||
}
|
||||
}
|
||||
|
||||
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 (tl->derived && (item_tables & tl->table->map))
|
||||
{
|
||||
my_printf_error(ER_NON_UPDATABLE_TABLE, ER(ER_NON_UPDATABLE_TABLE),
|
||||
MYF(0), tl->alias, "UPDATE");
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 +671,7 @@ int multi_update::prepare(List<Item> ¬_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 +682,7 @@ int multi_update::prepare(List<Item> ¬_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 +745,6 @@ int multi_update::prepare(List<Item> ¬_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 +990,13 @@ bool multi_update::send_data(List<Item> ¬_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)
|
||||
{
|
||||
table->file->print_error(error,MYF(0));
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -986,7 +1062,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);
|
||||
|
@ -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->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:
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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 */
|
||||
|
Loading…
x
Reference in New Issue
Block a user