summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--BitKeeper/etc/logging_ok1
-rwxr-xr-xBuild-tools/Bootstrap22
-rwxr-xr-xBuild-tools/Do-compile8
-rwxr-xr-xBuild-tools/Do-rpm89
-rw-r--r--Build-tools/logger.pm1
-rw-r--r--client/mysql.cc12
-rw-r--r--client/mysqldump.c103
-rw-r--r--client/mysqltest.c405
-rw-r--r--configure.in4
-rw-r--r--include/my_base.h10
-rw-r--r--include/my_dir.h11
-rw-r--r--include/my_global.h3
-rw-r--r--include/my_sys.h2
-rw-r--r--innobase/btr/btr0cur.c105
-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--libmysqld/lib_sql.cc7
-rw-r--r--myisam/mi_check.c14
-rw-r--r--myisam/mi_dbug.c4
-rw-r--r--myisam/mi_key.c54
-rw-r--r--myisam/mi_open.c3
-rw-r--r--myisam/mi_search.c25
-rw-r--r--mysql-test/r/auto_increment.result26
-rw-r--r--mysql-test/r/binary.result1
-rw-r--r--mysql-test/r/func_str.result3
-rw-r--r--mysql-test/r/func_time.result9
-rw-r--r--mysql-test/r/handler.result2
-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.result10
-rw-r--r--mysql-test/r/insert.result2
-rw-r--r--mysql-test/r/join_outer.result17
-rw-r--r--mysql-test/r/loaddata.result18
-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.result2
-rw-r--r--mysql-test/r/rpl_EE_error.result16
-rw-r--r--mysql-test/r/rpl_max_relay_size.result2
-rw-r--r--mysql-test/r/rpl_rotate_logs.result17
-rw-r--r--mysql-test/r/rpl_trunc_binlog.result2
-rw-r--r--mysql-test/r/symlink.result20
-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_decimal.result195
-rw-r--r--mysql-test/r/type_enum.result10
-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/func_str.test1
-rw-r--r--mysql-test/t/func_time.test7
-rw-r--r--mysql-test/t/handler.test2
-rw-r--r--mysql-test/t/innodb.test12
-rw-r--r--mysql-test/t/insert.test2
-rw-r--r--mysql-test/t/join_outer.test13
-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.test36
-rw-r--r--mysql-test/t/mysqldump.test3
-rw-r--r--mysql-test/t/rpl_EE_error.test30
-rw-r--r--mysql-test/t/rpl_log_pos.test2
-rw-r--r--mysql-test/t/rpl_max_relay_size.test1
-rw-r--r--mysql-test/t/rpl_rotate_logs.test9
-rw-r--r--mysql-test/t/rpl_trunc_binlog.test1
-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_decimal.test17
-rw-r--r--mysql-test/t/type_enum.test11
-rw-r--r--mysys/my_lib.c339
-rw-r--r--mysys/my_symlink.c1
-rw-r--r--mysys/my_symlink2.c12
-rw-r--r--sql/field.cc10
-rw-r--r--sql/field.h7
-rw-r--r--sql/ha_innodb.cc4
-rw-r--r--sql/item.cc8
-rw-r--r--sql/item.h4
-rw-r--r--sql/item_strfunc.cc2
-rw-r--r--sql/lex.h1
-rw-r--r--sql/log_event.cc6
-rw-r--r--sql/mysql_priv.h1
-rw-r--r--sql/mysqld.cc96
-rw-r--r--sql/nt_servc.cc4
-rw-r--r--sql/opt_range.cc45
-rw-r--r--sql/records.cc11
-rw-r--r--sql/share/czech/errmsg.txt2
-rw-r--r--sql/share/english/errmsg.txt2
-rw-r--r--sql/share/estonian/errmsg.txt2
-rw-r--r--sql/share/french/errmsg.txt2
-rw-r--r--sql/share/greek/errmsg.txt2
-rw-r--r--sql/share/hungarian/errmsg.txt2
-rw-r--r--sql/share/japanese/errmsg.txt2
-rw-r--r--sql/share/korean/errmsg.txt2
-rw-r--r--sql/share/norwegian-ny/errmsg.txt2
-rw-r--r--sql/share/norwegian/errmsg.txt2
-rw-r--r--sql/share/polish/errmsg.txt2
-rw-r--r--sql/share/romanian/errmsg.txt2
-rw-r--r--sql/share/slovak/errmsg.txt2
-rw-r--r--sql/sql_acl.cc5
-rw-r--r--sql/sql_base.cc15
-rw-r--r--sql/sql_class.h14
-rw-r--r--sql/sql_db.cc2
-rw-r--r--sql/sql_delete.cc12
-rw-r--r--sql/sql_insert.cc6
-rw-r--r--sql/sql_load.cc63
-rw-r--r--sql/sql_parse.cc18
-rw-r--r--sql/sql_rename.cc1
-rw-r--r--sql/sql_select.cc35
-rw-r--r--sql/sql_show.cc2
-rw-r--r--sql/sql_table.cc13
-rw-r--r--sql/sql_update.cc33
-rw-r--r--sql/table.cc21
-rw-r--r--sql/table.h2
-rw-r--r--sql/time.cc4
-rw-r--r--strings/ctype-tis620.c18
-rw-r--r--strings/strto.c2
-rw-r--r--strings/strtoll.c3
-rw-r--r--strings/strtoull.c1
-rw-r--r--support-files/mysql.server.sh2
-rw-r--r--support-files/mysql.spec.sh27
127 files changed, 2226 insertions, 715 deletions
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok
index 17af13c2e75..386ab8a0e49 100644
--- a/BitKeeper/etc/logging_ok
+++ b/BitKeeper/etc/logging_ok
@@ -34,6 +34,7 @@ hf@deer.(none)
hf@deer.mysql.r18.ru
hf@genie.(none)
igor@hundin.mysql.fi
+igor@rurik.mysql.com
jani@dsl-jkl1657.dial.inet.fi
jani@hynda.(none)
jani@hynda.mysql.fi
diff --git a/Build-tools/Bootstrap b/Build-tools/Bootstrap
index 94446d9880f..930d053b113 100755
--- a/Build-tools/Bootstrap
+++ b/Build-tools/Bootstrap
@@ -99,6 +99,8 @@ if (defined $opt_build_command)
print_help("") if ($opt_help);
defined($REPO=$ARGV[0]) || print_help("Please enter the BK repository to be used!");
+$subject= "Bootstrap of $REPO failed" if $opt_mail;
+
&logger("Starting build");
&abort("The directory \"$REPO\" could not be found!") if (!-d $REPO);
&logger("Using $REPO as the BK parent repository");
@@ -274,11 +276,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/{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 +368,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 e5783dbf515..e92654ccffd 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= ();
@@ -75,7 +77,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" : "");
@@ -83,7 +85,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";
@@ -110,7 +112,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..a216a3ba5dc 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,30 @@ else
die "ERROR: $LOGGER cannot be found!\n";
}
+$subject= "RPM build for $SPECFILE failed" if $opt_mail;
+
+# 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 +109,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 +139,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 +152,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 +189,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";
+$command.= " $RPMDIR/$RPMARCH/MySQL*$VERSION*.$RPMARCH.rpm $PWD";
+&logger("Moving binary RPMs to current dir.");
&run_command($command, "Error moving binary RPMs!");
#
@@ -181,11 +204,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 +224,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 +251,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/Build-tools/logger.pm b/Build-tools/logger.pm
index becde95df18..835d8014aa0 100644
--- a/Build-tools/logger.pm
+++ b/Build-tools/logger.pm
@@ -53,7 +53,6 @@ sub abort
if ($opt_mail && !$opt_dry_run)
{
$messagefile= "/tmp/message.$$";
- $subject= "Bootstrap of $REPO failed";
open(TMP,">$messagefile");
print TMP "$message\n\n";
close TMP;
diff --git a/client/mysql.cc b/client/mysql.cc
index fd63c0dc18e..370213d4fc4 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -358,7 +358,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);
@@ -574,8 +574,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},
@@ -1359,7 +1359,7 @@ com_help (String *buffer __attribute__((unused)),
}
if (connected)
tee_fprintf(stdout,
- "\nConnection id: %ld (Can be used with mysqladmin kill)\n\n",
+ "\nConnection id: %lu (Can be used with mysqladmin kill)\n\n",
mysql_thread_id(&mysql));
else
tee_fprintf(stdout, "Not connected! Reconnect with 'connect'!\n\n");
@@ -2109,7 +2109,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 ***");
@@ -2323,7 +2323,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 d8e63cd611a..489869f6c3d 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -36,7 +36,7 @@
** Added --single-transaction option 06/06/2002 by Peter Zaitsev
*/
-#define DUMP_VERSION "9.09"
+#define DUMP_VERSION "9.10"
#include <my_global.h>
#include <my_sys.h>
@@ -236,8 +236,8 @@ 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,
@@ -262,6 +262,8 @@ static int dump_databases(char **);
static int dump_all_databases();
static char *quote_name(const char *name, char *buff, my_bool force);
static void print_quoted_xml(FILE *output, char *fname, char *str, uint len);
+static const char *check_if_ignore_table(const char *table_name);
+
static void print_version(void)
{
@@ -564,6 +566,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;
+}
+
+
/*
getStructure -- retrievs database structure, prints out corresponding
CREATE statement and fills out insert_pat.
@@ -590,7 +609,8 @@ static uint getTableStructure(char *table, char* db)
if (verbose)
fprintf(stderr, "-- Retrieving table structure for table %s...\n", table);
- sprintf(insert_pat,"SET OPTION SQL_QUOTE_SHOW_CREATE=%d", (opt_quoted || opt_keywords));
+ sprintf(insert_pat,"SET OPTION SQL_QUOTE_SHOW_CREATE=%d",
+ (opt_quoted || opt_keywords));
result_table= quote_name(table, table_buff, 1);
opt_quoted_table= quote_name(table, table_buff2, 0);
if (!mysql_query(sock,insert_pat))
@@ -819,7 +839,9 @@ static uint getTableStructure(char *table, char* db)
/* Get MySQL specific create options */
if (create_options)
{
- sprintf(buff,"show table status like %s",result_table);
+ 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)
@@ -924,11 +946,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];
@@ -1434,6 +1468,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;
diff --git a/client/mysqltest.c b/client/mysqltest.c
index a168099e6d6..e3aa78c05df 100644
--- a/client/mysqltest.c
+++ b/client/mysqltest.c
@@ -42,7 +42,7 @@
**********************************************************************/
-#define MTEST_VERSION "1.29"
+#define MTEST_VERSION "1.30"
#include <my_global.h>
#include <mysql_embed.h>
@@ -54,18 +54,15 @@
#include <m_ctype.h>
#include <my_dir.h>
#include <hash.h>
-#include <stdio.h>
-#include <stdlib.h>
#include <my_getopt.h>
#include <stdarg.h>
#include <sys/stat.h>
-#include <unistd.h>
-#include <errno.h>
#include <violite.h>
-#define MAX_QUERY 65536
+#define MAX_QUERY 65536
+#define MAX_COLUMNS 256
#define PAD_SIZE 128
-#define MAX_CONS 1024
+#define MAX_CONS 128
#define MAX_INCLUDE_DEPTH 16
#define LAZY_GUESS_BUF_SIZE 8192
#define INIT_Q_LINES 1024
@@ -79,6 +76,11 @@
#endif
#define MAX_SERVER_ARGS 20
+/* Defines to make this look like MySQL 4.1 */
+#define charset_info default_charset_info
+#define my_isvar(A,B) isvar(B)
+#define my_hash_insert(A,B) hash_insert((A), (B))
+
/*
Sometimes in a test the client starts before
the server - to solve the problem, we try again
@@ -117,7 +119,6 @@ static FILE** cur_file;
static FILE** file_stack_end;
static uint lineno_stack[MAX_INCLUDE_DEPTH];
static char TMPDIR[FN_REFLEN];
-static int *block_ok_stack_end;
static int *cur_block, *block_stack_end;
static int block_stack[BLOCK_STACK_DEPTH];
@@ -135,10 +136,10 @@ static const char *embedded_server_groups[] = {
NullS
};
-#include "sslopt-vars.h"
-
DYNAMIC_ARRAY q_lines;
+#include "sslopt-vars.h"
+
typedef struct
{
char file[FN_REFLEN];
@@ -180,7 +181,8 @@ typedef struct
VAR var_reg[10];
/*Perl/shell-like variable registers */
HASH var_hash;
-int disable_query_log=0, disable_result_log=0;
+my_bool disable_query_log=0, disable_result_log=0, disable_warnings=0;
+my_bool disable_info= 1; /* By default off */
struct connection cons[MAX_CONS];
struct connection* cur_con, *next_con, *cons_end;
@@ -200,7 +202,7 @@ Q_SYNC_WITH_MASTER,
Q_SYNC_SLAVE_WITH_MASTER,
Q_ERROR,
Q_SEND, Q_REAP,
-Q_DIRTY_CLOSE, Q_REPLACE,
+Q_DIRTY_CLOSE, Q_REPLACE, Q_REPLACE_COLUMN,
Q_PING, Q_EVAL,
Q_RPL_PROBE, Q_ENABLE_RPL_PARSE,
Q_DISABLE_RPL_PARSE, Q_EVAL_RESULT,
@@ -209,6 +211,8 @@ Q_ENABLE_RESULT_LOG, Q_DISABLE_RESULT_LOG,
Q_SERVER_START, Q_SERVER_STOP,Q_REQUIRE_MANAGER,
Q_WAIT_FOR_SLAVE_TO_STOP,
Q_REQUIRE_VERSION,
+Q_ENABLE_WARNINGS, Q_DISABLE_WARNINGS,
+Q_ENABLE_INFO, Q_DISABLE_INFO,
Q_EXEC,
Q_UNKNOWN, /* Unknown command. */
Q_COMMENT, /* Comments, ignored. */
@@ -260,6 +264,7 @@ const char *command_names[]=
"reap",
"dirty_close",
"replace_result",
+ "replace_column",
"ping",
"eval",
"rpl_probe",
@@ -275,6 +280,10 @@ const char *command_names[]=
"require_manager",
"wait_for_slave_to_stop",
"require_version",
+ "enable_warnings",
+ "disable_warnings",
+ "enable_info",
+ "disable_info",
"exec",
0
};
@@ -301,7 +310,7 @@ VAR* var_get(const char *var_name, const char** var_name_end, my_bool raw,
int eval_expr(VAR* v, const char *p, const char** p_end);
static int read_server_arguments(const char *name);
-/* Definitions for replace */
+/* Definitions for replace result */
typedef struct st_pointer_array { /* when using array-strings */
TYPELIB typelib; /* Pointer to strings */
@@ -329,6 +338,13 @@ static char *out_buff;
static uint out_length;
static int eval_result = 0;
+/* For column replace */
+char *replace_column[MAX_COLUMNS];
+uint max_replace_column= 0;
+
+static void get_replace_column(struct st_query *q);
+static void free_replace_column();
+
/* Disable functions that only exist in MySQL 4.0 */
#if MYSQL_VERSION_ID < 40000 || defined(EMBEDDED_LIBRARY)
void mysql_enable_rpl_parse(MYSQL* mysql __attribute__((unused))) {}
@@ -339,7 +355,6 @@ int mysql_rpl_probe(MYSQL *mysql __attribute__((unused))) { return 1; }
static void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val,
int len);
-
static void do_eval(DYNAMIC_STRING* query_eval, const char* query)
{
const char* p;
@@ -434,6 +449,7 @@ static void free_used_memory()
delete_dynamic(&q_lines);
dynstr_free(&ds_res);
free_replace();
+ free_replace_column();
my_free(pass,MYF(MY_ALLOW_ZERO_PTR));
free_defaults(default_argv);
mysql_server_end();
@@ -602,7 +618,7 @@ VAR* var_get(const char* var_name, const char** var_name_end, my_bool raw,
{
const char* save_var_name = var_name, *end;
end = (var_name_end) ? *var_name_end : 0;
- while (isvar(*var_name) && var_name != end)
+ while (my_isvar(charset_info,*var_name) && var_name != end)
++var_name;
if (var_name == save_var_name)
{
@@ -647,7 +663,7 @@ static VAR* var_obtain(char* name, int len)
if ((v = (VAR*)hash_search(&var_hash, name, len)))
return v;
v = var_init(0, name, len, "", 0);
- hash_insert(&var_hash, (byte*)v);
+ my_hash_insert(&var_hash, (byte*)v);
return v;
}
@@ -700,13 +716,13 @@ int do_wait_for_slave_to_stop(struct st_query* q __attribute__((unused)))
MYSQL* mysql = &cur_con->mysql;
for (;;)
{
- MYSQL_RES* res;
+ MYSQL_RES *res;
MYSQL_ROW row;
int done;
LINT_INIT(res);
- if (mysql_query(mysql,"show status like 'Slave_running'")
- || !(res=mysql_store_result(mysql)))
+ if (mysql_query(mysql,"show status like 'Slave_running'") ||
+ !(res=mysql_store_result(mysql)))
die("Query failed while probing slave for stop: %s",
mysql_error(mysql));
if (!(row=mysql_fetch_row(res)) || !row[1])
@@ -753,10 +769,8 @@ int do_server_op(struct st_query* q,const char* op)
com_p=strmov(com_p,"_exec ");
if (!*p)
die("Missing server name in server_%s\n",op);
- while (*p && !isspace(*p))
- {
- *com_p++=*p++;
- }
+ while (*p && !my_isspace(charset_info,*p))
+ *com_p++= *p++;
*com_p++=' ';
com_p=int10_to_str(manager_wait_timeout,com_p,10);
*com_p++ = '\n';
@@ -786,7 +800,7 @@ int do_require_version(struct st_query* q)
if (!*p)
die("Missing version argument in require_version\n");
ver_arg = p;
- while (*p && !isspace(*p))
+ while (*p && !my_isspace(charset_info,*p))
p++;
*p = 0;
ver_arg_len = p - ver_arg;
@@ -816,7 +830,7 @@ int do_source(struct st_query* q)
if (!*p)
die("Missing file name in source\n");
name = p;
- while (*p && !isspace(*p))
+ while (*p && !my_isspace(charset_info,*p))
p++;
*p = 0;
@@ -848,7 +862,7 @@ int do_exec(struct st_query* q)
FILE *res_file;
char *cmd= q->first_argument;
- while (*cmd && isspace(*cmd))
+ while (*cmd && my_isspace(charset_info, *cmd))
cmd++;
if (!*cmd)
die("Missing argument in exec\n");
@@ -1018,16 +1032,16 @@ int do_system(struct st_query* q)
var_init(&v, 0, 0, 0, 0);
eval_expr(&v, p, 0); /* NULL terminated */
if (v.str_val_len)
- {
- char expr_buf[512];
- if ((uint)v.str_val_len > sizeof(expr_buf) - 1)
- v.str_val_len = sizeof(expr_buf) - 1;
- memcpy(expr_buf, v.str_val, v.str_val_len);
- expr_buf[v.str_val_len] = 0;
- DBUG_PRINT("info", ("running system command '%s'", expr_buf));
- if (system(expr_buf) && q->abort_on_error)
- die("system command '%s' failed", expr_buf);
- }
+ {
+ char expr_buf[512];
+ if ((uint)v.str_val_len > sizeof(expr_buf) - 1)
+ v.str_val_len = sizeof(expr_buf) - 1;
+ memcpy(expr_buf, v.str_val, v.str_val_len);
+ expr_buf[v.str_val_len] = 0;
+ DBUG_PRINT("info", ("running system command '%s'", expr_buf));
+ if (system(expr_buf) && q->abort_on_error)
+ die("system command '%s' failed", expr_buf);
+ }
var_free(&v);
return 0;
}
@@ -1075,7 +1089,8 @@ int do_sync_with_master2(const char* p)
mysql_errno(mysql), mysql_error(mysql));
if (!(last_result = res = mysql_store_result(mysql)))
- die("line %u: mysql_store_result() returned NULL", start_lineno);
+ die("line %u: mysql_store_result() returned NULL for '%s'", start_lineno,
+ query_buf);
if (!(row = mysql_fetch_row(res)))
die("line %u: empty result in %s", start_lineno, query_buf);
if (!row[0])
@@ -1099,17 +1114,19 @@ int do_save_master_pos()
MYSQL_RES* res;
MYSQL_ROW row;
MYSQL* mysql = &cur_con->mysql;
+ const char *query;
int rpl_parse;
rpl_parse = mysql_rpl_parse_enabled(mysql);
mysql_disable_rpl_parse(mysql);
- if (mysql_query(mysql, "show master status"))
+ if (mysql_query(mysql, query= "show master status"))
die("At line %u: failed in show master status: %d: %s", start_lineno,
mysql_errno(mysql), mysql_error(mysql));
if (!(last_result =res = mysql_store_result(mysql)))
- die("line %u: mysql_store_result() retuned NULL", start_lineno);
+ die("line %u: mysql_store_result() retuned NULL for '%s'", start_lineno,
+ query);
if (!(row = mysql_fetch_row(res)))
die("line %u: empty result in show master status", start_lineno);
strnmov(master_pos.file, row[0], sizeof(master_pos.file)-1);
@@ -1130,11 +1147,11 @@ int do_let(struct st_query* q)
if (!*p)
die("Missing variable name in let\n");
var_name = p;
- while (*p && (*p != '=' || isspace(*p)))
+ while (*p && (*p != '=' || my_isspace(charset_info,*p)))
p++;
var_name_end = p;
if (*p == '=') p++;
- while (*p && isspace(*p))
+ while (*p && my_isspace(charset_info,*p))
p++;
var_val_start = p;
return var_set(var_name, var_name_end, var_val_start, q->end);
@@ -1163,8 +1180,8 @@ int do_disable_rpl_parse(struct st_query* q __attribute__((unused)))
int do_sleep(struct st_query* q, my_bool real_sleep)
{
- char* p=q->first_argument;
- while (*p && isspace(*p))
+ char *p=q->first_argument;
+ while (*p && my_isspace(charset_info,*p))
p++;
if (!*p)
die("Missing argument in sleep\n");
@@ -1180,7 +1197,7 @@ static void get_file_name(char *filename, struct st_query* q)
char* p=q->first_argument;
strnmov(filename, p, FN_REFLEN);
/* Remove end space */
- while (p > filename && isspace(p[-1]))
+ while (p > filename && my_isspace(charset_info,p[-1]))
p--;
p[0]=0;
}
@@ -1266,7 +1283,7 @@ static char *get_string(char **to_ptr, char **from_ptr,
if (*from != ' ' && *from)
die("Wrong string argument in %s\n", q->query);
- while (isspace(*from)) /* Point to next string */
+ while (my_isspace(charset_info,*from)) /* Point to next string */
from++;
*to =0; /* End of string marker */
@@ -1323,8 +1340,8 @@ static void get_replace(struct st_query *q)
insert_pointer_name(&to_array,to);
}
for (i=1,pos=word_end_chars ; i < 256 ; i++)
- if (isspace(i))
- *pos++=i;
+ if (my_isspace(charset_info,i))
+ *pos++= i;
*pos=0; /* End pointer */
if (!(glob_replace=init_replace((char**) from_array.typelib.type_names,
(char**) to_array.typelib.type_names,
@@ -1360,7 +1377,7 @@ int select_connection(char *p)
if (!*p)
die("Missing connection name in connect\n");
name = p;
- while (*p && !isspace(*p))
+ while (*p && !my_isspace(charset_info,*p))
p++;
*p = 0;
@@ -1386,7 +1403,7 @@ int close_connection(struct st_query* q)
if (!*p)
die("Missing connection name in connect\n");
name = p;
- while (*p && !isspace(*p))
+ while (*p && !my_isspace(charset_info,*p))
p++;
*p = 0;
@@ -1394,6 +1411,7 @@ int close_connection(struct st_query* q)
{
if (!strcmp(con->name, name))
{
+#ifndef EMBEDDED_LIBRARY
if (q->type == Q_DIRTY_CLOSE)
{
if (con->mysql.net.vio)
@@ -1402,7 +1420,7 @@ int close_connection(struct st_query* q)
con->mysql.net.vio = 0;
}
}
-
+#endif
mysql_close(&con->mysql);
DBUG_RETURN(0);
}
@@ -1422,11 +1440,13 @@ int close_connection(struct st_query* q)
char* safe_get_param(char* str, char** arg, const char* msg)
{
DBUG_ENTER("safe_get_param");
- while (*str && isspace(*str)) str++;
+ while (*str && my_isspace(charset_info,*str))
+ str++;
*arg = str;
for (; *str && *str != ',' && *str != ')' ; str++)
{
- if (isspace(*str)) *str = 0;
+ if (my_isspace(charset_info,*str))
+ *str = 0;
}
if (!*str)
die(msg);
@@ -1474,7 +1494,6 @@ int do_connect(struct st_query* q)
char* p=q->first_argument;
char buff[FN_REFLEN];
int con_port;
- int con_error;
int free_con_sock = 0;
DBUG_ENTER("do_connect");
@@ -1539,9 +1558,9 @@ int do_connect(struct st_query* q)
/* Special database to allow one to connect without a database name */
if (con_db && !strcmp(con_db,"*NO-ONE*"))
con_db=0;
- if ((con_error = safe_connect(&next_con->mysql, con_host,
- con_user, con_pass,
- con_db, con_port, con_sock ? con_sock: 0)))
+ if ((safe_connect(&next_con->mysql, con_host,
+ con_user, con_pass,
+ con_db, con_port, con_sock ? con_sock: 0)))
die("Could not open connection '%s': %s", con_name,
mysql_error(&next_con->mysql));
@@ -1663,7 +1682,7 @@ int read_line(char* buf, int size)
{
state = R_COMMENT;
}
- else if (isspace(c))
+ else if (my_isspace(charset_info,c))
{
if (c == '\n')
start_lineno= ++*lineno; /* Query hasn't started yet */
@@ -1789,7 +1808,7 @@ int read_query(struct st_query** q_ptr)
{
expected_errno = 0;
p++;
- for (;isdigit(*p);p++)
+ for (;my_isdigit(charset_info,*p);p++)
expected_errno = expected_errno * 10 + *p - '0';
q->expected_errno[0] = expected_errno;
q->expected_errno[1] = 0;
@@ -1797,25 +1816,28 @@ int read_query(struct st_query** q_ptr)
}
}
- while (*p && isspace(*p)) p++ ;
+ while (*p && my_isspace(charset_info,*p))
+ p++ ;
if (*p == '@')
{
p++;
p1 = q->record_file;
- while (!isspace(*p) &&
+ while (!my_isspace(charset_info,*p) &&
p1 < q->record_file + sizeof(q->record_file) - 1)
*p1++ = *p++;
*p1 = 0;
}
}
- while (*p && isspace(*p)) p++;
+ while (*p && my_isspace(charset_info,*p))
+ p++;
if (!(q->query_buf=q->query=my_strdup(p,MYF(MY_WME))))
die(NullS);
/* Calculate first word and first argument */
- for (p=q->query; *p && !isspace(*p) ; p++) ;
+ for (p=q->query; *p && !my_isspace(charset_info,*p) ; p++) ;
q->first_word_len = (uint) (p - q->query);
- while (*p && isspace(*p)) p++;
+ while (*p && my_isspace(charset_info,*p))
+ p++;
q->first_argument=p;
q->end = strend(q->query);
parser.read_lines++;
@@ -1825,34 +1847,34 @@ int read_query(struct st_query** q_ptr)
static struct my_option my_long_options[] =
{
- {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'",
+ {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.",
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
{"database", 'D', "Database to use.", (gptr*) &db, (gptr*) &db, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"basedir", 'b', "Basedir for tests", (gptr*) &opt_basedir,
+ {"basedir", 'b', "Basedir for tests.", (gptr*) &opt_basedir,
(gptr*) &opt_basedir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"big-test", 'B', "Define BIG_TEST to 1", (gptr*) &opt_big_test,
+ {"big-test", 'B', "Define BIG_TEST to 1.", (gptr*) &opt_big_test,
(gptr*) &opt_big_test, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"compress", 'C', "Use the compressed server/client protocol",
+ {"compress", 'C', "Use the compressed server/client protocol.",
(gptr*) &opt_compress, (gptr*) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
0, 0, 0},
{"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG,
0, 0, 0, 0, 0, 0},
{"host", 'h', "Connect to host.", (gptr*) &host, (gptr*) &host, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"manager-user", OPT_MANAGER_USER, "Undocumented: Used for debugging",
+ {"manager-user", OPT_MANAGER_USER, "Undocumented: Used for debugging.",
(gptr*) &manager_user, (gptr*) &manager_user, 0, GET_STR, REQUIRED_ARG, 0,
0, 0, 0, 0, 0},
- {"manager-host", OPT_MANAGER_HOST, "Undocumented: Used for debugging",
+ {"manager-host", OPT_MANAGER_HOST, "Undocumented: Used for debugging.",
(gptr*) &manager_host, (gptr*) &manager_host, 0, GET_STR, REQUIRED_ARG,
0, 0, 0, 0, 0, 0},
- {"manager-password", OPT_MANAGER_PASSWD, "Undocumented: Used for debugging",
+ {"manager-password", OPT_MANAGER_PASSWD, "Undocumented: Used for debugging.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"manager-port", OPT_MANAGER_PORT, "Undocumented: Used for debugging",
+ {"manager-port", OPT_MANAGER_PORT, "Undocumented: Used for debugging.",
(gptr*) &manager_port, (gptr*) &manager_port, 0, GET_INT, REQUIRED_ARG,
MYSQL_MANAGER_PORT, 0, 0, 0, 0, 0},
{"manager-wait-timeout", OPT_MANAGER_WAIT_TIMEOUT,
- "Undocumented: Used for debugging", (gptr*) &manager_wait_timeout,
+ "Undocumented: Used for debugging.", (gptr*) &manager_wait_timeout,
(gptr*) &manager_wait_timeout, 0, GET_INT, REQUIRED_ARG, 3, 0, 0, 0, 0, 0},
{"password", 'p', "Password to use when connecting to server.",
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
@@ -1865,16 +1887,16 @@ static struct my_option my_long_options[] =
{"result-file", 'R', "Read/Store result from/in this file.",
(gptr*) &result_file, (gptr*) &result_file, 0, GET_STR, REQUIRED_ARG,
0, 0, 0, 0, 0, 0},
- {"server-arg", 'A', "Send enbedded server this as a paramenter",
+ {"server-arg", 'A', "Send enbedded server this as a paramenter.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"server-file", 'F', "Read embedded server arguments from file",
+ {"server-file", 'F', "Read embedded server arguments from file.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"silent", 's', "Suppress all normal output. Synonym for --quiet.",
(gptr*) &silent, (gptr*) &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"skip-safemalloc", OPT_SKIP_SAFEMALLOC,
- "Don't use the memory allocation checking", 0, 0, 0, GET_NO_ARG, NO_ARG,
+ "Don't use the memory allocation checking.", 0, 0, 0, GET_NO_ARG, NO_ARG,
0, 0, 0, 0, 0, 0},
- {"sleep", 'T', "Sleep always this many seconds on sleep commands",
+ {"sleep", 'T', "Sleep always this many seconds on sleep commands.",
(gptr*) &opt_sleep, (gptr*) &opt_sleep, 0, GET_INT, REQUIRED_ARG, 0, 0, 0,
0, 0, 0},
{"socket", 'S', "Socket file to use for connection.",
@@ -1883,7 +1905,7 @@ static struct my_option my_long_options[] =
#include "sslopt-longopts.h"
{"test-file", 'x', "Read test from/in this file (default stdin).",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"tmpdir", 't', "Temporary directory where sockets are put",
+ {"tmpdir", 't', "Temporary directory where sockets are put.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"user", 'u', "User for login.", (gptr*) &user, (gptr*) &user, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -1894,7 +1916,6 @@ static struct my_option my_long_options[] =
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
-
static void print_version(void)
{
printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,MTEST_VERSION,
@@ -1995,12 +2016,10 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
int parse_args(int argc, char **argv)
{
- int ho_error;
-
load_defaults("my",load_default_groups,&argc,&argv);
default_argv= argv;
- if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
+ if ((handle_options(&argc, &argv, my_long_options, get_one_option)))
exit(1);
if (argc > 1)
@@ -2068,6 +2087,45 @@ static void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val,
/*
+ Append all results to the dynamic string separated with '\t'
+ Values may be converted with 'replace_column'
+*/
+
+static void append_result(DYNAMIC_STRING *ds, MYSQL_RES *res)
+{
+ MYSQL_ROW row;
+ uint num_fields= mysql_num_fields(res);
+ unsigned long *lengths;
+ while ((row = mysql_fetch_row(res)))
+ {
+ uint i;
+ lengths = mysql_fetch_lengths(res);
+ for (i = 0; i < num_fields; i++)
+ {
+ const char *val= row[i];
+ ulonglong len= lengths[i];
+
+ if (i < max_replace_column && replace_column[i])
+ {
+ val= replace_column[i];
+ len= strlen(val);
+ }
+ if (!val)
+ {
+ val= "NULL";
+ len= 4;
+ }
+ if (i)
+ dynstr_append_mem(ds, "\t", 1);
+ replace_dynstr_append_mem(ds, val, len);
+ }
+ dynstr_append_mem(ds, "\n", 1);
+ }
+ free_replace_column();
+}
+
+
+/*
* flags control the phased/stages of query execution to be performed
* if QUERY_SEND bit is on, the query will be sent. If QUERY_REAP is on
* the result will be read - for regular query, both bits must be on
@@ -2076,12 +2134,7 @@ static void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val,
int run_query(MYSQL* mysql, struct st_query* q, int flags)
{
MYSQL_RES* res = 0;
- MYSQL_FIELD* fields;
- MYSQL_ROW row;
- int num_fields,i, error = 0;
- unsigned long* lengths;
- char* val;
- int len;
+ int i, error = 0;
DYNAMIC_STRING *ds;
DYNAMIC_STRING ds_tmp;
DYNAMIC_STRING eval_query;
@@ -2153,33 +2206,31 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
goto end; /* Ok */
}
}
+ DBUG_PRINT("info",("i: %d expected_errors: %d", i, q->expected_errors));
+ replace_dynstr_append_mem(ds, mysql_error(mysql),
+ strlen(mysql_error(mysql)));
+ dynstr_append_mem(ds,"\n",1);
if (i)
{
- replace_dynstr_append_mem(ds, mysql_error(mysql),
- strlen(mysql_error(mysql)));
- dynstr_append_mem(ds,"\n",1);
verbose_msg("query '%s' failed with wrong errno %d instead of %d...",
q->query, mysql_errno(mysql), q->expected_errno[0]);
- error=1;
+ error= 1;
goto end;
}
- replace_dynstr_append_mem(ds,mysql_error(mysql),
- strlen(mysql_error(mysql)));
- dynstr_append_mem(ds,"\n",1);
verbose_msg("query '%s' failed: %d: %s", q->query, mysql_errno(mysql),
mysql_error(mysql));
/*
- if we do not abort on error, failure to run the query does
- not fail the whole test case
+ if we do not abort on error, failure to run the query does
+ not fail the whole test case
*/
goto end;
}
/*{
verbose_msg("failed in mysql_store_result for query '%s' (%d)", query,
- mysql_errno(mysql));
+ mysql_errno(mysql));
error = 1;
goto end;
- }*/
+ }*/
}
if (q->expected_errno[0])
@@ -2190,45 +2241,33 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
goto end;
}
- if (!res)
- goto end;
-
if (!disable_result_log)
{
- fields = mysql_fetch_fields(res);
- num_fields = mysql_num_fields(res);
- for (i = 0; i < num_fields; i++)
- {
- if (i)
- dynstr_append_mem(ds, "\t", 1);
- dynstr_append(ds, fields[i].name);
- }
-
- dynstr_append_mem(ds, "\n", 1);
-
- while ((row = mysql_fetch_row(res)))
+ if (res)
{
- lengths = mysql_fetch_lengths(res);
+ int num_fields= mysql_num_fields(res);
+ MYSQL_FIELD *fields= mysql_fetch_fields(res);
for (i = 0; i < num_fields; i++)
{
- val = (char*)row[i];
- len = lengths[i];
-
- if (!val)
- {
- val = (char*)"NULL";
- len = 4;
- }
-
if (i)
dynstr_append_mem(ds, "\t", 1);
- replace_dynstr_append_mem(ds, val, len);
+ dynstr_append(ds, fields[i].name);
}
dynstr_append_mem(ds, "\n", 1);
+ append_result(ds, res);
+ }
+
+ if (!disable_info && mysql_info(mysql))
+ {
+ dynstr_append(ds, "info: ");
+ dynstr_append(ds, mysql_info(mysql));
+ dynstr_append_mem(ds, "\n", 1);
}
- if (glob_replace)
- free_replace();
}
+
+ if (glob_replace)
+ free_replace();
+
if (record)
{
if (!q->record_file[0] && !result_file)
@@ -2273,7 +2312,7 @@ void get_query_type(struct st_query* q)
q->type=(enum enum_commands) type; /* Found command */
}
-static byte* get_var_key(const byte* var, uint* len,
+static byte *get_var_key(const byte* var, uint* len,
my_bool __attribute__((unused)) t)
{
register char* key;
@@ -2282,11 +2321,11 @@ static byte* get_var_key(const byte* var, uint* len,
return (byte*)key;
}
-static VAR* var_init(VAR* v, const char* name, int name_len, const char* val,
+static VAR *var_init(VAR *v, const char *name, int name_len, const char *val,
int val_len)
{
int val_alloc_len;
- VAR* tmp_var;
+ VAR *tmp_var;
if (!name_len && name)
name_len = strlen(name);
if (!val_len && val)
@@ -2302,7 +2341,6 @@ static VAR* var_init(VAR* v, const char* name, int name_len, const char* val,
if (!(tmp_var->str_val = my_malloc(val_alloc_len+1, MYF(MY_WME))))
die("Out of memory");
- /* 'name' may be NULL here, but in this case name_len is 0 */
memcpy(tmp_var->name, name, name_len);
if (val)
{
@@ -2317,7 +2355,7 @@ static VAR* var_init(VAR* v, const char* name, int name_len, const char* val,
return tmp_var;
}
-static void var_free(void* v)
+static void var_free(void *v)
{
my_free(((VAR*) v)->str_val, MYF(MY_WME));
if (((VAR*)v)->alloced)
@@ -2325,38 +2363,42 @@ static void var_free(void* v)
}
-static void var_from_env(const char* name, const char* def_val)
+static void var_from_env(const char *name, const char *def_val)
{
- const char* tmp;
- VAR* v;
+ const char *tmp;
+ VAR *v;
if (!(tmp = getenv(name)))
tmp = def_val;
v = var_init(0, name, 0, tmp, 0);
- hash_insert(&var_hash, (byte*)v);
+ my_hash_insert(&var_hash, (byte*)v);
}
-static void init_var_hash()
+static void init_var_hash(MYSQL *mysql)
{
- VAR* v;
+ VAR *v;
DBUG_ENTER("init_var_hash");
- if (hash_init(&var_hash, 1024, 0, 0, get_var_key, var_free, MYF(0)))
+ if (hash_init(&var_hash,
+ 1024, 0, 0, get_var_key, var_free, MYF(0)))
die("Variable hash initialization failed");
var_from_env("MASTER_MYPORT", "9306");
var_from_env("SLAVE_MYPORT", "9307");
var_from_env("MYSQL_TEST_DIR", "/tmp");
var_from_env("BIG_TEST", opt_big_test ? "1" : "0");
- v=var_init(0,"MAX_TABLES", 0, (sizeof(ulong) == 4) ? "31" : "63",0);
- hash_insert(&var_hash, (byte*)v);
+ v= var_init(0,"MAX_TABLES", 0, (sizeof(ulong) == 4) ? "31" : "62",0);
+ my_hash_insert(&var_hash, (byte*) v);
+ v= var_init(0,"SERVER_VERSION", 0, mysql_get_server_info(mysql), 0);
+ my_hash_insert(&var_hash, (byte*) v);
+
DBUG_VOID_RETURN;
}
-int main(int argc, char** argv)
+int main(int argc, char **argv)
{
int error = 0;
- struct st_query* q;
+ struct st_query *q;
my_bool require_file=0, q_send_flag=0;
char save_file[FN_REFLEN];
MY_INIT(argv[0]);
@@ -2381,7 +2423,6 @@ int main(int argc, char** argv)
memset(block_stack, 0, sizeof(block_stack));
block_stack_end = block_stack + BLOCK_STACK_DEPTH;
memset(block_ok_stack, 0, sizeof(block_stack));
- block_ok_stack_end = block_ok_stack + BLOCK_STACK_DEPTH;
cur_block = block_stack;
block_ok = block_ok_stack;
*block_ok = 1;
@@ -2391,7 +2432,6 @@ int main(int argc, char** argv)
embedded_server_args,
(char**) embedded_server_groups))
die("Can't initialize MySQL server");
- init_var_hash();
if (cur_file == file_stack)
*++cur_file = stdin;
*lineno=1;
@@ -2410,14 +2450,14 @@ int main(int argc, char** argv)
opt_ssl_capath, opt_ssl_cipher);
#endif
- cur_con->name = my_strdup("default", MYF(MY_WME));
- if (!cur_con->name)
+ if (!(cur_con->name = my_strdup("default", MYF(MY_WME))))
die("Out of memory");
- if (safe_connect(&cur_con->mysql, host,
- user, pass, db, port, unix_sock))
+ if (safe_connect(&cur_con->mysql, host, user, pass, db, port, unix_sock))
die("Failed in mysql_real_connect(): %s", mysql_error(&cur_con->mysql));
+ init_var_hash(&cur_con->mysql);
+
while (!read_query(&q))
{
int current_line_inc = 1, processed = 0;
@@ -2439,6 +2479,10 @@ int main(int argc, char** argv)
case Q_DISABLE_QUERY_LOG: disable_query_log=1; break;
case Q_ENABLE_RESULT_LOG: disable_result_log=0; break;
case Q_DISABLE_RESULT_LOG: disable_result_log=1; break;
+ case Q_ENABLE_WARNINGS: disable_warnings=0; break;
+ case Q_DISABLE_WARNINGS: disable_warnings=1; break;
+ case Q_ENABLE_INFO: disable_info=0; break;
+ case Q_DISABLE_INFO: disable_info=1; break;
case Q_SOURCE: do_source(q); break;
case Q_SLEEP: do_sleep(q, 0); break;
case Q_REAL_SLEEP: do_sleep(q, 1); break;
@@ -2515,6 +2559,9 @@ int main(int argc, char** argv)
case Q_REPLACE:
get_replace(q);
break;
+ case Q_REPLACE_COLUMN:
+ get_replace_column(q);
+ break;
case Q_SAVE_MASTER_POS: do_save_master_pos(); break;
case Q_SYNC_WITH_MASTER: do_sync_with_master(q); break;
case Q_SYNC_SLAVE_WITH_MASTER:
@@ -2565,7 +2612,8 @@ int main(int argc, char** argv)
}
dynstr_free(&ds_res);
- if (!silent) {
+ if (!silent)
+ {
if (error)
printf("not ok\n");
else
@@ -2584,7 +2632,7 @@ int main(int argc, char** argv)
*/
-static int read_server_arguments(const char* name)
+static int read_server_arguments(const char *name)
{
char argument[1024],buff[FN_REFLEN], *str=0;
FILE *file;
@@ -3336,3 +3384,60 @@ static void free_replace_buffer(void)
{
my_free(out_buff,MYF(MY_WME));
}
+
+
+/****************************************************************************
+ Replace results for a column
+*****************************************************************************/
+
+static void free_replace_column()
+{
+ uint i;
+ for (i=0 ; i < max_replace_column ; i++)
+ {
+ if (replace_column[i])
+ {
+ my_free(replace_column[i], 0);
+ replace_column[i]= 0;
+ }
+ }
+ max_replace_column= 0;
+}
+
+/*
+ Get arguments for replace_columns. The syntax is:
+ replace-column column_number to_string [column_number to_string ...]
+ Where each argument may be quoted with ' or "
+ A argument may also be a variable, in which case the value of the
+ variable is replaced.
+*/
+
+static void get_replace_column(struct st_query *q)
+{
+ char *from=q->first_argument;
+ char *buff,*start;
+ DBUG_ENTER("get_replace_columns");
+
+ free_replace_column();
+ if (!*from)
+ die("Missing argument in %s\n", q->query);
+
+ /* Allocate a buffer for results */
+ start=buff=my_malloc(strlen(from)+1,MYF(MY_WME | MY_FAE));
+ while (*from)
+ {
+ char *to;
+ uint column_number;
+
+ to= get_string(&buff, &from, q);
+ if (!(column_number= atoi(to)) || column_number > MAX_COLUMNS)
+ die("Wrong column number to replace_columns in %s\n", q->query);
+ if (!*from)
+ die("Wrong number of arguments to replace in %s\n", q->query);
+ to= get_string(&buff, &from, q);
+ my_free(replace_column[column_number-1], MY_ALLOW_ZERO_PTR);
+ replace_column[column_number-1]= my_strdup(to, MYF(MY_WME | MY_FAE));
+ set_if_bigger(max_replace_column, column_number);
+ }
+ my_free(start, MYF(0));
+}
diff --git a/configure.in b/configure.in
index a4fe75ce896..fd9f6a4f721 100644
--- a/configure.in
+++ b/configure.in
@@ -4,7 +4,7 @@ dnl Process this file with autoconf to produce a configure script.
AC_INIT(sql/mysqld.cc)
AC_CANONICAL_SYSTEM
# The Docs Makefile.am parses this line!
-AM_INIT_AUTOMAKE(mysql, 4.0.17)
+AM_INIT_AUTOMAKE(mysql, 4.0.18)
AM_CONFIG_HEADER(config.h)
PROTOCOL_VERSION=10
@@ -733,7 +733,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/include/my_base.h b/include/my_base.h
index 91a248cd401..5344d876f99 100644
--- a/include/my_base.h
+++ b/include/my_base.h
@@ -180,11 +180,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 bcd6004d72a..168961a620d 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -267,6 +267,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
diff --git a/include/my_sys.h b/include/my_sys.h
index acb4c01b4f1..e1656cfc626 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -167,7 +167,7 @@ extern char *my_strdup_with_length(const byte *from, uint length,
#if defined(_AIX) && !defined(__GNUC__)
#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))
diff --git a/innobase/btr/btr0cur.c b/innobase/btr/btr0cur.c
index 29a8fd44b9e..bfb4d042850 100644
--- a/innobase/btr/btr0cur.c
+++ b/innobase/btr/btr0cur.c
@@ -1146,7 +1146,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. */
@@ -1170,12 +1169,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 */
@@ -1222,6 +1225,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));
@@ -1308,68 +1318,7 @@ btr_cur_parse_update_in_place(
}
/*****************************************************************
-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 */
-{
- dict_index_t* index = cursor->index;
- dict_index_t* clust_index;
- ulint err;
- rec_t* rec;
- dulint roll_ptr = ut_dulint_zero;
- trx_t* trx = thr_get_trx(thr);
-
- /* Only secondary index records are updated using this function */
- ut_ad(0 == (index->type & DICT_CLUSTERED));
-
- rec = btr_cur_get_rec(cursor);
-
- if (btr_cur_print_record_ops && thr) {
- printf(
- "Trx with id %lu %lu going to update table %s index %s\n",
- ut_dulint_get_high(thr_get_trx(thr)->id),
- ut_dulint_get_low(thr_get_trx(thr)->id),
- index->table_name, index->name);
- rec_print(rec);
- }
-
- err = lock_sec_rec_modify_check_and_lock(0, rec, index, thr);
-
- if (err != DB_SUCCESS) {
-
- return(err);
- }
-
- /* Remove possible hash index pointer to this record */
- btr_search_update_hash_on_delete(cursor);
-
- row_upd_rec_in_place(rec, update);
-
- clust_index = dict_table_get_first_index(index->table);
-
- /* Note that roll_ptr is really just a dummy value since
- a secondary index record does not contain any sys columns */
-
- btr_cur_update_in_place_log(BTR_KEEP_SYS_FLAG, rec, clust_index,
- update, trx, roll_ptr, mtr);
- return(DB_SUCCESS);
-}
-
-/*****************************************************************
-Updates a record when the update causes no size changes in its fields.
-We assume here that the ordering fields of the record do not change. */
+Updates a record when the update causes no size changes in its fields. */
ulint
btr_cur_update_in_place(
@@ -1389,13 +1338,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);
@@ -1420,7 +1366,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);
@@ -1494,9 +1445,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);
@@ -1546,8 +1494,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);
@@ -1729,7 +1677,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),
@@ -1779,8 +1726,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 3f9b5316185..4b39368c540 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 e02859bc851..45c5897eee7 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);
@@ -1829,7 +1845,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 f02fbeeb8fd..27d27b75a1c 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 b22e494f891..34c3aaf9142 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 db68479509d..e3725c8b39e 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/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc
index d33f384f81e..2c54603ea7a 100644
--- a/libmysqld/lib_sql.cc
+++ b/libmysqld/lib_sql.cc
@@ -224,6 +224,7 @@ static bool check_user(THD *thd,enum_server_command command, const char *user,
send_error(net,ER_OUT_OF_RESOURCES);
return 1;
}
+ strmake(thd->priv_host, LOCAL_HOST, sizeof(thd->priv_host)-1);
thd->master_access=acl_getroot(thd, thd->host, thd->ip, thd->user,
passwd, thd->scramble,
&thd->priv_user, thd->priv_host,
@@ -276,6 +277,12 @@ static bool check_user(THD *thd,enum_server_command command, const char *user,
}
+void THD::clear_error()
+{
+ net.last_error[0]= 0;
+ net.last_errno= 0;
+}
+
/*
Make a copy of array and the strings array points to
*/
diff --git a/myisam/mi_check.c b/myisam/mi_check.c
index 007ae950990..38e48eb5e06 100644
--- a/myisam/mi_check.c
+++ b/myisam/mi_check.c
@@ -126,7 +126,7 @@ 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");
@@ -1188,9 +1188,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,
@@ -1861,11 +1860,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,
@@ -2225,9 +2222,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 482287938c0..fe5b36fd304 100644
--- a/myisam/mi_dbug.c
+++ b/myisam/mi_dbug.c
@@ -137,6 +137,10 @@ void _mi_print_key(FILE *stream, register MI_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 89f6bc490fa..766ecf334b6 100644
--- a/myisam/mi_key.c
+++ b/myisam/mi_key.c
@@ -18,6 +18,7 @@
#include "myisamdef.h"
#include "m_ctype.h"
+#include <assert.h>
#ifdef HAVE_IEEEFP_H
#include <ieeefp.h>
#endif
@@ -388,53 +389,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;
- MI_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 */
+ MI_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 580261d8078..944a8af01e9 100644
--- a/myisam/mi_open.c
+++ b/myisam/mi_open.c
@@ -815,6 +815,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;
@@ -823,7 +825,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/myisam/mi_search.c b/myisam/mi_search.c
index 423b15ff8f7..5d0750f6a82 100644
--- a/myisam/mi_search.c
+++ b/myisam/mi_search.c
@@ -783,7 +783,8 @@ int _mi_key_cmp(register MI_KEYSEG *keyseg, register uchar *a,
if (piks &&
(flag=_mi_compare_text(keyseg->charset,a,a_length,b,b_length,
- (my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0))))
+ (my_bool) ((nextflag & SEARCH_PREFIX) &&
+ next_key_length <= 0))))
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a+=a_length;
b+=b_length;
@@ -801,7 +802,8 @@ int _mi_key_cmp(register MI_KEYSEG *keyseg, register uchar *a,
}
if (piks &&
(flag=_mi_compare_text(keyseg->charset,a,a_length,b,b_length,
- (my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0))))
+ (my_bool) ((nextflag & SEARCH_PREFIX)
+ && next_key_length <= 0))))
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a=end;
b+=length;
@@ -817,7 +819,8 @@ int _mi_key_cmp(register MI_KEYSEG *keyseg, register uchar *a,
if (piks &&
(flag=compare_bin(a,a_length,b,b_length,
- (my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0))))
+ (my_bool) ((nextflag & SEARCH_PREFIX) &&
+ next_key_length <= 0))))
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a+=a_length;
b+=b_length;
@@ -828,7 +831,8 @@ int _mi_key_cmp(register MI_KEYSEG *keyseg, register uchar *a,
uint length=keyseg->length;
if (piks &&
(flag=compare_bin(a,length,b,length,
- (my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0))))
+ (my_bool) ((nextflag & SEARCH_PREFIX) &&
+ next_key_length <= 0))))
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a+=length;
b+=length;
@@ -841,9 +845,17 @@ int _mi_key_cmp(register MI_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) && next_key_length <= 0))))
+ (my_bool) ((nextflag & SEARCH_PREFIX) &&
+ next_key_length <= 0))))
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a+=a_length;
b+=b_length;
@@ -859,7 +871,8 @@ int _mi_key_cmp(register MI_KEYSEG *keyseg, register uchar *a,
if (piks &&
(flag=compare_bin(a,a_length,b,b_length,
- (my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0))))
+ (my_bool) ((nextflag & SEARCH_PREFIX) &&
+ next_key_length <= 0))))
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a+=a_length;
b+=b_length;
diff --git a/mysql-test/r/auto_increment.result b/mysql-test/r/auto_increment.result
index e79e6aab56b..cbd2d48b38d 100644
--- a/mysql-test/r/auto_increment.result
+++ b/mysql-test/r/auto_increment.result
@@ -105,3 +105,29 @@ 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;
diff --git a/mysql-test/r/binary.result b/mysql-test/r/binary.result
index 4d5eb62cc71..2de8b01bc3a 100644
--- a/mysql-test/r/binary.result
+++ b/mysql-test/r/binary.result
@@ -65,6 +65,7 @@ a b
alter table t1 modify b tinytext not null, drop key b, add key (b(100));
select * from t1 where b="hello ";
a b
+hello hello
select * from t1 ignore index (b) where b="hello ";
a b
hello hello
diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result
index dcb788f520f..35a5ba70e86 100644
--- a/mysql-test/r/func_str.result
+++ b/mysql-test/r/func_str.result
@@ -164,6 +164,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 61aa4306c61..4715227425e 100644
--- a/mysql-test/r/func_time.result
+++ b/mysql-test/r/func_time.result
@@ -431,3 +431,12 @@ 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
diff --git a/mysql-test/r/handler.result b/mysql-test/r/handler.result
index 4af38807518..5467ea6dec2 100644
--- a/mysql-test/r/handler.result
+++ b/mysql-test/r/handler.result
@@ -142,7 +142,7 @@ insert into t1 values (17);
handler t2 read first;
Unknown table 't2' in HANDLER
handler t1 open as t2;
-alter table t1 type=MyISAM;
+alter table t1 engine=MyISAM;
handler t2 read first;
Unknown table 't2' in HANDLER
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 3938fc80f10..ce5491a718f 100644
--- a/mysql-test/r/innodb.result
+++ b/mysql-test/r/innodb.result
@@ -1233,3 +1233,13 @@ create table t2 (c char(8) not null, b char(8) not null, a char(8) not null, pri
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) type=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;
diff --git a/mysql-test/r/insert.result b/mysql-test/r/insert.result
index 270994e3998..7520fd7e6cc 100644
--- a/mysql-test/r/insert.result
+++ b/mysql-test/r/insert.result
@@ -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;
id t2
1 mysql.com
diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result
index debec01fbdc..ae4d99e6241 100644
--- a/mysql-test/r/join_outer.result
+++ b/mysql-test/r/join_outer.result
@@ -667,3 +667,20 @@ left outer join t2 using (f2)
left outer join t3 using (f3);
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;
+table type possible_keys key key_len ref rows Extra
+t1 ALL NULL NULL NULL NULL 3
+t2 ALL NULL NULL NULL NULL 2
+t3 ALL NULL NULL NULL NULL 2
+drop table t1, t2, t3;
diff --git a/mysql-test/r/loaddata.result b/mysql-test/r/loaddata.result
index 0b7925de1c5..1730d7b5c25 100644
--- a/mysql-test/r/loaddata.result
+++ b/mysql-test/r/loaddata.result
@@ -26,3 +26,21 @@ 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;
+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;
+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 8edf43a51ad..16bc92cb711 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;
Unknown table 'T2' in field list
RENAME TABLE T1 TO T2;
@@ -20,7 +25,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 350cea420b6..31be96fc0fd 100644
--- a/mysql-test/r/multi_update.result
+++ b/mysql-test/r/multi_update.result
@@ -327,3 +327,36 @@ 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;
+drop table if exists t1, t2;
+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;
diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result
index 27ca3fbaaf5..837a3627647 100644
--- a/mysql-test/r/mysqldump.result
+++ b/mysql-test/r/mysqldump.result
@@ -32,6 +32,6 @@ CREATE TABLE t1 (
a double default NULL
) TYPE=MyISAM;
-INSERT INTO t1 VALUES (NULL);
+INSERT INTO t1 VALUES (RES);
DROP TABLE t1;
diff --git a/mysql-test/r/rpl_EE_error.result b/mysql-test/r/rpl_EE_error.result
new file mode 100644
index 00000000000..a5043250df6
--- /dev/null
+++ b/mysql-test/r/rpl_EE_error.result
@@ -0,0 +1,16 @@
+slave stop;
+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;
+slave start;
+create table t1 (a int) type=myisam;
+flush tables;
+drop table t1;
+create table t1 (a int, unique(a)) type=myisam;
+set sql_log_bin=0;
+insert into t1 values(2);
+set sql_log_bin=1;
+insert into t1 values(1),(2);
+Duplicate entry '2' for key 1
+drop table t1;
diff --git a/mysql-test/r/rpl_max_relay_size.result b/mysql-test/r/rpl_max_relay_size.result
index 1fa3fcd1adb..d74bc80c0ab 100644
--- a/mysql-test/r/rpl_max_relay_size.result
+++ b/mysql-test/r/rpl_max_relay_size.result
@@ -26,7 +26,7 @@ select @@global.max_relay_log_size;
start slave;
show slave status;
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 1 master-bin.001 50477 slave-relay-bin.004 9457 master-bin.001 Yes Yes 0 0 50477 9457
+127.0.0.1 root MASTER_PORT 1 master-bin.001 50477 slave-relay-bin.004 9457 master-bin.001 Yes Yes 0 0 50477 #
stop slave;
reset slave;
set global max_relay_log_size=0;
diff --git a/mysql-test/r/rpl_rotate_logs.result b/mysql-test/r/rpl_rotate_logs.result
index 07490744d81..89d7f4a795a 100644
--- a/mysql-test/r/rpl_rotate_logs.result
+++ b/mysql-test/r/rpl_rotate_logs.result
@@ -1,11 +1,11 @@
drop table if exists t1, t2, t3, t4;
drop table if exists t1, t2, t3, t4;
slave start;
-Could not initialize master info structure, check permisions on master.info
+Could not initialize master info structure, more error messages can be found in the MySQL error log
slave start;
-Could not initialize master info structure, check permisions on master.info
+Could not initialize master info structure, more error messages can be found in the MySQL error log
change master to master_host='127.0.0.1',master_port=MASTER_PORT, master_user='root';
-Could not initialize master info structure, check permisions on master.info
+Could not initialize master info structure, more error messages can be found in the MySQL error log
reset slave;
change master to master_host='127.0.0.1',master_port=MASTER_PORT, master_user='root';
reset master;
@@ -16,13 +16,12 @@ create table t1 (s text);
insert into t1 values('Could not break slave'),('Tried hard');
show slave status;
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 60 master-bin.001 417 slave-relay-bin.001 458 master-bin.001 Yes Yes 0 0 417 458
+127.0.0.1 root MASTER_PORT 60 master-bin.001 417 slave-relay-bin.001 458 master-bin.001 Yes Yes 0 0 417 #
select * from t1;
s
Could not break slave
Tried hard
flush logs;
-drop table if exists t2;
create table t2(m int not null auto_increment primary key);
insert into t2 values (34),(67),(123);
flush logs;
@@ -48,7 +47,7 @@ master-bin.003
insert into t2 values (65);
show slave status;
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 60 master-bin.003 290 slave-relay-bin.001 1073 master-bin.003 Yes Yes 0 0 290 1073
+127.0.0.1 root MASTER_PORT 60 master-bin.003 290 slave-relay-bin.001 1073 master-bin.003 Yes Yes 0 0 290 #
select * from t2;
m
34
@@ -58,8 +57,10 @@ m
1234
create temporary table temp_table (a char(80) not null);
insert into temp_table values ("testing temporary tables part 2");
-drop table if exists t3;
create table t3 (n int);
+select count(*) from t3 where n >= 4;
+count(*)
+100
create table t4 select * from temp_table;
show master logs;
Log_name
@@ -73,7 +74,7 @@ a
testing temporary tables part 2
show slave status;
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 60 master-bin.004 2886 slave-relay-bin.001 7870 master-bin.004 Yes Yes 0 0 2886 7870
+127.0.0.1 root MASTER_PORT 60 master-bin.004 2886 slave-relay-bin.001 7870 master-bin.004 Yes Yes 0 0 2886 #
lock tables t3 read;
select count(*) from t3 where n >= 4;
count(*)
diff --git a/mysql-test/r/rpl_trunc_binlog.result b/mysql-test/r/rpl_trunc_binlog.result
index eb5dcf7c593..272fa210807 100644
--- a/mysql-test/r/rpl_trunc_binlog.result
+++ b/mysql-test/r/rpl_trunc_binlog.result
@@ -10,4 +10,4 @@ reset slave;
start slave;
show slave status;
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 1 master-bin.002 4 slave-relay-bin.002 161 master-bin.001 Yes No 0 Rolling back unfinished transaction (no COMMIT or ROLLBACK) from relay log. Probably cause is that the master died while writing the transaction to it's binary log. 0 79 317
+127.0.0.1 root MASTER_PORT 1 master-bin.002 4 slave-relay-bin.002 161 master-bin.001 Yes No 0 Rolling back unfinished transaction (no COMMIT or ROLLBACK) from relay log. Probably cause is that the master died while writing the transaction to it's binary log. 0 79 #
diff --git a/mysql-test/r/symlink.result b/mysql-test/r/symlink.result
index 2deecae7243..d07a8613883 100644
--- a/mysql-test/r/symlink.result
+++ b/mysql-test/r/symlink.result
@@ -64,3 +64,23 @@ t9 CREATE TABLE `t9` (
PRIMARY KEY (`a`)
) TYPE=MyISAM DATA DIRECTORY='TEST_DIR/var/tmp/' INDEX DIRECTORY='TEST_DIR/var/run/'
drop database mysqltest;
+create table t1 (a int not null) type=myisam;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL default '0'
+) TYPE=MyISAM
+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
+) TYPE=MyISAM
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL default '0',
+ `b` int(11) default NULL
+) TYPE=MyISAM
+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 ad390c9fa92..1b387214292 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;
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 d7c41743bf3..0bb9146fafc 100644
--- a/mysql-test/r/type_blob.result
+++ b/mysql-test/r/type_blob.result
@@ -455,3 +455,149 @@ select if(imagem is null, "ERROR", "OK"),length(imagem) from t1 where id = 1;
if(imagem is null, "ERROR", "OK") length(imagem)
OK 581
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
+3 NULL
+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
+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_decimal.result b/mysql-test/r/type_decimal.result
index b74765696a2..5268ff3696b 100644
--- a/mysql-test/r/type_decimal.result
+++ b/mysql-test/r/type_decimal.result
@@ -363,3 +363,198 @@ CREATE TABLE t1 (a_dec DECIMAL(-2,1));
Too big column length for column 'a_dec' (max = 255). Use BLOB instead
CREATE TABLE t1 (a_dec DECIMAL(-1,1));
Too big column length for column 'a_dec' (max = 255). Use BLOB instead
+create table t1(a decimal(7,3));
+insert into t1 values ('1'),('+1'),('-1'),('0000000001'),('+0000000001'),('-0000000001'),('10'),('+10'),('-10'),('0000000010'),('+0000000010'),('-0000000010'),('100'),('+100'),('-100'),('0000000100'),('+0000000100'),('-0000000100'),('1000'),('+1000'),('-1000'),('0000001000'),('+0000001000'),('-0000001000'),('10000'),('+10000'),('-10000'),('0000010000'),('+0000010000'),('-0000010000'),('100000'),('+100000'),('-100000'),('0000100000'),('+0000100000'),('-0000100000'),('1000000'),('+1000000'),('-1000000'),('0001000000'),('+0001000000'),('-0001000000'),('10000000'),('+10000000'),('-10000000'),('0010000000'),('+0010000000'),('-0010000000'),('100000000'),('+100000000'),('-100000000'),('0100000000'),('+0100000000'),('-0100000000'),('1000000000'),('+1000000000'),('-1000000000'),('1000000000'),('+1000000000'),('-1000000000');
+select * from t1;
+a
+1.000
++1.000
+-1.000
+00001.000
++0001.000
+-0001.000
+10.000
++10.000
+-10.000
+00010.000
++0010.000
+-0010.000
+100.000
++100.000
+-100.000
+00100.000
++0100.000
+-0100.000
+1000.000
++1000.000
+-1000.000
+01000.000
++1000.000
+-1000.000
+10000.000
+10000.000
+-9999.999
+10000.000
+10000.000
+-9999.999
+99999.999
+99999.999
+-9999.999
+99999.999
+99999.999
+-9999.999
+99999.999
+99999.999
+-9999.999
+99999.999
+99999.999
+-9999.999
+99999.999
+99999.999
+-9999.999
+99999.999
+99999.999
+-9999.999
+99999.999
+99999.999
+-9999.999
+99999.999
+99999.999
+-9999.999
+99999.999
+99999.999
+-9999.999
+99999.999
+99999.999
+-9999.999
+drop table t1;
+create table t1(a decimal(7,3) unsigned);
+insert into t1 values ('1'),('+1'),('-1'),('0000000001'),('+0000000001'),('-0000000001'),('10'),('+10'),('-10'),('0000000010'),('+0000000010'),('-0000000010'),('100'),('+100'),('-100'),('0000000100'),('+0000000100'),('-0000000100'),('1000'),('+1000'),('-1000'),('0000001000'),('+0000001000'),('-0000001000'),('10000'),('+10000'),('-10000'),('0000010000'),('+0000010000'),('-0000010000'),('100000'),('+100000'),('-100000'),('0000100000'),('+0000100000'),('-0000100000'),('1000000'),('+1000000'),('-1000000'),('0001000000'),('+0001000000'),('-0001000000'),('10000000'),('+10000000'),('-10000000'),('0010000000'),('+0010000000'),('-0010000000'),('100000000'),('+100000000'),('-100000000'),('0100000000'),('+0100000000'),('-0100000000'),('1000000000'),('+1000000000'),('-1000000000'),('1000000000'),('+1000000000'),('-1000000000');
+select * from t1;
+a
+1.000
++1.000
+0.000
+0001.000
++001.000
+0.000
+10.000
++10.000
+0.000
+0010.000
++010.000
+0.000
+100.000
++100.000
+0.000
+0100.000
++100.000
+0.000
+1000.000
+1000.000
+0.000
+1000.000
+1000.000
+0.000
+9999.999
+9999.999
+0.000
+9999.999
+9999.999
+0.000
+9999.999
+9999.999
+0.000
+9999.999
+9999.999
+0.000
+9999.999
+9999.999
+0.000
+9999.999
+9999.999
+0.000
+9999.999
+9999.999
+0.000
+9999.999
+9999.999
+0.000
+9999.999
+9999.999
+0.000
+9999.999
+9999.999
+0.000
+9999.999
+9999.999
+0.000
+9999.999
+9999.999
+0.000
+drop table t1;
+create table t1(a decimal(7,3) zerofill);
+insert into t1 values ('1'),('+1'),('-1'),('0000000001'),('+0000000001'),('-0000000001'),('10'),('+10'),('-10'),('0000000010'),('+0000000010'),('-0000000010'),('100'),('+100'),('-100'),('0000000100'),('+0000000100'),('-0000000100'),('1000'),('+1000'),('-1000'),('0000001000'),('+0000001000'),('-0000001000'),('10000'),('+10000'),('-10000'),('0000010000'),('+0000010000'),('-0000010000'),('100000'),('+100000'),('-100000'),('0000100000'),('+0000100000'),('-0000100000'),('1000000'),('+1000000'),('-1000000'),('0001000000'),('+0001000000'),('-0001000000'),('10000000'),('+10000000'),('-10000000'),('0010000000'),('+0010000000'),('-0010000000'),('100000000'),('+100000000'),('-100000000'),('0100000000'),('+0100000000'),('-0100000000'),('1000000000'),('+1000000000'),('-1000000000'),('1000000000'),('+1000000000'),('-1000000000');
+select * from t1;
+a
+0001.000
+0001.000
+0000.000
+0001.000
+0001.000
+0000.000
+0010.000
+0010.000
+0000.000
+0010.000
+0010.000
+0000.000
+0100.000
+0100.000
+0000.000
+0100.000
+0100.000
+0000.000
+1000.000
+1000.000
+0000.000
+1000.000
+1000.000
+0000.000
+9999.999
+9999.999
+0000.000
+9999.999
+9999.999
+0000.000
+9999.999
+9999.999
+0000.000
+9999.999
+9999.999
+0000.000
+9999.999
+9999.999
+0000.000
+9999.999
+9999.999
+0000.000
+9999.999
+9999.999
+0000.000
+9999.999
+9999.999
+0000.000
+9999.999
+9999.999
+0000.000
+9999.999
+9999.999
+0000.000
+9999.999
+9999.999
+0000.000
+9999.999
+9999.999
+0000.000
+drop table t1;
diff --git a/mysql-test/r/type_enum.result b/mysql-test/r/type_enum.result
index ee3bd077798..03cfdc3c286 100644
--- a/mysql-test/r/type_enum.result
+++ b/mysql-test/r/type_enum.result
@@ -1636,3 +1636,13 @@ t1 CREATE TABLE `t1` (
`a` enum('','a','b') NOT NULL default 'b'
) TYPE=MyISAM
drop table t1;
+create table t1 (a enum ('0','1'));
+insert into t1 set a='foobar';
+select * from t1;
+a
+
+update t1 set a = replace(a,'x','y');
+select * from t1;
+a
+
+drop table t1;
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 5fba4bb9234..8c614131684 100644
--- a/mysql-test/t/auto_increment.test
+++ b/mysql-test/t/auto_increment.test
@@ -70,3 +70,22 @@ select * from t1;
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;
diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test
index b07b0b635c1..33d89b3ca37 100644
--- a/mysql-test/t/func_str.test
+++ b/mysql-test/t/func_str.test
@@ -67,6 +67,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 deb3358da00..99824ab121d 100644
--- a/mysql-test/t/func_time.test
+++ b/mysql-test/t/func_time.test
@@ -201,3 +201,10 @@ select * from t1, t2 where t1.start between t2.ctime1 and t2.ctime2;
select * from t1, t2 where t1.start >= t2.ctime1 and t1.start <= t2.ctime2;
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');
diff --git a/mysql-test/t/handler.test b/mysql-test/t/handler.test
index 737b220c805..736091a52a9 100644
--- a/mysql-test/t/handler.test
+++ b/mysql-test/t/handler.test
@@ -75,7 +75,7 @@ insert into t1 values (17);
--error 1109
handler t2 read first;
handler t1 open as t2;
-alter table t1 type=MyISAM;
+alter table t1 engine=MyISAM;
--error 1109
handler t2 read first;
drop table t1;
diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test
index ea9c5e0cf55..7cc509caf74 100644
--- a/mysql-test/t/innodb.test
+++ b/mysql-test/t/innodb.test
@@ -857,3 +857,15 @@ 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) type=innodb;
+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/insert.test b/mysql-test/t/insert.test
index fbb9134ff7f..12dfe6e50a9 100644
--- a/mysql-test/t/insert.test
+++ b/mysql-test/t/insert.test
@@ -68,7 +68,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 ee7d55d2a4e..bed4d4b033b 100644
--- a/mysql-test/t/join_outer.test
+++ b/mysql-test/t/join_outer.test
@@ -437,3 +437,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/loaddata.test b/mysql-test/t/loaddata.test
index 732ed248702..9269eb19b05 100644
--- a/mysql-test/t/loaddata.test
+++ b/mysql-test/t/loaddata.test
@@ -18,3 +18,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 86ea2918fd2..5bc19f26c0e 100644
--- a/mysql-test/t/lowercase_table.test
+++ b/mysql-test/t/lowercase_table.test
@@ -2,19 +2,22 @@
# Test of --lower-case-table-names
#
-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;
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;
--error 1109
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 7aa4e74cec0..56dcf9a03a9 100644
--- a/mysql-test/t/multi_update.test
+++ b/mysql-test/t/multi_update.test
@@ -267,3 +267,39 @@ insert into t2 values (1,1), (3,1);
update t1 left join t2 on t1.a=t2.a set t1.b=2, t2.b=2 where t1.b=1 and t2.b=1 or t2.a is NULL;
select t1.a, t1.b,t2.a, t2.b from t1 left join t2 on t1.a=t2.a where t1.b=1 and t2.b=1 or t2.a is NULL;
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
+
+drop table if exists t1, t2;
+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;
+
diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test
index 525949bd602..bc63dc37d96 100644
--- a/mysql-test/t/mysqldump.test
+++ b/mysql-test/t/mysqldump.test
@@ -25,5 +25,8 @@ DROP TABLE t1;
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;
diff --git a/mysql-test/t/rpl_EE_error.test b/mysql-test/t/rpl_EE_error.test
new file mode 100644
index 00000000000..de69c4897c3
--- /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) type=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)) type=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_log_pos.test b/mysql-test/t/rpl_log_pos.test
index e11ba92cfa7..859180d4e25 100644
--- a/mysql-test/t/rpl_log_pos.test
+++ b/mysql-test/t/rpl_log_pos.test
@@ -23,9 +23,9 @@ sleep 5;
show slave status;
slave stop;
change master to master_log_pos=173;
---replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT
slave start;
sleep 2;
+--replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT
show slave status;
connection master;
show master status;
diff --git a/mysql-test/t/rpl_max_relay_size.test b/mysql-test/t/rpl_max_relay_size.test
index a2167b1ef36..7e9a8a1872e 100644
--- a/mysql-test/t/rpl_max_relay_size.test
+++ b/mysql-test/t/rpl_max_relay_size.test
@@ -37,6 +37,7 @@ select @@global.max_relay_log_size;
start slave;
sync_with_master;
--replace_result $MASTER_MYPORT MASTER_PORT 3306 MASTER_PORT 3334 MASTER_PORT
+--replace_column 18 #
show slave status;
stop slave;
reset slave;
diff --git a/mysql-test/t/rpl_rotate_logs.test b/mysql-test/t/rpl_rotate_logs.test
index c4dc5de38da..70366fc1749 100644
--- a/mysql-test/t/rpl_rotate_logs.test
+++ b/mysql-test/t/rpl_rotate_logs.test
@@ -50,11 +50,11 @@ save_master_pos;
connection slave;
sync_with_master;
--replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT
+--replace_column 18 #
show slave status;
select * from t1;
connection master;
flush logs;
-drop table if exists t2;
create table t2(m int not null auto_increment primary key);
insert into t2 values (34),(67),(123);
flush logs;
@@ -102,6 +102,7 @@ save_master_pos;
connection slave;
sync_with_master;
--replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT
+--replace_column 18 #
show slave status;
select * from t2;
@@ -113,7 +114,7 @@ connection master;
create temporary table temp_table (a char(80) not null);
insert into temp_table values ("testing temporary tables part 2");
let $1=100;
-drop table if exists t3;
+
create table t3 (n int);
disable_query_log;
while ($1)
@@ -123,17 +124,17 @@ while ($1)
dec $1;
}
enable_query_log;
+select count(*) from t3 where n >= 4;
create table t4 select * from temp_table;
show master logs;
show master status;
save_master_pos;
connection slave;
-#slave stop;
-#slave start;
sync_with_master;
select * from t4;
--replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT
+--replace_column 18 #
show slave status;
# because of concurrent insert, the table may not be up to date
# if we do not lock
diff --git a/mysql-test/t/rpl_trunc_binlog.test b/mysql-test/t/rpl_trunc_binlog.test
index 2c34b7a442f..98138b61ab7 100644
--- a/mysql-test/t/rpl_trunc_binlog.test
+++ b/mysql-test/t/rpl_trunc_binlog.test
@@ -21,4 +21,5 @@ start slave;
# can't sync_with_master so we must sleep
sleep 3;
--replace_result $MASTER_MYPORT MASTER_PORT
+--replace_column 18 #
show slave status;
diff --git a/mysql-test/t/symlink.test b/mysql-test/t/symlink.test
index 5e1fe313a7e..7a42a60054e 100644
--- a/mysql-test/t/symlink.test
+++ b/mysql-test/t/symlink.test
@@ -90,3 +90,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 eeb79f497fa..3acab9f56de 100644
--- a/mysql-test/t/truncate.test
+++ b/mysql-test/t/truncate.test
@@ -21,3 +21,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 4132b1f48a4..cf5c0d6e581 100644
--- a/mysql-test/t/type_blob.test
+++ b/mysql-test/t/type_blob.test
@@ -263,3 +263,52 @@ insert into t1 (id) values (1);
update t1 set imagem=load_file('../../std_data/words.dat') where id=1;
select if(imagem is null, "ERROR", "OK"),length(imagem) from t1 where id = 1;
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_decimal.test b/mysql-test/t/type_decimal.test
index 7aedc051905..82e53e7bde6 100644
--- a/mysql-test/t/type_decimal.test
+++ b/mysql-test/t/type_decimal.test
@@ -240,3 +240,20 @@ CREATE TABLE t1 (a_dec DECIMAL(-1,0));
CREATE TABLE t1 (a_dec DECIMAL(-2,1));
--error 1074
CREATE TABLE t1 (a_dec DECIMAL(-1,1));
+
+#
+# Zero prepend overflow bug
+#
+
+create table t1(a decimal(7,3));
+insert into t1 values ('1'),('+1'),('-1'),('0000000001'),('+0000000001'),('-0000000001'),('10'),('+10'),('-10'),('0000000010'),('+0000000010'),('-0000000010'),('100'),('+100'),('-100'),('0000000100'),('+0000000100'),('-0000000100'),('1000'),('+1000'),('-1000'),('0000001000'),('+0000001000'),('-0000001000'),('10000'),('+10000'),('-10000'),('0000010000'),('+0000010000'),('-0000010000'),('100000'),('+100000'),('-100000'),('0000100000'),('+0000100000'),('-0000100000'),('1000000'),('+1000000'),('-1000000'),('0001000000'),('+0001000000'),('-0001000000'),('10000000'),('+10000000'),('-10000000'),('0010000000'),('+0010000000'),('-0010000000'),('100000000'),('+100000000'),('-100000000'),('0100000000'),('+0100000000'),('-0100000000'),('1000000000'),('+1000000000'),('-1000000000'),('1000000000'),('+1000000000'),('-1000000000');
+select * from t1;
+drop table t1;
+create table t1(a decimal(7,3) unsigned);
+insert into t1 values ('1'),('+1'),('-1'),('0000000001'),('+0000000001'),('-0000000001'),('10'),('+10'),('-10'),('0000000010'),('+0000000010'),('-0000000010'),('100'),('+100'),('-100'),('0000000100'),('+0000000100'),('-0000000100'),('1000'),('+1000'),('-1000'),('0000001000'),('+0000001000'),('-0000001000'),('10000'),('+10000'),('-10000'),('0000010000'),('+0000010000'),('-0000010000'),('100000'),('+100000'),('-100000'),('0000100000'),('+0000100000'),('-0000100000'),('1000000'),('+1000000'),('-1000000'),('0001000000'),('+0001000000'),('-0001000000'),('10000000'),('+10000000'),('-10000000'),('0010000000'),('+0010000000'),('-0010000000'),('100000000'),('+100000000'),('-100000000'),('0100000000'),('+0100000000'),('-0100000000'),('1000000000'),('+1000000000'),('-1000000000'),('1000000000'),('+1000000000'),('-1000000000');
+select * from t1;
+drop table t1;
+create table t1(a decimal(7,3) zerofill);
+insert into t1 values ('1'),('+1'),('-1'),('0000000001'),('+0000000001'),('-0000000001'),('10'),('+10'),('-10'),('0000000010'),('+0000000010'),('-0000000010'),('100'),('+100'),('-100'),('0000000100'),('+0000000100'),('-0000000100'),('1000'),('+1000'),('-1000'),('0000001000'),('+0000001000'),('-0000001000'),('10000'),('+10000'),('-10000'),('0000010000'),('+0000010000'),('-0000010000'),('100000'),('+100000'),('-100000'),('0000100000'),('+0000100000'),('-0000100000'),('1000000'),('+1000000'),('-1000000'),('0001000000'),('+0001000000'),('-0001000000'),('10000000'),('+10000000'),('-10000000'),('0010000000'),('+0010000000'),('-0010000000'),('100000000'),('+100000000'),('-100000000'),('0100000000'),('+0100000000'),('-0100000000'),('1000000000'),('+1000000000'),('-1000000000'),('1000000000'),('+1000000000'),('-1000000000');
+select * from t1;
+drop table t1;
diff --git a/mysql-test/t/type_enum.test b/mysql-test/t/type_enum.test
index 8f399e4364e..78b850b6ea6 100644
--- a/mysql-test/t/type_enum.test
+++ b/mysql-test/t/type_enum.test
@@ -21,3 +21,14 @@ drop table t1;
create table t1 (a enum (' ','a','b ') not null default 'b ');
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; \ No newline at end of file
diff --git a/mysys/my_lib.c b/mysys/my_lib.c
index 426acedc646..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))
{
- do
+ 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
+ {
+#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;
+ finfo.mystat->st_mode=mode;
#ifdef __BORLANDC__
- fnames[fcnt].mystat.st_mtime=((uint32) find.ff_ftime);
+ finfo.mystat->st_mtime=((uint32) find.ff_ftime);
#else
- fnames[fcnt].mystat.st_mtime=((uint32) find.time_write);
-#endif
- ++fcnt;
-#ifdef __BORLANDC__
- } while ((eof= findnext(&find)) == 0 && fcnt < maxfcnt);
-#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))
{
- do
+ 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
+ {
+ 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);
diff --git a/mysys/my_symlink.c b/mysys/my_symlink.c
index abef0096e28..b366678769e 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/sql/field.cc b/sql/field.cc
index d43089ec35c..fd0bea83a05 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -632,7 +632,7 @@ void Field_decimal::store(const char *from,uint len)
if (zerofill)
{
left_wall=to-1;
- while (pos != left_wall) // Fill with zeros
+ while (pos > left_wall) // Fill with zeros
*pos--='0';
}
else
@@ -640,7 +640,7 @@ void Field_decimal::store(const char *from,uint len)
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';
}
@@ -2589,7 +2589,7 @@ void Field_timestamp::store(longlong nr)
{
long not_used;
- 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++;
timestamp=0;
@@ -4623,7 +4623,7 @@ void Field_enum::store(const char *from,uint length)
uint tmp=find_enum(typelib,from,length);
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 buff[7], *end;
@@ -4721,7 +4721,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((const char*)"",0);
else
val_ptr->set((const char*) typelib->type_names[tmp-1],
(uint) strlen(typelib->type_names[tmp-1]));
diff --git a/sql/field.h b/sql/field.h
index 3186f9f5275..8a829a455ed 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -799,9 +799,10 @@ public:
binary_flag(binary_arg)
{
if (binary_arg)
- flags|=BINARY_FLAG;
+ flags|= BINARY_FLAG;
}
- Field_varstring(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg,
+ Field_varstring(uint32 len_arg,bool maybe_null_arg,
+ const char *field_name_arg,
struct st_table *table_arg, bool binary_arg)
:Field_str((char*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0,0,
NONE, field_name_arg, table_arg),
@@ -856,7 +857,7 @@ public:
{
flags|= BLOB_FLAG;
if (binary_arg)
- flags|=BINARY_FLAG;
+ flags|= BINARY_FLAG;
}
enum_field_types type() const { return FIELD_TYPE_BLOB;}
enum ha_base_keytype key_type() const
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 47c49b79d77..beff8c1f515 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -1788,7 +1788,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;
@@ -3270,7 +3270,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 60fc383d757..fcc9372773a 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -117,6 +117,14 @@ bool Item::get_time(TIME *ltime)
return 0;
}
+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)
+{
+ name = (char*) field_name_par;
+}
+
+
Item_field::Item_field(Field *f) :Item_ident(NullS,f->table_name,f->field_name)
{
set_field(f);
diff --git a/sql/item.h b/sql/item.h
index e8a6313b6a0..f96f4cd506a 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -119,9 +119,7 @@ public:
const char *table_name;
const char *field_name;
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)
- { name = (char*) field_name_par; }
+ const char *field_name_par);
const char *full_name() const;
unsigned int size_of() { return sizeof(*this);}
};
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 7434f6bd57b..a4d04253dd7 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -2169,7 +2169,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/lex.h b/sql/lex.h
index 3bbe1da185e..10ba11f2169 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -131,6 +131,7 @@ static SYMBOL symbols[] = {
{ "DYNAMIC", SYM(DYNAMIC_SYM),0,0},
{ "END", SYM(END),0,0},
{ "ELSE", SYM(ELSE),0,0},
+ { "ENGINE", SYM(TYPE_SYM),0,0}, /* Alias for TYPE= */
{ "ESCAPE", SYM(ESCAPE_SYM),0,0},
{ "ESCAPED", SYM(ESCAPED),0,0},
{ "ENABLE", SYM(ENABLE_SYM),0,0},
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 9779b7401dd..4413a77c364 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -1922,7 +1922,7 @@ Default database: '%s'",
// assume no convert for next query unless set explictly
thd->variables.convert_set = 0;
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));
}
@@ -2094,10 +2094,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->fatal_error)
{
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 04529919990..d0e0e6992fa 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -364,6 +364,7 @@ void mysql_execute_command(void);
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
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index b75a94a261c..cc17b4e97fd 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -500,6 +500,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();
/****************************************************************************
** Code to end mysqld
@@ -1459,17 +1461,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 | O_TRUNC, MYF(MY_WME))) >= 0)
- {
- char buff[21];
- sprintf(buff,"%lu\n",(ulong) getpid());
- (void) my_write(pidFile, buff,strlen(buff),MYF(MY_WME));
- (void) my_close(pidFile,MYF(0));
- }
- }
+ create_pid_file();
// no signal handler
}
@@ -1753,17 +1745,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 | O_TRUNC, 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();
+
#ifdef HAVE_STACK_TRACE_ON_SEGV
if (opt_do_pstack)
{
@@ -2610,8 +2593,8 @@ int main(int argc, char **argv)
{
char file_path[FN_REFLEN];
my_path(file_path, argv[0], ""); /* Find name in path */
- fn_format(file_path,argv[0],file_path,"",MY_REPLACE_DIR+
- MY_UNPACK_FILENAME | MY_RESOLVE_SYMLINKS);
+ fn_format(file_path,argv[0],file_path,"",
+ MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_RESOLVE_SYMLINKS);
if (argc == 2)
{
if (!default_service_handling(argv, MYSQL_SERVICENAME, MYSQL_SERVICENAME,
@@ -4963,6 +4946,17 @@ static void fix_paths(void)
if (!(slave_load_tmpdir = (char*) my_strdup(mysql_tmpdir, MYF(MY_FAE))))
exit(1);
}
+
+ /*
+ 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 becasue file system %s is case insensitve", mysql_real_data_home);
+ }
}
@@ -5096,6 +5090,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 b18d3d00d88..8a3757a9768 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 02b7699fad6..74e3f855db7 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -942,9 +942,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)
@@ -1056,15 +1057,38 @@ 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);
- 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) {
@@ -2233,7 +2257,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
@@ -2367,7 +2392,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,
@@ -2412,7 +2438,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);
}
}
@@ -2465,7 +2491,8 @@ QUICK_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, TABLE_REF *ref)
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 fd46506203f..415e75a467b 100644
--- a/sql/records.cc
+++ b/sql/records.cc
@@ -99,11 +99,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/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt
index 6e8f060b6b1..e36475d7803 100644
--- a/sql/share/czech/errmsg.txt
+++ b/sql/share/czech/errmsg.txt
@@ -211,7 +211,7 @@
"This operation cannot be performed with a running slave, run SLAVE STOP first",
"This operation requires a running slave, configure slave and do SLAVE START",
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
-"Could not initialize master info structure, check permisions on master.info",
+"Could not initialize master info structure, more error messages can be found in the MySQL error log",
"Could not create slave thread, check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
"You may only use constant expressions with SET",
diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt
index 9d4fd9af41c..7104eb64d56 100644
--- a/sql/share/english/errmsg.txt
+++ b/sql/share/english/errmsg.txt
@@ -202,7 +202,7 @@
"This operation cannot be performed with a running slave, run SLAVE STOP first",
"This operation requires a running slave, configure slave and do SLAVE START",
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
-"Could not initialize master info structure, check permisions on master.info",
+"Could not initialize master info structure, more error messages can be found in the MySQL error log",
"Could not create slave thread, check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
"You may only use constant expressions with SET",
diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt
index 6cbd7249374..f583568193f 100644
--- a/sql/share/estonian/errmsg.txt
+++ b/sql/share/estonian/errmsg.txt
@@ -207,7 +207,7 @@
"This operation cannot be performed with a running slave, run SLAVE STOP first",
"This operation requires a running slave, configure slave and do SLAVE START",
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
-"Could not initialize master info structure, check permisions on master.info",
+"Could not initialize master info structure, more error messages can be found in the MySQL error log",
"Could not create slave thread, check system resources",
"Kasutajal %-.64s on juba rohkem ühendusi kui lubatud 'max_user_connections' muutujaga",
"Ainult konstantsed suurused on lubatud SET klauslis",
diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt
index d85ef75bb3a..cabb22a6494 100644
--- a/sql/share/french/errmsg.txt
+++ b/sql/share/french/errmsg.txt
@@ -202,7 +202,7 @@
"Cette opération ne peut être réalisée avec un esclave actif, faites SLAVE STOP d'abord",
"Cette opération nécessite un esclave actif, configurez les esclaves et faites SLAVE START",
"Le server n'est pas configuré comme un esclave, changez le fichier de configuration ou utilisez CHANGE MASTER TO",
-"Impossible d'initialiser les structures d'information de maître, vérifiez les permissions sur master.info",
+"Impossible d'initialiser les structures d'information de maître, vous trouverez des messages d'erreur supplémentaires dans le journal des erreurs de MySQL",
"Impossible de créer une tâche esclave, vérifiez les ressources système",
"L'utilisateur %-.64s possède déjà plus de 'max_user_connections' connections actives",
"Seules les expressions constantes sont autorisées avec SET",
diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt
index e9d812cab0f..d993d80dcc1 100644
--- a/sql/share/greek/errmsg.txt
+++ b/sql/share/greek/errmsg.txt
@@ -202,7 +202,7 @@
"This operation cannot be performed with a running slave, run SLAVE STOP first",
"This operation requires a running slave, configure slave and do SLAVE START",
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
-"Could not initialize master info structure, check permisions on master.info",
+"Could not initialize master info structure, more error messages can be found in the MySQL error log",
"Could not create slave thread, check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
"You may only use constant expressions with SET",
diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt
index 5390511ba74..4a65e735ef9 100644
--- a/sql/share/hungarian/errmsg.txt
+++ b/sql/share/hungarian/errmsg.txt
@@ -204,7 +204,7 @@
"This operation cannot be performed with a running slave, run SLAVE STOP first",
"This operation requires a running slave, configure slave and do SLAVE START",
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
-"Could not initialize master info structure, check permisions on master.info",
+"Could not initialize master info structure, more error messages can be found in the MySQL error log",
"Could not create slave thread, check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
"You may only use constant expressions with SET",
diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt
index 89a770d0be8..c384c4bded4 100644
--- a/sql/share/japanese/errmsg.txt
+++ b/sql/share/japanese/errmsg.txt
@@ -204,7 +204,7 @@
"This operation cannot be performed with a running slave, run SLAVE STOP first",
"This operation requires a running slave, configure slave and do SLAVE START",
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
-"Could not initialize master info structure, check permisions on master.info",
+"Could not initialize master info structure, more error messages can be found in the MySQL error log",
"Could not create slave thread, check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
"You may only use constant expressions with SET",
diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt
index f808a7f0f5d..b706069b495 100644
--- a/sql/share/korean/errmsg.txt
+++ b/sql/share/korean/errmsg.txt
@@ -202,7 +202,7 @@
"This operation cannot be performed with a running slave, run SLAVE STOP first",
"This operation requires a running slave, configure slave and do SLAVE START",
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
-"Could not initialize master info structure, check permisions on master.info",
+"Could not initialize master info structure, more error messages can be found in the MySQL error log",
"Could not create slave thread, check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
"You may only use constant expressions with SET",
diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt
index 4a8207bebff..2c1deead312 100644
--- a/sql/share/norwegian-ny/errmsg.txt
+++ b/sql/share/norwegian-ny/errmsg.txt
@@ -204,7 +204,7 @@
"This operation cannot be performed with a running slave, run SLAVE STOP first",
"This operation requires a running slave, configure slave and do SLAVE START",
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
-"Could not initialize master info structure, check permisions on master.info",
+"Could not initialize master info structure, more error messages can be found in the MySQL error log",
"Could not create slave thread, check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
"You may only use constant expressions with SET",
diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt
index e441ef3e3fc..42b35c18cfc 100644
--- a/sql/share/norwegian/errmsg.txt
+++ b/sql/share/norwegian/errmsg.txt
@@ -204,7 +204,7 @@
"This operation cannot be performed with a running slave, run SLAVE STOP first",
"This operation requires a running slave, configure slave and do SLAVE START",
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
-"Could not initialize master info structure, check permisions on master.info",
+"Could not initialize master info structure, more error messages can be found in the MySQL error log",
"Could not create slave thread, check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
"You may only use constant expressions with SET",
diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt
index 4429a187599..d8e84b08a9a 100644
--- a/sql/share/polish/errmsg.txt
+++ b/sql/share/polish/errmsg.txt
@@ -206,7 +206,7 @@
"This operation cannot be performed with a running slave, run SLAVE STOP first",
"This operation requires a running slave, configure slave and do SLAVE START",
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
-"Could not initialize master info structure, check permisions on master.info",
+"Could not initialize master info structure, more error messages can be found in the MySQL error log",
"Could not create slave thread, check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
"You may only use constant expressions with SET",
diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt
index 49524349087..44e8b9fa8de 100644
--- a/sql/share/romanian/errmsg.txt
+++ b/sql/share/romanian/errmsg.txt
@@ -206,7 +206,7 @@
"This operation cannot be performed with a running slave, run SLAVE STOP first",
"This operation requires a running slave, configure slave and do SLAVE START",
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
-"Could not initialize master info structure, check permisions on master.info",
+"Could not initialize master info structure, more error messages can be found in the MySQL error log",
"Could not create slave thread, check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
"You may only use constant expressions with SET",
diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt
index 31bdd40dd62..411f93b97da 100644
--- a/sql/share/slovak/errmsg.txt
+++ b/sql/share/slovak/errmsg.txt
@@ -210,7 +210,7 @@
"This operation cannot be performed with a running slave, run SLAVE STOP first",
"This operation requires a running slave, configure slave and do SLAVE START",
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
-"Could not initialize master info structure, check permisions on master.info",
+"Could not initialize master info structure, more error messages can be found in the MySQL error log",
"Could not create slave thread, check system resources",
"User %-.64s has already more than 'max_user_connections' active connections",
"You may only use constant expressions with SET",
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 03a359d44e7..6df636386d6 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -1130,6 +1130,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);
@@ -1202,11 +1203,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_base.cc b/sql/sql_base.cc
index dd80062d6e7..9937336fb4a 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -575,8 +575,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;
@@ -1721,6 +1721,19 @@ find_field_in_tables(THD *thd,Item_field *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);
+ casedn_str(name_buff);
+ db= name_buff;
+ }
if (table_name)
{ /* Qualified field */
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 9287a0c8c79..632e7b49d9f 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -590,6 +590,15 @@ public:
void add_changed_table(TABLE *table);
void add_changed_table(const char *key, long key_length);
CHANGED_TABLE_LIST * changed_table_dup(const char *key, long key_length);
+#ifndef EMBEDDED_LIBRARY
+ inline void clear_error()
+ {
+ net.last_error[0]= 0;
+ net.last_errno= 0;
+ }
+#else
+ void clear_error();
+#endif
};
/* Flags for the THD::system_thread (bitmap) variable */
@@ -608,7 +617,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() {}
};
@@ -844,10 +853,11 @@ 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;
+
public:
multi_delete(THD *thd, TABLE_LIST *dt, uint num_of_tables);
~multi_delete();
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index 6251b1ec624..6c11067ac8f 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -86,6 +86,7 @@ int mysql_create_db(THD *thd, char *db, uint create_options, bool silent)
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);
}
@@ -176,6 +177,7 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
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_delete.cc b/sql/sql_delete.cc
index ee2b720907d..7ca259425aa 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -181,6 +181,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)
@@ -234,7 +236,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)
{
@@ -337,6 +339,7 @@ bool multi_delete::send_data(List<Item> &values)
continue;
table->file->position(table->record[0]);
+ found++;
if (secure_counter < 0)
{
@@ -412,7 +415,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)
@@ -422,6 +425,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++)
@@ -485,6 +490,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)
@@ -597,6 +604,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 a92379a6d3b..75a37e4035c 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -310,6 +310,8 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
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)
@@ -1196,7 +1198,7 @@ bool delayed_insert::handle_inserts(void)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
using_ignore=1;
}
- thd.net.last_errno = 0; // reset error for binlog
+ thd.clear_error(); // reset error for binlog
if (write_record(table,&info))
{
info.error_count++; // Ignore errors
@@ -1391,6 +1393,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);
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index e692e7b8dab..7c3e7b8e877 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -71,10 +71,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,
@@ -85,14 +86,15 @@ 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;
LOAD_FILE_INFO lf_info;
char *db = table_list->db; // This is never null
/* 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
@@ -235,16 +237,18 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
thd->count_cuted_fields=1; /* 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;
@@ -260,9 +264,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))
@@ -271,7 +277,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=0; /* Don`t calc cuted fields */
@@ -369,7 +376,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;
@@ -388,6 +395,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
@@ -444,7 +462,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;
@@ -494,6 +512,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())
@@ -821,7 +845,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 d59dda43d67..50e515d7179 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -56,7 +56,6 @@ static int check_for_max_user_connections(USER_CONN *uc);
static void decrease_user_connections(USER_CONN *uc);
static bool check_db_used(THD *thd,TABLE_LIST *tables);
static bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *tables);
-static bool check_dup(const char *db, const char *name, TABLE_LIST *tables);
static void mysql_init_query(THD *thd);
static void remove_escape(char *name);
static void refresh_status(void);
@@ -1972,12 +1971,11 @@ mysql_execute_command(void)
case SQLCOM_REPLACE_SELECT:
case SQLCOM_INSERT_SELECT:
{
-
- /*
- Check that we have modify privileges for the first table and
- select privileges for the rest
- */
{
+ /*
+ Check that we have modify privileges for the first table and
+ select privileges for the rest
+ */
ulong privilege= (lex->sql_command == SQLCOM_INSERT_SELECT ?
INSERT_ACL : INSERT_ACL | DELETE_ACL);
TABLE_LIST *save_next=tables->next;
@@ -1990,6 +1988,10 @@ mysql_execute_command(void)
if ((res=check_table_access(thd, SELECT_ACL, save_next)))
goto error;
}
+ /* 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;
@@ -2460,6 +2462,7 @@ mysql_execute_command(void)
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);
}
@@ -2480,6 +2483,7 @@ mysql_execute_command(void)
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);
}
@@ -3600,7 +3604,7 @@ void add_join_natural(TABLE_LIST *a,TABLE_LIST *b)
/* Check if name is used in table list */
-static bool check_dup(const char *db, const char *name, TABLE_LIST *tables)
+bool check_dup(const char *db, const char *name, TABLE_LIST *tables)
{
for (; tables ; tables=tables->next)
if (!strcmp(name,tables->real_name) && !strcmp(db,tables->db))
diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc
index d7e998264f3..05d31c173d3 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 892ad02bb5b..45defba4a94 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1261,7 +1261,8 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
} while (keyuse->table == table && keyuse->key == key);
if (eq_part == PREV_BITS(uint,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)
@@ -1683,10 +1684,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;
}
@@ -1777,13 +1774,26 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
{
KEY_FIELD *key_fields,*end;
+ KEY_FIELD *field;
if (!(key_fields=(KEY_FIELD*)
thd->alloc(sizeof(key_fields[0])*(thd->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)
@@ -1792,10 +1802,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);
}
@@ -2020,7 +2028,8 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
if (found_part == PREV_BITS(uint,keyinfo->key_parts))
{ /* 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;
@@ -2520,8 +2529,8 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
if (j->type == JT_FT) /* no-op */;
else if (j->type == JT_CONST)
j->table->const_table=1;
- else if (((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY))
- != HA_NOSAME) ||
+ else if (((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY |
+ HA_END_SPACE_KEY)) != HA_NOSAME) ||
keyparts != keyinfo->key_parts)
j->type=JT_REF; /* Must read with repeat */
else if (ref_key == j->ref.key_copy)
@@ -5814,7 +5823,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 cb6cd18b7c8..1a2f900eb7e 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -213,7 +213,7 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path,
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)))
continue;
}
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 94ecf33b9c6..2833946fe3b 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -237,6 +237,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);
@@ -288,10 +289,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;
@@ -779,6 +780,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));
@@ -1561,6 +1563,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);
}
@@ -1695,8 +1698,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
}
/*
- ** Collect all keys which isn't in drop list. Add only those
- ** for which some fields exists.
+ Collect all keys which isn't in drop list. Add only those
+ for which some fields exists.
*/
List_iterator<Key> key_it(keys);
@@ -1931,6 +1934,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);
}
@@ -2063,6 +2067,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 d5034644830..4f5f21d61ad 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -319,6 +319,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)
@@ -440,7 +442,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)
{}
@@ -544,6 +546,26 @@ 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) &&
+ check_dup(table_ref->db, table_ref->real_name, update_tables))
+ table->no_cache= 1; // Disable row cache
+ }
DBUG_RETURN(thd->fatal_error != 0);
}
@@ -684,7 +706,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)
{
@@ -819,8 +841,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;
@@ -939,6 +964,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/table.cc b/sql/table.cc
index 0789f7469e7..c8def7441fd 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -430,14 +430,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;
@@ -476,6 +479,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 |=
@@ -513,7 +522,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->type() != FIELD_TYPE_BLOB)
{ // Create a new field
field=key_part->field=field->new_field(&outparam->mem_root,
@@ -527,7 +536,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
diff --git a/sql/table.h b/sql/table.h
index 57be97ffbda..f3b0e148cc0 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -101,7 +101,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;
Field *next_number_field, /* Set if next_number is activated */
*found_next_number_field, /* Set on open */
*rowid_field;
diff --git a/sql/time.cc b/sql/time.cc
index bf218fa58ab..5dc229b1d88 100644
--- a/sql/time.cc
+++ b/sql/time.cc
@@ -125,6 +125,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 */
@@ -445,7 +447,7 @@ time_t str_to_timestamp(const char *str,uint length)
if (str_to_TIME(str,length,&l_time,0) == TIMESTAMP_NONE)
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/strings/ctype-tis620.c b/strings/ctype-tis620.c
index edadadf3a43..7ffc83ea005 100644
--- a/strings/ctype-tis620.c
+++ b/strings/ctype-tis620.c
@@ -538,8 +538,10 @@ int my_strnncoll_tis620(const uchar * s1, int len1, const uchar * s2, int len2)
tc1= thai2sortable(s1, len1);
tc2= thai2sortable(s2, len2);
i= strcmp((char*)tc1, (char*)tc2);
- free(tc1);
- free(tc2);
+ if (tc1 != s1)
+ free(tc1);
+ if (tc2 != s2)
+ free(tc2);
return i;
}
@@ -555,7 +557,8 @@ int my_strnxfrm_tis620(uchar * dest, const uchar * src, int len, int srclen)
tmp= thai2sortable(src,srclen);
set_if_smaller(bufSize,(uint) len);
memcpy((uchar *)dest, tmp, bufSize);
- free(tmp);
+ if (tmp != src)
+ free(tmp);
return (int)bufSize;
}
@@ -570,8 +573,10 @@ int my_strcoll_tis620(const uchar * s1, const uchar * s2)
tc1= thai2sortable(s1, (int) strlen((char*)s1));
tc2= thai2sortable(s2, (int) strlen((char*)s2));
i= strcmp((char*)tc1, (char*)tc2);
- free(tc1);
- free(tc2);
+ if (tc1 != s1)
+ free(tc1);
+ if (tc2 != s2)
+ free(tc2);
return i;
}
@@ -587,7 +592,8 @@ int my_strxfrm_tis620(uchar * dest, const uchar * src, int len)
bufSize= (uint)buffsize((char*) src);
tmp= thai2sortable(src, len);
memcpy((uchar *)dest, tmp, bufSize);
- free(tmp);
+ if (tmp != src)
+ free(tmp);
return bufSize;
}
diff --git a/strings/strto.c b/strings/strto.c
index bd0c8e38fde..c98b19a7e67 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/mysql.server.sh b/support-files/mysql.server.sh
index 36eb5c4dff6..d55068db64e 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 658b90d1a3f..e1c3476f738 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
@@ -442,11 +442,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*
@@ -498,6 +499,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
@@ -525,7 +527,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
@@ -546,11 +548,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
@@ -558,15 +561,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 Nov 21 2003 Lenz Grimmer <lenz@mysql.com>
- removed dependency on MySQL-client from the MySQL-devel subpackage