summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xBuild-tools/Bootstrap20
-rwxr-xr-xBuild-tools/Do-compile8
-rwxr-xr-xBuild-tools/Do-rpm85
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-classic/String Tables/0009-English/value.shl2
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-gpl/String Tables/0009-English/value.shl2
-rwxr-xr-xVC++Files/InstallShield/4.0.XX-pro/String Tables/0009-English/value.shl2
-rw-r--r--acinclude.m44
-rw-r--r--client/mysql.cc10
-rw-r--r--client/mysqldump.c177
-rw-r--r--configure.in2
-rw-r--r--dbug/dbug.c2
-rw-r--r--include/config-win.h5
-rw-r--r--include/my_base.h10
-rw-r--r--include/my_dir.h11
-rw-r--r--include/my_global.h18
-rw-r--r--include/my_pthread.h3
-rw-r--r--include/my_sys.h4
-rw-r--r--include/mysql_com.h2
-rw-r--r--include/mysql_embed.h2
-rw-r--r--innobase/btr/btr0cur.c42
-rw-r--r--innobase/include/btr0cur.h16
-rw-r--r--innobase/include/row0upd.h35
-rw-r--r--innobase/lock/lock0lock.c6
-rw-r--r--innobase/row/row0ins.c25
-rw-r--r--innobase/row/row0sel.c8
-rw-r--r--innobase/row/row0umod.c124
-rw-r--r--innobase/row/row0upd.c86
-rw-r--r--innobase/row/row0vers.c27
-rw-r--r--libmysql/libmysql.c23
-rw-r--r--myisam/ft_boolean_search.c11
-rw-r--r--myisam/mi_check.c38
-rw-r--r--myisam/mi_dbug.c4
-rw-r--r--myisam/mi_key.c54
-rw-r--r--myisam/mi_open.c3
-rw-r--r--mysql-test/r/auto_increment.result26
-rw-r--r--mysql-test/r/bdb.result11
-rw-r--r--mysql-test/r/binary.result1
-rw-r--r--mysql-test/r/func_group.result25
-rw-r--r--mysql-test/r/func_op.result18
-rw-r--r--mysql-test/r/func_str.result21
-rw-r--r--mysql-test/r/func_time.result36
-rw-r--r--mysql-test/r/group_by.result31
-rw-r--r--mysql-test/r/have_mest_timezone.require2
-rw-r--r--mysql-test/r/have_met_timezone.require2
-rw-r--r--mysql-test/r/innodb.result26
-rw-r--r--mysql-test/r/insert.result2
-rw-r--r--mysql-test/r/join_outer.result17
-rw-r--r--mysql-test/r/limit.result23
-rw-r--r--mysql-test/r/loaddata.result28
-rw-r--r--mysql-test/r/lowercase_table.result10
-rw-r--r--mysql-test/r/multi_update.result33
-rw-r--r--mysql-test/r/mysqldump.result60
-rw-r--r--mysql-test/r/query_cache.result11
-rw-r--r--mysql-test/r/rpl_EE_error.result16
-rw-r--r--mysql-test/r/rpl_multi_update.result26
-rw-r--r--mysql-test/r/rpl_rotate_logs.result3
-rw-r--r--mysql-test/r/select_found.result19
-rw-r--r--mysql-test/r/symlink.result22
-rw-r--r--mysql-test/r/timezone.result9
-rw-r--r--mysql-test/r/truncate.result9
-rw-r--r--mysql-test/r/type_blob.result146
-rw-r--r--mysql-test/r/type_datetime.result21
-rw-r--r--mysql-test/r/type_decimal.result8
-rw-r--r--mysql-test/r/type_enum.result15
-rw-r--r--mysql-test/r/type_timestamp.result28
-rw-r--r--mysql-test/r/union.result10
-rw-r--r--mysql-test/r/warnings.result4
-rw-r--r--mysql-test/std_data/loaddata3.dat6
-rw-r--r--mysql-test/std_data/loaddata4.dat1
-rw-r--r--mysql-test/t/auto_increment.test19
-rw-r--r--mysql-test/t/bdb.test19
-rw-r--r--mysql-test/t/func_group.test8
-rw-r--r--mysql-test/t/func_op.test9
-rw-r--r--mysql-test/t/func_str.test7
-rw-r--r--mysql-test/t/func_time.test19
-rw-r--r--mysql-test/t/group_by.test24
-rw-r--r--mysql-test/t/innodb.test37
-rw-r--r--mysql-test/t/insert.test2
-rw-r--r--mysql-test/t/join_outer.test13
-rw-r--r--mysql-test/t/limit.test22
-rw-r--r--mysql-test/t/loaddata.test11
-rw-r--r--mysql-test/t/lowercase_table.test7
-rw-r--r--mysql-test/t/multi_update.test39
-rw-r--r--mysql-test/t/mysqldump.test30
-rw-r--r--mysql-test/t/query_cache.test4
-rw-r--r--mysql-test/t/rpl_EE_error.test30
-rw-r--r--mysql-test/t/rpl_multi_update.test24
-rw-r--r--mysql-test/t/rpl_rotate_logs.test1
-rw-r--r--mysql-test/t/select_found.test14
-rw-r--r--mysql-test/t/symlink.test22
-rw-r--r--mysql-test/t/timezone.test18
-rw-r--r--mysql-test/t/truncate.test12
-rw-r--r--mysql-test/t/type_blob.test49
-rw-r--r--mysql-test/t/type_datetime.test5
-rw-r--r--mysql-test/t/type_decimal.test6
-rw-r--r--mysql-test/t/type_enum.test11
-rw-r--r--mysql-test/t/type_timestamp.test13
-rw-r--r--mysql-test/t/union.test13
-rw-r--r--mysys/charset.c76
-rw-r--r--mysys/mf_pack.c27
-rw-r--r--mysys/my_handler.c8
-rw-r--r--mysys/my_init.c20
-rw-r--r--mysys/my_lib.c345
-rw-r--r--mysys/my_symlink.c1
-rw-r--r--mysys/my_symlink2.c12
-rw-r--r--mysys/my_thr_init.c29
-rw-r--r--regex/reginit.c10
-rw-r--r--sql-common/client.c3
-rw-r--r--sql/field.cc135
-rw-r--r--sql/field.h15
-rw-r--r--sql/ha_innodb.cc6
-rw-r--r--sql/item.cc17
-rw-r--r--sql/item.h8
-rw-r--r--sql/item_func.cc46
-rw-r--r--sql/item_func.h46
-rw-r--r--sql/item_strfunc.cc29
-rw-r--r--sql/item_strfunc.h4
-rw-r--r--sql/item_subselect.cc16
-rw-r--r--sql/item_sum.cc68
-rw-r--r--sql/item_sum.h23
-rw-r--r--sql/item_timefunc.cc73
-rw-r--r--sql/log.cc6
-rw-r--r--sql/log_event.cc13
-rw-r--r--sql/log_event.h4
-rw-r--r--sql/mysql_priv.h15
-rw-r--r--sql/mysqld.cc105
-rw-r--r--sql/nt_servc.cc4
-rw-r--r--sql/opt_range.cc53
-rw-r--r--sql/records.cc11
-rw-r--r--sql/repl_failsafe.cc8
-rw-r--r--sql/set_var.cc6
-rw-r--r--sql/share/czech/errmsg.txt4
-rw-r--r--sql/share/danish/errmsg.txt4
-rw-r--r--sql/share/dutch/errmsg.txt4
-rw-r--r--sql/share/english/errmsg.txt4
-rw-r--r--sql/share/estonian/errmsg.txt4
-rw-r--r--sql/share/french/errmsg.txt4
-rw-r--r--sql/share/greek/errmsg.txt4
-rw-r--r--sql/share/hungarian/errmsg.txt4
-rw-r--r--sql/share/italian/errmsg.txt4
-rw-r--r--sql/share/japanese/errmsg.txt4
-rw-r--r--sql/share/korean/errmsg.txt4
-rw-r--r--sql/share/norwegian-ny/errmsg.txt4
-rw-r--r--sql/share/norwegian/errmsg.txt4
-rw-r--r--sql/share/polish/errmsg.txt4
-rw-r--r--sql/share/romanian/errmsg.txt4
-rw-r--r--sql/share/russian/errmsg.txt4
-rw-r--r--sql/share/serbian/errmsg.txt4
-rw-r--r--sql/share/slovak/errmsg.txt4
-rw-r--r--sql/share/spanish/errmsg.txt4
-rw-r--r--sql/share/swedish/errmsg.txt4
-rw-r--r--sql/share/ukrainian/errmsg.txt4
-rw-r--r--sql/slave.cc35
-rw-r--r--sql/sql_acl.cc12
-rw-r--r--sql/sql_acl.h12
-rw-r--r--sql/sql_analyse.cc8
-rw-r--r--sql/sql_base.cc18
-rw-r--r--sql/sql_cache.cc34
-rw-r--r--sql/sql_class.h13
-rw-r--r--sql/sql_client.cc1
-rw-r--r--sql/sql_db.cc2
-rw-r--r--sql/sql_delete.cc22
-rw-r--r--sql/sql_insert.cc7
-rw-r--r--sql/sql_load.cc63
-rw-r--r--sql/sql_parse.cc274
-rw-r--r--sql/sql_prepare.cc4
-rw-r--r--sql/sql_rename.cc1
-rw-r--r--sql/sql_select.cc58
-rw-r--r--sql/sql_show.cc14
-rw-r--r--sql/sql_table.cc9
-rw-r--r--sql/sql_update.cc34
-rw-r--r--sql/sql_yacc.yy3
-rw-r--r--sql/table.cc30
-rw-r--r--sql/table.h2
-rw-r--r--sql/time.cc72
-rw-r--r--sql/uniques.cc16
-rw-r--r--strings/strto.c2
-rw-r--r--strings/strtoll.c3
-rw-r--r--strings/strtoull.c1
-rwxr-xr-xsupport-files/MacOSX/MySQL7
-rw-r--r--support-files/mysql.server.sh2
-rw-r--r--support-files/mysql.spec.sh27
182 files changed, 3074 insertions, 1123 deletions
diff --git a/Build-tools/Bootstrap b/Build-tools/Bootstrap
index 17b15d190b0..7d3ac1322f4 100755
--- a/Build-tools/Bootstrap
+++ b/Build-tools/Bootstrap
@@ -274,11 +274,13 @@ if (defined $opt_changelog)
#
unless ($opt_skip_manual)
{
- $msg= "Adding manual.texi";
+ $msg= "Updating manual files";
&logger($msg);
- $command= "install -m 644 $opt_docdir/Docs/{internals,manual,reservedwords}.texi";
- $command.= " $target_dir/Docs/";
- &run_command($command, "Could not update the manual in $target_dir/Docs/!");
+ foreach $file qw/internals manual reservedwords/
+ {
+ system ("bk cat $opt_docdir/Docs/$file.texi > $target_dir/Docs/$file.texi") == 0
+ or &abort("Could not update $file.texi in $target_dir/Docs/!");
+ }
}
#
@@ -364,11 +366,13 @@ sub print_help
Usage: Bootstrap [options] <bk repository>
-Checks out (exports) a clear-text version of the given local BitKeeper
+Creates a MySQL source distribution to be used for the release builds.
+
+It checks out (exports) a clear-text version of the given local BitKeeper
repository, creates and adds a Changelog file (if requested), adds the
-latest manual.texi from the mysqldoc tree and builds a source distribution
-(*.tar.gz) file. Optionally, the test suite can be run before the source
-archive is being created.
+latest manual files from the mysqldoc BK tree and builds a source
+distribution (*.tar.gz) file. Optionally, the test suite and the
+distribution check can be run before the source archive is being created.
Options:
diff --git a/Build-tools/Do-compile b/Build-tools/Do-compile
index 0541ebe96ce..2039c2f1c5a 100755
--- a/Build-tools/Do-compile
+++ b/Build-tools/Do-compile
@@ -1,6 +1,8 @@
#!/usr/bin/perl -w
+use File::Basename;
use Getopt::Long;
+use Sys::Hostname;
@config_options= ();
@make_options= ();
@@ -76,7 +78,7 @@ if (@config_env > 0)
$opt_config_env= join(" ", @config_env);
}
-chomp($host=`hostname`);
+$host= hostname();
chomp($uname=`uname`);
$full_host_name=$host;
$connect_option= ($opt_tcpip ? "--host=$host" : "");
@@ -84,7 +86,7 @@ $host =~ /^([^.-]*)/;
$host=$1 . $opt_suffix;
$email="$opt_user\@mysql.com";
chomp($pwd = `pwd`);
-$VER= `basename $opt_distribution`; chop $VER;
+$VER= basename($opt_distribution);
$VER=~ /mysql.*-([1-9]\.[0-9]{1,2}\.[0-9]{1,2}.*)\.tar*/; $version=$1;
($major, $minor, $release) = split(/\./,$version);
$log="$pwd/Logs/$host-$major.$minor$opt_version_suffix.log";
@@ -111,7 +113,7 @@ if (defined($gcc_version) && ! $opt_config_env)
$new_opt_tmp=0;
if ($opt_tmp)
{
- if (! -d $opt_tmp)
+ unless (-d $opt_tmp)
{
safe_system("mkdir $opt_tmp");
$new_opt_tmp=1;
diff --git a/Build-tools/Do-rpm b/Build-tools/Do-rpm
index 0f423feb921..cedd55d1405 100755
--- a/Build-tools/Do-rpm
+++ b/Build-tools/Do-rpm
@@ -3,14 +3,12 @@
# Do-rpm - compile RPM packages out of a source tarball and move the
# resulting RPM packages into the current directory.
#
-# The script currently assumes the following environment (which should exist
-# like that, if the Do-compile script was used to build the binary
-# distribution)
+# The script currently assumes the following environment:
#
# - there must be a source distribution (mysql-<version>.tar.gz)
# in the current directory
-# - there must be a spec file (mysql-<version>.spec) in the directory
-# $HOME/<hostname>/mysql-<version>/support-files/
+# - You must provide the name of an RPM spec file (mysql-<version>.spec)
+# as the argument
#
# Use the "--help" option for more info!
#
@@ -35,7 +33,10 @@ $opt_log= undef;
$opt_mail= "";
$opt_verbose= undef;
+# Set a dummy version until we know the correct one
+$VERSION= "x.y.z";
$MAJOR= $MINOR= $RELEASE= 0;
+$SUFFIX= "";
GetOptions(
"cc=s",
@@ -50,7 +51,9 @@ GetOptions(
"verbose|v",
) || &print_help;
-defined($VERSION=$ARGV[0]) || print_help("Please provide the MySQL version!");
+&print_help("") if ($opt_help);
+
+defined($SPECFILE=$ARGV[0]) || print_help("Please provide the spec file name!");
# Include helper functions
$PWD= cwd();
@@ -64,6 +67,28 @@ else
die "ERROR: $LOGGER cannot be found!\n";
}
+# Open the spec file and extract the version number
+open(SPEC, $SPECFILE) or &abort("Unable to open \"$ARGV[0]\": $!");
+@spec= <SPEC>;
+close SPEC;
+
+foreach (@spec)
+{
+ if (m/^%define\s*mysql_version\s*(.*)/)
+ {
+ $VERSION= $1;
+ ($MAJOR, $MINOR, $RELEASE)= split(/\./,$VERSION);
+ ($RELEASE, $SUFFIX)= split(/\-/,$RELEASE);
+ $SUFFIX= "-" . $SUFFIX if ($SUFFIX);
+ }
+}
+
+$HOST= hostname();
+$HOST=~ /^([^.-]*)/;
+$HOST= $1;
+$LOGFILE= "$PWD/Logs/Do-rpm-$HOST-$MAJOR.$MINOR.log";
+&logger("Using spec file for version: $VERSION");
+
#
# Override predefined Log file name
#
@@ -82,14 +107,6 @@ if (defined $opt_log)
}
}
-($MAJOR, $MINOR, $RELEASE)= split(/\./, $VERSION);
-$HOST= hostname();
-$HOST=~ /^([^.-]*)/;
-$HOST= $1;
-$LOGFILE= "$PWD/Logs/Do-rpm-$HOST-$MAJOR.$MINOR.log";
-
-&print_help("") if ($opt_help);
-
#
# Newer RPM versions ship with a separate tool "rpmbuild" to build RPMs
#
@@ -120,8 +137,7 @@ chomp($SOURCEDIR= `$RPM --eval "%{_sourcedir}" 2> /dev/null`);
chomp($SPECDIR= `$RPM --eval "%{_specdir}" 2> /dev/null`);
chomp($SRCRPMDIR= `$RPM --eval "%{_srcrpmdir}" 2> /dev/null`);
-$SOURCEFILE= "mysql-$VERSION.tar.gz";
-$SPECFILE= "$PWD/$HOST/mysql-$VERSION/support-files/mysql-$VERSION.spec";
+$SOURCEFILE= glob "mysql*-$VERSION.tar.gz";
&logger("Starting RPM build of MySQL-$VERSION on $HOST");
@@ -134,10 +150,13 @@ foreach $file ($SOURCEFILE, $SPECFILE)
# Install source and spec file
#
&logger("Copying SOURCE and SPEC file to build directories.");
-copy($SOURCEFILE, $SOURCEDIR)
-or &abort("Unable to copy $SOURCEFILE to $SOURCEDIR!");
-copy($SPECFILE, $SPECDIR)
-or &abort("Unable to copy $SPECFILE to $SPECDIR!");
+unless ($opt_dry_run)
+{
+ copy($SOURCEFILE, $SOURCEDIR)
+ or &abort("Unable to copy $SOURCEFILE to $SOURCEDIR!");
+ copy($SPECFILE, $SPECDIR)
+ or &abort("Unable to copy $SPECFILE to $SPECDIR!");
+}
#
# Set environment variables - these are being used in the
@@ -168,11 +187,13 @@ $command.= basename($SPECFILE);
$command= "mv";
$command.= " -v " if ($opt_verbose);
$command.= "$SRCRPMDIR/MySQL*$VERSION*.src.rpm $PWD";
+&logger("Moving source RPM to current dir.");
&run_command($command, "Error moving source RPM!");
$command= "mv";
$command.= " -v " if ($opt_verbose);
$command.= "$RPMDIR/$RPMARCH/MySQL*$VERSION*.$RPMARCH.rpm $PWD";
+&logger("Moving binary RPMs to current dir.");
&run_command($command, "Error moving binary RPMs!");
#
@@ -181,11 +202,14 @@ $command.= "$RPMDIR/$RPMARCH/MySQL*$VERSION*.$RPMARCH.rpm $PWD";
if ($opt_clean)
{
&logger("Removing spec file and source package");
- unlink("$SPECDIR/" . basename($SPECFILE));
- unlink("$SOURCEDIR/$SOURCEFILE");
+ unless ($opt_dry_run)
+ {
+ unlink("$SPECDIR/" . basename($SPECFILE));
+ unlink("$SOURCEDIR/$SOURCEFILE");
+ }
}
-&logger("SUCCESS: RPM files successfully created.") if (!$opt_dry_run);
+&logger("SUCCESS: RPM files successfully created.") unless ($opt_dry_run);
exit 0;
sub print_help
@@ -198,11 +222,14 @@ sub print_help
}
print <<EOF;
-Usage: Do-rpm <options> <version>
+Usage: Do-rpm [options] <specfile>
-Creates a binary RPM package out of a MySQL source distribution and moves the
-resulting RPMs into the current directory. <version> is the MySQL version
-number (e.g. 4.0.11-gamma)
+Creates a binary RPM package out of a MySQL source distribution and moves
+the resulting RPMs into the current directory. <specfile> is the MySQL RPM
+spec file to use (e.g. mysql-4.0.17.spec).
+
+This script expects to find the required MySQL source distribution
+(mysql-<version>.tar.gz) in the current directory.
Options:
@@ -222,6 +249,10 @@ Options:
Example: --mail=user\\\@domain.com
-v, --verbose Verbose execution
+Example:
+
+ Do-rpm -cv mysql-4.0.17.spec
+
EOF
exit 1;
}
diff --git a/VC++Files/InstallShield/4.0.XX-classic/String Tables/0009-English/value.shl b/VC++Files/InstallShield/4.0.XX-classic/String Tables/0009-English/value.shl
index 5f767a63f43..868c801c68c 100755
--- a/VC++Files/InstallShield/4.0.XX-classic/String Tables/0009-English/value.shl
+++ b/VC++Files/InstallShield/4.0.XX-classic/String Tables/0009-English/value.shl
@@ -19,5 +19,5 @@ ERROR_UNINSTSETUP=unInstaller setup failed to initialize. You may not be able t
[General]
Language=0009
Type=STRINGTABLESPECIFIC
-Version=@VERSION@
+Version=1.00.000
diff --git a/VC++Files/InstallShield/4.0.XX-gpl/String Tables/0009-English/value.shl b/VC++Files/InstallShield/4.0.XX-gpl/String Tables/0009-English/value.shl
index 0a6c33be42b..35e7c278cc9 100755
--- a/VC++Files/InstallShield/4.0.XX-gpl/String Tables/0009-English/value.shl
+++ b/VC++Files/InstallShield/4.0.XX-gpl/String Tables/0009-English/value.shl
@@ -19,5 +19,5 @@ ERROR_UNINSTSETUP=unInstaller setup failed to initialize. You may not be able t
[General]
Language=0009
Type=STRINGTABLESPECIFIC
-Version=@VERSION@
+Version=1.00.000
diff --git a/VC++Files/InstallShield/4.0.XX-pro/String Tables/0009-English/value.shl b/VC++Files/InstallShield/4.0.XX-pro/String Tables/0009-English/value.shl
index 61b2e6fb50f..525f3be0b3e 100755
--- a/VC++Files/InstallShield/4.0.XX-pro/String Tables/0009-English/value.shl
+++ b/VC++Files/InstallShield/4.0.XX-pro/String Tables/0009-English/value.shl
@@ -19,5 +19,5 @@ ERROR_UNINSTSETUP=unInstaller setup failed to initialize. You may not be able t
[General]
Language=0009
Type=STRINGTABLESPECIFIC
-Version=@VERSION@
+Version=1.00.000
diff --git a/acinclude.m4 b/acinclude.m4
index 15a6abc38d4..d3a404e5fb0 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -785,7 +785,7 @@ AC_DEFUN(MYSQL_FIND_OPENSSL, [
for d in /usr/ssl/lib /usr/local/ssl/lib /usr/lib/openssl \
/usr/lib /usr/lib64 /opt/ssl/lib /opt/openssl/lib /usr/local/lib/ ; do
- if test -f $d/libssl.a ; then
+ if test -f $d/libssl.a || test -f $d/libssl.so || test -f $d/libssl.dylib ; then
OPENSSL_LIB=$d
fi
done
@@ -797,7 +797,7 @@ AC_DEFUN(MYSQL_FIND_OPENSSL, [
if test -f $incs/openssl/ssl.h ; then
OPENSSL_INCLUDE=-I$incs
fi
- if test -f $libs/libssl.a ; then
+ if test -f $libs/libssl.a || test -f $libs/libssl.so || test -f $libs/libssl.dylib ; then
OPENSSL_LIB=$libs
fi
;;
diff --git a/client/mysql.cc b/client/mysql.cc
index 42088d107ed..df55ebcfab0 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -380,7 +380,7 @@ int main(int argc,char *argv[])
put_info("Welcome to the MySQL monitor. Commands end with ; or \\g.",
INFO_INFO);
sprintf((char*) glob_buffer.ptr(),
- "Your MySQL connection id is %ld to server version: %s\n",
+ "Your MySQL connection id is %lu to server version: %s\n",
mysql_thread_id(&mysql),mysql_get_server_info(&mysql));
put_info((char*) glob_buffer.ptr(),INFO_INFO);
@@ -613,8 +613,8 @@ static struct my_option my_long_options[] =
0, 1},
{"max_allowed_packet", OPT_MAX_ALLOWED_PACKET, "",
(gptr*) &max_allowed_packet, (gptr*) &max_allowed_packet, 0, GET_ULONG,
- REQUIRED_ARG, 16 *1024L*1024L, 4096, 512*1024L*1024L, MALLOC_OVERHEAD,
- 1024, 0},
+ REQUIRED_ARG, 16 *1024L*1024L, 4096, (longlong) 2*1024L*1024L*1024L,
+ MALLOC_OVERHEAD, 1024, 0},
{"net_buffer_length", OPT_NET_BUFFER_LENGTH, "",
(gptr*) &net_buffer_length, (gptr*) &net_buffer_length, 0, GET_ULONG,
REQUIRED_ARG, 16384, 1024, 512*1024*1024L, MALLOC_OVERHEAD, 1024, 0},
@@ -2346,7 +2346,7 @@ com_connect(String *buffer, char *line)
if (connected)
{
- sprintf(buff,"Connection id: %ld",mysql_thread_id(&mysql));
+ sprintf(buff,"Connection id: %lu",mysql_thread_id(&mysql));
put_info(buff,INFO_INFO);
sprintf(buff,"Current database: %s\n",
current_db ? current_db : "*** NONE ***");
@@ -2652,7 +2652,7 @@ com_status(String *buffer __attribute__((unused)),
{
MYSQL_RES *result;
LINT_INIT(result);
- tee_fprintf(stdout, "\nConnection id:\t\t%ld\n",mysql_thread_id(&mysql));
+ tee_fprintf(stdout, "\nConnection id:\t\t%lu\n",mysql_thread_id(&mysql));
if (!mysql_query(&mysql,"select DATABASE(),USER()") &&
(result=mysql_use_result(&mysql)))
{
diff --git a/client/mysqldump.c b/client/mysqldump.c
index af47b7c6955..018cd43ce87 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -37,7 +37,7 @@
** 10 Jun 2003: SET NAMES and --no-set-names by Alexander Barkov
*/
-#define DUMP_VERSION "10.3"
+#define DUMP_VERSION "10.4"
#include <my_global.h>
#include <my_sys.h>
@@ -81,7 +81,7 @@ static my_bool verbose=0,tFlag=0,cFlag=0,dFlag=0,quick= 1, extended_insert= 1,
opt_alldbs=0,opt_create_db=0,opt_first_slave=0,opt_set_names=0,
opt_autocommit=0,opt_master_data,opt_disable_keys=1,opt_xml=0,
opt_delete_master_logs=0, tty_password=0,
- opt_single_transaction=0;
+ opt_single_transaction=0, opt_comments= 0;
static MYSQL mysql_connection,*sock=0;
static char insert_pat[12 * 1024],*opt_password=0,*current_user=0,
*current_host=0,*path=0,*fields_terminated=0,
@@ -276,12 +276,15 @@ static struct my_option my_long_options[] =
NO_ARG, 0, 0, 0, 0, 0, 0},
{"max_allowed_packet", OPT_MAX_ALLOWED_PACKET, "",
(gptr*) &max_allowed_packet, (gptr*) &max_allowed_packet, 0,
- GET_ULONG, REQUIRED_ARG, 24*1024*1024, 4096, 1024*1024L*1024L,
- MALLOC_OVERHEAD, 1024, 0},
+ GET_ULONG, REQUIRED_ARG, 24*1024*1024, 4096,
+ (longlong) 2L*1024L*1024L*1024L, MALLOC_OVERHEAD, 1024, 0},
{"net_buffer_length", OPT_NET_BUFFER_LENGTH, "",
(gptr*) &net_buffer_length, (gptr*) &net_buffer_length, 0,
GET_ULONG, REQUIRED_ARG, 1024*1024L-1025, 4096, 16*1024L*1024L,
MALLOC_OVERHEAD-1024, 1024, 0},
+ {"comments", 'i', "Write additional information.",
+ (gptr*) &opt_comments, (gptr*) &opt_comments, 0, GET_BOOL, NO_ARG,
+ 1, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
@@ -298,6 +301,8 @@ static int init_dumping(char *);
static int dump_databases(char **);
static int dump_all_databases();
static char *quote_name(const char *name, char *buff, my_bool force);
+static const char *check_if_ignore_table(const char *table_name);
+
static void print_version(void)
{
@@ -341,7 +346,7 @@ static void write_header(FILE *sql_file, char *db_name)
fputs("<?xml version=\"1.0\"?>\n", sql_file);
fputs("<mysqldump>\n", sql_file);
}
- else
+ else if (opt_comments)
{
fprintf(sql_file, "-- MySQL dump %s\n--\n", DUMP_VERSION);
fprintf(sql_file, "-- Host: %s Database: %s\n",
@@ -652,6 +657,23 @@ static char *quote_name(const char *name, char *buff, my_bool force)
} /* quote_name */
+
+static char *quote_for_like(const char *name, char *buff)
+{
+ char *to= buff;
+ *to++= '\'';
+ while (*name)
+ {
+ if (*name == '\'' || *name == '_' || *name == '\\' || *name == '%')
+ *to++= '\\';
+ *to++= *name++;
+ }
+ to[0]= '\'';
+ to[1]= 0;
+ return buff;
+}
+
+
/*
Quote and print a string.
@@ -850,7 +872,8 @@ static uint getTableStructure(char *table, char* db)
}
write_header(sql_file, db);
}
- fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n",
+ if (!opt_xml && opt_comments)
+ fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n",
result_table);
if (opt_drop)
fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", opt_quoted_table);
@@ -926,7 +949,7 @@ static uint getTableStructure(char *table, char* db)
}
write_header(sql_file, db);
}
- if (!opt_xml)
+ if (!opt_xml && opt_comments)
fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n",
result_table);
if (opt_drop)
@@ -1063,16 +1086,9 @@ static uint getTableStructure(char *table, char* db)
/* Get MySQL specific create options */
if (create_options)
{
- ulong len= strlen(table);
- char *tmp= (char*) my_malloc(len * 2 + 1, MYF(MY_WME));
- if (!tmp)
- {
- ignore_errors= 0;
- safe_exit(EX_MYSQLERR);
- }
- mysql_real_escape_string(&mysql_connection, tmp, table, len);
- sprintf(buff,"show table status like \"%s\"", tmp);
- my_free(tmp, MYF(MY_WME));
+ char show_name_buff[FN_REFLEN];
+ sprintf(buff,"show table status like %s",
+ quote_for_like(table, show_name_buff));
if (mysql_query(sock, buff))
{
if (mysql_errno(sock) != ER_PARSE_ERROR)
@@ -1187,11 +1203,23 @@ static void dumpTable(uint numFields, char *table)
MYSQL_FIELD *field;
MYSQL_ROW row;
ulong rownr, row_break, total_length, init_length;
+ const char *table_type;
- if (verbose)
- fprintf(stderr, "-- Sending SELECT query...\n");
result_table= quote_name(table,table_buff, 1);
opt_quoted_table= quote_name(table, table_buff2, 0);
+
+ /* Check table type */
+ if ((table_type= check_if_ignore_table(table)))
+ {
+ if (verbose)
+ fprintf(stderr,
+ "-- Skipping data for table '%s' because it's of type %s\n",
+ table, table_type);
+ return;
+ }
+
+ if (verbose)
+ fprintf(stderr, "-- Sending SELECT query...\n");
if (path)
{
char filename[FN_REFLEN], tmp_path[FN_REFLEN];
@@ -1230,14 +1258,14 @@ static void dumpTable(uint numFields, char *table)
}
else
{
- if (!opt_xml)
+ if (!opt_xml && opt_comments)
fprintf(md_result_file,"\n--\n-- Dumping data for table %s\n--\n",
result_table);
sprintf(query, "SELECT /*!40001 SQL_NO_CACHE */ * FROM %s",
result_table);
if (where)
{
- if (!opt_xml)
+ if (!opt_xml && opt_comments)
fprintf(md_result_file,"-- WHERE: %s\n",where);
strxmov(strend(query), " WHERE ",where,NullS);
}
@@ -1333,11 +1361,23 @@ static void dumpTable(uint numFields, char *table)
}
else
{
- /* change any strings ("inf","nan",..) into NULL */
+ /* change any strings ("inf", "-inf", "nan") into NULL */
char *ptr = row[i];
- dynstr_append(&extended_row,
- (!my_isalpha(charset_info,*ptr)) ?
- ptr : "NULL");
+ if (my_isalpha(charset_info, *ptr) || (*ptr == '-' &&
+ my_isalpha(charset_info, ptr[1])))
+ dynstr_append(&extended_row, "NULL");
+ else
+ {
+ if (field->type == FIELD_TYPE_DECIMAL)
+ {
+ /* add " signs around */
+ dynstr_append(&extended_row, "\"");
+ dynstr_append(&extended_row, ptr);
+ dynstr_append(&extended_row, "\"");
+ }
+ else
+ dynstr_append(&extended_row, ptr);
+ }
}
}
else
@@ -1369,7 +1409,7 @@ static void dumpTable(uint numFields, char *table)
}
else
{
- /* change any strings ("inf","nan",..) into NULL */
+ /* change any strings ("inf", "-inf", "nan") into NULL */
char *ptr = row[i];
if (opt_xml)
{
@@ -1379,19 +1419,20 @@ static void dumpTable(uint numFields, char *table)
md_result_file);
fputs("</field>\n", md_result_file);
}
+ else if (my_isalpha(charset_info, *ptr) ||
+ (*ptr == '-' && my_isalpha(charset_info, ptr[1])))
+ fputs("NULL", md_result_file);
+ else if (field->type == FIELD_TYPE_DECIMAL)
+ {
+ /* add " signs around */
+ fputs("\"", md_result_file);
+ fputs(ptr, md_result_file);
+ fputs("\"", md_result_file);
+ }
else
- fputs((!my_isalpha(charset_info,*ptr)) ?
- ptr : "NULL", md_result_file);
+ fputs(ptr, md_result_file);
}
}
- else
- {
- if (opt_xml)
- print_xml_tag1(md_result_file, "\t\t", "field name=",
- field->name, "NULL</field>\n");
- else
- fputs("NULL", md_result_file);
- }
}
}
@@ -1529,8 +1570,8 @@ static int init_dumping(char *database)
*/
char quoted_database_buf[64*2+3];
char *qdatabase= quote_name(database,quoted_database_buf,opt_quoted);
-
- fprintf(md_result_file,"\n--\n-- Current Database: %s\n--\n", qdatabase);
+ if (opt_comments)
+ fprintf(md_result_file,"\n--\n-- Current Database: %s\n--\n", qdatabase);
if (!opt_create_db)
{
char qbuf[256];
@@ -1726,6 +1767,61 @@ static void print_value(FILE *file, MYSQL_RES *result, MYSQL_ROW row,
} /* print_value */
+/*
+ Check if we the table is one of the table types that should be ignored:
+ MRG_ISAM, MRG_MYISAM
+
+ SYNOPSIS
+ check_if_ignore_table()
+ table_name Table name to check
+
+ GLOBAL VARIABLES
+ sock MySQL socket
+ verbose Write warning messages
+
+ RETURN
+ 0 Table should be backuped
+ # Type of table (that should be skipped)
+*/
+
+static const char *check_if_ignore_table(const char *table_name)
+{
+ char buff[FN_REFLEN+80], show_name_buff[FN_REFLEN];
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ const char *result= 0;
+
+ sprintf(buff,"show table status like %s",
+ quote_for_like(table_name, show_name_buff));
+ if (mysql_query(sock, buff))
+ {
+ if (mysql_errno(sock) != ER_PARSE_ERROR)
+ { /* If old MySQL version */
+ if (verbose)
+ fprintf(stderr,
+ "-- Warning: Couldn't get status information for table %s (%s)\n",
+ table_name,mysql_error(sock));
+ return 0; /* assume table is ok */
+ }
+ }
+ if (!(res= mysql_store_result(sock)) ||
+ !(row= mysql_fetch_row(res)))
+ {
+ fprintf(stderr,
+ "Error: Couldn't read status information for table %s (%s)\n",
+ table_name, mysql_error(sock));
+ if (res)
+ mysql_free_result(res);
+ return 0; /* assume table is ok */
+ }
+ if (strcmp(row[1], (result= "MRG_MyISAM")) &&
+ strcmp(row[1], (result= "MRG_ISAM")))
+ result= 0;
+ mysql_free_result(res);
+ return result;
+}
+
+
int main(int argc, char **argv)
{
MYSQL_ROW row;
@@ -1795,8 +1891,9 @@ int main(int argc, char **argv)
row = mysql_fetch_row(master);
if (row && row[0] && row[1])
{
- fprintf(md_result_file,
- "\n--\n-- Position to start replication from\n--\n\n");
+ if (opt_comments)
+ fprintf(md_result_file,
+ "\n--\n-- Position to start replication from\n--\n\n");
fprintf(md_result_file,
"CHANGE MASTER TO MASTER_LOG_FILE='%s', \
MASTER_LOG_POS=%s ;\n",row[0],row[1]);
diff --git a/configure.in b/configure.in
index f46e48eaa1a..e607f87747b 100644
--- a/configure.in
+++ b/configure.in
@@ -731,7 +731,7 @@ AC_CHECK_HEADERS(fcntl.h float.h floatingpoint.h ieeefp.h limits.h \
strings.h string.h synch.h sys/mman.h sys/socket.h netinet/in.h arpa/inet.h \
sys/timeb.h sys/types.h sys/un.h sys/vadvise.h sys/wait.h term.h \
unistd.h utime.h sys/utime.h termio.h termios.h sched.h crypt.h alloca.h \
- sys/ioctl.h malloc.h sys/malloc.h)
+ sys/ioctl.h malloc.h sys/malloc.h linux/config.h)
#--------------------------------------------------------------------
# Check for system libraries. Adds the library to $LIBS
diff --git a/dbug/dbug.c b/dbug/dbug.c
index f7b2fb75ba0..d96ef0cae09 100644
--- a/dbug/dbug.c
+++ b/dbug/dbug.c
@@ -501,7 +501,7 @@ void _db_push_ (const char *control)
if (! _db_fp_)
_db_fp_= stderr; /* Output stream, default stderr */
- if (control && *control == '-')
+ if (*control == '-')
{
if (*++control == '#')
control++;
diff --git a/include/config-win.h b/include/config-win.h
index 86318bddbcb..10490fd2f91 100644
--- a/include/config-win.h
+++ b/include/config-win.h
@@ -93,6 +93,7 @@ functions */
#define LONGLONG_MIN ((__int64) 0x8000000000000000)
#define LONGLONG_MAX ((__int64) 0x7FFFFFFFFFFFFFFF)
+#define ULONGLONG_MAX ((unsigned __int64) 0xFFFFFFFFFFFFFFFF)
#define LL(A) ((__int64) A)
/* Type information */
@@ -158,6 +159,10 @@ typedef uint rf_SetTimer;
#define USE_MB_IDENT 1
#define USE_STRCOLL 1
+/* All windows servers should support .sym files */
+#undef USE_SYMDIR
+#define USE_SYMDIR
+
/* If LOAD DATA LOCAL INFILE should be enabled by default */
#define ENABLED_LOCAL_INFILE 1
diff --git a/include/my_base.h b/include/my_base.h
index 25521d7b13d..89b46de520f 100644
--- a/include/my_base.h
+++ b/include/my_base.h
@@ -190,11 +190,17 @@ enum ha_base_keytype {
/* poor old NISAM has 8-bit flags :-( */
#define HA_SORT_ALLOWS_SAME 128 /* Intern bit when sorting records */
#endif
+/*
+ Key has a part that can have end space. If this is an unique key
+ we have to handle it differently from other unique keys as we can find
+ many matching rows for one key (becaue end space are not compared)
+*/
+#define HA_END_SPACE_KEY 4096
- /* These flags can be order to key-seg-flag */
+ /* These flags can be added to key-seg-flag */
#define HA_SPACE_PACK 1 /* Pack space in key-seg */
-#define HA_PART_KEY 4 /* Used by MySQL for part-key-cols */
+#define HA_PART_KEY_SEG 4 /* Used by MySQL for part-key-cols */
#define HA_VAR_LENGTH 8
#define HA_NULL_PART 16
#define HA_BLOB_PART 32
diff --git a/include/my_dir.h b/include/my_dir.h
index 4ccda050914..851b6d8d7e9 100644
--- a/include/my_dir.h
+++ b/include/my_dir.h
@@ -74,14 +74,21 @@ typedef struct my_stat
#endif /* USE_MY_STAT_STRUCT */
-typedef struct fileinfo /* Struct returned from my_dir & my_stat */
+/* Struct describing one file returned from my_dir */
+typedef struct fileinfo
{
char *name;
- MY_STAT mystat;
+ MY_STAT *mystat;
} FILEINFO;
typedef struct st_my_dir /* Struct returned from my_dir */
{
+ /*
+ These members are just copies of parts of DYNAMIC_ARRAY structure,
+ which is allocated right after the end of MY_DIR structure (MEM_ROOT
+ for storing names is also resides there). We've left them here because
+ we don't want to change code that uses my_dir.
+ */
struct fileinfo *dir_entry;
uint number_off_files;
} MY_DIR;
diff --git a/include/my_global.h b/include/my_global.h
index d74a66e9ab9..32516cd5810 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -287,6 +287,9 @@ C_MODE_END
#endif
#ifdef HAVE_ATOMIC_ADD
#define __SMP__
+#ifdef HAVE_LINUX_CONFIG_H
+#include <linux/config.h> /* May define CONFIG_SMP */
+#endif
#ifndef CONFIG_SMP
#define CONFIG_SMP
#endif
@@ -626,11 +629,26 @@ extern double my_atof(const char*);
#define HAVE_LONG_LONG 1
#endif
+/*
+ Some pre-ANSI-C99 systems like AIX 5.1 and Linux/GCC 2.95 define
+ ULONGLONG_MAX, LONGLONG_MIN, LONGLONG_MAX; we use them if they're defined.
+ Also on Windows we define these constants by hand in config-win.h.
+*/
+
#if defined(HAVE_LONG_LONG) && !defined(LONGLONG_MIN)
#define LONGLONG_MIN ((long long) 0x8000000000000000LL)
#define LONGLONG_MAX ((long long) 0x7FFFFFFFFFFFFFFFLL)
#endif
+#if defined(HAVE_LONG_LONG) && !defined(ULONGLONG_MAX)
+/* First check for ANSI C99 definition: */
+#ifdef ULLONG_MAX
+#define ULONGLONG_MAX ULLONG_MAX
+#else
+#define ULONGLONG_MAX ((unsigned long long)(~0ULL))
+#endif
+#endif /* defined (HAVE_LONG_LONG) && !defined(ULONGLONG_MAX)*/
+
#if SIZEOF_LONG == 4
#define INT_MIN32 (long) 0x80000000L
#define INT_MAX32 (long) 0x7FFFFFFFL
diff --git a/include/my_pthread.h b/include/my_pthread.h
index 44e6edcddec..cf04d078c70 100644
--- a/include/my_pthread.h
+++ b/include/my_pthread.h
@@ -117,6 +117,7 @@ void pthread_exit(void *a); /* was #define pthread_exit(A) ExitThread(A)*/
#undef SAFE_MUTEX /* This will cause conflicts */
#define pthread_key(T,V) DWORD V
#define pthread_key_create(A,B) ((*A=TlsAlloc())==0xFFFFFFFF)
+#define pthread_key_delete(A) TlsFree(A)
#define pthread_getspecific(A) (TlsGetValue(A))
#define my_pthread_getspecific(T,A) ((T) TlsGetValue(A))
#define my_pthread_getspecific_ptr(T,V) ((T) TlsGetValue(V))
@@ -125,6 +126,7 @@ void pthread_exit(void *a); /* was #define pthread_exit(A) ExitThread(A)*/
#else
#define pthread_key(T,V) __declspec(thread) T V
#define pthread_key_create(A,B) pthread_dummy(0)
+#define pthread_key_delete(A) pthread_dummy(0)
#define pthread_getspecific(A) (&(A))
#define my_pthread_getspecific(T,A) (&(A))
#define my_pthread_getspecific_ptr(T,V) (V)
@@ -180,6 +182,7 @@ extern int pthread_mutex_destroy (pthread_mutex_t *);
typedef int pthread_attr_t; /* Needed by Unixware 7.0.0 */
#define pthread_key_create(A,B) thr_keycreate((A),(B))
+#define pthread_key_delete(A) thr_keydelete(A)
#define pthread_handler_decl(A,B) void *A(void *B)
#define pthread_key(T,V) pthread_key_t V
diff --git a/include/my_sys.h b/include/my_sys.h
index 59d5767d204..7927192848a 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -163,7 +163,7 @@ extern char *my_strdup_with_length(const byte *from, uint length,
#if defined(_AIX) && !defined(__GNUC__) && !defined(_AIX43)
#pragma alloca
#endif /* _AIX */
-#if defined(__GNUC__) && !defined(HAVE_ALLOCA_H)
+#if defined(__GNUC__) && !defined(HAVE_ALLOCA_H) && ! defined(alloca)
#define alloca __builtin_alloca
#endif /* GNUC */
#define my_alloca(SZ) alloca((size_t) (SZ))
@@ -583,7 +583,7 @@ extern int my_printf_error _VARARGS((uint my_err, const char *format,
extern int my_message(uint my_err, const char *str,myf MyFlags);
extern int my_message_no_curses(uint my_err, const char *str,myf MyFlags);
extern int my_message_curses(uint my_err, const char *str,myf MyFlags);
-extern void my_init(void);
+extern my_bool my_init(void);
extern void my_end(int infoflag);
extern int my_redel(const char *from, const char *to, int MyFlags);
extern int my_copystat(const char *from, const char *to, int MyFlags);
diff --git a/include/mysql_com.h b/include/mysql_com.h
index 2036b3d0ac2..d4c1ac5440a 100644
--- a/include/mysql_com.h
+++ b/include/mysql_com.h
@@ -351,7 +351,7 @@ const char *mysql_errno_to_sqlstate(unsigned int mysql_errno);
/* Some other useful functions */
-void my_init(void);
+my_bool my_init(void);
int load_defaults(const char *conf_file, const char **groups,
int *argc, char ***argv);
my_bool my_thread_init(void);
diff --git a/include/mysql_embed.h b/include/mysql_embed.h
index 7a169d4133e..df358e29872 100644
--- a/include/mysql_embed.h
+++ b/include/mysql_embed.h
@@ -32,4 +32,6 @@
#undef MYSQL_SERVER_SUFFIX
#define MYSQL_SERVER_SUFFIX "-embedded"
+#undef HAVE_QUERY_CACHE /* Cache dosn't work yet */
+
#endif /* EMBEDDED_LIBRARY */
diff --git a/innobase/btr/btr0cur.c b/innobase/btr/btr0cur.c
index 93e9e815c99..b2bfdbec4e4 100644
--- a/innobase/btr/btr0cur.c
+++ b/innobase/btr/btr0cur.c
@@ -1151,7 +1151,6 @@ btr_cur_pessimistic_insert(
}
/*==================== B-TREE UPDATE =========================*/
-/* Only clustered index records are modified using these functions */
/*****************************************************************
For an update, checks the locks and does the undo logging. */
@@ -1175,12 +1174,16 @@ btr_cur_upd_lock_and_undo(
ut_ad(cursor && update && thr && roll_ptr);
- /* Only clustered index records are updated using this function */
- ut_ad((cursor->index)->type & DICT_CLUSTERED);
-
rec = btr_cur_get_rec(cursor);
index = cursor->index;
+ if (!(index->type & DICT_CLUSTERED)) {
+ /* We do undo logging only when we update a clustered index
+ record */
+ return(lock_sec_rec_modify_check_and_lock(flags, rec, index,
+ thr));
+ }
+
/* Check if we have to wait for a lock: enqueue an explicit lock
request if yes */
@@ -1227,6 +1230,13 @@ btr_cur_update_in_place_log(
mach_write_to_1(log_ptr, flags);
log_ptr++;
+ /* The code below assumes index is a clustered index: change index to
+ the clustered index if we are updating a secondary index record (or we
+ could as well skip writing the sys col values to the log in this case
+ because they are not needed for a secondary index record update) */
+
+ index = dict_table_get_first_index(index->table);
+
log_ptr = row_upd_write_sys_vals_to_log(index, trx, roll_ptr, log_ptr,
mtr);
mach_write_to_2(log_ptr, rec - buf_frame_align(rec));
@@ -1394,13 +1404,10 @@ btr_cur_update_in_place(
buf_block_t* block;
ulint err;
rec_t* rec;
- dulint roll_ptr;
+ dulint roll_ptr = ut_dulint_zero;
trx_t* trx;
ibool was_delete_marked;
- /* Only clustered index records are updated using this function */
- ut_ad(cursor->index->type & DICT_CLUSTERED);
-
rec = btr_cur_get_rec(cursor);
index = cursor->index;
trx = thr_get_trx(thr);
@@ -1425,7 +1432,12 @@ btr_cur_update_in_place(
block = buf_block_align(rec);
if (block->is_hashed) {
- if (row_upd_changes_ord_field_binary(NULL, index, update)) {
+ /* The function row_upd_changes_ord_field_binary works only
+ if the update vector was built for a clustered index, we must
+ NOT call it if index is secondary */
+
+ if (!(index->type & DICT_CLUSTERED)
+ || row_upd_changes_ord_field_binary(NULL, index, update)) {
/* Remove possible hash index pointer to this record */
btr_search_update_hash_on_delete(cursor);
@@ -1499,9 +1511,6 @@ btr_cur_optimistic_update(
mem_heap_t* heap;
ibool reorganized = FALSE;
ulint i;
-
- /* Only clustered index records are updated using this function */
- ut_ad((cursor->index)->type & DICT_CLUSTERED);
page = btr_cur_get_page(cursor);
rec = btr_cur_get_rec(cursor);
@@ -1551,8 +1560,8 @@ btr_cur_optimistic_update(
new_entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec, heap);
- row_upd_index_replace_new_col_vals(new_entry, index, update, NULL);
-
+ row_upd_index_replace_new_col_vals_index_pos(new_entry, index, update,
+ NULL);
old_rec_size = rec_get_size(rec);
new_rec_size = rec_get_converted_size(new_entry);
@@ -1735,7 +1744,6 @@ btr_cur_pessimistic_update(
index = cursor->index;
tree = index->tree;
- ut_ad(index->type & DICT_CLUSTERED);
ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree),
MTR_MEMO_X_LOCK));
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
@@ -1786,8 +1794,8 @@ btr_cur_pessimistic_update(
new_entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec, heap);
- row_upd_index_replace_new_col_vals(new_entry, index, update, heap);
-
+ row_upd_index_replace_new_col_vals_index_pos(new_entry, index, update,
+ heap);
if (!(flags & BTR_KEEP_SYS_FLAG)) {
row_upd_index_entry_sys_field(new_entry, index, DATA_ROLL_PTR,
roll_ptr);
diff --git a/innobase/include/btr0cur.h b/innobase/include/btr0cur.h
index 506877333c3..31aecef8104 100644
--- a/innobase/include/btr0cur.h
+++ b/innobase/include/btr0cur.h
@@ -188,22 +188,6 @@ btr_cur_pessimistic_insert(
que_thr_t* thr, /* in: query thread or NULL */
mtr_t* mtr); /* in: mtr */
/*****************************************************************
-Updates a secondary index record when the update causes no size
-changes in its fields. The only case when this function is currently
-called is that in a char field characters change to others which
-are identified in the collation order. */
-
-ulint
-btr_cur_update_sec_rec_in_place(
-/*============================*/
- /* out: DB_SUCCESS or error number */
- btr_cur_t* cursor, /* in: cursor on the record to update;
- cursor stays valid and positioned on the
- same record */
- upd_t* update, /* in: update vector */
- que_thr_t* thr, /* in: query thread */
- mtr_t* mtr); /* in: mtr */
-/*****************************************************************
Updates a record when the update causes no size changes in its fields. */
ulint
diff --git a/innobase/include/row0upd.h b/innobase/include/row0upd.h
index 473c55c7ef9..f5e0a88231f 100644
--- a/innobase/include/row0upd.h
+++ b/innobase/include/row0upd.h
@@ -123,8 +123,8 @@ row_upd_changes_field_size_or_external(
/* out: TRUE if the update changes the size of
some field in index or the field is external
in rec or update */
- rec_t* rec, /* in: record in clustered index */
- dict_index_t* index, /* in: clustered index */
+ rec_t* rec, /* in: record in index */
+ dict_index_t* index, /* in: index */
upd_t* update);/* in: update vector */
/***************************************************************
Replaces the new column values stored in the update vector to the record
@@ -172,12 +172,30 @@ Replaces the new column values stored in the update vector to the index entry
given. */
void
+row_upd_index_replace_new_col_vals_index_pos(
+/*=========================================*/
+ dtuple_t* entry, /* in/out: index entry where replaced */
+ dict_index_t* index, /* in: index; NOTE that this may also be a
+ non-clustered index */
+ upd_t* update, /* in: an update vector built for the index so
+ that the field number in an upd_field is the
+ index position */
+ mem_heap_t* heap); /* in: memory heap to which we allocate and
+ copy the new values, set this as NULL if you
+ do not want allocation */
+/***************************************************************
+Replaces the new column values stored in the update vector to the index entry
+given. */
+
+void
row_upd_index_replace_new_col_vals(
/*===============================*/
dtuple_t* entry, /* in/out: index entry where replaced */
- dict_index_t* index, /* in: index; NOTE that may also be a
+ dict_index_t* index, /* in: index; NOTE that this may also be a
non-clustered index */
- upd_t* update, /* in: update vector */
+ upd_t* update, /* in: an update vector built for the
+ CLUSTERED index so that the field number in
+ an upd_field is the clustered index position */
mem_heap_t* heap); /* in: memory heap to which we allocate and
copy the new values, set this as NULL if you
do not want allocation */
@@ -199,7 +217,9 @@ row_upd_changes_ord_field_binary(
known when this function is called, e.g., at
compile time */
dict_index_t* index, /* in: index of the record */
- upd_t* update);/* in: update vector for the row */
+ upd_t* update);/* in: update vector for the row; NOTE: the
+ field numbers in this MUST be clustered index
+ positions! */
/***************************************************************
Checks if an update vector changes an ordering field of an index record.
This function is fast if the update vector is short or the number of ordering
@@ -271,7 +291,10 @@ row_upd_index_parse(
/* Update vector field */
struct upd_field_struct{
- ulint field_no; /* field number in the clustered
+ ulint field_no; /* field number in an index, usually
+ the clustered index, but in updating
+ a secondary index record in btr0cur.c
+ this is the position in the secondary
index */
que_node_t* exp; /* expression for calculating a new
value: it refers to column values and
diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c
index af589cd9441..7fdca02ee94 100644
--- a/innobase/lock/lock0lock.c
+++ b/innobase/lock/lock0lock.c
@@ -339,6 +339,11 @@ lock_deadlock_recursive(
ulint* cost); /* in/out: number of calculation steps thus
far: if this exceeds LOCK_MAX_N_STEPS_...
we return TRUE */
+
+#define lock_mutex_enter_kernel() mutex_enter(&kernel_mutex)
+#define lock_mutex_exit_kernel() mutex_exit(&kernel_mutex)
+
+#ifdef notdefined
/*************************************************************************
Reserves the kernel mutex. This function is used in this module to allow
monitoring the contention degree on the kernel mutex caused by the lock
@@ -362,6 +367,7 @@ lock_mutex_exit_kernel(void)
{
mutex_exit(&kernel_mutex);
}
+#endif
#ifdef notdefined
diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c
index 1a7864be5e9..c89f41f69ad 100644
--- a/innobase/row/row0ins.c
+++ b/innobase/row/row0ins.c
@@ -225,11 +225,15 @@ ulint
row_ins_sec_index_entry_by_modify(
/*==============================*/
/* out: DB_SUCCESS or error code */
+ ulint mode, /* in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
+ depending on whether mtr holds just a leaf
+ latch or also a tree latch */
btr_cur_t* cursor, /* in: B-tree cursor */
dtuple_t* entry, /* in: index entry to insert */
que_thr_t* thr, /* in: query thread */
mtr_t* mtr) /* in: mtr */
{
+ big_rec_t* dummy_big_rec;
mem_heap_t* heap;
upd_t* update;
rec_t* rec;
@@ -241,16 +245,28 @@ row_ins_sec_index_entry_by_modify(
ut_ad(rec_get_deleted_flag(rec));
/* We know that in the alphabetical ordering, entry and rec are
- identical. But in their binary form there may be differences if
+ identified. But in their binary form there may be differences if
there are char fields in them. Therefore we have to calculate the
- difference and do an update-in-place if necessary. */
+ difference. */
heap = mem_heap_create(1024);
update = row_upd_build_sec_rec_difference_binary(cursor->index,
entry, rec, heap);
+ if (mode == BTR_MODIFY_LEAF) {
+ /* Try an optimistic updating of the record, keeping changes
+ within the page */
- err = btr_cur_update_sec_rec_in_place(cursor, update, thr, mtr);
+ err = btr_cur_optimistic_update(BTR_KEEP_SYS_FLAG, cursor,
+ update, 0, thr, mtr);
+ if (err == DB_OVERFLOW || err == DB_UNDERFLOW) {
+ err = DB_FAIL;
+ }
+ } else {
+ ut_a(mode == BTR_MODIFY_TREE);
+ err = btr_cur_pessimistic_update(BTR_KEEP_SYS_FLAG, cursor,
+ &dummy_big_rec, update, 0, thr, mtr);
+ }
mem_heap_free(heap);
@@ -1838,7 +1854,8 @@ row_ins_index_entry_low(
ext_vec, n_ext_vec,
thr, &mtr);
} else {
- err = row_ins_sec_index_entry_by_modify(&cursor, entry,
+ err = row_ins_sec_index_entry_by_modify(mode, &cursor,
+ entry,
thr, &mtr);
}
diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c
index f41574b2855..e6080a5f201 100644
--- a/innobase/row/row0sel.c
+++ b/innobase/row/row0sel.c
@@ -51,7 +51,8 @@ to que_run_threads: this is to allow canceling runaway queries */
/************************************************************************
Returns TRUE if the user-defined column values in a secondary index record
-are the same as the corresponding columns in the clustered index record.
+are alphabetically the same as the corresponding columns in the clustered
+index record.
NOTE: the comparison is NOT done as a binary comparison, but character
fields are compared with collation! */
static
@@ -96,11 +97,6 @@ row_sel_sec_rec_is_for_clust_rec(
clust_len = ifield->prefix_len;
}
- if (sec_len != clust_len) {
-
- return(FALSE);
- }
-
if (0 != cmp_data_data(dict_col_get_type(col),
clust_field, clust_len,
sec_field, sec_len)) {
diff --git a/innobase/row/row0umod.c b/innobase/row/row0umod.c
index 0a050e0a1b6..1bfd71f8c64 100644
--- a/innobase/row/row0umod.c
+++ b/innobase/row/row0umod.c
@@ -377,8 +377,14 @@ row_undo_mod_del_mark_or_remove_sec_low(
}
/***************************************************************
-Delete marks or removes a secondary index entry if found. */
-UNIV_INLINE
+Delete marks or removes a secondary index entry if found.
+NOTE that if we updated the fields of a delete-marked secondary index record
+so that alphabetically they stayed the same, e.g., 'abc' -> 'aBc', we cannot
+return to the original values because we do not know them. But this should
+not cause problems because in row0sel.c, in queries we always retrieve the
+clustered index record or an earlier version of it, if the secondary index
+record through which we do the search is delete-marked. */
+static
ulint
row_undo_mod_del_mark_or_remove_sec(
/*================================*/
@@ -403,20 +409,31 @@ row_undo_mod_del_mark_or_remove_sec(
}
/***************************************************************
-Delete unmarks a secondary index entry which must be found. */
+Delete unmarks a secondary index entry which must be found. It might not be
+delete-marked at the moment, but it does not harm to unmark it anyway. We also
+need to update the fields of the secondary index record if we updated its
+fields but alphabetically they stayed the same, e.g., 'abc' -> 'aBc'. */
static
-void
-row_undo_mod_del_unmark_sec(
-/*========================*/
+ulint
+row_undo_mod_del_unmark_sec_and_undo_update(
+/*========================================*/
+ /* out: DB_FAIL or DB_SUCCESS or
+ DB_OUT_OF_FILE_SPACE */
+ ulint mode, /* in: search mode: BTR_MODIFY_LEAF or
+ BTR_MODIFY_TREE */
undo_node_t* node, /* in: row undo node */
que_thr_t* thr, /* in: query thread */
dict_index_t* index, /* in: index */
dtuple_t* entry) /* in: index entry */
{
+ mem_heap_t* heap;
btr_pcur_t pcur;
btr_cur_t* btr_cur;
- ulint err;
+ upd_t* update;
+ rec_t* rec;
+ ulint err = DB_SUCCESS;
ibool found;
+ big_rec_t* dummy_big_rec;
mtr_t mtr;
char err_buf[1000];
@@ -425,8 +442,8 @@ row_undo_mod_del_unmark_sec(
log_free_check();
mtr_start(&mtr);
- found = row_search_index_entry(index, entry, BTR_MODIFY_LEAF, &pcur,
- &mtr);
+ found = row_search_index_entry(index, entry, mode, &pcur, &mtr);
+
if (!found) {
fprintf(stderr,
"InnoDB: error in sec index entry del undo in\n"
@@ -443,17 +460,47 @@ row_undo_mod_del_unmark_sec(
"%s\nInnoDB: Make a detailed bug report and send it\n",
err_buf);
fprintf(stderr, "InnoDB: to mysql@lists.mysql.com\n");
-
} else {
btr_cur = btr_pcur_get_btr_cur(&pcur);
+ rec = btr_cur_get_rec(btr_cur);
+
err = btr_cur_del_mark_set_sec_rec(BTR_NO_LOCKING_FLAG,
btr_cur, FALSE, thr, &mtr);
- ut_ad(err == DB_SUCCESS);
+ ut_a(err == DB_SUCCESS);
+ heap = mem_heap_create(100);
+
+ update = row_upd_build_sec_rec_difference_binary(index, entry,
+ rec, heap);
+ if (upd_get_n_fields(update) == 0) {
+
+ /* Do nothing */
+
+ } else if (mode == BTR_MODIFY_LEAF) {
+ /* Try an optimistic updating of the record, keeping
+ changes within the page */
+
+ err = btr_cur_optimistic_update(BTR_KEEP_SYS_FLAG
+ | BTR_NO_LOCKING_FLAG,
+ btr_cur, update, 0, thr, &mtr);
+ if (err == DB_OVERFLOW || err == DB_UNDERFLOW) {
+ err = DB_FAIL;
+ }
+ } else {
+ ut_a(mode == BTR_MODIFY_TREE);
+ err = btr_cur_pessimistic_update(BTR_KEEP_SYS_FLAG
+ | BTR_NO_LOCKING_FLAG,
+ btr_cur, &dummy_big_rec,
+ update, 0, thr, &mtr);
+ }
+
+ mem_heap_free(heap);
}
btr_pcur_close(&pcur);
mtr_commit(&mtr);
+
+ return(err);
}
/***************************************************************
@@ -501,13 +548,14 @@ static
ulint
row_undo_mod_del_mark_sec(
/*======================*/
- /* out: DB_SUCCESS */
+ /* out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
undo_node_t* node, /* in: row undo node */
que_thr_t* thr) /* in: query thread */
{
mem_heap_t* heap;
dtuple_t* entry;
dict_index_t* index;
+ ulint err;
heap = mem_heap_create(1024);
@@ -516,7 +564,21 @@ row_undo_mod_del_mark_sec(
entry = row_build_index_entry(node->row, index, heap);
- row_undo_mod_del_unmark_sec(node, thr, index, entry);
+ err = row_undo_mod_del_unmark_sec_and_undo_update(
+ BTR_MODIFY_LEAF,
+ node, thr, index, entry);
+ if (err == DB_FAIL) {
+ err = row_undo_mod_del_unmark_sec_and_undo_update(
+ BTR_MODIFY_TREE,
+ node, thr, index, entry);
+ }
+
+ if (err != DB_SUCCESS) {
+
+ mem_heap_free(heap);
+
+ return(err);
+ }
node->index = dict_table_get_next_index(node->index);
}
@@ -532,7 +594,7 @@ static
ulint
row_undo_mod_upd_exist_sec(
/*=======================*/
- /* out: DB_SUCCESS or error code */
+ /* out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
undo_node_t* node, /* in: row undo node */
que_thr_t* thr) /* in: query thread */
{
@@ -558,22 +620,48 @@ row_undo_mod_upd_exist_sec(
/* Build the newest version of the index entry */
entry = row_build_index_entry(node->row, index, heap);
+ /* NOTE that if we updated the fields of a
+ delete-marked secondary index record so that
+ alphabetically they stayed the same, e.g.,
+ 'abc' -> 'aBc', we cannot return to the original
+ values because we do not know them. But this should
+ not cause problems because in row0sel.c, in queries
+ we always retrieve the clustered index record or an
+ earlier version of it, if the secondary index record
+ through which we do the search is delete-marked. */
+
err = row_undo_mod_del_mark_or_remove_sec(node, thr,
- index, entry);
+ index, entry);
if (err != DB_SUCCESS) {
mem_heap_free(heap);
return(err);
}
-
+
/* We may have to update the delete mark in the
secondary index record of the previous version of
- the row */
+ the row. We also need to update the fields of
+ the secondary index record if we updated its fields
+ but alphabetically they stayed the same, e.g.,
+ 'abc' -> 'aBc'. */
row_upd_index_replace_new_col_vals(entry, index,
node->update, NULL);
+ err = row_undo_mod_del_unmark_sec_and_undo_update(
+ BTR_MODIFY_LEAF,
+ node, thr, index, entry);
+ if (err == DB_FAIL) {
+ err =
+ row_undo_mod_del_unmark_sec_and_undo_update(
+ BTR_MODIFY_TREE,
+ node, thr, index, entry);
+ }
- row_undo_mod_del_unmark_sec(node, thr, index, entry);
+ if (err != DB_SUCCESS) {
+ mem_heap_free(heap);
+
+ return(err);
+ }
}
node->index = dict_table_get_next_index(node->index);
diff --git a/innobase/row/row0upd.c b/innobase/row/row0upd.c
index 606f7404d50..b9e9b8c15c9 100644
--- a/innobase/row/row0upd.c
+++ b/innobase/row/row0upd.c
@@ -361,8 +361,8 @@ row_upd_changes_field_size_or_external(
/* out: TRUE if the update changes the size of
some field in index or the field is external
in rec or update */
- rec_t* rec, /* in: record in clustered index */
- dict_index_t* index, /* in: clustered index */
+ rec_t* rec, /* in: record in index */
+ dict_index_t* index, /* in: index */
upd_t* update) /* in: update vector */
{
upd_field_t* upd_field;
@@ -372,8 +372,6 @@ row_upd_changes_field_size_or_external(
ulint n_fields;
ulint i;
- ut_ad(index->type & DICT_CLUSTERED);
-
n_fields = upd_get_n_fields(update);
for (i = 0; i < n_fields; i++) {
@@ -698,7 +696,7 @@ row_upd_build_sec_rec_difference_binary(
ulint i;
/* This function is used only for a secondary index */
- ut_ad(0 == (index->type & DICT_CLUSTERED));
+ ut_a(0 == (index->type & DICT_CLUSTERED));
update = upd_create(dtuple_get_n_fields(entry), heap);
@@ -710,7 +708,13 @@ row_upd_build_sec_rec_difference_binary(
dfield = dtuple_get_nth_field(entry, i);
- ut_a(len == dfield_get_len(dfield));
+ /* NOTE that it may be that len != dfield_get_len(dfield) if we
+ are updating in a character set and collation where strings of
+ different length can be equal in an alphabetical comparison,
+ and also in the case where we have a column prefix index
+ and the last characters in the index field are spaces; the
+ latter case probably caused the assertion failures reported at
+ row0upd.c line 713 in versions 4.0.14 - 4.0.16. */
/* NOTE: we compare the fields as binary strings!
(No collation) */
@@ -820,12 +824,76 @@ Replaces the new column values stored in the update vector to the index entry
given. */
void
+row_upd_index_replace_new_col_vals_index_pos(
+/*=========================================*/
+ dtuple_t* entry, /* in/out: index entry where replaced */
+ dict_index_t* index, /* in: index; NOTE that this may also be a
+ non-clustered index */
+ upd_t* update, /* in: an update vector built for the index so
+ that the field number in an upd_field is the
+ index position */
+ mem_heap_t* heap) /* in: memory heap to which we allocate and
+ copy the new values, set this as NULL if you
+ do not want allocation */
+{
+ dict_field_t* field;
+ upd_field_t* upd_field;
+ dfield_t* dfield;
+ dfield_t* new_val;
+ ulint j;
+ ulint i;
+
+ ut_ad(index);
+
+ dtuple_set_info_bits(entry, update->info_bits);
+
+ for (j = 0; j < dict_index_get_n_fields(index); j++) {
+
+ field = dict_index_get_nth_field(index, j);
+
+ for (i = 0; i < upd_get_n_fields(update); i++) {
+
+ upd_field = upd_get_nth_field(update, i);
+
+ if (upd_field->field_no == j) {
+
+ dfield = dtuple_get_nth_field(entry, j);
+
+ new_val = &(upd_field->new_val);
+
+ dfield_set_data(dfield, new_val->data,
+ new_val->len);
+ if (heap && new_val->len != UNIV_SQL_NULL) {
+ dfield->data = mem_heap_alloc(heap,
+ new_val->len);
+ ut_memcpy(dfield->data, new_val->data,
+ new_val->len);
+ }
+
+ if (field->prefix_len > 0
+ && new_val->len != UNIV_SQL_NULL
+ && new_val->len > field->prefix_len) {
+
+ dfield->len = field->prefix_len;
+ }
+ }
+ }
+ }
+}
+
+/***************************************************************
+Replaces the new column values stored in the update vector to the index entry
+given. */
+
+void
row_upd_index_replace_new_col_vals(
/*===============================*/
dtuple_t* entry, /* in/out: index entry where replaced */
dict_index_t* index, /* in: index; NOTE that this may also be a
non-clustered index */
- upd_t* update, /* in: update vector */
+ upd_t* update, /* in: an update vector built for the
+ CLUSTERED index so that the field number in
+ an upd_field is the clustered index position */
mem_heap_t* heap) /* in: memory heap to which we allocate and
copy the new values, set this as NULL if you
do not want allocation */
@@ -893,7 +961,9 @@ row_upd_changes_ord_field_binary(
known when this function is called, e.g., at
compile time */
dict_index_t* index, /* in: index of the record */
- upd_t* update) /* in: update vector for the row */
+ upd_t* update) /* in: update vector for the row; NOTE: the
+ field numbers in this MUST be clustered index
+ positions! */
{
upd_field_t* upd_field;
dict_field_t* ind_field;
diff --git a/innobase/row/row0vers.c b/innobase/row/row0vers.c
index d4a463d8a96..fca56389e45 100644
--- a/innobase/row/row0vers.c
+++ b/innobase/row/row0vers.c
@@ -117,9 +117,10 @@ row_vers_impl_x_locked_off_kernel(
return(NULL);
}
- /* We look up if some earlier version of the clustered index record
- would require rec to be in a different state (delete marked or
- unmarked, or not existing). If there is such a version, then rec was
+ /* We look up if some earlier version, which was modified by the trx_id
+ transaction, of the clustered index record would require rec to be in
+ a different state (delete marked or unmarked, or have different field
+ values, or not existing). If there is such a version, then rec was
modified by the trx_id transaction, and it has an implicit x-lock on
rec. Note that if clust_rec itself would require rec to be in a
different state, then the trx_id transaction has not yet had time to
@@ -188,6 +189,8 @@ row_vers_impl_x_locked_off_kernel(
vers_del = rec_get_deleted_flag(prev_version);
+ /* We check if entry and rec are identified in the alphabetical
+ ordering */
if (0 == cmp_dtuple_rec(entry, rec)) {
/* The delete marks of rec and prev_version should be
equal for rec to be in the state required by
@@ -198,6 +201,20 @@ row_vers_impl_x_locked_off_kernel(
break;
}
+
+ /* It is possible that the row was updated so that the
+ secondary index record remained the same in
+ alphabetical ordering, but the field values changed
+ still. For example, 'abc' -> 'ABC'. Check also that. */
+
+ dtuple_set_types_binary(entry,
+ dtuple_get_n_fields(entry));
+ if (0 != cmp_dtuple_rec(entry, rec)) {
+
+ trx = trx_get_on_id(trx_id);
+
+ break;
+ }
} else if (!rec_del) {
/* The delete mark should be set in rec for it to be
in the state required by prev_version */
@@ -256,8 +273,8 @@ row_vers_must_preserve_del_marked(
Finds out if a version of the record, where the version >= the current
purge view, should have ientry as its secondary index entry. We check
if there is any not delete marked version of the record where the trx
-id >= purge view, and the secondary index entry == ientry; exactly in
-this case we return TRUE. */
+id >= purge view, and the secondary index entry and ientry are identified in
+the alphabetical ordering; exactly in this case we return TRUE. */
ibool
row_vers_old_has_index_entry(
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index a6718d6f320..728454a50fb 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -94,6 +94,25 @@ my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list);
static my_bool mysql_client_init= 0;
static my_bool org_my_init_done= 0;
+
+/*
+ Initialize the MySQL client library
+
+ SYNOPSIS
+ mysql_server_init()
+
+ NOTES
+ Should be called before doing any other calls to the MySQL
+ client library to initialize thread specific variables etc.
+ It's called by mysql_init() to ensure that things will work for
+ old not threaded applications that doesn't call mysql_server_init()
+ directly.
+
+ RETURN
+ 0 ok
+ 1 could not initialize environment (out of memory or thread keys)
+*/
+
int STDCALL mysql_server_init(int argc, char **argv, char **groups)
{
int result= 0;
@@ -101,7 +120,8 @@ int STDCALL mysql_server_init(int argc, char **argv, char **groups)
{
mysql_client_init=1;
org_my_init_done=my_init_done;
- my_init(); /* Will init threads */
+ if (my_init()) /* Will init threads */
+ return 1;
init_client_errs();
if (!mysql_port)
{
@@ -141,6 +161,7 @@ int STDCALL mysql_server_init(int argc, char **argv, char **groups)
return result;
}
+
void STDCALL mysql_server_end()
{
end_embedded_server();
diff --git a/myisam/ft_boolean_search.c b/myisam/ft_boolean_search.c
index f48a12b6f28..8cbb7a71a43 100644
--- a/myisam/ft_boolean_search.c
+++ b/myisam/ft_boolean_search.c
@@ -373,10 +373,13 @@ FT_INFO * ft_init_boolean_search(MI_INFO *info, uint keynr, byte *query,
to alloc queue with alloc_root()
*/
res=ftb->queue.max_elements=1+query_len/(min(ft_min_word_len,2)+1);
- ftb->queue.root=(byte **)alloc_root(&ftb->mem_root, (res+1)*sizeof(void*));
+ if (!(ftb->queue.root=
+ (byte **)alloc_root(&ftb->mem_root, (res+1)*sizeof(void*))))
+ goto err;
reinit_queue(& ftb->queue, res, 0, 0,
(int (*)(void*,byte*,byte*))FTB_WORD_cmp, 0);
- ftbe=(FTB_EXPR *)alloc_root(&ftb->mem_root, sizeof(FTB_EXPR));
+ if (!(ftbe=(FTB_EXPR *)alloc_root(&ftb->mem_root, sizeof(FTB_EXPR))))
+ goto err;
ftbe->weight=1;
ftbe->flags=FTB_FLAG_YES;
ftbe->nos=1;
@@ -394,6 +397,10 @@ FT_INFO * ft_init_boolean_search(MI_INFO *info, uint keynr, byte *query,
if (ftb->queue.elements<2) ftb->with_scan &= ~FTB_FLAG_TRUNC;
ftb->state=READY;
return ftb;
+err:
+ free_root(& ftb->mem_root, MYF(0));
+ my_free((gptr)ftb,MYF(0));
+ return 0;
}
diff --git a/myisam/mi_check.c b/myisam/mi_check.c
index f9e943fe42c..a55929805fa 100644
--- a/myisam/mi_check.c
+++ b/myisam/mi_check.c
@@ -112,20 +112,13 @@ int chk_status(MI_CHECK *param, register MI_INFO *info)
int chk_del(MI_CHECK *param, register MI_INFO *info, uint test_flag)
{
reg2 ha_rows i;
- uint j,delete_link_length;
+ uint delete_link_length;
my_off_t empty,next_link,old_link;
char buff[22],buff2[22];
DBUG_ENTER("chk_del");
- if (!(test_flag & T_SILENT))
- puts("- check key delete-chain");
-
LINT_INIT(old_link);
param->record_checksum=0;
- param->key_file_blocks=info->s->base.keystart;
- for (j=0 ; j < info->s->state.header.max_block_size ; j++)
- if (check_k_link(param,info,j))
- goto wrong;
delete_link_length=((info->s->options & HA_OPTION_PACK_RECORD) ? 20 :
info->s->rec_reflength+1);
@@ -352,6 +345,18 @@ int chk_key(MI_CHECK *param, register MI_INFO *info)
char buff[22],buff2[22];
DBUG_ENTER("chk_key");
+ if (!(param->testflag & T_SILENT))
+ puts("- check key delete-chain");
+
+ param->key_file_blocks=info->s->base.keystart;
+ for (key=0 ; key < info->s->state.header.max_block_size ; key++)
+ if (check_k_link(param,info,key))
+ {
+ if (param->testflag & T_VERBOSE) puts("");
+ mi_check_print_error(param,"key delete-link-chain corrupted");
+ DBUG_RETURN(-1);
+ }
+
if (!(param->testflag & T_SILENT)) puts("- check index reference");
all_keydata=all_totaldata=key_totlength=0;
@@ -507,6 +512,7 @@ int chk_key(MI_CHECK *param, register MI_INFO *info)
DBUG_RETURN(result);
} /* chk_key */
+
static int chk_index_down(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
my_off_t page, uchar *buff, ha_rows *keys,
ha_checksum *key_checksum, uint level)
@@ -548,7 +554,7 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
uint used_length,comp_flag,nod_flag,key_length,not_used;
uchar key[MI_MAX_POSSIBLE_KEY_BUFF],*temp_buff,*keypos,*old_keypos,*endpos;
my_off_t next_page,record;
- char llbuff[22],llbuff2[22];
+ char llbuff[22];
DBUG_ENTER("chk_index");
DBUG_DUMP("buff",(byte*) buff,mi_getint(buff));
@@ -646,7 +652,7 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
if (record >= info->state->data_file_length)
{
#ifndef DBUG_OFF
- char llbuff3[22];
+ char llbuff2[22], llbuff3[22];
#endif
mi_check_print_error(param,"Found key at page %s that points to record outside datafile",llstr(page,llbuff));
DBUG_PRINT("test",("page: %s record: %s filelength: %s",
@@ -1208,9 +1214,8 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
if (!rep_quick)
{
/* Get real path for data file */
- fn_format(param->temp_filename,name,"", MI_NAME_DEXT,2+4+32);
if ((new_file=my_raid_create(fn_format(param->temp_filename,
- param->temp_filename,"",
+ share->data_file_name, "",
DATA_TMP_EXT, 2+4),
0,param->tmpfile_createflag,
share->base.raid_type,
@@ -1882,11 +1887,9 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
if (!rep_quick)
{
/* Get real path for data file */
- fn_format(param->temp_filename,name,"", MI_NAME_DEXT,2+4+32);
if ((new_file=my_raid_create(fn_format(param->temp_filename,
- param->temp_filename, "",
- DATA_TMP_EXT,
- 2+4),
+ share->data_file_name, "",
+ DATA_TMP_EXT, 2+4),
0,param->tmpfile_createflag,
share->base.raid_type,
share->base.raid_chunks,
@@ -2248,9 +2251,8 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
if (!rep_quick)
{
/* Get real path for data file */
- fn_format(param->temp_filename,name,"", MI_NAME_DEXT,2+4+32);
if ((new_file=my_raid_create(fn_format(param->temp_filename,
- param->temp_filename, "",
+ share->data_file_name, "",
DATA_TMP_EXT,
2+4),
0,param->tmpfile_createflag,
diff --git a/myisam/mi_dbug.c b/myisam/mi_dbug.c
index 6548b38c135..02d1c7d05d6 100644
--- a/myisam/mi_dbug.c
+++ b/myisam/mi_dbug.c
@@ -137,6 +137,10 @@ void _mi_print_key(FILE *stream, register HA_KEYSEG *keyseg,
{
uint tmp_length;
get_key_length(tmp_length,key);
+ /*
+ The following command sometimes gives a warning from valgrind.
+ Not yet sure if the bug is in valgrind, glibc or mysqld
+ */
VOID(fprintf(stream,"%.*s",(int) tmp_length,key));
key+=tmp_length;
break;
diff --git a/myisam/mi_key.c b/myisam/mi_key.c
index 93e3b9621f3..97af156e89a 100644
--- a/myisam/mi_key.c
+++ b/myisam/mi_key.c
@@ -19,6 +19,7 @@
#include "myisamdef.h"
#include "m_ctype.h"
#include "sp_defs.h"
+#include <assert.h>
#ifdef HAVE_IEEEFP_H
#include <ieeefp.h>
#endif
@@ -397,53 +398,86 @@ int _mi_read_key_record(MI_INFO *info, my_off_t filepos, byte *buf)
return(-1); /* Wrong data to read */
}
+
+/*
+ Update auto_increment info
- /* Update auto_increment info */
+ SYNOPSIS
+ update_auto_increment()
+ info MyISAM handler
+ record Row to update
+
+ IMPLEMENTATION
+ Only replace the auto_increment value if it is higher than the previous
+ one. For signed columns we don't update the auto increment value if it's
+ less than zero.
+*/
void update_auto_increment(MI_INFO *info,const byte *record)
{
- ulonglong value;
- HA_KEYSEG *keyseg=info->s->keyinfo[info->s->base.auto_key-1].seg;
- const uchar *key=(uchar*) record+keyseg->start;
+ ulonglong value= 0; /* Store unsigned values here */
+ longlong s_value= 0; /* Store signed values here */
+ HA_KEYSEG *keyseg= info->s->keyinfo[info->s->base.auto_key-1].seg;
+ const uchar *key= (uchar*) record + keyseg->start;
switch (keyseg->type) {
case HA_KEYTYPE_INT8:
+ s_value= (longlong) *(char*)key;
+ break;
case HA_KEYTYPE_BINARY:
value=(ulonglong) *(uchar*) key;
break;
case HA_KEYTYPE_SHORT_INT:
+ s_value= (longlong) sint2korr(key);
+ break;
case HA_KEYTYPE_USHORT_INT:
value=(ulonglong) uint2korr(key);
break;
case HA_KEYTYPE_LONG_INT:
+ s_value= (longlong) sint4korr(key);
+ break;
case HA_KEYTYPE_ULONG_INT:
value=(ulonglong) uint4korr(key);
break;
case HA_KEYTYPE_INT24:
+ s_value= (longlong) sint3korr(key);
+ break;
case HA_KEYTYPE_UINT24:
value=(ulonglong) uint3korr(key);
break;
- case HA_KEYTYPE_FLOAT: /* This shouldn't be used */
+ case HA_KEYTYPE_FLOAT: /* This shouldn't be used */
{
float f_1;
float4get(f_1,key);
- value = (ulonglong) f_1;
+ /* Ignore negative values */
+ value = (f_1 < (float) 0.0) ? 0 : (ulonglong) f_1;
break;
}
- case HA_KEYTYPE_DOUBLE: /* This shouldn't be used */
+ case HA_KEYTYPE_DOUBLE: /* This shouldn't be used */
{
double f_1;
float8get(f_1,key);
- value = (ulonglong) f_1;
+ /* Ignore negative values */
+ value = (f_1 < 0.0) ? 0 : (ulonglong) f_1;
break;
}
case HA_KEYTYPE_LONGLONG:
+ s_value= sint8korr(key);
+ break;
case HA_KEYTYPE_ULONGLONG:
value= uint8korr(key);
break;
default:
- value=0; /* Error */
+ DBUG_ASSERT(0);
+ value=0; /* Error */
break;
}
- set_if_bigger(info->s->state.auto_increment,value);
+
+ /*
+ The following code works becasue if s_value < 0 then value is 0
+ and if s_value == 0 then value will contain either s_value or the
+ correct value.
+ */
+ set_if_bigger(info->s->state.auto_increment,
+ (s_value > 0) ? (ulonglong) s_value : value);
}
diff --git a/myisam/mi_open.c b/myisam/mi_open.c
index d5492ae5e35..2c4661c4d3e 100644
--- a/myisam/mi_open.c
+++ b/myisam/mi_open.c
@@ -867,6 +867,8 @@ char *mi_state_info_read(char *ptr, MI_STATE_INFO *state)
state->status = mi_uint4korr(ptr); ptr +=4;
state->update_count=mi_uint4korr(ptr); ptr +=4;
+ ptr+= state->state_diff_length;
+
for (i=0; i < keys; i++)
{
state->key_root[i]= mi_sizekorr(ptr); ptr +=8;
@@ -875,7 +877,6 @@ char *mi_state_info_read(char *ptr, MI_STATE_INFO *state)
{
state->key_del[i] = mi_sizekorr(ptr); ptr +=8;
}
- ptr+= state->state_diff_length;
state->sec_index_changed = mi_uint4korr(ptr); ptr +=4;
state->sec_index_used = mi_uint4korr(ptr); ptr +=4;
state->version = mi_uint4korr(ptr); ptr +=4;
diff --git a/mysql-test/r/auto_increment.result b/mysql-test/r/auto_increment.result
index 05317c0f845..89d07af6cf3 100644
--- a/mysql-test/r/auto_increment.result
+++ b/mysql-test/r/auto_increment.result
@@ -106,6 +106,32 @@ Table Op Msg_type Msg_text
test.t1 check warning Found row where the auto_increment column has the value 0
test.t1 check status OK
drop table t1;
+create table t1 (a int not null auto_increment primary key);
+insert into t1 values (NULL);
+insert into t1 values (-1);
+select last_insert_id();
+last_insert_id()
+1
+insert into t1 values (NULL);
+select * from t1;
+a
+-1
+1
+2
+drop table t1;
+create table t1 (a int not null auto_increment primary key) /*!41002 type=heap */;
+insert into t1 values (NULL);
+insert into t1 values (-1);
+select last_insert_id();
+last_insert_id()
+1
+insert into t1 values (NULL);
+select * from t1;
+a
+-1
+1
+2
+drop table t1;
create table t1 (i tinyint unsigned not null auto_increment primary key);
insert into t1 set i = 254;
insert into t1 set i = null;
diff --git a/mysql-test/r/bdb.result b/mysql-test/r/bdb.result
index 6021f02f2a6..b02574cf8a3 100644
--- a/mysql-test/r/bdb.result
+++ b/mysql-test/r/bdb.result
@@ -1145,3 +1145,14 @@ x
7
6
drop table t1;
+create table t1 ( c char(8) not null ) engine=bdb;
+insert into t1 values ('0'),('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9');
+insert into t1 values ('A'),('B'),('C'),('D'),('E'),('F');
+alter table t1 add b char(8) not null;
+alter table t1 add a char(8) not null;
+alter table t1 add primary key (a,b,c);
+update t1 set a=c, b=c;
+create table t2 (c char(8) not null, b char(8) not null, a char(8) not null, primary key(a,b,c)) engine=bdb;
+insert into t2 select * from t1;
+delete t1,t2 from t2,t1 where t1.a<'B' and t2.b=t1.b;
+drop table t1,t2;
diff --git a/mysql-test/r/binary.result b/mysql-test/r/binary.result
index 5da627a30b9..d4576791aed 100644
--- a/mysql-test/r/binary.result
+++ b/mysql-test/r/binary.result
@@ -66,6 +66,7 @@ concat("-",a,"-",b,"-")
alter table t1 modify b tinytext not null, drop key b, add key (b(100));
select concat("-",a,"-",b,"-") from t1 where b="hello ";
concat("-",a,"-",b,"-")
+-hello-hello-
select concat("-",a,"-",b,"-") from t1 ignore index (b) where b="hello ";
concat("-",a,"-",b,"-")
-hello-hello-
diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result
index bdac40d3378..6a704f2847d 100644
--- a/mysql-test/r/func_group.result
+++ b/mysql-test/r/func_group.result
@@ -47,7 +47,7 @@ sum(all a) count(all a) avg(all a) std(all a) variance(all a) bit_or(all a) bit_
21 6 3.5000 1.7078 2.9167 7 0 1 6 E
select grp, sum(a),count(a),avg(a),std(a),variance(a),bit_or(a),bit_and(a),min(a),max(a),min(c),max(c) from t1 group by grp;
grp sum(a) count(a) avg(a) std(a) variance(a) bit_or(a) bit_and(a) min(a) max(a) min(c) max(c)
-NULL NULL 0 NULL NULL NULL 0 0 NULL NULL
+NULL NULL 0 NULL NULL NULL 0 18446744073709551615 NULL NULL
1 1 1 1.0000 0.0000 0.0000 1 1 1 1 a a
2 5 2 2.5000 0.5000 0.2500 3 2 2 3 b c
3 15 3 5.0000 0.8165 0.6667 7 4 4 6 C E
@@ -576,8 +576,8 @@ insert into t1 values (1,null);
insert into t1 values (2,null);
select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b)
-1 0 NULL NULL NULL NULL NULL 0 0
-2 0 NULL NULL NULL NULL NULL 0 0
+1 0 NULL NULL NULL NULL NULL 18446744073709551615 0
+2 0 NULL NULL NULL NULL NULL 18446744073709551615 0
select SQL_BIG_RESULT a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b)
1 0 NULL NULL NULL NULL NULL 18446744073709551615 0
@@ -585,8 +585,8 @@ a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b)
insert into t1 values (2,1);
select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b)
-1 0 NULL NULL NULL NULL NULL 0 0
-2 1 1 1.0000 0.0000 1 1 0 1
+1 0 NULL NULL NULL NULL NULL 18446744073709551615 0
+2 1 1 1.0000 0.0000 1 1 1 1
select SQL_BIG_RESULT a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b)
1 0 NULL NULL NULL NULL NULL 18446744073709551615 0
@@ -594,8 +594,8 @@ a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b)
insert into t1 values (3,1);
select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b)
-1 0 NULL NULL NULL NULL NULL 0 0
-2 1 1 1.0000 0.0000 1 1 0 1
+1 0 NULL NULL NULL NULL NULL 18446744073709551615 0
+2 1 1 1.0000 0.0000 1 1 1 1
3 1 1 1.0000 0.0000 1 1 1 1
select SQL_BIG_RESULT a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b), bit_xor(b) from t1 group by a;
a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b) bit_xor(b)
@@ -632,3 +632,14 @@ select a from t1 having a=1;
a
1
drop table t1;
+create table t1 (col int);
+insert into t1 values (-1), (-2), (-3);
+select bit_and(col), bit_or(col) from t1;
+bit_and(col) bit_or(col)
+18446744073709551612 18446744073709551615
+select SQL_BIG_RESULT bit_and(col), bit_or(col) from t1 group by col;
+bit_and(col) bit_or(col)
+18446744073709551613 18446744073709551613
+18446744073709551614 18446744073709551614
+18446744073709551615 18446744073709551615
+drop table t1;
diff --git a/mysql-test/r/func_op.result b/mysql-test/r/func_op.result
index 25a7ac20b66..fb1e715ac3b 100644
--- a/mysql-test/r/func_op.result
+++ b/mysql-test/r/func_op.result
@@ -17,3 +17,21 @@ Note 1003 select high_priority (1 | (1 + 1)) AS `1 | (1+1)`,(5 & 3) AS `5 & 3`,b
select 1 << 32,1 << 63, 1 << 64, 4 >> 2, 4 >> 63, 1<< 63 >> 60;
1 << 32 1 << 63 1 << 64 4 >> 2 4 >> 63 1<< 63 >> 60
4294967296 9223372036854775808 0 1 0 8
+select -1 | 0, -1 ^ 0, -1 & 0;
+-1 | 0 -1 ^ 0 -1 & 0
+18446744073709551615 18446744073709551615 0
+select -1 | 1, -1 ^ 1, -1 & 1;
+-1 | 1 -1 ^ 1 -1 & 1
+18446744073709551615 18446744073709551614 1
+select 1 | -1, 1 ^ -1, 1 & -1;
+1 | -1 1 ^ -1 1 & -1
+18446744073709551615 18446744073709551614 1
+select 0 | -1, 0 ^ -1, 0 & -1;
+0 | -1 0 ^ -1 0 & -1
+18446744073709551615 18446744073709551615 0
+select -1 >> 0, -1 << 0;
+-1 >> 0 -1 << 0
+18446744073709551615 18446744073709551615
+select -1 >> 1, -1 << 1;
+-1 >> 1 -1 << 1
+9223372036854775807 18446744073709551614
diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result
index ac075e129ee..c74feccfb7f 100644
--- a/mysql-test/r/func_str.result
+++ b/mysql-test/r/func_str.result
@@ -144,12 +144,12 @@ montymontymontymontymonty * *
select reverse('abc'),reverse('abcd');
reverse('abc') reverse('abcd')
cba dcba
-select rpad('a',4,'1'),rpad('a',4,'12'),rpad('abcd',3,'12');
-rpad('a',4,'1') rpad('a',4,'12') rpad('abcd',3,'12')
-a111 a121 abc
-select lpad('a',4,'1'),lpad('a',4,'12'),lpad('abcd',3,'12');
-lpad('a',4,'1') lpad('a',4,'12') lpad('abcd',3,'12')
-111a 121a abc
+select rpad('a',4,'1'),rpad('a',4,'12'),rpad('abcd',3,'12'), rpad(11, 10 , 22), rpad("ab", 10, 22);
+rpad('a',4,'1') rpad('a',4,'12') rpad('abcd',3,'12') rpad(11, 10 , 22) rpad("ab", 10, 22)
+a111 a121 abc 1122222222 ab22222222
+select lpad('a',4,'1'),lpad('a',4,'12'),lpad('abcd',3,'12'), lpad(11, 10 , 22);
+lpad('a',4,'1') lpad('a',4,'12') lpad('abcd',3,'12') lpad(11, 10 , 22)
+111a 121a abc 2222222211
select rpad(741653838,17,'0'),lpad(741653838,17,'0');
rpad(741653838,17,'0') lpad(741653838,17,'0')
74165383800000000 00000000741653838
@@ -159,6 +159,12 @@ abcdaba abaabcd
select rpad('abcd',1,'ab'),lpad('abcd',1,'ab');
rpad('abcd',1,'ab') lpad('abcd',1,'ab')
a a
+select rpad('STRING', 20, CONCAT('p','a','d') );
+rpad('STRING', 20, CONCAT('p','a','d') )
+STRINGpadpadpadpadpa
+select lpad('STRING', 20, CONCAT('p','a','d') );
+lpad('STRING', 20, CONCAT('p','a','d') )
+padpadpadpadpaSTRING
select LEAST(NULL,'HARRY','HARRIOT',NULL,'HAROLD'),GREATEST(NULL,'HARRY','HARRIOT',NULL,'HAROLD');
LEAST(NULL,'HARRY','HARRIOT',NULL,'HAROLD') GREATEST(NULL,'HARRY','HARRIOT',NULL,'HAROLD')
HAROLD HARRY
@@ -183,6 +189,9 @@ NULL '\0\Z'
select length(quote(concat(char(0),"test")));
length(quote(concat(char(0),"test")))
8
+select hex(quote(concat(char(224),char(227),char(230),char(231),char(232),char(234),char(235))));
+hex(quote(concat(char(224),char(227),char(230),char(231),char(232),char(234),char(235))))
+27E0E3E6E7E8EAEB27
select reverse("");
reverse("")
diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result
index b3c3d8dff5c..0998f7b8bcf 100644
--- a/mysql-test/r/func_time.result
+++ b/mysql-test/r/func_time.result
@@ -95,11 +95,34 @@ week(19981231,2) week(19981231,3) week(20000101,2) week(20000101,3)
52 53 52 52
select week(20001231,2),week(20001231,3);
week(20001231,2) week(20001231,3)
-1 52
+53 52
+select week(19981231,0) as '0', week(19981231,1) as '1', week(19981231,2) as '2', week(19981231,3) as '3', week(19981231,4) as '4', week(19981231,5) as '5', week(19981231,6) as '6', week(19981231,7) as '7';
+0 1 2 3 4 5 6 7
+52 53 52 53 52 52 52 52
+select week(20000101,0) as '0', week(20000101,1) as '1', week(20000101,2) as '2', week(20000101,3) as '3', week(20000101,4) as '4', week(20000101,5) as '5', week(20000101,6) as '6', week(20000101,7) as '7';
+0 1 2 3 4 5 6 7
+0 0 52 52 0 0 52 52
+select week(20000106,0) as '0', week(20000106,1) as '1', week(20000106,2) as '2', week(20000106,3) as '3', week(20000106,4) as '4', week(20000106,5) as '5', week(20000106,6) as '6', week(20000106,7) as '7';
+0 1 2 3 4 5 6 7
+1 1 1 1 1 1 1 1
+select week(20001231,0) as '0', week(20001231,1) as '1', week(20001231,2) as '2', week(20001231,3) as '3', week(20001231,4) as '4', week(20001231,5) as '5', week(20001231,6) as '6', week(20001231,7) as '7';
+0 1 2 3 4 5 6 7
+53 52 53 52 53 52 1 52
+select week(20010101,0) as '0', week(20010101,1) as '1', week(20010101,2) as '2', week(20010101,3) as '3', week(20010101,4) as '4', week(20010101,5) as '5', week(20010101,6) as '6', week(20010101,7) as '7';
+0 1 2 3 4 5 6 7
+0 1 53 1 1 1 1 1
+select yearweek(20001231,0), yearweek(20001231,1), yearweek(20001231,2), yearweek(20001231,3), yearweek(20001231,4), yearweek(20001231,5), yearweek(20001231,6), yearweek(20001231,7);
+yearweek(20001231,0) yearweek(20001231,1) yearweek(20001231,2) yearweek(20001231,3) yearweek(20001231,4) yearweek(20001231,5) yearweek(20001231,6) yearweek(20001231,7)
+200053 200052 200053 200052 200101 200052 200101 200052
+set default_week_format = 6;
+select week(20001231), week(20001231,6);
+week(20001231) week(20001231,6)
+1 1
+set default_week_format = 0;
set default_week_format = 2;
select week(20001231),week(20001231,2),week(20001231,0);
week(20001231) week(20001231,2) week(20001231,0)
-1 1 53
+53 53 53
set default_week_format = 0;
select date_format('1998-12-31','%x-%v'),date_format('1999-01-01','%x-%v');
date_format('1998-12-31','%x-%v') date_format('1999-01-01','%x-%v')
@@ -408,6 +431,15 @@ select * from t1, t3 where t1.start between t3.ctime1 and t3.ctime2;
start ctime1 ctime2
2002-11-04 00:00:00 2002-10-29 16:51:06 2002-11-05 16:47:31
drop table t1,t2,t3;
+select @a:=FROM_UNIXTIME(1);
+@a:=FROM_UNIXTIME(1)
+1970-01-01 03:00:01
+select unix_timestamp(@a);
+unix_timestamp(@a)
+1
+select unix_timestamp('1969-12-01 19:00:01');
+unix_timestamp('1969-12-01 19:00:01')
+0
CREATE TABLE t1 (datetime datetime, timestamp timestamp, date date, time time);
INSERT INTO t1 values ("2001-01-02 03:04:05", "2002-01-02 03:04:05", "2003-01-02", "06:07:08");
SELECT * from t1;
diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result
index 853260a0164..bbe3326fd34 100644
--- a/mysql-test/r/group_by.result
+++ b/mysql-test/r/group_by.result
@@ -291,7 +291,7 @@ Warnings:
Note 1003 select high_priority big_result test.t1.spID AS `spid`,sum(test.t1.userID) AS `sum(userid)` from test.t1 group by test.t1.spID desc
explain select sql_big_result spid,sum(userid) from t1 group by spid desc order by null;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ALL NULL NULL NULL NULL 8
+1 SIMPLE t1 ALL NULL NULL NULL NULL 8 Using filesort
select sql_big_result spid,sum(userid) from t1 group by spid desc;
spid sum(userid)
7 3
@@ -600,3 +600,32 @@ count(*) category
1 3
1 4
drop table t1;
+CREATE TABLE t1 (
+userid int(10) unsigned,
+score smallint(5) unsigned,
+key (score)
+);
+INSERT INTO t1 VALUES (1,1),(2,2),(1,1),(3,3),(3,3),(3,3),(3,3),(3,3);
+SELECT userid,count(*) FROM t1 GROUP BY userid DESC;
+userid count(*)
+3 5
+2 1
+1 2
+EXPLAIN SELECT userid,count(*) FROM t1 GROUP BY userid DESC;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 8 Using temporary; Using filesort
+DROP TABLE t1;
+CREATE TABLE t1 (
+i int(11) default NULL,
+j int(11) default NULL
+);
+INSERT INTO t1 VALUES (1,2),(2,3),(4,5),(3,5),(1,5),(23,5);
+SELECT i, COUNT(DISTINCT(i)) FROM t1 GROUP BY j ORDER BY NULL;
+i COUNT(DISTINCT(i))
+1 1
+2 1
+4 4
+explain SELECT i, COUNT(DISTINCT(i)) FROM t1 GROUP BY j ORDER BY NULL;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 6 Using filesort
+DROP TABLE t1;
diff --git a/mysql-test/r/have_mest_timezone.require b/mysql-test/r/have_mest_timezone.require
deleted file mode 100644
index 2a219f39b7e..00000000000
--- a/mysql-test/r/have_mest_timezone.require
+++ /dev/null
@@ -1,2 +0,0 @@
-Variable_name Value
-timezone MEST
diff --git a/mysql-test/r/have_met_timezone.require b/mysql-test/r/have_met_timezone.require
new file mode 100644
index 00000000000..b3fde075ebd
--- /dev/null
+++ b/mysql-test/r/have_met_timezone.require
@@ -0,0 +1,2 @@
+FROM_UNIXTIME(24*3600)
+1970-01-02 01:00:00
diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result
index 58c0042e122..eb0b9af8e38 100644
--- a/mysql-test/r/innodb.result
+++ b/mysql-test/r/innodb.result
@@ -1312,17 +1312,41 @@ a b
111 100
111 100
drop table t1;
+create table t1 ( c char(8) not null ) engine=innodb;
+insert into t1 values ('0'),('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9');
+insert into t1 values ('A'),('B'),('C'),('D'),('E'),('F');
+alter table t1 add b char(8) not null;
+alter table t1 add a char(8) not null;
+alter table t1 add primary key (a,b,c);
+update t1 set a=c, b=c;
+create table t2 (c char(8) not null, b char(8) not null, a char(8) not null, primary key(a,b,c)) engine=innodb;
+insert into t2 select * from t1;
+delete t1,t2 from t2,t1 where t1.a<'B' and t2.b=t1.b;
+drop table t1,t2;
+SET AUTOCOMMIT=1;
+create table t1 (a integer auto_increment primary key) engine=innodb;
+insert into t1 (a) values (NULL),(NULL);
+truncate table t1;
+insert into t1 (a) values (NULL),(NULL);
+SELECT * from t1;
+a
+3
+4
+drop table t1;
CREATE TABLE t1 (col1 int(1))ENGINE=InnoDB;
CREATE TABLE t2 (col1 int(1),stamp TIMESTAMP,INDEX stamp_idx
(stamp))ENGINE=InnoDB;
insert into t1 values (1),(2),(3);
-insert into t2 values (1, 20020204130000),(2, 20020204130000),(4,20020204310000 );
+insert into t2 values (1, 20020204130000),(2, 20020204130000),(4,20020204310000 ),(5,20020204230000);
+Warnings:
+Warning 1264 Data truncated for column 'stamp' at row 3
SELECT col1 FROM t1 UNION SELECT col1 FROM t2 WHERE stamp <
'20020204120000' GROUP BY col1;
col1
1
2
3
+4
drop table t1,t2;
CREATE TABLE t1 (
`id` int(10) unsigned NOT NULL auto_increment,
diff --git a/mysql-test/r/insert.result b/mysql-test/r/insert.result
index 23eef0b3c59..ff5111c552e 100644
--- a/mysql-test/r/insert.result
+++ b/mysql-test/r/insert.result
@@ -73,7 +73,7 @@ drop table t1;
create table t1 (email varchar(50));
insert into t1 values ('sasha@mysql.com'),('monty@mysql.com'),('foo@hotmail.com'),('foo@aol.com'),('bar@aol.com');
create table t2(id int not null auto_increment primary key, t2 varchar(50), unique(t2));
-insert into t2 (t2) select distinct substring(email, locate('@', email)+1) from t1;
+insert delayed into t2 (t2) select distinct substring(email, locate('@', email)+1) from t1;
select * from t2;
id t2
1 mysql.com
diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result
index 76c1b06b638..c40f86827f8 100644
--- a/mysql-test/r/join_outer.result
+++ b/mysql-test/r/join_outer.result
@@ -665,3 +665,20 @@ left outer join t2 using (f2)
left outer join t3 using (f3);
ERROR 42S22: Unknown column 'test.t2.f3' in 'on clause'
drop table t1,t2,t3;
+create table t1 (a1 int, a2 int);
+create table t2 (b1 int not null, b2 int);
+create table t3 (c1 int, c2 int);
+insert into t1 values (1,2), (2,2), (3,2);
+insert into t2 values (1,3), (2,3);
+insert into t3 values (2,4), (3,4);
+select * from t1 left join t2 on b1 = a1 left join t3 on c1 = a1 and b1 is null;
+a1 a2 b1 b2 c1 c2
+1 2 1 3 NULL NULL
+2 2 2 3 NULL NULL
+3 2 NULL NULL 3 4
+explain select * from t1 left join t2 on b1 = a1 left join t3 on c1 = a1 and b1 is null;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3
+1 SIMPLE t2 ALL NULL NULL NULL NULL 2
+1 SIMPLE t3 ALL NULL NULL NULL NULL 2
+drop table t1, t2, t3;
diff --git a/mysql-test/r/limit.result b/mysql-test/r/limit.result
index 5a8edc99c12..c82105e6a49 100644
--- a/mysql-test/r/limit.result
+++ b/mysql-test/r/limit.result
@@ -36,9 +36,7 @@ a b
3 4
drop table t1;
create table t1 (i int);
-insert into t1 (i) values(1);
-insert into t1 (i) values(1);
-insert into t1 (i) values(1);
+insert into t1 (i) values(1),(1),(1);
delete from t1 limit 1;
update t1 set i=2 limit 1;
delete from t1 limit 0;
@@ -50,3 +48,22 @@ i
drop table t1;
select 0 limit 0;
0
+CREATE TABLE t1(id int auto_increment primary key, id2 int, index(id2));
+INSERT INTO t1 (id2) values (0),(0),(0);
+DELETE FROM t1 WHERE id=1;
+INSERT INTO t1 SET id2=0;
+SELECT * FROM t1;
+id id2
+4 0
+2 0
+3 0
+DELETE FROM t1 WHERE id2 = 0 ORDER BY id LIMIT 1;
+SELECT * FROM t1;
+id id2
+4 0
+3 0
+DELETE FROM t1 WHERE id2 = 0 ORDER BY id desc LIMIT 1;
+SELECT * FROM t1;
+id id2
+3 0
+DROP TABLE t1;
diff --git a/mysql-test/r/loaddata.result b/mysql-test/r/loaddata.result
index d738431e016..0547596dfbd 100644
--- a/mysql-test/r/loaddata.result
+++ b/mysql-test/r/loaddata.result
@@ -31,7 +31,7 @@ drop table t1;
create table t1 (a text, b text);
load data infile '../../std_data/loaddata2.dat' into table t1 fields terminated by ',' enclosed by '''';
Warnings:
-Warning 1260 Record count is fewer than the column count at row 3
+Warning 1260 Row 3 doesn't contain data for all columns
select concat('|',a,'|'), concat('|',b,'|') from t1;
concat('|',a,'|') concat('|',b,'|')
|Field A| |Field B|
@@ -40,3 +40,29 @@ Field 3,'Field 4|
|Field 5' ,'Field 6| NULL
|Field 6| | 'Field 7'|
drop table t1;
+create table t1 (a int, b char(10));
+load data infile '../../std_data/loaddata3.dat' into table t1 fields terminated by '' enclosed by '' ignore 1 lines;
+Warnings:
+Warning 1264 Data truncated for column 'a' at row 3
+Warning 1261 Row 3 was truncated; It contained more data than there where input columns
+Warning 1264 Data truncated for column 'a' at row 5
+Warning 1261 Row 5 was truncated; It contained more data than there where input columns
+select * from t1;
+a b
+1 row 1
+2 row 2
+0 1234567890
+3 row 3
+0 1234567890
+truncate table t1;
+load data infile '../../std_data/loaddata4.dat' into table t1 fields terminated by '' enclosed by '' lines terminated by '' ignore 1 lines;
+Warnings:
+Warning 1264 Data truncated for column 'a' at row 4
+Warning 1260 Row 4 doesn't contain data for all columns
+select * from t1;
+a b
+1 row 1
+2 row 2
+3 row 3
+0
+drop table t1;
diff --git a/mysql-test/r/lowercase_table.result b/mysql-test/r/lowercase_table.result
index 9c6b212a4b6..0ba4a4be945 100644
--- a/mysql-test/r/lowercase_table.result
+++ b/mysql-test/r/lowercase_table.result
@@ -1,6 +1,8 @@
-drop table if exists t1,t2,t3;
+drop table if exists t1,t2,t3,t4,T1;
create table T1 (id int primary key, Word varchar(40) not null, Index(Word));
+create table t4 (id int primary key, Word varchar(40) not null);
INSERT INTO T1 VALUES (1, 'a'), (2, 'b'), (3, 'c');
+INSERT INTO T4 VALUES(1,'match');
SELECT * FROM t1;
id Word
1 a
@@ -12,6 +14,9 @@ id
SELECT T2.id from t1 as T2 LIMIT 1;
id
1
+SELECT * from t1 left join t4 on (test.t1.id= TEST.t4.id) where TEST.t1.id >= test.t4.id;
+id Word id Word
+1 a 1 match
SELECT T2.id from t1 as t2 LIMIT 1;
id
1
@@ -21,7 +26,8 @@ ALTER TABLE T2 RENAME T3;
show tables like 't_';
Tables_in_test (t_)
t3
-drop table t3;
+t4
+drop table t3,t4;
create table t1 (a int);
select count(*) from T1;
count(*)
diff --git a/mysql-test/r/multi_update.result b/mysql-test/r/multi_update.result
index 38d60cd21d5..d335c9c1d10 100644
--- a/mysql-test/r/multi_update.result
+++ b/mysql-test/r/multi_update.result
@@ -341,6 +341,38 @@ select t1.a, t1.b,t2.a, t2.b from t1 left join t2 on t1.a=t2.a where t1.b=1 and
a b a b
2 2 NULL NULL
drop table t1,t2;
+create table t1 (a int not null auto_increment primary key, b int not null);
+insert into t1 (b) values (1),(2),(3),(4);
+update t1, t1 as t2 set t1.b=t2.b+1 where t1.a=t2.a;
+select * from t1;
+a b
+1 2
+2 3
+3 4
+4 5
+drop table t1;
+create table t1(id1 smallint(5), field char(5));
+create table t2(id2 smallint(5), field char(5));
+insert into t1 values (1, 'a'), (2, 'aa');
+insert into t2 values (1, 'b'), (2, 'bb');
+select * from t1;
+id1 field
+1 a
+2 aa
+select * from t2;
+id2 field
+1 b
+2 bb
+update t2 inner join t1 on t1.id1=t2.id2
+set t2.field=t1.field
+where 0=1;
+update t2, t1 set t2.field=t1.field
+where t1.id1=t2.id2 and 0=1;
+delete t1, t2 from t2 inner join t1 on t1.id1=t2.id2
+where 0=1;
+delete t1, t2 from t2,t1
+where t1.id1=t2.id2 and 0=1;
+drop table t1,t2;
create table t1 ( a int not null, b int not null) ;
alter table t1 add index i1(a);
delete from t1 where a > 2000000;
@@ -363,3 +395,4 @@ t2 rows after big delete 1900001
select 't1 rows after big delete', count(*) from t1;
t1 rows after big delete count(*)
t1 rows after big delete 1900001
+drop table t1,t2;
diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result
index b49f8012776..04effdfef7c 100644
--- a/mysql-test/r/mysqldump.result
+++ b/mysql-test/r/mysqldump.result
@@ -18,6 +18,47 @@ INSERT INTO t1 VALUES (1), (2);
</database>
</mysqldump>
DROP TABLE t1;
+CREATE TABLE t1 (a decimal(240, 20));
+INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"),
+("0987654321098765432109876543210987654321");
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (
+ a decimal(240,20) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+
+/*!40000 ALTER TABLE t1 DISABLE KEYS */;
+LOCK TABLES t1 WRITE;
+INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890.00000000000000000000"),("0987654321098765432109876543210987654321.00000000000000000000");
+UNLOCK TABLES;
+/*!40000 ALTER TABLE t1 ENABLE KEYS */;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+
+DROP TABLE t1;
+CREATE TABLE t1 (a double);
+INSERT INTO t1 VALUES (-9e999999);
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (
+ a double default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+
+/*!40000 ALTER TABLE t1 DISABLE KEYS */;
+LOCK TABLES t1 WRITE;
+INSERT INTO t1 VALUES (RES);
+UNLOCK TABLES;
+/*!40000 ALTER TABLE t1 ENABLE KEYS */;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+
+DROP TABLE t1;
CREATE TABLE t1(a int, b text, c varchar(3));
INSERT INTO t1 VALUES (1, "test", "tes"), (2, "TEST", "TES");
<?xml version="1.0"?>
@@ -64,30 +105,11 @@ INSERT INTO t1 VALUES ("1\""), ("\"2");
DROP TABLE t1;
CREATE TABLE t1 (a VARCHAR(255)) DEFAULT CHARSET koi8r;
INSERT INTO t1 VALUES (_koi8r x'C1C2C3C4C5');
--- MySQL dump 10.3
---
--- Host: localhost Database: test
--- ------------------------------------------------------
--- Server version 4.1.2-alpha-debug-log
-
-/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT, CHARACTER_SET_CLIENT=utf8 */;
-/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
-/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
-/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE=NO_AUTO_VALUE_ON_ZERO */;
-
---
--- Table structure for table `t1`
---
-
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (
a varchar(255) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=koi8r;
---
--- Dumping data for table `t1`
---
-
/*!40000 ALTER TABLE t1 DISABLE KEYS */;
LOCK TABLES t1 WRITE;
diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result
index bf658bae89e..fe2ded691d4 100644
--- a/mysql-test/r/query_cache.result
+++ b/mysql-test/r/query_cache.result
@@ -370,16 +370,23 @@ insert into mysqltest.t1 (a) values (1);
select * from mysqltest.t1 where i is null;
i a
1 1
+create table t1(a int);
+select * from t1;
+a
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
select * from mysqltest.t1;
i a
1 1
show status like "Qcache_queries_in_cache";
Variable_name Value
-Qcache_queries_in_cache 1
+Qcache_queries_in_cache 2
drop database mysqltest;
show status like "Qcache_queries_in_cache";
Variable_name Value
-Qcache_queries_in_cache 0
+Qcache_queries_in_cache 1
+drop table t1;
create table t1 (a char(1) not null collate koi8r_general_ci);
insert into t1 values(_koi8r"á");
set CHARACTER SET koi8r;
diff --git a/mysql-test/r/rpl_EE_error.result b/mysql-test/r/rpl_EE_error.result
new file mode 100644
index 00000000000..49ad4832c81
--- /dev/null
+++ b/mysql-test/r/rpl_EE_error.result
@@ -0,0 +1,16 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+create table t1 (a int) engine=myisam;
+flush tables;
+drop table t1;
+create table t1 (a int, unique(a)) engine=myisam;
+set sql_log_bin=0;
+insert into t1 values(2);
+set sql_log_bin=1;
+insert into t1 values(1),(2);
+ERROR 23000: Duplicate entry '2' for key 1
+drop table t1;
diff --git a/mysql-test/r/rpl_multi_update.result b/mysql-test/r/rpl_multi_update.result
new file mode 100644
index 00000000000..65587d25f63
--- /dev/null
+++ b/mysql-test/r/rpl_multi_update.result
@@ -0,0 +1,26 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+CREATE TABLE t1 (
+a int unsigned not null auto_increment primary key,
+b int unsigned,
+) ENGINE=MyISAM;
+CREATE TABLE t2 (
+a int unsigned not null auto_increment primary key,
+b int unsigned
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (NULL, 0);
+INSERT INTO t1 SELECT NULL, 0 FROM t1;
+INSERT INTO t2 VALUES (NULL, 0), (NULL,1);
+SELECT * FROM t1 ORDER BY a;
+a b
+1 0
+2 0
+SELECT * FROM t2 ORDER BY a;
+a b
+1 0
+2 1
+UPDATE t1, t2 SET t1.b = t2.b WHERE t1.a = t2.a;
diff --git a/mysql-test/r/rpl_rotate_logs.result b/mysql-test/r/rpl_rotate_logs.result
index 87ebf870f38..2264272051a 100644
--- a/mysql-test/r/rpl_rotate_logs.result
+++ b/mysql-test/r/rpl_rotate_logs.result
@@ -68,6 +68,9 @@ m
create temporary table temp_table (a char(80) not null);
insert into temp_table values ("testing temporary tables part 2");
create table t3 (n int);
+select count(*) from t3 where n >= 4;
+count(*)
+100
create table t4 select * from temp_table;
show binary logs;
Log_name
diff --git a/mysql-test/r/select_found.result b/mysql-test/r/select_found.result
index 42f7257dbba..e302a0cefeb 100644
--- a/mysql-test/r/select_found.result
+++ b/mysql-test/r/select_found.result
@@ -189,3 +189,22 @@ SELECT FOUND_ROWS();
FOUND_ROWS()
3
drop table t1;
+create table t1 (id int, primary key (id));
+insert into t1 values (1), (2), (3), (4), (5);
+select SQL_CALC_FOUND_ROWS * from t1 where id > 3 limit 0, 1;
+id
+4
+select FOUND_ROWS();
+FOUND_ROWS()
+2
+select SQL_CALC_FOUND_ROWS * from t1 where id > 3 AND 1=2 limit 0, 1;
+id
+select FOUND_ROWS();
+FOUND_ROWS()
+0
+select SQL_CALC_FOUND_ROWS * from t1 where id > 6 limit 0, 1;
+id
+select FOUND_ROWS();
+FOUND_ROWS()
+0
+drop table t1;
diff --git a/mysql-test/r/symlink.result b/mysql-test/r/symlink.result
index 48a44fc2b44..4ba0ca0eac4 100644
--- a/mysql-test/r/symlink.result
+++ b/mysql-test/r/symlink.result
@@ -64,3 +64,25 @@ t9 CREATE TABLE `t9` (
PRIMARY KEY (`a`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 DATA DIRECTORY='TEST_DIR/var/tmp/' INDEX DIRECTORY='TEST_DIR/var/run/'
drop database mysqltest;
+create table t1 (a int not null) type=myisam;
+Warnings:
+Warning 1286 'TYPE=database_engine' is deprecated. Use 'ENGINE=database_engine' instead.
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL default '0'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+alter table t1 add b int;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL default '0',
+ `b` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL default '0',
+ `b` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
diff --git a/mysql-test/r/timezone.result b/mysql-test/r/timezone.result
index b82b39da262..20706408075 100644
--- a/mysql-test/r/timezone.result
+++ b/mysql-test/r/timezone.result
@@ -1,4 +1,13 @@
DROP TABLE IF EXISTS t1;
+show variables like "timezone";
+Variable_name Value
+timezone MET
+select @a:=FROM_UNIXTIME(1);
+@a:=FROM_UNIXTIME(1)
+1970-01-01 01:00:01
+select unix_timestamp(@a);
+unix_timestamp(@a)
+1
CREATE TABLE t1 (ts int);
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 01:00'));
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 02:00'));
diff --git a/mysql-test/r/truncate.result b/mysql-test/r/truncate.result
index 0e256c1bf8e..d777bd184b2 100644
--- a/mysql-test/r/truncate.result
+++ b/mysql-test/r/truncate.result
@@ -23,3 +23,12 @@ n
drop table t1;
truncate non_existing_table;
ERROR 42S02: Table 'test.non_existing_table' doesn't exist
+create table t1 (a integer auto_increment primary key);
+insert into t1 (a) values (NULL),(NULL);
+truncate table t1;
+insert into t1 (a) values (NULL),(NULL);
+SELECT * from t1;
+a
+1
+2
+drop table t1;
diff --git a/mysql-test/r/type_blob.result b/mysql-test/r/type_blob.result
index a69e3308f0a..255b7f0d942 100644
--- a/mysql-test/r/type_blob.result
+++ b/mysql-test/r/type_blob.result
@@ -510,3 +510,149 @@ show full fields from t1;
Field Type Collation Null Key Default Extra Privileges Comment
load_file('../../std_data/words.dat') longblob NULL YES NULL select,insert,update,references
drop table t1;
+create table t1 (id integer primary key auto_increment, txt text not null, unique index txt_index (txt (20)));
+insert into t1 (txt) values ('Chevy'), ('Chevy ');
+select * from t1 where txt='Chevy';
+id txt
+1 Chevy
+2 Chevy
+select * from t1 where txt='Chevy ';
+id txt
+1 Chevy
+2 Chevy
+select * from t1 where txt='Chevy ' or txt='Chevy';
+id txt
+1 Chevy
+2 Chevy
+select * from t1 where txt='Chevy' or txt='Chevy ';
+id txt
+1 Chevy
+2 Chevy
+select * from t1 where id='1' or id='2';
+id txt
+1 Chevy
+2 Chevy
+insert into t1 (txt) values('Ford');
+select * from t1 where txt='Chevy' or txt='Chevy ' or txt='Ford';
+id txt
+1 Chevy
+2 Chevy
+3 Ford
+select * from t1 where txt='Chevy' or txt='Chevy ';
+id txt
+1 Chevy
+2 Chevy
+select * from t1 where txt='Chevy' or txt='Chevy ' or txt=' Chevy';
+id txt
+1 Chevy
+2 Chevy
+select * from t1 where txt in ('Chevy ','Chevy');
+id txt
+1 Chevy
+2 Chevy
+select * from t1 where txt in ('Chevy');
+id txt
+1 Chevy
+2 Chevy
+select * from t1 where txt between 'Chevy' and 'Chevy';
+id txt
+1 Chevy
+2 Chevy
+select * from t1 where txt between 'Chevy' and 'Chevy' or txt='Chevy ';
+id txt
+1 Chevy
+2 Chevy
+select * from t1 where txt between 'Chevy' and 'Chevy ';
+id txt
+1 Chevy
+2 Chevy
+select * from t1 where txt < 'Chevy ';
+id txt
+select * from t1 where txt <= 'Chevy';
+id txt
+1 Chevy
+2 Chevy
+select * from t1 where txt > 'Chevy';
+id txt
+3 Ford
+select * from t1 where txt >= 'Chevy';
+id txt
+1 Chevy
+2 Chevy
+3 Ford
+drop table t1;
+create table t1 (id integer primary key auto_increment, txt text, unique index txt_index (txt (20)));
+insert into t1 (txt) values ('Chevy'), ('Chevy '), (NULL);
+select * from t1 where txt='Chevy' or txt is NULL;
+id txt
+1 Chevy
+2 Chevy
+3 NULL
+select * from t1 where txt='Chevy ';
+id txt
+1 Chevy
+2 Chevy
+select * from t1 where txt='Chevy ' or txt='Chevy';
+id txt
+1 Chevy
+2 Chevy
+select * from t1 where txt='Chevy' or txt='Chevy ';
+id txt
+1 Chevy
+2 Chevy
+select * from t1 where id='1' or id='2';
+id txt
+1 Chevy
+2 Chevy
+insert into t1 (txt) values('Ford');
+select * from t1 where txt='Chevy' or txt='Chevy ' or txt='Ford';
+id txt
+1 Chevy
+2 Chevy
+4 Ford
+select * from t1 where txt='Chevy' or txt='Chevy ';
+id txt
+1 Chevy
+2 Chevy
+select * from t1 where txt='Chevy' or txt='Chevy ' or txt=' Chevy';
+id txt
+1 Chevy
+2 Chevy
+select * from t1 where txt in ('Chevy ','Chevy');
+id txt
+1 Chevy
+2 Chevy
+select * from t1 where txt in ('Chevy');
+id txt
+1 Chevy
+2 Chevy
+select * from t1 where txt between 'Chevy' and 'Chevy';
+id txt
+1 Chevy
+2 Chevy
+select * from t1 where txt between 'Chevy' and 'Chevy' or txt='Chevy ';
+id txt
+1 Chevy
+2 Chevy
+select * from t1 where txt between 'Chevy' and 'Chevy ';
+id txt
+1 Chevy
+2 Chevy
+select * from t1 where txt < 'Chevy ';
+id txt
+select * from t1 where txt < 'Chevy ' or txt is NULL;
+id txt
+3 NULL
+select * from t1 where txt <= 'Chevy';
+id txt
+1 Chevy
+2 Chevy
+select * from t1 where txt > 'Chevy';
+id txt
+4 Ford
+select * from t1 where txt >= 'Chevy';
+id txt
+1 Chevy
+2 Chevy
+4 Ford
+drop table t1;
diff --git a/mysql-test/r/type_datetime.result b/mysql-test/r/type_datetime.result
index 204266d6ec2..c1ee621697d 100644
--- a/mysql-test/r/type_datetime.result
+++ b/mysql-test/r/type_datetime.result
@@ -1,6 +1,12 @@
drop table if exists t1;
create table t1 (t datetime);
-insert into t1 values(101),(691231),(700101),(991231),(10000101),(99991231),(101000000),(691231000000),(700101000000),(991231235959),(10000101000000),(99991231235959);
+insert into t1 values(101),(691231),(700101),(991231),(10000101),(99991231),(101000000),(691231000000),(700101000000),(991231235959),(10000101000000),(99991231235959),(20030102030460),(20030102036301),(20030102240401),(20030132030401),(20031302030460);
+Warnings:
+Warning 1264 Data truncated for column 't' at row 13
+Warning 1264 Data truncated for column 't' at row 14
+Warning 1264 Data truncated for column 't' at row 15
+Warning 1264 Data truncated for column 't' at row 16
+Warning 1264 Data truncated for column 't' at row 17
select * from t1;
t
2000-01-01 00:00:00
@@ -15,6 +21,11 @@ t
1999-12-31 23:59:59
1000-01-01 00:00:00
9999-12-31 23:59:59
+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
delete from t1 where t > 0;
optimize table t1;
Table Op Msg_type Msg_text
@@ -22,7 +33,8 @@ test.t1 optimize status OK
check table t1;
Table Op Msg_type Msg_text
test.t1 check status OK
-insert into t1 values("000101"),("691231"),("700101"),("991231"),("00000101"),("00010101"),("99991231"),("00101000000"),("691231000000"),("700101000000"),("991231235959"),("10000101000000"),("99991231235959");
+delete from t1;
+insert into t1 values("000101"),("691231"),("700101"),("991231"),("00000101"),("00010101"),("99991231"),("00101000000"),("691231000000"),("700101000000"),("991231235959"),("10000101000000"),("99991231235959"),("20030102030460"),("20030102036301"),("20030102240401"),("20030132030401"),("20031302030460");
select * from t1;
t
2000-01-01 00:00:00
@@ -38,6 +50,11 @@ t
1999-12-31 23:59:59
1000-01-01 00:00:00
9999-12-31 23:59:59
+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
drop table t1;
CREATE TABLE t1 (a timestamp, b date, c time, d datetime);
insert into t1 (b,c,d) values(now(),curtime(),now());
diff --git a/mysql-test/r/type_decimal.result b/mysql-test/r/type_decimal.result
index da25394eb08..3d3e5082b8a 100644
--- a/mysql-test/r/type_decimal.result
+++ b/mysql-test/r/type_decimal.result
@@ -444,3 +444,11 @@ CREATE TABLE t1 (a_dec DECIMAL(-2,1));
ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '-2,1))' at line 1
CREATE TABLE t1 (a_dec DECIMAL(-1,1));
ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '-1,1))' at line 1
+create table t1(a decimal(10,4));
+insert into t1 values ("+0000100000000");
+Warnings:
+Warning 1263 Data truncated, out of range for column 'a' at row 1
+select * from t1;
+a
+9999999.9999
+drop table t1;
diff --git a/mysql-test/r/type_enum.result b/mysql-test/r/type_enum.result
index 2ab6695e5c6..db14a658bd2 100644
--- a/mysql-test/r/type_enum.result
+++ b/mysql-test/r/type_enum.result
@@ -1636,7 +1636,20 @@ t1 CREATE TABLE `t1` (
`a` enum('','a','b') NOT NULL default 'b'
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
-set names latin1;
+create table t1 (a enum ('0','1'));
+insert into t1 set a='foobar';
+Warnings:
+Warning 1264 Data truncated for column 'a' at row 1
+select * from t1;
+a
+
+update t1 set a = replace(a,'x','y');
+Warnings:
+Warning 1264 Data truncated for column 'a' at row 1
+select * from t1;
+a
+
+drop table t1;
create table t1 (a enum(0xE4, '1', '2') not null default 0xE4);
show columns from t1;
Field Type Null Key Default Extra
diff --git a/mysql-test/r/type_timestamp.result b/mysql-test/r/type_timestamp.result
index 0c75155146d..172ccc440f4 100644
--- a/mysql-test/r/type_timestamp.result
+++ b/mysql-test/r/type_timestamp.result
@@ -43,7 +43,13 @@ date_format(a,"%Y %y") year(a) year(now())
1970 70 1970 1970
drop table t1;
create table t1 (ix timestamp);
-insert into t1 values (19991101000000),(19990102030405),(19990630232922),(19990601000000),(19990930232922),(19990531232922),(19990501000000),(19991101000000),(19990501000000);
+insert into t1 values (19991101000000),(19990102030405),(19990630232922),(19990601000000),(19990930232922),(19990531232922),(19990501000000),(19991101000000),(19990501000000),(20030101010160),(20030101016001),(20030101240101),(20030132010101),(20031301010101);
+Warnings:
+Warning 1264 Data truncated for column 'ix' at row 10
+Warning 1264 Data truncated for column 'ix' at row 11
+Warning 1264 Data truncated for column 'ix' at row 12
+Warning 1264 Data truncated for column 'ix' at row 13
+Warning 1264 Data truncated for column 'ix' at row 14
select ix+0 from t1;
ix+0
19991101000000
@@ -55,6 +61,24 @@ ix+0
19990501000000
19991101000000
19990501000000
+0
+0
+0
+0
+0
+delete from t1;
+insert into t1 values ("19991101000000"),("19990102030405"),("19990630232922"),("19990601000000"),("20030101010160"),("20030101016001"),("20030101240101"),("20030132010101"),("20031301010101");
+select ix+0 from t1;
+ix+0
+19991101000000
+19990102030405
+19990630232922
+19990601000000
+0
+0
+0
+0
+0
drop table t1;
CREATE TABLE t1 (date date, date_time datetime, time_stamp timestamp);
INSERT INTO t1 VALUES ("1998-12-31","1998-12-31 23:59:59",19981231235959);
@@ -104,3 +128,5 @@ 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
drop table t1;
+create table t1 (a timestamp default 1);
+ERROR 42000: Invalid default value for 'a'
diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result
index b3bf95bdf3d..4a514e3dd18 100644
--- a/mysql-test/r/union.result
+++ b/mysql-test/r/union.result
@@ -3,7 +3,7 @@ CREATE TABLE t1 (a int not null, b char (10) not null);
insert into t1 values(1,'a'),(2,'b'),(3,'c'),(3,'c');
CREATE TABLE t2 (a int not null, b char (10) not null);
insert into t2 values (3,'c'),(4,'d'),(5,'f'),(6,'e');
-select a,b from t1 union select a,b from t2;
+select a,b from t1 union distinct select a,b from t2;
a b
1 a
2 b
@@ -434,7 +434,15 @@ a
3
(SELECT * FROM t1) UNION all (SELECT SQL_CALC_FOUND_ROWS * FROM t2) LIMIT 1;
ERROR 42000: Wrong usage/placement of 'SQL_CALC_FOUND_ROWS'
+create temporary table t1 select a from t1 union select a from t2;
+drop temporary table t1;
+create table t1 select a from t1 union select a from t2;
+ERROR HY000: You can't specify target table 't1' for update in FROM clause
drop table t1,t2;
+select length(version()) > 1 as `*` UNION select 2;
+*
+1
+2
CREATE TABLE t1 ( id int(3) unsigned default '0') ENGINE=MyISAM;
INSERT INTO t1 (id) VALUES("1");
CREATE TABLE t2 ( id int(3) unsigned default '0', id_master int(5) default '0', text1 varchar(5) default NULL, text2 varchar(5) default NULL) ENGINE=MyISAM;
diff --git a/mysql-test/r/warnings.result b/mysql-test/r/warnings.result
index 39435d24ee1..5c7c75bac00 100644
--- a/mysql-test/r/warnings.result
+++ b/mysql-test/r/warnings.result
@@ -49,9 +49,9 @@ Warnings:
Warning 1262 Data truncated, NULL supplied to NOT NULL column 'b' at row 2
Warning 1264 Data truncated for column 'd' at row 3
Warning 1264 Data truncated for column 'c' at row 4
-Warning 1260 Record count is fewer than the column count at row 5
+Warning 1260 Row 5 doesn't contain data for all columns
Warning 1264 Data truncated for column 'b' at row 6
-Warning 1261 Record count is more than the column count at row 7
+Warning 1261 Row 7 was truncated; It contained more data than there where input columns
Warning 1263 Data truncated, out of range for column 'a' at row 8
select @@warning_count;
@@warning_count
diff --git a/mysql-test/std_data/loaddata3.dat b/mysql-test/std_data/loaddata3.dat
new file mode 100644
index 00000000000..4c82f1396c5
--- /dev/null
+++ b/mysql-test/std_data/loaddata3.dat
@@ -0,0 +1,6 @@
+number row data
+1 row 1
+2 row 2
+error 12345678901234567890123456789012345678901234567890
+3 row 3
+wrong end 12345678901234567890123456789012345678901234567890
diff --git a/mysql-test/std_data/loaddata4.dat b/mysql-test/std_data/loaddata4.dat
new file mode 100644
index 00000000000..9c0d744438c
--- /dev/null
+++ b/mysql-test/std_data/loaddata4.dat
@@ -0,0 +1 @@
+test row data 1 row 1 2 row 2 3 row 3
diff --git a/mysql-test/t/auto_increment.test b/mysql-test/t/auto_increment.test
index 6cf286f86c0..f2a769d9f06 100644
--- a/mysql-test/t/auto_increment.test
+++ b/mysql-test/t/auto_increment.test
@@ -74,6 +74,25 @@ check table t1;
drop table t1;
#
+# Test negative values (Bug #1366)
+#
+
+create table t1 (a int not null auto_increment primary key);
+insert into t1 values (NULL);
+insert into t1 values (-1);
+select last_insert_id();
+insert into t1 values (NULL);
+select * from t1;
+drop table t1;
+
+create table t1 (a int not null auto_increment primary key) /*!41002 type=heap */;
+insert into t1 values (NULL);
+insert into t1 values (-1);
+select last_insert_id();
+insert into t1 values (NULL);
+select * from t1;
+drop table t1;
+#
# last_insert_id() madness
#
create table t1 (i tinyint unsigned not null auto_increment primary key);
diff --git a/mysql-test/t/bdb.test b/mysql-test/t/bdb.test
index 44bb753d6a1..12b81f27147 100644
--- a/mysql-test/t/bdb.test
+++ b/mysql-test/t/bdb.test
@@ -789,3 +789,22 @@ select * from t1 where x <= 10 and x >= 7 order by x desc;
select * from t1 where x <= 8 and x >= 5 order by x desc;
select * from t1 where x < 8 and x > 5 order by x desc;
drop table t1;
+
+#
+# Test of multi-table-updates (bug #1980).
+#
+
+create table t1 ( c char(8) not null ) engine=bdb;
+insert into t1 values ('0'),('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9');
+insert into t1 values ('A'),('B'),('C'),('D'),('E'),('F');
+
+alter table t1 add b char(8) not null;
+alter table t1 add a char(8) not null;
+alter table t1 add primary key (a,b,c);
+update t1 set a=c, b=c;
+
+create table t2 (c char(8) not null, b char(8) not null, a char(8) not null, primary key(a,b,c)) engine=bdb;
+insert into t2 select * from t1;
+
+delete t1,t2 from t2,t1 where t1.a<'B' and t2.b=t1.b;
+drop table t1,t2;
diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test
index 17ed4c03b5a..ce89cbe1b22 100644
--- a/mysql-test/t/func_group.test
+++ b/mysql-test/t/func_group.test
@@ -370,3 +370,11 @@ insert into t1 values (1);
select max(a) as b from t1 having b=1;
select a from t1 having a=1;
drop table t1;
+#
+# Bug #1972: test for bit_and(), bit_or() and negative values
+#
+create table t1 (col int);
+insert into t1 values (-1), (-2), (-3);
+select bit_and(col), bit_or(col) from t1;
+select SQL_BIG_RESULT bit_and(col), bit_or(col) from t1 group by col;
+drop table t1;
diff --git a/mysql-test/t/func_op.test b/mysql-test/t/func_op.test
index cb6ca58f193..33a2884b424 100644
--- a/mysql-test/t/func_op.test
+++ b/mysql-test/t/func_op.test
@@ -7,3 +7,12 @@ explain extended select 1+1,1-1,1+1*2,8/5,8%5,mod(8,5),mod(8,5)|0,-(1+1)*-2;
select 1 | (1+1),5 & 3,bit_count(7) ;
explain extended select 1 | (1+1),5 & 3,bit_count(7) ;
select 1 << 32,1 << 63, 1 << 64, 4 >> 2, 4 >> 63, 1<< 63 >> 60;
+#
+# bug #1993: bit functions must be unsigned
+#
+select -1 | 0, -1 ^ 0, -1 & 0;
+select -1 | 1, -1 ^ 1, -1 & 1;
+select 1 | -1, 1 ^ -1, 1 & -1;
+select 0 | -1, 0 ^ -1, 0 & -1;
+select -1 >> 0, -1 << 0;
+select -1 >> 1, -1 << 1;
diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test
index 0003f14c9ca..ad7b9b21b51 100644
--- a/mysql-test/t/func_str.test
+++ b/mysql-test/t/func_str.test
@@ -61,11 +61,13 @@ select aes_decrypt("a","a");
select aes_decrypt(aes_encrypt("","a"),"a");
select repeat('monty',5),concat('*',space(5),'*');
select reverse('abc'),reverse('abcd');
-select rpad('a',4,'1'),rpad('a',4,'12'),rpad('abcd',3,'12');
-select lpad('a',4,'1'),lpad('a',4,'12'),lpad('abcd',3,'12');
+select rpad('a',4,'1'),rpad('a',4,'12'),rpad('abcd',3,'12'), rpad(11, 10 , 22), rpad("ab", 10, 22);
+select lpad('a',4,'1'),lpad('a',4,'12'),lpad('abcd',3,'12'), lpad(11, 10 , 22);
select rpad(741653838,17,'0'),lpad(741653838,17,'0');
select rpad('abcd',7,'ab'),lpad('abcd',7,'ab');
select rpad('abcd',1,'ab'),lpad('abcd',1,'ab');
+select rpad('STRING', 20, CONCAT('p','a','d') );
+select lpad('STRING', 20, CONCAT('p','a','d') );
select LEAST(NULL,'HARRY','HARRIOT',NULL,'HAROLD'),GREATEST(NULL,'HARRY','HARRIOT',NULL,'HAROLD');
select least(1,2,3) | greatest(16,32,8), least(5,4)*1,greatest(-1.0,1.0)*1,least(3,2,1)*1.0,greatest(1,1.1,1.0),least("10",9),greatest("A","B","0");
@@ -77,6 +79,7 @@ select quote('\'\"\\test');
select quote(concat('abc\'', '\\cba'));
select quote(1/0), quote('\0\Z');
select length(quote(concat(char(0),"test")));
+select hex(quote(concat(char(224),char(227),char(230),char(231),char(232),char(234),char(235))));
#
# Wrong usage of functions
diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test
index 6f114fe18ae..06d0ff3fa1d 100644
--- a/mysql-test/t/func_time.test
+++ b/mysql-test/t/func_time.test
@@ -42,6 +42,18 @@ select yearweek("2000-01-06",1) as '2000', yearweek("2001-01-06",1) as '2001', y
select week(19981231,2), week(19981231,3), week(20000101,2), week(20000101,3);
select week(20001231,2),week(20001231,3);
+select week(19981231,0) as '0', week(19981231,1) as '1', week(19981231,2) as '2', week(19981231,3) as '3', week(19981231,4) as '4', week(19981231,5) as '5', week(19981231,6) as '6', week(19981231,7) as '7';
+select week(20000101,0) as '0', week(20000101,1) as '1', week(20000101,2) as '2', week(20000101,3) as '3', week(20000101,4) as '4', week(20000101,5) as '5', week(20000101,6) as '6', week(20000101,7) as '7';
+select week(20000106,0) as '0', week(20000106,1) as '1', week(20000106,2) as '2', week(20000106,3) as '3', week(20000106,4) as '4', week(20000106,5) as '5', week(20000106,6) as '6', week(20000106,7) as '7';
+select week(20001231,0) as '0', week(20001231,1) as '1', week(20001231,2) as '2', week(20001231,3) as '3', week(20001231,4) as '4', week(20001231,5) as '5', week(20001231,6) as '6', week(20001231,7) as '7';
+select week(20010101,0) as '0', week(20010101,1) as '1', week(20010101,2) as '2', week(20010101,3) as '3', week(20010101,4) as '4', week(20010101,5) as '5', week(20010101,6) as '6', week(20010101,7) as '7';
+
+select yearweek(20001231,0), yearweek(20001231,1), yearweek(20001231,2), yearweek(20001231,3), yearweek(20001231,4), yearweek(20001231,5), yearweek(20001231,6), yearweek(20001231,7);
+
+set default_week_format = 6;
+select week(20001231), week(20001231,6);
+set default_week_format = 0;
+
set default_week_format = 2;
select week(20001231),week(20001231,2),week(20001231,0);
set default_week_format = 0;
@@ -194,6 +206,13 @@ select * from t1, t3 where t1.start between t3.ctime1 and t3.ctime2;
drop table t1,t2,t3;
#
+# Test unix timestamp
+#
+select @a:=FROM_UNIXTIME(1);
+select unix_timestamp(@a);
+select unix_timestamp('1969-12-01 19:00:01');
+
+#
# Test types from + INTERVAL
#
diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test
index 1e65bef19b7..d6d1922c10f 100644
--- a/mysql-test/t/group_by.test
+++ b/mysql-test/t/group_by.test
@@ -432,3 +432,27 @@ select id, sum(qty) as sqty, count(qty) as cqty from t1 group by id having sum(q
select count(*), case interval(qty,2,3,4,5,6,7,8) when -1 then NULL when 0 then "zero" when 1 then "one" when 2 then "two" end as category from t1 group by category;
select count(*), interval(qty,2,3,4,5,6,7,8) as category from t1 group by category;
drop table t1;
+#
+# Tests for bug #1355: 'Using filesort' is missing in EXPLAIN when ORDER BY
+# NULL is used.
+#
+CREATE TABLE t1 (
+ userid int(10) unsigned,
+ score smallint(5) unsigned,
+ key (score)
+);
+INSERT INTO t1 VALUES (1,1),(2,2),(1,1),(3,3),(3,3),(3,3),(3,3),(3,3);
+# Here we select unordered GROUP BY into a temporary talbe,
+# and then sort it with filesort (GROUP BY in MySQL
+# implies sorted order of results)
+SELECT userid,count(*) FROM t1 GROUP BY userid DESC;
+EXPLAIN SELECT userid,count(*) FROM t1 GROUP BY userid DESC;
+DROP TABLE t1;
+CREATE TABLE t1 (
+ i int(11) default NULL,
+ j int(11) default NULL
+);
+INSERT INTO t1 VALUES (1,2),(2,3),(4,5),(3,5),(1,5),(23,5);
+SELECT i, COUNT(DISTINCT(i)) FROM t1 GROUP BY j ORDER BY NULL;
+explain SELECT i, COUNT(DISTINCT(i)) FROM t1 GROUP BY j ORDER BY NULL;
+DROP TABLE t1;
diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test
index 6f7a0e100c3..b227614e7ae 100644
--- a/mysql-test/t/innodb.test
+++ b/mysql-test/t/innodb.test
@@ -902,12 +902,47 @@ update t1 set a=a+10+b where a=1 order by b;
select * from t1 order by a,b;
drop table t1;
+#
+# Test of multi-table-updates (bug #1980).
+#
+
+create table t1 ( c char(8) not null ) engine=innodb;
+insert into t1 values ('0'),('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9');
+insert into t1 values ('A'),('B'),('C'),('D'),('E'),('F');
+
+alter table t1 add b char(8) not null;
+alter table t1 add a char(8) not null;
+alter table t1 add primary key (a,b,c);
+update t1 set a=c, b=c;
+
+create table t2 (c char(8) not null, b char(8) not null, a char(8) not null, primary key(a,b,c)) engine=innodb;
+insert into t2 select * from t1;
+
+delete t1,t2 from t2,t1 where t1.a<'B' and t2.b=t1.b;
+drop table t1,t2;
+
+#
+# test autoincrement with TRUNCATE
+#
+
+SET AUTOCOMMIT=1;
+create table t1 (a integer auto_increment primary key) engine=innodb;
+insert into t1 (a) values (NULL),(NULL);
+truncate table t1;
+insert into t1 (a) values (NULL),(NULL);
+SELECT * from t1;
+drop table t1;
+
+#
+# Test timestamps
+#
CREATE TABLE t1 (col1 int(1))ENGINE=InnoDB;
CREATE TABLE t2 (col1 int(1),stamp TIMESTAMP,INDEX stamp_idx
(stamp))ENGINE=InnoDB;
insert into t1 values (1),(2),(3);
-insert into t2 values (1, 20020204130000),(2, 20020204130000),(4,20020204310000 );
+# Note that timestamp 3 is wrong
+insert into t2 values (1, 20020204130000),(2, 20020204130000),(4,20020204310000 ),(5,20020204230000);
SELECT col1 FROM t1 UNION SELECT col1 FROM t2 WHERE stamp <
'20020204120000' GROUP BY col1;
drop table t1,t2;
diff --git a/mysql-test/t/insert.test b/mysql-test/t/insert.test
index 62d277bfad5..73b5f453bb4 100644
--- a/mysql-test/t/insert.test
+++ b/mysql-test/t/insert.test
@@ -71,7 +71,7 @@ drop table t1;
create table t1 (email varchar(50));
insert into t1 values ('sasha@mysql.com'),('monty@mysql.com'),('foo@hotmail.com'),('foo@aol.com'),('bar@aol.com');
create table t2(id int not null auto_increment primary key, t2 varchar(50), unique(t2));
-insert into t2 (t2) select distinct substring(email, locate('@', email)+1) from t1;
+insert delayed into t2 (t2) select distinct substring(email, locate('@', email)+1) from t1;
select * from t2;
drop table t1,t2;
diff --git a/mysql-test/t/join_outer.test b/mysql-test/t/join_outer.test
index d048208a8ff..4ffe1c075b6 100644
--- a/mysql-test/t/join_outer.test
+++ b/mysql-test/t/join_outer.test
@@ -438,3 +438,16 @@ select * from t1
left outer join t2 using (f2)
left outer join t3 using (f3);
drop table t1,t2,t3;
+
+create table t1 (a1 int, a2 int);
+create table t2 (b1 int not null, b2 int);
+create table t3 (c1 int, c2 int);
+
+insert into t1 values (1,2), (2,2), (3,2);
+insert into t2 values (1,3), (2,3);
+insert into t3 values (2,4), (3,4);
+
+select * from t1 left join t2 on b1 = a1 left join t3 on c1 = a1 and b1 is null;
+explain select * from t1 left join t2 on b1 = a1 left join t3 on c1 = a1 and b1 is null;
+
+drop table t1, t2, t3;
diff --git a/mysql-test/t/limit.test b/mysql-test/t/limit.test
index 88a9831aa68..61c57c9b468 100644
--- a/mysql-test/t/limit.test
+++ b/mysql-test/t/limit.test
@@ -22,9 +22,7 @@ select * from t1;
drop table t1;
create table t1 (i int);
-insert into t1 (i) values(1);
-insert into t1 (i) values(1);
-insert into t1 (i) values(1);
+insert into t1 (i) values(1),(1),(1);
delete from t1 limit 1;
update t1 set i=2 limit 1;
delete from t1 limit 0;
@@ -32,4 +30,22 @@ update t1 set i=3 limit 0;
select * from t1;
drop table t1;
+# LIMIT 0
+
select 0 limit 0;
+
+#
+# Test with DELETE, ORDER BY and limit (bug #1024)
+#
+
+CREATE TABLE t1(id int auto_increment primary key, id2 int, index(id2));
+INSERT INTO t1 (id2) values (0),(0),(0);
+DELETE FROM t1 WHERE id=1;
+INSERT INTO t1 SET id2=0;
+SELECT * FROM t1;
+DELETE FROM t1 WHERE id2 = 0 ORDER BY id LIMIT 1;
+# should have deleted WHERE id=2
+SELECT * FROM t1;
+DELETE FROM t1 WHERE id2 = 0 ORDER BY id desc LIMIT 1;
+SELECT * FROM t1;
+DROP TABLE t1;
diff --git a/mysql-test/t/loaddata.test b/mysql-test/t/loaddata.test
index 1720ae69bbb..aa0ea0a2f55 100644
--- a/mysql-test/t/loaddata.test
+++ b/mysql-test/t/loaddata.test
@@ -20,3 +20,14 @@ create table t1 (a text, b text);
load data infile '../../std_data/loaddata2.dat' into table t1 fields terminated by ',' enclosed by '''';
select concat('|',a,'|'), concat('|',b,'|') from t1;
drop table t1;
+
+create table t1 (a int, b char(10));
+load data infile '../../std_data/loaddata3.dat' into table t1 fields terminated by '' enclosed by '' ignore 1 lines;
+select * from t1;
+truncate table t1;
+load data infile '../../std_data/loaddata4.dat' into table t1 fields terminated by '' enclosed by '' lines terminated by '' ignore 1 lines;
+
+# The empty line last comes from the end line field in the file
+select * from t1;
+drop table t1;
+
diff --git a/mysql-test/t/lowercase_table.test b/mysql-test/t/lowercase_table.test
index 28e45bde5c5..601f1734ac6 100644
--- a/mysql-test/t/lowercase_table.test
+++ b/mysql-test/t/lowercase_table.test
@@ -3,21 +3,24 @@
#
--disable_warnings
-drop table if exists t1,t2,t3;
+drop table if exists t1,t2,t3,t4,T1;
--enable_warnings
create table T1 (id int primary key, Word varchar(40) not null, Index(Word));
+create table t4 (id int primary key, Word varchar(40) not null);
INSERT INTO T1 VALUES (1, 'a'), (2, 'b'), (3, 'c');
+INSERT INTO T4 VALUES(1,'match');
SELECT * FROM t1;
SELECT T1.id from T1 LIMIT 1;
SELECT T2.id from t1 as T2 LIMIT 1;
+SELECT * from t1 left join t4 on (test.t1.id= TEST.t4.id) where TEST.t1.id >= test.t4.id;
# This gave an error in 4.0, but it's fixed in 4.1
SELECT T2.id from t1 as t2 LIMIT 1;
RENAME TABLE T1 TO T2;
ALTER TABLE T2 ADD new_col int not null;
ALTER TABLE T2 RENAME T3;
show tables like 't_';
-drop table t3;
+drop table t3,t4;
#
# Test alias
#
diff --git a/mysql-test/t/multi_update.test b/mysql-test/t/multi_update.test
index 115007d9e63..6f012801972 100644
--- a/mysql-test/t/multi_update.test
+++ b/mysql-test/t/multi_update.test
@@ -60,8 +60,8 @@ delete from t1, t2, t3 using t1,t2,t3 where t1.id1 = t2.id2 and t2.id2 = t3.id3
select count(*) from t1 where id1;
select count(*) from t2 where id2;
select count(*) from t3 where id3;
-
drop table t1,t2,t3;
+
create table t1(id1 int not null primary key, t varchar(100)) pack_keys = 1;
create table t2(id2 int not null, t varchar(100), index(id2)) pack_keys = 1;
disable_query_log;
@@ -277,6 +277,41 @@ select t1.a, t1.b,t2.a, t2.b from t1 left join t2 on t1.a=t2.a where t1.b=1 and
drop table t1,t2;
#
+# Test reuse of same table
+#
+
+create table t1 (a int not null auto_increment primary key, b int not null);
+insert into t1 (b) values (1),(2),(3),(4);
+update t1, t1 as t2 set t1.b=t2.b+1 where t1.a=t2.a;
+select * from t1;
+drop table t1;
+
+# Test multi-update and multi-delete with impossible where
+
+create table t1(id1 smallint(5), field char(5));
+create table t2(id2 smallint(5), field char(5));
+
+insert into t1 values (1, 'a'), (2, 'aa');
+insert into t2 values (1, 'b'), (2, 'bb');
+
+select * from t1;
+select * from t2;
+
+update t2 inner join t1 on t1.id1=t2.id2
+ set t2.field=t1.field
+ where 0=1;
+update t2, t1 set t2.field=t1.field
+ where t1.id1=t2.id2 and 0=1;
+
+delete t1, t2 from t2 inner join t1 on t1.id1=t2.id2
+ where 0=1;
+delete t1, t2 from t2,t1
+ where t1.id1=t2.id2 and 0=1;
+
+drop table t1,t2;
+
+
+#
# Test for bug #1820.
#
@@ -309,4 +344,4 @@ delete t1,t2 from t1,t2 where t1.b=t2.a and t1.a < 100*1000;
select 't2 rows after big delete', count(*) from t2;
select 't1 rows after big delete', count(*) from t1;
-#drop table t1,t2;
+drop table t1,t2;
diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test
index 582fae0da36..1299d73eb99 100644
--- a/mysql-test/t/mysqldump.test
+++ b/mysql-test/t/mysqldump.test
@@ -6,12 +6,34 @@ DROP TABLE IF EXISTS t1, `"t"1`;
CREATE TABLE t1(a int);
INSERT INTO t1 VALUES (1), (2);
---exec $MYSQL_DUMP --skip-all -X test t1
+--exec $MYSQL_DUMP --skip-all --skip-comments -X test t1
+DROP TABLE t1;
+
+#
+# Bug #2005
+#
+
+CREATE TABLE t1 (a decimal(240, 20));
+INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"),
+("0987654321098765432109876543210987654321");
+--exec $MYSQL_DUMP --skip-comments test t1
+DROP TABLE t1;
+
+#
+# Bug #2055
+#
+
+CREATE TABLE t1 (a double);
+INSERT INTO t1 VALUES (-9e999999);
+# The following replaces is here because some systems replaces the above
+# double with '-inf' and others with MAX_DOUBLE
+--replace_result (-1.79769313486232e+308) (RES) (NULL) (RES)
+--exec $MYSQL_DUMP --skip-comments test t1
DROP TABLE t1;
CREATE TABLE t1(a int, b text, c varchar(3));
INSERT INTO t1 VALUES (1, "test", "tes"), (2, "TEST", "TES");
---exec $MYSQL_DUMP --skip-all -X test t1
+--exec $MYSQL_DUMP --skip-all --skip-comments -X test t1
DROP TABLE t1;
#
@@ -20,7 +42,7 @@ DROP TABLE t1;
CREATE TABLE t1 (`a"b"` char(2));
INSERT INTO t1 VALUES ("1\""), ("\"2");
---exec $MYSQL_DUMP --skip-all -X test t1
+--exec $MYSQL_DUMP --skip-all --skip-comments -X test t1
DROP TABLE t1;
#
@@ -29,5 +51,5 @@ DROP TABLE t1;
CREATE TABLE t1 (a VARCHAR(255)) DEFAULT CHARSET koi8r;
INSERT INTO t1 VALUES (_koi8r x'C1C2C3C4C5');
---exec $MYSQL_DUMP test t1
+--exec $MYSQL_DUMP --skip-comments test t1
DROP TABLE t1;
diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test
index c93d616b379..d7681e9c2ec 100644
--- a/mysql-test/t/query_cache.test
+++ b/mysql-test/t/query_cache.test
@@ -254,10 +254,14 @@ select * from mysqltest.t1 where i is null;
#
# drop db
#
+create table t1(a int);
+select * from t1;
+show status like "Qcache_queries_in_cache";
select * from mysqltest.t1;
show status like "Qcache_queries_in_cache";
drop database mysqltest;
show status like "Qcache_queries_in_cache";
+drop table t1;
#
# Charset convertion (cp1251_koi8 always present)
diff --git a/mysql-test/t/rpl_EE_error.test b/mysql-test/t/rpl_EE_error.test
new file mode 100644
index 00000000000..1a1572b48b0
--- /dev/null
+++ b/mysql-test/t/rpl_EE_error.test
@@ -0,0 +1,30 @@
+# See if an EE_ error in one event of the master's binlog stops replication
+# (it should not: in this configuration the EE_ error is probably not
+# critical). Example: you do a DROP TABLE on a table which has no MYI file
+# check if START SLAVE, RESET SLAVE, CHANGE MASTER reset Last_slave_error and
+# Last_slave_errno in SHOW SLAVE STATUS (1st and 3rd commands did not: bug 986).
+
+source include/master-slave.inc;
+
+create table t1 (a int) engine=myisam;
+flush tables;
+system rm ./var/master-data/test/t1.MYI ;
+drop table t1;
+save_master_pos;
+connection slave;
+sync_with_master;
+
+# Now a real error.
+
+connection master;
+create table t1 (a int, unique(a)) engine=myisam;
+set sql_log_bin=0;
+insert into t1 values(2);
+set sql_log_bin=1;
+save_master_pos;
+--error 1062;
+insert into t1 values(1),(2);
+drop table t1;
+save_master_pos;
+connection slave;
+wait_for_slave_to_stop;
diff --git a/mysql-test/t/rpl_multi_update.test b/mysql-test/t/rpl_multi_update.test
new file mode 100644
index 00000000000..98a199ae412
--- /dev/null
+++ b/mysql-test/t/rpl_multi_update.test
@@ -0,0 +1,24 @@
+source include/master-slave.inc;
+
+CREATE TABLE t1 (
+ a int unsigned not null auto_increment primary key,
+ b int unsigned,
+) ENGINE=MyISAM;
+
+CREATE TABLE t2 (
+ a int unsigned not null auto_increment primary key,
+ b int unsigned
+) ENGINE=MyISAM;
+
+INSERT INTO t1 VALUES (NULL, 0);
+INSERT INTO t1 SELECT NULL, 0 FROM t1;
+
+INSERT INTO t2 VALUES (NULL, 0), (NULL,1);
+
+SELECT * FROM t1 ORDER BY a;
+SELECT * FROM t2 ORDER BY a;
+
+UPDATE t1, t2 SET t1.b = t2.b WHERE t1.a = t2.a;
+save_master_pos;
+connection slave;
+sync_with_master;
diff --git a/mysql-test/t/rpl_rotate_logs.test b/mysql-test/t/rpl_rotate_logs.test
index 7560d56af1c..0d447b8d1a3 100644
--- a/mysql-test/t/rpl_rotate_logs.test
+++ b/mysql-test/t/rpl_rotate_logs.test
@@ -130,6 +130,7 @@ while ($1)
dec $1;
}
enable_query_log;
+select count(*) from t3 where n >= 4;
create table t4 select * from temp_table;
show binary logs;
show master status;
diff --git a/mysql-test/t/select_found.test b/mysql-test/t/select_found.test
index f787cec6533..3cf736cafb0 100644
--- a/mysql-test/t/select_found.test
+++ b/mysql-test/t/select_found.test
@@ -95,3 +95,17 @@ SELECT FOUND_ROWS();
SELECT SQL_CALC_FOUND_ROWS * FROM t1 ORDER BY numeropost LIMIT 0;
SELECT FOUND_ROWS();
drop table t1;
+
+#
+# Test problem with impossible WHERE (Bug #1468)
+#
+
+create table t1 (id int, primary key (id));
+insert into t1 values (1), (2), (3), (4), (5);
+select SQL_CALC_FOUND_ROWS * from t1 where id > 3 limit 0, 1;
+select FOUND_ROWS();
+select SQL_CALC_FOUND_ROWS * from t1 where id > 3 AND 1=2 limit 0, 1;
+select FOUND_ROWS();
+select SQL_CALC_FOUND_ROWS * from t1 where id > 6 limit 0, 1;
+select FOUND_ROWS();
+drop table t1;
diff --git a/mysql-test/t/symlink.test b/mysql-test/t/symlink.test
index 716eed7abc0..c0a9ce1bbcf 100644
--- a/mysql-test/t/symlink.test
+++ b/mysql-test/t/symlink.test
@@ -93,3 +93,25 @@ select count(*) from mysqltest.t9;
--replace_result $MYSQL_TEST_DIR TEST_DIR
show create table mysqltest.t9;
drop database mysqltest;
+
+#
+# Test changing data dir (Bug #1662)
+#
+
+create table t1 (a int not null) type=myisam;
+disable_query_log;
+eval alter table t1 data directory="$MYSQL_TEST_DIR/var/tmp";
+enable_query_log;
+--replace_result $MYSQL_TEST_DIR TEST_DIR
+show create table t1;
+alter table t1 add b int;
+disable_query_log;
+eval alter table t1 data directory="$MYSQL_TEST_DIR/var/log";
+enable_query_log;
+--replace_result $MYSQL_TEST_DIR TEST_DIR
+show create table t1;
+disable_query_log;
+eval alter table t1 index directory="$MYSQL_TEST_DIR/var/log";
+enable_query_log;
+show create table t1;
+drop table t1;
diff --git a/mysql-test/t/timezone.test b/mysql-test/t/timezone.test
index 14facc0374a..ab732c11a34 100644
--- a/mysql-test/t/timezone.test
+++ b/mysql-test/t/timezone.test
@@ -1,9 +1,9 @@
#
-# Test of timezone handling. This script must be run with TZ=MEST
+# Test of timezone handling. This script must be run with TZ=MET
--- require r/have_mest_timezone.require
+-- require r/have_met_timezone.require
disable_query_log;
-show variables like "timezone";
+select FROM_UNIXTIME(24*3600);
enable_query_log;
# Initialization
@@ -11,6 +11,17 @@ enable_query_log;
DROP TABLE IF EXISTS t1;
--enable_warnings
+show variables like "timezone";
+
+#
+# Test unix timestamp
+#
+select @a:=FROM_UNIXTIME(1);
+select unix_timestamp(@a);
+
+#
+# Test of some values, including some with daylight saving time
+#
CREATE TABLE t1 (ts int);
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 01:00'));
@@ -26,3 +37,4 @@ INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 04:00:01'));
SELECT ts,from_unixtime(ts) FROM t1;
DROP TABLE t1;
+
diff --git a/mysql-test/t/truncate.test b/mysql-test/t/truncate.test
index dd80baba269..434a1907e42 100644
--- a/mysql-test/t/truncate.test
+++ b/mysql-test/t/truncate.test
@@ -24,3 +24,15 @@ select * from t1;
drop table t1;
--error 1146
truncate non_existing_table;
+
+#
+# test autoincrement with TRUNCATE
+#
+
+create table t1 (a integer auto_increment primary key);
+insert into t1 (a) values (NULL),(NULL);
+truncate table t1;
+insert into t1 (a) values (NULL),(NULL);
+SELECT * from t1;
+drop table t1;
+
diff --git a/mysql-test/t/type_blob.test b/mysql-test/t/type_blob.test
index c9c3284fe0d..70fa2f9b172 100644
--- a/mysql-test/t/type_blob.test
+++ b/mysql-test/t/type_blob.test
@@ -308,3 +308,52 @@ drop table t1;
create table t1 select load_file('../../std_data/words.dat');
show full fields from t1;
drop table t1;
+
+#
+# Test blob's with end space (Bug #1651)
+#
+
+create table t1 (id integer primary key auto_increment, txt text not null, unique index txt_index (txt (20)));
+insert into t1 (txt) values ('Chevy'), ('Chevy ');
+select * from t1 where txt='Chevy';
+select * from t1 where txt='Chevy ';
+select * from t1 where txt='Chevy ' or txt='Chevy';
+select * from t1 where txt='Chevy' or txt='Chevy ';
+select * from t1 where id='1' or id='2';
+insert into t1 (txt) values('Ford');
+select * from t1 where txt='Chevy' or txt='Chevy ' or txt='Ford';
+select * from t1 where txt='Chevy' or txt='Chevy ';
+select * from t1 where txt='Chevy' or txt='Chevy ' or txt=' Chevy';
+select * from t1 where txt in ('Chevy ','Chevy');
+select * from t1 where txt in ('Chevy');
+select * from t1 where txt between 'Chevy' and 'Chevy';
+select * from t1 where txt between 'Chevy' and 'Chevy' or txt='Chevy ';
+select * from t1 where txt between 'Chevy' and 'Chevy ';
+select * from t1 where txt < 'Chevy ';
+select * from t1 where txt <= 'Chevy';
+select * from t1 where txt > 'Chevy';
+select * from t1 where txt >= 'Chevy';
+drop table t1;
+
+create table t1 (id integer primary key auto_increment, txt text, unique index txt_index (txt (20)));
+insert into t1 (txt) values ('Chevy'), ('Chevy '), (NULL);
+select * from t1 where txt='Chevy' or txt is NULL;
+select * from t1 where txt='Chevy ';
+select * from t1 where txt='Chevy ' or txt='Chevy';
+select * from t1 where txt='Chevy' or txt='Chevy ';
+select * from t1 where id='1' or id='2';
+insert into t1 (txt) values('Ford');
+select * from t1 where txt='Chevy' or txt='Chevy ' or txt='Ford';
+select * from t1 where txt='Chevy' or txt='Chevy ';
+select * from t1 where txt='Chevy' or txt='Chevy ' or txt=' Chevy';
+select * from t1 where txt in ('Chevy ','Chevy');
+select * from t1 where txt in ('Chevy');
+select * from t1 where txt between 'Chevy' and 'Chevy';
+select * from t1 where txt between 'Chevy' and 'Chevy' or txt='Chevy ';
+select * from t1 where txt between 'Chevy' and 'Chevy ';
+select * from t1 where txt < 'Chevy ';
+select * from t1 where txt < 'Chevy ' or txt is NULL;
+select * from t1 where txt <= 'Chevy';
+select * from t1 where txt > 'Chevy';
+select * from t1 where txt >= 'Chevy';
+drop table t1;
diff --git a/mysql-test/t/type_datetime.test b/mysql-test/t/type_datetime.test
index 7cedbc087e4..cec2aa3582b 100644
--- a/mysql-test/t/type_datetime.test
+++ b/mysql-test/t/type_datetime.test
@@ -7,12 +7,13 @@ drop table if exists t1;
--enable_warnings
create table t1 (t datetime);
-insert into t1 values(101),(691231),(700101),(991231),(10000101),(99991231),(101000000),(691231000000),(700101000000),(991231235959),(10000101000000),(99991231235959);
+insert into t1 values(101),(691231),(700101),(991231),(10000101),(99991231),(101000000),(691231000000),(700101000000),(991231235959),(10000101000000),(99991231235959),(20030102030460),(20030102036301),(20030102240401),(20030132030401),(20031302030460);
select * from t1;
delete from t1 where t > 0;
optimize table t1;
check table t1;
-insert into t1 values("000101"),("691231"),("700101"),("991231"),("00000101"),("00010101"),("99991231"),("00101000000"),("691231000000"),("700101000000"),("991231235959"),("10000101000000"),("99991231235959");
+delete from t1;
+insert into t1 values("000101"),("691231"),("700101"),("991231"),("00000101"),("00010101"),("99991231"),("00101000000"),("691231000000"),("700101000000"),("991231235959"),("10000101000000"),("99991231235959"),("20030102030460"),("20030102036301"),("20030102240401"),("20030132030401"),("20031302030460");
select * from t1;
drop table t1;
diff --git a/mysql-test/t/type_decimal.test b/mysql-test/t/type_decimal.test
index 36bd8eb48e4..8250f40fc99 100644
--- a/mysql-test/t/type_decimal.test
+++ b/mysql-test/t/type_decimal.test
@@ -244,3 +244,9 @@ CREATE TABLE t1 (a_dec DECIMAL(-1,0));
CREATE TABLE t1 (a_dec DECIMAL(-2,1));
--error 1064
CREATE TABLE t1 (a_dec DECIMAL(-1,1));
+
+# Zero prepend overflow bug
+create table t1(a decimal(10,4));
+insert into t1 values ("+0000100000000");
+select * from t1;
+drop table t1;
diff --git a/mysql-test/t/type_enum.test b/mysql-test/t/type_enum.test
index c53277334a6..b8f32107892 100644
--- a/mysql-test/t/type_enum.test
+++ b/mysql-test/t/type_enum.test
@@ -26,6 +26,17 @@ show create table t1;
drop table t1;
#
+# Tests of wrong enum values (bug #2023)
+#
+
+create table t1 (a enum ('0','1'));
+insert into t1 set a='foobar';
+select * from t1;
+update t1 set a = replace(a,'x','y');
+select * from t1;
+drop table t1;
+
+#
# Bug #2077
#
diff --git a/mysql-test/t/type_timestamp.test b/mysql-test/t/type_timestamp.test
index cd76dbe6ab0..fc7cd019171 100644
--- a/mysql-test/t/type_timestamp.test
+++ b/mysql-test/t/type_timestamp.test
@@ -37,8 +37,11 @@ select date_format(a,"%Y %y"),year(a),year(now()) from t1;
drop table t1;
create table t1 (ix timestamp);
-insert into t1 values (19991101000000),(19990102030405),(19990630232922),(19990601000000),(19990930232922),(19990531232922),(19990501000000),(19991101000000),(19990501000000);
-select ix+0 from t1;
+insert into t1 values (19991101000000),(19990102030405),(19990630232922),(19990601000000),(19990930232922),(19990531232922),(19990501000000),(19991101000000),(19990501000000),(20030101010160),(20030101016001),(20030101240101),(20030132010101),(20031301010101);
+select ix+0 from t1;
+delete from t1;
+insert into t1 values ("19991101000000"),("19990102030405"),("19990630232922"),("19990601000000"),("20030101010160"),("20030101016001"),("20030101240101"),("20030132010101"),("20031301010101");
+select ix+0 from t1;
drop table t1;
CREATE TABLE t1 (date date, date_time datetime, time_stamp timestamp);
@@ -72,3 +75,9 @@ set new=1;
select * from t1;
drop table t1;
+#
+# Bug #1885
+#
+
+--error 1067
+create table t1 (a timestamp default 1);
diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test
index 6138bba5a31..8ce4aa997fc 100644
--- a/mysql-test/t/union.test
+++ b/mysql-test/t/union.test
@@ -11,7 +11,7 @@ insert into t1 values(1,'a'),(2,'b'),(3,'c'),(3,'c');
CREATE TABLE t2 (a int not null, b char (10) not null);
insert into t2 values (3,'c'),(4,'d'),(5,'f'),(6,'e');
-select a,b from t1 union select a,b from t2;
+select a,b from t1 union distinct select a,b from t2;
select a,b from t1 union all select a,b from t2;
select a,b from t1 union all select a,b from t2 order by b;
select a,b from t1 union all select a,b from t2 union select 7,'g';
@@ -247,9 +247,19 @@ SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY a desc LIMIT 1;
--error 1234
(SELECT * FROM t1) UNION all (SELECT SQL_CALC_FOUND_ROWS * FROM t2) LIMIT 1;
+create temporary table t1 select a from t1 union select a from t2;
+drop temporary table t1;
+--error 1093
+create table t1 select a from t1 union select a from t2;
drop table t1,t2;
#
+# Problem with alias '*' (BUG #1249)
+#
+
+select length(version()) > 1 as `*` UNION select 2;
+
+#
# Test for another bug with UNION and LEFT JOIN
#
CREATE TABLE t1 ( id int(3) unsigned default '0') ENGINE=MyISAM;
@@ -455,4 +465,3 @@ show status like 'Slow_queries';
select count(*) from t1 where a=7 union select count(*) from t1 where b=13;
show status like 'Slow_queries';
drop table t1;
-
diff --git a/mysys/charset.c b/mysys/charset.c
index 4111dd246cb..1fe926a51d6 100644
--- a/mysys/charset.c
+++ b/mysys/charset.c
@@ -188,9 +188,11 @@ static my_bool create_fromuni(CHARSET_INFO *cs)
break;
numchars=idx[i].uidx.to-idx[i].uidx.from+1;
- idx[i].uidx.tab=(unsigned char*)my_once_alloc(numchars *
- sizeof(*idx[i].uidx.tab),
- MYF(MY_WME));
+ if (!(idx[i].uidx.tab=(uchar*) my_once_alloc(numchars *
+ sizeof(*idx[i].uidx.tab),
+ MYF(MY_WME))))
+ return TRUE;
+
bzero(idx[i].uidx.tab,numchars*sizeof(*idx[i].uidx.tab));
for (ch=1; ch < PLANE_SIZE; ch++)
@@ -206,8 +208,10 @@ static my_bool create_fromuni(CHARSET_INFO *cs)
/* Allocate and fill reverse table for each plane */
n=i;
- cs->tab_from_uni= (MY_UNI_IDX*) my_once_alloc(sizeof(MY_UNI_IDX)*(n+1),
- MYF(MY_WME));
+ if (!(cs->tab_from_uni= (MY_UNI_IDX*) my_once_alloc(sizeof(MY_UNI_IDX)*(n+1),
+ MYF(MY_WME))))
+ return TRUE;
+
for (i=0; i< n; i++)
cs->tab_from_uni[i]= idx[i].uidx;
@@ -217,46 +221,64 @@ static my_bool create_fromuni(CHARSET_INFO *cs)
}
-static void simple_cs_copy_data(CHARSET_INFO *to, CHARSET_INFO *from)
+static int simple_cs_copy_data(CHARSET_INFO *to, CHARSET_INFO *from)
{
to->number= from->number ? from->number : to->number;
if (from->csname)
- to->csname= my_once_strdup(from->csname,MYF(MY_WME));
+ if (!(to->csname= my_once_strdup(from->csname,MYF(MY_WME))))
+ goto err;
if (from->name)
- to->name= my_once_strdup(from->name,MYF(MY_WME));
+ if (!(to->name= my_once_strdup(from->name,MYF(MY_WME))))
+ goto err;
if (from->comment)
- to->comment= my_once_strdup(from->comment,MYF(MY_WME));
+ if (!(to->comment= my_once_strdup(from->comment,MYF(MY_WME))))
+ goto err;
if (from->ctype)
{
- to->ctype= (uchar*) my_once_memdup((char*) from->ctype,
- MY_CS_CTYPE_TABLE_SIZE, MYF(MY_WME));
+ if (!(to->ctype= (uchar*) my_once_memdup((char*) from->ctype,
+ MY_CS_CTYPE_TABLE_SIZE,
+ MYF(MY_WME))))
+ goto err;
init_state_maps(to);
}
if (from->to_lower)
- to->to_lower= (uchar*) my_once_memdup((char*) from->to_lower,
- MY_CS_TO_LOWER_TABLE_SIZE, MYF(MY_WME));
+ if (!(to->to_lower= (uchar*) my_once_memdup((char*) from->to_lower,
+ MY_CS_TO_LOWER_TABLE_SIZE,
+ MYF(MY_WME))))
+ goto err;
+
if (from->to_upper)
- to->to_upper= (uchar*) my_once_memdup((char*) from->to_upper,
- MY_CS_TO_UPPER_TABLE_SIZE, MYF(MY_WME));
+ if (!(to->to_upper= (uchar*) my_once_memdup((char*) from->to_upper,
+ MY_CS_TO_UPPER_TABLE_SIZE,
+ MYF(MY_WME))))
+ goto err;
if (from->sort_order)
{
- to->sort_order= (uchar*) my_once_memdup((char*) from->sort_order,
- MY_CS_SORT_ORDER_TABLE_SIZE,
- MYF(MY_WME));
+ if (!(to->sort_order= (uchar*) my_once_memdup((char*) from->sort_order,
+ MY_CS_SORT_ORDER_TABLE_SIZE,
+ MYF(MY_WME))))
+ goto err;
set_max_sort_char(to);
}
if (from->tab_to_uni)
{
uint sz= MY_CS_TO_UNI_TABLE_SIZE*sizeof(uint16);
- to->tab_to_uni= (uint16*) my_once_memdup((char*)from->tab_to_uni, sz,
- MYF(MY_WME));
- create_fromuni(to);
+ if (!(to->tab_to_uni= (uint16*) my_once_memdup((char*)from->tab_to_uni,
+ sz, MYF(MY_WME))))
+ goto err;
+ if (create_fromuni(to))
+ goto err;
}
to->mbmaxlen= 1;
+
+ return 0;
+
+err:
+ return 1;
}
@@ -292,7 +314,8 @@ static int add_collation(CHARSET_INFO *cs)
if (!(all_charsets[cs->number]->state & MY_CS_COMPILED))
{
simple_cs_init_functions(all_charsets[cs->number]);
- simple_cs_copy_data(all_charsets[cs->number],cs);
+ if (simple_cs_copy_data(all_charsets[cs->number],cs))
+ return MY_XML_ERROR;
if (simple_cs_is_full(all_charsets[cs->number]))
{
all_charsets[cs->number]->state |= MY_CS_LOADED;
@@ -313,11 +336,14 @@ static int add_collation(CHARSET_INFO *cs)
CHARSET_INFO *dst= all_charsets[cs->number];
dst->number= cs->number;
if (cs->comment)
- dst->comment= my_once_strdup(cs->comment,MYF(MY_WME));
+ if (!(dst->comment= my_once_strdup(cs->comment,MYF(MY_WME))))
+ return MY_XML_ERROR;
if (cs->csname)
- dst->csname= my_once_strdup(cs->csname,MYF(MY_WME));
+ if (!(dst->csname= my_once_strdup(cs->csname,MYF(MY_WME))))
+ return MY_XML_ERROR;
if (cs->name)
- dst->name= my_once_strdup(cs->name,MYF(MY_WME));
+ if (!(dst->name= my_once_strdup(cs->name,MYF(MY_WME))))
+ return MY_XML_ERROR;
}
cs->number= 0;
cs->primary_number= 0;
diff --git a/mysys/mf_pack.c b/mysys/mf_pack.c
index b3aa347006e..e2e811fe89a 100644
--- a/mysys/mf_pack.c
+++ b/mysys/mf_pack.c
@@ -210,13 +210,13 @@ uint cleanup_dirname(register my_string to, const char *from)
} /* cleanup_dirname */
- /*
- On system where you don't have symbolic links, the following
- code will allow you to create a file:
- directory-name.lnk that should contain the real path
- to the directory. This will be used if the directory name
- doesn't exists
- */
+/*
+ On system where you don't have symbolic links, the following
+ code will allow you to create a file:
+ directory-name.sym that should contain the real path
+ to the directory. This will be used if the directory name
+ doesn't exists
+*/
my_bool my_use_symdir=0; /* Set this if you want to use symdirs */
@@ -228,16 +228,17 @@ void symdirget(char *dir)
char *pos=strend(dir);
if (dir[0] && pos[-1] != FN_DEVCHAR && access(dir, F_OK))
{
- FILE *fp;
+ File file;
+ uint length;
char temp= *(--pos); /* May be "/" or "\" */
strmov(pos,".sym");
- fp = my_fopen(dir, O_RDONLY,MYF(0));
+ file= my_open(dir, O_RDONLY, MYF(0));
*pos++=temp; *pos=0; /* Restore old filename */
- if (fp)
+ if (file >= 0)
{
- if (fgets(buff, sizeof(buff)-1, fp))
+ if ((length= my_read(file, buff, sizeof(buff), MYF(0))) > 0)
{
- for (pos=strend(buff);
+ for (pos= buff + length ;
pos > buff && (iscntrl(pos[-1]) || isspace(pos[-1])) ;
pos --);
@@ -247,7 +248,7 @@ void symdirget(char *dir)
strmake(dir,buff, (uint) (pos-buff));
}
- my_fclose(fp,MYF(0));
+ my_close(file, MYF(0));
}
}
}
diff --git a/mysys/my_handler.c b/mysys/my_handler.c
index 2fd7f1fcdee..6ee6167d3c1 100644
--- a/mysys/my_handler.c
+++ b/mysys/my_handler.c
@@ -189,6 +189,14 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
get_key_pack_length(b_length,pack_length,b);
next_key_length=key_length-b_length-pack_length;
+ if (!(nextflag & (SEARCH_PREFIX | SEARCH_UPDATE)))
+ {
+ while (a_length && a[a_length-1] == ' ')
+ a_length--;
+ while (b_length && b[b_length-1] == ' ')
+ b_length--;
+ }
+
if (piks &&
(flag= mi_compare_text(keyseg->charset,a,a_length,b,b_length,
(my_bool) ((nextflag & SEARCH_PREFIX) &&
diff --git a/mysys/my_init.c b/mysys/my_init.c
index 4a7e9194dae..d68af1400c5 100644
--- a/mysys/my_init.c
+++ b/mysys/my_init.c
@@ -61,13 +61,22 @@ static ulong atoi_octal(const char *str)
}
- /* Init my_sys functions and my_sys variabels */
+/*
+ Init my_sys functions and my_sys variabels
+
+ SYNOPSIS
+ my_init()
-void my_init(void)
+ RETURN
+ 0 ok
+ 1 Couldn't initialize environment
+*/
+
+my_bool my_init(void)
{
my_string str;
if (my_init_done)
- return;
+ return 0;
my_init_done=1;
#if defined(THREAD) && defined(SAFE_MUTEX)
safe_mutex_global_init(); /* Must be called early */
@@ -77,7 +86,8 @@ void my_init(void)
#if defined(HAVE_PTHREAD_INIT)
pthread_init(); /* Must be called before DBUG_ENTER */
#endif
- my_thread_global_init();
+ if (my_thread_global_init())
+ return 1;
#if !defined( __WIN__) && !defined(OS2) && !defined(__NETWARE__)
sigfillset(&my_signals); /* signals blocked by mf_brkhant */
#endif
@@ -109,7 +119,7 @@ void my_init(void)
#ifdef __WIN__
win32_init_tcp_ip();
#endif
- DBUG_VOID_RETURN;
+ DBUG_RETURN(0);
}
} /* my_init */
diff --git a/mysys/my_lib.c b/mysys/my_lib.c
index 035bafd07b9..055e00d2efc 100644
--- a/mysys/my_lib.c
+++ b/mysys/my_lib.c
@@ -62,8 +62,15 @@
#define READDIR(A,B,C) (!(C=readdir(A)))
#endif
+/*
+ We are assuming that directory we are reading is either has less than
+ 100 files and so can be read in one initial chunk or has more than 1000
+ files and so big increment are suitable.
+*/
+#define ENTRIES_START_SIZE (8192/sizeof(FILEINFO))
+#define ENTRIES_INCREMENT (65536/sizeof(FILEINFO))
+#define NAMES_START_SIZE 32768
-#define STARTSIZE ONCE_ALLOC_INIT*8 /* some mallocmargin */
static int comp_names(struct fileinfo *a,struct fileinfo *b);
@@ -74,7 +81,13 @@ void my_dirend(MY_DIR *buffer)
{
DBUG_ENTER("my_dirend");
if (buffer)
+ {
+ delete_dynamic((DYNAMIC_ARRAY*)((char*)buffer +
+ ALIGN_SIZE(sizeof(MY_DIR))));
+ free_root((MEM_ROOT*)((char*)buffer + ALIGN_SIZE(sizeof(MY_DIR)) +
+ ALIGN_SIZE(sizeof(DYNAMIC_ARRAY))), MYF(0));
my_free((gptr) buffer,MYF(0));
+ }
DBUG_VOID_RETURN;
} /* my_dirend */
@@ -91,14 +104,14 @@ static int comp_names(struct fileinfo *a, struct fileinfo *b)
MY_DIR *my_dir(const char *path, myf MyFlags)
{
+ char *buffer;
+ MY_DIR *result= 0;
+ FILEINFO finfo;
+ DYNAMIC_ARRAY *dir_entries_storage;
+ MEM_ROOT *names_storage;
DIR *dirp;
struct dirent *dp;
- struct fileinfo *fnames;
- char *buffer, *obuffer, *tempptr;
- uint fcnt,i,size,firstfcnt, maxfcnt,length;
char tmp_path[FN_REFLEN+1],*tmp_file;
- my_ptrdiff_t diff;
- bool eof;
#ifdef THREAD
char dirent_tmp[sizeof(struct dirent)+_POSIX_PATH_MAX+1];
#endif
@@ -110,74 +123,72 @@ MY_DIR *my_dir(const char *path, myf MyFlags)
#endif
dirp = opendir(directory_file_name(tmp_path,(my_string) path));
- size = STARTSIZE;
#if defined(__amiga__)
if ((dirp->dd_fd) < 0) /* Directory doesn't exists */
goto error;
#endif
- if (dirp == NULL || ! (buffer = (char *) my_malloc(size, MyFlags)))
+ if (dirp == NULL ||
+ ! (buffer= my_malloc(ALIGN_SIZE(sizeof(MY_DIR)) +
+ ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)) +
+ sizeof(MEM_ROOT), MyFlags)))
+ goto error;
+
+ dir_entries_storage= (DYNAMIC_ARRAY*)(buffer + ALIGN_SIZE(sizeof(MY_DIR)));
+ names_storage= (MEM_ROOT*)(buffer + ALIGN_SIZE(sizeof(MY_DIR)) +
+ ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)));
+
+ if (my_init_dynamic_array(dir_entries_storage, sizeof(FILEINFO),
+ ENTRIES_START_SIZE, ENTRIES_INCREMENT))
+ {
+ my_free((gptr) buffer,MYF(0));
goto error;
+ }
+ init_alloc_root(names_storage, NAMES_START_SIZE, NAMES_START_SIZE);
+
+ /* MY_DIR structure is allocated and completly initialized at this point */
+ result= (MY_DIR*)buffer;
- fcnt = 0;
tmp_file=strend(tmp_path);
- firstfcnt = maxfcnt = (size - sizeof(MY_DIR)) /
- (sizeof(struct fileinfo) + FN_LEN);
- fnames= (struct fileinfo *) (buffer + sizeof(MY_DIR));
- tempptr = (char *) (fnames + maxfcnt);
#ifdef THREAD
dp= (struct dirent*) dirent_tmp;
#else
dp=0;
#endif
- eof=0;
- for (;;)
+
+ while (!(READDIR(dirp,(struct dirent*) dirent_tmp,dp)))
{
- while (fcnt < maxfcnt &&
- !(eof= READDIR(dirp,(struct dirent*) dirent_tmp,dp)))
+ if (!(finfo.name= strdup_root(names_storage, dp->d_name)))
+ goto error;
+
+ if (MyFlags & MY_WANT_STAT)
{
- bzero((gptr) (fnames+fcnt),sizeof(fnames[0])); /* for purify */
- fnames[fcnt].name = tempptr;
- tempptr = strmov(tempptr,dp->d_name) + 1;
- if (MyFlags & MY_WANT_STAT)
- {
- VOID(strmov(tmp_file,dp->d_name));
- VOID(my_stat(tmp_path, &fnames[fcnt].mystat, MyFlags));
- }
- ++fcnt;
+ if (!(finfo.mystat= (MY_STAT*)alloc_root(names_storage,
+ sizeof(MY_STAT))))
+ goto error;
+
+ bzero(finfo.mystat, sizeof(MY_STAT));
+ VOID(strmov(tmp_file,dp->d_name));
+ VOID(my_stat(tmp_path, finfo.mystat, MyFlags));
}
- if (eof)
- break;
- size += STARTSIZE; obuffer = buffer;
- if (!(buffer = (char *) my_realloc((gptr) buffer, size,
- MyFlags | MY_FREE_ON_ERROR)))
- goto error; /* No memory */
- length= (uint) (sizeof(struct fileinfo ) * firstfcnt);
- diff= PTR_BYTE_DIFF(buffer , obuffer) + (int) length;
- fnames= (struct fileinfo *) (buffer + sizeof(MY_DIR));
- tempptr= ADD_TO_PTR(tempptr,diff,char*);
- for (i = 0; i < maxfcnt; i++)
- fnames[i].name = ADD_TO_PTR(fnames[i].name,diff,char*);
-
- /* move filenames upp a bit */
- maxfcnt += firstfcnt;
- bmove_upp(tempptr,tempptr-length,
- (uint) (tempptr- (char*) (fnames+maxfcnt)));
+ else
+ finfo.mystat= NULL;
+
+ if (push_dynamic(dir_entries_storage, (gptr)&finfo))
+ goto error;
}
(void) closedir(dirp);
- {
- MY_DIR * s = (MY_DIR *) buffer;
- s->number_off_files = (uint) fcnt;
- s->dir_entry = fnames;
- }
- if (!(MyFlags & MY_DONT_SORT))
- qsort((void *) fnames, (size_s) fcnt, sizeof(struct fileinfo),
- (qsort_cmp) comp_names);
#if defined(THREAD) && !defined(HAVE_READDIR_R)
pthread_mutex_unlock(&THR_LOCK_open);
#endif
- DBUG_RETURN((MY_DIR *) buffer);
+ result->dir_entry= (FILEINFO *)dir_entries_storage->buffer;
+ result->number_off_files= dir_entries_storage->elements;
+
+ if (!(MyFlags & MY_DONT_SORT))
+ qsort((void *) result->dir_entry, result->number_off_files,
+ sizeof(FILEINFO), (qsort_cmp) comp_names);
+ DBUG_RETURN(result);
error:
#if defined(THREAD) && !defined(HAVE_READDIR_R)
@@ -186,6 +197,7 @@ MY_DIR *my_dir(const char *path, myf MyFlags)
my_errno=errno;
if (dirp)
(void) closedir(dirp);
+ my_dirend(result);
if (MyFlags & (MY_FAE | MY_WME))
my_error(EE_DIR,MYF(ME_BELL+ME_WAITTANG),path,my_errno);
DBUG_RETURN((MY_DIR *) NULL);
@@ -349,10 +361,11 @@ my_string directory_file_name (my_string dst, const char *src)
MY_DIR *my_dir(const char *path, myf MyFlags)
{
- struct fileinfo *fnames;
- char *buffer, *obuffer, *tempptr;
- int eof,i,fcnt,firstfcnt,length,maxfcnt;
- uint size;
+ char *buffer;
+ MY_DIR *result= 0;
+ FILEINFO finfo;
+ DYNAMIC_ARRAY *dir_entries_storage;
+ MEM_ROOT *names_storage;
#ifdef __BORLANDC__
struct ffblk find;
#else
@@ -360,7 +373,6 @@ MY_DIR *my_dir(const char *path, myf MyFlags)
#endif
ushort mode;
char tmp_path[FN_REFLEN],*tmp_file,attrib;
- my_ptrdiff_t diff;
#ifdef _WIN64
__int64 handle;
#else
@@ -392,85 +404,88 @@ MY_DIR *my_dir(const char *path, myf MyFlags)
goto error;
#endif
- size = STARTSIZE;
- firstfcnt = maxfcnt = (size - sizeof(MY_DIR)) /
- (sizeof(struct fileinfo) + FN_LEN);
- if ((buffer = (char *) my_malloc(size, MyFlags)) == 0)
+ if (!(buffer= my_malloc(ALIGN_SIZE(sizeof(MY_DIR)) +
+ ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)) +
+ sizeof(MEM_ROOT), MyFlags)))
goto error;
- fnames= (struct fileinfo *) (buffer + sizeof(MY_DIR));
- tempptr = (char *) (fnames + maxfcnt);
- fcnt = 0;
- for (;;)
+ dir_entries_storage= (DYNAMIC_ARRAY*)(buffer + ALIGN_SIZE(sizeof(MY_DIR)));
+ names_storage= (MEM_ROOT*)(buffer + ALIGN_SIZE(sizeof(MY_DIR)) +
+ ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)));
+
+ if (my_init_dynamic_array(dir_entries_storage, sizeof(FILEINFO),
+ ENTRIES_START_SIZE, ENTRIES_INCREMENT))
+ {
+ my_free((gptr) buffer,MYF(0));
+ goto error;
+ }
+ init_alloc_root(names_storage, NAMES_START_SIZE, NAMES_START_SIZE);
+
+ /* MY_DIR structure is allocated and completly initialized at this point */
+ result= (MY_DIR*)buffer;
+
+ do
{
- do
+#ifdef __BORLANDC__
+ if (!(finfo.name= strdup_root(names_storage, find.ff_name)))
+ goto error;
+#else
+ if (!(finfo.name= strdup_root(names_storage, find.name)))
+ goto error;
+#endif
+ if (MyFlags & MY_WANT_STAT)
{
- fnames[fcnt].name = tempptr;
+ if (!(finfo.mystat= (MY_STAT*)alloc_root(names_storage,
+ sizeof(MY_STAT))))
+ goto error;
+
+ bzero(finfo.mystat, sizeof(MY_STAT));
#ifdef __BORLANDC__
- tempptr = strmov(tempptr,find.ff_name) + 1;
- fnames[fcnt].mystat.st_size=find.ff_fsize;
- fnames[fcnt].mystat.st_uid=fnames[fcnt].mystat.st_gid=0;
+ finfo.mystat->st_size=find.ff_fsize;
mode=MY_S_IREAD; attrib=find.ff_attrib;
#else
- tempptr = strmov(tempptr,find.name) + 1;
- fnames[fcnt].mystat.st_size=find.size;
- fnames[fcnt].mystat.st_uid=fnames[fcnt].mystat.st_gid=0;
+ finfo.mystat->st_size=find.size;
mode=MY_S_IREAD; attrib=find.attrib;
#endif
if (!(attrib & _A_RDONLY))
mode|=MY_S_IWRITE;
if (attrib & _A_SUBDIR)
mode|=MY_S_IFDIR;
- fnames[fcnt].mystat.st_mode=mode;
-#ifdef __BORLANDC__
- fnames[fcnt].mystat.st_mtime=((uint32) find.ff_ftime);
-#else
- fnames[fcnt].mystat.st_mtime=((uint32) find.time_write);
-#endif
- ++fcnt;
+ finfo.mystat->st_mode=mode;
#ifdef __BORLANDC__
- } while ((eof= findnext(&find)) == 0 && fcnt < maxfcnt);
+ finfo.mystat->st_mtime=((uint32) find.ff_ftime);
#else
- } while ((eof= _findnext(handle,&find)) == 0 && fcnt < maxfcnt);
+ finfo.mystat->st_mtime=((uint32) find.time_write);
#endif
+ }
+ else
+ finfo.mystat= NULL;
- DBUG_PRINT("test",("eof: %d errno: %d",eof,errno));
- if (eof)
- break;
- size += STARTSIZE; obuffer = buffer;
- if (!(buffer = (char *) my_realloc((gptr) buffer, size,
- MyFlags | MY_FREE_ON_ERROR)))
+ if (push_dynamic(dir_entries_storage, (gptr)&finfo))
goto error;
- length= sizeof(struct fileinfo ) * firstfcnt;
- diff= PTR_BYTE_DIFF(buffer , obuffer) +length;
- fnames= (struct fileinfo *) (buffer + sizeof(MY_DIR));
- tempptr= ADD_TO_PTR(tempptr,diff,char*);
- for (i = 0; i < maxfcnt; i++)
- fnames[i].name = ADD_TO_PTR(fnames[i].name,diff,char*);
-
- /* move filenames upp a bit */
- maxfcnt += firstfcnt;
- bmove_upp(tempptr,ADD_TO_PTR(tempptr,-length,char*),
- (int) PTR_BYTE_DIFF(tempptr,fnames+maxfcnt));
- }
- {
- MY_DIR * s = (MY_DIR *) buffer;
- s->number_off_files = (uint) fcnt;
- s->dir_entry = fnames;
- }
- if (!(MyFlags & MY_DONT_SORT))
- qsort(fnames,fcnt,sizeof(struct fileinfo),(qsort_cmp) comp_names);
-#ifndef __BORLANDC__
+
+#ifdef __BORLANDC__
+ } while (findnext(&find) == 0);
+#else
+ } while (_findnext(handle,&find) == 0);
+
_findclose(handle);
#endif
- DBUG_RETURN((MY_DIR *) buffer);
+ result->dir_entry= (FILEINFO *)dir_entries_storage->buffer;
+ result->number_off_files= dir_entries_storage->elements;
+
+ if (!(MyFlags & MY_DONT_SORT))
+ qsort((void *) result->dir_entry, result->number_off_files,
+ sizeof(FILEINFO), (qsort_cmp) comp_names);
+ DBUG_RETURN(result);
error:
my_errno=errno;
#ifndef __BORLANDC__
if (handle != -1)
_findclose(handle);
#endif
+ my_dirend(result);
if (MyFlags & MY_FAE+MY_WME)
my_error(EE_DIR,MYF(ME_BELL+ME_WAITTANG),path,errno);
DBUG_RETURN((MY_DIR *) NULL);
@@ -485,14 +500,14 @@ error:
MY_DIR *my_dir(const char* path, myf MyFlags)
{
- struct fileinfo *fnames;
- char *buffer, *obuffer, *tempptr;
- int eof,i,fcnt,firstfcnt,length,maxfcnt;
- uint size;
+ char *buffer;
+ MY_DIR *result= 0;
+ FILEINFO finfo;
+ DYNAMIC_ARRAY *dir_entries_storage;
+ MEM_ROOT *names_storage;
struct find_t find;
ushort mode;
char tmp_path[FN_REFLEN],*tmp_file,attrib;
- my_ptrdiff_t diff;
DBUG_ENTER("my_dir");
DBUG_PRINT("my",("path: '%s' stat: %d MyFlags: %d",path,MyFlags));
@@ -514,63 +529,65 @@ MY_DIR *my_dir(const char* path, myf MyFlags)
if (_dos_findfirst(tmp_path,_A_NORMAL | _A_SUBDIR, &find))
goto error;
- size = STARTSIZE;
- firstfcnt = maxfcnt = (size - sizeof(MY_DIR)) /
- (sizeof(struct fileinfo) + FN_LEN);
- if ((buffer = (char *) my_malloc(size, MyFlags)) == 0)
+ if (!(buffer= my_malloc(ALIGN_SIZE(sizeof(MY_DIR)) +
+ ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)) +
+ sizeof(MEM_ROOT), MyFlags)))
goto error;
- fnames= (struct fileinfo *) (buffer + sizeof(MY_DIR));
- tempptr = (char *) (fnames + maxfcnt);
- fcnt = 0;
- for (;;)
+ dir_entries_storage= (DYNAMIC_ARRAY*)(buffer + ALIGN_SIZE(sizeof(MY_DIR)));
+ names_storage= (MEM_ROOT*)(buffer + ALIGN_SIZE(sizeof(MY_DIR)) +
+ ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)));
+
+ if (my_init_dynamic_array(dir_entries_storage, sizeof(FILEINFO),
+ ENTRIES_START_SIZE, ENTRIES_INCREMENT))
+ {
+ my_free((gptr) buffer,MYF(0));
+ goto error;
+ }
+ init_alloc_root(names_storage, NAMES_START_SIZE, NAMES_START_SIZE);
+
+ /* MY_DIR structure is allocated and completly initialized at this point */
+ result= (MY_DIR*)buffer;
+
+ do
{
- do
+ if (!(finfo.name= strdup_root(names_storage, find.name)))
+ goto error;
+
+ if (MyFlags & MY_WANT_STAT)
{
- fnames[fcnt].name = tempptr;
- tempptr = strmov(tempptr,find.name) + 1;
- fnames[fcnt].mystat.st_size=find.size;
- fnames[fcnt].mystat.st_uid=fnames[fcnt].mystat.st_gid=0;
- mode=MY_S_IREAD; attrib=find.attrib;
+ if (!(finfo.mystat= (MY_STAT*)alloc_root(names_storage,
+ sizeof(MY_STAT))))
+ goto error;
+
+ bzero(finfo.mystat, sizeof(MY_STAT));
+ finfo.mystat->st_size= find.size;
+ mode= MY_S_IREAD; attrib= find.attrib;
if (!(attrib & _A_RDONLY))
- mode|=MY_S_IWRITE;
+ mode|= MY_S_IWRITE;
if (attrib & _A_SUBDIR)
- mode|=MY_S_IFDIR;
- fnames[fcnt].mystat.st_mode=mode;
- fnames[fcnt].mystat.st_mtime=((uint32) find.wr_date << 16) +
- find.wr_time;
- ++fcnt;
- } while ((eof= _dos_findnext(&find)) == 0 && fcnt < maxfcnt);
-
- DBUG_PRINT("test",("eof: %d errno: %d",eof,errno));
- if (eof)
- break;
- size += STARTSIZE; obuffer = buffer;
- if (!(buffer = (char *) my_realloc((gptr) buffer, size,
- MyFlags | MY_FREE_ON_ERROR)))
+ mode|= MY_S_IFDIR;
+ finfo.mystat->st_mode= mode;
+ finfo.mystat->st_mtime= ((uint32) find.wr_date << 16) + find.wr_time;
+ }
+ else
+ finfo.mystat= NULL;
+
+ if (push_dynamic(dir_entries_storage, (gptr)&finfo))
goto error;
- length= sizeof(struct fileinfo ) * firstfcnt;
- diff= PTR_BYTE_DIFF(buffer , obuffer) +length;
- fnames= (struct fileinfo *) (buffer + sizeof(MY_DIR));
- tempptr= ADD_TO_PTR(tempptr,diff,char*);
- for (i = 0; i < maxfcnt; i++)
- fnames[i].name = ADD_TO_PTR(fnames[i].name,diff,char*);
-
- /* move filenames upp a bit */
- maxfcnt += firstfcnt;
- bmove_upp(tempptr,ADD_TO_PTR(tempptr,-length,char*),
- (int) PTR_BYTE_DIFF(tempptr,fnames+maxfcnt));
- }
- {
- MY_DIR * s = (MY_DIR *) buffer;
- s->number_off_files = (uint) fcnt;
- s->dir_entry = fnames;
- }
+
+ } while (_dos_findnext(&find) == 0);
+
+ result->dir_entry= (FILEINFO *)dir_entries_storage->buffer;
+ result->number_off_files= dir_entries_storage->elements;
+
if (!(MyFlags & MY_DONT_SORT))
- qsort(fnames,fcnt,sizeof(struct fileinfo),(qsort_cmp) comp_names);
- DBUG_RETURN((MY_DIR *) buffer);
+ qsort((void *) result->dir_entry, result->number_off_files,
+ sizeof(FILEINFO), (qsort_cmp) comp_names);
+ DBUG_RETURN(result);
error:
+ my_dirend(result);
if (MyFlags & MY_FAE+MY_WME)
my_error(EE_DIR,MYF(ME_BELL+ME_WAITTANG),path,errno);
DBUG_RETURN((MY_DIR *) NULL);
@@ -602,9 +619,11 @@ MY_STAT *my_stat(const char *path, MY_STAT *stat_area, myf my_flags)
if ((m_used= (stat_area == NULL)))
if (!(stat_area = (MY_STAT *) my_malloc(sizeof(MY_STAT), my_flags)))
goto error;
- if ( ! stat((my_string) path, (struct stat *) stat_area) )
+ if (! stat((my_string) path, (struct stat *) stat_area) )
DBUG_RETURN(stat_area);
- my_errno=errno;
+
+ DBUG_PRINT("error",("Got errno: %d from stat", errno));
+ my_errno= errno;
if (m_used) /* Free if new area */
my_free((gptr) stat_area,MYF(0));
diff --git a/mysys/my_symlink.c b/mysys/my_symlink.c
index b9468d42cfc..045802c5e61 100644
--- a/mysys/my_symlink.c
+++ b/mysys/my_symlink.c
@@ -72,6 +72,7 @@ int my_symlink(const char *content, const char *linkname, myf MyFlags)
#else
int result;
DBUG_ENTER("my_symlink");
+ DBUG_PRINT("enter",("content: %s linkname: %s", content, linkname));
result= 0;
if (symlink(content, linkname))
diff --git a/mysys/my_symlink2.c b/mysys/my_symlink2.c
index 68b034bec5c..913f632fbb4 100644
--- a/mysys/my_symlink2.c
+++ b/mysys/my_symlink2.c
@@ -31,9 +31,19 @@ File my_create_with_symlink(const char *linkname, const char *filename,
File file;
int tmp_errno;
/* Test if we should create a link */
- int create_link=(linkname && strcmp(linkname,filename));
+ int create_link;
DBUG_ENTER("my_create_with_symlink");
+ if (my_disable_symlinks)
+ {
+ /* Create only the file, not the link and file */
+ create_link= 0;
+ if (linkname)
+ filename= linkname;
+ }
+ else
+ create_link= (linkname && strcmp(linkname,filename));
+
if (!(MyFlags & MY_DELETE_OLD))
{
if (!access(filename,F_OK))
diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c
index 1d4219e7bfb..237eeefa325 100644
--- a/mysys/my_thr_init.c
+++ b/mysys/my_thr_init.c
@@ -44,12 +44,23 @@ pthread_mutexattr_t my_fast_mutexattr;
pthread_mutexattr_t my_errchk_mutexattr;
#endif
+/*
+ initialize thread environment
+
+ SYNOPSIS
+ my_thread_global_init()
+
+ RETURN
+ 0 ok
+ 1 error (Couldn't create THR_KEY_mysys)
+*/
+
my_bool my_thread_global_init(void)
{
- if (pthread_key_create(&THR_KEY_mysys,free))
+ if (pthread_key_create(&THR_KEY_mysys,0))
{
fprintf(stderr,"Can't initialize threads: error %d\n",errno);
- exit(1);
+ return 1;
}
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
pthread_mutexattr_init(&my_fast_mutexattr);
@@ -78,15 +89,18 @@ my_bool my_thread_global_init(void)
#ifndef HAVE_GETHOSTBYNAME_R
pthread_mutex_init(&LOCK_gethostbyname_r,MY_MUTEX_INIT_SLOW);
#endif
- return my_thread_init();
+ if (my_thread_init())
+ {
+ my_thread_global_end(); /* Clean up */
+ return 1;
+ }
+ return 0;
}
void my_thread_global_end(void)
{
-#if defined(USE_TLS)
- (void) TlsFree(THR_KEY_mysys);
-#endif
+ pthread_key_delete(THR_KEY_mysys);
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
pthread_mutexattr_destroy(&my_fast_mutexattr);
#endif
@@ -155,6 +169,9 @@ my_bool my_thread_init(void)
tmp= &THR_KEY_mysys;
#endif
tmp->id= ++thread_id;
+#if defined(__WIN__) && defined(EMBEDDED_LIBRARY)
+ tmp->thread_self= (pthread_t)getpid();
+#endif
pthread_mutex_init(&tmp->mutex,MY_MUTEX_INIT_FAST);
pthread_cond_init(&tmp->suspend, NULL);
tmp->init= 1;
diff --git a/regex/reginit.c b/regex/reginit.c
index 09ffff37ef0..74ad3dc6de4 100644
--- a/regex/reginit.c
+++ b/regex/reginit.c
@@ -49,6 +49,16 @@ void regex_init(CHARSET_INFO *cs)
for (i=0; i < CCLASS_LAST ; i++)
{
char *tmp=(char*) malloc(count[i]+1);
+ if (!tmp)
+ {
+ /*
+ This is very unlikely to happen as this function is called once
+ at program startup
+ */
+ fprintf(stderr,
+ "Fatal error: Can't allocate memory in regex_init\n");
+ exit(1);
+ }
memcpy(tmp,buff[i],count[i]*sizeof(char));
tmp[count[i]]=0;
cclasses[i].chars=tmp;
diff --git a/sql-common/client.c b/sql-common/client.c
index 73e90d08b51..14b45942e15 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -967,7 +967,8 @@ void mysql_read_default_options(struct st_mysql_options *options,
#endif
break;
case 27:
- options->max_allowed_packet= atoi(opt_arg);
+ if (opt_arg)
+ options->max_allowed_packet= atoi(opt_arg);
break;
case 28: /* protocol */
if ((options->protocol = find_type(opt_arg,
diff --git a/sql/field.cc b/sql/field.cc
index 237427a9d80..a9029b893e3 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -791,7 +791,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
if (zerofill)
{
left_wall=to-1;
- while (pos != left_wall) // Fill with zeros
+ while (pos > left_wall) // Fill with zeros
*pos--='0';
}
else
@@ -799,7 +799,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
left_wall=to+(sign_char != 0)-1;
if (!expo_sign_char) // If exponent was specified, ignore prezeros
{
- for (;pos != left_wall && pre_zeros_from !=pre_zeros_end;
+ for (;pos > left_wall && pre_zeros_from !=pre_zeros_end;
pre_zeros_from++)
*pos--= '0';
}
@@ -1016,7 +1016,7 @@ int Field_decimal::cmp(const char *a_ptr,const char *b_ptr)
return 0;
if (*a_ptr == '-')
return -1;
- else if (*b_ptr == '-')
+ if (*b_ptr == '-')
return 1;
while (a_ptr != end)
@@ -2853,34 +2853,72 @@ int Field_timestamp::store(double nr)
function.
*/
-static longlong fix_datetime(longlong nr)
+static longlong fix_datetime(longlong nr, TIME *time_res,
+ const char *field_name, bool *error)
{
- current_thd->last_cuted_field= 0;
+ long part1,part2;
+
+ *error= 0;
if (nr == LL(0) || nr >= LL(10000101000000))
- return nr; // Normal datetime >= Year 1000
+ goto ok;
if (nr < 101)
goto err;
if (nr <= (YY_PART_YEAR-1)*10000L+1231L)
- return (nr+20000000L)*1000000L; // YYMMDD, year: 2000-2069
+ {
+ nr= (nr+20000000L)*1000000L; // YYMMDD, year: 2000-2069
+ goto ok;
+ }
if (nr < (YY_PART_YEAR)*10000L+101L)
goto err;
if (nr <= 991231L)
- return (nr+19000000L)*1000000L; // YYMMDD, year: 1970-1999
+ {
+ nr= (nr+19000000L)*1000000L; // YYMMDD, year: 1970-1999
+ goto ok;
+ }
if (nr < 10000101L)
goto err;
if (nr <= 99991231L)
- return nr*1000000L;
+ {
+ nr= nr*1000000L;
+ goto ok;
+ }
if (nr < 101000000L)
goto err;
if (nr <= (YY_PART_YEAR-1)*LL(10000000000)+LL(1231235959))
- return nr+LL(20000000000000); // YYMMDDHHMMSS, 2000-2069
+ {
+ nr= nr+LL(20000000000000); // YYMMDDHHMMSS, 2000-2069
+ goto ok;
+ }
if (nr < YY_PART_YEAR*LL(10000000000)+ LL(101000000))
goto err;
if (nr <= LL(991231235959))
- return nr+LL(19000000000000); // YYMMDDHHMMSS, 1970-1999
-
+ nr= nr+LL(19000000000000); // YYMMDDHHMMSS, 1970-1999
+
+ ok:
+ part1=(long) (nr/LL(1000000));
+ part2=(long) (nr - (longlong) part1*LL(1000000));
+ time_res->year= (int) (part1/10000L); part1%=10000L;
+ time_res->month= (int) part1 / 100;
+ time_res->day= (int) part1 % 100;
+ time_res->hour= (int) (part2/10000L); part2%=10000L;
+ time_res->minute=(int) part2 / 100;
+ time_res->second=(int) part2 % 100;
+
+ if (time_res->year <= 9999 && time_res->month <= 12 &&
+ time_res->day <= 31 && time_res->hour <= 23 &&
+ time_res->minute <= 59 && time_res->second <= 59)
+ return nr;
+
err:
- current_thd->last_cuted_field= 1;
+ THD *thd= current_thd;
+ if (thd->count_cuted_fields)
+ {
+ thd->cuted_fields++;
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_DATA_TRUNCATED, ER(ER_WARN_DATA_TRUNCATED),
+ field_name, thd->row_count);
+ }
+ *error= 1;
return LL(0);
}
@@ -2888,24 +2926,17 @@ static longlong fix_datetime(longlong nr)
int Field_timestamp::store(longlong nr)
{
TIME l_time;
- time_t timestamp;
- long part1,part2;
+ time_t timestamp= 0;
+ bool error;
- if ((nr=fix_datetime(nr)))
+ if ((nr= fix_datetime(nr, &l_time, field_name, &error)))
{
long not_used;
- part1=(long) (nr/LL(1000000));
- part2=(long) (nr - (longlong) part1*LL(1000000));
- l_time.year= (int) (part1/10000L); part1%=10000L;
- l_time.month= (int) part1 / 100;
- l_time.day= (int) part1 % 100;
- l_time.hour= (int) (part2/10000L); part2%=10000L;
- l_time.minute=(int) part2 / 100;
- l_time.second=(int) part2 % 100;
- timestamp=my_gmt_sec(&l_time, &not_used);
- }
- else
- timestamp=0;
+
+ if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR-1)
+ goto err;
+ timestamp= my_gmt_sec(&l_time, &not_used);
+ }
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
{
@@ -2914,9 +2945,12 @@ int Field_timestamp::store(longlong nr)
else
#endif
longstore(ptr,(uint32) timestamp);
- if (current_thd->last_cuted_field)
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
- return 0;
+ return error;
+
+err:
+ longstore(ptr,(uint32) 0);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
+ return 1;
}
@@ -3350,7 +3384,7 @@ int Field_year::store(const char *from, uint len,CHARSET_INFO *cs)
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
return 1;
}
- else if (current_thd->count_cuted_fields && !test_if_int(from,len,end,cs))
+ if (current_thd->count_cuted_fields && !test_if_int(from,len,end,cs))
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
if (nr != 0 || len != 4)
{
@@ -3363,6 +3397,7 @@ int Field_year::store(const char *from, uint len,CHARSET_INFO *cs)
return 0;
}
+
int Field_year::store(double nr)
{
if (nr < 0.0 || nr >= 2155.0)
@@ -3825,15 +3860,10 @@ int Field_datetime::store(double nr)
int Field_datetime::store(longlong nr)
{
- int error= 0;
- if (nr < 0 || nr > LL(99991231235959))
- {
- nr=0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE);
- error= 1;
- }
- else
- nr=fix_datetime(nr);
+ TIME not_used;
+ bool error;
+
+ nr= fix_datetime(nr, &not_used, field_name, &error);
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
{
@@ -3842,11 +3872,10 @@ int Field_datetime::store(longlong nr)
else
#endif
longlongstore(ptr,nr);
- if (current_thd->last_cuted_field)
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
return error;
}
+
void Field_datetime::store_time(TIME *ltime,timestamp_type type)
{
longlong tmp;
@@ -5064,7 +5093,7 @@ int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs)
uint tmp=find_type(typelib, from, length, 0);
if (!tmp)
{
- if (length < 6) // Can't be more than 99999 enums
+ if (length < 6) // Can't be more than 99999 enums
{
/* This is for reading numbers with LOAD DATA INFILE */
char *end;
@@ -5159,7 +5188,7 @@ String *Field_enum::val_str(String *val_buffer __attribute__((unused)),
{
uint tmp=(uint) Field_enum::val_int();
if (!tmp || tmp > typelib->count)
- val_ptr->length(0);
+ val_ptr->set("", 0, field_charset);
else
val_ptr->set((const char*) typelib->type_names[tmp-1],
(uint) strlen(typelib->type_names[tmp-1]),
@@ -5224,12 +5253,13 @@ void Field_enum::sql_type(String &res) const
int Field_set::store(const char *from,uint length,CHARSET_INFO *cs)
{
- bool set_warning= 0;
+ bool got_warning= 0;
int err= 0;
char *not_used;
uint not_used2;
char buff[80];
String tmpstr(buff,sizeof(buff), &my_charset_bin);
+
/* Convert character set if nesessary */
if (use_conversion(cs, field_charset))
{
@@ -5238,7 +5268,7 @@ int Field_set::store(const char *from,uint length,CHARSET_INFO *cs)
length= tmpstr.length();
}
ulonglong tmp= find_set(typelib, from, length, &not_used, &not_used2,
- &set_warning);
+ &got_warning);
if (!tmp && length && length < 22)
{
/* This is for reading numbers with LOAD DATA INFILE */
@@ -5248,16 +5278,11 @@ int Field_set::store(const char *from,uint length,CHARSET_INFO *cs)
tmp > (ulonglong) (((longlong) 1 << typelib->count) - (longlong) 1))
{
tmp=0;
- THD *thd= current_thd;
- if (thd->count_cuted_fields)
- {
- thd->cuted_fields++;
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_WARN_DATA_TRUNCATED, ER(ER_WARN_DATA_TRUNCATED),
- field_name, 0);
- }
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
}
}
+ else if (got_warning)
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
store_type(tmp);
return err;
}
diff --git a/sql/field.h b/sql/field.h
index 508fbad41a1..e3b4bf29fb8 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -872,11 +872,14 @@ public:
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg, CHARSET_INFO *cs)
:Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
- unireg_check_arg, field_name_arg, table_arg, cs) {};
- Field_varstring(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg,
+ unireg_check_arg, field_name_arg, table_arg, cs)
+ {}
+ Field_varstring(uint32 len_arg,bool maybe_null_arg,
+ const char *field_name_arg,
struct st_table *table_arg, CHARSET_INFO *cs)
:Field_str((char*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0,0,
- NONE, field_name_arg, table_arg, cs) {};
+ NONE, field_name_arg, table_arg, cs)
+ {}
enum_field_types type() const { return FIELD_TYPE_VAR_STRING; }
enum ha_base_keytype key_type() const
@@ -924,9 +927,9 @@ public:
:Field_str((char*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0,0,
NONE, field_name_arg, table_arg, cs),
geom_flag(true), packlength(4)
- {
- flags|= BLOB_FLAG;
- }
+ {
+ flags|= BLOB_FLAG;
+ }
enum_field_types type() const { return FIELD_TYPE_BLOB;}
enum ha_base_keytype key_type() const
{ return binary() ? HA_KEYTYPE_VARBINARY : HA_KEYTYPE_VARTEXT; }
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 7fc0664445d..419eac6d1c3 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -33,11 +33,9 @@ InnoDB */
#include "mysql_priv.h"
#include "slave.h"
-#include "sql_cache.h"
#ifdef HAVE_INNOBASE_DB
#include <m_ctype.h>
-#include <assert.h>
#include <hash.h>
#include <myisampack.h>
@@ -1860,7 +1858,7 @@ ha_innobase::store_key_val_for_row(
|| mysql_type == FIELD_TYPE_BLOB
|| mysql_type == FIELD_TYPE_LONG_BLOB) {
- ut_a(key_part->key_part_flag & HA_PART_KEY);
+ ut_a(key_part->key_part_flag & HA_PART_KEY_SEG);
if (is_null) {
buff += key_part->length + 2;
@@ -3345,7 +3343,7 @@ create_index(
for (i = 0; i < n_fields; i++) {
key_part = key->key_part + i;
- /* (The flag HA_PART_KEY denotes in MySQL a column prefix
+ /* (The flag HA_PART_KEY_SEG denotes in MySQL a column prefix
field in an index: we only store a specified number of first
bytes of the column to the index field.) The flag does not
seem to be properly set by MySQL. Let us fall back on testing
diff --git a/sql/item.cc b/sql/item.cc
index 072a7e5878f..301d2990e0b 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -101,6 +101,14 @@ void Item::print_item_w_name(String *str)
}
+Item_ident::Item_ident(const char *db_name_par,const char *table_name_par,
+ const char *field_name_par)
+ :db_name(db_name_par),table_name(table_name_par),field_name(field_name_par),
+ depended_from(0)
+{
+ name = (char*) field_name_par;
+}
+
// Constructor used by Item_field & Item_ref (see Item comment)
Item_ident::Item_ident(THD *thd, Item_ident &item):
Item(thd, item),
@@ -646,10 +654,10 @@ String *Item_param::val_str(String* str)
{
switch (item_result_type) {
case INT_RESULT:
- str->set(int_value, default_charset());
+ str->set(int_value, &my_charset_bin);
return str;
case REAL_RESULT:
- str->set(real_value, 2, default_charset());
+ str->set(real_value, 2, &my_charset_bin);
return str;
default:
return (String*) &str_value;
@@ -1734,12 +1742,11 @@ Item_result item_cmp_type(Item_result a,Item_result b)
{
if (a == STRING_RESULT && b == STRING_RESULT)
return STRING_RESULT;
- else if (a == INT_RESULT && b == INT_RESULT)
+ if (a == INT_RESULT && b == INT_RESULT)
return INT_RESULT;
else if (a == ROW_RESULT || b == ROW_RESULT)
return ROW_RESULT;
- else
- return REAL_RESULT;
+ return REAL_RESULT;
}
diff --git a/sql/item.h b/sql/item.h
index a94a7a77597..c6258518213 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -239,12 +239,8 @@ public:
const char *field_name;
st_select_lex *depended_from;
Item_ident(const char *db_name_par,const char *table_name_par,
- const char *field_name_par)
- :db_name(db_name_par), table_name(table_name_par),
- field_name(field_name_par), depended_from(0)
- { name = (char*) field_name_par; }
- // Constructor used by Item_field & Item_ref (see Item comment)
- Item_ident(THD *thd, Item_ident &item);
+ const char *field_name_par);
+ Item_ident::Item_ident(THD *thd, Item_ident &item);
const char *full_name() const;
bool remove_dependence_processor(byte * arg);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 0ccc7febd0a..b9cbb38db1a 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -317,6 +317,7 @@ void Item_func::print_op(String *str)
str->append(')');
}
+
bool Item_func::eq(const Item *item, bool binary_cmp) const
{
/* Assume we don't have rtti */
@@ -372,8 +373,7 @@ String *Item_real_func::val_str(String *str)
double nr=val();
if (null_value)
return 0; /* purecov: inspected */
- else
- str->set(nr,decimals,default_charset());
+ str->set(nr,decimals, &my_charset_bin);
return str;
}
@@ -385,18 +385,17 @@ String *Item_num_func::val_str(String *str)
longlong nr=val_int();
if (null_value)
return 0; /* purecov: inspected */
- else if (!unsigned_flag)
- str->set(nr,default_charset());
+ if (!unsigned_flag)
+ str->set(nr,&my_charset_bin);
else
- str->set((ulonglong) nr,default_charset());
+ str->set((ulonglong) nr,&my_charset_bin);
}
else
{
double nr=val();
if (null_value)
return 0; /* purecov: inspected */
- else
- str->set(nr,decimals,default_charset());
+ str->set(nr,decimals,&my_charset_bin);
}
return str;
}
@@ -422,10 +421,10 @@ String *Item_int_func::val_str(String *str)
longlong nr=val_int();
if (null_value)
return 0;
- else if (!unsigned_flag)
- str->set(nr,default_charset());
+ if (!unsigned_flag)
+ str->set(nr,&my_charset_bin);
else
- str->set((ulonglong) nr,default_charset());
+ str->set((ulonglong) nr,&my_charset_bin);
return str;
}
@@ -451,18 +450,17 @@ String *Item_num_op::val_str(String *str)
longlong nr=val_int();
if (null_value)
return 0; /* purecov: inspected */
- else if (!unsigned_flag)
- str->set(nr,default_charset());
+ if (!unsigned_flag)
+ str->set(nr,&my_charset_bin);
else
- str->set((ulonglong) nr,default_charset());
+ str->set((ulonglong) nr,&my_charset_bin);
}
else
{
double nr=val();
if (null_value)
return 0; /* purecov: inspected */
- else
- str->set(nr,decimals,default_charset());
+ str->set(nr,decimals,&my_charset_bin);
}
return str;
}
@@ -1032,10 +1030,10 @@ String *Item_func_min_max::val_str(String *str)
longlong nr=val_int();
if (null_value)
return 0;
- else if (!unsigned_flag)
- str->set(nr,default_charset());
+ if (!unsigned_flag)
+ str->set(nr,&my_charset_bin);
else
- str->set((ulonglong) nr,default_charset());
+ str->set((ulonglong) nr,&my_charset_bin);
return str;
}
case REAL_RESULT:
@@ -1043,8 +1041,7 @@ String *Item_func_min_max::val_str(String *str)
double nr=val();
if (null_value)
return 0; /* purecov: inspected */
- else
- str->set(nr,decimals,default_charset());
+ str->set(nr,decimals,&my_charset_bin);
return str;
}
case STRING_RESULT:
@@ -1672,8 +1669,7 @@ String *Item_func_udf_float::val_str(String *str)
double nr=val();
if (null_value)
return 0; /* purecov: inspected */
- else
- str->set(nr,decimals,default_charset());
+ str->set(nr,decimals,&my_charset_bin);
return str;
}
@@ -1693,10 +1689,10 @@ String *Item_func_udf_int::val_str(String *str)
longlong nr=val_int();
if (null_value)
return 0;
- else if (!unsigned_flag)
- str->set(nr,default_charset());
+ if (!unsigned_flag)
+ str->set(nr,&my_charset_bin);
else
- str->set((ulonglong) nr,default_charset());
+ str->set((ulonglong) nr,&my_charset_bin);
return str;
}
diff --git a/sql/item_func.h b/sql/item_func.h
index 6b43ebaccbe..ac67b5a4065 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -659,25 +659,31 @@ public:
void fix_length_and_dec();
};
+/* Base class for all bit functions: '~', '|', '^', '&', '>>', '<<' */
-class Item_func_bit_or :public Item_int_func
+class Item_func_bit: public Item_int_func
{
public:
- Item_func_bit_or(Item *a,Item *b) :Item_int_func(a,b) {}
+ Item_func_bit(Item *a, Item *b) :Item_int_func(a, b) {}
+ Item_func_bit(Item *a) :Item_int_func(a) {}
+ void fix_length_and_dec() { unsigned_flag= 1; }
+ void print(String *str) { print_op(str); }
+};
+
+class Item_func_bit_or :public Item_func_bit
+{
+public:
+ Item_func_bit_or(Item *a, Item *b) :Item_func_bit(a, b) {}
longlong val_int();
const char *func_name() const { return "|"; }
- void fix_length_and_dec() { unsigned_flag=1; }
- void print(String *str) { print_op(str); }
};
-class Item_func_bit_and :public Item_int_func
+class Item_func_bit_and :public Item_func_bit
{
public:
- Item_func_bit_and(Item *a,Item *b) :Item_int_func(a,b) {}
+ Item_func_bit_and(Item *a, Item *b) :Item_func_bit(a, b) {}
longlong val_int();
const char *func_name() const { return "&"; }
- void fix_length_and_dec() { unsigned_flag=1; }
- void print(String *str) { print_op(str); }
};
class Item_func_bit_count :public Item_int_func
@@ -689,34 +695,32 @@ public:
void fix_length_and_dec() { max_length=2; }
};
-class Item_func_shift_left :public Item_int_func
+class Item_func_shift_left :public Item_func_bit
{
public:
- Item_func_shift_left(Item *a,Item *b) :Item_int_func(a,b) {}
+ Item_func_shift_left(Item *a, Item *b) :Item_func_bit(a, b) {}
longlong val_int();
const char *func_name() const { return "<<"; }
- void fix_length_and_dec() { unsigned_flag=1; }
- void print(String *str) { print_op(str); }
};
-class Item_func_shift_right :public Item_int_func
+class Item_func_shift_right :public Item_func_bit
{
public:
- Item_func_shift_right(Item *a,Item *b) :Item_int_func(a,b) {}
+ Item_func_shift_right(Item *a, Item *b) :Item_func_bit(a, b) {}
longlong val_int();
const char *func_name() const { return ">>"; }
- void print(String *str) { print_op(str); }
};
-class Item_func_bit_neg :public Item_int_func
+class Item_func_bit_neg :public Item_func_bit
{
public:
- Item_func_bit_neg(Item *a) :Item_int_func(a) {}
+ Item_func_bit_neg(Item *a) :Item_func_bit(a) {}
longlong val_int();
const char *func_name() const { return "~"; }
- void fix_length_and_dec() { unsigned_flag=1; }
+ void print(String *str) { Item_func::print(str); }
};
+
class Item_func_set_last_insert_id :public Item_int_func
{
public:
@@ -1021,14 +1025,12 @@ public:
};
-class Item_func_bit_xor : public Item_int_func
+class Item_func_bit_xor : public Item_func_bit
{
public:
- Item_func_bit_xor(Item *a,Item *b) :Item_int_func(a,b) {}
+ Item_func_bit_xor(Item *a, Item *b) :Item_func_bit(a, b) {}
longlong val_int();
const char *func_name() const { return "^"; }
- void fix_length_xor_dec() { unsigned_flag=1; }
- void print(String *str) { print_op(str); }
};
class Item_func_is_free_lock :public Item_int_func
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index f40d38dd4a8..3cb03d7ea49 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -1582,6 +1582,11 @@ Item_func_format::Item_func_format(Item *org,int dec) :Item_str_func(org)
}
+/*
+ TODO: This needs to be fixed for multi-byte character set where numbers
+ are stored in more than one byte
+*/
+
String *Item_func_format::val_str(String *str)
{
double nr =args[0]->val();
@@ -1590,7 +1595,8 @@ String *Item_func_format::val_str(String *str)
if ((null_value=args[0]->null_value))
return 0; /* purecov: inspected */
dec= decimals ? decimals+1 : 0;
- str->set(nr,decimals,default_charset());
+ /* Here default_charset() is right as this is not an automatic conversion */
+ str->set(nr,decimals, default_charset());
#ifdef HAVE_ISNAN
if (isnan(nr))
return str;
@@ -1839,14 +1845,11 @@ inline String* alloc_buffer(String *res,String *str,String *tmp_value,
str->length(length);
return str;
}
- else
- {
- if (tmp_value->alloc(length))
- return 0;
- (void) tmp_value->copy(*res);
- tmp_value->length(length);
- return tmp_value;
- }
+ if (tmp_value->alloc(length))
+ return 0;
+ (void) tmp_value->copy(*res);
+ tmp_value->length(length);
+ return tmp_value;
}
res->length(length);
return res;
@@ -1947,7 +1950,7 @@ String *Item_func_rpad::val_str(String *str)
int32 count= (int32) args[1]->val_int();
int32 byte_count= count * collation.collation->mbmaxlen;
String *res =args[0]->val_str(str);
- String *rpad = args[2]->val_str(str);
+ String *rpad = args[2]->val_str(&rpad_str);
if (!res || args[1]->null_value || !rpad || count < 0)
goto err;
@@ -2384,6 +2387,10 @@ String* Item_func_export_set::val_str(String* str)
null_value=1;
return 0;
}
+ /*
+ Arg count can only be 3, 4 or 5 here. This is guaranteed from the
+ grammar for EXPORT_SET()
+ */
switch(arg_count) {
case 5:
num_set_values = (uint) args[4]->val_int();
@@ -2513,7 +2520,7 @@ String *Item_func_quote::val_str(String *str)
new_length= arg_length+2; /* for beginning and ending ' signs */
for (from= (char*) arg->ptr(), end= from + arg_length; from < end; from++)
- new_length+= get_esc_bit(escmask, *from);
+ new_length+= get_esc_bit(escmask, (uchar) *from);
/*
We have to use realloc() instead of alloc() as we want to keep the
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index a7949511f02..40b00cdd488 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -474,7 +474,7 @@ public:
class Item_func_rpad :public Item_str_func
{
- String tmp_value;
+ String tmp_value, rpad_str;
public:
Item_func_rpad(Item *arg1,Item *arg2,Item *arg3)
:Item_str_func(arg1,arg2,arg3) {}
@@ -486,7 +486,7 @@ public:
class Item_func_lpad :public Item_str_func
{
- String tmp_value;
+ String tmp_value, lpad_str;
public:
Item_func_lpad(Item *arg1,Item *arg2,Item *arg3)
:Item_str_func(arg1,arg2,arg3) {}
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 7b401b50d4c..bc16fe87c2a 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -344,7 +344,7 @@ void Item_singlerow_subselect::bring_value()
exec();
}
-double Item_singlerow_subselect::val ()
+double Item_singlerow_subselect::val()
{
if (!exec() && !value->null_value)
{
@@ -358,7 +358,7 @@ double Item_singlerow_subselect::val ()
}
}
-longlong Item_singlerow_subselect::val_int ()
+longlong Item_singlerow_subselect::val_int()
{
if (!exec() && !value->null_value)
{
@@ -466,7 +466,7 @@ void Item_exists_subselect::fix_length_and_dec()
max_columns= engine->cols();
}
-double Item_exists_subselect::val ()
+double Item_exists_subselect::val()
{
if (exec())
{
@@ -476,7 +476,7 @@ double Item_exists_subselect::val ()
return (double) value;
}
-longlong Item_exists_subselect::val_int ()
+longlong Item_exists_subselect::val_int()
{
if (exec())
{
@@ -493,11 +493,11 @@ String *Item_exists_subselect::val_str(String *str)
reset();
return 0;
}
- str->set(value,default_charset());
+ str->set(value,&my_charset_bin);
return str;
}
-double Item_in_subselect::val ()
+double Item_in_subselect::val()
{
if (exec())
{
@@ -510,7 +510,7 @@ double Item_in_subselect::val ()
return (double) value;
}
-longlong Item_in_subselect::val_int ()
+longlong Item_in_subselect::val_int()
{
if (exec())
{
@@ -536,7 +536,7 @@ String *Item_in_subselect::val_str(String *str)
null_value= 1;
return 0;
}
- str->set(value,default_charset());
+ str->set(value, &my_charset_bin);
return str;
}
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 62782e1f710..a31374a3fc3 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -140,7 +140,7 @@ Item_sum_num::val_str(String *str)
double nr=val();
if (null_value)
return 0;
- str->set(nr,decimals,default_charset());
+ str->set(nr,decimals, &my_charset_bin);
return str;
}
@@ -148,10 +148,13 @@ Item_sum_num::val_str(String *str)
String *
Item_sum_int::val_str(String *str)
{
- longlong nr=val_int();
+ longlong nr= val_int();
if (null_value)
return 0;
- str->set(nr,default_charset());
+ if (unsigned_flag)
+ str->set((ulonglong) nr, &my_charset_bin);
+ else
+ str->set(nr, &my_charset_bin);
return str;
}
@@ -474,13 +477,13 @@ Item_sum_hybrid::val_str(String *str)
case STRING_RESULT:
return &value;
case REAL_RESULT:
- str->set(sum,decimals,default_charset());
+ str->set(sum,decimals, &my_charset_bin);
break;
case INT_RESULT:
if (unsigned_flag)
- str->set((ulonglong) sum_int,default_charset());
+ str->set((ulonglong) sum_int, &my_charset_bin);
else
- str->set((longlong) sum_int,default_charset());
+ str->set((longlong) sum_int, &my_charset_bin);
break;
case ROW_RESULT:
default:
@@ -776,9 +779,16 @@ void Item_sum_avg::reset_field()
void Item_sum_bit::reset_field()
{
+ reset();
+ int8store(result_field->ptr, bits);
+}
+
+void Item_sum_bit::update_field()
+{
char *res=result_field->ptr;
- ulonglong nr=(ulonglong) args[0]->val_int();
- int8store(res,nr);
+ bits= uint8korr(res);
+ add();
+ int8store(res, bits);
}
/*
@@ -916,37 +926,6 @@ Item_sum_hybrid::min_max_update_int_field()
}
-void Item_sum_or::update_field()
-{
- ulonglong nr;
- char *res=result_field->ptr;
-
- nr=uint8korr(res);
- nr|= (ulonglong) args[0]->val_int();
- int8store(res,nr);
-}
-
-void Item_sum_xor::update_field()
-{
- ulonglong nr;
- char *res=result_field->ptr;
-
- nr=uint8korr(res);
- nr^= (ulonglong) args[0]->val_int();
- int8store(res,nr);
-}
-
-void Item_sum_and::update_field()
-{
- ulonglong nr;
- char *res=result_field->ptr;
-
- nr=uint8korr(res);
- nr&= (ulonglong) args[0]->val_int();
- int8store(res,nr);
-}
-
-
Item_avg_field::Item_avg_field(Item_sum_avg *item)
{
name=item->name;
@@ -956,6 +935,7 @@ Item_avg_field::Item_avg_field(Item_sum_avg *item)
maybe_null=1;
}
+
double Item_avg_field::val()
{
double nr;
@@ -978,7 +958,7 @@ String *Item_avg_field::val_str(String *str)
double nr=Item_avg_field::val();
if (null_value)
return 0;
- str->set(nr,decimals,default_charset());
+ str->set(nr,decimals, &my_charset_bin);
return str;
}
@@ -1026,7 +1006,7 @@ String *Item_variance_field::val_str(String *str)
double nr=val();
if (null_value)
return 0;
- str->set(nr,decimals,default_charset());
+ str->set(nr,decimals, &my_charset_bin);
return str;
}
@@ -1415,8 +1395,7 @@ String *Item_sum_udf_float::val_str(String *str)
double nr=val();
if (null_value)
return 0; /* purecov: inspected */
- else
- str->set(nr,decimals,default_charset());
+ str->set(nr,decimals, &my_charset_bin);
return str;
}
@@ -1441,8 +1420,7 @@ String *Item_sum_udf_int::val_str(String *str)
longlong nr=val_int();
if (null_value)
return 0;
- else
- str->set(nr,default_charset());
+ str->set(nr, &my_charset_bin);
return str;
}
diff --git a/sql/item_sum.h b/sql/item_sum.h
index d454f06ccde..8065218df97 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -65,7 +65,18 @@ public:
inline bool reset() { clear(); return add(); };
virtual void clear()= 0;
virtual bool add()=0;
+ /*
+ Called when new group is started and results are being saved in
+ a temporary table. Similar to reset(), but must also store value in
+ result_field. Like reset() it is supposed to reset start value to
+ default.
+ */
virtual void reset_field()=0;
+ /*
+ Called for each new value in the group, when temporary table is in use.
+ Similar to add(), but uses temporary table field to obtain current value,
+ Updated value is then saved in the field.
+ */
virtual void update_field()=0;
virtual bool keep_field_type(void) const { return 0; }
virtual void fix_length_and_dec() { maybe_null=1; null_value=1; }
@@ -445,10 +456,10 @@ public:
class Item_sum_bit :public Item_sum_int
{
- protected:
+protected:
ulonglong reset_bits,bits;
- public:
+public:
Item_sum_bit(Item *item_par,ulonglong reset_arg)
:Item_sum_int(item_par),reset_bits(reset_arg),bits(reset_arg) {}
Item_sum_bit(THD *thd, Item_sum_bit &item):
@@ -457,6 +468,7 @@ class Item_sum_bit :public Item_sum_int
void clear();
longlong val_int();
void reset_field();
+ void update_field();
void fix_length_and_dec()
{ decimals=0; max_length=21; unsigned_flag=1; maybe_null=null_value=0; }
};
@@ -464,11 +476,10 @@ class Item_sum_bit :public Item_sum_int
class Item_sum_or :public Item_sum_bit
{
- public:
+public:
Item_sum_or(Item *item_par) :Item_sum_bit(item_par,LL(0)) {}
Item_sum_or(THD *thd, Item_sum_or &item) :Item_sum_bit(thd, item) {}
bool add();
- void update_field();
const char *func_name() const { return "bit_or"; }
Item *copy_or_same(THD* thd);
};
@@ -477,10 +488,9 @@ class Item_sum_or :public Item_sum_bit
class Item_sum_and :public Item_sum_bit
{
public:
- Item_sum_and(Item *item_par) :Item_sum_bit(item_par, ~(ulonglong) LL(0)) {}
+ Item_sum_and(Item *item_par) :Item_sum_bit(item_par, ULONGLONG_MAX) {}
Item_sum_and(THD *thd, Item_sum_and &item) :Item_sum_bit(thd, item) {}
bool add();
- void update_field();
const char *func_name() const { return "bit_and"; }
Item *copy_or_same(THD* thd);
};
@@ -491,7 +501,6 @@ class Item_sum_xor :public Item_sum_bit
Item_sum_xor(Item *item_par) :Item_sum_bit(item_par,LL(0)) {}
Item_sum_xor(THD *thd, Item_sum_xor &item) :Item_sum_bit(thd, item) {}
bool add();
- void update_field();
const char *func_name() const { return "bit_xor"; }
Item *copy_or_same(THD* thd);
};
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index a5372a4ae60..9799c5814c4 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -526,8 +526,11 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time,
uint year;
if (type == TIMESTAMP_TIME)
return 1;
- length= int10_to_str(calc_week(l_time, 0, (*ptr) == 'U', &year),
- intbuff, 10) - intbuff;
+ length= int10_to_str(calc_week(l_time,
+ (*ptr) == 'U' ?
+ WEEK_FIRST_WEEKDAY : WEEK_MONDAY_FIRST,
+ &year),
+ intbuff, 10) - intbuff;
str->append_with_prefill(intbuff, length, 2, '0');
}
break;
@@ -537,8 +540,12 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time,
uint year;
if (type == TIMESTAMP_TIME)
return 1;
- length= int10_to_str(calc_week(l_time, 1, (*ptr) == 'V', &year),
- intbuff, 10) - intbuff;
+ length= int10_to_str(calc_week(l_time,
+ ((*ptr) == 'V' ?
+ (WEEK_YEAR | WEEK_FIRST_WEEKDAY) :
+ (WEEK_YEAR | WEEK_MONDAY_FIRST)),
+ &year),
+ intbuff, 10) - intbuff;
str->append_with_prefill(intbuff, length, 2, '0');
}
break;
@@ -548,7 +555,11 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time,
uint year;
if (type == TIMESTAMP_TIME)
return 1;
- (void) calc_week(l_time, 1, (*ptr) == 'X', &year);
+ (void) calc_week(l_time,
+ ((*ptr) == 'X' ?
+ WEEK_YEAR | WEEK_FIRST_WEEKDAY :
+ WEEK_YEAR | WEEK_MONDAY_FIRST),
+ &year);
length= int10_to_str(year, intbuff, 10) - intbuff;
str->append_with_prefill(intbuff, length, 4, '0');
}
@@ -718,27 +729,51 @@ longlong Item_func_second::val_int()
}
-/*
- Returns the week of year.
+uint week_mode(uint mode)
+{
+ uint week_format= (mode & 7);
+ if (!(week_format & WEEK_MONDAY_FIRST))
+ week_format^= WEEK_FIRST_WEEKDAY;
+ return week_format;
+}
- The bits in week_format has the following meaning:
- 0 If not set: USA format: Sunday is first day of week
- If set: ISO format: Monday is first day of week
- 1 If not set: Week is in range 0-53
- If set Week is in range 1-53.
+/*
+ The bits in week_format(for calc_week() function) has the following meaning:
+ WEEK_MONDAY_FIRST (0) If not set Sunday is first day of week
+ If set Monday is first day of week
+ WEEK_YEAR (1) If not set Week is in range 0-53
+
+ Week 0 is returned for the the last week of the previous year (for
+ a date at start of january) In this case one can get 53 for the
+ first week of next year. This flag ensures that the week is
+ relevant for the given year. Note that this flag is only
+ releveant if WEEK_JANUARY is not set.
+
+ If set Week is in range 1-53.
+
+ In this case one may get week 53 for a date in January (when
+ the week is that last week of previous year) and week 1 for a
+ date in December.
+
+ WEEK_FIRST_WEEKDAY (2) If not set Weeks are numbered according
+ to ISO 8601:1988
+ If set The week that contains the first
+ 'first-day-of-week' is week 1.
+
+ ISO 8601:1988 means that if the week containing January 1 has
+ four or more days in the new year, then it is week 1;
+ Otherwise it is the last week of the previous year, and the
+ next week is week 1.
*/
longlong Item_func_week::val_int()
{
uint year;
- uint week_format;
TIME ltime;
if (get_arg0_date(&ltime,0))
return 0;
- week_format= (uint) args[1]->val_int();
- return (longlong) calc_week(&ltime,
- (week_format & 2) != 0,
- (week_format & 1) == 0,
+ return (longlong) calc_week(&ltime,
+ week_mode((uint) args[1]->val_int()),
&year);
}
@@ -749,7 +784,9 @@ longlong Item_func_yearweek::val_int()
TIME ltime;
if (get_arg0_date(&ltime,0))
return 0;
- week=calc_week(&ltime, 1, (args[1]->val_int() & 1) == 0, &year);
+ week= calc_week(&ltime,
+ (week_mode((uint) args[1]->val_int()) | WEEK_YEAR),
+ &year);
return week+year*100;
}
diff --git a/sql/log.cc b/sql/log.cc
index 936373daf03..b490845c256 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -964,7 +964,7 @@ void MYSQL_LOG::new_file(bool need_lock)
We log the whole file name for log file as the user may decide
to change base names at some point.
*/
- THD* thd = current_thd;
+ THD *thd = current_thd; /* may be 0 if we are reacting to SIGHUP */
Rotate_log_event r(thd,new_name+dirname_length(new_name));
r.set_log_pos(this);
r.write(&log_file);
@@ -1231,8 +1231,6 @@ bool MYSQL_LOG::write(Log_event* event_info)
Intvar_log_event e(thd,(uchar) LAST_INSERT_ID_EVENT,
thd->current_insert_id);
e.set_log_pos(this);
- if (thd->server_id)
- e.server_id = thd->server_id;
if (e.write(file))
goto err;
}
@@ -1240,8 +1238,6 @@ bool MYSQL_LOG::write(Log_event* event_info)
{
Intvar_log_event e(thd,(uchar) INSERT_ID_EVENT,thd->last_insert_id);
e.set_log_pos(this);
- if (thd->server_id)
- e.server_id = thd->server_id;
if (e.write(file))
goto err;
}
diff --git a/sql/log_event.cc b/sql/log_event.cc
index d0dc0a83b11..b609e6c6b11 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -239,6 +239,13 @@ Log_event::Log_event(THD* thd_arg, uint16 flags_arg, bool using_trans)
}
+/*
+ This minimal constructor is for when you are not even sure that there is a
+ valid THD. For example in the server when we are shutting down or flushing
+ logs after receiving a SIGHUP (then we must write a Rotate to the binlog but
+ we have no THD, so we need this minimal constructor).
+*/
+
Log_event::Log_event()
:temp_buf(0), exec_time(0), cached_event_len(0), flags(0), cache_stmt(0),
thd(0)
@@ -1032,7 +1039,7 @@ Default database: '%s'",
thd->variables.convert_set = 0;
#endif
close_thread_tables(thd);
- free_root(&thd->mem_root,0);
+ free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC));
return (thd->query_error ? thd->query_error : Log_event::exec_event(rli));
}
#endif
@@ -1794,10 +1801,10 @@ Slave: load data infile on table '%s' at log position %s in log \
slave_print_error(rli,sql_errno,"\
Error '%s' running LOAD DATA INFILE on table '%s'. Default database: '%s'",
err, (char*)table_name, print_slave_db_safe(db));
- free_root(&thd->mem_root,0);
+ free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC));
return 1;
}
- free_root(&thd->mem_root,0);
+ free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC));
if (thd->is_fatal_error)
{
diff --git a/sql/log_event.h b/sql/log_event.h
index 6cc8a7ca06d..d615c0e361b 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -698,7 +698,7 @@ public:
#ifndef MYSQL_CLIENT
Intvar_log_event(THD* thd_arg,uchar type_arg, ulonglong val_arg)
- :Log_event(),val(val_arg),type(type_arg)
+ :Log_event(thd_arg,0,0),val(val_arg),type(type_arg)
{}
#ifdef HAVE_REPLICATION
void pack_info(Protocol* protocol);
@@ -841,7 +841,7 @@ public:
Rotate_log_event(THD* thd_arg, const char* new_log_ident_arg,
uint ident_len_arg = 0,
ulonglong pos_arg = LOG_EVENT_OFFSET)
- :Log_event(thd_arg,0,0), new_log_ident(new_log_ident_arg),
+ :Log_event(), new_log_ident(new_log_ident_arg),
pos(pos_arg),ident_len(ident_len_arg ? ident_len_arg :
(uint) strlen(new_log_ident_arg)), alloced(0)
{}
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 7f003d0ce1f..b7a2d1a74b9 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -283,6 +283,11 @@ void debug_sync_point(const char* lock_name, uint lock_timeout);
#define tmp_file_prefix "#sql" /* Prefix for tmp tables */
#define tmp_file_prefix_length 4
+/* Flags for calc_week() function. */
+#define WEEK_MONDAY_FIRST 1
+#define WEEK_YEAR 2
+#define WEEK_FIRST_WEEKDAY 4
+
struct st_table;
class THD;
@@ -418,6 +423,7 @@ void mysql_execute_command(THD *thd);
bool do_command(THD *thd);
bool dispatch_command(enum enum_server_command command, THD *thd,
char* packet, uint packet_length);
+bool check_dup(const char *db, const char *name, TABLE_LIST *tables);
#ifndef EMBEDDED_LIBRARY
bool check_stack_overrun(THD *thd,char *dummy);
#else
@@ -431,17 +437,11 @@ void kill_mysql(void);
void close_connection(THD *thd, uint errcode, bool lock);
bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
bool *write_to_binlog);
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
bool check_access(THD *thd, ulong access, const char *db, ulong *save_priv,
bool no_grant, bool no_errors);
bool check_table_access(THD *thd, ulong want_access, TABLE_LIST *tables,
bool no_errors);
bool check_global_access(THD *thd, ulong want_access);
-#else
-#define check_access(thd, access, db, save_priv, no_grant, no_errors) false
-#define check_table_access(thd, want_access, tables, no_errors) false
-#define check_global_access(thd, want_access) false
-#endif
int mysql_backup_table(THD* thd, TABLE_LIST* table_list);
int mysql_restore_table(THD* thd, TABLE_LIST* table_list);
@@ -977,8 +977,7 @@ void filesort_free_buffers(TABLE *table);
void change_double_for_sort(double nr,byte *to);
int get_quick_record(SQL_SELECT *select);
int calc_weekday(long daynr,bool sunday_first_day_of_week);
-uint calc_week(TIME *ltime, bool with_year, bool sunday_first_day_of_week,
- uint *year);
+uint calc_week(TIME *l_time, uint week_behaviour, uint *year);
void find_date(char *pos,uint *vek,uint flag);
TYPELIB *convert_strings_to_array_type(my_string *typelibs, my_string *end);
TYPELIB *typelib(List<String> &strings);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index f90e653b44c..b237847faed 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -497,6 +497,8 @@ static uint set_maximum_open_files(uint max_file_limit);
static ulong find_bit_type(const char *x, TYPELIB *bit_lib);
static void clean_up(bool print_message);
static void clean_up_mutexes(void);
+static int test_if_case_insensitive(const char *dir_name);
+static void create_pid_file();
#ifndef EMBEDDED_LIBRARY
/****************************************************************************
@@ -1058,7 +1060,7 @@ static void set_user(const char *user)
}
return;
}
- else if (!user)
+ if (!user)
{
if (!opt_bootstrap)
{
@@ -1480,16 +1482,7 @@ static void start_signal_handler(void)
{
// Save vm id of this process
if (!opt_bootstrap)
- {
- File pidFile;
- if ((pidFile = my_create(pidfile_name,0664, O_WRONLY, MYF(MY_WME))) >= 0)
- {
- char buff[21];
- sprintf(buff,"%lu",(ulong) getpid());
- (void) my_write(pidFile, buff,strlen(buff),MYF(MY_WME));
- (void) my_close(pidFile,MYF(0));
- }
- }
+ create_pid_file();
// no signal handler
}
@@ -1775,16 +1768,8 @@ extern "C" void *signal_hand(void *arg __attribute__((unused)))
/* Save pid to this process (or thread on Linux) */
if (!opt_bootstrap)
- {
- File pidFile;
- if ((pidFile = my_create(pidfile_name,0664, O_WRONLY, MYF(MY_WME))) >= 0)
- {
- char buff[21];
- ulong length= my_sprintf(buff, (buff,"%lu",(ulong) getpid()));
- (void) my_write(pidFile, buff, length, MYF(MY_WME));
- (void) my_close(pidFile,MYF(0));
- }
- }
+ create_pid_file();
+
#ifdef HAVE_STACK_TRACE_ON_SEGV
if (opt_do_pstack)
{
@@ -2756,7 +2741,7 @@ default_service_handling(char **argv,
}
/* We must have servicename last */
*pos++= ' ';
- strmake(pos, servicename, (uint) (end+2 - pos));
+ (void) add_quoted_string(pos, servicename, end);
if (Service.got_service_option(argv, "install"))
{
@@ -4595,7 +4580,7 @@ The minimum value for this variable is 4096.",
1, 0},
{"table_cache", OPT_TABLE_CACHE,
"The number of open tables for all threads.", (gptr*) &table_cache_size,
- (gptr*) &table_cache_size, 0, GET_ULONG, REQUIRED_ARG, 64, 1, 16384, 0, 1,
+ (gptr*) &table_cache_size, 0, GET_ULONG, REQUIRED_ARG, 64, 1, ~0L, 0, 1,
0},
{"thread_concurrency", OPT_THREAD_CONCURRENCY,
"Permits the application to give the threads system a hint for the desired number of threads that should be run at the same time.",
@@ -4613,7 +4598,7 @@ The minimum value for this variable is 4096.",
{"thread_stack", OPT_THREAD_STACK,
"The stack size for each thread.", (gptr*) &thread_stack,
(gptr*) &thread_stack, 0, GET_ULONG, REQUIRED_ARG,DEFAULT_THREAD_STACK,
- 1024*32, ~0L, 0, 1024, 0},
+ 1024L*128L, ~0L, 0, 1024, 0},
{"transaction_alloc_block_size", OPT_TRANS_ALLOC_BLOCK_SIZE,
"Allocation block size for transactions to be stored in binary log",
(gptr*) &global_system_variables.trans_alloc_block_size,
@@ -4638,7 +4623,7 @@ The minimum value for this variable is 4096.",
"The default week format used by WEEK() functions.",
(gptr*) &global_system_variables.default_week_format,
(gptr*) &max_system_variables.default_week_format,
- 0, GET_ULONG, REQUIRED_ARG, 0, 0, 3L, 0, 1, 0},
+ 0, GET_ULONG, REQUIRED_ARG, 0, 0, 7L, 0, 1, 0},
{ "date-format", OPT_DATE_FORMAT,
"The DATE format (For future).",
(gptr*) &opt_date_time_formats[TIMESTAMP_DATE],
@@ -5376,11 +5361,10 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
my_use_symdir=0;
break;
case (int) OPT_BIND_ADDRESS:
- if (!argument ||
- (my_bind_addr= (ulong) inet_addr(argument)) == INADDR_NONE)
+ if ((my_bind_addr= (ulong) inet_addr(argument)) == INADDR_NONE)
{
struct hostent *ent;
- if (argument || argument[0])
+ if (argument[0])
ent=gethostbyname(argument);
else
{
@@ -5790,6 +5774,17 @@ static void fix_paths(void)
exit(1);
}
#endif /* HAVE_REPLICATION */
+
+ /*
+ Ensure that lower_case_table_names is set on system where we have case
+ insensitive names. If this is not done the users MyISAM tables will
+ get corrupted if accesses with names of different case.
+ */
+ if (!lower_case_table_names &&
+ test_if_case_insensitive(mysql_real_data_home) == 1)
+ {
+ sql_print_error("Warning: Setting lower_case_table_names=1 because file system for '%s' is case insensitive", mysql_real_data_home);
+ }
}
@@ -5943,6 +5938,60 @@ skipp: ;
} /* find_bit_type */
+/*
+ Check if file system used for databases is case insensitive
+
+ SYNOPSIS
+ test_if_case_sensitive()
+ dir_name Directory to test
+
+ RETURN
+ -1 Don't know (Test failed)
+ 0 File system is case sensitive
+ 1 File system is case insensitive
+*/
+
+static int test_if_case_insensitive(const char *dir_name)
+{
+ int result= 0;
+ File file;
+ char buff[FN_REFLEN], buff2[FN_REFLEN];
+ MY_STAT stat_info;
+
+ fn_format(buff, glob_hostname, dir_name, ".lower-test",
+ MY_UNPACK_FILENAME | MY_REPLACE_EXT | MY_REPLACE_DIR);
+ fn_format(buff2, glob_hostname, dir_name, ".LOWER-TEST",
+ MY_UNPACK_FILENAME | MY_REPLACE_EXT | MY_REPLACE_DIR);
+ (void) my_delete(buff2, MYF(0));
+ if ((file= my_create(buff, 0666, O_RDWR, MYF(0))) < 0)
+ {
+ sql_print_error("Warning: Can't create test file %s", buff);
+ return -1;
+ }
+ my_close(file, MYF(0));
+ if (my_stat(buff2, &stat_info, MYF(0)))
+ result= 1; // Can access file
+ (void) my_delete(buff, MYF(MY_WME));
+ return result;
+}
+
+
+/* Create file to store pid number */
+
+static void create_pid_file()
+{
+ File file;
+ if ((file = my_create(pidfile_name,0664,
+ O_WRONLY | O_TRUNC, MYF(MY_WME))) >= 0)
+ {
+ char buff[21];
+ sprintf(buff,"%lu\n",(ulong) getpid());
+ (void) my_write(file, buff,strlen(buff),MYF(MY_WME));
+ (void) my_close(file, MYF(0));
+ }
+}
+
+
/*****************************************************************************
Instantiate templates
*****************************************************************************/
diff --git a/sql/nt_servc.cc b/sql/nt_servc.cc
index 25fc010d9a5..3e9d68d5fdb 100644
--- a/sql/nt_servc.cc
+++ b/sql/nt_servc.cc
@@ -496,9 +496,9 @@ BOOL NTService::IsService(LPCSTR ServiceName)
BOOL ret_value=FALSE;
SC_HANDLE service, scm;
- if (scm = OpenSCManager(0, 0,SC_MANAGER_ENUMERATE_SERVICE))
+ if ((scm= OpenSCManager(0, 0,SC_MANAGER_ENUMERATE_SERVICE)))
{
- if ((service = OpenService(scm,ServiceName, SERVICE_ALL_ACCESS )))
+ if ((service = OpenService(scm,ServiceName, SERVICE_QUERY_STATUS )))
{
ret_value=TRUE;
CloseServiceHandle(service);
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index bbdc1913a8c..54c3f3c0ae3 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -966,9 +966,10 @@ static SEL_ARG *
get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
Item_func::Functype type,Item *value)
{
- uint maybe_null=(uint) field->real_maybe_null();
+ uint maybe_null=(uint) field->real_maybe_null(), copies;
uint field_length=field->pack_length()+maybe_null;
SEL_ARG *tree;
+ char *str, *str2;
DBUG_ENTER("get_mm_leaf");
if (type == Item_func::LIKE_FUNC)
@@ -1069,16 +1070,39 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
/* This happens when we try to insert a NULL field in a not null column */
DBUG_RETURN(&null_element); // cmp with NULL is never true
}
- // Get local copy of key
- char *str= (char*) alloc_root(param->mem_root,
- key_part->part_length+maybe_null);
+ /* Get local copy of key */
+ copies= 1;
+ if (field->key_type() == HA_KEYTYPE_VARTEXT)
+ copies= 2;
+ str= str2= (char*) alloc_root(param->mem_root,
+ (key_part->part_length+maybe_null)*copies+1);
if (!str)
DBUG_RETURN(0);
if (maybe_null)
*str= (char) field->is_real_null(); // Set to 1 if null
field->get_key_image(str+maybe_null,key_part->part_length,
field->charset(),key_part->image_type);
- if (!(tree=new SEL_ARG(field,str,str)))
+ if (copies == 2)
+ {
+ /*
+ The key is stored as 2 byte length + key
+ key doesn't match end space. In other words, a key 'X ' should match
+ all rows between 'X' and 'X ...'
+ */
+ uint length= uint2korr(str+maybe_null);
+ char *end;
+ str2= str+ key_part->part_length + maybe_null;
+ /* remove end space */
+ while (length > 0 && str[length+HA_KEY_BLOB_LENGTH+maybe_null-1] == ' ')
+ length--;
+ int2store(str+maybe_null, length);
+ /* Create key that is space filled */
+ memcpy(str2, str, length + HA_KEY_BLOB_LENGTH + maybe_null);
+ bfill(str2+ length+ HA_KEY_BLOB_LENGTH +maybe_null,
+ key_part->part_length-length - HA_KEY_BLOB_LENGTH, ' ');
+ int2store(str2+maybe_null, key_part->part_length - HA_KEY_BLOB_LENGTH);
+ }
+ if (!(tree=new SEL_ARG(field,str,str2)))
DBUG_RETURN(0); // out of memory
switch (type) {
@@ -1460,7 +1484,7 @@ key_or(SEL_ARG *key1,SEL_ARG *key2)
}
return 0;
}
- else if (!key2)
+ if (!key2)
{
key1->use_count--;
key1->free_tree();
@@ -2219,7 +2243,8 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
param->range_count++;
if (!tmp_min_flag && ! tmp_max_flag &&
(uint) key_tree->part+1 == param->table->key_info[keynr].key_parts &&
- (param->table->key_info[keynr].flags & HA_NOSAME) &&
+ (param->table->key_info[keynr].flags & (HA_NOSAME | HA_END_SPACE_KEY)) ==
+ HA_NOSAME &&
min_key_length == max_key_length &&
!memcmp(param->min_key,param->max_key,min_key_length))
tmp=1; // Max one record
@@ -2373,7 +2398,8 @@ get_quick_keys(PARAM *param,QUICK_SELECT *quick,KEY_PART *key,
{
KEY *table_key=quick->head->key_info+quick->index;
flag=EQ_RANGE;
- if (table_key->flags & HA_NOSAME && key->part == table_key->key_parts-1)
+ if ((table_key->flags & (HA_NOSAME | HA_END_SPACE_KEY)) == HA_NOSAME &&
+ key->part == table_key->key_parts-1)
{
if (!(table_key->flags & HA_NULL_PART_KEY) ||
!null_part_in_key(key,
@@ -2419,7 +2445,7 @@ bool QUICK_SELECT::unique_key_range()
if (((tmp=ranges.head())->flag & (EQ_RANGE | NULL_RANGE)) == EQ_RANGE)
{
KEY *key=head->key_info+index;
- return ((key->flags & HA_NOSAME) &&
+ return ((key->flags & (HA_NOSAME | HA_END_SPACE_KEY)) == HA_NOSAME &&
key->key_length == tmp->min_length);
}
}
@@ -2454,6 +2480,7 @@ QUICK_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, TABLE_REF *ref)
QUICK_SELECT *quick=new QUICK_SELECT(thd, table, ref->key, 1);
KEY *key_info = &table->key_info[ref->key];
KEY_PART *key_part;
+ QUICK_RANGE *range;
uint part;
if (!quick)
@@ -2461,18 +2488,18 @@ QUICK_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, TABLE_REF *ref)
if (cp_buffer_from_ref(ref))
{
if (thd->is_fatal_error)
- return 0; // out of memory
+ goto err; // out of memory
return quick; // empty range
}
- QUICK_RANGE *range= new QUICK_RANGE();
- if (!range)
+ if (!(range= new QUICK_RANGE()))
goto err; // out of memory
range->min_key=range->max_key=(char*) ref->key_buff;
range->min_length=range->max_length=ref->key_length;
range->flag= ((ref->key_length == key_info->key_length &&
- (key_info->flags & HA_NOSAME)) ? EQ_RANGE : 0);
+ (key_info->flags & (HA_NOSAME | HA_END_SPACE_KEY)) ==
+ HA_NOSAME) ? EQ_RANGE : 0);
if (!(quick->key_parts=key_part=(KEY_PART *)
alloc_root(&quick->alloc,sizeof(KEY_PART)*ref->key_parts)))
diff --git a/sql/records.cc b/sql/records.cc
index 7ba9ff0f42f..0feb873a6af 100644
--- a/sql/records.cc
+++ b/sql/records.cc
@@ -118,11 +118,12 @@ void init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
info->read_record=rr_sequential;
table->file->rnd_init();
/* We can use record cache if we don't update dynamic length tables */
- if (use_record_cache > 0 ||
- (int) table->reginfo.lock_type <= (int) TL_READ_HIGH_PRIORITY ||
- !(table->db_options_in_use & HA_OPTION_PACK_RECORD) ||
- (use_record_cache < 0 &&
- !(table->file->table_flags() & HA_NOT_DELETE_WITH_CACHE)))
+ if (!table->no_cache &&
+ (use_record_cache > 0 ||
+ (int) table->reginfo.lock_type <= (int) TL_READ_HIGH_PRIORITY ||
+ !(table->db_options_in_use & HA_OPTION_PACK_RECORD) ||
+ (use_record_cache < 0 &&
+ !(table->file->table_flags() & HA_NOT_DELETE_WITH_CACHE))))
VOID(table->file->extra_opt(HA_EXTRA_CACHE,
thd->variables.read_buff_size));
}
diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc
index 084f7386b7b..18456af8048 100644
--- a/sql/repl_failsafe.cc
+++ b/sql/repl_failsafe.cc
@@ -52,6 +52,13 @@ static Slave_log_event* find_slave_event(IO_CACHE* log,
const char* log_file_name,
char* errmsg);
+/*
+ All of the functions defined in this file which are not used (the ones to
+ handle failsafe) are not used; their code has not been updated for more than
+ one year now so should be considered as BADLY BROKEN. Do not enable it.
+ The used functions (to handle LOAD DATA FROM MASTER, plus some small
+ functions like register_slave()) are working.
+*/
static int init_failsafe_rpl_thread(THD* thd)
{
@@ -418,7 +425,6 @@ static Slave_log_event* find_slave_event(IO_CACHE* log,
my_snprintf(errmsg, SLAVE_ERRMSG_SIZE,
"Could not find slave event in log '%s'",
(char*)log_file_name);
- delete ev;
return 0;
}
diff --git a/sql/set_var.cc b/sql/set_var.cc
index f9d5377b890..c8b11eb0f58 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -791,9 +791,8 @@ bool update_sys_var_str(sys_var_str *var_str, rw_lock_t *var_mutex,
/* If the string is "", delete old init command */
if (var && (new_length= var->value->str_value.length()))
{
- if (!(res= my_strdup_with_length(var->value->str_value.ptr(),
- new_length,
- MYF(0))))
+ if (!(res= my_strdup_with_length((byte*) var->value->str_value.ptr(),
+ new_length, MYF(0))))
return 1;
}
/*
@@ -2505,6 +2504,7 @@ bool sys_var_thd_storage_engine::check(THD *thd, set_var *var)
}
return 0;
}
+ value= "unknown";
err:
my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), value);
diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt
index d6a0c51bdff..4470739cbdd 100644
--- a/sql/share/czech/errmsg.txt
+++ b/sql/share/czech/errmsg.txt
@@ -272,8 +272,8 @@ character-set=latin2
"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
"Z_DATA_ERROR: Input data was corrupted for zlib",
"%d line(s) was(were) cut by group_concat()",
-"Record count is fewer than the column count at row %ld",
-"Record count is more than the column count at row %ld",
+"Row %ld doesn't contain data for all columns",
+"Row %ld was truncated; It contained more data than there where input columns",
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
"Data truncated, out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt
index 1d889e6258e..d005150cb89 100644
--- a/sql/share/danish/errmsg.txt
+++ b/sql/share/danish/errmsg.txt
@@ -266,8 +266,8 @@ character-set=latin1
"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
"Z_DATA_ERROR: Input data was corrupted for zlib",
"%d line(s) was(were) cut by group_concat()",
-"Record count is fewer than the column count at row %ld",
-"Record count is more than the column count at row %ld",
+"Row %ld doesn't contain data for all columns",
+"Row %ld was truncated; It contained more data than there where input columns",
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
"Data truncated, out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt
index 4798ea55b42..3fd44f9ec69 100644
--- a/sql/share/dutch/errmsg.txt
+++ b/sql/share/dutch/errmsg.txt
@@ -274,8 +274,8 @@ character-set=latin1
"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
"Z_DATA_ERROR: Input data was corrupted for zlib",
"%d line(s) was(were) cut by group_concat()",
-"Record count is fewer than the column count at row %ld",
-"Record count is more than the column count at row %ld",
+"Row %ld doesn't contain data for all columns",
+"Row %ld was truncated; It contained more data than there where input columns",
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
"Data truncated, out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt
index 920ec433da0..6400093a6cf 100644
--- a/sql/share/english/errmsg.txt
+++ b/sql/share/english/errmsg.txt
@@ -263,8 +263,8 @@ character-set=latin1
"ZLIB: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
"ZLIB: Input data was corrupted for zlib",
"%d line(s) was(were) cut by group_concat()",
-"Record count is fewer than the column count at row %ld",
-"Record count is more than the column count at row %ld",
+"Row %ld doesn't contain data for all columns",
+"Row %ld was truncated; It contained more data than there where input columns",
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
"Data truncated, out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt
index 0c9b5c96308..eb7e6d0508b 100644
--- a/sql/share/estonian/errmsg.txt
+++ b/sql/share/estonian/errmsg.txt
@@ -268,8 +268,8 @@ character-set=latin7
"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
"Z_DATA_ERROR: Input data was corrupted for zlib",
"%d line(s) was(were) cut by group_concat()",
-"Record count is fewer than the column count at row %ld",
-"Record count is more than the column count at row %ld",
+"Row %ld doesn't contain data for all columns",
+"Row %ld was truncated; It contained more data than there where input columns",
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
"Data truncated, out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt
index a9d3f9b049a..d5a4874a49d 100644
--- a/sql/share/french/errmsg.txt
+++ b/sql/share/french/errmsg.txt
@@ -263,8 +263,8 @@ character-set=latin1
"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
"Z_DATA_ERROR: Input data was corrupted for zlib",
"%d line(s) was(were) cut by group_concat()",
-"Record count is fewer than the column count at row %ld",
-"Record count is more than the column count at row %ld",
+"Row %ld doesn't contain data for all columns",
+"Row %ld was truncated; It contained more data than there where input columns",
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
"Data truncated, out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt
index 5dfd1173467..5472e824e61 100644
--- a/sql/share/greek/errmsg.txt
+++ b/sql/share/greek/errmsg.txt
@@ -263,8 +263,8 @@ character-set=greek
"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
"Z_DATA_ERROR: Input data was corrupted for zlib",
"%d line(s) was(were) cut by group_concat()",
-"Record count is fewer than the column count at row %ld",
-"Record count is more than the column count at row %ld",
+"Row %ld doesn't contain data for all columns",
+"Row %ld was truncated; It contained more data than there where input columns",
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
"Data truncated, out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt
index d454c51caba..463aaed5760 100644
--- a/sql/share/hungarian/errmsg.txt
+++ b/sql/share/hungarian/errmsg.txt
@@ -265,8 +265,8 @@ character-set=latin2
"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
"Z_DATA_ERROR: Input data was corrupted for zlib",
"%d line(s) was(were) cut by group_concat()",
-"Record count is fewer than the column count at row %ld",
-"Record count is more than the column count at row %ld",
+"Row %ld doesn't contain data for all columns",
+"Row %ld was truncated; It contained more data than there where input columns",
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
"Data truncated, out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt
index 18715b4930b..204e1f980cc 100644
--- a/sql/share/italian/errmsg.txt
+++ b/sql/share/italian/errmsg.txt
@@ -263,8 +263,8 @@ character-set=latin1
"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
"Z_DATA_ERROR: Input data was corrupted for zlib",
"%d line(s) was(were) cut by group_concat()",
-"Record count is fewer than the column count at row %ld",
-"Record count is more than the column count at row %ld",
+"Row %ld doesn't contain data for all columns",
+"Row %ld was truncated; It contained more data than there where input columns",
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
"Data truncated, out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt
index b034c8f657f..b8b9688fd38 100644
--- a/sql/share/japanese/errmsg.txt
+++ b/sql/share/japanese/errmsg.txt
@@ -265,8 +265,8 @@ character-set=ujis
"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
"Z_DATA_ERROR: Input data was corrupted for zlib",
"%d line(s) was(were) cut by group_concat()",
-"Record count is fewer than the column count at row %ld",
-"Record count is more than the column count at row %ld",
+"Row %ld doesn't contain data for all columns",
+"Row %ld was truncated; It contained more data than there where input columns",
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
"Data truncated, out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt
index df15d77c075..055d1a0a2c7 100644
--- a/sql/share/korean/errmsg.txt
+++ b/sql/share/korean/errmsg.txt
@@ -263,8 +263,8 @@ character-set=euckr
"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
"Z_DATA_ERROR: Input data was corrupted for zlib",
"%d line(s) was(were) cut by group_concat()",
-"Record count is fewer than the column count at row %ld",
-"Record count is more than the column count at row %ld",
+"Row %ld doesn't contain data for all columns",
+"Row %ld was truncated; It contained more data than there where input columns",
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
"Data truncated, out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt
index b46a52ae2de..735a2583685 100644
--- a/sql/share/norwegian-ny/errmsg.txt
+++ b/sql/share/norwegian-ny/errmsg.txt
@@ -265,8 +265,8 @@ character-set=latin1
"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
"Z_DATA_ERROR: Input data was corrupted for zlib",
"%d line(s) was(were) cut by group_concat()",
-"Record count is fewer than the column count at row %ld",
-"Record count is more than the column count at row %ld",
+"Row %ld doesn't contain data for all columns",
+"Row %ld was truncated; It contained more data than there where input columns",
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
"Data truncated, out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt
index 3727e49d2ad..2c434da271e 100644
--- a/sql/share/norwegian/errmsg.txt
+++ b/sql/share/norwegian/errmsg.txt
@@ -265,8 +265,8 @@ character-set=latin1
"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
"Z_DATA_ERROR: Input data was corrupted for zlib",
"%d line(s) was(were) cut by group_concat()",
-"Record count is fewer than the column count at row %ld",
-"Record count is more than the column count at row %ld",
+"Row %ld doesn't contain data for all columns",
+"Row %ld was truncated; It contained more data than there where input columns",
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
"Data truncated, out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt
index 1cb5b384e4b..78fcb2a7993 100644
--- a/sql/share/polish/errmsg.txt
+++ b/sql/share/polish/errmsg.txt
@@ -267,8 +267,8 @@ character-set=latin2
"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
"Z_DATA_ERROR: Input data was corrupted for zlib",
"%d line(s) was(were) cut by group_concat()",
-"Record count is fewer than the column count at row %ld",
-"Record count is more than the column count at row %ld",
+"Row %ld doesn't contain data for all columns",
+"Row %ld was truncated; It contained more data than there where input columns",
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
"Data truncated, out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt
index 519f86e284c..528a0d081ff 100644
--- a/sql/share/romanian/errmsg.txt
+++ b/sql/share/romanian/errmsg.txt
@@ -267,8 +267,8 @@ character-set=latin2
"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
"Z_DATA_ERROR: Input data was corrupted for zlib",
"%d line(s) was(were) cut by group_concat()",
-"Record count is fewer than the column count at row %ld",
-"Record count is more than the column count at row %ld",
+"Row %ld doesn't contain data for all columns",
+"Row %ld was truncated; It contained more data than there where input columns",
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
"Data truncated, out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt
index ae186929898..5224f19b001 100644
--- a/sql/share/russian/errmsg.txt
+++ b/sql/share/russian/errmsg.txt
@@ -265,8 +265,8 @@ character-set=koi8r
"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
"Z_DATA_ERROR: Input data was corrupted for zlib",
"%d line(s) was(were) cut by group_concat()",
-"Record count is fewer than the column count at row %ld",
-"Record count is more than the column count at row %ld",
+"Row %ld doesn't contain data for all columns",
+"Row %ld was truncated; It contained more data than there where input columns",
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
"Data truncated, out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt
index 0719b88bec0..904c8f0c8b9 100644
--- a/sql/share/serbian/errmsg.txt
+++ b/sql/share/serbian/errmsg.txt
@@ -258,8 +258,8 @@ character-set=cp1250
"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
"Z_DATA_ERROR: Input data was corrupted for zlib",
"%d line(s) was(were) cut by group_concat()",
-"Record count is fewer than the column count at row %ld",
-"Record count is more than the column count at row %ld",
+"Row %ld doesn't contain data for all columns",
+"Row %ld was truncated; It contained more data than there where input columns",
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
"Data truncated, out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt
index cb5957fb892..0f5a70fa2c6 100644
--- a/sql/share/slovak/errmsg.txt
+++ b/sql/share/slovak/errmsg.txt
@@ -271,8 +271,8 @@ character-set=latin2
"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
"Z_DATA_ERROR: Input data was corrupted for zlib",
"%d line(s) was(were) cut by group_concat()",
-"Record count is fewer than the column count at row %ld",
-"Record count is more than the column count at row %ld",
+"Row %ld doesn't contain data for all columns",
+"Row %ld was truncated; It contained more data than there where input columns",
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
"Data truncated, out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt
index 0e95efff5aa..845a7da36eb 100644
--- a/sql/share/spanish/errmsg.txt
+++ b/sql/share/spanish/errmsg.txt
@@ -265,8 +265,8 @@ character-set=latin1
"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
"Z_DATA_ERROR: Input data was corrupted for zlib",
"%d line(s) was(were) cut by group_concat()",
-"Record count is fewer than the column count at row %ld",
-"Record count is more than the column count at row %ld",
+"Row %ld doesn't contain data for all columns",
+"Row %ld was truncated; It contained more data than there where input columns",
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
"Data truncated, out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt
index 5edf41e0202..9da0a511ddb 100644
--- a/sql/share/swedish/errmsg.txt
+++ b/sql/share/swedish/errmsg.txt
@@ -263,8 +263,8 @@ character-set=latin1
"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
"Z_DATA_ERROR: Input data was corrupted for zlib",
"%d rad(er) kapades av group_concat()",
-"Record count is fewer than the column count at row %ld",
-"Record count is more than the column count at row %ld",
+"Row %ld doesn't contain data for all columns",
+"Row %ld was truncated; It contained more data than there where input columns",
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
"Data truncated, out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt
index 8dbc2b582c9..7186e0550b2 100644
--- a/sql/share/ukrainian/errmsg.txt
+++ b/sql/share/ukrainian/errmsg.txt
@@ -268,8 +268,8 @@ character-set=koi8u
"Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)",
"Z_DATA_ERROR: Input data was corrupted for zlib",
"%d line(s) was(were) cut by group_concat()",
-"Record count is fewer than the column count at row %ld",
-"Record count is more than the column count at row %ld",
+"Row %ld doesn't contain data for all columns",
+"Row %ld was truncated; It contained more data than there where input columns",
"Data truncated, NULL supplied to NOT NULL column '%s' at row %ld",
"Data truncated, out of range for column '%s' at row %ld",
"Data truncated for column '%s' at row %ld",
diff --git a/sql/slave.cc b/sql/slave.cc
index b13ac799c9b..7f9967618ca 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -2352,7 +2352,9 @@ improper_arguments: %d timed_out: %d",
static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type)
{
DBUG_ENTER("init_slave_thread");
- thd->system_thread = thd->bootstrap = 1;
+ thd->system_thread = (thd_type == SLAVE_THD_SQL) ?
+ SYSTEM_THREAD_SLAVE_SQL : SYSTEM_THREAD_SLAVE_IO;
+ thd->bootstrap= 1;
thd->host_or_ip= "";
thd->client_capabilities = 0;
my_net_init(&thd->net, 0);
@@ -4036,8 +4038,20 @@ Before assert, my_b_tell(cur_log)=%s rli->event_relay_log_pos=%s",
sizeof(rli->event_relay_log_name)-1);
flush_relay_log_info(rli);
}
-
- // next log is hot
+
+ /*
+ Now we want to open this next log. To know if it's a hot log (the one
+ being written by the I/O thread now) or a cold log, we can use
+ is_active(); if it is hot, we use the I/O cache; if it's cold we open
+ the file normally. But if is_active() reports that the log is hot, this
+ may change between the test and the consequence of the test. So we may
+ open the I/O cache whereas the log is now cold, which is nonsense.
+ To guard against this, we need to have LOCK_log.
+ */
+
+ DBUG_PRINT("info",("hot_log: %d",hot_log));
+ if (!hot_log) /* if hot_log, we already have this mutex */
+ pthread_mutex_lock(log_lock);
if (rli->relay_log.is_active(rli->linfo.log_file_name))
{
#ifdef EXTRA_DEBUG
@@ -4050,15 +4064,24 @@ Before assert, my_b_tell(cur_log)=%s rli->event_relay_log_pos=%s",
/*
Read pointer has to be at the start since we are the only
- reader
+ reader.
+ We must keep the LOCK_log to read the 4 first bytes, as this is a hot
+ log (same as when we call read_log_event() above: for a hot log we
+ take the mutex).
*/
if (check_binlog_magic(cur_log,&errmsg))
+ {
+ if (!hot_log) pthread_mutex_unlock(log_lock);
goto err;
+ }
+ if (!hot_log) pthread_mutex_unlock(log_lock);
continue;
}
+ if (!hot_log) pthread_mutex_unlock(log_lock);
/*
- if we get here, the log was not hot, so we will have to
- open it ourselves
+ if we get here, the log was not hot, so we will have to open it
+ ourselves. We are sure that the log is still not hot now (a log can get
+ from hot to cold, but not from cold to hot). No need for LOCK_log.
*/
#ifdef EXTRA_DEBUG
sql_print_error("next log '%s' is not active",
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 5364357a24b..c0f36f202f3 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -697,6 +697,7 @@ int acl_getroot(THD *thd, USER_RESOURCES *mqh,
If cipher name is specified, we compare it to actual cipher in
use.
*/
+ X509 *cert;
if (vio_type(vio) != VIO_TYPE_SSL ||
SSL_get_verify_result(ssl) != X509_V_OK)
break;
@@ -717,7 +718,11 @@ int acl_getroot(THD *thd, USER_RESOURCES *mqh,
}
/* Prepare certificate (if exists) */
DBUG_PRINT("info",("checkpoint 1"));
- X509* cert=SSL_get_peer_certificate(ssl);
+ if (!(cert= SSL_get_peer_certificate(ssl)))
+ {
+ user_access=NO_ACCESS;
+ break;
+ }
DBUG_PRINT("info",("checkpoint 2"));
/* If X509 issuer is speified, we check it... */
if (acl_user->x509_issuer)
@@ -1186,6 +1191,7 @@ bool change_password(THD *thd, const char *host, const char *user,
acl_user->user ? acl_user->user : "",
acl_user->host.hostname ? acl_user->host.hostname : "",
new_password));
+ thd->clear_error();
mysql_update_log.write(thd, buff, query_length);
Query_log_event qinfo(thd, buff, query_length, 0);
mysql_bin_log.write(&qinfo);
@@ -1258,11 +1264,11 @@ static const char *calc_ip(const char *ip, long *val, char end)
static void update_hostname(acl_host_and_ip *host, const char *hostname)
{
host->hostname=(char*) hostname; // This will not be modified!
- if (hostname &&
+ if (!hostname ||
(!(hostname=calc_ip(hostname,&host->ip,'/')) ||
!(hostname=calc_ip(hostname+1,&host->ip_mask,'\0'))))
{
- host->ip=host->ip_mask=0; // Not a masked ip
+ host->ip= host->ip_mask=0; // Not a masked ip
}
}
diff --git a/sql/sql_acl.h b/sql/sql_acl.h
index 8b8115b10db..7b66a851d33 100644
--- a/sql/sql_acl.h
+++ b/sql/sql_acl.h
@@ -58,8 +58,6 @@
#define EXTRA_ACL (1L << 29)
#define NO_ACCESS (1L << 30)
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
-
/*
Defines to change the above bits to how things are stored in tables
This is needed as the 'host' and 'db' table is missing a few privileges
@@ -127,8 +125,6 @@ public:
char *user,*db;
};
-
-
/* prototypes */
bool hostname_requires_resolving(const char *hostname);
@@ -152,7 +148,7 @@ my_bool grant_init(THD *thd);
void grant_free(void);
void grant_reload(THD *thd);
bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
- uint show_command=0, bool dont_print_error=0);
+ uint show_command, bool dont_print_error);
bool check_grant_column (THD *thd,TABLE *table, const char *name, uint length,
uint show_command=0);
bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table);
@@ -165,5 +161,7 @@ void get_mqh(const char *user, const char *host, USER_CONN *uc);
int mysql_drop_user(THD *thd, List <LEX_USER> &list);
int mysql_revoke_all(THD *thd, List <LEX_USER> &list);
-#endif /*!NO_EMBEDDED_ACCESS_CHECKS*/
-
+#ifdef NO_EMBEDDED_ACCESS_CHECKS
+#define check_grant(A,B,C,D,E) 0
+#define check_grant_db(A,B) 0
+#endif
diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc
index a6c24a25d6e..9e73e06d9c6 100644
--- a/sql/sql_analyse.cc
+++ b/sql/sql_analyse.cc
@@ -213,8 +213,7 @@ bool test_if_number(NUM_INFO *info, const char *str, uint str_len)
info->is_float = 1; // we can't use variable decimals here
return 1;
}
- else
- return 0;
+ return 0;
}
for (str++; *(end - 1) == '0'; end--); // jump over zeros at the end
if (str == end) // number was something like '123.000'
@@ -229,11 +228,8 @@ bool test_if_number(NUM_INFO *info, const char *str, uint str_len)
info->dval = atod(begin);
return 1;
}
- else
- return 0;
}
- else
- return 0;
+ return 0;
}
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 55ddfec6bfb..0101037da85 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -513,8 +513,8 @@ void close_temporary_tables(THD *thd)
if (query && found_user_tables && mysql_bin_log.is_open())
{
/* The -1 is to remove last ',' */
+ thd->clear_error();
Query_log_event qinfo(thd, query, (ulong)(end-query)-1, 0);
- qinfo.error_code=0;
mysql_bin_log.write(&qinfo);
}
thd->temporary_tables=0;
@@ -1752,6 +1752,19 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
const char *table_name=item->table_name;
const char *name=item->field_name;
uint length=(uint) strlen(name);
+ char name_buff[NAME_LEN+1];
+
+ if (db && lower_case_table_names)
+ {
+ /*
+ convert database to lower case for comparision.
+ We can't do this in Item_field as this would change the
+ 'name' of the item which may be used in the select list
+ */
+ strmake(name_buff, db, sizeof(name_buff)-1);
+ my_casedn_str(files_charset_info, name_buff);
+ db= name_buff;
+ }
if (table_name && table_name[0])
{ /* Qualified field */
@@ -1969,7 +1982,8 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
while ( wild_num && (item= it++))
{
if (item->type() == Item::FIELD_ITEM && ((Item_field*) item)->field_name &&
- ((Item_field*) item)->field_name[0] == '*')
+ ((Item_field*) item)->field_name[0] == '*' &&
+ !((Item_field*) item)->field)
{
uint elem= fields.elements;
if (insert_fields(thd,tables,((Item_field*) item)->db_name,
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 396764cd532..71dd7123d98 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -1206,9 +1206,29 @@ void Query_cache::invalidate(char *db)
if (query_cache_size > 0)
{
DUMP(this);
- /* invalidate_table reduce list while only root of list remain */
- while (tables_blocks !=0 )
- invalidate_table(tables_blocks);
+ restart_search:
+ if (tables_blocks)
+ {
+ Query_cache_block *curr= tables_blocks;
+ Query_cache_block *next;
+ do
+ {
+ next= curr->next;
+ if (strcmp(db, (char*)(curr->table()->db())) == 0)
+ invalidate_table(curr);
+ /*
+ invalidate_table can freed block on which point 'next' (if
+ table of this block used only in queries which was deleted
+ by invalidate_table). As far as we do not allocate new blocks
+ and mark all headers of freed blocks as 'FREE' (even if they are
+ merged with other blocks) we can just test type of block
+ to be sure that block is not deleted
+ */
+ if (next->type == Query_cache_block::FREE)
+ goto restart_search;
+ curr= next;
+ } while (curr != tables_blocks);
+ }
}
STRUCT_UNLOCK(&structure_guard_mutex);
}
@@ -2218,9 +2238,11 @@ void Query_cache::free_memory_block(Query_cache_block *block)
{
DBUG_ENTER("Query_cache::free_memory_block");
block->used=0;
- DBUG_PRINT("qcache",("first_block 0x%lx, block 0x%lx, pnext 0x%lx pprev 0x%lx",
- (ulong) first_block, (ulong) block,block->pnext,
- (ulong) block->pprev));
+ block->type= Query_cache_block::FREE; // mark block as free in any case
+ DBUG_PRINT("qcache",
+ ("first_block 0x%lx, block 0x%lx, pnext 0x%lx pprev 0x%lx",
+ (ulong) first_block, (ulong) block, (ulong) block->pnext,
+ (ulong) block->pprev));
if (block->pnext != first_block && block->pnext->is_free())
block = join_free_blocks(block, block->pnext);
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 1fce0049269..5479a3cecb6 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -589,7 +589,7 @@ public:
long dbug_thread_id;
pthread_t real_id;
uint current_tablenr,tmp_table;
- uint server_status,open_options;
+ uint server_status,open_options,system_thread;
uint32 query_length;
uint32 db_length;
uint select_number; //number of select (used for EXPLAIN)
@@ -607,7 +607,7 @@ public:
bool last_cuted_field;
bool no_errors, allow_sum_func, password, is_fatal_error;
bool query_start_used,last_insert_id_used,insert_id_used,rand_used;
- bool system_thread,in_lock_tables,global_read_lock;
+ bool in_lock_tables,global_read_lock;
bool query_error, bootstrap, cleanup_done;
bool volatile killed;
bool tmp_table_used;
@@ -750,6 +750,11 @@ public:
void update_charset();
};
+/* Flags for the THD::system_thread (bitmap) variable */
+#define SYSTEM_THREAD_DELAYED_INSERT 1
+#define SYSTEM_THREAD_SLAVE_IO 2
+#define SYSTEM_THREAD_SLAVE_SQL 4
+
/*
Used to hold information about file and file structure in exchainge
via non-DB file (...INTO OUTFILE..., ...LOAD DATA...)
@@ -761,7 +766,7 @@ public:
String *field_term,*enclosed,*line_term,*line_start,*escaped;
bool opt_enclosed;
bool dumpfile;
- uint skip_lines;
+ ulong skip_lines;
sql_exchange(char *name,bool dumpfile_flag);
~sql_exchange() {}
};
@@ -1109,7 +1114,7 @@ class multi_delete :public select_result
TABLE_LIST *delete_tables, *table_being_deleted;
Unique **tempfiles;
THD *thd;
- ha_rows deleted;
+ ha_rows deleted, found;
uint num_of_tables;
int error;
bool do_delete, transactional_tables, log_delayed, normal_tables;
diff --git a/sql/sql_client.cc b/sql/sql_client.cc
index 9f3063cde2d..49d0d3087ad 100644
--- a/sql/sql_client.cc
+++ b/sql/sql_client.cc
@@ -37,4 +37,3 @@ void my_net_local_init(NET *net)
#endif
}
}
-
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index c61e6800cfa..1f652524ed3 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -298,6 +298,7 @@ int mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info)
if (mysql_bin_log.is_open())
{
Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
+ thd->clear_error();
mysql_bin_log.write(&qinfo);
}
send_ok(thd, result);
@@ -384,6 +385,7 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
if (mysql_bin_log.is_open())
{
Query_log_event qinfo(thd, query, query_length, 0);
+ thd->clear_error();
mysql_bin_log.write(&qinfo);
}
send_ok(thd,(ulong) deleted);
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 94ae1743fd9..4ab0cfa20c1 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -135,14 +135,20 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
fields, all_fields, order) ||
!(sortorder=make_unireg_sortorder(order, &length)) ||
(table->sort.found_records = filesort(thd, table, sortorder, length,
- (SQL_SELECT *) 0, HA_POS_ERROR,
+ select, HA_POS_ERROR,
&examined_rows))
== HA_POS_ERROR)
{
delete select;
free_underlaid_joins(thd, &thd->lex.select_lex);
- DBUG_RETURN(-1); // This will force out message
+ DBUG_RETURN(-1); // This will force out message
}
+ /*
+ Filesort has already found and selected the rows we want to delete,
+ so we don't need the where clause
+ */
+ delete select;
+ select= 0;
}
init_read_record(&info,thd,table,select,1,1);
@@ -205,6 +211,8 @@ cleanup:
mysql_update_log.write(thd,thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
+ if (error <= 0)
+ thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length,
log_delayed);
if (mysql_bin_log.write(&qinfo) && transactional_table)
@@ -251,7 +259,7 @@ extern "C" int refposcmp2(void* arg, const void *a,const void *b)
multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt,
uint num_of_tables_arg)
- : delete_tables(dt), thd(thd_arg), deleted(0),
+ : delete_tables(dt), thd(thd_arg), deleted(0), found(0),
num_of_tables(num_of_tables_arg), error(0),
do_delete(0), transactional_tables(0), log_delayed(0), normal_tables(0)
{
@@ -355,6 +363,7 @@ bool multi_delete::send_data(List<Item> &values)
continue;
table->file->position(table->record[0]);
+ found++;
if (secure_counter < 0)
{
@@ -430,7 +439,7 @@ int multi_delete::do_deletes(bool from_send_error)
if (from_send_error)
{
- /* Found out table number for 'table_being_deleted' */
+ /* Found out table number for 'table_being_deleted*/
for (TABLE_LIST *aux=delete_tables;
aux != table_being_deleted;
aux=aux->next)
@@ -440,6 +449,8 @@ int multi_delete::do_deletes(bool from_send_error)
table_being_deleted = delete_tables;
do_delete= 0;
+ if (!found)
+ DBUG_RETURN(0);
for (table_being_deleted=table_being_deleted->next;
table_being_deleted ;
table_being_deleted=table_being_deleted->next, counter++)
@@ -510,6 +521,8 @@ bool multi_delete::send_eof()
mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
+ if (error <= 0)
+ thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length,
log_delayed);
if (mysql_bin_log.write(&qinfo) && !normal_tables)
@@ -621,6 +634,7 @@ end:
mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
+ thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length,
thd->tmp_table);
mysql_bin_log.write(&qinfo);
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 4484cdbe248..46ff9770893 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -380,6 +380,8 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
mysql_update_log.write(thd, thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
+ if (error <= 0)
+ thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length,
log_delayed);
if (mysql_bin_log.write(&qinfo) && transactional_table)
@@ -645,7 +647,7 @@ public:
thd.lex.current_select= 0; /* for my_message_sql */
bzero((char*) &thd.net,sizeof(thd.net)); // Safety
- thd.system_thread=1;
+ thd.system_thread= SYSTEM_THREAD_DELAYED_INSERT;
thd.host_or_ip= "";
bzero((char*) &info,sizeof(info));
pthread_mutex_init(&mutex,MY_MUTEX_INIT_FAST);
@@ -1512,6 +1514,8 @@ bool select_insert::send_eof()
mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
+ if (!error)
+ thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length,
table->file->has_transactions());
mysql_bin_log.write(&qinfo);
@@ -1525,7 +1529,6 @@ bool select_insert::send_eof()
::send_error(thd);
DBUG_RETURN(1);
}
-
char buff[160];
if (info.handle_duplicates == DUP_IGNORE)
sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records,
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index 0f39ab2663f..0c35e99ed08 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -72,10 +72,11 @@ public:
};
static int read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,
- List<Item> &fields, READ_INFO &read_info);
+ List<Item> &fields, READ_INFO &read_info,
+ ulong skip_lines);
static int read_sep_field(THD *thd,COPY_INFO &info,TABLE *table,
List<Item> &fields, READ_INFO &read_info,
- String &enclosed);
+ String &enclosed, ulong skip_lines);
int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
List<Item> &fields, enum enum_duplicates handle_duplicates,
@@ -85,8 +86,8 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
File file;
TABLE *table;
int error;
- String *field_term=ex->field_term,*escaped=ex->escaped,
- *enclosed=ex->enclosed;
+ String *field_term=ex->field_term,*escaped=ex->escaped;
+ String *enclosed=ex->enclosed;
bool is_fifo=0;
#ifndef EMBEDDED_LIBRARY
LOAD_FILE_INFO lf_info;
@@ -95,6 +96,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
/* If no current database, use database where table is located */
char *tdb= thd->db ? thd->db : db;
bool transactional_table, log_delayed;
+ ulong skip_lines= ex->skip_lines;
DBUG_ENTER("mysql_load");
#ifdef EMBEDDED_LIBRARY
@@ -254,16 +256,18 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
thd->count_cuted_fields= CHECK_FIELD_WARN; /* calc cuted fields */
thd->cuted_fields=0L;
- if (ex->line_term->length() && field_term->length())
+ /* Skip lines if there is a line terminator */
+ if (ex->line_term->length())
{
- // ex->skip_lines needs to be preserved for logging
- uint skip_lines = ex->skip_lines;
- while (skip_lines--)
+ /* ex->skip_lines needs to be preserved for logging */
+ while (skip_lines > 0)
{
+ skip_lines--;
if (read_info.next_line())
break;
}
}
+
if (!(error=test(read_info.error)))
{
uint save_time_stamp=table->time_stamp;
@@ -279,9 +283,11 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
table->file->deactivate_non_unique_index((ha_rows) 0);
table->copy_blobs=1;
if (!field_term->length() && !enclosed->length())
- error=read_fixed_length(thd,info,table,fields,read_info);
+ error=read_fixed_length(thd,info,table,fields,read_info,
+ skip_lines);
else
- error=read_sep_field(thd,info,table,fields,read_info,*enclosed);
+ error=read_sep_field(thd,info,table,fields,read_info,*enclosed,
+ skip_lines);
if (table->file->extra(HA_EXTRA_NO_CACHE))
error=1; /* purecov: inspected */
if (table->file->activate_all_index(thd))
@@ -290,7 +296,8 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
table->time_stamp=save_time_stamp;
table->next_number_field=0;
}
- if (file >= 0) my_close(file,MYF(0));
+ if (file >= 0)
+ my_close(file,MYF(0));
free_blobs(table); /* if pack_blob was used */
table->copy_blobs=0;
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
@@ -395,7 +402,7 @@ err:
static int
read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields,
- READ_INFO &read_info)
+ READ_INFO &read_info, ulong skip_lines)
{
List_iterator_fast<Item> it(fields);
Item_field *sql_field;
@@ -415,6 +422,17 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields,
my_error(ER_SERVER_SHUTDOWN,MYF(0));
DBUG_RETURN(1);
}
+ if (skip_lines)
+ {
+ /*
+ We could implement this with a simple seek if:
+ - We are not using DATA INFILE LOCAL
+ - escape character is ""
+ - line starting prefix is ""
+ */
+ skip_lines--;
+ continue;
+ }
it.rewind();
byte *pos=read_info.row_start;
#ifdef HAVE_purify
@@ -485,7 +503,7 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields,
static int
read_sep_field(THD *thd,COPY_INFO &info,TABLE *table,
List<Item> &fields, READ_INFO &read_info,
- String &enclosed)
+ String &enclosed, ulong skip_lines)
{
List_iterator_fast<Item> it(fields);
Item_field *sql_field;
@@ -536,6 +554,12 @@ read_sep_field(THD *thd,COPY_INFO &info,TABLE *table,
}
if (read_info.error)
break;
+ if (skip_lines)
+ {
+ if (!--skip_lines)
+ thd->cuted_fields= 0L; // Reset warnings
+ continue;
+ }
if (sql_field)
{ // Last record
if (sql_field == (Item_field*) fields.head())
@@ -875,7 +899,18 @@ found_eof:
}
/*
-** One can't use fixed length with multi-byte charset **
+ Read a row with fixed length.
+
+ NOTES
+ The row may not be fixed size on disk if there are escape
+ characters in the file.
+
+ IMPLEMENTATION NOTE
+ One can't use fixed length with multi-byte charset **
+
+ RETURN
+ 0 ok
+ 1 error
*/
int READ_INFO::read_fixed_length()
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 1d49c2fa21f..36f56d2b090 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -51,14 +51,9 @@ extern "C" int gethostname(char *name, int namelen);
static int check_for_max_user_connections(THD *thd, USER_CONN *uc);
static void decrease_user_connections(USER_CONN *uc);
static bool check_db_used(THD *thd,TABLE_LIST *tables);
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
static bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *tables);
static bool single_table_command_access(THD *thd, ulong privilege,
TABLE_LIST *tables, int *res);
-#else
-#define check_merge_table_access(thd, db, tables) false
-#define single_table_command_access(thd, privilege, tables, res) false
-#endif
static void remove_escape(char *name);
static void refresh_status(void);
static bool append_file_to_dir(THD *thd, char **filename_ptr,
@@ -177,7 +172,6 @@ end:
}
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
/*
Check if user exist and password supplied is correct.
@@ -210,6 +204,11 @@ int check_user(THD *thd, enum enum_server_command command,
{
DBUG_ENTER("check_user");
+#ifdef NO_EMBEDDED_ACCESS_CHECKS
+ thd->master_access= GLOBAL_ACLS; // Full rights
+ return 0;
+#else
+
my_bool opt_secure_auth_local;
pthread_mutex_lock(&LOCK_global_system_variables);
opt_secure_auth_local= opt_secure_auth;
@@ -334,7 +333,7 @@ int check_user(THD *thd, enum enum_server_command command,
}
}
else
- send_ok(thd);
+ send_ok(thd);
thd->password= test(passwd_len); // remember for error messages
/* Ready to handle queries */
DBUG_RETURN(0);
@@ -355,11 +354,9 @@ int check_user(THD *thd, enum enum_server_command command,
thd->host_or_ip,
passwd_len ? ER(ER_YES) : ER(ER_NO));
DBUG_RETURN(-1);
+#endif /* NO_EMBEDDED_ACCESS_CHECKS */
}
-#endif /*!NO_EMBEDDED_ACCESS_CHECKS*/
-
-
/*
Check for maximum allowable user connections, if the mysqld server is
started with corresponding variable that is greater then 0.
@@ -510,7 +507,6 @@ bool is_update_query(enum enum_sql_command command)
return uc_update_queries[command];
}
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
/*
Check if maximum queries per hour limit has been reached
returns 0 if OK.
@@ -529,6 +525,9 @@ static bool check_mqh(THD *thd, uint check_command)
DBUG_ENTER("check_mqh");
DBUG_ASSERT(uc != 0);
+#ifdef NO_EMBEDDED_ACCESS_CHECKS
+ DBUG_RETURN(0);
+#else
/* If more than a hour since last check, reset resource checking */
if (check_time - uc->intime >= 3600)
{
@@ -562,12 +561,13 @@ static bool check_mqh(THD *thd, uint check_command)
}
end:
DBUG_RETURN(error);
+#endif /* NO_EMBEDDED_ACCESS_CHECKS */
}
static void reset_mqh(THD *thd, LEX_USER *lu, bool get_them= 0)
{
-
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
(void) pthread_mutex_lock(&LOCK_user_conn);
if (lu) // for GRANT
{
@@ -591,7 +591,8 @@ static void reset_mqh(THD *thd, LEX_USER *lu, bool get_them= 0)
{
for (uint idx=0;idx < hash_user_connections.records; idx++)
{
- USER_CONN *uc=(struct user_conn *) hash_element(&hash_user_connections, idx);
+ USER_CONN *uc=(struct user_conn *) hash_element(&hash_user_connections,
+ idx);
if (get_them)
get_mqh(uc->user,uc->host,uc);
uc->questions=0;
@@ -600,8 +601,8 @@ static void reset_mqh(THD *thd, LEX_USER *lu, bool get_them= 0)
}
}
(void) pthread_mutex_unlock(&LOCK_user_conn);
+#endif /* NO_EMBEDDED_ACCESS_CHECKS */
}
-#endif /*!NO_EMBEDDED_ACCESS_CHECKS*/
/*
Perform handshake, authorize client and update thd ACL variables.
@@ -1066,7 +1067,6 @@ extern "C" pthread_handler_decl(handle_bootstrap,arg)
thd->query= thd->memdup_w_gap(buff, length+1, thd->db_length+1);
thd->query[length] = '\0';
thd->query_id=query_id++;
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (mqh_used && thd->user_connect && check_mqh(thd, SQLCOM_END))
{
thd->net.error = 0;
@@ -1074,7 +1074,6 @@ extern "C" pthread_handler_decl(handle_bootstrap,arg)
free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC));
break;
}
-#endif
mysql_parse(thd,thd->query,length);
close_thread_tables(thd); // Free tables
if (thd->is_fatal_error)
@@ -1138,12 +1137,10 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd)
if (!(table=open_ltable(thd, table_list, TL_READ_NO_INSERT)))
DBUG_RETURN(1);
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (check_access(thd, SELECT_ACL, db, &table_list->grant.privilege,0,0))
goto err;
- if (grant_option && check_grant(thd, SELECT_ACL, table_list))
+ if (grant_option && check_grant(thd, SELECT_ACL, table_list, 0, 0))
goto err;
-#endif
thd->free_list = 0;
thd->query_length=(uint) strlen(tbl_name);
thd->query = tbl_name;
@@ -1447,13 +1444,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
my_casedn_str(files_charset_info, table_list.real_name);
remove_escape(table_list.real_name); // This can't have wildcards
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (check_access(thd,SELECT_ACL,table_list.db,&thd->col_access,0,0))
break;
table_list.grant.privilege=thd->col_access;
- if (grant_option && check_grant(thd,SELECT_ACL,&table_list,2))
+ if (grant_option && check_grant(thd,SELECT_ACL,&table_list,2,0))
break;
-#endif /*DONT_ALLOW_SHOW_COMMANDS*/
mysqld_list_fields(thd,&table_list,fields);
free_items(thd->free_list);
break;
@@ -1599,19 +1594,12 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break;
case COM_PROCESS_INFO:
statistic_increment(com_stat[SQLCOM_SHOW_PROCESSLIST],&LOCK_status);
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (!thd->priv_user[0] && check_global_access(thd,PROCESS_ACL))
break;
-#endif
mysql_log.write(thd,command,NullS);
mysqld_list_processes(thd,
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
thd->master_access & PROCESS_ACL ?
- NullS : thd->priv_user
-#else
- NullS
-#endif
- ,0);
+ NullS : thd->priv_user, 0);
break;
case COM_PROCESS_KILL:
{
@@ -1816,6 +1804,7 @@ mysql_execute_command(THD *thd)
}
}
if (&lex->select_lex != lex->all_selects_list &&
+ lex->sql_command != SQLCOM_CREATE_TABLE &&
lex->unit.create_total_list(thd, lex, &tables, 0))
DBUG_VOID_RETURN;
@@ -1824,11 +1813,7 @@ mysql_execute_command(THD *thd)
Except for the replication thread and the 'super' users.
*/
if (opt_readonly &&
- !(thd->slave_thread
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- || (thd->master_access & SUPER_ACL)
-#endif
- ) &&
+ !(thd->slave_thread || (thd->master_access & SUPER_ACL)) &&
(uc_update_queries[lex->sql_command] > 0))
{
send_error(thd, ER_CANT_UPDATE_WITH_READLOCK);
@@ -1840,7 +1825,6 @@ mysql_execute_command(THD *thd)
case SQLCOM_SELECT:
{
select_result *result=lex->result;
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (tables)
{
res=check_table_access(thd,
@@ -1856,7 +1840,6 @@ mysql_execute_command(THD *thd)
res=0;
break; // Error message is given
}
-#endif
/*
In case of single SELECT unit->global_parameters points on first SELECT
TODO: move counters to SELECT_LEX
@@ -2093,7 +2076,6 @@ mysql_execute_command(THD *thd)
{
if (!tables->db)
tables->db=thd->db;
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (check_access(thd,CREATE_ACL,tables->db,&tables->grant.privilege,0,0))
goto error; /* purecov: inspected */
if (grant_option)
@@ -2101,12 +2083,11 @@ mysql_execute_command(THD *thd)
/* Check that the first table has CREATE privilege */
TABLE_LIST *tmp_table_list=tables->next;
tables->next=0;
- bool error=check_grant(thd,CREATE_ACL,tables);
+ bool error=check_grant(thd,CREATE_ACL,tables,0,0);
tables->next=tmp_table_list;
if (error)
goto error;
}
-#endif
if (strlen(tables->real_name) > NAME_LEN)
{
net_printf(thd,ER_WRONG_TABLE_NAME, tables->real_name);
@@ -2129,43 +2110,34 @@ mysql_execute_command(THD *thd)
case SQLCOM_CREATE_TABLE:
{
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ /* Skip first table, which is the table we are creating */
+ TABLE_LIST *create_table= tables;
+ tables= tables->next;
+ lex->select_lex.table_list.first= (byte*) (tables);
+ create_table->next= 0;
+ if (&lex->select_lex != lex->all_selects_list &&
+ lex->unit.create_total_list(thd, lex, &tables, 0))
+ DBUG_VOID_RETURN;
+
ulong want_priv= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) ?
CREATE_TMP_ACL : CREATE_ACL);
-#endif
- if (!tables->db)
- tables->db=thd->db;
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- if (check_access(thd,want_priv,tables->db,&tables->grant.privilege,0,0) ||
- check_merge_table_access(thd, tables->db,
+ if (check_access(thd, want_priv, create_table->db,
+ &create_table->grant.privilege, 0, 0) ||
+ check_merge_table_access(thd, create_table->db,
(TABLE_LIST *)
lex->create_info.merge_list.first))
goto error; /* purecov: inspected */
- if (grant_option && want_priv != CREATE_TMP_ACL)
- {
- /* Check that the first table has CREATE privilege */
- TABLE_LIST *tmp_table_list=tables->next;
- tables->next=0;
- bool error=check_grant(thd, want_priv, tables);
- tables->next=tmp_table_list;
- if (error)
+ if (grant_option && want_priv != CREATE_TMP_ACL &&
+ check_grant(thd, want_priv, create_table,0,0))
goto error;
- }
-#endif
- if (strlen(tables->real_name) > NAME_LEN)
- {
- net_printf(thd, ER_WRONG_TABLE_NAME, tables->alias);
- res=0;
- break;
- }
#ifndef HAVE_READLINK
lex->create_info.data_file_name=lex->create_info.index_file_name=0;
#else
/* Fix names if symlinked tables */
if (append_file_to_dir(thd, &lex->create_info.data_file_name,
- tables->real_name) ||
+ create_table->real_name) ||
append_file_to_dir(thd,&lex->create_info.index_file_name,
- tables->real_name))
+ create_table->real_name))
{
res=-1;
break;
@@ -2189,49 +2161,42 @@ mysql_execute_command(THD *thd)
select_result *result;
if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) &&
- find_real_table_in_list(tables->next, tables->db, tables->real_name))
+ find_real_table_in_list(tables, create_table->db,
+ create_table->real_name))
{
- net_printf(thd,ER_UPDATE_TABLE_USED,tables->real_name);
+ net_printf(thd,ER_UPDATE_TABLE_USED, create_table->real_name);
DBUG_VOID_RETURN;
}
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- if (tables->next)
- {
- if (check_table_access(thd, SELECT_ACL, tables->next,0))
- goto error; // Error message is given
- }
-#endif
+ if (tables && check_table_access(thd, SELECT_ACL, tables,0))
+ goto error; // Error message is given
select_lex->options|= SELECT_NO_UNLOCK;
unit->offset_limit_cnt= select_lex->offset_limit;
unit->select_limit_cnt= select_lex->select_limit+
select_lex->offset_limit;
if (unit->select_limit_cnt < select_lex->select_limit)
- unit->select_limit_cnt= HA_POS_ERROR; // No limit
+ unit->select_limit_cnt= HA_POS_ERROR; // No limit
- /* Skip first table, which is the table we are creating */
- lex->select_lex.table_list.first=
- (byte*) (((TABLE_LIST *) lex->select_lex.table_list.first)->next);
- if (!(res=open_and_lock_tables(thd,tables->next)))
+ if (!(res=open_and_lock_tables(thd,tables)))
{
- if ((result=new select_create(tables->db ? tables->db : thd->db,
- tables->real_name, &lex->create_info,
+ res= -1; // If error
+ if ((result=new select_create(create_table->db,
+ create_table->real_name,
+ &lex->create_info,
lex->create_list,
lex->key_list,
select_lex->item_list,lex->duplicates)))
res=handle_select(thd, lex, result);
- else
- res= -1;
}
}
else // regular create
{
if (lex->name)
- res= mysql_create_like_table(thd, tables, &lex->create_info,
+ res= mysql_create_like_table(thd, create_table, &lex->create_info,
(Table_ident *)lex->name);
else
{
- res= mysql_create_table(thd,tables->db ? tables->db : thd->db,
- tables->real_name, &lex->create_info,
+ res= mysql_create_table(thd,create_table->db,
+ create_table->real_name, &lex->create_info,
lex->create_list,
lex->key_list,0,0,0); // do logging
}
@@ -2243,12 +2208,10 @@ mysql_execute_command(THD *thd)
case SQLCOM_CREATE_INDEX:
if (!tables->db)
tables->db=thd->db;
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (check_access(thd,INDEX_ACL,tables->db,&tables->grant.privilege,0,0))
goto error; /* purecov: inspected */
- if (grant_option && check_grant(thd,INDEX_ACL,tables))
+ if (grant_option && check_grant(thd,INDEX_ACL,tables,0,0))
goto error;
-#endif
thd->slow_command=TRUE;
if (end_active_trans(thd))
res= -1;
@@ -2316,10 +2279,9 @@ mysql_execute_command(THD *thd)
goto error; /* purecov: inspected */
if (!tables->db)
tables->db=thd->db;
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (grant_option)
{
- if (check_grant(thd,ALTER_ACL,tables))
+ if (check_grant(thd,ALTER_ACL,tables,0,0))
goto error;
if (lex->name && !test_all_bits(priv,INSERT_ACL | CREATE_ACL))
{ // Rename of table
@@ -2328,11 +2290,10 @@ mysql_execute_command(THD *thd)
tmp_table.real_name=lex->name;
tmp_table.db=select_lex->db;
tmp_table.grant.privilege=priv;
- if (check_grant(thd,INSERT_ACL | CREATE_ACL,tables))
+ if (check_grant(thd,INSERT_ACL | CREATE_ACL,tables,0,0))
goto error;
}
}
-#endif
/* Don't yet allow changing of symlinks with ALTER TABLE */
lex->create_info.data_file_name=lex->create_info.index_file_name=0;
/* ALTER TABLE ends previous transaction */
@@ -2360,7 +2321,6 @@ mysql_execute_command(THD *thd)
TABLE_LIST *table;
if (check_db_used(thd,tables))
goto error;
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
for (table=tables ; table ; table=table->next->next)
{
if (check_access(thd, ALTER_ACL | DROP_ACL, table->db,
@@ -2374,14 +2334,13 @@ mysql_execute_command(THD *thd)
old_list=table[0];
new_list=table->next[0];
old_list.next=new_list.next=0;
- if (check_grant(thd,ALTER_ACL,&old_list) ||
+ if (check_grant(thd,ALTER_ACL,&old_list,0,0) ||
(!test_all_bits(table->next->grant.privilege,
INSERT_ACL | CREATE_ACL) &&
- check_grant(thd,INSERT_ACL | CREATE_ACL, &new_list)))
+ check_grant(thd,INSERT_ACL | CREATE_ACL, &new_list,0,0)))
goto error;
}
}
-#endif
query_cache_invalidate3(thd, tables, 0);
if (end_active_trans(thd))
res= -1;
@@ -2535,12 +2494,10 @@ mysql_execute_command(THD *thd)
res= -1;
break;
case SQLCOM_UPDATE_MULTI:
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (check_access(thd,UPDATE_ACL,tables->db,&tables->grant.privilege,0,0))
goto error;
- if (grant_option && check_grant(thd,UPDATE_ACL,tables))
+ if (grant_option && check_grant(thd,UPDATE_ACL,tables,0,0))
goto error;
-#endif
if (select_lex->item_list.elements != lex->value_list.elements)
{
send_error(thd,ER_WRONG_VALUE_COUNT);
@@ -2570,16 +2527,12 @@ mysql_execute_command(THD *thd)
case SQLCOM_REPLACE:
case SQLCOM_INSERT:
{
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
my_bool update=(lex->value_list.elements ? UPDATE_ACL : 0);
ulong privilege= (lex->duplicates == DUP_REPLACE ?
INSERT_ACL | DELETE_ACL : INSERT_ACL | update);
if (single_table_command_access(thd, privilege, tables, &res))
goto error;
-#else
- my_bool update=(lex->value_list.elements ? 1 : 0);
-#endif
if (select_lex->item_list.elements != lex->value_list.elements)
{
send_error(thd,ER_WRONG_VALUE_COUNT);
@@ -2595,12 +2548,10 @@ mysql_execute_command(THD *thd)
case SQLCOM_REPLACE_SELECT:
case SQLCOM_INSERT_SELECT:
{
-
/*
Check that we have modify privileges for the first table and
select privileges for the rest
*/
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
{
ulong privilege= (lex->duplicates == DUP_REPLACE ?
INSERT_ACL | DELETE_ACL : INSERT_ACL);
@@ -2608,14 +2559,18 @@ mysql_execute_command(THD *thd)
tables->next=0;
if (check_access(thd, privilege,
tables->db,&tables->grant.privilege,0,0) ||
- (grant_option && check_grant(thd, privilege, tables)))
+ (grant_option && check_grant(thd, privilege, tables,0,0)))
goto error;
tables->next=save_next;
if ((res=check_table_access(thd, SELECT_ACL, save_next,0)))
goto error;
}
-#endif
+
+ /* Fix lock for first table */
+ if (tables->lock_type == TL_WRITE_DELAYED)
+ tables->lock_type = TL_WRITE;
+
/* Don't unlock tables until command is written to binary log */
select_lex->options|= SELECT_NO_UNLOCK;
@@ -2649,12 +2604,10 @@ mysql_execute_command(THD *thd)
break;
}
case SQLCOM_TRUNCATE:
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (check_access(thd,DELETE_ACL,tables->db,&tables->grant.privilege,0,0))
goto error; /* purecov: inspected */
- if (grant_option && check_grant(thd,DELETE_ACL,tables))
+ if (grant_option && check_grant(thd,DELETE_ACL,tables,0,0))
goto error;
-#endif
/*
Don't allow this within a transaction because we want to use
re-generate table
@@ -2668,12 +2621,10 @@ mysql_execute_command(THD *thd)
break;
case SQLCOM_DELETE:
{
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (single_table_command_access(thd, DELETE_ACL, tables, &res))
goto error;
// Set privilege for the WHERE clause
tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege);
-#endif
res = mysql_delete(thd,tables, select_lex->where,
(ORDER*) select_lex->order_list.first,
select_lex->select_limit, select_lex->options);
@@ -2795,12 +2746,10 @@ mysql_execute_command(THD *thd)
case SQLCOM_DROP_INDEX:
if (!tables->db)
tables->db=thd->db;
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (check_access(thd,INDEX_ACL,tables->db,&tables->grant.privilege,0,0))
goto error; /* purecov: inspected */
- if (grant_option && check_grant(thd,INDEX_ACL,tables))
+ if (grant_option && check_grant(thd,INDEX_ACL,tables,0,0))
goto error;
-#endif
if (end_active_trans(thd))
res= -1;
else
@@ -2818,18 +2767,11 @@ mysql_execute_command(THD *thd)
break;
#endif
case SQLCOM_SHOW_PROCESSLIST:
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (!thd->priv_user[0] && check_global_access(thd,PROCESS_ACL))
break;
-#endif
mysqld_list_processes(thd,
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
thd->master_access & PROCESS_ACL ? NullS :
- thd->priv_user
-#else
- NullS
-#endif
- ,lex->verbose);
+ thd->priv_user,lex->verbose);
break;
case SQLCOM_SHOW_STORAGE_ENGINES:
res= mysqld_show_storage_engines(thd);
@@ -2855,10 +2797,8 @@ mysql_execute_command(THD *thd)
DBUG_VOID_RETURN;
#else
{
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (grant_option && check_access(thd, FILE_ACL, any_db,0,0,0))
goto error;
-#endif
res= mysqld_show_logs(thd);
break;
}
@@ -2882,7 +2822,6 @@ mysql_execute_command(THD *thd)
net_printf(thd,ER_WRONG_DB_NAME, db);
goto error;
}
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (check_access(thd,SELECT_ACL,db,&thd->col_access,0,0))
goto error; /* purecov: inspected */
if (!thd->col_access && check_grant_db(thd,db))
@@ -2893,7 +2832,6 @@ mysql_execute_command(THD *thd)
db);
goto error;
}
-#endif
/* grant is checked in mysqld_show_tables */
if (select_lex->options & SELECT_DESCRIBE)
res= mysqld_extend_show_tables(thd,db,
@@ -2927,13 +2865,11 @@ mysql_execute_command(THD *thd)
}
remove_escape(db); // Fix escaped '_'
remove_escape(tables->real_name);
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (check_access(thd,SELECT_ACL | EXTRA_ACL,db,&thd->col_access,0,0))
goto error; /* purecov: inspected */
tables->grant.privilege=thd->col_access;
- if (grant_option && check_grant(thd,SELECT_ACL,tables,2))
+ if (grant_option && check_grant(thd,SELECT_ACL,tables,2,0))
goto error;
-#endif
res= mysqld_show_fields(thd,tables,
(lex->wild ? lex->wild->ptr() : NullS),
lex->verbose);
@@ -2956,13 +2892,11 @@ mysql_execute_command(THD *thd)
remove_escape(tables->real_name);
if (!tables->db)
tables->db=thd->db;
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (check_access(thd,SELECT_ACL,db,&thd->col_access,0,0))
goto error; /* purecov: inspected */
tables->grant.privilege=thd->col_access;
- if (grant_option && check_grant(thd,SELECT_ACL,tables,2))
+ if (grant_option && check_grant(thd,SELECT_ACL,tables,2,0))
goto error;
-#endif
res= mysqld_show_keys(thd,tables);
break;
}
@@ -2973,7 +2907,6 @@ mysql_execute_command(THD *thd)
case SQLCOM_LOAD:
{
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
uint privilege= (lex->duplicates == DUP_REPLACE ?
INSERT_ACL | DELETE_ACL : INSERT_ACL);
@@ -2990,11 +2923,11 @@ mysql_execute_command(THD *thd)
send_error(thd,ER_NOT_ALLOWED_COMMAND);
goto error;
}
- if (check_access(thd,privilege,tables->db,&tables->grant.privilege,0,0) ||
- grant_option && check_grant(thd,privilege,tables))
+ if (check_access(thd,privilege,tables->db,&tables->grant.privilege,0,
+ 0) ||
+ grant_option && check_grant(thd,privilege,tables,0,0))
goto error;
}
-#endif /*NO_EMBEDDED_ACCESS_CHECKS*/
res=mysql_load(thd, lex->exchange, tables, lex->field_list,
lex->duplicates, (bool) lex->local_file, lex->lock_option);
break;
@@ -3238,7 +3171,7 @@ mysql_execute_command(THD *thd)
if (grant_option && check_grant(thd,
(lex->grant | lex->grant_tot_col |
GRANT_ACL),
- tables))
+ tables,0,0))
goto error;
if (!(res = mysql_table_grant(thd,tables,lex->users_list, lex->columns,
lex->grant,
@@ -3247,6 +3180,7 @@ mysql_execute_command(THD *thd)
mysql_update_log.write(thd, thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
+ thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo);
}
@@ -3267,6 +3201,7 @@ mysql_execute_command(THD *thd)
mysql_update_log.write(thd, thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
+ thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo);
}
@@ -3444,7 +3379,6 @@ error:
}
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
/*
Check grants for commands which work only with one table and all other
tables belong to subselects.
@@ -3465,23 +3399,23 @@ static bool single_table_command_access(THD *thd, ulong privilege,
TABLE_LIST *tables, int *res)
{
- if (check_access(thd, privilege, tables->db, &tables->grant.privilege,0,0))
- return 1;
+ if (check_access(thd, privilege, tables->db, &tables->grant.privilege,0,0))
+ return 1;
- // Show only 1 table for check_grant
- TABLE_LIST *subselects_tables= tables->next;
- tables->next= 0;
- if (grant_option && check_grant(thd, privilege, tables))
- return 1;
+ // Show only 1 table for check_grant
+ TABLE_LIST *subselects_tables= tables->next;
+ tables->next= 0;
+ if (grant_option && check_grant(thd, privilege, tables, 0, 0))
+ return 1;
- // check rights on tables of subselect (if exists)
- if (subselects_tables)
- {
- tables->next= subselects_tables;
- if ((*res= check_table_access(thd, SELECT_ACL, subselects_tables,0)))
- return 1;
- }
- return 0;
+ // check rights on tables of subselect (if exists)
+ if (subselects_tables)
+ {
+ tables->next= subselects_tables;
+ if ((*res= check_table_access(thd, SELECT_ACL, subselects_tables,0)))
+ return 1;
+ }
+ return 0;
}
@@ -3524,6 +3458,9 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
DBUG_RETURN(TRUE); /* purecov: tested */
}
+#ifdef NO_EMBEDDED_ACCESS_CHECKS
+ DBUG_RETURN(0);
+#else
if ((thd->master_access & want_access) == want_access)
{
/*
@@ -3573,6 +3510,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
thd->priv_host,
db ? db : thd->db ? thd->db : "unknown"); /* purecov: tested */
DBUG_RETURN(TRUE); /* purecov: tested */
+#endif /* NO_EMBEDDED_ACCESS_CHECKS */
}
@@ -3597,6 +3535,9 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
bool check_global_access(THD *thd, ulong want_access)
{
+#ifdef NO_EMBEDDED_ACCESS_CHECKS
+ return 0;
+#else
char command[128];
if ((thd->master_access & want_access))
return 0;
@@ -3604,6 +3545,7 @@ bool check_global_access(THD *thd, ulong want_access)
net_printf(thd,ER_SPECIFIC_ACCESS_DENIED_ERROR,
command);
return 1;
+#endif /* NO_EMBEDDED_ACCESS_CHECKS */
}
@@ -3668,7 +3610,6 @@ static bool check_merge_table_access(THD *thd, char *db,
return error;
}
-#endif /*!NO_EMBEDDED_ACCESS_CHECKS*/
static bool check_db_used(THD *thd,TABLE_LIST *tables)
{
@@ -3780,7 +3721,9 @@ mysql_init_query(THD *thd)
thd->last_insert_id_used= thd->query_start_used= thd->insert_id_used=0;
thd->sent_row_count= thd->examined_row_count= 0;
thd->is_fatal_error= thd->rand_used= 0;
- thd->server_status &= ~SERVER_MORE_RESULTS_EXISTS;
+ thd->server_status&= ~ (SERVER_MORE_RESULTS_EXISTS |
+ SERVER_QUERY_NO_INDEX_USED |
+ SERVER_QUERY_NO_GOOD_INDEX_USED);
thd->tmp_table_used= 0;
if (opt_bin_log)
reset_dynamic(&thd->user_var_events);
@@ -3925,9 +3868,7 @@ mysql_parse(THD *thd, char *inBuf, uint length)
else
{
mysql_execute_command(thd);
-#ifndef EMBEDDED_LIBRARY /* TODO query cache in embedded library*/
query_cache_end_of_result(&thd->net);
-#endif
}
}
}
@@ -3935,9 +3876,7 @@ mysql_parse(THD *thd, char *inBuf, uint length)
{
DBUG_PRINT("info",("Command aborted. Fatal_error: %d",
thd->is_fatal_error));
-#ifndef EMBEDDED_LIBRARY /* TODO query cache in embedded library*/
query_cache_abort(&thd->net);
-#endif
}
thd->proc_info="freeing items";
free_items(thd->free_list); /* Free strings used by items */
@@ -3987,7 +3926,12 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
if (default_value)
{
- if (default_value->type() == Item::NULL_ITEM)
+ if (type == FIELD_TYPE_TIMESTAMP)
+ {
+ net_printf(thd, ER_INVALID_DEFAULT, field_name);
+ DBUG_RETURN(1);
+ }
+ else if (default_value->type() == Item::NULL_ITEM)
{
default_value=0;
if ((type_modifier & (NOT_NULL_FLAG | AUTO_INCREMENT_FLAG)) ==
@@ -4653,10 +4597,8 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
UNLOCK_ACTIVE_MI;
}
#endif
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (options & REFRESH_USER_RESOURCES)
reset_mqh(thd,(LEX_USER *) NULL);
-#endif
if (write_to_binlog)
*write_to_binlog= tmp_write_to_binlog;
return result;
@@ -4691,18 +4633,14 @@ void kill_one_thread(THD *thd, ulong id)
VOID(pthread_mutex_unlock(&LOCK_thread_count));
if (tmp)
{
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
if ((thd->master_access & SUPER_ACL) ||
!strcmp(thd->user,tmp->user))
-#endif
{
tmp->awake(1 /*prepare to die*/);
error=0;
}
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
else
error=ER_KILL_DENIED_ERROR;
-#endif
pthread_mutex_unlock(&tmp->LOCK_delete);
}
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 790b80eb127..58e6dbff1ed 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -544,7 +544,7 @@ static bool mysql_test_insert_fields(PREP_STMT *stmt,
if (check_access(thd,privilege,table_list->db,
&table_list->grant.privilege,0,0) ||
- (grant_option && check_grant(thd,privilege,table_list)))
+ (grant_option && check_grant(thd,privilege,table_list,0,0)))
DBUG_RETURN(1);
#endif
if (open_and_lock_tables(thd, table_list))
@@ -599,7 +599,7 @@ static bool mysql_test_upd_fields(PREP_STMT *stmt, TABLE_LIST *table_list,
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (check_access(thd,UPDATE_ACL,table_list->db,
&table_list->grant.privilege,0,0) ||
- (grant_option && check_grant(thd,UPDATE_ACL,table_list)))
+ (grant_option && check_grant(thd,UPDATE_ACL,table_list,0,0)))
DBUG_RETURN(1);
#endif
if (open_and_lock_tables(thd, table_list))
diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc
index 19b4d299e59..3ab6621f35b 100644
--- a/sql/sql_rename.cc
+++ b/sql/sql_rename.cc
@@ -82,6 +82,7 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list)
mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
+ thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo);
}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 0bf493ee953..16b9a341ee5 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1119,8 +1119,21 @@ JOIN::exec()
if (select_options & SELECT_DESCRIBE)
{
- if (!order && !no_order)
- order=group_list;
+ /*
+ Check if we managed to optimize ORDER BY away and don't use temporary
+ table to resolve ORDER BY: in that case, we only may need to do
+ filesort for GROUP BY.
+ */
+ if (!order && !no_order && (!skip_sort_order || !need_tmp))
+ {
+ /*
+ Reset 'order' to 'group_list' and reinit variables describing
+ 'order'
+ */
+ order= group_list;
+ simple_order= simple_group;
+ skip_sort_order= 0;
+ }
if (order &&
(const_tables == tables ||
((simple_order || skip_sort_order) &&
@@ -1859,7 +1872,8 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
} while (keyuse->table == table && keyuse->key == key);
if (eq_part.is_prefix(table->key_info[key].key_parts) &&
- (table->key_info[key].flags & HA_NOSAME) &&
+ ((table->key_info[key].flags & (HA_NOSAME | HA_END_SPACE_KEY)) ==
+ HA_NOSAME) &&
!table->fulltext_searched)
{
if (const_ref == eq_part)
@@ -2343,10 +2357,6 @@ add_key_part(DYNAMIC_ARRAY *keyuse_array,KEY_FIELD *key_field)
}
}
}
- /* Mark that we can optimize LEFT JOIN */
- if (key_field->val->type() == Item::NULL_ITEM &&
- !key_field->field->real_maybe_null())
- key_field->field->table->reginfo.not_exists_optimize=1;
}
@@ -2445,15 +2455,28 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
SELECT_LEX *select_lex)
{
uint and_level,i,found_eq_constant;
- KEY_FIELD *key_fields,*end;
+ KEY_FIELD *key_fields, *end, *field;
if (!(key_fields=(KEY_FIELD*)
thd->alloc(sizeof(key_fields[0])*
(thd->lex.current_select->cond_count+1)*2)))
return TRUE; /* purecov: inspected */
- and_level=0; end=key_fields;
+ and_level= 0;
+ field= end= key_fields;
+ if (my_init_dynamic_array(keyuse,sizeof(KEYUSE),20,64))
+ return TRUE;
if (cond)
+ {
add_key_fields(join_tab,&end,&and_level,cond,normal_tables);
+ for (; field != end ; field++)
+ {
+ add_key_part(keyuse,field);
+ /* Mark that we can optimize LEFT JOIN */
+ if (field->val->type() == Item::NULL_ITEM &&
+ !field->field->real_maybe_null())
+ field->field->table->reginfo.not_exists_optimize=1;
+ }
+ }
for (i=0 ; i < tables ; i++)
{
if (join_tab[i].on_expr)
@@ -2462,10 +2485,8 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
join_tab[i].table->map);
}
}
- if (my_init_dynamic_array(keyuse,sizeof(KEYUSE),20,64))
- return TRUE;
/* fill keyuse with found key parts */
- for (KEY_FIELD *field=key_fields ; field != end ; field++)
+ for ( ; field != end ; field++)
add_key_part(keyuse,field);
if (select_lex->ftfunc_list->elements)
@@ -2715,7 +2736,8 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
!found_ref_or_null)
{ /* use eq key */
max_key_part= (uint) ~0;
- if ((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME)
+ if ((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY |
+ HA_END_SPACE_KEY)) == HA_NOSAME)
{
tmp=prev_record_reads(join,found_ref);
records=1.0;
@@ -3228,9 +3250,9 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
return 0;
if (j->type == JT_CONST)
j->table->const_table= 1;
- else if (((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY))
- != HA_NOSAME) || keyparts != keyinfo->key_parts ||
- null_ref_key)
+ else if (((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY |
+ HA_END_SPACE_KEY)) != HA_NOSAME) ||
+ keyparts != keyinfo->key_parts || null_ref_key)
{
/* Must read with repeat */
j->type= null_ref_key ? JT_REF_OR_NULL : JT_REF;
@@ -4051,6 +4073,8 @@ return_zero_rows(JOIN *join, select_result *result,TABLE_LIST *tables,
}
result->send_eof(); // Should be safe
}
+ /* Update results for FOUND_ROWS */
+ join->thd->limit_found_rows= join->thd->examined_row_count= 0;
DBUG_RETURN(0);
}
@@ -6764,7 +6788,7 @@ part_of_refkey(TABLE *table,Field *field)
for (uint part=0 ; part < ref_parts ; part++,key_part++)
if (field->eq(key_part->field) &&
- !(key_part->key_part_flag & HA_PART_KEY))
+ !(key_part->key_part_flag & HA_PART_KEY_SEG))
return table->reginfo.join_tab->ref.items[part];
}
return (Item*) 0;
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index c3996f142ad..52f7e6cb9ed 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -384,11 +384,23 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path,
#ifdef USE_SYMDIR
char *ext;
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;
*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
#endif
{
- if (file->name[0] == '.' || !MY_S_ISDIR(file->mystat.st_mode) ||
+ if (file->name[0] == '.' || !MY_S_ISDIR(file->mystat->st_mode) ||
(wild && wild_compare(file->name,wild,0)))
continue;
}
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index a7a3e325bd9..d61a52003ec 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -260,6 +260,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
mysql_update_log.write(thd, thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
+ thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length,
tmp_table_deleted && !some_tables_deleted);
mysql_bin_log.write(&qinfo);
@@ -310,10 +311,10 @@ static int sort_keys(KEY *a, KEY *b)
{
if (!(b->flags & HA_NOSAME))
return -1;
- if ((a->flags ^ b->flags) & HA_NULL_PART_KEY)
+ if ((a->flags ^ b->flags) & (HA_NULL_PART_KEY | HA_END_SPACE_KEY))
{
/* Sort NOT NULL keys before other keys */
- return (a->flags & HA_NULL_PART_KEY) ? 1 : -1;
+ return (a->flags & (HA_NULL_PART_KEY | HA_END_SPACE_KEY)) ? 1 : -1;
}
if (a->name == primary_key_name)
return -1;
@@ -993,6 +994,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
mysql_update_log.write(thd,thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
+ thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length,
test(create_info->options &
HA_LEX_CREATE_TMP_TABLE));
@@ -2082,6 +2084,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
mysql_update_log.write(thd, thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
+ thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo);
}
@@ -2465,6 +2468,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
mysql_update_log.write(thd, thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
+ thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo);
}
@@ -2596,6 +2600,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
mysql_update_log.write(thd, thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
+ thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo);
}
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 95dff107350..7dc537768f3 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -352,6 +352,8 @@ int mysql_update(THD *thd,
mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
+ if (error <= 0)
+ thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length,
log_delayed);
if (mysql_bin_log.write(&qinfo) && transactional_table)
@@ -473,7 +475,7 @@ multi_update::multi_update(THD *thd_arg, TABLE_LIST *table_list,
:all_tables(table_list), update_tables(0), thd(thd_arg), tmp_tables(0),
updated(0), found(0), fields(field_list), values(value_list),
table_count(0), copy_field(0), handle_duplicates(handle_duplicates_arg),
- do_update(1), trans_safe(0)
+ do_update(1), trans_safe(0), transactional_tables(1)
{}
@@ -577,6 +579,27 @@ int multi_update::prepare(List<Item> &not_used_values,
for (i=0 ; i < table_count ; i++)
set_if_bigger(max_fields, fields_for_table[i]->elements);
copy_field= new Copy_field[max_fields];
+
+ /*
+ Mark all copies of tables that are updates to ensure that
+ init_read_record() will not try to enable a cache on them
+
+ The problem is that for queries like
+
+ UPDATE t1, t1 AS t2 SET t1.b=t2.c WHERE t1.a=t2.a;
+
+ the row buffer may contain things that doesn't match what is on disk
+ which will cause an error when reading a row.
+ (This issue is mostly relevent for MyISAM tables)
+ */
+ for (table_ref= all_tables; table_ref; table_ref=table_ref->next)
+ {
+ TABLE *table=table_ref->table;
+ if (!(tables_to_update & table->map) &&
+ find_real_table_in_list(update_tables, table_ref->db,
+ table_ref->real_name))
+ table->no_cache= 1; // Disable row cache
+ }
DBUG_RETURN(thd->is_fatal_error != 0);
}
@@ -718,7 +741,7 @@ multi_update::~multi_update()
{
TABLE_LIST *table;
for (table= update_tables ; table; table= table->next)
- table->table->no_keyread=0;
+ table->table->no_keyread= table->table->no_cache= 0;
if (tmp_tables)
{
@@ -853,8 +876,11 @@ int multi_update::do_updates(bool from_send_error)
ha_rows org_updated;
TABLE *table;
DBUG_ENTER("do_updates");
+
- do_update= 0; // Don't retry this function
+ do_update= 0; // Don't retry this function
+ if (!found)
+ DBUG_RETURN(0);
for (cur_table= update_tables; cur_table ; cur_table= cur_table->next)
{
table = cur_table->table;
@@ -981,6 +1007,8 @@ bool multi_update::send_eof()
mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
+ if (local_error <= 0)
+ thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length,
log_delayed);
if (mysql_bin_log.write(&qinfo) && trans_safe)
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 6fb71730559..a1e3c566826 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -581,9 +581,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%left SHIFT_LEFT SHIFT_RIGHT
%left '-' '+'
%left '*' '/' '%' DIV_SYM MOD_SYM
-%left NEG '~'
%left XOR
%left '^'
+%left NEG '~'
%right NOT
%right BINARY COLLATE_SYM
@@ -5506,6 +5506,7 @@ order_or_limit:
union_option:
/* empty */ {}
+ | DISTINCT {}
| ALL {Select->master_unit()->union_option|= UNION_ALL;};
singlerow_subselect:
diff --git a/sql/table.cc b/sql/table.cc
index 7c12762d9c4..912c133e571 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -507,14 +507,17 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
if (primary_key >= MAX_KEY && (keyinfo->flags & HA_NOSAME))
{
/*
- If the UNIQUE key don't have NULL columns, declare this as
- a primary key.
+ If the UNIQUE key doesn't have NULL columns and is not a part key
+ declare this as a primary key.
*/
primary_key=key;
for (i=0 ; i < keyinfo->key_parts ;i++)
{
- if (!key_part[i].fieldnr ||
- outparam->field[key_part[i].fieldnr-1]->null_ptr)
+ uint fieldnr= key_part[i].fieldnr;
+ if (!fieldnr ||
+ outparam->field[fieldnr-1]->null_ptr ||
+ outparam->field[fieldnr-1]->key_length() !=
+ key_part[i].length)
{
primary_key=MAX_KEY; // Can't be used
break;
@@ -554,6 +557,12 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
keyinfo->extra_length+=HA_KEY_BLOB_LENGTH;
key_part->store_length+=HA_KEY_BLOB_LENGTH;
keyinfo->key_length+= HA_KEY_BLOB_LENGTH;
+ /*
+ Mark that there may be many matching values for one key
+ combination ('a', 'a ', 'a '...)
+ */
+ if (!(field->flags & BINARY_FLAG))
+ keyinfo->flags|= HA_END_SPACE_KEY;
}
if (i == 0 && key != primary_key)
field->flags |=
@@ -591,7 +600,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
}
if (field->key_length() != key_part->length)
{
- key_part->key_part_flag|= HA_PART_KEY;
+ key_part->key_part_flag|= HA_PART_KEY_SEG;
if (!(field->flags & BLOB_FLAG))
{ // Create a new field
field=key_part->field=field->new_field(&outparam->mem_root,
@@ -605,7 +614,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
as we need to test for NULL = NULL.
*/
if (field->real_maybe_null())
- key_part->key_part_flag|= HA_PART_KEY;
+ key_part->key_part_flag|= HA_PART_KEY_SEG;
}
else
{ // Error: shorten key
@@ -1237,14 +1246,17 @@ bool get_field(MEM_ROOT *mem, Field *field, String *res)
char *get_field(MEM_ROOT *mem, Field *field)
{
- char buff[MAX_FIELD_WIDTH];
+ char buff[MAX_FIELD_WIDTH], *to;
String str(buff,sizeof(buff),&my_charset_bin);
uint length;
field->val_str(&str,&str);
- if (!(length= str.length()))
+ length= str.length();
+ if (!length || !(to= (char*) alloc_root(mem,length+1)))
return NullS;
- return strmake_root(mem, str.ptr(), length);
+ memcpy(to,str.ptr(),(uint) length);
+ to[length]=0;
+ return to;
}
diff --git a/sql/table.h b/sql/table.h
index 4dcd24b2aff..00fe803cde2 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -116,7 +116,7 @@ struct st_table {
my_bool fulltext_searched;
my_bool crashed;
my_bool is_view;
- my_bool no_keyread;
+ my_bool no_keyread, no_cache;
my_bool clear_query_id; /* To reset query_id for tables and cols */
my_bool auto_increment_field_not_null;
Field *next_number_field, /* Set if next_number is activated */
diff --git a/sql/time.cc b/sql/time.cc
index fe22b80d59d..9a18a150c50 100644
--- a/sql/time.cc
+++ b/sql/time.cc
@@ -124,6 +124,8 @@ long my_gmt_sec(TIME *t, long *my_timezone)
tmp-=t->minute*60 + t->second; // Move to previous hour
}
*my_timezone= current_timezone;
+ if (tmp < 0 && t->year <= 1900+YY_PART_YEAR)
+ tmp= 0;
return (long) tmp;
} /* my_gmt_sec */
@@ -174,42 +176,72 @@ uint calc_days_in_year(uint year)
366 : 365;
}
-/* Calculate week. If 'with_year' is not set, then return a week 0-53, where
- 0 means that it's the last week of the previous year.
- If 'with_year' is set then the week will always be in the range 1-53 and
- the year out parameter will contain the year for the week */
-uint calc_week(TIME *l_time, bool with_year, bool sunday_first_day_of_week,
- uint *year)
+/*
+ The bits in week_format has the following meaning:
+ WEEK_MONDAY_FIRST (0) If not set Sunday is first day of week
+ If set Monday is first day of week
+ WEEK_YEAR (1) If not set Week is in range 0-53
+
+ Week 0 is returned for the the last week of the previous year (for
+ a date at start of january) In this case one can get 53 for the
+ first week of next year. This flag ensures that the week is
+ relevant for the given year. Note that this flag is only
+ releveant if WEEK_JANUARY is not set.
+
+ If set Week is in range 1-53.
+
+ In this case one may get week 53 for a date in January (when
+ the week is that last week of previous year) and week 1 for a
+ date in December.
+
+ WEEK_FIRST_WEEKDAY (2) If not set Weeks are numbered according
+ to ISO 8601:1988
+ If set The week that contains the first
+ 'first-day-of-week' is week 1.
+
+ ISO 8601:1988 means that if the week containing January 1 has
+ four or more days in the new year, then it is week 1;
+ Otherwise it is the last week of the previous year, and the
+ next week is week 1.
+*/
+
+uint calc_week(TIME *l_time, uint week_behaviour, uint *year)
{
uint days;
ulong daynr=calc_daynr(l_time->year,l_time->month,l_time->day);
ulong first_daynr=calc_daynr(l_time->year,1,1);
- uint weekday=calc_weekday(first_daynr,sunday_first_day_of_week);
+ bool monday_first= test(week_behaviour & WEEK_MONDAY_FIRST);
+ bool week_year= test(week_behaviour & WEEK_YEAR);
+ bool first_weekday= test(week_behaviour & WEEK_FIRST_WEEKDAY);
+
+ uint weekday=calc_weekday(first_daynr, !monday_first);
*year=l_time->year;
- if (l_time->month == 1 && l_time->day <= 7-weekday &&
- ((!sunday_first_day_of_week && weekday >= 4) ||
- (sunday_first_day_of_week && weekday != 0)))
+
+ if (l_time->month == 1 && l_time->day <= 7-weekday)
{
- /* Last week of the previous year */
- if (!with_year)
+ if (!week_year &&
+ (first_weekday && weekday != 0 ||
+ !first_weekday && weekday >= 4))
return 0;
- with_year=0; // Don't check the week again
+ week_year= 1;
(*year)--;
first_daynr-= (days=calc_days_in_year(*year));
weekday= (weekday + 53*7- days) % 7;
}
- if ((sunday_first_day_of_week && weekday != 0) ||
- (!sunday_first_day_of_week && weekday >= 4))
+
+ if ((first_weekday && weekday != 0) ||
+ (!first_weekday && weekday >= 4))
days= daynr - (first_daynr+ (7-weekday));
else
days= daynr - (first_daynr - weekday);
- if (with_year && days >= 52*7)
+
+ if (week_year && days >= 52*7)
{
- /* Check if we are on the first week of the next year (or week 53) */
weekday= (weekday + calc_days_in_year(*year)) % 7;
- if (weekday < 4)
- { // We are at first week on next year
+ if (!first_weekday && weekday < 4 ||
+ first_weekday && weekday == 0)
+ {
(*year)++;
return 1;
}
@@ -605,7 +637,7 @@ time_t str_to_timestamp(const char *str,uint length)
if (str_to_TIME(str,length,&l_time,0) <= TIMESTAMP_DATETIME_ERROR)
return(0);
- if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR)
+ if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR-1)
{
current_thd->cuted_fields++;
return(0);
diff --git a/sql/uniques.cc b/sql/uniques.cc
index f289fd11f5b..d060965aa66 100644
--- a/sql/uniques.cc
+++ b/sql/uniques.cc
@@ -37,14 +37,20 @@
int unique_write_to_file(gptr key, element_count count, Unique *unique)
{
+ /*
+ Use unique->size (size of element stored in the tree) and not
+ unique->tree.size_of_element. The latter is different from unique->size
+ when tree implementation chooses to store pointer to key in TREE_ELEMENT
+ (instead of storing the element itself there)
+ */
return my_b_write(&unique->file, (byte*) key,
- unique->tree.size_of_element) ? 1 : 0;
+ unique->size) ? 1 : 0;
}
int unique_write_to_ptrs(gptr key, element_count count, Unique *unique)
{
- memcpy(unique->record_pointers, key, unique->tree.size_of_element);
- unique->record_pointers+=unique->tree.size_of_element;
+ memcpy(unique->record_pointers, key, unique->size);
+ unique->record_pointers+=unique->size;
return 0;
}
@@ -132,8 +138,8 @@ bool Unique::get(TABLE *table)
bzero((char*) &sort_param,sizeof(sort_param));
sort_param.max_rows= elements;
sort_param.sort_form=table;
- sort_param.rec_length= sort_param.sort_length=sort_param.ref_length=
- tree.size_of_element;
+ sort_param.rec_length= sort_param.sort_length= sort_param.ref_length=
+ size;
sort_param.keys= max_in_memory_size / sort_param.sort_length;
sort_param.not_killable=1;
diff --git a/strings/strto.c b/strings/strto.c
index 0c215ff270c..6f12656cb20 100644
--- a/strings/strto.c
+++ b/strings/strto.c
@@ -35,8 +35,6 @@
it can be compiled with the UNSIGNED and/or LONGLONG flag set
*/
-#define strtoll glob_strtoll /* Fix for True64 */
-
#include <my_global.h>
#include "m_string.h"
#include "m_ctype.h"
diff --git a/strings/strtoll.c b/strings/strtoll.c
index 8d0ba21d576..b0b4ef328fc 100644
--- a/strings/strtoll.c
+++ b/strings/strtoll.c
@@ -16,8 +16,9 @@
/* This is defines strtoll() if neaded */
+#define strtoll glob_strtoll /* Fix for True64 */
+
#include <my_global.h>
-#include <m_string.h>
#if !defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
#define USE_LONGLONG
#include "strto.c"
diff --git a/strings/strtoull.c b/strings/strtoull.c
index 25201e546ce..f4f3ce19bf7 100644
--- a/strings/strtoull.c
+++ b/strings/strtoull.c
@@ -17,7 +17,6 @@
/* This is defines strtoull() */
#include <my_global.h>
-#include <m_string.h>
#if !defined(HAVE_STRTOULL) && defined(HAVE_LONG_LONG)
#define USE_UNSIGNED
#define USE_LONGLONG
diff --git a/support-files/MacOSX/MySQL b/support-files/MacOSX/MySQL
index dfba5f8f982..f6579700384 100755
--- a/support-files/MacOSX/MySQL
+++ b/support-files/MacOSX/MySQL
@@ -11,6 +11,13 @@
# Written by Lenz Grimmer <lenz@mysql.com>
#
+# Suppress the annoying "$1: unbound variable" error when no option
+# was given
+if [ -z $1 ] ; then
+ echo "Usage: $0 [start|stop|restart] "
+ exit 1
+fi
+
# Source the common setup functions for startup scripts
test -r /etc/rc.common || exit 1
. /etc/rc.common
diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh
index 30ee4ab545f..5911ecd942b 100644
--- a/support-files/mysql.server.sh
+++ b/support-files/mysql.server.sh
@@ -145,7 +145,7 @@ case "$mode" in
then
# Give extra arguments to mysqld with the my.cnf file. This script may
# be overwritten at next upgrade.
- $bindir/mysqld_safe --datadir=$datadir --pid-file=$pid_file &
+ $bindir/mysqld_safe --datadir=$datadir --pid-file=$pid_file >/dev/null 2>&1 &
# Make lock for RedHat / SuSE
if test -w /var/lock/subsys
then
diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh
index 0eb642650d7..5a9fbf64b1c 100644
--- a/support-files/mysql.spec.sh
+++ b/support-files/mysql.spec.sh
@@ -260,7 +260,7 @@ export PATH
# If we want to compile with RAID using gcc 3, we need to use
# gcc instead of g++ to avoid linking problems (RAID code is written in C++)
-if gcc -v 2>&1 | grep 'version 3' > /dev/null 2>&1
+test -z $CXX && test -z $CC && if gcc -v 2>&1 | grep 'gcc version 3' > /dev/null 2>&1
then
export CXX="gcc"
fi
@@ -443,11 +443,12 @@ fi
[ "$RBR" != "/" ] && [ -d $RBR ] && rm -rf $RBR;
%files server
-%defattr(755 root, root)
+%defattr(-,root,root,0755)
-%doc %attr(644, root, root) COPYING README
-%doc %attr(644, root, root) Docs/manual.{html,ps,texi,txt} Docs/manual_toc.html
-%doc %attr(644, root, root) support-files/my-*.cnf
+%doc COPYING README
+%doc Docs/manual.{html,ps,texi,txt}
+%doc Docs/manual_toc.html
+%doc support-files/my-*.cnf
%doc %attr(644, root, root) %{_infodir}/mysql.info*
@@ -500,6 +501,7 @@ fi
%attr(755, root, root) %{_datadir}/mysql/
%files client
+%defattr(-, root, root, 0755)
%attr(755, root, root) %{_bindir}/msql2mysql
%attr(755, root, root) %{_bindir}/mysql
%attr(755, root, root) %{_bindir}/mysql_find_rows
@@ -527,7 +529,7 @@ fi
/sbin/ldconfig
%files devel
-%defattr(644 root, root)
+%defattr(-, root, root, 0755)
%attr(755, root, root) %{_bindir}/comp_err
%attr(755, root, root) %{_bindir}/mysql_config
%dir %attr(755, root, root) %{_includedir}/mysql
@@ -548,11 +550,12 @@ fi
%{_libdir}/mysql/libvio.a
%files shared
-%defattr(755 root, root)
+%defattr(-, root, root, 0755)
# Shared libraries (omit for architectures that don't support them)
%{_libdir}/*.so*
%files bench
+%defattr(-, root, root, 0755)
%attr(-, root, root) %{_datadir}/sql-bench
%attr(-, root, root) %{_datadir}/mysql-test
%attr(755, root, root) %{_bindir}/mysqlmanager
@@ -560,15 +563,25 @@ fi
%attr(755, root, root) %{_bindir}/mysqlmanagerc
%files Max
+%defattr(-, root, root, 0755)
%attr(755, root, root) %{_sbindir}/mysqld-max
%attr(644, root, root) %{_libdir}/mysql/mysqld-max.sym
%files embedded
+%defattr(-, root, root, 0755)
%attr(644, root, root) %{_libdir}/mysql/libmysqld.a
# The spec file changelog only includes changes made to the spec file
# itself
%changelog
+* Fri Dec 13 2003 Lenz Grimmer <lenz@mysql.com>
+
+- fixed file permissions (BUG 1672)
+
+* Thu Dec 11 2003 Lenz Grimmer <lenz@mysql.com>
+
+- made testing for gcc3 a bit more robust
+
* Fri Dec 05 2003 Lenz Grimmer <lenz@mysql.com>
- added missing file mysql_create_system_tables to the server subpackage