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:
unknown 2004-10-06 19:14:33 +03:00
commit bbab9ec678
83 changed files with 1906 additions and 506 deletions

View File

@ -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

View File

@ -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");
}
}

View File

@ -90,6 +90,7 @@ sub add_copyright
$ARGV =~ /\.cc$/ ||
$ARGV =~ /\.h$/ ||
$ARGV =~ /\.cpp$/ ||
$ARGV =~ /\.txt$/ ||
$ARGV =~ /\.yy$/)
{
$start_copyright="/* ";

View File

@ -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@

View File

@ -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)

View File

@ -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;

View File

@ -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.],

View File

@ -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) +\

View File

@ -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])) +\

View File

@ -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;

View File

@ -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) ==

View File

@ -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(

View File

@ -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);

View File

@ -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;
}

View File

@ -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(

View File

@ -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

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View 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)

View File

@ -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"

View File

@ -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));

View File

@ -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 */

View File

@ -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";

View File

@ -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"

View File

@ -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,

View File

@ -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)))

View File

@ -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;

View File

@ -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);
}

View File

@ -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++)

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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
);

View File

@ -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;
#

View File

@ -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;

View File

@ -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;

View File

@ -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
#

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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)",

View File

@ -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)))

View File

@ -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 */

View File

@ -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;
}

View File

@ -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

View File

@ -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 {

View File

@ -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) {

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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();
};

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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)
{

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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);

View File

@ -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,

View File

@ -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));

View File

@ -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

View File

@ -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;

View File

@ -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);
}

View File

@ -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

View File

@ -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"

View File

@ -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
{

View File

@ -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);
}

View File

@ -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

View File

@ -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> &not_used_values,
{
TABLE_LIST *table_ref;
SQL_LIST update;
table_map tables_to_update= 0;
table_map tables_to_update;
Item_field *item;
List_iterator_fast<Item> field_it(*fields);
List_iterator_fast<Item> value_it(*values);
@ -608,8 +682,7 @@ int multi_update::prepare(List<Item> &not_used_values,
thd->cuted_fields=0L;
thd->proc_info="updating main table";
while ((item= (Item_field *) field_it++))
tables_to_update|= item->used_tables();
tables_to_update= get_table_map(fields);
if (!tables_to_update)
{
@ -672,7 +745,6 @@ int multi_update::prepare(List<Item> &not_used_values,
/* Split fields into fields_for_table[] and values_by_table[] */
field_it.rewind();
while ((item= (Item_field *) field_it++))
{
Item *value= value_it++;
@ -918,9 +990,13 @@ bool multi_update::send_data(List<Item> &not_used_values)
if ((error=table->file->update_row(table->record[1],
table->record[0])))
{
table->file->print_error(error,MYF(0));
updated--;
DBUG_RETURN(1);
if (handle_duplicates != DUP_IGNORE ||
error != HA_ERR_FOUND_DUPP_KEY)
{
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);

View File

@ -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:

View File

@ -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");
}

View File

@ -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 */