diff options
222 files changed, 4542 insertions, 1373 deletions
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index c9fe18eed46..a28e7dc78f0 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -13,6 +13,7 @@ antony@ltantony.rdg.cyberkinetica.homeunix.net arjen@co3064164-a.bitbike.com arjen@fred.bitbike.com arjen@george.bitbike.com +bar@bar.intranet.mysql.r18.ru bar@bar.mysql.r18.ru bar@bar.udmsearch.izhnet.ru bar@gw.udmsearch.izhnet.ru diff --git a/Build-tools/Bootstrap b/Build-tools/Bootstrap index 17b15d190b0..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/{internals,manual,reservedwords}.texi"; - $command.= " $target_dir/Docs/"; - &run_command($command, "Could not update the manual in $target_dir/Docs/!"); + foreach $file qw/internals manual reservedwords/ + { + system ("bk cat $opt_docdir/Docs/$file.texi > $target_dir/Docs/$file.texi") == 0 + or &abort("Could not update $file.texi in $target_dir/Docs/!"); + } } # @@ -364,11 +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 0541ebe96ce..2039c2f1c5a 100755 --- a/Build-tools/Do-compile +++ b/Build-tools/Do-compile @@ -1,6 +1,8 @@ #!/usr/bin/perl -w +use File::Basename; use Getopt::Long; +use Sys::Hostname; @config_options= (); @make_options= (); @@ -76,7 +78,7 @@ if (@config_env > 0) $opt_config_env= join(" ", @config_env); } -chomp($host=`hostname`); +$host= hostname(); chomp($uname=`uname`); $full_host_name=$host; $connect_option= ($opt_tcpip ? "--host=$host" : ""); @@ -84,7 +86,7 @@ $host =~ /^([^.-]*)/; $host=$1 . $opt_suffix; $email="$opt_user\@mysql.com"; chomp($pwd = `pwd`); -$VER= `basename $opt_distribution`; chop $VER; +$VER= basename($opt_distribution); $VER=~ /mysql.*-([1-9]\.[0-9]{1,2}\.[0-9]{1,2}.*)\.tar*/; $version=$1; ($major, $minor, $release) = split(/\./,$version); $log="$pwd/Logs/$host-$major.$minor$opt_version_suffix.log"; @@ -111,7 +113,7 @@ if (defined($gcc_version) && ! $opt_config_env) $new_opt_tmp=0; if ($opt_tmp) { - if (! -d $opt_tmp) + unless (-d $opt_tmp) { safe_system("mkdir $opt_tmp"); $new_opt_tmp=1; diff --git a/Build-tools/Do-rpm b/Build-tools/Do-rpm index 0f423feb921..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/VC++Files/InstallShield/4.0.XX-classic/String Tables/0009-English/value.shl b/VC++Files/InstallShield/4.0.XX-classic/String Tables/0009-English/value.shl index 5f767a63f43..868c801c68c 100755 --- a/VC++Files/InstallShield/4.0.XX-classic/String Tables/0009-English/value.shl +++ b/VC++Files/InstallShield/4.0.XX-classic/String Tables/0009-English/value.shl @@ -19,5 +19,5 @@ ERROR_UNINSTSETUP=unInstaller setup failed to initialize. You may not be able t [General] Language=0009 Type=STRINGTABLESPECIFIC -Version=@VERSION@ +Version=1.00.000 diff --git a/VC++Files/InstallShield/4.0.XX-gpl/String Tables/0009-English/value.shl b/VC++Files/InstallShield/4.0.XX-gpl/String Tables/0009-English/value.shl index 0a6c33be42b..35e7c278cc9 100755 --- a/VC++Files/InstallShield/4.0.XX-gpl/String Tables/0009-English/value.shl +++ b/VC++Files/InstallShield/4.0.XX-gpl/String Tables/0009-English/value.shl @@ -19,5 +19,5 @@ ERROR_UNINSTSETUP=unInstaller setup failed to initialize. You may not be able t [General] Language=0009 Type=STRINGTABLESPECIFIC -Version=@VERSION@ +Version=1.00.000 diff --git a/VC++Files/InstallShield/4.0.XX-pro/String Tables/0009-English/value.shl b/VC++Files/InstallShield/4.0.XX-pro/String Tables/0009-English/value.shl index 61b2e6fb50f..525f3be0b3e 100755 --- a/VC++Files/InstallShield/4.0.XX-pro/String Tables/0009-English/value.shl +++ b/VC++Files/InstallShield/4.0.XX-pro/String Tables/0009-English/value.shl @@ -19,5 +19,5 @@ ERROR_UNINSTSETUP=unInstaller setup failed to initialize. You may not be able t [General] Language=0009 Type=STRINGTABLESPECIFIC -Version=@VERSION@ +Version=1.00.000 diff --git a/acinclude.m4 b/acinclude.m4 index 15a6abc38d4..d3a404e5fb0 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -785,7 +785,7 @@ AC_DEFUN(MYSQL_FIND_OPENSSL, [ for d in /usr/ssl/lib /usr/local/ssl/lib /usr/lib/openssl \ /usr/lib /usr/lib64 /opt/ssl/lib /opt/openssl/lib /usr/local/lib/ ; do - if test -f $d/libssl.a ; then + if test -f $d/libssl.a || test -f $d/libssl.so || test -f $d/libssl.dylib ; then OPENSSL_LIB=$d fi done @@ -797,7 +797,7 @@ AC_DEFUN(MYSQL_FIND_OPENSSL, [ if test -f $incs/openssl/ssl.h ; then OPENSSL_INCLUDE=-I$incs fi - if test -f $libs/libssl.a ; then + if test -f $libs/libssl.a || test -f $libs/libssl.so || test -f $libs/libssl.dylib ; then OPENSSL_LIB=$libs fi ;; diff --git a/client/mysql.cc b/client/mysql.cc index 7ae30cc5688..16923eaf149 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -380,7 +380,7 @@ int main(int argc,char *argv[]) put_info("Welcome to the MySQL monitor. Commands end with ; or \\g.", INFO_INFO); sprintf((char*) glob_buffer.ptr(), - "Your MySQL connection id is %ld to server version: %s\n", + "Your MySQL connection id is %lu to server version: %s\n", mysql_thread_id(&mysql),mysql_get_server_info(&mysql)); put_info((char*) glob_buffer.ptr(),INFO_INFO); @@ -613,8 +613,8 @@ static struct my_option my_long_options[] = 0, 1}, {"max_allowed_packet", OPT_MAX_ALLOWED_PACKET, "", (gptr*) &max_allowed_packet, (gptr*) &max_allowed_packet, 0, GET_ULONG, - REQUIRED_ARG, 16 *1024L*1024L, 4096, 512*1024L*1024L, MALLOC_OVERHEAD, - 1024, 0}, + REQUIRED_ARG, 16 *1024L*1024L, 4096, (longlong) 2*1024L*1024L*1024L, + MALLOC_OVERHEAD, 1024, 0}, {"net_buffer_length", OPT_NET_BUFFER_LENGTH, "", (gptr*) &net_buffer_length, (gptr*) &net_buffer_length, 0, GET_ULONG, REQUIRED_ARG, 16384, 1024, 512*1024*1024L, MALLOC_OVERHEAD, 1024, 0}, @@ -2346,7 +2346,7 @@ com_connect(String *buffer, char *line) if (connected) { - sprintf(buff,"Connection id: %ld",mysql_thread_id(&mysql)); + sprintf(buff,"Connection id: %lu",mysql_thread_id(&mysql)); put_info(buff,INFO_INFO); sprintf(buff,"Current database: %s\n", current_db ? current_db : "*** NONE ***"); @@ -2545,8 +2545,11 @@ static int sql_real_connect(char *host,char *database,char *user,char *password, uint silent) { - mysql_close(&mysql); - connected= 0; + if (connected) + { + connected= 0; + mysql_close(&mysql); + } mysql_init(&mysql); if (opt_connect_timeout) { @@ -2652,7 +2655,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 5c3fa44e30b..018cd43ce87 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -37,7 +37,7 @@ ** 10 Jun 2003: SET NAMES and --no-set-names by Alexander Barkov */ -#define DUMP_VERSION "10.3" +#define DUMP_VERSION "10.4" #include <my_global.h> #include <my_sys.h> @@ -81,7 +81,7 @@ static my_bool verbose=0,tFlag=0,cFlag=0,dFlag=0,quick= 1, extended_insert= 1, opt_alldbs=0,opt_create_db=0,opt_first_slave=0,opt_set_names=0, opt_autocommit=0,opt_master_data,opt_disable_keys=1,opt_xml=0, opt_delete_master_logs=0, tty_password=0, - opt_single_transaction=0; + opt_single_transaction=0, opt_comments= 0; static MYSQL mysql_connection,*sock=0; static char insert_pat[12 * 1024],*opt_password=0,*current_user=0, *current_host=0,*path=0,*fields_terminated=0, @@ -89,11 +89,7 @@ static char insert_pat[12 * 1024],*opt_password=0,*current_user=0, *where=0, *opt_compatible_mode_str= 0, *err_ptr= 0; -#ifdef HAVE_CHARSET_utf8 -static char *default_charset= (char*) "utf8"; -#else -static char *default_charset= (char*) MYSQL_DEFAULT_CHARSET_NAME; -#endif +static char *default_charset= (char*) MYSQL_UNIVERSAL_CLIENT_CHARSET; static ulong opt_compatible_mode= 0; static uint opt_mysql_port= 0, err_len= 0; static my_string opt_mysql_unix_port=0; @@ -280,12 +276,15 @@ static struct my_option my_long_options[] = NO_ARG, 0, 0, 0, 0, 0, 0}, {"max_allowed_packet", OPT_MAX_ALLOWED_PACKET, "", (gptr*) &max_allowed_packet, (gptr*) &max_allowed_packet, 0, - GET_ULONG, REQUIRED_ARG, 24*1024*1024, 4096, 1024*1024L*1024L, - MALLOC_OVERHEAD, 1024, 0}, + GET_ULONG, REQUIRED_ARG, 24*1024*1024, 4096, + (longlong) 2L*1024L*1024L*1024L, MALLOC_OVERHEAD, 1024, 0}, {"net_buffer_length", OPT_NET_BUFFER_LENGTH, "", (gptr*) &net_buffer_length, (gptr*) &net_buffer_length, 0, GET_ULONG, REQUIRED_ARG, 1024*1024L-1025, 4096, 16*1024L*1024L, MALLOC_OVERHEAD-1024, 1024, 0}, + {"comments", 'i', "Write additional information.", + (gptr*) &opt_comments, (gptr*) &opt_comments, 0, GET_BOOL, NO_ARG, + 1, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; @@ -302,6 +301,8 @@ static int init_dumping(char *); static int dump_databases(char **); static int dump_all_databases(); static char *quote_name(const char *name, char *buff, my_bool force); +static const char *check_if_ignore_table(const char *table_name); + static void print_version(void) { @@ -345,7 +346,7 @@ static void write_header(FILE *sql_file, char *db_name) fputs("<?xml version=\"1.0\"?>\n", sql_file); fputs("<mysqldump>\n", sql_file); } - else + else if (opt_comments) { fprintf(sql_file, "-- MySQL dump %s\n--\n", DUMP_VERSION); fprintf(sql_file, "-- Host: %s Database: %s\n", @@ -656,6 +657,23 @@ static char *quote_name(const char *name, char *buff, my_bool force) } /* quote_name */ + +static char *quote_for_like(const char *name, char *buff) +{ + char *to= buff; + *to++= '\''; + while (*name) + { + if (*name == '\'' || *name == '_' || *name == '\\' || *name == '%') + *to++= '\\'; + *to++= *name++; + } + to[0]= '\''; + to[1]= 0; + return buff; +} + + /* Quote and print a string. @@ -854,7 +872,8 @@ static uint getTableStructure(char *table, char* db) } write_header(sql_file, db); } - fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n", + if (!opt_xml && opt_comments) + fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n", result_table); if (opt_drop) fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", opt_quoted_table); @@ -930,7 +949,7 @@ static uint getTableStructure(char *table, char* db) } write_header(sql_file, db); } - if (!opt_xml) + if (!opt_xml && opt_comments) fprintf(sql_file, "\n--\n-- Table structure for table %s\n--\n\n", result_table); if (opt_drop) @@ -1067,16 +1086,9 @@ static uint getTableStructure(char *table, char* db) /* Get MySQL specific create options */ if (create_options) { - ulong len= strlen(table); - char *tmp= (char*) my_malloc(len * 2 + 1, MYF(MY_WME)); - if (!tmp) - { - ignore_errors= 0; - safe_exit(EX_MYSQLERR); - } - mysql_real_escape_string(&mysql_connection, tmp, table, len); - sprintf(buff,"show table status like \"%s\"", tmp); - my_free(tmp, MYF(MY_WME)); + char show_name_buff[FN_REFLEN]; + sprintf(buff,"show table status like %s", + quote_for_like(table, show_name_buff)); if (mysql_query(sock, buff)) { if (mysql_errno(sock) != ER_PARSE_ERROR) @@ -1191,11 +1203,23 @@ static void dumpTable(uint numFields, char *table) MYSQL_FIELD *field; MYSQL_ROW row; ulong rownr, row_break, total_length, init_length; + const char *table_type; - if (verbose) - fprintf(stderr, "-- Sending SELECT query...\n"); result_table= quote_name(table,table_buff, 1); opt_quoted_table= quote_name(table, table_buff2, 0); + + /* Check table type */ + if ((table_type= check_if_ignore_table(table))) + { + if (verbose) + fprintf(stderr, + "-- Skipping data for table '%s' because it's of type %s\n", + table, table_type); + return; + } + + if (verbose) + fprintf(stderr, "-- Sending SELECT query...\n"); if (path) { char filename[FN_REFLEN], tmp_path[FN_REFLEN]; @@ -1234,14 +1258,14 @@ static void dumpTable(uint numFields, char *table) } else { - if (!opt_xml) + if (!opt_xml && opt_comments) fprintf(md_result_file,"\n--\n-- Dumping data for table %s\n--\n", result_table); sprintf(query, "SELECT /*!40001 SQL_NO_CACHE */ * FROM %s", result_table); if (where) { - if (!opt_xml) + if (!opt_xml && opt_comments) fprintf(md_result_file,"-- WHERE: %s\n",where); strxmov(strend(query), " WHERE ",where,NullS); } @@ -1337,11 +1361,23 @@ static void dumpTable(uint numFields, char *table) } else { - /* change any strings ("inf","nan",..) into NULL */ + /* change any strings ("inf", "-inf", "nan") into NULL */ char *ptr = row[i]; - dynstr_append(&extended_row, - (!my_isalpha(charset_info,*ptr)) ? - ptr : "NULL"); + if (my_isalpha(charset_info, *ptr) || (*ptr == '-' && + my_isalpha(charset_info, ptr[1]))) + dynstr_append(&extended_row, "NULL"); + else + { + if (field->type == FIELD_TYPE_DECIMAL) + { + /* add " signs around */ + dynstr_append(&extended_row, "\""); + dynstr_append(&extended_row, ptr); + dynstr_append(&extended_row, "\""); + } + else + dynstr_append(&extended_row, ptr); + } } } else @@ -1373,7 +1409,7 @@ static void dumpTable(uint numFields, char *table) } else { - /* change any strings ("inf","nan",..) into NULL */ + /* change any strings ("inf", "-inf", "nan") into NULL */ char *ptr = row[i]; if (opt_xml) { @@ -1383,19 +1419,20 @@ static void dumpTable(uint numFields, char *table) md_result_file); fputs("</field>\n", md_result_file); } + else if (my_isalpha(charset_info, *ptr) || + (*ptr == '-' && my_isalpha(charset_info, ptr[1]))) + fputs("NULL", md_result_file); + else if (field->type == FIELD_TYPE_DECIMAL) + { + /* add " signs around */ + fputs("\"", md_result_file); + fputs(ptr, md_result_file); + fputs("\"", md_result_file); + } else - fputs((!my_isalpha(charset_info,*ptr)) ? - ptr : "NULL", md_result_file); + fputs(ptr, md_result_file); } } - else - { - if (opt_xml) - print_xml_tag1(md_result_file, "\t\t", "field name=", - field->name, "NULL</field>\n"); - else - fputs("NULL", md_result_file); - } } } @@ -1533,8 +1570,8 @@ static int init_dumping(char *database) */ char quoted_database_buf[64*2+3]; char *qdatabase= quote_name(database,quoted_database_buf,opt_quoted); - - fprintf(md_result_file,"\n--\n-- Current Database: %s\n--\n", qdatabase); + if (opt_comments) + fprintf(md_result_file,"\n--\n-- Current Database: %s\n--\n", qdatabase); if (!opt_create_db) { char qbuf[256]; @@ -1730,6 +1767,61 @@ static void print_value(FILE *file, MYSQL_RES *result, MYSQL_ROW row, } /* print_value */ +/* + Check if we the table is one of the table types that should be ignored: + MRG_ISAM, MRG_MYISAM + + SYNOPSIS + check_if_ignore_table() + table_name Table name to check + + GLOBAL VARIABLES + sock MySQL socket + verbose Write warning messages + + RETURN + 0 Table should be backuped + # Type of table (that should be skipped) +*/ + +static const char *check_if_ignore_table(const char *table_name) +{ + char buff[FN_REFLEN+80], show_name_buff[FN_REFLEN]; + MYSQL_RES *res; + MYSQL_ROW row; + const char *result= 0; + + sprintf(buff,"show table status like %s", + quote_for_like(table_name, show_name_buff)); + if (mysql_query(sock, buff)) + { + if (mysql_errno(sock) != ER_PARSE_ERROR) + { /* If old MySQL version */ + if (verbose) + fprintf(stderr, + "-- Warning: Couldn't get status information for table %s (%s)\n", + table_name,mysql_error(sock)); + return 0; /* assume table is ok */ + } + } + if (!(res= mysql_store_result(sock)) || + !(row= mysql_fetch_row(res))) + { + fprintf(stderr, + "Error: Couldn't read status information for table %s (%s)\n", + table_name, mysql_error(sock)); + if (res) + mysql_free_result(res); + return 0; /* assume table is ok */ + } + if (strcmp(row[1], (result= "MRG_MyISAM")) && + strcmp(row[1], (result= "MRG_ISAM"))) + result= 0; + mysql_free_result(res); + return result; +} + + int main(int argc, char **argv) { MYSQL_ROW row; @@ -1799,8 +1891,9 @@ int main(int argc, char **argv) row = mysql_fetch_row(master); if (row && row[0] && row[1]) { - fprintf(md_result_file, - "\n--\n-- Position to start replication from\n--\n\n"); + if (opt_comments) + fprintf(md_result_file, + "\n--\n-- Position to start replication from\n--\n\n"); fprintf(md_result_file, "CHANGE MASTER TO MASTER_LOG_FILE='%s', \ MASTER_LOG_POS=%s ;\n",row[0],row[1]); diff --git a/client/mysqltest.c b/client/mysqltest.c index b3b8cd55221..d034007cb29 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -2153,7 +2153,7 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags) DYNAMIC_STRING *ds; DYNAMIC_STRING ds_tmp; DYNAMIC_STRING eval_query; - char* query, buff[MAX_DELIMITER + 1]= {0}; + char* query; int query_len; DBUG_ENTER("run_query"); @@ -2188,8 +2188,8 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags) if ((flags & QUERY_SEND) && !disable_query_log && !counter) { replace_dynstr_append_mem(ds,query, query_len); - sprintf(buff, "%s\n", delimiter); - dynstr_append_mem(ds, buff, delimiter_length + 1); + dynstr_append_mem(ds, delimiter, delimiter_length); + dynstr_append_mem(ds, "\n", 1); } if (!(flags & QUERY_REAP)) DBUG_RETURN(0); diff --git a/configure.in b/configure.in index 812261a7c95..cf19670dc6e 100644 --- a/configure.in +++ b/configure.in @@ -731,7 +731,7 @@ AC_CHECK_HEADERS(fcntl.h float.h floatingpoint.h ieeefp.h limits.h \ strings.h string.h synch.h sys/mman.h sys/socket.h netinet/in.h arpa/inet.h \ sys/timeb.h sys/types.h sys/un.h sys/vadvise.h sys/wait.h term.h \ unistd.h utime.h sys/utime.h termio.h termios.h sched.h crypt.h alloca.h \ - sys/ioctl.h malloc.h sys/malloc.h) + sys/ioctl.h malloc.h sys/malloc.h linux/config.h) #-------------------------------------------------------------------- # Check for system libraries. Adds the library to $LIBS diff --git a/dbug/dbug.c b/dbug/dbug.c index f7b2fb75ba0..d96ef0cae09 100644 --- a/dbug/dbug.c +++ b/dbug/dbug.c @@ -501,7 +501,7 @@ void _db_push_ (const char *control) if (! _db_fp_) _db_fp_= stderr; /* Output stream, default stderr */ - if (control && *control == '-') + if (*control == '-') { if (*++control == '#') control++; diff --git a/include/config-win.h b/include/config-win.h index 86318bddbcb..10490fd2f91 100644 --- a/include/config-win.h +++ b/include/config-win.h @@ -93,6 +93,7 @@ functions */ #define LONGLONG_MIN ((__int64) 0x8000000000000000) #define LONGLONG_MAX ((__int64) 0x7FFFFFFFFFFFFFFF) +#define ULONGLONG_MAX ((unsigned __int64) 0xFFFFFFFFFFFFFFFF) #define LL(A) ((__int64) A) /* Type information */ @@ -158,6 +159,10 @@ typedef uint rf_SetTimer; #define USE_MB_IDENT 1 #define USE_STRCOLL 1 +/* All windows servers should support .sym files */ +#undef USE_SYMDIR +#define USE_SYMDIR + /* If LOAD DATA LOCAL INFILE should be enabled by default */ #define ENABLED_LOCAL_INFILE 1 diff --git a/include/errmsg.h b/include/errmsg.h index 24326b1efef..8f3ddfa9796 100644 --- a/include/errmsg.h +++ b/include/errmsg.h @@ -86,5 +86,4 @@ extern const char *client_errors[]; /* Error messages */ #define CR_SHARED_MEMORY_CONNECT_SET_ERROR 2045 #define CR_CONN_UNKNOW_PROTOCOL 2046 #define CR_INVALID_CONN_HANDLE 2047 -#define CR_MYSQL_SERVER_INIT_MISSED 2048 -#define CR_SECURE_AUTH 2049 +#define CR_SECURE_AUTH 2048 diff --git a/include/my_base.h b/include/my_base.h index 25521d7b13d..89b46de520f 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -190,11 +190,17 @@ enum ha_base_keytype { /* poor old NISAM has 8-bit flags :-( */ #define HA_SORT_ALLOWS_SAME 128 /* Intern bit when sorting records */ #endif +/* + Key has a part that can have end space. If this is an unique key + we have to handle it differently from other unique keys as we can find + many matching rows for one key (becaue end space are not compared) +*/ +#define HA_END_SPACE_KEY 4096 - /* These flags can be order to key-seg-flag */ + /* These flags can be added to key-seg-flag */ #define HA_SPACE_PACK 1 /* Pack space in key-seg */ -#define HA_PART_KEY 4 /* Used by MySQL for part-key-cols */ +#define HA_PART_KEY_SEG 4 /* Used by MySQL for part-key-cols */ #define HA_VAR_LENGTH 8 #define HA_NULL_PART 16 #define HA_BLOB_PART 32 diff --git a/include/my_dir.h b/include/my_dir.h index 4ccda050914..851b6d8d7e9 100644 --- a/include/my_dir.h +++ b/include/my_dir.h @@ -74,14 +74,21 @@ typedef struct my_stat #endif /* USE_MY_STAT_STRUCT */ -typedef struct fileinfo /* Struct returned from my_dir & my_stat */ +/* Struct describing one file returned from my_dir */ +typedef struct fileinfo { char *name; - MY_STAT mystat; + MY_STAT *mystat; } FILEINFO; typedef struct st_my_dir /* Struct returned from my_dir */ { + /* + These members are just copies of parts of DYNAMIC_ARRAY structure, + which is allocated right after the end of MY_DIR structure (MEM_ROOT + for storing names is also resides there). We've left them here because + we don't want to change code that uses my_dir. + */ struct fileinfo *dir_entry; uint number_off_files; } MY_DIR; diff --git a/include/my_global.h b/include/my_global.h index a34a0bd786c..3275b010bb4 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -294,6 +294,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 @@ -633,11 +636,26 @@ extern double my_atof(const char*); #define HAVE_LONG_LONG 1 #endif +/* + Some pre-ANSI-C99 systems like AIX 5.1 and Linux/GCC 2.95 define + ULONGLONG_MAX, LONGLONG_MIN, LONGLONG_MAX; we use them if they're defined. + Also on Windows we define these constants by hand in config-win.h. +*/ + #if defined(HAVE_LONG_LONG) && !defined(LONGLONG_MIN) #define LONGLONG_MIN ((long long) 0x8000000000000000LL) #define LONGLONG_MAX ((long long) 0x7FFFFFFFFFFFFFFFLL) #endif +#if defined(HAVE_LONG_LONG) && !defined(ULONGLONG_MAX) +/* First check for ANSI C99 definition: */ +#ifdef ULLONG_MAX +#define ULONGLONG_MAX ULLONG_MAX +#else +#define ULONGLONG_MAX ((unsigned long long)(~0ULL)) +#endif +#endif /* defined (HAVE_LONG_LONG) && !defined(ULONGLONG_MAX)*/ + #if SIZEOF_LONG == 4 #define INT_MIN32 (long) 0x80000000L #define INT_MAX32 (long) 0x7FFFFFFFL @@ -1162,4 +1180,10 @@ typedef union { #endif #endif +#ifdef HAVE_CHARSET_utf8 +#define MYSQL_UNIVERSAL_CLIENT_CHARSET "utf8" +#else +#define MYSQL_UNIVERSAL_CLIENT_CHARSET MYSQL_DEFAULT_CHARSET_NAME +#endif + #endif /* my_global_h */ diff --git a/include/my_pthread.h b/include/my_pthread.h index 44e6edcddec..cf04d078c70 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -117,6 +117,7 @@ void pthread_exit(void *a); /* was #define pthread_exit(A) ExitThread(A)*/ #undef SAFE_MUTEX /* This will cause conflicts */ #define pthread_key(T,V) DWORD V #define pthread_key_create(A,B) ((*A=TlsAlloc())==0xFFFFFFFF) +#define pthread_key_delete(A) TlsFree(A) #define pthread_getspecific(A) (TlsGetValue(A)) #define my_pthread_getspecific(T,A) ((T) TlsGetValue(A)) #define my_pthread_getspecific_ptr(T,V) ((T) TlsGetValue(V)) @@ -125,6 +126,7 @@ void pthread_exit(void *a); /* was #define pthread_exit(A) ExitThread(A)*/ #else #define pthread_key(T,V) __declspec(thread) T V #define pthread_key_create(A,B) pthread_dummy(0) +#define pthread_key_delete(A) pthread_dummy(0) #define pthread_getspecific(A) (&(A)) #define my_pthread_getspecific(T,A) (&(A)) #define my_pthread_getspecific_ptr(T,V) (V) @@ -180,6 +182,7 @@ extern int pthread_mutex_destroy (pthread_mutex_t *); typedef int pthread_attr_t; /* Needed by Unixware 7.0.0 */ #define pthread_key_create(A,B) thr_keycreate((A),(B)) +#define pthread_key_delete(A) thr_keydelete(A) #define pthread_handler_decl(A,B) void *A(void *B) #define pthread_key(T,V) pthread_key_t V diff --git a/include/my_sys.h b/include/my_sys.h index 59d5767d204..7927192848a 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -163,7 +163,7 @@ extern char *my_strdup_with_length(const byte *from, uint length, #if defined(_AIX) && !defined(__GNUC__) && !defined(_AIX43) #pragma alloca #endif /* _AIX */ -#if defined(__GNUC__) && !defined(HAVE_ALLOCA_H) +#if defined(__GNUC__) && !defined(HAVE_ALLOCA_H) && ! defined(alloca) #define alloca __builtin_alloca #endif /* GNUC */ #define my_alloca(SZ) alloca((size_t) (SZ)) @@ -583,7 +583,7 @@ extern int my_printf_error _VARARGS((uint my_err, const char *format, extern int my_message(uint my_err, const char *str,myf MyFlags); extern int my_message_no_curses(uint my_err, const char *str,myf MyFlags); extern int my_message_curses(uint my_err, const char *str,myf MyFlags); -extern void my_init(void); +extern my_bool my_init(void); extern void my_end(int infoflag); extern int my_redel(const char *from, const char *to, int MyFlags); extern int my_copystat(const char *from, const char *to, int MyFlags); diff --git a/include/mysql.h b/include/mysql.h index fd0330b35da..d1b467f9649 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -638,9 +638,6 @@ int STDCALL mysql_drop_db(MYSQL *mysql, const char *DB); (*(mysql)->methods->advanced_command)(mysql, command, \ NullS, 0, arg, length, skip_check) unsigned long net_safe_read(MYSQL* mysql); -void mysql_once_init(void); - -extern my_bool server_inited; #ifdef __NETWARE__ #pragma pack(pop) /* restore alignment */ diff --git a/include/mysql_com.h b/include/mysql_com.h index 3e91670cf9e..cc2e1056a9e 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -356,7 +356,7 @@ const char *mysql_errno_to_sqlstate(unsigned int mysql_errno); /* Some other useful functions */ -void my_init(void); +my_bool my_init(void); int load_defaults(const char *conf_file, const char **groups, int *argc, char ***argv); my_bool my_thread_init(void); diff --git a/include/mysql_embed.h b/include/mysql_embed.h index 7a169d4133e..df358e29872 100644 --- a/include/mysql_embed.h +++ b/include/mysql_embed.h @@ -32,4 +32,6 @@ #undef MYSQL_SERVER_SUFFIX #define MYSQL_SERVER_SUFFIX "-embedded" +#undef HAVE_QUERY_CACHE /* Cache dosn't work yet */ + #endif /* EMBEDDED_LIBRARY */ diff --git a/include/mysqld_error.h b/include/mysqld_error.h index 4f2c387dbc3..2f333bec7c8 100644 --- a/include/mysqld_error.h +++ b/include/mysqld_error.h @@ -301,7 +301,7 @@ #define ER_BAD_FT_COLUMN 1282 #define ER_UNKNOWN_KEY_CACHE 1283 #define ER_WARN_HOSTNAME_WONT_WORK 1284 -#define ER_UNKNOWN_TABLE_ENGINE 1285 +#define ER_UNKNOWN_STORAGE_ENGINE 1285 #define ER_WARN_DEPRECATED_SYNTAX 1286 #define ER_SP_NO_RECURSIVE_CREATE 1287 #define ER_SP_ALREADY_EXISTS 1288 diff --git a/include/sql_state.h b/include/sql_state.h index de8df2d88a5..f4fbe434490 100644 --- a/include/sql_state.h +++ b/include/sql_state.h @@ -161,7 +161,7 @@ ER_WARN_DATA_OUT_OF_RANGE, "01000", "", ER_WARN_DATA_TRUNCATED, "01000", "", ER_WRONG_NAME_FOR_INDEX, "42000", "", ER_WRONG_NAME_FOR_CATALOG, "42000", "", -ER_UNKNOWN_TABLE_ENGINE, "42000", "", +ER_UNKNOWN_STORAGE_ENGINE, "42000", "", /* 5.0 */ ER_SP_NO_RECURSIVE_CREATE, "2F003", "", ER_SP_ALREADY_EXISTS, "42000", "", diff --git a/innobase/btr/btr0cur.c b/innobase/btr/btr0cur.c index 93e9e815c99..b2bfdbec4e4 100644 --- a/innobase/btr/btr0cur.c +++ b/innobase/btr/btr0cur.c @@ -1151,7 +1151,6 @@ btr_cur_pessimistic_insert( } /*==================== B-TREE UPDATE =========================*/ -/* Only clustered index records are modified using these functions */ /***************************************************************** For an update, checks the locks and does the undo logging. */ @@ -1175,12 +1174,16 @@ btr_cur_upd_lock_and_undo( ut_ad(cursor && update && thr && roll_ptr); - /* Only clustered index records are updated using this function */ - ut_ad((cursor->index)->type & DICT_CLUSTERED); - rec = btr_cur_get_rec(cursor); index = cursor->index; + if (!(index->type & DICT_CLUSTERED)) { + /* We do undo logging only when we update a clustered index + record */ + return(lock_sec_rec_modify_check_and_lock(flags, rec, index, + thr)); + } + /* Check if we have to wait for a lock: enqueue an explicit lock request if yes */ @@ -1227,6 +1230,13 @@ btr_cur_update_in_place_log( mach_write_to_1(log_ptr, flags); log_ptr++; + /* The code below assumes index is a clustered index: change index to + the clustered index if we are updating a secondary index record (or we + could as well skip writing the sys col values to the log in this case + because they are not needed for a secondary index record update) */ + + index = dict_table_get_first_index(index->table); + log_ptr = row_upd_write_sys_vals_to_log(index, trx, roll_ptr, log_ptr, mtr); mach_write_to_2(log_ptr, rec - buf_frame_align(rec)); @@ -1394,13 +1404,10 @@ btr_cur_update_in_place( buf_block_t* block; ulint err; rec_t* rec; - dulint roll_ptr; + dulint roll_ptr = ut_dulint_zero; trx_t* trx; ibool was_delete_marked; - /* Only clustered index records are updated using this function */ - ut_ad(cursor->index->type & DICT_CLUSTERED); - rec = btr_cur_get_rec(cursor); index = cursor->index; trx = thr_get_trx(thr); @@ -1425,7 +1432,12 @@ btr_cur_update_in_place( block = buf_block_align(rec); if (block->is_hashed) { - if (row_upd_changes_ord_field_binary(NULL, index, update)) { + /* The function row_upd_changes_ord_field_binary works only + if the update vector was built for a clustered index, we must + NOT call it if index is secondary */ + + if (!(index->type & DICT_CLUSTERED) + || row_upd_changes_ord_field_binary(NULL, index, update)) { /* Remove possible hash index pointer to this record */ btr_search_update_hash_on_delete(cursor); @@ -1499,9 +1511,6 @@ btr_cur_optimistic_update( mem_heap_t* heap; ibool reorganized = FALSE; ulint i; - - /* Only clustered index records are updated using this function */ - ut_ad((cursor->index)->type & DICT_CLUSTERED); page = btr_cur_get_page(cursor); rec = btr_cur_get_rec(cursor); @@ -1551,8 +1560,8 @@ btr_cur_optimistic_update( new_entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec, heap); - row_upd_index_replace_new_col_vals(new_entry, index, update, NULL); - + row_upd_index_replace_new_col_vals_index_pos(new_entry, index, update, + NULL); old_rec_size = rec_get_size(rec); new_rec_size = rec_get_converted_size(new_entry); @@ -1735,7 +1744,6 @@ btr_cur_pessimistic_update( index = cursor->index; tree = index->tree; - ut_ad(index->type & DICT_CLUSTERED); ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree), MTR_MEMO_X_LOCK)); ut_ad(mtr_memo_contains(mtr, buf_block_align(page), @@ -1786,8 +1794,8 @@ btr_cur_pessimistic_update( new_entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec, heap); - row_upd_index_replace_new_col_vals(new_entry, index, update, heap); - + row_upd_index_replace_new_col_vals_index_pos(new_entry, index, update, + heap); if (!(flags & BTR_KEEP_SYS_FLAG)) { row_upd_index_entry_sys_field(new_entry, index, DATA_ROLL_PTR, roll_ptr); diff --git a/innobase/include/btr0cur.h b/innobase/include/btr0cur.h index 506877333c3..31aecef8104 100644 --- a/innobase/include/btr0cur.h +++ b/innobase/include/btr0cur.h @@ -188,22 +188,6 @@ btr_cur_pessimistic_insert( que_thr_t* thr, /* in: query thread or NULL */ mtr_t* mtr); /* in: mtr */ /***************************************************************** -Updates a secondary index record when the update causes no size -changes in its fields. The only case when this function is currently -called is that in a char field characters change to others which -are identified in the collation order. */ - -ulint -btr_cur_update_sec_rec_in_place( -/*============================*/ - /* out: DB_SUCCESS or error number */ - btr_cur_t* cursor, /* in: cursor on the record to update; - cursor stays valid and positioned on the - same record */ - upd_t* update, /* in: update vector */ - que_thr_t* thr, /* in: query thread */ - mtr_t* mtr); /* in: mtr */ -/***************************************************************** Updates a record when the update causes no size changes in its fields. */ ulint diff --git a/innobase/include/row0upd.h b/innobase/include/row0upd.h index 473c55c7ef9..f5e0a88231f 100644 --- a/innobase/include/row0upd.h +++ b/innobase/include/row0upd.h @@ -123,8 +123,8 @@ row_upd_changes_field_size_or_external( /* out: TRUE if the update changes the size of some field in index or the field is external in rec or update */ - rec_t* rec, /* in: record in clustered index */ - dict_index_t* index, /* in: clustered index */ + rec_t* rec, /* in: record in index */ + dict_index_t* index, /* in: index */ upd_t* update);/* in: update vector */ /*************************************************************** Replaces the new column values stored in the update vector to the record @@ -172,12 +172,30 @@ Replaces the new column values stored in the update vector to the index entry given. */ void +row_upd_index_replace_new_col_vals_index_pos( +/*=========================================*/ + dtuple_t* entry, /* in/out: index entry where replaced */ + dict_index_t* index, /* in: index; NOTE that this may also be a + non-clustered index */ + upd_t* update, /* in: an update vector built for the index so + that the field number in an upd_field is the + index position */ + mem_heap_t* heap); /* in: memory heap to which we allocate and + copy the new values, set this as NULL if you + do not want allocation */ +/*************************************************************** +Replaces the new column values stored in the update vector to the index entry +given. */ + +void row_upd_index_replace_new_col_vals( /*===============================*/ dtuple_t* entry, /* in/out: index entry where replaced */ - dict_index_t* index, /* in: index; NOTE that may also be a + dict_index_t* index, /* in: index; NOTE that this may also be a non-clustered index */ - upd_t* update, /* in: update vector */ + upd_t* update, /* in: an update vector built for the + CLUSTERED index so that the field number in + an upd_field is the clustered index position */ mem_heap_t* heap); /* in: memory heap to which we allocate and copy the new values, set this as NULL if you do not want allocation */ @@ -199,7 +217,9 @@ row_upd_changes_ord_field_binary( known when this function is called, e.g., at compile time */ dict_index_t* index, /* in: index of the record */ - upd_t* update);/* in: update vector for the row */ + upd_t* update);/* in: update vector for the row; NOTE: the + field numbers in this MUST be clustered index + positions! */ /*************************************************************** Checks if an update vector changes an ordering field of an index record. This function is fast if the update vector is short or the number of ordering @@ -271,7 +291,10 @@ row_upd_index_parse( /* Update vector field */ struct upd_field_struct{ - ulint field_no; /* field number in the clustered + ulint field_no; /* field number in an index, usually + the clustered index, but in updating + a secondary index record in btr0cur.c + this is the position in the secondary index */ que_node_t* exp; /* expression for calculating a new value: it refers to column values and diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c index af589cd9441..7fdca02ee94 100644 --- a/innobase/lock/lock0lock.c +++ b/innobase/lock/lock0lock.c @@ -339,6 +339,11 @@ lock_deadlock_recursive( ulint* cost); /* in/out: number of calculation steps thus far: if this exceeds LOCK_MAX_N_STEPS_... we return TRUE */ + +#define lock_mutex_enter_kernel() mutex_enter(&kernel_mutex) +#define lock_mutex_exit_kernel() mutex_exit(&kernel_mutex) + +#ifdef notdefined /************************************************************************* Reserves the kernel mutex. This function is used in this module to allow monitoring the contention degree on the kernel mutex caused by the lock @@ -362,6 +367,7 @@ lock_mutex_exit_kernel(void) { mutex_exit(&kernel_mutex); } +#endif #ifdef notdefined diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c index 1a7864be5e9..c89f41f69ad 100644 --- a/innobase/row/row0ins.c +++ b/innobase/row/row0ins.c @@ -225,11 +225,15 @@ ulint row_ins_sec_index_entry_by_modify( /*==============================*/ /* out: DB_SUCCESS or error code */ + ulint mode, /* in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE, + depending on whether mtr holds just a leaf + latch or also a tree latch */ btr_cur_t* cursor, /* in: B-tree cursor */ dtuple_t* entry, /* in: index entry to insert */ que_thr_t* thr, /* in: query thread */ mtr_t* mtr) /* in: mtr */ { + big_rec_t* dummy_big_rec; mem_heap_t* heap; upd_t* update; rec_t* rec; @@ -241,16 +245,28 @@ row_ins_sec_index_entry_by_modify( ut_ad(rec_get_deleted_flag(rec)); /* We know that in the alphabetical ordering, entry and rec are - identical. But in their binary form there may be differences if + identified. But in their binary form there may be differences if there are char fields in them. Therefore we have to calculate the - difference and do an update-in-place if necessary. */ + difference. */ heap = mem_heap_create(1024); update = row_upd_build_sec_rec_difference_binary(cursor->index, entry, rec, heap); + if (mode == BTR_MODIFY_LEAF) { + /* Try an optimistic updating of the record, keeping changes + within the page */ - err = btr_cur_update_sec_rec_in_place(cursor, update, thr, mtr); + err = btr_cur_optimistic_update(BTR_KEEP_SYS_FLAG, cursor, + update, 0, thr, mtr); + if (err == DB_OVERFLOW || err == DB_UNDERFLOW) { + err = DB_FAIL; + } + } else { + ut_a(mode == BTR_MODIFY_TREE); + err = btr_cur_pessimistic_update(BTR_KEEP_SYS_FLAG, cursor, + &dummy_big_rec, update, 0, thr, mtr); + } mem_heap_free(heap); @@ -1838,7 +1854,8 @@ row_ins_index_entry_low( ext_vec, n_ext_vec, thr, &mtr); } else { - err = row_ins_sec_index_entry_by_modify(&cursor, entry, + err = row_ins_sec_index_entry_by_modify(mode, &cursor, + entry, thr, &mtr); } diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c index f41574b2855..e6080a5f201 100644 --- a/innobase/row/row0sel.c +++ b/innobase/row/row0sel.c @@ -51,7 +51,8 @@ to que_run_threads: this is to allow canceling runaway queries */ /************************************************************************ Returns TRUE if the user-defined column values in a secondary index record -are the same as the corresponding columns in the clustered index record. +are alphabetically the same as the corresponding columns in the clustered +index record. NOTE: the comparison is NOT done as a binary comparison, but character fields are compared with collation! */ static @@ -96,11 +97,6 @@ row_sel_sec_rec_is_for_clust_rec( clust_len = ifield->prefix_len; } - if (sec_len != clust_len) { - - return(FALSE); - } - if (0 != cmp_data_data(dict_col_get_type(col), clust_field, clust_len, sec_field, sec_len)) { diff --git a/innobase/row/row0umod.c b/innobase/row/row0umod.c index 0a050e0a1b6..1bfd71f8c64 100644 --- a/innobase/row/row0umod.c +++ b/innobase/row/row0umod.c @@ -377,8 +377,14 @@ row_undo_mod_del_mark_or_remove_sec_low( } /*************************************************************** -Delete marks or removes a secondary index entry if found. */ -UNIV_INLINE +Delete marks or removes a secondary index entry if found. +NOTE that if we updated the fields of a delete-marked secondary index record +so that alphabetically they stayed the same, e.g., 'abc' -> 'aBc', we cannot +return to the original values because we do not know them. But this should +not cause problems because in row0sel.c, in queries we always retrieve the +clustered index record or an earlier version of it, if the secondary index +record through which we do the search is delete-marked. */ +static ulint row_undo_mod_del_mark_or_remove_sec( /*================================*/ @@ -403,20 +409,31 @@ row_undo_mod_del_mark_or_remove_sec( } /*************************************************************** -Delete unmarks a secondary index entry which must be found. */ +Delete unmarks a secondary index entry which must be found. It might not be +delete-marked at the moment, but it does not harm to unmark it anyway. We also +need to update the fields of the secondary index record if we updated its +fields but alphabetically they stayed the same, e.g., 'abc' -> 'aBc'. */ static -void -row_undo_mod_del_unmark_sec( -/*========================*/ +ulint +row_undo_mod_del_unmark_sec_and_undo_update( +/*========================================*/ + /* out: DB_FAIL or DB_SUCCESS or + DB_OUT_OF_FILE_SPACE */ + ulint mode, /* in: search mode: BTR_MODIFY_LEAF or + BTR_MODIFY_TREE */ undo_node_t* node, /* in: row undo node */ que_thr_t* thr, /* in: query thread */ dict_index_t* index, /* in: index */ dtuple_t* entry) /* in: index entry */ { + mem_heap_t* heap; btr_pcur_t pcur; btr_cur_t* btr_cur; - ulint err; + upd_t* update; + rec_t* rec; + ulint err = DB_SUCCESS; ibool found; + big_rec_t* dummy_big_rec; mtr_t mtr; char err_buf[1000]; @@ -425,8 +442,8 @@ row_undo_mod_del_unmark_sec( log_free_check(); mtr_start(&mtr); - found = row_search_index_entry(index, entry, BTR_MODIFY_LEAF, &pcur, - &mtr); + found = row_search_index_entry(index, entry, mode, &pcur, &mtr); + if (!found) { fprintf(stderr, "InnoDB: error in sec index entry del undo in\n" @@ -443,17 +460,47 @@ row_undo_mod_del_unmark_sec( "%s\nInnoDB: Make a detailed bug report and send it\n", err_buf); fprintf(stderr, "InnoDB: to mysql@lists.mysql.com\n"); - } else { btr_cur = btr_pcur_get_btr_cur(&pcur); + rec = btr_cur_get_rec(btr_cur); + err = btr_cur_del_mark_set_sec_rec(BTR_NO_LOCKING_FLAG, btr_cur, FALSE, thr, &mtr); - ut_ad(err == DB_SUCCESS); + ut_a(err == DB_SUCCESS); + heap = mem_heap_create(100); + + update = row_upd_build_sec_rec_difference_binary(index, entry, + rec, heap); + if (upd_get_n_fields(update) == 0) { + + /* Do nothing */ + + } else if (mode == BTR_MODIFY_LEAF) { + /* Try an optimistic updating of the record, keeping + changes within the page */ + + err = btr_cur_optimistic_update(BTR_KEEP_SYS_FLAG + | BTR_NO_LOCKING_FLAG, + btr_cur, update, 0, thr, &mtr); + if (err == DB_OVERFLOW || err == DB_UNDERFLOW) { + err = DB_FAIL; + } + } else { + ut_a(mode == BTR_MODIFY_TREE); + err = btr_cur_pessimistic_update(BTR_KEEP_SYS_FLAG + | BTR_NO_LOCKING_FLAG, + btr_cur, &dummy_big_rec, + update, 0, thr, &mtr); + } + + mem_heap_free(heap); } btr_pcur_close(&pcur); mtr_commit(&mtr); + + return(err); } /*************************************************************** @@ -501,13 +548,14 @@ static ulint row_undo_mod_del_mark_sec( /*======================*/ - /* out: DB_SUCCESS */ + /* out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE */ undo_node_t* node, /* in: row undo node */ que_thr_t* thr) /* in: query thread */ { mem_heap_t* heap; dtuple_t* entry; dict_index_t* index; + ulint err; heap = mem_heap_create(1024); @@ -516,7 +564,21 @@ row_undo_mod_del_mark_sec( entry = row_build_index_entry(node->row, index, heap); - row_undo_mod_del_unmark_sec(node, thr, index, entry); + err = row_undo_mod_del_unmark_sec_and_undo_update( + BTR_MODIFY_LEAF, + node, thr, index, entry); + if (err == DB_FAIL) { + err = row_undo_mod_del_unmark_sec_and_undo_update( + BTR_MODIFY_TREE, + node, thr, index, entry); + } + + if (err != DB_SUCCESS) { + + mem_heap_free(heap); + + return(err); + } node->index = dict_table_get_next_index(node->index); } @@ -532,7 +594,7 @@ static ulint row_undo_mod_upd_exist_sec( /*=======================*/ - /* out: DB_SUCCESS or error code */ + /* out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE */ undo_node_t* node, /* in: row undo node */ que_thr_t* thr) /* in: query thread */ { @@ -558,22 +620,48 @@ row_undo_mod_upd_exist_sec( /* Build the newest version of the index entry */ entry = row_build_index_entry(node->row, index, heap); + /* NOTE that if we updated the fields of a + delete-marked secondary index record so that + alphabetically they stayed the same, e.g., + 'abc' -> 'aBc', we cannot return to the original + values because we do not know them. But this should + not cause problems because in row0sel.c, in queries + we always retrieve the clustered index record or an + earlier version of it, if the secondary index record + through which we do the search is delete-marked. */ + err = row_undo_mod_del_mark_or_remove_sec(node, thr, - index, entry); + index, entry); if (err != DB_SUCCESS) { mem_heap_free(heap); return(err); } - + /* We may have to update the delete mark in the secondary index record of the previous version of - the row */ + the row. We also need to update the fields of + the secondary index record if we updated its fields + but alphabetically they stayed the same, e.g., + 'abc' -> 'aBc'. */ row_upd_index_replace_new_col_vals(entry, index, node->update, NULL); + err = row_undo_mod_del_unmark_sec_and_undo_update( + BTR_MODIFY_LEAF, + node, thr, index, entry); + if (err == DB_FAIL) { + err = + row_undo_mod_del_unmark_sec_and_undo_update( + BTR_MODIFY_TREE, + node, thr, index, entry); + } - row_undo_mod_del_unmark_sec(node, thr, index, entry); + if (err != DB_SUCCESS) { + mem_heap_free(heap); + + return(err); + } } node->index = dict_table_get_next_index(node->index); diff --git a/innobase/row/row0upd.c b/innobase/row/row0upd.c index 606f7404d50..b9e9b8c15c9 100644 --- a/innobase/row/row0upd.c +++ b/innobase/row/row0upd.c @@ -361,8 +361,8 @@ row_upd_changes_field_size_or_external( /* out: TRUE if the update changes the size of some field in index or the field is external in rec or update */ - rec_t* rec, /* in: record in clustered index */ - dict_index_t* index, /* in: clustered index */ + rec_t* rec, /* in: record in index */ + dict_index_t* index, /* in: index */ upd_t* update) /* in: update vector */ { upd_field_t* upd_field; @@ -372,8 +372,6 @@ row_upd_changes_field_size_or_external( ulint n_fields; ulint i; - ut_ad(index->type & DICT_CLUSTERED); - n_fields = upd_get_n_fields(update); for (i = 0; i < n_fields; i++) { @@ -698,7 +696,7 @@ row_upd_build_sec_rec_difference_binary( ulint i; /* This function is used only for a secondary index */ - ut_ad(0 == (index->type & DICT_CLUSTERED)); + ut_a(0 == (index->type & DICT_CLUSTERED)); update = upd_create(dtuple_get_n_fields(entry), heap); @@ -710,7 +708,13 @@ row_upd_build_sec_rec_difference_binary( dfield = dtuple_get_nth_field(entry, i); - ut_a(len == dfield_get_len(dfield)); + /* NOTE that it may be that len != dfield_get_len(dfield) if we + are updating in a character set and collation where strings of + different length can be equal in an alphabetical comparison, + and also in the case where we have a column prefix index + and the last characters in the index field are spaces; the + latter case probably caused the assertion failures reported at + row0upd.c line 713 in versions 4.0.14 - 4.0.16. */ /* NOTE: we compare the fields as binary strings! (No collation) */ @@ -820,12 +824,76 @@ Replaces the new column values stored in the update vector to the index entry given. */ void +row_upd_index_replace_new_col_vals_index_pos( +/*=========================================*/ + dtuple_t* entry, /* in/out: index entry where replaced */ + dict_index_t* index, /* in: index; NOTE that this may also be a + non-clustered index */ + upd_t* update, /* in: an update vector built for the index so + that the field number in an upd_field is the + index position */ + mem_heap_t* heap) /* in: memory heap to which we allocate and + copy the new values, set this as NULL if you + do not want allocation */ +{ + dict_field_t* field; + upd_field_t* upd_field; + dfield_t* dfield; + dfield_t* new_val; + ulint j; + ulint i; + + ut_ad(index); + + dtuple_set_info_bits(entry, update->info_bits); + + for (j = 0; j < dict_index_get_n_fields(index); j++) { + + field = dict_index_get_nth_field(index, j); + + for (i = 0; i < upd_get_n_fields(update); i++) { + + upd_field = upd_get_nth_field(update, i); + + if (upd_field->field_no == j) { + + dfield = dtuple_get_nth_field(entry, j); + + new_val = &(upd_field->new_val); + + dfield_set_data(dfield, new_val->data, + new_val->len); + if (heap && new_val->len != UNIV_SQL_NULL) { + dfield->data = mem_heap_alloc(heap, + new_val->len); + ut_memcpy(dfield->data, new_val->data, + new_val->len); + } + + if (field->prefix_len > 0 + && new_val->len != UNIV_SQL_NULL + && new_val->len > field->prefix_len) { + + dfield->len = field->prefix_len; + } + } + } + } +} + +/*************************************************************** +Replaces the new column values stored in the update vector to the index entry +given. */ + +void row_upd_index_replace_new_col_vals( /*===============================*/ dtuple_t* entry, /* in/out: index entry where replaced */ dict_index_t* index, /* in: index; NOTE that this may also be a non-clustered index */ - upd_t* update, /* in: update vector */ + upd_t* update, /* in: an update vector built for the + CLUSTERED index so that the field number in + an upd_field is the clustered index position */ mem_heap_t* heap) /* in: memory heap to which we allocate and copy the new values, set this as NULL if you do not want allocation */ @@ -893,7 +961,9 @@ row_upd_changes_ord_field_binary( known when this function is called, e.g., at compile time */ dict_index_t* index, /* in: index of the record */ - upd_t* update) /* in: update vector for the row */ + upd_t* update) /* in: update vector for the row; NOTE: the + field numbers in this MUST be clustered index + positions! */ { upd_field_t* upd_field; dict_field_t* ind_field; diff --git a/innobase/row/row0vers.c b/innobase/row/row0vers.c index d4a463d8a96..fca56389e45 100644 --- a/innobase/row/row0vers.c +++ b/innobase/row/row0vers.c @@ -117,9 +117,10 @@ row_vers_impl_x_locked_off_kernel( return(NULL); } - /* We look up if some earlier version of the clustered index record - would require rec to be in a different state (delete marked or - unmarked, or not existing). If there is such a version, then rec was + /* We look up if some earlier version, which was modified by the trx_id + transaction, of the clustered index record would require rec to be in + a different state (delete marked or unmarked, or have different field + values, or not existing). If there is such a version, then rec was modified by the trx_id transaction, and it has an implicit x-lock on rec. Note that if clust_rec itself would require rec to be in a different state, then the trx_id transaction has not yet had time to @@ -188,6 +189,8 @@ row_vers_impl_x_locked_off_kernel( vers_del = rec_get_deleted_flag(prev_version); + /* We check if entry and rec are identified in the alphabetical + ordering */ if (0 == cmp_dtuple_rec(entry, rec)) { /* The delete marks of rec and prev_version should be equal for rec to be in the state required by @@ -198,6 +201,20 @@ row_vers_impl_x_locked_off_kernel( break; } + + /* It is possible that the row was updated so that the + secondary index record remained the same in + alphabetical ordering, but the field values changed + still. For example, 'abc' -> 'ABC'. Check also that. */ + + dtuple_set_types_binary(entry, + dtuple_get_n_fields(entry)); + if (0 != cmp_dtuple_rec(entry, rec)) { + + trx = trx_get_on_id(trx_id); + + break; + } } else if (!rec_del) { /* The delete mark should be set in rec for it to be in the state required by prev_version */ @@ -256,8 +273,8 @@ row_vers_must_preserve_del_marked( Finds out if a version of the record, where the version >= the current purge view, should have ientry as its secondary index entry. We check if there is any not delete marked version of the record where the trx -id >= purge view, and the secondary index entry == ientry; exactly in -this case we return TRUE. */ +id >= purge view, and the secondary index entry and ientry are identified in +the alphabetical ordering; exactly in this case we return TRUE. */ ibool row_vers_old_has_index_entry( diff --git a/libmysql/client_settings.h b/libmysql/client_settings.h index 3798eaa3544..b1a85f567f9 100644 --- a/libmysql/client_settings.h +++ b/libmysql/client_settings.h @@ -58,3 +58,14 @@ int cli_stmt_execute(MYSQL_STMT *stmt); MYSQL_DATA * cli_read_binary_rows(MYSQL_STMT *stmt); int cli_unbuffered_fetch(MYSQL *mysql, char **row); const char * cli_read_statistic(MYSQL *mysql); + +#ifdef EMBEDDED_LIBRARY +int init_embedded_server(int argc, char **argv, char **groups); +void end_embedded_server(); + +#else +/* Prevent warnings of unused parameters */ +#define init_embedded_server(a,b,c) ((void)a, (void)b, (void)c, 0) +#define end_embedded_server() +#endif /*EMBEDDED_LIBRARY*/ + diff --git a/libmysql/errmsg.c b/libmysql/errmsg.c index 4dfcfe6a1d3..569267ddb37 100644 --- a/libmysql/errmsg.c +++ b/libmysql/errmsg.c @@ -72,7 +72,6 @@ const char *client_errors[]= "Can't open shared memory. Can't send the request event to server (%lu)", "Wrong or unknown protocol", "Invalid connection handle", - "mysql_server_init wasn't called", "Connection using old (pre 4.1.1) authentication protocol refused (client option 'secure_auth' enabled)" }; @@ -129,7 +128,6 @@ const char *client_errors[]= "Can't open shared memory. Can't send the request event to server (%lu)", "Wrong or unknown protocol", "Invalid connection handle", - "mysql_server_init wasn't called", "Connection using old (pre 4.1.1) authentication protocol refused (client option 'secure_auth' enabled)" }; @@ -184,7 +182,6 @@ const char *client_errors[]= "Can't open shared memory. Can't send the request event to server (%lu)", "Wrong or unknown protocol", "Invalid connection handle", - "mysql_server_init wasn't called", "Connection using old (pre 4.1.1) authentication protocol refused (client option 'secure_auth' enabled)" }; #endif diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index b3ae6034520..2c62a71a798 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -94,13 +94,34 @@ my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list); static my_bool mysql_client_init= 0; static my_bool org_my_init_done= 0; -void mysql_once_init(void) + +/* + Initialize the MySQL client library + + SYNOPSIS + mysql_server_init() + + NOTES + Should be called before doing any other calls to the MySQL + client library to initialize thread specific variables etc. + It's called by mysql_init() to ensure that things will work for + old not threaded applications that doesn't call mysql_server_init() + directly. + + RETURN + 0 ok + 1 could not initialize environment (out of memory or thread keys) +*/ + +int STDCALL mysql_server_init(int argc, char **argv, char **groups) { + int result= 0; if (!mysql_client_init) { mysql_client_init=1; org_my_init_done=my_init_done; - my_init(); /* Will init threads */ + if (my_init()) /* Will init threads */ + return 1; init_client_errs(); if (!mysql_port) { @@ -131,24 +152,19 @@ void mysql_once_init(void) #if defined(SIGPIPE) && !defined(__WIN__) (void) signal(SIGPIPE, SIG_IGN); #endif + result= init_embedded_server(argc, argv, groups); } #ifdef THREAD else - my_thread_init(); /* Init if new thread */ + result= (int)my_thread_init(); /* Init if new thread */ #endif + return result; } -#ifndef EMBEDDED_LIBRARY -int STDCALL mysql_server_init(int argc __attribute__((unused)), - char **argv __attribute__((unused)), - char **groups __attribute__((unused))) -{ - mysql_once_init(); - return 0; -} void STDCALL mysql_server_end() { + end_embedded_server(); /* If library called my_init(), free memory allocated by it */ if (!org_my_init_done) { @@ -163,8 +179,6 @@ void STDCALL mysql_server_end() mysql_client_init= org_my_init_done= 0; } -#endif /*EMBEDDED_LIBRARY*/ - my_bool STDCALL mysql_thread_init() { #ifdef THREAD diff --git a/libmysqld/embedded_priv.h b/libmysqld/embedded_priv.h index 833cc1b1f80..673531c0c14 100644 --- a/libmysqld/embedded_priv.h +++ b/libmysqld/embedded_priv.h @@ -28,5 +28,4 @@ extern void init_embedded_mysql(MYSQL *mysql, int client_flag, char *db); extern void *create_embedded_thd(int client_flag, char *db); extern MYSQL_METHODS embedded_methods; void free_old_query(MYSQL *mysql); -extern my_bool server_inited; C_MODE_END diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index 198ab499fbf..89012a84857 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -42,9 +42,6 @@ C_MODE_START #include "errmsg.h" #include <sql_common.h> -static my_bool org_my_init_done; -my_bool server_inited; - static my_bool emb_advanced_command(MYSQL *mysql, enum enum_server_command command, const char *header, ulong header_length, @@ -305,7 +302,7 @@ extern "C" char ** copy_arguments_ptr= 0; -int STDCALL mysql_server_init(int argc, char **argv, char **groups) +int init_embedded_server(int argc, char **argv, char **groups) { char glob_hostname[FN_REFLEN]; @@ -329,17 +326,7 @@ int STDCALL mysql_server_init(int argc, char **argv, char **groups) if (!groups) groups= (char**) fake_groups; - - /* Only call MY_INIT() if it hasn't been called before */ - if (!server_inited) - { - server_inited=1; - org_my_init_done=my_init_done; - } - if (!org_my_init_done) - { - MY_INIT((char *)"mysql_embedded"); // init my_sys library & pthreads - } + my_progname= (char *)"mysql_embedded"; if (init_common_variables("my", *argcp, *argvp, (const char **)groups)) { @@ -438,14 +425,11 @@ int STDCALL mysql_server_init(int argc, char **argv, char **groups) return 0; } -void STDCALL mysql_server_end() +void end_embedded_server() { my_free((char*) copy_arguments_ptr, MYF(MY_ALLOW_ZERO_PTR)); copy_arguments_ptr=0; clean_up(0); - /* If library called my_init(), free memory allocated by it */ - if (!org_my_init_done) - my_end(0); } } /* extern "C" */ diff --git a/libmysqld/libmysqld.c b/libmysqld/libmysqld.c index 59c18368279..f96c06ff0f6 100644 --- a/libmysqld/libmysqld.c +++ b/libmysqld/libmysqld.c @@ -163,20 +163,12 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, db ? db : "(Null)", user ? user : "(Null)")); -#if defined(EMBEDDED_LIBRARY) || !defined(DBUG_OFF) - if (!server_inited) - { - mysql->net.last_errno=CR_MYSQL_SERVER_INIT_MISSED; - strmov(mysql->net.last_error,ER(mysql->net.last_errno)); - goto error; - } -#endif - if (mysql->options.methods_to_use == MYSQL_OPT_USE_REMOTE_CONNECTION || (mysql->options.methods_to_use == MYSQL_OPT_GUESS_CONNECTION && host && strcmp(host,LOCAL_HOST))) - cli_mysql_real_connect(mysql, host, user, - passwd, db, port, unix_socket, client_flag); + DBUG_RETURN(cli_mysql_real_connect(mysql, host, user, + passwd, db, port, + unix_socket, client_flag)); mysql->methods= &embedded_methods; diff --git a/myisam/ft_boolean_search.c b/myisam/ft_boolean_search.c index f48a12b6f28..8cbb7a71a43 100644 --- a/myisam/ft_boolean_search.c +++ b/myisam/ft_boolean_search.c @@ -373,10 +373,13 @@ FT_INFO * ft_init_boolean_search(MI_INFO *info, uint keynr, byte *query, to alloc queue with alloc_root() */ res=ftb->queue.max_elements=1+query_len/(min(ft_min_word_len,2)+1); - ftb->queue.root=(byte **)alloc_root(&ftb->mem_root, (res+1)*sizeof(void*)); + if (!(ftb->queue.root= + (byte **)alloc_root(&ftb->mem_root, (res+1)*sizeof(void*)))) + goto err; reinit_queue(& ftb->queue, res, 0, 0, (int (*)(void*,byte*,byte*))FTB_WORD_cmp, 0); - ftbe=(FTB_EXPR *)alloc_root(&ftb->mem_root, sizeof(FTB_EXPR)); + if (!(ftbe=(FTB_EXPR *)alloc_root(&ftb->mem_root, sizeof(FTB_EXPR)))) + goto err; ftbe->weight=1; ftbe->flags=FTB_FLAG_YES; ftbe->nos=1; @@ -394,6 +397,10 @@ FT_INFO * ft_init_boolean_search(MI_INFO *info, uint keynr, byte *query, if (ftb->queue.elements<2) ftb->with_scan &= ~FTB_FLAG_TRUNC; ftb->state=READY; return ftb; +err: + free_root(& ftb->mem_root, MYF(0)); + my_free((gptr)ftb,MYF(0)); + return 0; } diff --git a/myisam/mi_check.c b/myisam/mi_check.c index 2b14e8bf8eb..c61e94b6399 100644 --- a/myisam/mi_check.c +++ b/myisam/mi_check.c @@ -112,20 +112,13 @@ int chk_status(MI_CHECK *param, register MI_INFO *info) int chk_del(MI_CHECK *param, register MI_INFO *info, uint test_flag) { reg2 ha_rows i; - uint j,delete_link_length; + uint delete_link_length; my_off_t empty,next_link,old_link; char buff[22],buff2[22]; DBUG_ENTER("chk_del"); - if (!(test_flag & T_SILENT)) - puts("- check key delete-chain"); - LINT_INIT(old_link); param->record_checksum=0; - param->key_file_blocks=info->s->base.keystart; - for (j=0 ; j < info->s->state.header.max_block_size ; j++) - if (check_k_link(param,info,j)) - goto wrong; delete_link_length=((info->s->options & HA_OPTION_PACK_RECORD) ? 20 : info->s->rec_reflength+1); @@ -352,6 +345,18 @@ int chk_key(MI_CHECK *param, register MI_INFO *info) char buff[22],buff2[22]; DBUG_ENTER("chk_key"); + if (!(param->testflag & T_SILENT)) + puts("- check key delete-chain"); + + param->key_file_blocks=info->s->base.keystart; + for (key=0 ; key < info->s->state.header.max_block_size ; key++) + if (check_k_link(param,info,key)) + { + if (param->testflag & T_VERBOSE) puts(""); + mi_check_print_error(param,"key delete-link-chain corrupted"); + DBUG_RETURN(-1); + } + if (!(param->testflag & T_SILENT)) puts("- check index reference"); all_keydata=all_totaldata=key_totlength=0; @@ -507,6 +512,7 @@ int chk_key(MI_CHECK *param, register MI_INFO *info) DBUG_RETURN(result); } /* chk_key */ + static int chk_index_down(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, my_off_t page, uchar *buff, ha_rows *keys, ha_checksum *key_checksum, uint level) @@ -548,7 +554,7 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, uint used_length,comp_flag,nod_flag,key_length,not_used; uchar key[MI_MAX_POSSIBLE_KEY_BUFF],*temp_buff,*keypos,*old_keypos,*endpos; my_off_t next_page,record; - char llbuff[22],llbuff2[22]; + char llbuff[22]; DBUG_ENTER("chk_index"); DBUG_DUMP("buff",(byte*) buff,mi_getint(buff)); @@ -646,7 +652,7 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, if (record >= info->state->data_file_length) { #ifndef DBUG_OFF - char llbuff3[22]; + char llbuff2[22], llbuff3[22]; #endif mi_check_print_error(param,"Found key at page %s that points to record outside datafile",llstr(page,llbuff)); DBUG_PRINT("test",("page: %s record: %s filelength: %s", @@ -1208,9 +1214,8 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, if (!rep_quick) { /* Get real path for data file */ - fn_format(param->temp_filename,name,"", MI_NAME_DEXT,2+4+32); if ((new_file=my_raid_create(fn_format(param->temp_filename, - param->temp_filename,"", + share->data_file_name, "", DATA_TMP_EXT, 2+4), 0,param->tmpfile_createflag, share->base.raid_type, @@ -1882,11 +1887,9 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, if (!rep_quick) { /* Get real path for data file */ - fn_format(param->temp_filename,name,"", MI_NAME_DEXT,2+4+32); if ((new_file=my_raid_create(fn_format(param->temp_filename, - param->temp_filename, "", - DATA_TMP_EXT, - 2+4), + share->data_file_name, "", + DATA_TMP_EXT, 2+4), 0,param->tmpfile_createflag, share->base.raid_type, share->base.raid_chunks, @@ -2248,9 +2251,8 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info, if (!rep_quick) { /* Get real path for data file */ - fn_format(param->temp_filename,name,"", MI_NAME_DEXT,2+4+32); if ((new_file=my_raid_create(fn_format(param->temp_filename, - param->temp_filename, "", + share->data_file_name, "", DATA_TMP_EXT, 2+4), 0,param->tmpfile_createflag, diff --git a/myisam/mi_dbug.c b/myisam/mi_dbug.c index 6548b38c135..02d1c7d05d6 100644 --- a/myisam/mi_dbug.c +++ b/myisam/mi_dbug.c @@ -137,6 +137,10 @@ void _mi_print_key(FILE *stream, register HA_KEYSEG *keyseg, { uint tmp_length; get_key_length(tmp_length,key); + /* + The following command sometimes gives a warning from valgrind. + Not yet sure if the bug is in valgrind, glibc or mysqld + */ VOID(fprintf(stream,"%.*s",(int) tmp_length,key)); key+=tmp_length; break; diff --git a/myisam/mi_key.c b/myisam/mi_key.c index 93e3b9621f3..97af156e89a 100644 --- a/myisam/mi_key.c +++ b/myisam/mi_key.c @@ -19,6 +19,7 @@ #include "myisamdef.h" #include "m_ctype.h" #include "sp_defs.h" +#include <assert.h> #ifdef HAVE_IEEEFP_H #include <ieeefp.h> #endif @@ -397,53 +398,86 @@ int _mi_read_key_record(MI_INFO *info, my_off_t filepos, byte *buf) return(-1); /* Wrong data to read */ } + +/* + Update auto_increment info - /* Update auto_increment info */ + SYNOPSIS + update_auto_increment() + info MyISAM handler + record Row to update + + IMPLEMENTATION + Only replace the auto_increment value if it is higher than the previous + one. For signed columns we don't update the auto increment value if it's + less than zero. +*/ void update_auto_increment(MI_INFO *info,const byte *record) { - ulonglong value; - HA_KEYSEG *keyseg=info->s->keyinfo[info->s->base.auto_key-1].seg; - const uchar *key=(uchar*) record+keyseg->start; + ulonglong value= 0; /* Store unsigned values here */ + longlong s_value= 0; /* Store signed values here */ + HA_KEYSEG *keyseg= info->s->keyinfo[info->s->base.auto_key-1].seg; + const uchar *key= (uchar*) record + keyseg->start; switch (keyseg->type) { case HA_KEYTYPE_INT8: + s_value= (longlong) *(char*)key; + break; case HA_KEYTYPE_BINARY: value=(ulonglong) *(uchar*) key; break; case HA_KEYTYPE_SHORT_INT: + s_value= (longlong) sint2korr(key); + break; case HA_KEYTYPE_USHORT_INT: value=(ulonglong) uint2korr(key); break; case HA_KEYTYPE_LONG_INT: + s_value= (longlong) sint4korr(key); + break; case HA_KEYTYPE_ULONG_INT: value=(ulonglong) uint4korr(key); break; case HA_KEYTYPE_INT24: + s_value= (longlong) sint3korr(key); + break; case HA_KEYTYPE_UINT24: value=(ulonglong) uint3korr(key); break; - case HA_KEYTYPE_FLOAT: /* This shouldn't be used */ + case HA_KEYTYPE_FLOAT: /* This shouldn't be used */ { float f_1; float4get(f_1,key); - value = (ulonglong) f_1; + /* Ignore negative values */ + value = (f_1 < (float) 0.0) ? 0 : (ulonglong) f_1; break; } - case HA_KEYTYPE_DOUBLE: /* This shouldn't be used */ + case HA_KEYTYPE_DOUBLE: /* This shouldn't be used */ { double f_1; float8get(f_1,key); - value = (ulonglong) f_1; + /* Ignore negative values */ + value = (f_1 < 0.0) ? 0 : (ulonglong) f_1; break; } case HA_KEYTYPE_LONGLONG: + s_value= sint8korr(key); + break; case HA_KEYTYPE_ULONGLONG: value= uint8korr(key); break; default: - value=0; /* Error */ + DBUG_ASSERT(0); + value=0; /* Error */ break; } - set_if_bigger(info->s->state.auto_increment,value); + + /* + The following code works becasue if s_value < 0 then value is 0 + and if s_value == 0 then value will contain either s_value or the + correct value. + */ + set_if_bigger(info->s->state.auto_increment, + (s_value > 0) ? (ulonglong) s_value : value); } diff --git a/myisam/mi_open.c b/myisam/mi_open.c index d5492ae5e35..2c4661c4d3e 100644 --- a/myisam/mi_open.c +++ b/myisam/mi_open.c @@ -867,6 +867,8 @@ char *mi_state_info_read(char *ptr, MI_STATE_INFO *state) state->status = mi_uint4korr(ptr); ptr +=4; state->update_count=mi_uint4korr(ptr); ptr +=4; + ptr+= state->state_diff_length; + for (i=0; i < keys; i++) { state->key_root[i]= mi_sizekorr(ptr); ptr +=8; @@ -875,7 +877,6 @@ char *mi_state_info_read(char *ptr, MI_STATE_INFO *state) { state->key_del[i] = mi_sizekorr(ptr); ptr +=8; } - ptr+= state->state_diff_length; state->sec_index_changed = mi_uint4korr(ptr); ptr +=4; state->sec_index_used = mi_uint4korr(ptr); ptr +=4; state->version = mi_uint4korr(ptr); ptr +=4; diff --git a/mysql-test/r/auto_increment.result b/mysql-test/r/auto_increment.result index 05317c0f845..7a7faf0db9a 100644 --- a/mysql-test/r/auto_increment.result +++ b/mysql-test/r/auto_increment.result @@ -106,6 +106,32 @@ Table Op Msg_type Msg_text test.t1 check warning Found row where the auto_increment column has the value 0 test.t1 check status OK drop table t1; +create table t1 (a int not null auto_increment primary key); +insert into t1 values (NULL); +insert into t1 values (-1); +select last_insert_id(); +last_insert_id() +1 +insert into t1 values (NULL); +select * from t1; +a +-1 +1 +2 +drop table t1; +create table t1 (a int not null auto_increment primary key) /*!40102 engine=heap */; +insert into t1 values (NULL); +insert into t1 values (-1); +select last_insert_id(); +last_insert_id() +1 +insert into t1 values (NULL); +select * from t1; +a +1 +-1 +2 +drop table t1; create table t1 (i tinyint unsigned not null auto_increment primary key); insert into t1 set i = 254; insert into t1 set i = null; diff --git a/mysql-test/r/bdb.result b/mysql-test/r/bdb.result index 6021f02f2a6..b02574cf8a3 100644 --- a/mysql-test/r/bdb.result +++ b/mysql-test/r/bdb.result @@ -1145,3 +1145,14 @@ x 7 6 drop table t1; +create table t1 ( c char(8) not null ) engine=bdb; +insert into t1 values ('0'),('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9'); +insert into t1 values ('A'),('B'),('C'),('D'),('E'),('F'); +alter table t1 add b char(8) not null; +alter table t1 add a char(8) not null; +alter table t1 add primary key (a,b,c); +update t1 set a=c, b=c; +create table t2 (c char(8) not null, b char(8) not null, a char(8) not null, primary key(a,b,c)) engine=bdb; +insert into t2 select * from t1; +delete t1,t2 from t2,t1 where t1.a<'B' and t2.b=t1.b; +drop table t1,t2; diff --git a/mysql-test/r/binary.result b/mysql-test/r/binary.result index 5da627a30b9..d4576791aed 100644 --- a/mysql-test/r/binary.result +++ b/mysql-test/r/binary.result @@ -66,6 +66,7 @@ concat("-",a,"-",b,"-") alter table t1 modify b tinytext not null, drop key b, add key (b(100)); select concat("-",a,"-",b,"-") from t1 where b="hello "; concat("-",a,"-",b,"-") +-hello-hello- select concat("-",a,"-",b,"-") from t1 ignore index (b) where b="hello "; concat("-",a,"-",b,"-") -hello-hello- diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index 78433c10014..940c9e9a50b 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -189,9 +189,9 @@ select * from t1; if('2002'='2002','Y','N') Y drop table if exists t1; -SET SESSION table_type="heap"; -SELECT @@table_type; -@@table_type +SET SESSION storage_engine="heap"; +SELECT @@storage_engine; +@@storage_engine HEAP CREATE TABLE t1 (a int not null); show create table t1; @@ -200,10 +200,10 @@ t1 CREATE TABLE `t1` ( `a` int(11) NOT NULL default '0' ) ENGINE=HEAP DEFAULT CHARSET=latin1 drop table t1; -SET SESSION table_type="gemini"; +SET SESSION storage_engine="gemini"; ERROR 42000: Unknown table engine 'gemini' -SELECT @@table_type; -@@table_type +SELECT @@storage_engine; +@@storage_engine HEAP CREATE TABLE t1 (a int not null); show create table t1; @@ -211,7 +211,7 @@ Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) NOT NULL default '0' ) ENGINE=HEAP DEFAULT CHARSET=latin1 -SET SESSION table_type=default; +SET SESSION storage_engine=default; drop table t1; create table t1 ( k1 varchar(2), k2 int, primary key(k1,k2)); insert into t1 values ("a", 1), ("b", 2); @@ -334,9 +334,9 @@ ERROR 42000: Incorrect table name 'a/a' drop table t1, t2, t3; drop table t3; drop database test_$1; -SET SESSION table_type="heap"; -SELECT @@table_type; -@@table_type +SET SESSION storage_engine="heap"; +SELECT @@storage_engine; +@@storage_engine HEAP CREATE TABLE t1 (a int not null); show create table t1; @@ -345,10 +345,10 @@ t1 CREATE TABLE `t1` ( `a` int(11) NOT NULL default '0' ) ENGINE=HEAP DEFAULT CHARSET=latin1 drop table t1; -SET SESSION table_type="gemini"; +SET SESSION storage_engine="gemini"; ERROR 42000: Unknown table engine 'gemini' -SELECT @@table_type; -@@table_type +SELECT @@storage_engine; +@@storage_engine HEAP CREATE TABLE t1 (a int not null); show create table t1; @@ -356,7 +356,7 @@ Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) NOT NULL default '0' ) ENGINE=HEAP DEFAULT CHARSET=latin1 -SET SESSION table_type=default; +SET SESSION storage_engine=default; drop table t1; create table t1(a int,b int,c int unsigned,d date,e char,f datetime,g time,h blob); insert into t1(a)values(1); diff --git a/mysql-test/r/ctype_create.result b/mysql-test/r/ctype_create.result new file mode 100644 index 00000000000..b9146b5818f --- /dev/null +++ b/mysql-test/r/ctype_create.result @@ -0,0 +1,20 @@ +SET @@character_set_server=latin5; +CREATE DATABASE db1 DEFAULT CHARACTER SET cp1251; +USE db1; +CREATE DATABASE db2; +SHOW CREATE DATABASE db1; +Database Create Database +db1 CREATE DATABASE `db1` /*!40100 DEFAULT CHARACTER SET cp1251 */ +SHOW CREATE DATABASE db2; +Database Create Database +db2 CREATE DATABASE `db2` /*!40100 DEFAULT CHARACTER SET latin5 */ +DROP DATABASE db2; +USE db1; +CREATE TABLE t1 (a char(10)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` char(10) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=cp1251 +DROP TABLE t1; +DROP DATABASE db1; diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result index bdac40d3378..6a704f2847d 100644 --- a/mysql-test/r/func_group.result +++ b/mysql-test/r/func_group.result @@ -47,7 +47,7 @@ sum(all a) count(all a) avg(all a) std(all a) variance(all a) bit_or(all a) bit_ 21 6 3.5000 1.7078 2.9167 7 0 1 6 E select grp, sum(a),count(a),avg(a),std(a),variance(a),bit_or(a),bit_and(a),min(a),max(a),min(c),max(c) from t1 group by grp; grp sum(a) count(a) avg(a) std(a) variance(a) bit_or(a) bit_and(a) min(a) max(a) min(c) max(c) -NULL NULL 0 NULL NULL NULL 0 0 NULL NULL +NULL NULL 0 NULL NULL NULL 0 18446744073709551615 NULL NULL 1 1 1 1.0000 0.0000 0.0000 1 1 1 1 a a 2 5 2 2.5000 0.5000 0.2500 3 2 2 3 b c 3 15 3 5.0000 0.8165 0.6667 7 4 4 6 C E @@ -576,8 +576,8 @@ insert into t1 values (1,null); insert into t1 values (2,null); select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a; a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b) -1 0 NULL NULL NULL NULL NULL 0 0 -2 0 NULL NULL NULL NULL NULL 0 0 +1 0 NULL NULL NULL NULL NULL 18446744073709551615 0 +2 0 NULL NULL NULL NULL NULL 18446744073709551615 0 select SQL_BIG_RESULT a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a; a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b) 1 0 NULL NULL NULL NULL NULL 18446744073709551615 0 @@ -585,8 +585,8 @@ a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b) insert into t1 values (2,1); select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a; a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b) -1 0 NULL NULL NULL NULL NULL 0 0 -2 1 1 1.0000 0.0000 1 1 0 1 +1 0 NULL NULL NULL NULL NULL 18446744073709551615 0 +2 1 1 1.0000 0.0000 1 1 1 1 select SQL_BIG_RESULT a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a; a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b) 1 0 NULL NULL NULL NULL NULL 18446744073709551615 0 @@ -594,8 +594,8 @@ a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b) insert into t1 values (3,1); select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a; a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b) -1 0 NULL NULL NULL NULL NULL 0 0 -2 1 1 1.0000 0.0000 1 1 0 1 +1 0 NULL NULL NULL NULL NULL 18446744073709551615 0 +2 1 1 1.0000 0.0000 1 1 1 1 3 1 1 1.0000 0.0000 1 1 1 1 select SQL_BIG_RESULT a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b), bit_xor(b) from t1 group by a; a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b) bit_xor(b) @@ -632,3 +632,14 @@ select a from t1 having a=1; a 1 drop table t1; +create table t1 (col int); +insert into t1 values (-1), (-2), (-3); +select bit_and(col), bit_or(col) from t1; +bit_and(col) bit_or(col) +18446744073709551612 18446744073709551615 +select SQL_BIG_RESULT bit_and(col), bit_or(col) from t1 group by col; +bit_and(col) bit_or(col) +18446744073709551613 18446744073709551613 +18446744073709551614 18446744073709551614 +18446744073709551615 18446744073709551615 +drop table t1; diff --git a/mysql-test/r/func_op.result b/mysql-test/r/func_op.result index 25a7ac20b66..fb1e715ac3b 100644 --- a/mysql-test/r/func_op.result +++ b/mysql-test/r/func_op.result @@ -17,3 +17,21 @@ Note 1003 select high_priority (1 | (1 + 1)) AS `1 | (1+1)`,(5 & 3) AS `5 & 3`,b select 1 << 32,1 << 63, 1 << 64, 4 >> 2, 4 >> 63, 1<< 63 >> 60; 1 << 32 1 << 63 1 << 64 4 >> 2 4 >> 63 1<< 63 >> 60 4294967296 9223372036854775808 0 1 0 8 +select -1 | 0, -1 ^ 0, -1 & 0; +-1 | 0 -1 ^ 0 -1 & 0 +18446744073709551615 18446744073709551615 0 +select -1 | 1, -1 ^ 1, -1 & 1; +-1 | 1 -1 ^ 1 -1 & 1 +18446744073709551615 18446744073709551614 1 +select 1 | -1, 1 ^ -1, 1 & -1; +1 | -1 1 ^ -1 1 & -1 +18446744073709551615 18446744073709551614 1 +select 0 | -1, 0 ^ -1, 0 & -1; +0 | -1 0 ^ -1 0 & -1 +18446744073709551615 18446744073709551615 0 +select -1 >> 0, -1 << 0; +-1 >> 0 -1 << 0 +18446744073709551615 18446744073709551615 +select -1 >> 1, -1 << 1; +-1 >> 1 -1 << 1 +9223372036854775807 18446744073709551614 diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index ac075e129ee..c74feccfb7f 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -144,12 +144,12 @@ montymontymontymontymonty * * select reverse('abc'),reverse('abcd'); reverse('abc') reverse('abcd') cba dcba -select rpad('a',4,'1'),rpad('a',4,'12'),rpad('abcd',3,'12'); -rpad('a',4,'1') rpad('a',4,'12') rpad('abcd',3,'12') -a111 a121 abc -select lpad('a',4,'1'),lpad('a',4,'12'),lpad('abcd',3,'12'); -lpad('a',4,'1') lpad('a',4,'12') lpad('abcd',3,'12') -111a 121a abc +select rpad('a',4,'1'),rpad('a',4,'12'),rpad('abcd',3,'12'), rpad(11, 10 , 22), rpad("ab", 10, 22); +rpad('a',4,'1') rpad('a',4,'12') rpad('abcd',3,'12') rpad(11, 10 , 22) rpad("ab", 10, 22) +a111 a121 abc 1122222222 ab22222222 +select lpad('a',4,'1'),lpad('a',4,'12'),lpad('abcd',3,'12'), lpad(11, 10 , 22); +lpad('a',4,'1') lpad('a',4,'12') lpad('abcd',3,'12') lpad(11, 10 , 22) +111a 121a abc 2222222211 select rpad(741653838,17,'0'),lpad(741653838,17,'0'); rpad(741653838,17,'0') lpad(741653838,17,'0') 74165383800000000 00000000741653838 @@ -159,6 +159,12 @@ abcdaba abaabcd select rpad('abcd',1,'ab'),lpad('abcd',1,'ab'); rpad('abcd',1,'ab') lpad('abcd',1,'ab') a a +select rpad('STRING', 20, CONCAT('p','a','d') ); +rpad('STRING', 20, CONCAT('p','a','d') ) +STRINGpadpadpadpadpa +select lpad('STRING', 20, CONCAT('p','a','d') ); +lpad('STRING', 20, CONCAT('p','a','d') ) +padpadpadpadpaSTRING select LEAST(NULL,'HARRY','HARRIOT',NULL,'HAROLD'),GREATEST(NULL,'HARRY','HARRIOT',NULL,'HAROLD'); LEAST(NULL,'HARRY','HARRIOT',NULL,'HAROLD') GREATEST(NULL,'HARRY','HARRIOT',NULL,'HAROLD') HAROLD HARRY @@ -183,6 +189,9 @@ NULL '\0\Z' select length(quote(concat(char(0),"test"))); length(quote(concat(char(0),"test"))) 8 +select hex(quote(concat(char(224),char(227),char(230),char(231),char(232),char(234),char(235)))); +hex(quote(concat(char(224),char(227),char(230),char(231),char(232),char(234),char(235)))) +27E0E3E6E7E8EAEB27 select reverse(""); reverse("") diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index 37184705641..64a45837a15 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -95,11 +95,34 @@ week(19981231,2) week(19981231,3) week(20000101,2) week(20000101,3) 52 53 52 52 select week(20001231,2),week(20001231,3); week(20001231,2) week(20001231,3) -1 52 +53 52 +select week(19981231,0) as '0', week(19981231,1) as '1', week(19981231,2) as '2', week(19981231,3) as '3', week(19981231,4) as '4', week(19981231,5) as '5', week(19981231,6) as '6', week(19981231,7) as '7'; +0 1 2 3 4 5 6 7 +52 53 52 53 52 52 52 52 +select week(20000101,0) as '0', week(20000101,1) as '1', week(20000101,2) as '2', week(20000101,3) as '3', week(20000101,4) as '4', week(20000101,5) as '5', week(20000101,6) as '6', week(20000101,7) as '7'; +0 1 2 3 4 5 6 7 +0 0 52 52 0 0 52 52 +select week(20000106,0) as '0', week(20000106,1) as '1', week(20000106,2) as '2', week(20000106,3) as '3', week(20000106,4) as '4', week(20000106,5) as '5', week(20000106,6) as '6', week(20000106,7) as '7'; +0 1 2 3 4 5 6 7 +1 1 1 1 1 1 1 1 +select week(20001231,0) as '0', week(20001231,1) as '1', week(20001231,2) as '2', week(20001231,3) as '3', week(20001231,4) as '4', week(20001231,5) as '5', week(20001231,6) as '6', week(20001231,7) as '7'; +0 1 2 3 4 5 6 7 +53 52 53 52 53 52 1 52 +select week(20010101,0) as '0', week(20010101,1) as '1', week(20010101,2) as '2', week(20010101,3) as '3', week(20010101,4) as '4', week(20010101,5) as '5', week(20010101,6) as '6', week(20010101,7) as '7'; +0 1 2 3 4 5 6 7 +0 1 53 1 1 1 1 1 +select yearweek(20001231,0), yearweek(20001231,1), yearweek(20001231,2), yearweek(20001231,3), yearweek(20001231,4), yearweek(20001231,5), yearweek(20001231,6), yearweek(20001231,7); +yearweek(20001231,0) yearweek(20001231,1) yearweek(20001231,2) yearweek(20001231,3) yearweek(20001231,4) yearweek(20001231,5) yearweek(20001231,6) yearweek(20001231,7) +200053 200052 200053 200052 200101 200052 200101 200052 +set default_week_format = 6; +select week(20001231), week(20001231,6); +week(20001231) week(20001231,6) +1 1 +set default_week_format = 0; set default_week_format = 2; select week(20001231),week(20001231,2),week(20001231,0); week(20001231) week(20001231,2) week(20001231,0) -1 1 53 +53 53 53 set default_week_format = 0; select date_format('1998-12-31','%x-%v'),date_format('1999-01-01','%x-%v'); date_format('1998-12-31','%x-%v') date_format('1999-01-01','%x-%v') @@ -408,6 +431,15 @@ select * from t1, t3 where t1.start between t3.ctime1 and t3.ctime2; start ctime1 ctime2 2002-11-04 00:00:00 2002-10-29 16:51:06 2002-11-05 16:47:31 drop table t1,t2,t3; +select @a:=FROM_UNIXTIME(1); +@a:=FROM_UNIXTIME(1) +1970-01-01 03:00:01 +select unix_timestamp(@a); +unix_timestamp(@a) +1 +select unix_timestamp('1969-12-01 19:00:01'); +unix_timestamp('1969-12-01 19:00:01') +0 CREATE TABLE t1 (datetime datetime, timestamp timestamp, date date, time time); INSERT INTO t1 values ("2001-01-02 03:04:05", "2002-01-02 03:04:05", "2003-01-02", "06:07:08"); SELECT * from t1; diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index 853260a0164..bbe3326fd34 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -291,7 +291,7 @@ Warnings: Note 1003 select high_priority big_result test.t1.spID AS `spid`,sum(test.t1.userID) AS `sum(userid)` from test.t1 group by test.t1.spID desc explain select sql_big_result spid,sum(userid) from t1 group by spid desc order by null; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 8 +1 SIMPLE t1 ALL NULL NULL NULL NULL 8 Using filesort select sql_big_result spid,sum(userid) from t1 group by spid desc; spid sum(userid) 7 3 @@ -600,3 +600,32 @@ count(*) category 1 3 1 4 drop table t1; +CREATE TABLE t1 ( +userid int(10) unsigned, +score smallint(5) unsigned, +key (score) +); +INSERT INTO t1 VALUES (1,1),(2,2),(1,1),(3,3),(3,3),(3,3),(3,3),(3,3); +SELECT userid,count(*) FROM t1 GROUP BY userid DESC; +userid count(*) +3 5 +2 1 +1 2 +EXPLAIN SELECT userid,count(*) FROM t1 GROUP BY userid DESC; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 8 Using temporary; Using filesort +DROP TABLE t1; +CREATE TABLE t1 ( +i int(11) default NULL, +j int(11) default NULL +); +INSERT INTO t1 VALUES (1,2),(2,3),(4,5),(3,5),(1,5),(23,5); +SELECT i, COUNT(DISTINCT(i)) FROM t1 GROUP BY j ORDER BY NULL; +i COUNT(DISTINCT(i)) +1 1 +2 1 +4 4 +explain SELECT i, COUNT(DISTINCT(i)) FROM t1 GROUP BY j ORDER BY NULL; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 6 Using filesort +DROP TABLE t1; diff --git a/mysql-test/r/have_mest_timezone.require b/mysql-test/r/have_mest_timezone.require deleted file mode 100644 index 2a219f39b7e..00000000000 --- a/mysql-test/r/have_mest_timezone.require +++ /dev/null @@ -1,2 +0,0 @@ -Variable_name Value -timezone MEST diff --git a/mysql-test/r/have_met_timezone.require b/mysql-test/r/have_met_timezone.require new file mode 100644 index 00000000000..b3fde075ebd --- /dev/null +++ b/mysql-test/r/have_met_timezone.require @@ -0,0 +1,2 @@ +FROM_UNIXTIME(24*3600) +1970-01-02 01:00:00 diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 58c0042e122..eb0b9af8e38 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -1312,17 +1312,41 @@ a b 111 100 111 100 drop table t1; +create table t1 ( c char(8) not null ) engine=innodb; +insert into t1 values ('0'),('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9'); +insert into t1 values ('A'),('B'),('C'),('D'),('E'),('F'); +alter table t1 add b char(8) not null; +alter table t1 add a char(8) not null; +alter table t1 add primary key (a,b,c); +update t1 set a=c, b=c; +create table t2 (c char(8) not null, b char(8) not null, a char(8) not null, primary key(a,b,c)) engine=innodb; +insert into t2 select * from t1; +delete t1,t2 from t2,t1 where t1.a<'B' and t2.b=t1.b; +drop table t1,t2; +SET AUTOCOMMIT=1; +create table t1 (a integer auto_increment primary key) engine=innodb; +insert into t1 (a) values (NULL),(NULL); +truncate table t1; +insert into t1 (a) values (NULL),(NULL); +SELECT * from t1; +a +3 +4 +drop table t1; CREATE TABLE t1 (col1 int(1))ENGINE=InnoDB; CREATE TABLE t2 (col1 int(1),stamp TIMESTAMP,INDEX stamp_idx (stamp))ENGINE=InnoDB; insert into t1 values (1),(2),(3); -insert into t2 values (1, 20020204130000),(2, 20020204130000),(4,20020204310000 ); +insert into t2 values (1, 20020204130000),(2, 20020204130000),(4,20020204310000 ),(5,20020204230000); +Warnings: +Warning 1264 Data truncated for column 'stamp' at row 3 SELECT col1 FROM t1 UNION SELECT col1 FROM t2 WHERE stamp < '20020204120000' GROUP BY col1; col1 1 2 3 +4 drop table t1,t2; CREATE TABLE t1 ( `id` int(10) unsigned NOT NULL auto_increment, diff --git a/mysql-test/r/insert.result b/mysql-test/r/insert.result index d6d99d7ce98..d9e57b48d39 100644 --- a/mysql-test/r/insert.result +++ b/mysql-test/r/insert.result @@ -73,7 +73,7 @@ drop table t1; create table t1 (email varchar(50)); insert into t1 values ('sasha@mysql.com'),('monty@mysql.com'),('foo@hotmail.com'),('foo@aol.com'),('bar@aol.com'); create table t2(id int not null auto_increment primary key, t2 varchar(50), unique(t2)); -insert into t2 (t2) select distinct substring(email, locate('@', email)+1) from t1; +insert delayed into t2 (t2) select distinct substring(email, locate('@', email)+1) from t1; select * from t2; id t2 1 mysql.com diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result index 76c1b06b638..c40f86827f8 100644 --- a/mysql-test/r/join_outer.result +++ b/mysql-test/r/join_outer.result @@ -665,3 +665,20 @@ left outer join t2 using (f2) left outer join t3 using (f3); ERROR 42S22: Unknown column 'test.t2.f3' in 'on clause' drop table t1,t2,t3; +create table t1 (a1 int, a2 int); +create table t2 (b1 int not null, b2 int); +create table t3 (c1 int, c2 int); +insert into t1 values (1,2), (2,2), (3,2); +insert into t2 values (1,3), (2,3); +insert into t3 values (2,4), (3,4); +select * from t1 left join t2 on b1 = a1 left join t3 on c1 = a1 and b1 is null; +a1 a2 b1 b2 c1 c2 +1 2 1 3 NULL NULL +2 2 2 3 NULL NULL +3 2 NULL NULL 3 4 +explain select * from t1 left join t2 on b1 = a1 left join t3 on c1 = a1 and b1 is null; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 +1 SIMPLE t2 ALL NULL NULL NULL NULL 2 +1 SIMPLE t3 ALL NULL NULL NULL NULL 2 +drop table t1, t2, t3; diff --git a/mysql-test/r/key_cache.result b/mysql-test/r/key_cache.result index 394099b363c..af3cf956222 100644 --- a/mysql-test/r/key_cache.result +++ b/mysql-test/r/key_cache.result @@ -40,8 +40,8 @@ SELECT @@medium.key_buffer_size; SET @@global.key_buffer_size=@save_key_buffer; SELECT @@default.key_buffer_size; ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'default.key_buffer_size' at line 1 -SELECT @@skr.table_type="test"; -ERROR HY000: Variable 'table_type' is not a variable component (Can't be used as XXXX.variable_name) +SELECT @@skr.storage_engine="test"; +ERROR HY000: Variable 'storage_engine' is not a variable component (Can't be used as XXXX.variable_name) select @@keycache1.key_cache_block_size; @@keycache1.key_cache_block_size 0 diff --git a/mysql-test/r/limit.result b/mysql-test/r/limit.result index 5a8edc99c12..c82105e6a49 100644 --- a/mysql-test/r/limit.result +++ b/mysql-test/r/limit.result @@ -36,9 +36,7 @@ a b 3 4 drop table t1; create table t1 (i int); -insert into t1 (i) values(1); -insert into t1 (i) values(1); -insert into t1 (i) values(1); +insert into t1 (i) values(1),(1),(1); delete from t1 limit 1; update t1 set i=2 limit 1; delete from t1 limit 0; @@ -50,3 +48,22 @@ i drop table t1; select 0 limit 0; 0 +CREATE TABLE t1(id int auto_increment primary key, id2 int, index(id2)); +INSERT INTO t1 (id2) values (0),(0),(0); +DELETE FROM t1 WHERE id=1; +INSERT INTO t1 SET id2=0; +SELECT * FROM t1; +id id2 +4 0 +2 0 +3 0 +DELETE FROM t1 WHERE id2 = 0 ORDER BY id LIMIT 1; +SELECT * FROM t1; +id id2 +4 0 +3 0 +DELETE FROM t1 WHERE id2 = 0 ORDER BY id desc LIMIT 1; +SELECT * FROM t1; +id id2 +3 0 +DROP TABLE t1; diff --git a/mysql-test/r/loaddata.result b/mysql-test/r/loaddata.result index d738431e016..0547596dfbd 100644 --- a/mysql-test/r/loaddata.result +++ b/mysql-test/r/loaddata.result @@ -31,7 +31,7 @@ drop table t1; create table t1 (a text, b text); load data infile '../../std_data/loaddata2.dat' into table t1 fields terminated by ',' enclosed by ''''; Warnings: -Warning 1260 Record count is fewer than the column count at row 3 +Warning 1260 Row 3 doesn't contain data for all columns select concat('|',a,'|'), concat('|',b,'|') from t1; concat('|',a,'|') concat('|',b,'|') |Field A| |Field B| @@ -40,3 +40,29 @@ Field 3,'Field 4| |Field 5' ,'Field 6| NULL |Field 6| | 'Field 7'| drop table t1; +create table t1 (a int, b char(10)); +load data infile '../../std_data/loaddata3.dat' into table t1 fields terminated by '' enclosed by '' ignore 1 lines; +Warnings: +Warning 1264 Data truncated for column 'a' at row 3 +Warning 1261 Row 3 was truncated; It contained more data than there where input columns +Warning 1264 Data truncated for column 'a' at row 5 +Warning 1261 Row 5 was truncated; It contained more data than there where input columns +select * from t1; +a b +1 row 1 +2 row 2 +0 1234567890 +3 row 3 +0 1234567890 +truncate table t1; +load data infile '../../std_data/loaddata4.dat' into table t1 fields terminated by '' enclosed by '' lines terminated by '' ignore 1 lines; +Warnings: +Warning 1264 Data truncated for column 'a' at row 4 +Warning 1260 Row 4 doesn't contain data for all columns +select * from t1; +a b +1 row 1 +2 row 2 +3 row 3 +0 +drop table t1; diff --git a/mysql-test/r/lowercase_table.result b/mysql-test/r/lowercase_table.result index 9c6b212a4b6..0ba4a4be945 100644 --- a/mysql-test/r/lowercase_table.result +++ b/mysql-test/r/lowercase_table.result @@ -1,6 +1,8 @@ -drop table if exists t1,t2,t3; +drop table if exists t1,t2,t3,t4,T1; create table T1 (id int primary key, Word varchar(40) not null, Index(Word)); +create table t4 (id int primary key, Word varchar(40) not null); INSERT INTO T1 VALUES (1, 'a'), (2, 'b'), (3, 'c'); +INSERT INTO T4 VALUES(1,'match'); SELECT * FROM t1; id Word 1 a @@ -12,6 +14,9 @@ id SELECT T2.id from t1 as T2 LIMIT 1; id 1 +SELECT * from t1 left join t4 on (test.t1.id= TEST.t4.id) where TEST.t1.id >= test.t4.id; +id Word id Word +1 a 1 match SELECT T2.id from t1 as t2 LIMIT 1; id 1 @@ -21,7 +26,8 @@ ALTER TABLE T2 RENAME T3; show tables like 't_'; Tables_in_test (t_) t3 -drop table t3; +t4 +drop table t3,t4; create table t1 (a int); select count(*) from T1; count(*) diff --git a/mysql-test/r/multi_update.result b/mysql-test/r/multi_update.result index 5cad3d097ad..5979a946b51 100644 --- a/mysql-test/r/multi_update.result +++ b/mysql-test/r/multi_update.result @@ -341,6 +341,38 @@ select t1.a, t1.b,t2.a, t2.b from t1 left join t2 on t1.a=t2.a where t1.b=1 and a b a b 2 2 NULL NULL drop table t1,t2; +create table t1 (a int not null auto_increment primary key, b int not null); +insert into t1 (b) values (1),(2),(3),(4); +update t1, t1 as t2 set t1.b=t2.b+1 where t1.a=t2.a; +select * from t1; +a b +1 2 +2 3 +3 4 +4 5 +drop table t1; +create table t1(id1 smallint(5), field char(5)); +create table t2(id2 smallint(5), field char(5)); +insert into t1 values (1, 'a'), (2, 'aa'); +insert into t2 values (1, 'b'), (2, 'bb'); +select * from t1; +id1 field +1 a +2 aa +select * from t2; +id2 field +1 b +2 bb +update t2 inner join t1 on t1.id1=t2.id2 +set t2.field=t1.field +where 0=1; +update t2, t1 set t2.field=t1.field +where t1.id1=t2.id2 and 0=1; +delete t1, t2 from t2 inner join t1 on t1.id1=t2.id2 +where 0=1; +delete t1, t2 from t2,t1 +where t1.id1=t2.id2 and 0=1; +drop table t1,t2; create table t1 ( a int not null, b int not null) ; alter table t1 add index i1(a); delete from t1 where a > 2000000; @@ -364,8 +396,8 @@ select 't1 rows after big delete', count(*) from t1; t1 rows after big delete count(*) t1 rows after big delete 1900001 drop table t1,t2; -set @ttype_save=@@table_type; -set @@table_type=innodb; +set @ttype_save=@@storage_engine; +set @@storage_engine=innodb; create table t1 ( c char(8) not null ); insert into t1 values ('0'),('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9'); insert into t1 values ('A'),('B'),('C'),('D'),('E'),('F'); @@ -377,7 +409,7 @@ create table t2 like t1; 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 @@table_type=bdb; +set @@storage_engine=bdb; create table t1 ( c char(8) not null ); insert into t1 values ('0'),('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9'); insert into t1 values ('A'),('B'),('C'),('D'),('E'),('F'); @@ -388,5 +420,5 @@ update t1 set a=c, b=c; create table t2 like t1; insert into t2 select * from t1; delete t1,t2 from t2,t1 where t1.a<'B' and t2.b=t1.b; -set @@table_type=@ttype_save; +set @@storage_engine=@ttype_save; drop table t1,t2; diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index ce000ba5627..04effdfef7c 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -18,6 +18,47 @@ INSERT INTO t1 VALUES (1), (2); </database> </mysqldump> DROP TABLE t1; +CREATE TABLE t1 (a decimal(240, 20)); +INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"), +("0987654321098765432109876543210987654321"); +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 ( + a decimal(240,20) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + + +/*!40000 ALTER TABLE t1 DISABLE KEYS */; +LOCK TABLES t1 WRITE; +INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890.00000000000000000000"),("0987654321098765432109876543210987654321.00000000000000000000"); +UNLOCK TABLES; +/*!40000 ALTER TABLE t1 ENABLE KEYS */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; + +DROP TABLE t1; +CREATE TABLE t1 (a double); +INSERT INTO t1 VALUES (-9e999999); +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 ( + a double default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + + +/*!40000 ALTER TABLE t1 DISABLE KEYS */; +LOCK TABLES t1 WRITE; +INSERT INTO t1 VALUES (RES); +UNLOCK TABLES; +/*!40000 ALTER TABLE t1 ENABLE KEYS */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; + +DROP TABLE t1; CREATE TABLE t1(a int, b text, c varchar(3)); INSERT INTO t1 VALUES (1, "test", "tes"), (2, "TEST", "TES"); <?xml version="1.0"?> @@ -64,30 +105,11 @@ INSERT INTO t1 VALUES ("1\""), ("\"2"); DROP TABLE t1; CREATE TABLE t1 (a VARCHAR(255)) DEFAULT CHARSET koi8r; INSERT INTO t1 VALUES (_koi8r x'C1C2C3C4C5'); --- MySQL dump 10.3 --- --- Host: localhost Database: test --- ------------------------------------------------------ --- Server version 5.0.0-alpha-debug-log - -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT, CHARACTER_SET_CLIENT=utf8 */; -/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; -/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; -/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE=NO_AUTO_VALUE_ON_ZERO */; - --- --- Table structure for table `t1` --- - DROP TABLE IF EXISTS t1; CREATE TABLE t1 ( a varchar(255) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=koi8r; --- --- Dumping data for table `t1` --- - /*!40000 ALTER TABLE t1 DISABLE KEYS */; LOCK TABLES t1 WRITE; diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index 70b6740fc07..60a6fac6458 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -370,16 +370,23 @@ insert into mysqltest.t1 (a) values (1); select * from mysqltest.t1 where i is null; i a 1 1 +create table t1(a int); +select * from t1; +a +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 select * from mysqltest.t1; i a 1 1 show status like "Qcache_queries_in_cache"; Variable_name Value -Qcache_queries_in_cache 1 +Qcache_queries_in_cache 2 drop database mysqltest; show status like "Qcache_queries_in_cache"; Variable_name Value -Qcache_queries_in_cache 0 +Qcache_queries_in_cache 1 +drop table t1; create table t1 (a char(1) not null collate koi8r_general_ci); insert into t1 values(_koi8r"á"); set CHARACTER SET koi8r; diff --git a/mysql-test/r/rpl_EE_error.result b/mysql-test/r/rpl_EE_error.result new file mode 100644 index 00000000000..49ad4832c81 --- /dev/null +++ b/mysql-test/r/rpl_EE_error.result @@ -0,0 +1,16 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +create table t1 (a int) engine=myisam; +flush tables; +drop table t1; +create table t1 (a int, unique(a)) engine=myisam; +set sql_log_bin=0; +insert into t1 values(2); +set sql_log_bin=1; +insert into t1 values(1),(2); +ERROR 23000: Duplicate entry '2' for key 1 +drop table t1; diff --git a/mysql-test/r/rpl_multi_update.result b/mysql-test/r/rpl_multi_update.result new file mode 100644 index 00000000000..65587d25f63 --- /dev/null +++ b/mysql-test/r/rpl_multi_update.result @@ -0,0 +1,26 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +CREATE TABLE t1 ( +a int unsigned not null auto_increment primary key, +b int unsigned, +) ENGINE=MyISAM; +CREATE TABLE t2 ( +a int unsigned not null auto_increment primary key, +b int unsigned +) ENGINE=MyISAM; +INSERT INTO t1 VALUES (NULL, 0); +INSERT INTO t1 SELECT NULL, 0 FROM t1; +INSERT INTO t2 VALUES (NULL, 0), (NULL,1); +SELECT * FROM t1 ORDER BY a; +a b +1 0 +2 0 +SELECT * FROM t2 ORDER BY a; +a b +1 0 +2 1 +UPDATE t1, t2 SET t1.b = t2.b WHERE t1.a = t2.a; diff --git a/mysql-test/r/rpl_rotate_logs.result b/mysql-test/r/rpl_rotate_logs.result index 87ebf870f38..20755d265aa 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; start slave; -ERROR HY000: Could not initialize master info structure, check permisions on master.info +ERROR HY000: Could not initialize master info structure, more error messages can be found in the MySQL error log start slave; -ERROR HY000: Could not initialize master info structure, check permisions on master.info +ERROR HY000: 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'; -ERROR HY000: Could not initialize master info structure, check permisions on master.info +ERROR HY000: 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; @@ -68,6 +68,9 @@ m create temporary table temp_table (a char(80) not null); insert into temp_table values ("testing temporary tables part 2"); create table t3 (n int); +select count(*) from t3 where n >= 4; +count(*) +100 create table t4 select * from temp_table; show binary logs; Log_name diff --git a/mysql-test/r/select_found.result b/mysql-test/r/select_found.result index 42f7257dbba..e302a0cefeb 100644 --- a/mysql-test/r/select_found.result +++ b/mysql-test/r/select_found.result @@ -189,3 +189,22 @@ SELECT FOUND_ROWS(); FOUND_ROWS() 3 drop table t1; +create table t1 (id int, primary key (id)); +insert into t1 values (1), (2), (3), (4), (5); +select SQL_CALC_FOUND_ROWS * from t1 where id > 3 limit 0, 1; +id +4 +select FOUND_ROWS(); +FOUND_ROWS() +2 +select SQL_CALC_FOUND_ROWS * from t1 where id > 3 AND 1=2 limit 0, 1; +id +select FOUND_ROWS(); +FOUND_ROWS() +0 +select SQL_CALC_FOUND_ROWS * from t1 where id > 6 limit 0, 1; +id +select FOUND_ROWS(); +FOUND_ROWS() +0 +drop table t1; diff --git a/mysql-test/r/sum_distinct.result b/mysql-test/r/sum_distinct.result new file mode 100644 index 00000000000..c7f1a660267 --- /dev/null +++ b/mysql-test/r/sum_distinct.result @@ -0,0 +1,203 @@ +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 ( +id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT, +gender CHAR(1), +name VARCHAR(20) +); +SELECT SUM(DISTINCT LENGTH(name)) s1 FROM t1; +s1 +NULL +INSERT INTO t1 (gender, name) VALUES (NULL, NULL); +INSERT INTO t1 (gender, name) VALUES (NULL, NULL); +INSERT INTO t1 (gender, name) VALUES (NULL, NULL); +SELECT SUM(DISTINCT LENGTH(name)) s1 FROM t1; +s1 +NULL +INSERT INTO t1 (gender, name) VALUES ('F', 'Helen'), ('F', 'Anastasia'), +('F', 'Katherine'), ('F', 'Margo'), ('F', 'Magdalene'), ('F', 'Mary'); +CREATE TABLE t2 SELECT name FROM t1; +SELECT (SELECT SUM(DISTINCT LENGTH(name)) FROM t1) FROM t2; +(SELECT SUM(DISTINCT LENGTH(name)) FROM t1) +18 +18 +18 +18 +18 +18 +18 +18 +18 +DROP TABLE t2; +INSERT INTO t1 (gender, name) VALUES ('F', 'Eva'), ('F', 'Sofia'), +('F', 'Sara'), ('F', 'Golda'), ('F', 'Toba'), ('F', 'Victory'), +('F', 'Faina'), ('F', 'Miriam'), ('F', 'Beki'), ('F', 'America'), +('F', 'Susan'), ('F', 'Glory'), ('F', 'Priscilla'), ('F', 'Rosmary'), +('F', 'Rose'), ('F', 'Margareth'), ('F', 'Elizabeth'), ('F', 'Meredith'), +('F', 'Julie'), ('F', 'Xenia'), ('F', 'Zena'), ('F', 'Olga'), +('F', 'Brunhilda'), ('F', 'Nataly'), ('F', 'Lara'), ('F', 'Svetlana'), +('F', 'Grethem'), ('F', 'Irene'); +SELECT +SUM(DISTINCT LENGTH(name)) s1, +SUM(DISTINCT SUBSTRING(NAME, 1, 3)) s2, +SUM(DISTINCT LENGTH(SUBSTRING(name, 1, 4))) s3 +FROM t1; +s1 s2 s3 +42 0 7 +SELECT +SUM(DISTINCT LENGTH(g1.name)) s1, +SUM(DISTINCT SUBSTRING(g2.name, 1, 3)) s2, +SUM(DISTINCT LENGTH(SUBSTRING(g3.name, 1, 4))) s3 +FROM t1 g1, t1 g2, t1 g3; +s1 s2 s3 +42 0 7 +SELECT +SUM(DISTINCT LENGTH(g1.name)) s1, +SUM(DISTINCT SUBSTRING(g2.name, 1, 3)) s2, +SUM(DISTINCT LENGTH(SUBSTRING(g3.name, 1, 4))) s3 +FROM t1 g1, t1 g2, t1 g3 GROUP BY LENGTH(SUBSTRING(g3.name, 5, 10)); +s1 s2 s3 +42 0 NULL +42 0 7 +42 0 4 +42 0 4 +42 0 4 +42 0 4 +42 0 4 +SELECT SQL_BUFFER_RESULT +SUM(DISTINCT LENGTH(name)) s1, +SUM(DISTINCT SUBSTRING(NAME, 1, 3)) s2, +SUM(DISTINCT LENGTH(SUBSTRING(name, 1, 4))) s3 +FROM t1; +s1 s2 s3 +42 0 7 +SELECT SQL_BUFFER_RESULT +SUM(DISTINCT LENGTH(g1.name)) s1, +SUM(DISTINCT SUBSTRING(g2.name, 1, 3)) s2, +SUM(DISTINCT LENGTH(SUBSTRING(g3.name, 1, 4))) s3 +FROM t1 g1, t1 g2, t1 g3 GROUP BY LENGTH(SUBSTRING(g3.name, 5, 10)); +s1 s2 s3 +42 0 NULL +42 0 7 +42 0 4 +42 0 4 +42 0 4 +42 0 4 +42 0 4 +SET @l=1; +UPDATE t1 SET name=CONCAT(name, @l:=@l+1); +SELECT SUM(DISTINCT RIGHT(name, 1)) FROM t1; +SUM(DISTINCT RIGHT(name, 1)) +45 +SELECT SUM(DISTINCT id) FROM t1; +SUM(DISTINCT id) +703 +SELECT SUM(DISTINCT id % 11) FROM t1; +SUM(DISTINCT id % 11) +55 +DROP TABLE t1; +CREATE TABLE t1 (id INTEGER); +CREATE TABLE t2 (id INTEGER); +INSERT INTO t1 (id) VALUES (1), (1), (1),(1); +INSERT INTO t2 (id) SELECT id FROM t1; +INSERT INTO t1 (id) SELECT id FROM t2; +/* 8 */ +INSERT INTO t1 (id) SELECT id FROM t2; +/* 12 */ +INSERT INTO t1 (id) SELECT id FROM t2; +/* 16 */ +INSERT INTO t1 (id) SELECT id FROM t2; +/* 20 */ +INSERT INTO t1 (id) SELECT id FROM t2; +/* 24 */ +DELETE FROM t2; +INSERT INTO t2 (id) SELECT id+1 FROM t1; +INSERT INTO t1 SELECT id FROM t2; +DELETE FROM t2; +INSERT INTO t2 (id) SELECT id+2 FROM t1; +INSERT INTO t1 SELECT id FROM t2; +DELETE FROM t2; +INSERT INTO t2 (id) SELECT id+4 FROM t1; +INSERT INTO t1 SELECT id FROM t2; +DELETE FROM t2; +INSERT INTO t2 (id) SELECT id+8 FROM t1; +INSERT INTO t1 SELECT id FROM t2; +DELETE FROM t2; +INSERT INTO t2 (id) SELECT id+16 FROM t1; +INSERT INTO t1 SELECT id FROM t2; +DELETE FROM t2; +INSERT INTO t2 (id) SELECT id+32 FROM t1; +INSERT INTO t1 SELECT id FROM t2; +DELETE FROM t2; +INSERT INTO t2 (id) SELECT id+64 FROM t1; +INSERT INTO t1 SELECT id FROM t2; +DELETE FROM t2; +INSERT INTO t2 (id) SELECT id+128 FROM t1; +INSERT INTO t1 SELECT id FROM t2; +DELETE FROM t2; +INSERT INTO t2 (id) SELECT id+256 FROM t1; +INSERT INTO t1 SELECT id FROM t2; +DELETE FROM t2; +INSERT INTO t2 (id) SELECT id+512 FROM t1; +INSERT INTO t1 SELECT id FROM t2; +DELETE FROM t2; +INSERT INTO t2 (id) SELECT id+1024 FROM t1; +INSERT INTO t1 SELECT id FROM t2; +DELETE FROM t2; +INSERT INTO t2 (id) SELECT id+2048 FROM t1; +INSERT INTO t1 SELECT id FROM t2; +DELETE FROM t2; +INSERT INTO t2 (id) SELECT id+4096 FROM t1; +INSERT INTO t1 SELECT id FROM t2; +DELETE FROM t2; +INSERT INTO t2 (id) SELECT id+8192 FROM t1; +INSERT INTO t1 SELECT id FROM t2; +DELETE FROM t2; +INSERT INTO t2 SELECT id FROM t1 ORDER BY id*rand(); +SELECT SUM(DISTINCT id) sm FROM t1; +sm +134225920 +SELECT SUM(DISTINCT id) sm FROM t2; +sm +134225920 +SELECT SUM(DISTINCT id) sm FROM t1 group by id % 13; +sm +10327590 +10328851 +10330112 +10331373 +10332634 +10317510 +10318770 +10320030 +10321290 +10322550 +10323810 +10325070 +10326330 +SET max_heap_table_size=16384; +SHOW variables LIKE 'max_heap_table_size'; +Variable_name Value +max_heap_table_size 16384 +SELECT SUM(DISTINCT id) sm FROM t1; +sm +134225920 +SELECT SUM(DISTINCT id) sm FROM t2; +sm +134225920 +SELECT SUM(DISTINCT id) sm FROM t1 GROUP BY id % 13; +sm +10327590 +10328851 +10330112 +10331373 +10332634 +10317510 +10318770 +10320030 +10321290 +10322550 +10323810 +10325070 +10326330 +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/r/symlink.result b/mysql-test/r/symlink.result index 48a44fc2b44..4ba0ca0eac4 100644 --- a/mysql-test/r/symlink.result +++ b/mysql-test/r/symlink.result @@ -64,3 +64,25 @@ t9 CREATE TABLE `t9` ( PRIMARY KEY (`a`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DATA DIRECTORY='TEST_DIR/var/tmp/' INDEX DIRECTORY='TEST_DIR/var/run/' drop database mysqltest; +create table t1 (a int not null) type=myisam; +Warnings: +Warning 1286 'TYPE=database_engine' is deprecated. Use 'ENGINE=database_engine' instead. +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) NOT NULL default '0' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +alter table t1 add b int; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) NOT NULL default '0', + `b` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) NOT NULL default '0', + `b` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; diff --git a/mysql-test/r/timezone.result b/mysql-test/r/timezone.result index b82b39da262..20706408075 100644 --- a/mysql-test/r/timezone.result +++ b/mysql-test/r/timezone.result @@ -1,4 +1,13 @@ DROP TABLE IF EXISTS t1; +show variables like "timezone"; +Variable_name Value +timezone MET +select @a:=FROM_UNIXTIME(1); +@a:=FROM_UNIXTIME(1) +1970-01-01 01:00:01 +select unix_timestamp(@a); +unix_timestamp(@a) +1 CREATE TABLE t1 (ts int); INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 01:00')); INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 02:00')); diff --git a/mysql-test/r/truncate.result b/mysql-test/r/truncate.result index 0e256c1bf8e..d777bd184b2 100644 --- a/mysql-test/r/truncate.result +++ b/mysql-test/r/truncate.result @@ -23,3 +23,12 @@ n drop table t1; truncate non_existing_table; ERROR 42S02: Table 'test.non_existing_table' doesn't exist +create table t1 (a integer auto_increment primary key); +insert into t1 (a) values (NULL),(NULL); +truncate table t1; +insert into t1 (a) values (NULL),(NULL); +SELECT * from t1; +a +1 +2 +drop table t1; diff --git a/mysql-test/r/type_blob.result b/mysql-test/r/type_blob.result index a69e3308f0a..255b7f0d942 100644 --- a/mysql-test/r/type_blob.result +++ b/mysql-test/r/type_blob.result @@ -510,3 +510,149 @@ show full fields from t1; Field Type Collation Null Key Default Extra Privileges Comment load_file('../../std_data/words.dat') longblob NULL YES NULL select,insert,update,references drop table t1; +create table t1 (id integer primary key auto_increment, txt text not null, unique index txt_index (txt (20))); +insert into t1 (txt) values ('Chevy'), ('Chevy '); +select * from t1 where txt='Chevy'; +id txt +1 Chevy +2 Chevy +select * from t1 where txt='Chevy '; +id txt +1 Chevy +2 Chevy +select * from t1 where txt='Chevy ' or txt='Chevy'; +id txt +1 Chevy +2 Chevy +select * from t1 where txt='Chevy' or txt='Chevy '; +id txt +1 Chevy +2 Chevy +select * from t1 where id='1' or id='2'; +id txt +1 Chevy +2 Chevy +insert into t1 (txt) values('Ford'); +select * from t1 where txt='Chevy' or txt='Chevy ' or txt='Ford'; +id txt +1 Chevy +2 Chevy +3 Ford +select * from t1 where txt='Chevy' or txt='Chevy '; +id txt +1 Chevy +2 Chevy +select * from t1 where txt='Chevy' or txt='Chevy ' or txt=' Chevy'; +id txt +1 Chevy +2 Chevy +select * from t1 where txt in ('Chevy ','Chevy'); +id txt +1 Chevy +2 Chevy +select * from t1 where txt in ('Chevy'); +id txt +1 Chevy +2 Chevy +select * from t1 where txt between 'Chevy' and 'Chevy'; +id txt +1 Chevy +2 Chevy +select * from t1 where txt between 'Chevy' and 'Chevy' or txt='Chevy '; +id txt +1 Chevy +2 Chevy +select * from t1 where txt between 'Chevy' and 'Chevy '; +id txt +1 Chevy +2 Chevy +select * from t1 where txt < 'Chevy '; +id txt +select * from t1 where txt <= 'Chevy'; +id txt +1 Chevy +2 Chevy +select * from t1 where txt > 'Chevy'; +id txt +3 Ford +select * from t1 where txt >= 'Chevy'; +id txt +1 Chevy +2 Chevy +3 Ford +drop table t1; +create table t1 (id integer primary key auto_increment, txt text, unique index txt_index (txt (20))); +insert into t1 (txt) values ('Chevy'), ('Chevy '), (NULL); +select * from t1 where txt='Chevy' or txt is NULL; +id txt +1 Chevy +2 Chevy +3 NULL +select * from t1 where txt='Chevy '; +id txt +1 Chevy +2 Chevy +select * from t1 where txt='Chevy ' or txt='Chevy'; +id txt +1 Chevy +2 Chevy +select * from t1 where txt='Chevy' or txt='Chevy '; +id txt +1 Chevy +2 Chevy +select * from t1 where id='1' or id='2'; +id txt +1 Chevy +2 Chevy +insert into t1 (txt) values('Ford'); +select * from t1 where txt='Chevy' or txt='Chevy ' or txt='Ford'; +id txt +1 Chevy +2 Chevy +4 Ford +select * from t1 where txt='Chevy' or txt='Chevy '; +id txt +1 Chevy +2 Chevy +select * from t1 where txt='Chevy' or txt='Chevy ' or txt=' Chevy'; +id txt +1 Chevy +2 Chevy +select * from t1 where txt in ('Chevy ','Chevy'); +id txt +1 Chevy +2 Chevy +select * from t1 where txt in ('Chevy'); +id txt +1 Chevy +2 Chevy +select * from t1 where txt between 'Chevy' and 'Chevy'; +id txt +1 Chevy +2 Chevy +select * from t1 where txt between 'Chevy' and 'Chevy' or txt='Chevy '; +id txt +1 Chevy +2 Chevy +select * from t1 where txt between 'Chevy' and 'Chevy '; +id txt +1 Chevy +2 Chevy +select * from t1 where txt < 'Chevy '; +id txt +select * from t1 where txt < 'Chevy ' or txt is NULL; +id txt +3 NULL +select * from t1 where txt <= 'Chevy'; +id txt +1 Chevy +2 Chevy +select * from t1 where txt > 'Chevy'; +id txt +4 Ford +select * from t1 where txt >= 'Chevy'; +id txt +1 Chevy +2 Chevy +4 Ford +drop table t1; diff --git a/mysql-test/r/type_datetime.result b/mysql-test/r/type_datetime.result index 204266d6ec2..c1ee621697d 100644 --- a/mysql-test/r/type_datetime.result +++ b/mysql-test/r/type_datetime.result @@ -1,6 +1,12 @@ drop table if exists t1; create table t1 (t datetime); -insert into t1 values(101),(691231),(700101),(991231),(10000101),(99991231),(101000000),(691231000000),(700101000000),(991231235959),(10000101000000),(99991231235959); +insert into t1 values(101),(691231),(700101),(991231),(10000101),(99991231),(101000000),(691231000000),(700101000000),(991231235959),(10000101000000),(99991231235959),(20030102030460),(20030102036301),(20030102240401),(20030132030401),(20031302030460); +Warnings: +Warning 1264 Data truncated for column 't' at row 13 +Warning 1264 Data truncated for column 't' at row 14 +Warning 1264 Data truncated for column 't' at row 15 +Warning 1264 Data truncated for column 't' at row 16 +Warning 1264 Data truncated for column 't' at row 17 select * from t1; t 2000-01-01 00:00:00 @@ -15,6 +21,11 @@ t 1999-12-31 23:59:59 1000-01-01 00:00:00 9999-12-31 23:59:59 +0000-00-00 00:00:00 +0000-00-00 00:00:00 +0000-00-00 00:00:00 +0000-00-00 00:00:00 +0000-00-00 00:00:00 delete from t1 where t > 0; optimize table t1; Table Op Msg_type Msg_text @@ -22,7 +33,8 @@ test.t1 optimize status OK check table t1; Table Op Msg_type Msg_text test.t1 check status OK -insert into t1 values("000101"),("691231"),("700101"),("991231"),("00000101"),("00010101"),("99991231"),("00101000000"),("691231000000"),("700101000000"),("991231235959"),("10000101000000"),("99991231235959"); +delete from t1; +insert into t1 values("000101"),("691231"),("700101"),("991231"),("00000101"),("00010101"),("99991231"),("00101000000"),("691231000000"),("700101000000"),("991231235959"),("10000101000000"),("99991231235959"),("20030102030460"),("20030102036301"),("20030102240401"),("20030132030401"),("20031302030460"); select * from t1; t 2000-01-01 00:00:00 @@ -38,6 +50,11 @@ t 1999-12-31 23:59:59 1000-01-01 00:00:00 9999-12-31 23:59:59 +0000-00-00 00:00:00 +0000-00-00 00:00:00 +0000-00-00 00:00:00 +0000-00-00 00:00:00 +0000-00-00 00:00:00 drop table t1; CREATE TABLE t1 (a timestamp, b date, c time, d datetime); insert into t1 (b,c,d) values(now(),curtime(),now()); diff --git a/mysql-test/r/type_decimal.result b/mysql-test/r/type_decimal.result index da25394eb08..97d81d77722 100644 --- a/mysql-test/r/type_decimal.result +++ b/mysql-test/r/type_decimal.result @@ -444,3 +444,321 @@ CREATE TABLE t1 (a_dec DECIMAL(-2,1)); ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '-2,1))' at line 1 CREATE TABLE t1 (a_dec DECIMAL(-1,1)); ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '-1,1))' at line 1 +create table t1(a decimal(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'); +Warnings: +Warning 1263 Data truncated, out of range for column 'a' at row 27 +Warning 1263 Data truncated, out of range for column 'a' at row 30 +Warning 1263 Data truncated, out of range for column 'a' at row 31 +Warning 1263 Data truncated, out of range for column 'a' at row 32 +Warning 1263 Data truncated, out of range for column 'a' at row 33 +Warning 1263 Data truncated, out of range for column 'a' at row 34 +Warning 1263 Data truncated, out of range for column 'a' at row 35 +Warning 1263 Data truncated, out of range for column 'a' at row 36 +Warning 1263 Data truncated, out of range for column 'a' at row 37 +Warning 1263 Data truncated, out of range for column 'a' at row 38 +Warning 1263 Data truncated, out of range for column 'a' at row 39 +Warning 1263 Data truncated, out of range for column 'a' at row 40 +Warning 1263 Data truncated, out of range for column 'a' at row 41 +Warning 1263 Data truncated, out of range for column 'a' at row 42 +Warning 1263 Data truncated, out of range for column 'a' at row 43 +Warning 1263 Data truncated, out of range for column 'a' at row 44 +Warning 1263 Data truncated, out of range for column 'a' at row 45 +Warning 1263 Data truncated, out of range for column 'a' at row 46 +Warning 1263 Data truncated, out of range for column 'a' at row 47 +Warning 1263 Data truncated, out of range for column 'a' at row 48 +Warning 1263 Data truncated, out of range for column 'a' at row 49 +Warning 1263 Data truncated, out of range for column 'a' at row 50 +Warning 1263 Data truncated, out of range for column 'a' at row 51 +Warning 1263 Data truncated, out of range for column 'a' at row 52 +Warning 1263 Data truncated, out of range for column 'a' at row 53 +Warning 1263 Data truncated, out of range for column 'a' at row 54 +Warning 1263 Data truncated, out of range for column 'a' at row 55 +Warning 1263 Data truncated, out of range for column 'a' at row 56 +Warning 1263 Data truncated, out of range for column 'a' at row 57 +Warning 1263 Data truncated, out of range for column 'a' at row 58 +Warning 1263 Data truncated, out of range for column 'a' at row 59 +Warning 1263 Data truncated, out of range for column 'a' at row 60 +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'); +Warnings: +Warning 1263 Data truncated, out of range for column 'a' at row 3 +Warning 1263 Data truncated, out of range for column 'a' at row 6 +Warning 1263 Data truncated, out of range for column 'a' at row 9 +Warning 1263 Data truncated, out of range for column 'a' at row 12 +Warning 1263 Data truncated, out of range for column 'a' at row 15 +Warning 1263 Data truncated, out of range for column 'a' at row 18 +Warning 1263 Data truncated, out of range for column 'a' at row 21 +Warning 1263 Data truncated, out of range for column 'a' at row 24 +Warning 1263 Data truncated, out of range for column 'a' at row 25 +Warning 1263 Data truncated, out of range for column 'a' at row 26 +Warning 1263 Data truncated, out of range for column 'a' at row 27 +Warning 1263 Data truncated, out of range for column 'a' at row 28 +Warning 1263 Data truncated, out of range for column 'a' at row 29 +Warning 1263 Data truncated, out of range for column 'a' at row 30 +Warning 1263 Data truncated, out of range for column 'a' at row 31 +Warning 1263 Data truncated, out of range for column 'a' at row 32 +Warning 1263 Data truncated, out of range for column 'a' at row 33 +Warning 1263 Data truncated, out of range for column 'a' at row 34 +Warning 1263 Data truncated, out of range for column 'a' at row 35 +Warning 1263 Data truncated, out of range for column 'a' at row 36 +Warning 1263 Data truncated, out of range for column 'a' at row 37 +Warning 1263 Data truncated, out of range for column 'a' at row 38 +Warning 1263 Data truncated, out of range for column 'a' at row 39 +Warning 1263 Data truncated, out of range for column 'a' at row 40 +Warning 1263 Data truncated, out of range for column 'a' at row 41 +Warning 1263 Data truncated, out of range for column 'a' at row 42 +Warning 1263 Data truncated, out of range for column 'a' at row 43 +Warning 1263 Data truncated, out of range for column 'a' at row 44 +Warning 1263 Data truncated, out of range for column 'a' at row 45 +Warning 1263 Data truncated, out of range for column 'a' at row 46 +Warning 1263 Data truncated, out of range for column 'a' at row 47 +Warning 1263 Data truncated, out of range for column 'a' at row 48 +Warning 1263 Data truncated, out of range for column 'a' at row 49 +Warning 1263 Data truncated, out of range for column 'a' at row 50 +Warning 1263 Data truncated, out of range for column 'a' at row 51 +Warning 1263 Data truncated, out of range for column 'a' at row 52 +Warning 1263 Data truncated, out of range for column 'a' at row 53 +Warning 1263 Data truncated, out of range for column 'a' at row 54 +Warning 1263 Data truncated, out of range for column 'a' at row 55 +Warning 1263 Data truncated, out of range for column 'a' at row 56 +Warning 1263 Data truncated, out of range for column 'a' at row 57 +Warning 1263 Data truncated, out of range for column 'a' at row 58 +Warning 1263 Data truncated, out of range for column 'a' at row 59 +Warning 1263 Data truncated, out of range for column 'a' at row 60 +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'); +Warnings: +Warning 1263 Data truncated, out of range for column 'a' at row 3 +Warning 1263 Data truncated, out of range for column 'a' at row 6 +Warning 1263 Data truncated, out of range for column 'a' at row 9 +Warning 1263 Data truncated, out of range for column 'a' at row 12 +Warning 1263 Data truncated, out of range for column 'a' at row 15 +Warning 1263 Data truncated, out of range for column 'a' at row 18 +Warning 1263 Data truncated, out of range for column 'a' at row 21 +Warning 1263 Data truncated, out of range for column 'a' at row 24 +Warning 1263 Data truncated, out of range for column 'a' at row 25 +Warning 1263 Data truncated, out of range for column 'a' at row 26 +Warning 1263 Data truncated, out of range for column 'a' at row 27 +Warning 1263 Data truncated, out of range for column 'a' at row 28 +Warning 1263 Data truncated, out of range for column 'a' at row 29 +Warning 1263 Data truncated, out of range for column 'a' at row 30 +Warning 1263 Data truncated, out of range for column 'a' at row 31 +Warning 1263 Data truncated, out of range for column 'a' at row 32 +Warning 1263 Data truncated, out of range for column 'a' at row 33 +Warning 1263 Data truncated, out of range for column 'a' at row 34 +Warning 1263 Data truncated, out of range for column 'a' at row 35 +Warning 1263 Data truncated, out of range for column 'a' at row 36 +Warning 1263 Data truncated, out of range for column 'a' at row 37 +Warning 1263 Data truncated, out of range for column 'a' at row 38 +Warning 1263 Data truncated, out of range for column 'a' at row 39 +Warning 1263 Data truncated, out of range for column 'a' at row 40 +Warning 1263 Data truncated, out of range for column 'a' at row 41 +Warning 1263 Data truncated, out of range for column 'a' at row 42 +Warning 1263 Data truncated, out of range for column 'a' at row 43 +Warning 1263 Data truncated, out of range for column 'a' at row 44 +Warning 1263 Data truncated, out of range for column 'a' at row 45 +Warning 1263 Data truncated, out of range for column 'a' at row 46 +Warning 1263 Data truncated, out of range for column 'a' at row 47 +Warning 1263 Data truncated, out of range for column 'a' at row 48 +Warning 1263 Data truncated, out of range for column 'a' at row 49 +Warning 1263 Data truncated, out of range for column 'a' at row 50 +Warning 1263 Data truncated, out of range for column 'a' at row 51 +Warning 1263 Data truncated, out of range for column 'a' at row 52 +Warning 1263 Data truncated, out of range for column 'a' at row 53 +Warning 1263 Data truncated, out of range for column 'a' at row 54 +Warning 1263 Data truncated, out of range for column 'a' at row 55 +Warning 1263 Data truncated, out of range for column 'a' at row 56 +Warning 1263 Data truncated, out of range for column 'a' at row 57 +Warning 1263 Data truncated, out of range for column 'a' at row 58 +Warning 1263 Data truncated, out of range for column 'a' at row 59 +Warning 1263 Data truncated, out of range for column 'a' at row 60 +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 2ab6695e5c6..fe8f78453b7 100644 --- a/mysql-test/r/type_enum.result +++ b/mysql-test/r/type_enum.result @@ -1636,6 +1636,20 @@ t1 CREATE TABLE `t1` ( `a` enum('','a','b') NOT NULL default 'b' ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; +create table t1 (a enum ('0','1')); +insert into t1 set a='foobar'; +Warnings: +Warning 1264 Data truncated for column 'a' at row 1 +select * from t1; +a + +update t1 set a = replace(a,'x','y'); +Warnings: +Warning 1264 Data truncated for column 'a' at row 1 +select * from t1; +a + +drop table t1; set names latin1; create table t1 (a enum(0xE4, '1', '2') not null default 0xE4); show columns from t1; diff --git a/mysql-test/r/type_timestamp.result b/mysql-test/r/type_timestamp.result index 0c75155146d..172ccc440f4 100644 --- a/mysql-test/r/type_timestamp.result +++ b/mysql-test/r/type_timestamp.result @@ -43,7 +43,13 @@ date_format(a,"%Y %y") year(a) year(now()) 1970 70 1970 1970 drop table t1; create table t1 (ix timestamp); -insert into t1 values (19991101000000),(19990102030405),(19990630232922),(19990601000000),(19990930232922),(19990531232922),(19990501000000),(19991101000000),(19990501000000); +insert into t1 values (19991101000000),(19990102030405),(19990630232922),(19990601000000),(19990930232922),(19990531232922),(19990501000000),(19991101000000),(19990501000000),(20030101010160),(20030101016001),(20030101240101),(20030132010101),(20031301010101); +Warnings: +Warning 1264 Data truncated for column 'ix' at row 10 +Warning 1264 Data truncated for column 'ix' at row 11 +Warning 1264 Data truncated for column 'ix' at row 12 +Warning 1264 Data truncated for column 'ix' at row 13 +Warning 1264 Data truncated for column 'ix' at row 14 select ix+0 from t1; ix+0 19991101000000 @@ -55,6 +61,24 @@ ix+0 19990501000000 19991101000000 19990501000000 +0 +0 +0 +0 +0 +delete from t1; +insert into t1 values ("19991101000000"),("19990102030405"),("19990630232922"),("19990601000000"),("20030101010160"),("20030101016001"),("20030101240101"),("20030132010101"),("20031301010101"); +select ix+0 from t1; +ix+0 +19991101000000 +19990102030405 +19990630232922 +19990601000000 +0 +0 +0 +0 +0 drop table t1; CREATE TABLE t1 (date date, date_time datetime, time_stamp timestamp); INSERT INTO t1 VALUES ("1998-12-31","1998-12-31 23:59:59",19981231235959); @@ -104,3 +128,5 @@ t2 t4 t6 t8 t10 t12 t14 0000-00-00 00:00:00 0000-00-00 00:00:00 0000-00-00 00:00:00 0000-00-00 00:00:00 0000-00-00 00:00:00 0000-00-00 00:00:00 0000-00-00 00:00:00 1997-12-31 23:47:59 1997-12-31 23:47:59 1997-12-31 23:47:59 1997-12-31 23:47:59 1997-12-31 23:47:59 1997-12-31 23:47:59 1997-12-31 23:47:59 drop table t1; +create table t1 (a timestamp default 1); +ERROR 42000: Invalid default value for 'a' diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index b3bf95bdf3d..4a514e3dd18 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -3,7 +3,7 @@ CREATE TABLE t1 (a int not null, b char (10) not null); insert into t1 values(1,'a'),(2,'b'),(3,'c'),(3,'c'); CREATE TABLE t2 (a int not null, b char (10) not null); insert into t2 values (3,'c'),(4,'d'),(5,'f'),(6,'e'); -select a,b from t1 union select a,b from t2; +select a,b from t1 union distinct select a,b from t2; a b 1 a 2 b @@ -434,7 +434,15 @@ a 3 (SELECT * FROM t1) UNION all (SELECT SQL_CALC_FOUND_ROWS * FROM t2) LIMIT 1; ERROR 42000: Wrong usage/placement of 'SQL_CALC_FOUND_ROWS' +create temporary table t1 select a from t1 union select a from t2; +drop temporary table t1; +create table t1 select a from t1 union select a from t2; +ERROR HY000: You can't specify target table 't1' for update in FROM clause drop table t1,t2; +select length(version()) > 1 as `*` UNION select 2; +* +1 +2 CREATE TABLE t1 ( id int(3) unsigned default '0') ENGINE=MyISAM; INSERT INTO t1 (id) VALUES("1"); CREATE TABLE t2 ( id int(3) unsigned default '0', id_master int(5) default '0', text1 varchar(5) default NULL, text2 varchar(5) default NULL) ENGINE=MyISAM; diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index e8e3e875f09..ee40d0a48fa 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -137,13 +137,13 @@ set global concurrent_insert=DEFAULT; show variables like 'concurrent_insert'; Variable_name Value concurrent_insert ON -set table_type=MYISAM, table_type="HEAP", global table_type="INNODB"; -show local variables like 'table_type'; +set storage_engine=MYISAM, storage_engine="HEAP", global storage_engine="INNODB"; +show local variables like 'storage_engine'; Variable_name Value -table_type HEAP -show global variables like 'table_type'; +storage_engine HEAP +show global variables like 'storage_engine'; Variable_name Value -table_type InnoDB +storage_engine InnoDB set GLOBAL query_cache_size=100000; set GLOBAL myisam_max_sort_file_size=2000000; show global variables like 'myisam_max_sort_file_size'; @@ -240,17 +240,17 @@ set unknown_variable=1; ERROR HY000: Unknown system variable 'unknown_variable' set max_join_size="hello"; ERROR 42000: Wrong argument type to variable 'max_join_size' -set table_type=UNKNOWN_TABLE_TYPE; +set storage_engine=UNKNOWN_TABLE_TYPE; ERROR 42000: Unknown table engine 'UNKNOWN_TABLE_TYPE' -set table_type=INNODB, big_tables=2; +set storage_engine=INNODB, big_tables=2; ERROR 42000: Variable 'big_tables' can't be set to the value of '2' -show local variables like 'table_type'; +show local variables like 'storage_engine'; Variable_name Value -table_type HEAP +storage_engine HEAP set SESSION query_cache_size=10000; ERROR HY000: Variable 'query_cache_size' is a GLOBAL variable and should be set with SET GLOBAL -set GLOBAL table_type=DEFAULT; -ERROR 42000: Variable 'table_type' doesn't have a default value +set GLOBAL storage_engine=DEFAULT; +ERROR 42000: Variable 'storage_engine' doesn't have a default value set character_set_client=UNKNOWN_CHARACTER_SET; ERROR 42000: Unknown character set: 'UNKNOWN_CHARACTER_SET' set collation_connection=UNKNOWN_COLLATION; @@ -372,7 +372,7 @@ set sql_select_limit=1; set global sql_slave_skip_counter=100; set sql_warnings=1; set global table_cache=100; -set table_type=myisam; +set storage_engine=myisam; set global thread_cache_size=100; set timestamp=1, timestamp=default; set tmp_table_size=100; diff --git a/mysql-test/r/warnings.result b/mysql-test/r/warnings.result index 2769e284a95..5c7c75bac00 100644 --- a/mysql-test/r/warnings.result +++ b/mysql-test/r/warnings.result @@ -49,9 +49,9 @@ Warnings: Warning 1262 Data truncated, NULL supplied to NOT NULL column 'b' at row 2 Warning 1264 Data truncated for column 'd' at row 3 Warning 1264 Data truncated for column 'c' at row 4 -Warning 1260 Record count is fewer than the column count at row 5 +Warning 1260 Row 5 doesn't contain data for all columns Warning 1264 Data truncated for column 'b' at row 6 -Warning 1261 Record count is more than the column count at row 7 +Warning 1261 Row 7 was truncated; It contained more data than there where input columns Warning 1263 Data truncated, out of range for column 'a' at row 8 select @@warning_count; @@warning_count @@ -133,3 +133,6 @@ alter table t1 type=myisam; Warnings: Warning 1286 'TYPE=database_engine' is deprecated. Use 'ENGINE=database_engine' instead. drop table t1; +set table_type=MYISAM; +Warnings: +Warning 1286 'table_type' is deprecated. Use 'storage_engine' instead. diff --git a/mysql-test/std_data/loaddata3.dat b/mysql-test/std_data/loaddata3.dat new file mode 100644 index 00000000000..4c82f1396c5 --- /dev/null +++ b/mysql-test/std_data/loaddata3.dat @@ -0,0 +1,6 @@ +number row data +1 row 1 +2 row 2 +error 12345678901234567890123456789012345678901234567890 +3 row 3 +wrong end 12345678901234567890123456789012345678901234567890 diff --git a/mysql-test/std_data/loaddata4.dat b/mysql-test/std_data/loaddata4.dat new file mode 100644 index 00000000000..9c0d744438c --- /dev/null +++ b/mysql-test/std_data/loaddata4.dat @@ -0,0 +1 @@ +test row data 1 row 1 2 row 2 3 row 3 diff --git a/mysql-test/t/auto_increment.test b/mysql-test/t/auto_increment.test index 6cf286f86c0..99a75889431 100644 --- a/mysql-test/t/auto_increment.test +++ b/mysql-test/t/auto_increment.test @@ -74,6 +74,25 @@ check table t1; drop table t1; # +# Test negative values (Bug #1366) +# + +create table t1 (a int not null auto_increment primary key); +insert into t1 values (NULL); +insert into t1 values (-1); +select last_insert_id(); +insert into t1 values (NULL); +select * from t1; +drop table t1; + +create table t1 (a int not null auto_increment primary key) /*!40102 engine=heap */; +insert into t1 values (NULL); +insert into t1 values (-1); +select last_insert_id(); +insert into t1 values (NULL); +select * from t1; +drop table t1; +# # last_insert_id() madness # create table t1 (i tinyint unsigned not null auto_increment primary key); diff --git a/mysql-test/t/bdb.test b/mysql-test/t/bdb.test index 44bb753d6a1..12b81f27147 100644 --- a/mysql-test/t/bdb.test +++ b/mysql-test/t/bdb.test @@ -789,3 +789,22 @@ select * from t1 where x <= 10 and x >= 7 order by x desc; select * from t1 where x <= 8 and x >= 5 order by x desc; select * from t1 where x < 8 and x > 5 order by x desc; drop table t1; + +# +# Test of multi-table-updates (bug #1980). +# + +create table t1 ( c char(8) not null ) engine=bdb; +insert into t1 values ('0'),('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9'); +insert into t1 values ('A'),('B'),('C'),('D'),('E'),('F'); + +alter table t1 add b char(8) not null; +alter table t1 add a char(8) not null; +alter table t1 add primary key (a,b,c); +update t1 set a=c, b=c; + +create table t2 (c char(8) not null, b char(8) not null, a char(8) not null, primary key(a,b,c)) engine=bdb; +insert into t2 select * from t1; + +delete t1,t2 from t2,t1 where t1.a<'B' and t2.b=t1.b; +drop table t1,t2; diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index 35b6070d10d..64134fe9990 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -152,17 +152,17 @@ drop table if exists t1; # # Test default table type # -SET SESSION table_type="heap"; -SELECT @@table_type; +SET SESSION storage_engine="heap"; +SELECT @@storage_engine; CREATE TABLE t1 (a int not null); show create table t1; drop table t1; --error 1285 -SET SESSION table_type="gemini"; -SELECT @@table_type; +SET SESSION storage_engine="gemini"; +SELECT @@storage_engine; CREATE TABLE t1 (a int not null); show create table t1; -SET SESSION table_type=default; +SET SESSION storage_engine=default; drop table t1; @@ -272,17 +272,17 @@ drop database test_$1; # # Test default table type # -SET SESSION table_type="heap"; -SELECT @@table_type; +SET SESSION storage_engine="heap"; +SELECT @@storage_engine; CREATE TABLE t1 (a int not null); show create table t1; drop table t1; --error 1285 -SET SESSION table_type="gemini"; -SELECT @@table_type; +SET SESSION storage_engine="gemini"; +SELECT @@storage_engine; CREATE TABLE t1 (a int not null); show create table t1; -SET SESSION table_type=default; +SET SESSION storage_engine=default; drop table t1; # diff --git a/mysql-test/t/ctype_create.test b/mysql-test/t/ctype_create.test new file mode 100644 index 00000000000..a4858898535 --- /dev/null +++ b/mysql-test/t/ctype_create.test @@ -0,0 +1,39 @@ +# +# Test for various CREATE statements and character sets +# + + +# Check that the database charset is taken from server charset by default: +# - Change local character_set_server variable to latin5. +# - Create database with and without CHARACTER SET specification. +# At the same time check fix for the +# Bug#2151: +# "USE db" with non-default character set should never affect +# further CREATE DATABASEs. + + +SET @@character_set_server=latin5; +CREATE DATABASE db1 DEFAULT CHARACTER SET cp1251; +USE db1; +CREATE DATABASE db2; + +# +# This should be cp1251 +# +SHOW CREATE DATABASE db1; + +# +# This should take the default latin5 value from server level. +# +SHOW CREATE DATABASE db2; +DROP DATABASE db2; + +# +# Check that table value uses database level by default +# +USE db1; +CREATE TABLE t1 (a char(10)); +SHOW CREATE TABLE t1; + +DROP TABLE t1; +DROP DATABASE db1; diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test index 17ed4c03b5a..ce89cbe1b22 100644 --- a/mysql-test/t/func_group.test +++ b/mysql-test/t/func_group.test @@ -370,3 +370,11 @@ insert into t1 values (1); select max(a) as b from t1 having b=1; select a from t1 having a=1; drop table t1; +# +# Bug #1972: test for bit_and(), bit_or() and negative values +# +create table t1 (col int); +insert into t1 values (-1), (-2), (-3); +select bit_and(col), bit_or(col) from t1; +select SQL_BIG_RESULT bit_and(col), bit_or(col) from t1 group by col; +drop table t1; diff --git a/mysql-test/t/func_op.test b/mysql-test/t/func_op.test index cb6ca58f193..33a2884b424 100644 --- a/mysql-test/t/func_op.test +++ b/mysql-test/t/func_op.test @@ -7,3 +7,12 @@ explain extended select 1+1,1-1,1+1*2,8/5,8%5,mod(8,5),mod(8,5)|0,-(1+1)*-2; select 1 | (1+1),5 & 3,bit_count(7) ; explain extended select 1 | (1+1),5 & 3,bit_count(7) ; select 1 << 32,1 << 63, 1 << 64, 4 >> 2, 4 >> 63, 1<< 63 >> 60; +# +# bug #1993: bit functions must be unsigned +# +select -1 | 0, -1 ^ 0, -1 & 0; +select -1 | 1, -1 ^ 1, -1 & 1; +select 1 | -1, 1 ^ -1, 1 & -1; +select 0 | -1, 0 ^ -1, 0 & -1; +select -1 >> 0, -1 << 0; +select -1 >> 1, -1 << 1; diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 0003f14c9ca..ad7b9b21b51 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -61,11 +61,13 @@ select aes_decrypt("a","a"); select aes_decrypt(aes_encrypt("","a"),"a"); select repeat('monty',5),concat('*',space(5),'*'); select reverse('abc'),reverse('abcd'); -select rpad('a',4,'1'),rpad('a',4,'12'),rpad('abcd',3,'12'); -select lpad('a',4,'1'),lpad('a',4,'12'),lpad('abcd',3,'12'); +select rpad('a',4,'1'),rpad('a',4,'12'),rpad('abcd',3,'12'), rpad(11, 10 , 22), rpad("ab", 10, 22); +select lpad('a',4,'1'),lpad('a',4,'12'),lpad('abcd',3,'12'), lpad(11, 10 , 22); select rpad(741653838,17,'0'),lpad(741653838,17,'0'); select rpad('abcd',7,'ab'),lpad('abcd',7,'ab'); select rpad('abcd',1,'ab'),lpad('abcd',1,'ab'); +select rpad('STRING', 20, CONCAT('p','a','d') ); +select lpad('STRING', 20, CONCAT('p','a','d') ); select LEAST(NULL,'HARRY','HARRIOT',NULL,'HAROLD'),GREATEST(NULL,'HARRY','HARRIOT',NULL,'HAROLD'); select least(1,2,3) | greatest(16,32,8), least(5,4)*1,greatest(-1.0,1.0)*1,least(3,2,1)*1.0,greatest(1,1.1,1.0),least("10",9),greatest("A","B","0"); @@ -77,6 +79,7 @@ select quote('\'\"\\test'); select quote(concat('abc\'', '\\cba')); select quote(1/0), quote('\0\Z'); select length(quote(concat(char(0),"test"))); +select hex(quote(concat(char(224),char(227),char(230),char(231),char(232),char(234),char(235)))); # # Wrong usage of functions diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index aa2f0ddc512..7a6e2a815f4 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -42,6 +42,18 @@ select yearweek("2000-01-06",1) as '2000', yearweek("2001-01-06",1) as '2001', y select week(19981231,2), week(19981231,3), week(20000101,2), week(20000101,3); select week(20001231,2),week(20001231,3); +select week(19981231,0) as '0', week(19981231,1) as '1', week(19981231,2) as '2', week(19981231,3) as '3', week(19981231,4) as '4', week(19981231,5) as '5', week(19981231,6) as '6', week(19981231,7) as '7'; +select week(20000101,0) as '0', week(20000101,1) as '1', week(20000101,2) as '2', week(20000101,3) as '3', week(20000101,4) as '4', week(20000101,5) as '5', week(20000101,6) as '6', week(20000101,7) as '7'; +select week(20000106,0) as '0', week(20000106,1) as '1', week(20000106,2) as '2', week(20000106,3) as '3', week(20000106,4) as '4', week(20000106,5) as '5', week(20000106,6) as '6', week(20000106,7) as '7'; +select week(20001231,0) as '0', week(20001231,1) as '1', week(20001231,2) as '2', week(20001231,3) as '3', week(20001231,4) as '4', week(20001231,5) as '5', week(20001231,6) as '6', week(20001231,7) as '7'; +select week(20010101,0) as '0', week(20010101,1) as '1', week(20010101,2) as '2', week(20010101,3) as '3', week(20010101,4) as '4', week(20010101,5) as '5', week(20010101,6) as '6', week(20010101,7) as '7'; + +select yearweek(20001231,0), yearweek(20001231,1), yearweek(20001231,2), yearweek(20001231,3), yearweek(20001231,4), yearweek(20001231,5), yearweek(20001231,6), yearweek(20001231,7); + +set default_week_format = 6; +select week(20001231), week(20001231,6); +set default_week_format = 0; + set default_week_format = 2; select week(20001231),week(20001231,2),week(20001231,0); set default_week_format = 0; @@ -194,6 +206,13 @@ select * from t1, t3 where t1.start between t3.ctime1 and t3.ctime2; drop table t1,t2,t3; # +# Test unix timestamp +# +select @a:=FROM_UNIXTIME(1); +select unix_timestamp(@a); +select unix_timestamp('1969-12-01 19:00:01'); + +# # Test types from + INTERVAL # diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test index 1e65bef19b7..d6d1922c10f 100644 --- a/mysql-test/t/group_by.test +++ b/mysql-test/t/group_by.test @@ -432,3 +432,27 @@ select id, sum(qty) as sqty, count(qty) as cqty from t1 group by id having sum(q select count(*), case interval(qty,2,3,4,5,6,7,8) when -1 then NULL when 0 then "zero" when 1 then "one" when 2 then "two" end as category from t1 group by category; select count(*), interval(qty,2,3,4,5,6,7,8) as category from t1 group by category; drop table t1; +# +# Tests for bug #1355: 'Using filesort' is missing in EXPLAIN when ORDER BY +# NULL is used. +# +CREATE TABLE t1 ( + userid int(10) unsigned, + score smallint(5) unsigned, + key (score) +); +INSERT INTO t1 VALUES (1,1),(2,2),(1,1),(3,3),(3,3),(3,3),(3,3),(3,3); +# Here we select unordered GROUP BY into a temporary talbe, +# and then sort it with filesort (GROUP BY in MySQL +# implies sorted order of results) +SELECT userid,count(*) FROM t1 GROUP BY userid DESC; +EXPLAIN SELECT userid,count(*) FROM t1 GROUP BY userid DESC; +DROP TABLE t1; +CREATE TABLE t1 ( + i int(11) default NULL, + j int(11) default NULL +); +INSERT INTO t1 VALUES (1,2),(2,3),(4,5),(3,5),(1,5),(23,5); +SELECT i, COUNT(DISTINCT(i)) FROM t1 GROUP BY j ORDER BY NULL; +explain SELECT i, COUNT(DISTINCT(i)) FROM t1 GROUP BY j ORDER BY NULL; +DROP TABLE t1; diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index 6f7a0e100c3..b227614e7ae 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -902,12 +902,47 @@ update t1 set a=a+10+b where a=1 order by b; select * from t1 order by a,b; drop table t1; +# +# Test of multi-table-updates (bug #1980). +# + +create table t1 ( c char(8) not null ) engine=innodb; +insert into t1 values ('0'),('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9'); +insert into t1 values ('A'),('B'),('C'),('D'),('E'),('F'); + +alter table t1 add b char(8) not null; +alter table t1 add a char(8) not null; +alter table t1 add primary key (a,b,c); +update t1 set a=c, b=c; + +create table t2 (c char(8) not null, b char(8) not null, a char(8) not null, primary key(a,b,c)) engine=innodb; +insert into t2 select * from t1; + +delete t1,t2 from t2,t1 where t1.a<'B' and t2.b=t1.b; +drop table t1,t2; + +# +# test autoincrement with TRUNCATE +# + +SET AUTOCOMMIT=1; +create table t1 (a integer auto_increment primary key) engine=innodb; +insert into t1 (a) values (NULL),(NULL); +truncate table t1; +insert into t1 (a) values (NULL),(NULL); +SELECT * from t1; +drop table t1; + +# +# Test timestamps +# CREATE TABLE t1 (col1 int(1))ENGINE=InnoDB; CREATE TABLE t2 (col1 int(1),stamp TIMESTAMP,INDEX stamp_idx (stamp))ENGINE=InnoDB; insert into t1 values (1),(2),(3); -insert into t2 values (1, 20020204130000),(2, 20020204130000),(4,20020204310000 ); +# Note that timestamp 3 is wrong +insert into t2 values (1, 20020204130000),(2, 20020204130000),(4,20020204310000 ),(5,20020204230000); SELECT col1 FROM t1 UNION SELECT col1 FROM t2 WHERE stamp < '20020204120000' GROUP BY col1; drop table t1,t2; diff --git a/mysql-test/t/insert.test b/mysql-test/t/insert.test index 2b74a0c800f..b9b3a9192e6 100644 --- a/mysql-test/t/insert.test +++ b/mysql-test/t/insert.test @@ -71,7 +71,7 @@ drop table t1; create table t1 (email varchar(50)); insert into t1 values ('sasha@mysql.com'),('monty@mysql.com'),('foo@hotmail.com'),('foo@aol.com'),('bar@aol.com'); create table t2(id int not null auto_increment primary key, t2 varchar(50), unique(t2)); -insert into t2 (t2) select distinct substring(email, locate('@', email)+1) from t1; +insert delayed into t2 (t2) select distinct substring(email, locate('@', email)+1) from t1; select * from t2; drop table t1,t2; diff --git a/mysql-test/t/join_outer.test b/mysql-test/t/join_outer.test index d048208a8ff..4ffe1c075b6 100644 --- a/mysql-test/t/join_outer.test +++ b/mysql-test/t/join_outer.test @@ -438,3 +438,16 @@ select * from t1 left outer join t2 using (f2) left outer join t3 using (f3); drop table t1,t2,t3; + +create table t1 (a1 int, a2 int); +create table t2 (b1 int not null, b2 int); +create table t3 (c1 int, c2 int); + +insert into t1 values (1,2), (2,2), (3,2); +insert into t2 values (1,3), (2,3); +insert into t3 values (2,4), (3,4); + +select * from t1 left join t2 on b1 = a1 left join t3 on c1 = a1 and b1 is null; +explain select * from t1 left join t2 on b1 = a1 left join t3 on c1 = a1 and b1 is null; + +drop table t1, t2, t3; diff --git a/mysql-test/t/key_cache.test b/mysql-test/t/key_cache.test index df16e11daae..b2bc57f3804 100644 --- a/mysql-test/t/key_cache.test +++ b/mysql-test/t/key_cache.test @@ -42,7 +42,7 @@ SET @@global.key_buffer_size=@save_key_buffer; --error 1064 SELECT @@default.key_buffer_size; --error 1271 -SELECT @@skr.table_type="test"; +SELECT @@skr.storage_engine="test"; select @@keycache1.key_cache_block_size; select @@keycache1.key_buffer_size; diff --git a/mysql-test/t/limit.test b/mysql-test/t/limit.test index 88a9831aa68..61c57c9b468 100644 --- a/mysql-test/t/limit.test +++ b/mysql-test/t/limit.test @@ -22,9 +22,7 @@ select * from t1; drop table t1; create table t1 (i int); -insert into t1 (i) values(1); -insert into t1 (i) values(1); -insert into t1 (i) values(1); +insert into t1 (i) values(1),(1),(1); delete from t1 limit 1; update t1 set i=2 limit 1; delete from t1 limit 0; @@ -32,4 +30,22 @@ update t1 set i=3 limit 0; select * from t1; drop table t1; +# LIMIT 0 + select 0 limit 0; + +# +# Test with DELETE, ORDER BY and limit (bug #1024) +# + +CREATE TABLE t1(id int auto_increment primary key, id2 int, index(id2)); +INSERT INTO t1 (id2) values (0),(0),(0); +DELETE FROM t1 WHERE id=1; +INSERT INTO t1 SET id2=0; +SELECT * FROM t1; +DELETE FROM t1 WHERE id2 = 0 ORDER BY id LIMIT 1; +# should have deleted WHERE id=2 +SELECT * FROM t1; +DELETE FROM t1 WHERE id2 = 0 ORDER BY id desc LIMIT 1; +SELECT * FROM t1; +DROP TABLE t1; diff --git a/mysql-test/t/loaddata.test b/mysql-test/t/loaddata.test index 1720ae69bbb..aa0ea0a2f55 100644 --- a/mysql-test/t/loaddata.test +++ b/mysql-test/t/loaddata.test @@ -20,3 +20,14 @@ create table t1 (a text, b text); load data infile '../../std_data/loaddata2.dat' into table t1 fields terminated by ',' enclosed by ''''; select concat('|',a,'|'), concat('|',b,'|') from t1; drop table t1; + +create table t1 (a int, b char(10)); +load data infile '../../std_data/loaddata3.dat' into table t1 fields terminated by '' enclosed by '' ignore 1 lines; +select * from t1; +truncate table t1; +load data infile '../../std_data/loaddata4.dat' into table t1 fields terminated by '' enclosed by '' lines terminated by '' ignore 1 lines; + +# The empty line last comes from the end line field in the file +select * from t1; +drop table t1; + diff --git a/mysql-test/t/lowercase_table.test b/mysql-test/t/lowercase_table.test index 28e45bde5c5..601f1734ac6 100644 --- a/mysql-test/t/lowercase_table.test +++ b/mysql-test/t/lowercase_table.test @@ -3,21 +3,24 @@ # --disable_warnings -drop table if exists t1,t2,t3; +drop table if exists t1,t2,t3,t4,T1; --enable_warnings create table T1 (id int primary key, Word varchar(40) not null, Index(Word)); +create table t4 (id int primary key, Word varchar(40) not null); INSERT INTO T1 VALUES (1, 'a'), (2, 'b'), (3, 'c'); +INSERT INTO T4 VALUES(1,'match'); SELECT * FROM t1; SELECT T1.id from T1 LIMIT 1; SELECT T2.id from t1 as T2 LIMIT 1; +SELECT * from t1 left join t4 on (test.t1.id= TEST.t4.id) where TEST.t1.id >= test.t4.id; # This gave an error in 4.0, but it's fixed in 4.1 SELECT T2.id from t1 as t2 LIMIT 1; RENAME TABLE T1 TO T2; ALTER TABLE T2 ADD new_col int not null; ALTER TABLE T2 RENAME T3; show tables like 't_'; -drop table t3; +drop table t3,t4; # # Test alias # diff --git a/mysql-test/t/multi_update.test b/mysql-test/t/multi_update.test index 30cabc1cc3c..50bd2d114ed 100644 --- a/mysql-test/t/multi_update.test +++ b/mysql-test/t/multi_update.test @@ -60,8 +60,8 @@ delete from t1, t2, t3 using t1,t2,t3 where t1.id1 = t2.id2 and t2.id2 = t3.id3 select count(*) from t1 where id1; select count(*) from t2 where id2; select count(*) from t3 where id3; - drop table t1,t2,t3; + create table t1(id1 int not null primary key, t varchar(100)) pack_keys = 1; create table t2(id2 int not null, t varchar(100), index(id2)) pack_keys = 1; disable_query_log; @@ -277,6 +277,41 @@ select t1.a, t1.b,t2.a, t2.b from t1 left join t2 on t1.a=t2.a where t1.b=1 and drop table t1,t2; # +# Test reuse of same table +# + +create table t1 (a int not null auto_increment primary key, b int not null); +insert into t1 (b) values (1),(2),(3),(4); +update t1, t1 as t2 set t1.b=t2.b+1 where t1.a=t2.a; +select * from t1; +drop table t1; + +# Test multi-update and multi-delete with impossible where + +create table t1(id1 smallint(5), field char(5)); +create table t2(id2 smallint(5), field char(5)); + +insert into t1 values (1, 'a'), (2, 'aa'); +insert into t2 values (1, 'b'), (2, 'bb'); + +select * from t1; +select * from t2; + +update t2 inner join t1 on t1.id1=t2.id2 + set t2.field=t1.field + where 0=1; +update t2, t1 set t2.field=t1.field + where t1.id1=t2.id2 and 0=1; + +delete t1, t2 from t2 inner join t1 on t1.id1=t2.id2 + where 0=1; +delete t1, t2 from t2,t1 + where t1.id1=t2.id2 and 0=1; + +drop table t1,t2; + + +# # Test for bug #1820. # @@ -314,10 +349,10 @@ drop table t1,t2; # # Test for bug #1980. # -set @ttype_save=@@table_type; +set @ttype_save=@@storage_engine; --disable_warnings -set @@table_type=innodb; +set @@storage_engine=innodb; create table t1 ( c char(8) not null ); --enable_warnings @@ -337,7 +372,7 @@ delete t1,t2 from t2,t1 where t1.a<'B' and t2.b=t1.b; drop table t1,t2; --disable_warnings -set @@table_type=bdb; +set @@storage_engine=bdb; create table t1 ( c char(8) not null ); --enable_warnings @@ -354,5 +389,5 @@ insert into t2 select * from t1; delete t1,t2 from t2,t1 where t1.a<'B' and t2.b=t1.b; -set @@table_type=@ttype_save; +set @@storage_engine=@ttype_save; drop table t1,t2; diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 582fae0da36..1299d73eb99 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -6,12 +6,34 @@ DROP TABLE IF EXISTS t1, `"t"1`; CREATE TABLE t1(a int); INSERT INTO t1 VALUES (1), (2); ---exec $MYSQL_DUMP --skip-all -X test t1 +--exec $MYSQL_DUMP --skip-all --skip-comments -X test t1 +DROP TABLE t1; + +# +# Bug #2005 +# + +CREATE TABLE t1 (a decimal(240, 20)); +INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"), +("0987654321098765432109876543210987654321"); +--exec $MYSQL_DUMP --skip-comments test t1 +DROP TABLE t1; + +# +# Bug #2055 +# + +CREATE TABLE t1 (a double); +INSERT INTO t1 VALUES (-9e999999); +# The following replaces is here because some systems replaces the above +# double with '-inf' and others with MAX_DOUBLE +--replace_result (-1.79769313486232e+308) (RES) (NULL) (RES) +--exec $MYSQL_DUMP --skip-comments test t1 DROP TABLE t1; CREATE TABLE t1(a int, b text, c varchar(3)); INSERT INTO t1 VALUES (1, "test", "tes"), (2, "TEST", "TES"); ---exec $MYSQL_DUMP --skip-all -X test t1 +--exec $MYSQL_DUMP --skip-all --skip-comments -X test t1 DROP TABLE t1; # @@ -20,7 +42,7 @@ DROP TABLE t1; CREATE TABLE t1 (`a"b"` char(2)); INSERT INTO t1 VALUES ("1\""), ("\"2"); ---exec $MYSQL_DUMP --skip-all -X test t1 +--exec $MYSQL_DUMP --skip-all --skip-comments -X test t1 DROP TABLE t1; # @@ -29,5 +51,5 @@ DROP TABLE t1; CREATE TABLE t1 (a VARCHAR(255)) DEFAULT CHARSET koi8r; INSERT INTO t1 VALUES (_koi8r x'C1C2C3C4C5'); ---exec $MYSQL_DUMP test t1 +--exec $MYSQL_DUMP --skip-comments test t1 DROP TABLE t1; diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test index 11c422d6fc0..17ba5418c8a 100644 --- a/mysql-test/t/query_cache.test +++ b/mysql-test/t/query_cache.test @@ -254,10 +254,14 @@ select * from mysqltest.t1 where i is null; # # drop db # +create table t1(a int); +select * from t1; +show status like "Qcache_queries_in_cache"; select * from mysqltest.t1; show status like "Qcache_queries_in_cache"; drop database mysqltest; show status like "Qcache_queries_in_cache"; +drop table t1; # # Charset convertion (cp1251_koi8 always present) diff --git a/mysql-test/t/rpl_EE_error.test b/mysql-test/t/rpl_EE_error.test new file mode 100644 index 00000000000..1a1572b48b0 --- /dev/null +++ b/mysql-test/t/rpl_EE_error.test @@ -0,0 +1,30 @@ +# See if an EE_ error in one event of the master's binlog stops replication +# (it should not: in this configuration the EE_ error is probably not +# critical). Example: you do a DROP TABLE on a table which has no MYI file +# check if START SLAVE, RESET SLAVE, CHANGE MASTER reset Last_slave_error and +# Last_slave_errno in SHOW SLAVE STATUS (1st and 3rd commands did not: bug 986). + +source include/master-slave.inc; + +create table t1 (a int) engine=myisam; +flush tables; +system rm ./var/master-data/test/t1.MYI ; +drop table t1; +save_master_pos; +connection slave; +sync_with_master; + +# Now a real error. + +connection master; +create table t1 (a int, unique(a)) engine=myisam; +set sql_log_bin=0; +insert into t1 values(2); +set sql_log_bin=1; +save_master_pos; +--error 1062; +insert into t1 values(1),(2); +drop table t1; +save_master_pos; +connection slave; +wait_for_slave_to_stop; diff --git a/mysql-test/t/rpl_multi_update.test b/mysql-test/t/rpl_multi_update.test new file mode 100644 index 00000000000..98a199ae412 --- /dev/null +++ b/mysql-test/t/rpl_multi_update.test @@ -0,0 +1,24 @@ +source include/master-slave.inc; + +CREATE TABLE t1 ( + a int unsigned not null auto_increment primary key, + b int unsigned, +) ENGINE=MyISAM; + +CREATE TABLE t2 ( + a int unsigned not null auto_increment primary key, + b int unsigned +) ENGINE=MyISAM; + +INSERT INTO t1 VALUES (NULL, 0); +INSERT INTO t1 SELECT NULL, 0 FROM t1; + +INSERT INTO t2 VALUES (NULL, 0), (NULL,1); + +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; + +UPDATE t1, t2 SET t1.b = t2.b WHERE t1.a = t2.a; +save_master_pos; +connection slave; +sync_with_master; diff --git a/mysql-test/t/rpl_rotate_logs.test b/mysql-test/t/rpl_rotate_logs.test index 7560d56af1c..0d447b8d1a3 100644 --- a/mysql-test/t/rpl_rotate_logs.test +++ b/mysql-test/t/rpl_rotate_logs.test @@ -130,6 +130,7 @@ while ($1) dec $1; } enable_query_log; +select count(*) from t3 where n >= 4; create table t4 select * from temp_table; show binary logs; show master status; diff --git a/mysql-test/t/rpl_temporary-master.opt b/mysql-test/t/rpl_temporary-master.opt deleted file mode 100644 index e69de29bb2d..00000000000 --- a/mysql-test/t/rpl_temporary-master.opt +++ /dev/null diff --git a/mysql-test/t/select_found.test b/mysql-test/t/select_found.test index f787cec6533..3cf736cafb0 100644 --- a/mysql-test/t/select_found.test +++ b/mysql-test/t/select_found.test @@ -95,3 +95,17 @@ SELECT FOUND_ROWS(); SELECT SQL_CALC_FOUND_ROWS * FROM t1 ORDER BY numeropost LIMIT 0; SELECT FOUND_ROWS(); drop table t1; + +# +# Test problem with impossible WHERE (Bug #1468) +# + +create table t1 (id int, primary key (id)); +insert into t1 values (1), (2), (3), (4), (5); +select SQL_CALC_FOUND_ROWS * from t1 where id > 3 limit 0, 1; +select FOUND_ROWS(); +select SQL_CALC_FOUND_ROWS * from t1 where id > 3 AND 1=2 limit 0, 1; +select FOUND_ROWS(); +select SQL_CALC_FOUND_ROWS * from t1 where id > 6 limit 0, 1; +select FOUND_ROWS(); +drop table t1; diff --git a/mysql-test/t/sum_distinct.test b/mysql-test/t/sum_distinct.test new file mode 100644 index 00000000000..efbb21a7b85 --- /dev/null +++ b/mysql-test/t/sum_distinct.test @@ -0,0 +1,188 @@ +# +# Various tests for SUM(DISTINCT ...) +# +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE t1 ( + id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT, + gender CHAR(1), + name VARCHAR(20) +); + +# According to ANSI SQL, SUM(DISTINCT ...) should return NULL for empty +# record set + +SELECT SUM(DISTINCT LENGTH(name)) s1 FROM t1; + +# According to ANSI SQL, SUM(DISTINCT ...) should return NULL for records sets +# entirely consisting of NULLs + +INSERT INTO t1 (gender, name) VALUES (NULL, NULL); +INSERT INTO t1 (gender, name) VALUES (NULL, NULL); +INSERT INTO t1 (gender, name) VALUES (NULL, NULL); + +SELECT SUM(DISTINCT LENGTH(name)) s1 FROM t1; + + +# Filling table with t1 + +INSERT INTO t1 (gender, name) VALUES ('F', 'Helen'), ('F', 'Anastasia'), +('F', 'Katherine'), ('F', 'Margo'), ('F', 'Magdalene'), ('F', 'Mary'); + +CREATE TABLE t2 SELECT name FROM t1; + +SELECT (SELECT SUM(DISTINCT LENGTH(name)) FROM t1) FROM t2; + +DROP TABLE t2; + +INSERT INTO t1 (gender, name) VALUES ('F', 'Eva'), ('F', 'Sofia'), +('F', 'Sara'), ('F', 'Golda'), ('F', 'Toba'), ('F', 'Victory'), +('F', 'Faina'), ('F', 'Miriam'), ('F', 'Beki'), ('F', 'America'), +('F', 'Susan'), ('F', 'Glory'), ('F', 'Priscilla'), ('F', 'Rosmary'), +('F', 'Rose'), ('F', 'Margareth'), ('F', 'Elizabeth'), ('F', 'Meredith'), +('F', 'Julie'), ('F', 'Xenia'), ('F', 'Zena'), ('F', 'Olga'), +('F', 'Brunhilda'), ('F', 'Nataly'), ('F', 'Lara'), ('F', 'Svetlana'), +('F', 'Grethem'), ('F', 'Irene'); + +SELECT + SUM(DISTINCT LENGTH(name)) s1, + SUM(DISTINCT SUBSTRING(NAME, 1, 3)) s2, + SUM(DISTINCT LENGTH(SUBSTRING(name, 1, 4))) s3 +FROM t1; + +SELECT + SUM(DISTINCT LENGTH(g1.name)) s1, + SUM(DISTINCT SUBSTRING(g2.name, 1, 3)) s2, + SUM(DISTINCT LENGTH(SUBSTRING(g3.name, 1, 4))) s3 +FROM t1 g1, t1 g2, t1 g3; + +SELECT + SUM(DISTINCT LENGTH(g1.name)) s1, + SUM(DISTINCT SUBSTRING(g2.name, 1, 3)) s2, + SUM(DISTINCT LENGTH(SUBSTRING(g3.name, 1, 4))) s3 +FROM t1 g1, t1 g2, t1 g3 GROUP BY LENGTH(SUBSTRING(g3.name, 5, 10)); + +# here we explicitly request summing through temporary table (so +# Item_sum_sum_distinct::copy_or_same() is called) + +SELECT SQL_BUFFER_RESULT + SUM(DISTINCT LENGTH(name)) s1, + SUM(DISTINCT SUBSTRING(NAME, 1, 3)) s2, + SUM(DISTINCT LENGTH(SUBSTRING(name, 1, 4))) s3 +FROM t1; + +SELECT SQL_BUFFER_RESULT + SUM(DISTINCT LENGTH(g1.name)) s1, + SUM(DISTINCT SUBSTRING(g2.name, 1, 3)) s2, + SUM(DISTINCT LENGTH(SUBSTRING(g3.name, 1, 4))) s3 +FROM t1 g1, t1 g2, t1 g3 GROUP BY LENGTH(SUBSTRING(g3.name, 5, 10)); + +# this test demonstrates that strings are automatically converted to numbers +# before summing + +SET @l=1; +UPDATE t1 SET name=CONCAT(name, @l:=@l+1); + +SELECT SUM(DISTINCT RIGHT(name, 1)) FROM t1; + +# this is a test case for ordinary t1 + +SELECT SUM(DISTINCT id) FROM t1; +SELECT SUM(DISTINCT id % 11) FROM t1; + +DROP TABLE t1; + +# +# Test the case when distinct values doesn't fit in memory and +# filesort is used (see uniques.cc:merge_walk) +# + +CREATE TABLE t1 (id INTEGER); +CREATE TABLE t2 (id INTEGER); + +INSERT INTO t1 (id) VALUES (1), (1), (1),(1); +INSERT INTO t2 (id) SELECT id FROM t1; +INSERT INTO t1 (id) SELECT id FROM t2; /* 8 */ +INSERT INTO t1 (id) SELECT id FROM t2; /* 12 */ +INSERT INTO t1 (id) SELECT id FROM t2; /* 16 */ +INSERT INTO t1 (id) SELECT id FROM t2; /* 20 */ +INSERT INTO t1 (id) SELECT id FROM t2; /* 24 */ +DELETE FROM t2; +INSERT INTO t2 (id) SELECT id+1 FROM t1; +INSERT INTO t1 SELECT id FROM t2; +DELETE FROM t2; +INSERT INTO t2 (id) SELECT id+2 FROM t1; +INSERT INTO t1 SELECT id FROM t2; +DELETE FROM t2; +INSERT INTO t2 (id) SELECT id+4 FROM t1; +INSERT INTO t1 SELECT id FROM t2; +DELETE FROM t2; +INSERT INTO t2 (id) SELECT id+8 FROM t1; +INSERT INTO t1 SELECT id FROM t2; +DELETE FROM t2; +INSERT INTO t2 (id) SELECT id+16 FROM t1; +INSERT INTO t1 SELECT id FROM t2; +DELETE FROM t2; +INSERT INTO t2 (id) SELECT id+32 FROM t1; +INSERT INTO t1 SELECT id FROM t2; +DELETE FROM t2; +INSERT INTO t2 (id) SELECT id+64 FROM t1; +INSERT INTO t1 SELECT id FROM t2; +DELETE FROM t2; +INSERT INTO t2 (id) SELECT id+128 FROM t1; +INSERT INTO t1 SELECT id FROM t2; +DELETE FROM t2; +INSERT INTO t2 (id) SELECT id+256 FROM t1; +INSERT INTO t1 SELECT id FROM t2; +DELETE FROM t2; +INSERT INTO t2 (id) SELECT id+512 FROM t1; +INSERT INTO t1 SELECT id FROM t2; +DELETE FROM t2; +INSERT INTO t2 (id) SELECT id+1024 FROM t1; +INSERT INTO t1 SELECT id FROM t2; +DELETE FROM t2; +INSERT INTO t2 (id) SELECT id+2048 FROM t1; +INSERT INTO t1 SELECT id FROM t2; +DELETE FROM t2; +INSERT INTO t2 (id) SELECT id+4096 FROM t1; +INSERT INTO t1 SELECT id FROM t2; +DELETE FROM t2; +INSERT INTO t2 (id) SELECT id+8192 FROM t1; +INSERT INTO t1 SELECT id FROM t2; +DELETE FROM t2; +#INSERT INTO t2 (id) SELECT id+16384 FROM t1; +#INSERT INTO t1 SELECT id FROM t2; +#DELETE FROM t2; +#INSERT INTO t2 (id) SELECT id+32768 FROM t1; +#INSERT INTO t1 SELECT id FROM t2; +#DELETE FROM t2; +#INSERT INTO t2 (id) SELECT id+65536 FROM t1; +#INSERT INTO t1 SELECT id FROM t2; +#DELETE FROM t2; +INSERT INTO t2 SELECT id FROM t1 ORDER BY id*rand(); + +# SELECT '++++++++++++++++++++++++++++++++++++++++++++++++++'; + +SELECT SUM(DISTINCT id) sm FROM t1; +SELECT SUM(DISTINCT id) sm FROM t2; +SELECT SUM(DISTINCT id) sm FROM t1 group by id % 13; + +# this limit for max_heap_table_size is set to force testing the case, when +# all distinct sum values can not fit in memory and must be stored in a +# temporary table + +SET max_heap_table_size=16384; + +# to check that max_heap_table_size was actually set (hard limit for minimum +# max_heap_table_size is set in mysqld.cc): + +SHOW variables LIKE 'max_heap_table_size'; + +SELECT SUM(DISTINCT id) sm FROM t1; +SELECT SUM(DISTINCT id) sm FROM t2; +SELECT SUM(DISTINCT id) sm FROM t1 GROUP BY id % 13; + +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/t/symlink.test b/mysql-test/t/symlink.test index 716eed7abc0..c0a9ce1bbcf 100644 --- a/mysql-test/t/symlink.test +++ b/mysql-test/t/symlink.test @@ -93,3 +93,25 @@ select count(*) from mysqltest.t9; --replace_result $MYSQL_TEST_DIR TEST_DIR show create table mysqltest.t9; drop database mysqltest; + +# +# Test changing data dir (Bug #1662) +# + +create table t1 (a int not null) type=myisam; +disable_query_log; +eval alter table t1 data directory="$MYSQL_TEST_DIR/var/tmp"; +enable_query_log; +--replace_result $MYSQL_TEST_DIR TEST_DIR +show create table t1; +alter table t1 add b int; +disable_query_log; +eval alter table t1 data directory="$MYSQL_TEST_DIR/var/log"; +enable_query_log; +--replace_result $MYSQL_TEST_DIR TEST_DIR +show create table t1; +disable_query_log; +eval alter table t1 index directory="$MYSQL_TEST_DIR/var/log"; +enable_query_log; +show create table t1; +drop table t1; diff --git a/mysql-test/t/timezone.test b/mysql-test/t/timezone.test index 14facc0374a..ab732c11a34 100644 --- a/mysql-test/t/timezone.test +++ b/mysql-test/t/timezone.test @@ -1,9 +1,9 @@ # -# Test of timezone handling. This script must be run with TZ=MEST +# Test of timezone handling. This script must be run with TZ=MET --- require r/have_mest_timezone.require +-- require r/have_met_timezone.require disable_query_log; -show variables like "timezone"; +select FROM_UNIXTIME(24*3600); enable_query_log; # Initialization @@ -11,6 +11,17 @@ enable_query_log; DROP TABLE IF EXISTS t1; --enable_warnings +show variables like "timezone"; + +# +# Test unix timestamp +# +select @a:=FROM_UNIXTIME(1); +select unix_timestamp(@a); + +# +# Test of some values, including some with daylight saving time +# CREATE TABLE t1 (ts int); INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 01:00')); @@ -26,3 +37,4 @@ INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 04:00:01')); SELECT ts,from_unixtime(ts) FROM t1; DROP TABLE t1; + diff --git a/mysql-test/t/truncate.test b/mysql-test/t/truncate.test index dd80baba269..434a1907e42 100644 --- a/mysql-test/t/truncate.test +++ b/mysql-test/t/truncate.test @@ -24,3 +24,15 @@ select * from t1; drop table t1; --error 1146 truncate non_existing_table; + +# +# test autoincrement with TRUNCATE +# + +create table t1 (a integer auto_increment primary key); +insert into t1 (a) values (NULL),(NULL); +truncate table t1; +insert into t1 (a) values (NULL),(NULL); +SELECT * from t1; +drop table t1; + diff --git a/mysql-test/t/type_blob.test b/mysql-test/t/type_blob.test index c9c3284fe0d..70fa2f9b172 100644 --- a/mysql-test/t/type_blob.test +++ b/mysql-test/t/type_blob.test @@ -308,3 +308,52 @@ drop table t1; create table t1 select load_file('../../std_data/words.dat'); show full fields from t1; drop table t1; + +# +# Test blob's with end space (Bug #1651) +# + +create table t1 (id integer primary key auto_increment, txt text not null, unique index txt_index (txt (20))); +insert into t1 (txt) values ('Chevy'), ('Chevy '); +select * from t1 where txt='Chevy'; +select * from t1 where txt='Chevy '; +select * from t1 where txt='Chevy ' or txt='Chevy'; +select * from t1 where txt='Chevy' or txt='Chevy '; +select * from t1 where id='1' or id='2'; +insert into t1 (txt) values('Ford'); +select * from t1 where txt='Chevy' or txt='Chevy ' or txt='Ford'; +select * from t1 where txt='Chevy' or txt='Chevy '; +select * from t1 where txt='Chevy' or txt='Chevy ' or txt=' Chevy'; +select * from t1 where txt in ('Chevy ','Chevy'); +select * from t1 where txt in ('Chevy'); +select * from t1 where txt between 'Chevy' and 'Chevy'; +select * from t1 where txt between 'Chevy' and 'Chevy' or txt='Chevy '; +select * from t1 where txt between 'Chevy' and 'Chevy '; +select * from t1 where txt < 'Chevy '; +select * from t1 where txt <= 'Chevy'; +select * from t1 where txt > 'Chevy'; +select * from t1 where txt >= 'Chevy'; +drop table t1; + +create table t1 (id integer primary key auto_increment, txt text, unique index txt_index (txt (20))); +insert into t1 (txt) values ('Chevy'), ('Chevy '), (NULL); +select * from t1 where txt='Chevy' or txt is NULL; +select * from t1 where txt='Chevy '; +select * from t1 where txt='Chevy ' or txt='Chevy'; +select * from t1 where txt='Chevy' or txt='Chevy '; +select * from t1 where id='1' or id='2'; +insert into t1 (txt) values('Ford'); +select * from t1 where txt='Chevy' or txt='Chevy ' or txt='Ford'; +select * from t1 where txt='Chevy' or txt='Chevy '; +select * from t1 where txt='Chevy' or txt='Chevy ' or txt=' Chevy'; +select * from t1 where txt in ('Chevy ','Chevy'); +select * from t1 where txt in ('Chevy'); +select * from t1 where txt between 'Chevy' and 'Chevy'; +select * from t1 where txt between 'Chevy' and 'Chevy' or txt='Chevy '; +select * from t1 where txt between 'Chevy' and 'Chevy '; +select * from t1 where txt < 'Chevy '; +select * from t1 where txt < 'Chevy ' or txt is NULL; +select * from t1 where txt <= 'Chevy'; +select * from t1 where txt > 'Chevy'; +select * from t1 where txt >= 'Chevy'; +drop table t1; diff --git a/mysql-test/t/type_datetime.test b/mysql-test/t/type_datetime.test index 7cedbc087e4..cec2aa3582b 100644 --- a/mysql-test/t/type_datetime.test +++ b/mysql-test/t/type_datetime.test @@ -7,12 +7,13 @@ drop table if exists t1; --enable_warnings create table t1 (t datetime); -insert into t1 values(101),(691231),(700101),(991231),(10000101),(99991231),(101000000),(691231000000),(700101000000),(991231235959),(10000101000000),(99991231235959); +insert into t1 values(101),(691231),(700101),(991231),(10000101),(99991231),(101000000),(691231000000),(700101000000),(991231235959),(10000101000000),(99991231235959),(20030102030460),(20030102036301),(20030102240401),(20030132030401),(20031302030460); select * from t1; delete from t1 where t > 0; optimize table t1; check table t1; -insert into t1 values("000101"),("691231"),("700101"),("991231"),("00000101"),("00010101"),("99991231"),("00101000000"),("691231000000"),("700101000000"),("991231235959"),("10000101000000"),("99991231235959"); +delete from t1; +insert into t1 values("000101"),("691231"),("700101"),("991231"),("00000101"),("00010101"),("99991231"),("00101000000"),("691231000000"),("700101000000"),("991231235959"),("10000101000000"),("99991231235959"),("20030102030460"),("20030102036301"),("20030102240401"),("20030132030401"),("20031302030460"); select * from t1; drop table t1; diff --git a/mysql-test/t/type_decimal.test b/mysql-test/t/type_decimal.test index 36bd8eb48e4..cddb0347b7e 100644 --- a/mysql-test/t/type_decimal.test +++ b/mysql-test/t/type_decimal.test @@ -244,3 +244,21 @@ CREATE TABLE t1 (a_dec DECIMAL(-1,0)); CREATE TABLE t1 (a_dec DECIMAL(-2,1)); --error 1064 CREATE TABLE t1 (a_dec DECIMAL(-1,1)); + +# +# Zero prepend overflow bug +# +--disable-warnings +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'); +--enable-warnings +select * from t1; +drop table t1; diff --git a/mysql-test/t/type_enum.test b/mysql-test/t/type_enum.test index c53277334a6..b8f32107892 100644 --- a/mysql-test/t/type_enum.test +++ b/mysql-test/t/type_enum.test @@ -26,6 +26,17 @@ show create table t1; drop table t1; # +# Tests of wrong enum values (bug #2023) +# + +create table t1 (a enum ('0','1')); +insert into t1 set a='foobar'; +select * from t1; +update t1 set a = replace(a,'x','y'); +select * from t1; +drop table t1; + +# # Bug #2077 # diff --git a/mysql-test/t/type_timestamp.test b/mysql-test/t/type_timestamp.test index cd76dbe6ab0..fc7cd019171 100644 --- a/mysql-test/t/type_timestamp.test +++ b/mysql-test/t/type_timestamp.test @@ -37,8 +37,11 @@ select date_format(a,"%Y %y"),year(a),year(now()) from t1; drop table t1; create table t1 (ix timestamp); -insert into t1 values (19991101000000),(19990102030405),(19990630232922),(19990601000000),(19990930232922),(19990531232922),(19990501000000),(19991101000000),(19990501000000); -select ix+0 from t1; +insert into t1 values (19991101000000),(19990102030405),(19990630232922),(19990601000000),(19990930232922),(19990531232922),(19990501000000),(19991101000000),(19990501000000),(20030101010160),(20030101016001),(20030101240101),(20030132010101),(20031301010101); +select ix+0 from t1; +delete from t1; +insert into t1 values ("19991101000000"),("19990102030405"),("19990630232922"),("19990601000000"),("20030101010160"),("20030101016001"),("20030101240101"),("20030132010101"),("20031301010101"); +select ix+0 from t1; drop table t1; CREATE TABLE t1 (date date, date_time datetime, time_stamp timestamp); @@ -72,3 +75,9 @@ set new=1; select * from t1; drop table t1; +# +# Bug #1885 +# + +--error 1067 +create table t1 (a timestamp default 1); diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test index 6138bba5a31..8ce4aa997fc 100644 --- a/mysql-test/t/union.test +++ b/mysql-test/t/union.test @@ -11,7 +11,7 @@ insert into t1 values(1,'a'),(2,'b'),(3,'c'),(3,'c'); CREATE TABLE t2 (a int not null, b char (10) not null); insert into t2 values (3,'c'),(4,'d'),(5,'f'),(6,'e'); -select a,b from t1 union select a,b from t2; +select a,b from t1 union distinct select a,b from t2; select a,b from t1 union all select a,b from t2; select a,b from t1 union all select a,b from t2 order by b; select a,b from t1 union all select a,b from t2 union select 7,'g'; @@ -247,9 +247,19 @@ SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY a desc LIMIT 1; --error 1234 (SELECT * FROM t1) UNION all (SELECT SQL_CALC_FOUND_ROWS * FROM t2) LIMIT 1; +create temporary table t1 select a from t1 union select a from t2; +drop temporary table t1; +--error 1093 +create table t1 select a from t1 union select a from t2; drop table t1,t2; # +# Problem with alias '*' (BUG #1249) +# + +select length(version()) > 1 as `*` UNION select 2; + +# # Test for another bug with UNION and LEFT JOIN # CREATE TABLE t1 ( id int(3) unsigned default '0') ENGINE=MyISAM; @@ -455,4 +465,3 @@ show status like 'Slow_queries'; select count(*) from t1 where a=7 union select count(*) from t1 where b=13; show status like 'Slow_queries'; drop table t1; - diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index ef3dadeaffe..2fb2a663549 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -82,9 +82,9 @@ show variables like 'concurrent_insert'; set global concurrent_insert=DEFAULT; show variables like 'concurrent_insert'; -set table_type=MYISAM, table_type="HEAP", global table_type="INNODB"; -show local variables like 'table_type'; -show global variables like 'table_type'; +set storage_engine=MYISAM, storage_engine="HEAP", global storage_engine="INNODB"; +show local variables like 'storage_engine'; +show global variables like 'storage_engine'; set GLOBAL query_cache_size=100000; set GLOBAL myisam_max_sort_file_size=2000000; @@ -137,14 +137,14 @@ set unknown_variable=1; --error 1232 set max_join_size="hello"; --error 1285 -set table_type=UNKNOWN_TABLE_TYPE; +set storage_engine=UNKNOWN_TABLE_TYPE; --error 1231 -set table_type=INNODB, big_tables=2; -show local variables like 'table_type'; +set storage_engine=INNODB, big_tables=2; +show local variables like 'storage_engine'; --error 1229 set SESSION query_cache_size=10000; --error 1230 -set GLOBAL table_type=DEFAULT; +set GLOBAL storage_engine=DEFAULT; --error 1115 set character_set_client=UNKNOWN_CHARACTER_SET; --error 1272 @@ -247,7 +247,7 @@ set sql_select_limit=1; set global sql_slave_skip_counter=100; set sql_warnings=1; set global table_cache=100; -set table_type=myisam; +set storage_engine=myisam; set global thread_cache_size=100; set timestamp=1, timestamp=default; set tmp_table_size=100; diff --git a/mysql-test/t/warnings.test b/mysql-test/t/warnings.test index a94380db221..0456ca8c1fe 100644 --- a/mysql-test/t/warnings.test +++ b/mysql-test/t/warnings.test @@ -91,3 +91,8 @@ create table t1 (id int) type=heap; alter table t1 type=myisam; drop table t1; +# +# Test for deprecated table_type variable +# +set table_type=MYISAM; + diff --git a/mysys/charset.c b/mysys/charset.c index 4111dd246cb..1fe926a51d6 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -188,9 +188,11 @@ static my_bool create_fromuni(CHARSET_INFO *cs) break; numchars=idx[i].uidx.to-idx[i].uidx.from+1; - idx[i].uidx.tab=(unsigned char*)my_once_alloc(numchars * - sizeof(*idx[i].uidx.tab), - MYF(MY_WME)); + if (!(idx[i].uidx.tab=(uchar*) my_once_alloc(numchars * + sizeof(*idx[i].uidx.tab), + MYF(MY_WME)))) + return TRUE; + bzero(idx[i].uidx.tab,numchars*sizeof(*idx[i].uidx.tab)); for (ch=1; ch < PLANE_SIZE; ch++) @@ -206,8 +208,10 @@ static my_bool create_fromuni(CHARSET_INFO *cs) /* Allocate and fill reverse table for each plane */ n=i; - cs->tab_from_uni= (MY_UNI_IDX*) my_once_alloc(sizeof(MY_UNI_IDX)*(n+1), - MYF(MY_WME)); + if (!(cs->tab_from_uni= (MY_UNI_IDX*) my_once_alloc(sizeof(MY_UNI_IDX)*(n+1), + MYF(MY_WME)))) + return TRUE; + for (i=0; i< n; i++) cs->tab_from_uni[i]= idx[i].uidx; @@ -217,46 +221,64 @@ static my_bool create_fromuni(CHARSET_INFO *cs) } -static void simple_cs_copy_data(CHARSET_INFO *to, CHARSET_INFO *from) +static int simple_cs_copy_data(CHARSET_INFO *to, CHARSET_INFO *from) { to->number= from->number ? from->number : to->number; if (from->csname) - to->csname= my_once_strdup(from->csname,MYF(MY_WME)); + if (!(to->csname= my_once_strdup(from->csname,MYF(MY_WME)))) + goto err; if (from->name) - to->name= my_once_strdup(from->name,MYF(MY_WME)); + if (!(to->name= my_once_strdup(from->name,MYF(MY_WME)))) + goto err; if (from->comment) - to->comment= my_once_strdup(from->comment,MYF(MY_WME)); + if (!(to->comment= my_once_strdup(from->comment,MYF(MY_WME)))) + goto err; if (from->ctype) { - to->ctype= (uchar*) my_once_memdup((char*) from->ctype, - MY_CS_CTYPE_TABLE_SIZE, MYF(MY_WME)); + if (!(to->ctype= (uchar*) my_once_memdup((char*) from->ctype, + MY_CS_CTYPE_TABLE_SIZE, + MYF(MY_WME)))) + goto err; init_state_maps(to); } if (from->to_lower) - to->to_lower= (uchar*) my_once_memdup((char*) from->to_lower, - MY_CS_TO_LOWER_TABLE_SIZE, MYF(MY_WME)); + if (!(to->to_lower= (uchar*) my_once_memdup((char*) from->to_lower, + MY_CS_TO_LOWER_TABLE_SIZE, + MYF(MY_WME)))) + goto err; + if (from->to_upper) - to->to_upper= (uchar*) my_once_memdup((char*) from->to_upper, - MY_CS_TO_UPPER_TABLE_SIZE, MYF(MY_WME)); + if (!(to->to_upper= (uchar*) my_once_memdup((char*) from->to_upper, + MY_CS_TO_UPPER_TABLE_SIZE, + MYF(MY_WME)))) + goto err; if (from->sort_order) { - to->sort_order= (uchar*) my_once_memdup((char*) from->sort_order, - MY_CS_SORT_ORDER_TABLE_SIZE, - MYF(MY_WME)); + if (!(to->sort_order= (uchar*) my_once_memdup((char*) from->sort_order, + MY_CS_SORT_ORDER_TABLE_SIZE, + MYF(MY_WME)))) + goto err; set_max_sort_char(to); } if (from->tab_to_uni) { uint sz= MY_CS_TO_UNI_TABLE_SIZE*sizeof(uint16); - to->tab_to_uni= (uint16*) my_once_memdup((char*)from->tab_to_uni, sz, - MYF(MY_WME)); - create_fromuni(to); + if (!(to->tab_to_uni= (uint16*) my_once_memdup((char*)from->tab_to_uni, + sz, MYF(MY_WME)))) + goto err; + if (create_fromuni(to)) + goto err; } to->mbmaxlen= 1; + + return 0; + +err: + return 1; } @@ -292,7 +314,8 @@ static int add_collation(CHARSET_INFO *cs) if (!(all_charsets[cs->number]->state & MY_CS_COMPILED)) { simple_cs_init_functions(all_charsets[cs->number]); - simple_cs_copy_data(all_charsets[cs->number],cs); + if (simple_cs_copy_data(all_charsets[cs->number],cs)) + return MY_XML_ERROR; if (simple_cs_is_full(all_charsets[cs->number])) { all_charsets[cs->number]->state |= MY_CS_LOADED; @@ -313,11 +336,14 @@ static int add_collation(CHARSET_INFO *cs) CHARSET_INFO *dst= all_charsets[cs->number]; dst->number= cs->number; if (cs->comment) - dst->comment= my_once_strdup(cs->comment,MYF(MY_WME)); + if (!(dst->comment= my_once_strdup(cs->comment,MYF(MY_WME)))) + return MY_XML_ERROR; if (cs->csname) - dst->csname= my_once_strdup(cs->csname,MYF(MY_WME)); + if (!(dst->csname= my_once_strdup(cs->csname,MYF(MY_WME)))) + return MY_XML_ERROR; if (cs->name) - dst->name= my_once_strdup(cs->name,MYF(MY_WME)); + if (!(dst->name= my_once_strdup(cs->name,MYF(MY_WME)))) + return MY_XML_ERROR; } cs->number= 0; cs->primary_number= 0; diff --git a/mysys/charset2html.c b/mysys/charset2html.c index c6112bfeb9e..64021689bea 100644 --- a/mysys/charset2html.c +++ b/mysys/charset2html.c @@ -81,7 +81,7 @@ static void print_cs(CHARSET_INFO *cs) printf("<TR bgcolor=#%s>",clr ? "DDDDDD" : "EEEE99"); printf("<TD>%02X",ch[i].cod); printf("<TD>%04X",ch[i].uni); - printf("<TD>%d",ch[i].srt); + printf("<TD>%02X",ch[i].srt); printf("<TD>%s%s%s%s%s%s%s%s", ch[i].ctp & _U ? "U" : "", diff --git a/mysys/mf_pack.c b/mysys/mf_pack.c index b3aa347006e..e2e811fe89a 100644 --- a/mysys/mf_pack.c +++ b/mysys/mf_pack.c @@ -210,13 +210,13 @@ uint cleanup_dirname(register my_string to, const char *from) } /* cleanup_dirname */ - /* - On system where you don't have symbolic links, the following - code will allow you to create a file: - directory-name.lnk that should contain the real path - to the directory. This will be used if the directory name - doesn't exists - */ +/* + On system where you don't have symbolic links, the following + code will allow you to create a file: + directory-name.sym that should contain the real path + to the directory. This will be used if the directory name + doesn't exists +*/ my_bool my_use_symdir=0; /* Set this if you want to use symdirs */ @@ -228,16 +228,17 @@ void symdirget(char *dir) char *pos=strend(dir); if (dir[0] && pos[-1] != FN_DEVCHAR && access(dir, F_OK)) { - FILE *fp; + File file; + uint length; char temp= *(--pos); /* May be "/" or "\" */ strmov(pos,".sym"); - fp = my_fopen(dir, O_RDONLY,MYF(0)); + file= my_open(dir, O_RDONLY, MYF(0)); *pos++=temp; *pos=0; /* Restore old filename */ - if (fp) + if (file >= 0) { - if (fgets(buff, sizeof(buff)-1, fp)) + if ((length= my_read(file, buff, sizeof(buff), MYF(0))) > 0) { - for (pos=strend(buff); + for (pos= buff + length ; pos > buff && (iscntrl(pos[-1]) || isspace(pos[-1])) ; pos --); @@ -247,7 +248,7 @@ void symdirget(char *dir) strmake(dir,buff, (uint) (pos-buff)); } - my_fclose(fp,MYF(0)); + my_close(file, MYF(0)); } } } diff --git a/mysys/my_handler.c b/mysys/my_handler.c index 2fd7f1fcdee..6ee6167d3c1 100644 --- a/mysys/my_handler.c +++ b/mysys/my_handler.c @@ -189,6 +189,14 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a, get_key_pack_length(b_length,pack_length,b); next_key_length=key_length-b_length-pack_length; + if (!(nextflag & (SEARCH_PREFIX | SEARCH_UPDATE))) + { + while (a_length && a[a_length-1] == ' ') + a_length--; + while (b_length && b[b_length-1] == ' ') + b_length--; + } + if (piks && (flag= mi_compare_text(keyseg->charset,a,a_length,b,b_length, (my_bool) ((nextflag & SEARCH_PREFIX) && diff --git a/mysys/my_init.c b/mysys/my_init.c index 4a7e9194dae..d68af1400c5 100644 --- a/mysys/my_init.c +++ b/mysys/my_init.c @@ -61,13 +61,22 @@ static ulong atoi_octal(const char *str) } - /* Init my_sys functions and my_sys variabels */ +/* + Init my_sys functions and my_sys variabels + + SYNOPSIS + my_init() -void my_init(void) + RETURN + 0 ok + 1 Couldn't initialize environment +*/ + +my_bool my_init(void) { my_string str; if (my_init_done) - return; + return 0; my_init_done=1; #if defined(THREAD) && defined(SAFE_MUTEX) safe_mutex_global_init(); /* Must be called early */ @@ -77,7 +86,8 @@ void my_init(void) #if defined(HAVE_PTHREAD_INIT) pthread_init(); /* Must be called before DBUG_ENTER */ #endif - my_thread_global_init(); + if (my_thread_global_init()) + return 1; #if !defined( __WIN__) && !defined(OS2) && !defined(__NETWARE__) sigfillset(&my_signals); /* signals blocked by mf_brkhant */ #endif @@ -109,7 +119,7 @@ void my_init(void) #ifdef __WIN__ win32_init_tcp_ip(); #endif - DBUG_VOID_RETURN; + DBUG_RETURN(0); } } /* my_init */ diff --git a/mysys/my_lib.c b/mysys/my_lib.c index 035bafd07b9..055e00d2efc 100644 --- a/mysys/my_lib.c +++ b/mysys/my_lib.c @@ -62,8 +62,15 @@ #define READDIR(A,B,C) (!(C=readdir(A))) #endif +/* + We are assuming that directory we are reading is either has less than + 100 files and so can be read in one initial chunk or has more than 1000 + files and so big increment are suitable. +*/ +#define ENTRIES_START_SIZE (8192/sizeof(FILEINFO)) +#define ENTRIES_INCREMENT (65536/sizeof(FILEINFO)) +#define NAMES_START_SIZE 32768 -#define STARTSIZE ONCE_ALLOC_INIT*8 /* some mallocmargin */ static int comp_names(struct fileinfo *a,struct fileinfo *b); @@ -74,7 +81,13 @@ void my_dirend(MY_DIR *buffer) { DBUG_ENTER("my_dirend"); if (buffer) + { + delete_dynamic((DYNAMIC_ARRAY*)((char*)buffer + + ALIGN_SIZE(sizeof(MY_DIR)))); + free_root((MEM_ROOT*)((char*)buffer + ALIGN_SIZE(sizeof(MY_DIR)) + + ALIGN_SIZE(sizeof(DYNAMIC_ARRAY))), MYF(0)); my_free((gptr) buffer,MYF(0)); + } DBUG_VOID_RETURN; } /* my_dirend */ @@ -91,14 +104,14 @@ static int comp_names(struct fileinfo *a, struct fileinfo *b) MY_DIR *my_dir(const char *path, myf MyFlags) { + char *buffer; + MY_DIR *result= 0; + FILEINFO finfo; + DYNAMIC_ARRAY *dir_entries_storage; + MEM_ROOT *names_storage; DIR *dirp; struct dirent *dp; - struct fileinfo *fnames; - char *buffer, *obuffer, *tempptr; - uint fcnt,i,size,firstfcnt, maxfcnt,length; char tmp_path[FN_REFLEN+1],*tmp_file; - my_ptrdiff_t diff; - bool eof; #ifdef THREAD char dirent_tmp[sizeof(struct dirent)+_POSIX_PATH_MAX+1]; #endif @@ -110,74 +123,72 @@ MY_DIR *my_dir(const char *path, myf MyFlags) #endif dirp = opendir(directory_file_name(tmp_path,(my_string) path)); - size = STARTSIZE; #if defined(__amiga__) if ((dirp->dd_fd) < 0) /* Directory doesn't exists */ goto error; #endif - if (dirp == NULL || ! (buffer = (char *) my_malloc(size, MyFlags))) + if (dirp == NULL || + ! (buffer= my_malloc(ALIGN_SIZE(sizeof(MY_DIR)) + + ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)) + + sizeof(MEM_ROOT), MyFlags))) + goto error; + + dir_entries_storage= (DYNAMIC_ARRAY*)(buffer + ALIGN_SIZE(sizeof(MY_DIR))); + names_storage= (MEM_ROOT*)(buffer + ALIGN_SIZE(sizeof(MY_DIR)) + + ALIGN_SIZE(sizeof(DYNAMIC_ARRAY))); + + if (my_init_dynamic_array(dir_entries_storage, sizeof(FILEINFO), + ENTRIES_START_SIZE, ENTRIES_INCREMENT)) + { + my_free((gptr) buffer,MYF(0)); goto error; + } + init_alloc_root(names_storage, NAMES_START_SIZE, NAMES_START_SIZE); + + /* MY_DIR structure is allocated and completly initialized at this point */ + result= (MY_DIR*)buffer; - fcnt = 0; tmp_file=strend(tmp_path); - firstfcnt = maxfcnt = (size - sizeof(MY_DIR)) / - (sizeof(struct fileinfo) + FN_LEN); - fnames= (struct fileinfo *) (buffer + sizeof(MY_DIR)); - tempptr = (char *) (fnames + maxfcnt); #ifdef THREAD dp= (struct dirent*) dirent_tmp; #else dp=0; #endif - eof=0; - for (;;) + + while (!(READDIR(dirp,(struct dirent*) dirent_tmp,dp))) { - while (fcnt < maxfcnt && - !(eof= READDIR(dirp,(struct dirent*) dirent_tmp,dp))) + if (!(finfo.name= strdup_root(names_storage, dp->d_name))) + goto error; + + if (MyFlags & MY_WANT_STAT) { - bzero((gptr) (fnames+fcnt),sizeof(fnames[0])); /* for purify */ - fnames[fcnt].name = tempptr; - tempptr = strmov(tempptr,dp->d_name) + 1; - if (MyFlags & MY_WANT_STAT) - { - VOID(strmov(tmp_file,dp->d_name)); - VOID(my_stat(tmp_path, &fnames[fcnt].mystat, MyFlags)); - } - ++fcnt; + if (!(finfo.mystat= (MY_STAT*)alloc_root(names_storage, + sizeof(MY_STAT)))) + goto error; + + bzero(finfo.mystat, sizeof(MY_STAT)); + VOID(strmov(tmp_file,dp->d_name)); + VOID(my_stat(tmp_path, finfo.mystat, MyFlags)); } - if (eof) - break; - size += STARTSIZE; obuffer = buffer; - if (!(buffer = (char *) my_realloc((gptr) buffer, size, - MyFlags | MY_FREE_ON_ERROR))) - goto error; /* No memory */ - length= (uint) (sizeof(struct fileinfo ) * firstfcnt); - diff= PTR_BYTE_DIFF(buffer , obuffer) + (int) length; - fnames= (struct fileinfo *) (buffer + sizeof(MY_DIR)); - tempptr= ADD_TO_PTR(tempptr,diff,char*); - for (i = 0; i < maxfcnt; i++) - fnames[i].name = ADD_TO_PTR(fnames[i].name,diff,char*); - - /* move filenames upp a bit */ - maxfcnt += firstfcnt; - bmove_upp(tempptr,tempptr-length, - (uint) (tempptr- (char*) (fnames+maxfcnt))); + else + finfo.mystat= NULL; + + if (push_dynamic(dir_entries_storage, (gptr)&finfo)) + goto error; } (void) closedir(dirp); - { - MY_DIR * s = (MY_DIR *) buffer; - s->number_off_files = (uint) fcnt; - s->dir_entry = fnames; - } - if (!(MyFlags & MY_DONT_SORT)) - qsort((void *) fnames, (size_s) fcnt, sizeof(struct fileinfo), - (qsort_cmp) comp_names); #if defined(THREAD) && !defined(HAVE_READDIR_R) pthread_mutex_unlock(&THR_LOCK_open); #endif - DBUG_RETURN((MY_DIR *) buffer); + result->dir_entry= (FILEINFO *)dir_entries_storage->buffer; + result->number_off_files= dir_entries_storage->elements; + + if (!(MyFlags & MY_DONT_SORT)) + qsort((void *) result->dir_entry, result->number_off_files, + sizeof(FILEINFO), (qsort_cmp) comp_names); + DBUG_RETURN(result); error: #if defined(THREAD) && !defined(HAVE_READDIR_R) @@ -186,6 +197,7 @@ MY_DIR *my_dir(const char *path, myf MyFlags) my_errno=errno; if (dirp) (void) closedir(dirp); + my_dirend(result); if (MyFlags & (MY_FAE | MY_WME)) my_error(EE_DIR,MYF(ME_BELL+ME_WAITTANG),path,my_errno); DBUG_RETURN((MY_DIR *) NULL); @@ -349,10 +361,11 @@ my_string directory_file_name (my_string dst, const char *src) MY_DIR *my_dir(const char *path, myf MyFlags) { - struct fileinfo *fnames; - char *buffer, *obuffer, *tempptr; - int eof,i,fcnt,firstfcnt,length,maxfcnt; - uint size; + char *buffer; + MY_DIR *result= 0; + FILEINFO finfo; + DYNAMIC_ARRAY *dir_entries_storage; + MEM_ROOT *names_storage; #ifdef __BORLANDC__ struct ffblk find; #else @@ -360,7 +373,6 @@ MY_DIR *my_dir(const char *path, myf MyFlags) #endif ushort mode; char tmp_path[FN_REFLEN],*tmp_file,attrib; - my_ptrdiff_t diff; #ifdef _WIN64 __int64 handle; #else @@ -392,85 +404,88 @@ MY_DIR *my_dir(const char *path, myf MyFlags) goto error; #endif - size = STARTSIZE; - firstfcnt = maxfcnt = (size - sizeof(MY_DIR)) / - (sizeof(struct fileinfo) + FN_LEN); - if ((buffer = (char *) my_malloc(size, MyFlags)) == 0) + if (!(buffer= my_malloc(ALIGN_SIZE(sizeof(MY_DIR)) + + ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)) + + sizeof(MEM_ROOT), MyFlags))) goto error; - fnames= (struct fileinfo *) (buffer + sizeof(MY_DIR)); - tempptr = (char *) (fnames + maxfcnt); - fcnt = 0; - for (;;) + dir_entries_storage= (DYNAMIC_ARRAY*)(buffer + ALIGN_SIZE(sizeof(MY_DIR))); + names_storage= (MEM_ROOT*)(buffer + ALIGN_SIZE(sizeof(MY_DIR)) + + ALIGN_SIZE(sizeof(DYNAMIC_ARRAY))); + + if (my_init_dynamic_array(dir_entries_storage, sizeof(FILEINFO), + ENTRIES_START_SIZE, ENTRIES_INCREMENT)) + { + my_free((gptr) buffer,MYF(0)); + goto error; + } + init_alloc_root(names_storage, NAMES_START_SIZE, NAMES_START_SIZE); + + /* MY_DIR structure is allocated and completly initialized at this point */ + result= (MY_DIR*)buffer; + + do { - do +#ifdef __BORLANDC__ + if (!(finfo.name= strdup_root(names_storage, find.ff_name))) + goto error; +#else + if (!(finfo.name= strdup_root(names_storage, find.name))) + goto error; +#endif + if (MyFlags & MY_WANT_STAT) { - fnames[fcnt].name = tempptr; + if (!(finfo.mystat= (MY_STAT*)alloc_root(names_storage, + sizeof(MY_STAT)))) + goto error; + + bzero(finfo.mystat, sizeof(MY_STAT)); #ifdef __BORLANDC__ - tempptr = strmov(tempptr,find.ff_name) + 1; - fnames[fcnt].mystat.st_size=find.ff_fsize; - fnames[fcnt].mystat.st_uid=fnames[fcnt].mystat.st_gid=0; + finfo.mystat->st_size=find.ff_fsize; mode=MY_S_IREAD; attrib=find.ff_attrib; #else - tempptr = strmov(tempptr,find.name) + 1; - fnames[fcnt].mystat.st_size=find.size; - fnames[fcnt].mystat.st_uid=fnames[fcnt].mystat.st_gid=0; + finfo.mystat->st_size=find.size; mode=MY_S_IREAD; attrib=find.attrib; #endif if (!(attrib & _A_RDONLY)) mode|=MY_S_IWRITE; if (attrib & _A_SUBDIR) mode|=MY_S_IFDIR; - fnames[fcnt].mystat.st_mode=mode; -#ifdef __BORLANDC__ - fnames[fcnt].mystat.st_mtime=((uint32) find.ff_ftime); -#else - fnames[fcnt].mystat.st_mtime=((uint32) find.time_write); -#endif - ++fcnt; + finfo.mystat->st_mode=mode; #ifdef __BORLANDC__ - } while ((eof= findnext(&find)) == 0 && fcnt < maxfcnt); + finfo.mystat->st_mtime=((uint32) find.ff_ftime); #else - } while ((eof= _findnext(handle,&find)) == 0 && fcnt < maxfcnt); + finfo.mystat->st_mtime=((uint32) find.time_write); #endif + } + else + finfo.mystat= NULL; - DBUG_PRINT("test",("eof: %d errno: %d",eof,errno)); - if (eof) - break; - size += STARTSIZE; obuffer = buffer; - if (!(buffer = (char *) my_realloc((gptr) buffer, size, - MyFlags | MY_FREE_ON_ERROR))) + if (push_dynamic(dir_entries_storage, (gptr)&finfo)) goto error; - length= sizeof(struct fileinfo ) * firstfcnt; - diff= PTR_BYTE_DIFF(buffer , obuffer) +length; - fnames= (struct fileinfo *) (buffer + sizeof(MY_DIR)); - tempptr= ADD_TO_PTR(tempptr,diff,char*); - for (i = 0; i < maxfcnt; i++) - fnames[i].name = ADD_TO_PTR(fnames[i].name,diff,char*); - - /* move filenames upp a bit */ - maxfcnt += firstfcnt; - bmove_upp(tempptr,ADD_TO_PTR(tempptr,-length,char*), - (int) PTR_BYTE_DIFF(tempptr,fnames+maxfcnt)); - } - { - MY_DIR * s = (MY_DIR *) buffer; - s->number_off_files = (uint) fcnt; - s->dir_entry = fnames; - } - if (!(MyFlags & MY_DONT_SORT)) - qsort(fnames,fcnt,sizeof(struct fileinfo),(qsort_cmp) comp_names); -#ifndef __BORLANDC__ + +#ifdef __BORLANDC__ + } while (findnext(&find) == 0); +#else + } while (_findnext(handle,&find) == 0); + _findclose(handle); #endif - DBUG_RETURN((MY_DIR *) buffer); + result->dir_entry= (FILEINFO *)dir_entries_storage->buffer; + result->number_off_files= dir_entries_storage->elements; + + if (!(MyFlags & MY_DONT_SORT)) + qsort((void *) result->dir_entry, result->number_off_files, + sizeof(FILEINFO), (qsort_cmp) comp_names); + DBUG_RETURN(result); error: my_errno=errno; #ifndef __BORLANDC__ if (handle != -1) _findclose(handle); #endif + my_dirend(result); if (MyFlags & MY_FAE+MY_WME) my_error(EE_DIR,MYF(ME_BELL+ME_WAITTANG),path,errno); DBUG_RETURN((MY_DIR *) NULL); @@ -485,14 +500,14 @@ error: MY_DIR *my_dir(const char* path, myf MyFlags) { - struct fileinfo *fnames; - char *buffer, *obuffer, *tempptr; - int eof,i,fcnt,firstfcnt,length,maxfcnt; - uint size; + char *buffer; + MY_DIR *result= 0; + FILEINFO finfo; + DYNAMIC_ARRAY *dir_entries_storage; + MEM_ROOT *names_storage; struct find_t find; ushort mode; char tmp_path[FN_REFLEN],*tmp_file,attrib; - my_ptrdiff_t diff; DBUG_ENTER("my_dir"); DBUG_PRINT("my",("path: '%s' stat: %d MyFlags: %d",path,MyFlags)); @@ -514,63 +529,65 @@ MY_DIR *my_dir(const char* path, myf MyFlags) if (_dos_findfirst(tmp_path,_A_NORMAL | _A_SUBDIR, &find)) goto error; - size = STARTSIZE; - firstfcnt = maxfcnt = (size - sizeof(MY_DIR)) / - (sizeof(struct fileinfo) + FN_LEN); - if ((buffer = (char *) my_malloc(size, MyFlags)) == 0) + if (!(buffer= my_malloc(ALIGN_SIZE(sizeof(MY_DIR)) + + ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)) + + sizeof(MEM_ROOT), MyFlags))) goto error; - fnames= (struct fileinfo *) (buffer + sizeof(MY_DIR)); - tempptr = (char *) (fnames + maxfcnt); - fcnt = 0; - for (;;) + dir_entries_storage= (DYNAMIC_ARRAY*)(buffer + ALIGN_SIZE(sizeof(MY_DIR))); + names_storage= (MEM_ROOT*)(buffer + ALIGN_SIZE(sizeof(MY_DIR)) + + ALIGN_SIZE(sizeof(DYNAMIC_ARRAY))); + + if (my_init_dynamic_array(dir_entries_storage, sizeof(FILEINFO), + ENTRIES_START_SIZE, ENTRIES_INCREMENT)) + { + my_free((gptr) buffer,MYF(0)); + goto error; + } + init_alloc_root(names_storage, NAMES_START_SIZE, NAMES_START_SIZE); + + /* MY_DIR structure is allocated and completly initialized at this point */ + result= (MY_DIR*)buffer; + + do { - do + if (!(finfo.name= strdup_root(names_storage, find.name))) + goto error; + + if (MyFlags & MY_WANT_STAT) { - fnames[fcnt].name = tempptr; - tempptr = strmov(tempptr,find.name) + 1; - fnames[fcnt].mystat.st_size=find.size; - fnames[fcnt].mystat.st_uid=fnames[fcnt].mystat.st_gid=0; - mode=MY_S_IREAD; attrib=find.attrib; + if (!(finfo.mystat= (MY_STAT*)alloc_root(names_storage, + sizeof(MY_STAT)))) + goto error; + + bzero(finfo.mystat, sizeof(MY_STAT)); + finfo.mystat->st_size= find.size; + mode= MY_S_IREAD; attrib= find.attrib; if (!(attrib & _A_RDONLY)) - mode|=MY_S_IWRITE; + mode|= MY_S_IWRITE; if (attrib & _A_SUBDIR) - mode|=MY_S_IFDIR; - fnames[fcnt].mystat.st_mode=mode; - fnames[fcnt].mystat.st_mtime=((uint32) find.wr_date << 16) + - find.wr_time; - ++fcnt; - } while ((eof= _dos_findnext(&find)) == 0 && fcnt < maxfcnt); - - DBUG_PRINT("test",("eof: %d errno: %d",eof,errno)); - if (eof) - break; - size += STARTSIZE; obuffer = buffer; - if (!(buffer = (char *) my_realloc((gptr) buffer, size, - MyFlags | MY_FREE_ON_ERROR))) + mode|= MY_S_IFDIR; + finfo.mystat->st_mode= mode; + finfo.mystat->st_mtime= ((uint32) find.wr_date << 16) + find.wr_time; + } + else + finfo.mystat= NULL; + + if (push_dynamic(dir_entries_storage, (gptr)&finfo)) goto error; - length= sizeof(struct fileinfo ) * firstfcnt; - diff= PTR_BYTE_DIFF(buffer , obuffer) +length; - fnames= (struct fileinfo *) (buffer + sizeof(MY_DIR)); - tempptr= ADD_TO_PTR(tempptr,diff,char*); - for (i = 0; i < maxfcnt; i++) - fnames[i].name = ADD_TO_PTR(fnames[i].name,diff,char*); - - /* move filenames upp a bit */ - maxfcnt += firstfcnt; - bmove_upp(tempptr,ADD_TO_PTR(tempptr,-length,char*), - (int) PTR_BYTE_DIFF(tempptr,fnames+maxfcnt)); - } - { - MY_DIR * s = (MY_DIR *) buffer; - s->number_off_files = (uint) fcnt; - s->dir_entry = fnames; - } + + } while (_dos_findnext(&find) == 0); + + result->dir_entry= (FILEINFO *)dir_entries_storage->buffer; + result->number_off_files= dir_entries_storage->elements; + if (!(MyFlags & MY_DONT_SORT)) - qsort(fnames,fcnt,sizeof(struct fileinfo),(qsort_cmp) comp_names); - DBUG_RETURN((MY_DIR *) buffer); + qsort((void *) result->dir_entry, result->number_off_files, + sizeof(FILEINFO), (qsort_cmp) comp_names); + DBUG_RETURN(result); error: + my_dirend(result); if (MyFlags & MY_FAE+MY_WME) my_error(EE_DIR,MYF(ME_BELL+ME_WAITTANG),path,errno); DBUG_RETURN((MY_DIR *) NULL); @@ -602,9 +619,11 @@ MY_STAT *my_stat(const char *path, MY_STAT *stat_area, myf my_flags) if ((m_used= (stat_area == NULL))) if (!(stat_area = (MY_STAT *) my_malloc(sizeof(MY_STAT), my_flags))) goto error; - if ( ! stat((my_string) path, (struct stat *) stat_area) ) + if (! stat((my_string) path, (struct stat *) stat_area) ) DBUG_RETURN(stat_area); - my_errno=errno; + + DBUG_PRINT("error",("Got errno: %d from stat", errno)); + my_errno= errno; if (m_used) /* Free if new area */ my_free((gptr) stat_area,MYF(0)); diff --git a/mysys/my_symlink.c b/mysys/my_symlink.c index b9468d42cfc..045802c5e61 100644 --- a/mysys/my_symlink.c +++ b/mysys/my_symlink.c @@ -72,6 +72,7 @@ int my_symlink(const char *content, const char *linkname, myf MyFlags) #else int result; DBUG_ENTER("my_symlink"); + DBUG_PRINT("enter",("content: %s linkname: %s", content, linkname)); result= 0; if (symlink(content, linkname)) diff --git a/mysys/my_symlink2.c b/mysys/my_symlink2.c index 68b034bec5c..913f632fbb4 100644 --- a/mysys/my_symlink2.c +++ b/mysys/my_symlink2.c @@ -31,9 +31,19 @@ File my_create_with_symlink(const char *linkname, const char *filename, File file; int tmp_errno; /* Test if we should create a link */ - int create_link=(linkname && strcmp(linkname,filename)); + int create_link; DBUG_ENTER("my_create_with_symlink"); + if (my_disable_symlinks) + { + /* Create only the file, not the link and file */ + create_link= 0; + if (linkname) + filename= linkname; + } + else + create_link= (linkname && strcmp(linkname,filename)); + if (!(MyFlags & MY_DELETE_OLD)) { if (!access(filename,F_OK)) diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c index 1d4219e7bfb..237eeefa325 100644 --- a/mysys/my_thr_init.c +++ b/mysys/my_thr_init.c @@ -44,12 +44,23 @@ pthread_mutexattr_t my_fast_mutexattr; pthread_mutexattr_t my_errchk_mutexattr; #endif +/* + initialize thread environment + + SYNOPSIS + my_thread_global_init() + + RETURN + 0 ok + 1 error (Couldn't create THR_KEY_mysys) +*/ + my_bool my_thread_global_init(void) { - if (pthread_key_create(&THR_KEY_mysys,free)) + if (pthread_key_create(&THR_KEY_mysys,0)) { fprintf(stderr,"Can't initialize threads: error %d\n",errno); - exit(1); + return 1; } #ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP pthread_mutexattr_init(&my_fast_mutexattr); @@ -78,15 +89,18 @@ my_bool my_thread_global_init(void) #ifndef HAVE_GETHOSTBYNAME_R pthread_mutex_init(&LOCK_gethostbyname_r,MY_MUTEX_INIT_SLOW); #endif - return my_thread_init(); + if (my_thread_init()) + { + my_thread_global_end(); /* Clean up */ + return 1; + } + return 0; } void my_thread_global_end(void) { -#if defined(USE_TLS) - (void) TlsFree(THR_KEY_mysys); -#endif + pthread_key_delete(THR_KEY_mysys); #ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP pthread_mutexattr_destroy(&my_fast_mutexattr); #endif @@ -155,6 +169,9 @@ my_bool my_thread_init(void) tmp= &THR_KEY_mysys; #endif tmp->id= ++thread_id; +#if defined(__WIN__) && defined(EMBEDDED_LIBRARY) + tmp->thread_self= (pthread_t)getpid(); +#endif pthread_mutex_init(&tmp->mutex,MY_MUTEX_INIT_FAST); pthread_cond_init(&tmp->suspend, NULL); tmp->init= 1; diff --git a/regex/reginit.c b/regex/reginit.c index 09ffff37ef0..74ad3dc6de4 100644 --- a/regex/reginit.c +++ b/regex/reginit.c @@ -49,6 +49,16 @@ void regex_init(CHARSET_INFO *cs) for (i=0; i < CCLASS_LAST ; i++) { char *tmp=(char*) malloc(count[i]+1); + if (!tmp) + { + /* + This is very unlikely to happen as this function is called once + at program startup + */ + fprintf(stderr, + "Fatal error: Can't allocate memory in regex_init\n"); + exit(1); + } memcpy(tmp,buff[i],count[i]*sizeof(char)); tmp[count[i]]=0; cclasses[i].chars=tmp; diff --git a/sql-common/client.c b/sql-common/client.c index 374cbb29112..14b45942e15 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -967,7 +967,8 @@ void mysql_read_default_options(struct st_mysql_options *options, #endif break; case 27: - options->max_allowed_packet= atoi(opt_arg); + if (opt_arg) + options->max_allowed_packet= atoi(opt_arg); break; case 28: /* protocol */ if ((options->protocol = find_type(opt_arg, @@ -1310,7 +1311,8 @@ read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths) MYSQL * STDCALL mysql_init(MYSQL *mysql) { - mysql_once_init(); + if (mysql_server_init(0, NULL, NULL)) + return 0; if (!mysql) { if (!(mysql=(MYSQL*) my_malloc(sizeof(*mysql),MYF(MY_WME | MY_ZEROFILL)))) diff --git a/sql/client_settings.h b/sql/client_settings.h index b357e52ec9d..a8cd36af102 100644 --- a/sql/client_settings.h +++ b/sql/client_settings.h @@ -32,3 +32,5 @@ #undef HAVE_SMEM #undef _CUSTOMCONFIG_ +#define mysql_server_init(a,b,c) 0 + diff --git a/sql/field.cc b/sql/field.cc index 237427a9d80..a9029b893e3 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -791,7 +791,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs) if (zerofill) { left_wall=to-1; - while (pos != left_wall) // Fill with zeros + while (pos > left_wall) // Fill with zeros *pos--='0'; } else @@ -799,7 +799,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs) left_wall=to+(sign_char != 0)-1; if (!expo_sign_char) // If exponent was specified, ignore prezeros { - for (;pos != left_wall && pre_zeros_from !=pre_zeros_end; + for (;pos > left_wall && pre_zeros_from !=pre_zeros_end; pre_zeros_from++) *pos--= '0'; } @@ -1016,7 +1016,7 @@ int Field_decimal::cmp(const char *a_ptr,const char *b_ptr) return 0; if (*a_ptr == '-') return -1; - else if (*b_ptr == '-') + if (*b_ptr == '-') return 1; while (a_ptr != end) @@ -2853,34 +2853,72 @@ int Field_timestamp::store(double nr) function. */ -static longlong fix_datetime(longlong nr) +static longlong fix_datetime(longlong nr, TIME *time_res, + const char *field_name, bool *error) { - current_thd->last_cuted_field= 0; + long part1,part2; + + *error= 0; if (nr == LL(0) || nr >= LL(10000101000000)) - return nr; // Normal datetime >= Year 1000 + goto ok; if (nr < 101) goto err; if (nr <= (YY_PART_YEAR-1)*10000L+1231L) - return (nr+20000000L)*1000000L; // YYMMDD, year: 2000-2069 + { + nr= (nr+20000000L)*1000000L; // YYMMDD, year: 2000-2069 + goto ok; + } if (nr < (YY_PART_YEAR)*10000L+101L) goto err; if (nr <= 991231L) - return (nr+19000000L)*1000000L; // YYMMDD, year: 1970-1999 + { + nr= (nr+19000000L)*1000000L; // YYMMDD, year: 1970-1999 + goto ok; + } if (nr < 10000101L) goto err; if (nr <= 99991231L) - return nr*1000000L; + { + nr= nr*1000000L; + goto ok; + } if (nr < 101000000L) goto err; if (nr <= (YY_PART_YEAR-1)*LL(10000000000)+LL(1231235959)) - return nr+LL(20000000000000); // YYMMDDHHMMSS, 2000-2069 + { + nr= nr+LL(20000000000000); // YYMMDDHHMMSS, 2000-2069 + goto ok; + } if (nr < YY_PART_YEAR*LL(10000000000)+ LL(101000000)) goto err; if (nr <= LL(991231235959)) - return nr+LL(19000000000000); // YYMMDDHHMMSS, 1970-1999 - + nr= nr+LL(19000000000000); // YYMMDDHHMMSS, 1970-1999 + + ok: + part1=(long) (nr/LL(1000000)); + part2=(long) (nr - (longlong) part1*LL(1000000)); + time_res->year= (int) (part1/10000L); part1%=10000L; + time_res->month= (int) part1 / 100; + time_res->day= (int) part1 % 100; + time_res->hour= (int) (part2/10000L); part2%=10000L; + time_res->minute=(int) part2 / 100; + time_res->second=(int) part2 % 100; + + if (time_res->year <= 9999 && time_res->month <= 12 && + time_res->day <= 31 && time_res->hour <= 23 && + time_res->minute <= 59 && time_res->second <= 59) + return nr; + err: - current_thd->last_cuted_field= 1; + THD *thd= current_thd; + if (thd->count_cuted_fields) + { + thd->cuted_fields++; + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WARN_DATA_TRUNCATED, ER(ER_WARN_DATA_TRUNCATED), + field_name, thd->row_count); + } + *error= 1; return LL(0); } @@ -2888,24 +2926,17 @@ static longlong fix_datetime(longlong nr) int Field_timestamp::store(longlong nr) { TIME l_time; - time_t timestamp; - long part1,part2; + time_t timestamp= 0; + bool error; - if ((nr=fix_datetime(nr))) + if ((nr= fix_datetime(nr, &l_time, field_name, &error))) { long not_used; - part1=(long) (nr/LL(1000000)); - part2=(long) (nr - (longlong) part1*LL(1000000)); - l_time.year= (int) (part1/10000L); part1%=10000L; - l_time.month= (int) part1 / 100; - l_time.day= (int) part1 % 100; - l_time.hour= (int) (part2/10000L); part2%=10000L; - l_time.minute=(int) part2 / 100; - l_time.second=(int) part2 % 100; - timestamp=my_gmt_sec(&l_time, ¬_used); - } - else - timestamp=0; + + if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR-1) + goto err; + timestamp= my_gmt_sec(&l_time, ¬_used); + } #ifdef WORDS_BIGENDIAN if (table->db_low_byte_first) { @@ -2914,9 +2945,12 @@ int Field_timestamp::store(longlong nr) else #endif longstore(ptr,(uint32) timestamp); - if (current_thd->last_cuted_field) - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED); - return 0; + return error; + +err: + longstore(ptr,(uint32) 0); + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED); + return 1; } @@ -3350,7 +3384,7 @@ int Field_year::store(const char *from, uint len,CHARSET_INFO *cs) set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE); return 1; } - else if (current_thd->count_cuted_fields && !test_if_int(from,len,end,cs)) + if (current_thd->count_cuted_fields && !test_if_int(from,len,end,cs)) set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED); if (nr != 0 || len != 4) { @@ -3363,6 +3397,7 @@ int Field_year::store(const char *from, uint len,CHARSET_INFO *cs) return 0; } + int Field_year::store(double nr) { if (nr < 0.0 || nr >= 2155.0) @@ -3825,15 +3860,10 @@ int Field_datetime::store(double nr) int Field_datetime::store(longlong nr) { - int error= 0; - if (nr < 0 || nr > LL(99991231235959)) - { - nr=0; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE); - error= 1; - } - else - nr=fix_datetime(nr); + TIME not_used; + bool error; + + nr= fix_datetime(nr, ¬_used, field_name, &error); #ifdef WORDS_BIGENDIAN if (table->db_low_byte_first) { @@ -3842,11 +3872,10 @@ int Field_datetime::store(longlong nr) else #endif longlongstore(ptr,nr); - if (current_thd->last_cuted_field) - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED); return error; } + void Field_datetime::store_time(TIME *ltime,timestamp_type type) { longlong tmp; @@ -5064,7 +5093,7 @@ int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs) uint tmp=find_type(typelib, from, length, 0); if (!tmp) { - if (length < 6) // Can't be more than 99999 enums + if (length < 6) // Can't be more than 99999 enums { /* This is for reading numbers with LOAD DATA INFILE */ char *end; @@ -5159,7 +5188,7 @@ String *Field_enum::val_str(String *val_buffer __attribute__((unused)), { uint tmp=(uint) Field_enum::val_int(); if (!tmp || tmp > typelib->count) - val_ptr->length(0); + val_ptr->set("", 0, field_charset); else val_ptr->set((const char*) typelib->type_names[tmp-1], (uint) strlen(typelib->type_names[tmp-1]), @@ -5224,12 +5253,13 @@ void Field_enum::sql_type(String &res) const int Field_set::store(const char *from,uint length,CHARSET_INFO *cs) { - bool set_warning= 0; + bool got_warning= 0; int err= 0; char *not_used; uint not_used2; char buff[80]; String tmpstr(buff,sizeof(buff), &my_charset_bin); + /* Convert character set if nesessary */ if (use_conversion(cs, field_charset)) { @@ -5238,7 +5268,7 @@ int Field_set::store(const char *from,uint length,CHARSET_INFO *cs) length= tmpstr.length(); } ulonglong tmp= find_set(typelib, from, length, ¬_used, ¬_used2, - &set_warning); + &got_warning); if (!tmp && length && length < 22) { /* This is for reading numbers with LOAD DATA INFILE */ @@ -5248,16 +5278,11 @@ int Field_set::store(const char *from,uint length,CHARSET_INFO *cs) tmp > (ulonglong) (((longlong) 1 << typelib->count) - (longlong) 1)) { tmp=0; - THD *thd= current_thd; - if (thd->count_cuted_fields) - { - thd->cuted_fields++; - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_WARN_DATA_TRUNCATED, ER(ER_WARN_DATA_TRUNCATED), - field_name, 0); - } + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED); } } + else if (got_warning) + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED); store_type(tmp); return err; } diff --git a/sql/field.h b/sql/field.h index 508fbad41a1..e3b4bf29fb8 100644 --- a/sql/field.h +++ b/sql/field.h @@ -872,11 +872,14 @@ public: enum utype unireg_check_arg, const char *field_name_arg, struct st_table *table_arg, CHARSET_INFO *cs) :Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, - unireg_check_arg, field_name_arg, table_arg, cs) {}; - Field_varstring(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg, + unireg_check_arg, field_name_arg, table_arg, cs) + {} + Field_varstring(uint32 len_arg,bool maybe_null_arg, + const char *field_name_arg, struct st_table *table_arg, CHARSET_INFO *cs) :Field_str((char*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0,0, - NONE, field_name_arg, table_arg, cs) {}; + NONE, field_name_arg, table_arg, cs) + {} enum_field_types type() const { return FIELD_TYPE_VAR_STRING; } enum ha_base_keytype key_type() const @@ -924,9 +927,9 @@ public: :Field_str((char*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0,0, NONE, field_name_arg, table_arg, cs), geom_flag(true), packlength(4) - { - flags|= BLOB_FLAG; - } + { + flags|= BLOB_FLAG; + } enum_field_types type() const { return FIELD_TYPE_BLOB;} enum ha_base_keytype key_type() const { return binary() ? HA_KEYTYPE_VARBINARY : HA_KEYTYPE_VARTEXT; } diff --git a/sql/filesort.cc b/sql/filesort.cc index 27c59a05941..f97126017cc 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -792,6 +792,39 @@ uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek, } /* read_to_buffer */ +/* + Put all room used by freed buffer to use in adjacent buffer. Note, that + we can't simply distribute memory evenly between all buffers, because + new areas must not overlap with old ones. + SYNOPSYS + reuse_freed_buff() + queue IN list of non-empty buffers, without freed buffer + reuse IN empty buffer + key_length IN key length +*/ + +void reuse_freed_buff(QUEUE *queue, BUFFPEK *reuse, uint key_length) +{ + uchar *reuse_end= reuse->base + reuse->max_keys * key_length; + for (uint i= 0; i < queue->elements; ++i) + { + BUFFPEK *bp= (BUFFPEK *) queue_element(queue, i); + if (bp->base + bp->max_keys * key_length == reuse->base) + { + bp->max_keys+= reuse->max_keys; + return; + } + else if (bp->base == reuse_end) + { + bp->base= reuse->base; + bp->max_keys+= reuse->max_keys; + return; + } + } + DBUG_ASSERT(0); +} + + /* Merge buffers to one buffer */ @@ -917,29 +950,8 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, if (!(error= (int) read_to_buffer(from_file,buffpek, rec_length))) { - uchar *base= buffpek->base; - ulong max_keys= buffpek->max_keys; - VOID(queue_remove(&queue,0)); - - /* Put room used by buffer to use in other buffer */ - for (refpek= (BUFFPEK**) &queue_top(&queue); - refpek <= (BUFFPEK**) &queue_end(&queue); - refpek++) - { - buffpek= *refpek; - if (buffpek->base+buffpek->max_keys*rec_length == base) - { - buffpek->max_keys+= max_keys; - break; - } - else if (base+max_keys*rec_length == buffpek->base) - { - buffpek->base= base; - buffpek->max_keys+= max_keys; - break; - } - } + reuse_freed_buff(&queue, buffpek, rec_length); break; /* One buffer have been removed */ } else if (error == -1) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index d949f8bcf9c..56bb5d4f1ae 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -33,11 +33,9 @@ InnoDB */ #include "mysql_priv.h" #include "slave.h" -#include "sql_cache.h" #ifdef HAVE_INNOBASE_DB #include <m_ctype.h> -#include <assert.h> #include <hash.h> #include <myisampack.h> @@ -1860,7 +1858,7 @@ ha_innobase::store_key_val_for_row( || mysql_type == FIELD_TYPE_BLOB || mysql_type == FIELD_TYPE_LONG_BLOB) { - ut_a(key_part->key_part_flag & HA_PART_KEY); + ut_a(key_part->key_part_flag & HA_PART_KEY_SEG); if (is_null) { buff += key_part->length + 2; @@ -3348,7 +3346,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/ha_myisam.cc b/sql/ha_myisam.cc index 6356f209ba2..1a597415ff3 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -390,7 +390,7 @@ int ha_myisam::analyze(THD *thd, HA_CHECK_OPT* check_opt) int ha_myisam::restore(THD* thd, HA_CHECK_OPT *check_opt) { HA_CHECK_OPT tmp_check_opt; - char* backup_dir = thd->lex->backup_dir; + char* backup_dir= thd->lex->backup_dir; char src_path[FN_REFLEN], dst_path[FN_REFLEN]; char* table_name = table->real_name; int error; @@ -430,7 +430,7 @@ int ha_myisam::restore(THD* thd, HA_CHECK_OPT *check_opt) int ha_myisam::backup(THD* thd, HA_CHECK_OPT *check_opt) { - char* backup_dir = thd->lex->backup_dir; + char* backup_dir= thd->lex->backup_dir; char src_path[FN_REFLEN], dst_path[FN_REFLEN]; char* table_name = table->real_name; int error; diff --git a/sql/handler.cc b/sql/handler.cc index fe168d12fce..e9eecabaa84 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -104,7 +104,7 @@ enum db_type ha_resolve_by_name(const char *name, uint namelen) return DB_TYPE_UNKNOWN; } -const char *ha_get_table_type(enum db_type db_type) +const char *ha_get_storage_engine(enum db_type db_type) { show_table_type_st *types; for (types= sys_table_types; types->type; types++) diff --git a/sql/handler.h b/sql/handler.h index 2ad37233c9e..4a8abf5f131 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -399,7 +399,7 @@ extern TYPELIB tx_isolation_typelib; #define ha_supports_generate(T) (T != DB_TYPE_INNODB) enum db_type ha_resolve_by_name(const char *name, uint namelen); -const char *ha_get_table_type(enum db_type db_type); +const char *ha_get_storage_engine(enum db_type db_type); handler *get_new_handler(TABLE *table, enum db_type db_type); my_off_t ha_get_ptr(byte *ptr, uint pack_length); void ha_store_ptr(byte *buff, uint pack_length, my_off_t pos); diff --git a/sql/item.cc b/sql/item.cc index e4023afe8a7..acb2fdbb40a 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -54,7 +54,7 @@ Item::Item(): thd->free_list= this; /* Item constructor can be called during execution other then SQL_COM - command => we should check thd->lex.current_select on zero (thd->lex + command => we should check thd->lex->current_select on zero (thd->lex can be uninitialised) */ if (thd->lex->current_select) @@ -102,6 +102,14 @@ void Item::print_item_w_name(String *str) } +Item_ident::Item_ident(const char *db_name_par,const char *table_name_par, + const char *field_name_par) + :db_name(db_name_par),table_name(table_name_par),field_name(field_name_par), + depended_from(0) +{ + name = (char*) field_name_par; +} + // Constructor used by Item_field & Item_ref (see Item comment) Item_ident::Item_ident(THD *thd, Item_ident &item): Item(thd, item), @@ -676,10 +684,10 @@ String *Item_param::val_str(String* str) { switch (item_result_type) { case INT_RESULT: - str->set(int_value, default_charset()); + str->set(int_value, &my_charset_bin); return str; case REAL_RESULT: - str->set(real_value, 2, default_charset()); + str->set(real_value, 2, &my_charset_bin); return str; default: return (String*) &str_value; @@ -865,7 +873,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) Item **refer= (Item **)not_found_item; uint counter; // Prevent using outer fields in subselects, that is not supported now - SELECT_LEX *cursel=(SELECT_LEX *) thd->lex->current_select; + SELECT_LEX *cursel= (SELECT_LEX *) thd->lex->current_select; if (cursel->master_unit()->first_select()->linkage != DERIVED_TABLE_TYPE) { SELECT_LEX_UNIT *prev_unit= cursel->master_unit(); @@ -1764,12 +1772,11 @@ Item_result item_cmp_type(Item_result a,Item_result b) { if (a == STRING_RESULT && b == STRING_RESULT) return STRING_RESULT; - else if (a == INT_RESULT && b == INT_RESULT) + if (a == INT_RESULT && b == INT_RESULT) return INT_RESULT; else if (a == ROW_RESULT || b == ROW_RESULT) return ROW_RESULT; - else - return REAL_RESULT; + return REAL_RESULT; } diff --git a/sql/item.h b/sql/item.h index d8aea6552c3..4c6be932376 100644 --- a/sql/item.h +++ b/sql/item.h @@ -330,12 +330,8 @@ public: const char *field_name; st_select_lex *depended_from; Item_ident(const char *db_name_par,const char *table_name_par, - const char *field_name_par) - :db_name(db_name_par), table_name(table_name_par), - field_name(field_name_par), depended_from(0) - { name = (char*) field_name_par; } - // Constructor used by Item_field & Item_ref (see Item comment) - Item_ident(THD *thd, Item_ident &item); + const char *field_name_par); + Item_ident::Item_ident(THD *thd, Item_ident &item); const char *full_name() const; bool remove_dependence_processor(byte * arg); diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index bd88c79c8fb..a79ef21e97a 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1723,7 +1723,7 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) if (item->maybe_null) maybe_null=1; } - thd->lex->current_select->cond_count+=list.elements; + thd->lex->current_select->cond_count+= list.elements; fix_length_and_dec(); fixed= 1; return 0; diff --git a/sql/item_create.cc b/sql/item_create.cc index aa64cf52017..cccbf6e4226 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -72,7 +72,7 @@ Item *create_func_ceiling(Item* a) Item *create_func_connection_id(void) { THD *thd=current_thd; - thd->lex->safe_to_cache_query=0; + thd->lex->safe_to_cache_query= 0; return new Item_int(NullS,(longlong) ((thd->slave_thread) ? thd->variables.pseudo_thread_id : @@ -144,7 +144,7 @@ Item *create_func_floor(Item* a) Item *create_func_found_rows(void) { THD *thd=current_thd; - thd->lex->safe_to_cache_query=0; + thd->lex->safe_to_cache_query= 0; return new Item_int(NullS,(longlong) thd->found_rows(),21); } diff --git a/sql/item_func.cc b/sql/item_func.cc index 1552e3ec274..117ffcfca05 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -320,6 +320,7 @@ void Item_func::print_op(String *str) str->append(')'); } + bool Item_func::eq(const Item *item, bool binary_cmp) const { /* Assume we don't have rtti */ @@ -375,8 +376,7 @@ String *Item_real_func::val_str(String *str) double nr=val(); if (null_value) return 0; /* purecov: inspected */ - else - str->set(nr,decimals,default_charset()); + str->set(nr,decimals, &my_charset_bin); return str; } @@ -388,18 +388,17 @@ String *Item_num_func::val_str(String *str) longlong nr=val_int(); if (null_value) return 0; /* purecov: inspected */ - else if (!unsigned_flag) - str->set(nr,default_charset()); + if (!unsigned_flag) + str->set(nr,&my_charset_bin); else - str->set((ulonglong) nr,default_charset()); + str->set((ulonglong) nr,&my_charset_bin); } else { double nr=val(); if (null_value) return 0; /* purecov: inspected */ - else - str->set(nr,decimals,default_charset()); + str->set(nr,decimals,&my_charset_bin); } return str; } @@ -425,10 +424,10 @@ String *Item_int_func::val_str(String *str) longlong nr=val_int(); if (null_value) return 0; - else if (!unsigned_flag) - str->set(nr,default_charset()); + if (!unsigned_flag) + str->set(nr,&my_charset_bin); else - str->set((ulonglong) nr,default_charset()); + str->set((ulonglong) nr,&my_charset_bin); return str; } @@ -454,18 +453,17 @@ String *Item_num_op::val_str(String *str) longlong nr=val_int(); if (null_value) return 0; /* purecov: inspected */ - else if (!unsigned_flag) - str->set(nr,default_charset()); + if (!unsigned_flag) + str->set(nr,&my_charset_bin); else - str->set((ulonglong) nr,default_charset()); + str->set((ulonglong) nr,&my_charset_bin); } else { double nr=val(); if (null_value) return 0; /* purecov: inspected */ - else - str->set(nr,decimals,default_charset()); + str->set(nr,decimals,&my_charset_bin); } return str; } @@ -1035,10 +1033,10 @@ String *Item_func_min_max::val_str(String *str) longlong nr=val_int(); if (null_value) return 0; - else if (!unsigned_flag) - str->set(nr,default_charset()); + if (!unsigned_flag) + str->set(nr,&my_charset_bin); else - str->set((ulonglong) nr,default_charset()); + str->set((ulonglong) nr,&my_charset_bin); return str; } case REAL_RESULT: @@ -1046,8 +1044,7 @@ String *Item_func_min_max::val_str(String *str) double nr=val(); if (null_value) return 0; /* purecov: inspected */ - else - str->set(nr,decimals,default_charset()); + str->set(nr,decimals,&my_charset_bin); return str; } case STRING_RESULT: @@ -1682,8 +1679,7 @@ String *Item_func_udf_float::val_str(String *str) double nr=val(); if (null_value) return 0; /* purecov: inspected */ - else - str->set(nr,decimals,default_charset()); + str->set(nr,decimals,&my_charset_bin); return str; } @@ -1703,10 +1699,10 @@ String *Item_func_udf_int::val_str(String *str) longlong nr=val_int(); if (null_value) return 0; - else if (!unsigned_flag) - str->set(nr,default_charset()); + if (!unsigned_flag) + str->set(nr,&my_charset_bin); else - str->set((ulonglong) nr,default_charset()); + str->set((ulonglong) nr,&my_charset_bin); return str; } diff --git a/sql/item_func.h b/sql/item_func.h index d3cfaf63b5a..c2aa62ec2d7 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -660,25 +660,31 @@ public: void fix_length_and_dec(); }; +/* Base class for all bit functions: '~', '|', '^', '&', '>>', '<<' */ -class Item_func_bit_or :public Item_int_func +class Item_func_bit: public Item_int_func { public: - Item_func_bit_or(Item *a,Item *b) :Item_int_func(a,b) {} + Item_func_bit(Item *a, Item *b) :Item_int_func(a, b) {} + Item_func_bit(Item *a) :Item_int_func(a) {} + void fix_length_and_dec() { unsigned_flag= 1; } + void print(String *str) { print_op(str); } +}; + +class Item_func_bit_or :public Item_func_bit +{ +public: + Item_func_bit_or(Item *a, Item *b) :Item_func_bit(a, b) {} longlong val_int(); const char *func_name() const { return "|"; } - void fix_length_and_dec() { unsigned_flag=1; } - void print(String *str) { print_op(str); } }; -class Item_func_bit_and :public Item_int_func +class Item_func_bit_and :public Item_func_bit { public: - Item_func_bit_and(Item *a,Item *b) :Item_int_func(a,b) {} + Item_func_bit_and(Item *a, Item *b) :Item_func_bit(a, b) {} longlong val_int(); const char *func_name() const { return "&"; } - void fix_length_and_dec() { unsigned_flag=1; } - void print(String *str) { print_op(str); } }; class Item_func_bit_count :public Item_int_func @@ -690,34 +696,32 @@ public: void fix_length_and_dec() { max_length=2; } }; -class Item_func_shift_left :public Item_int_func +class Item_func_shift_left :public Item_func_bit { public: - Item_func_shift_left(Item *a,Item *b) :Item_int_func(a,b) {} + Item_func_shift_left(Item *a, Item *b) :Item_func_bit(a, b) {} longlong val_int(); const char *func_name() const { return "<<"; } - void fix_length_and_dec() { unsigned_flag=1; } - void print(String *str) { print_op(str); } }; -class Item_func_shift_right :public Item_int_func +class Item_func_shift_right :public Item_func_bit { public: - Item_func_shift_right(Item *a,Item *b) :Item_int_func(a,b) {} + Item_func_shift_right(Item *a, Item *b) :Item_func_bit(a, b) {} longlong val_int(); const char *func_name() const { return ">>"; } - void print(String *str) { print_op(str); } }; -class Item_func_bit_neg :public Item_int_func +class Item_func_bit_neg :public Item_func_bit { public: - Item_func_bit_neg(Item *a) :Item_int_func(a) {} + Item_func_bit_neg(Item *a) :Item_func_bit(a) {} longlong val_int(); const char *func_name() const { return "~"; } - void fix_length_and_dec() { unsigned_flag=1; } + void print(String *str) { Item_func::print(str); } }; + class Item_func_set_last_insert_id :public Item_int_func { public: @@ -1024,14 +1028,12 @@ public: }; -class Item_func_bit_xor : public Item_int_func +class Item_func_bit_xor : public Item_func_bit { public: - Item_func_bit_xor(Item *a,Item *b) :Item_int_func(a,b) {} + Item_func_bit_xor(Item *a, Item *b) :Item_func_bit(a, b) {} longlong val_int(); const char *func_name() const { return "^"; } - void fix_length_xor_dec() { unsigned_flag=1; } - void print(String *str) { print_op(str); } }; class Item_func_is_free_lock :public Item_int_func diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index f40d38dd4a8..3cb03d7ea49 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1582,6 +1582,11 @@ Item_func_format::Item_func_format(Item *org,int dec) :Item_str_func(org) } +/* + TODO: This needs to be fixed for multi-byte character set where numbers + are stored in more than one byte +*/ + String *Item_func_format::val_str(String *str) { double nr =args[0]->val(); @@ -1590,7 +1595,8 @@ String *Item_func_format::val_str(String *str) if ((null_value=args[0]->null_value)) return 0; /* purecov: inspected */ dec= decimals ? decimals+1 : 0; - str->set(nr,decimals,default_charset()); + /* Here default_charset() is right as this is not an automatic conversion */ + str->set(nr,decimals, default_charset()); #ifdef HAVE_ISNAN if (isnan(nr)) return str; @@ -1839,14 +1845,11 @@ inline String* alloc_buffer(String *res,String *str,String *tmp_value, str->length(length); return str; } - else - { - if (tmp_value->alloc(length)) - return 0; - (void) tmp_value->copy(*res); - tmp_value->length(length); - return tmp_value; - } + if (tmp_value->alloc(length)) + return 0; + (void) tmp_value->copy(*res); + tmp_value->length(length); + return tmp_value; } res->length(length); return res; @@ -1947,7 +1950,7 @@ String *Item_func_rpad::val_str(String *str) int32 count= (int32) args[1]->val_int(); int32 byte_count= count * collation.collation->mbmaxlen; String *res =args[0]->val_str(str); - String *rpad = args[2]->val_str(str); + String *rpad = args[2]->val_str(&rpad_str); if (!res || args[1]->null_value || !rpad || count < 0) goto err; @@ -2384,6 +2387,10 @@ String* Item_func_export_set::val_str(String* str) null_value=1; return 0; } + /* + Arg count can only be 3, 4 or 5 here. This is guaranteed from the + grammar for EXPORT_SET() + */ switch(arg_count) { case 5: num_set_values = (uint) args[4]->val_int(); @@ -2513,7 +2520,7 @@ String *Item_func_quote::val_str(String *str) new_length= arg_length+2; /* for beginning and ending ' signs */ for (from= (char*) arg->ptr(), end= from + arg_length; from < end; from++) - new_length+= get_esc_bit(escmask, *from); + new_length+= get_esc_bit(escmask, (uchar) *from); /* We have to use realloc() instead of alloc() as we want to keep the diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index a7949511f02..40b00cdd488 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -474,7 +474,7 @@ public: class Item_func_rpad :public Item_str_func { - String tmp_value; + String tmp_value, rpad_str; public: Item_func_rpad(Item *arg1,Item *arg2,Item *arg3) :Item_str_func(arg1,arg2,arg3) {} @@ -486,7 +486,7 @@ public: class Item_func_lpad :public Item_str_func { - String tmp_value; + String tmp_value, lpad_str; public: Item_func_lpad(Item *arg1,Item *arg2,Item *arg3) :Item_str_func(arg1,arg2,arg3) {} diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 6f5e2e492e7..43775e1c96c 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -344,7 +344,7 @@ void Item_singlerow_subselect::bring_value() exec(); } -double Item_singlerow_subselect::val () +double Item_singlerow_subselect::val() { if (!exec() && !value->null_value) { @@ -358,7 +358,7 @@ double Item_singlerow_subselect::val () } } -longlong Item_singlerow_subselect::val_int () +longlong Item_singlerow_subselect::val_int() { if (!exec() && !value->null_value) { @@ -466,7 +466,7 @@ void Item_exists_subselect::fix_length_and_dec() max_columns= engine->cols(); } -double Item_exists_subselect::val () +double Item_exists_subselect::val() { if (exec()) { @@ -476,7 +476,7 @@ double Item_exists_subselect::val () return (double) value; } -longlong Item_exists_subselect::val_int () +longlong Item_exists_subselect::val_int() { if (exec()) { @@ -493,11 +493,11 @@ String *Item_exists_subselect::val_str(String *str) reset(); return 0; } - str->set(value,default_charset()); + str->set(value,&my_charset_bin); return str; } -double Item_in_subselect::val () +double Item_in_subselect::val() { if (exec()) { @@ -510,7 +510,7 @@ double Item_in_subselect::val () return (double) value; } -longlong Item_in_subselect::val_int () +longlong Item_in_subselect::val_int() { if (exec()) { @@ -536,7 +536,7 @@ String *Item_in_subselect::val_str(String *str) null_value= 1; return 0; } - str->set(value,default_charset()); + str->set(value, &my_charset_bin); return str; } diff --git a/sql/item_sum.cc b/sql/item_sum.cc index a3d652d2fe1..3bc52159a96 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -140,7 +140,7 @@ Item_sum_num::val_str(String *str) double nr=val(); if (null_value) return 0; - str->set(nr,decimals,default_charset()); + str->set(nr,decimals, &my_charset_bin); return str; } @@ -148,10 +148,13 @@ Item_sum_num::val_str(String *str) String * Item_sum_int::val_str(String *str) { - longlong nr=val_int(); + longlong nr= val_int(); if (null_value) return 0; - str->set(nr,default_charset()); + if (unsigned_flag) + str->set((ulonglong) nr, &my_charset_bin); + else + str->set(nr, &my_charset_bin); return str; } @@ -262,6 +265,122 @@ double Item_sum_sum::val() } +/* Item_sum_sum_distinct */ + +Item_sum_sum_distinct::Item_sum_sum_distinct(Item *item) + :Item_sum_num(item), sum(0.0), tree(0) +{ + /* + quick_group is an optimizer hint, which means that GROUP BY can be + handled with help of index on grouped columns. + By setting quick_group to zero we force creation of temporary table + to perform GROUP BY. + */ + quick_group= 0; +} + + +Item_sum_sum_distinct::Item_sum_sum_distinct(THD *thd, + Item_sum_sum_distinct &original) + :Item_sum_num(thd, original), sum(0.0), tree(0) +{ + quick_group= 0; +} + + +Item_sum_sum_distinct::~Item_sum_sum_distinct() +{ + delete tree; +} + + +Item * +Item_sum_sum_distinct::copy_or_same(THD *thd) +{ + return new (&thd->mem_root) Item_sum_sum_distinct(thd, *this); +} + +C_MODE_START + +static int simple_raw_key_cmp(void* arg, const void* key1, const void* key2) +{ + return memcmp(key1, key2, *(uint *) arg); +} + +C_MODE_END + +bool Item_sum_sum_distinct::setup(THD *thd) +{ + SELECT_LEX *select_lex= thd->lex->current_select; + /* what does it mean??? */ + if (select_lex->linkage == GLOBAL_OPTIONS_TYPE) + return 1; + + DBUG_ASSERT(tree == 0); /* setup can not be called twice */ + + /* + Uniques handles all unique elements in a tree until they can't fit in. + Then thee tree is dumped to the temporary file. + See class Unique for details. + */ + null_value= maybe_null= 1; + /* + TODO: if underlying item result fits in 4 bytes we can take advantage + of it and have tree of long/ulong. It gives 10% performance boost + */ + static uint key_length= sizeof(double); + tree= new Unique(simple_raw_key_cmp, &key_length, key_length, + thd->variables.max_heap_table_size); + return tree == 0; +} + +void Item_sum_sum_distinct::clear() +{ + DBUG_ASSERT(tree); /* we always have a tree */ + null_value= 1; + tree->reset(); +} + +bool Item_sum_sum_distinct::add() +{ + /* args[0]->val() may reset args[0]->null_value */ + double val= args[0]->val(); + if (!args[0]->null_value) + { + DBUG_ASSERT(tree); + null_value= 0; + if (val) + return tree->unique_add(&val); + } + return 0; +} + +C_MODE_START + +static int sum_sum_distinct(void *element, element_count num_of_dups, + void *item_sum_sum_distinct) +{ + ((Item_sum_sum_distinct *) + (item_sum_sum_distinct))->add(* (double *) element); + return 0; +} + +C_MODE_END + +double Item_sum_sum_distinct::val() +{ + /* + We don't have a tree only if 'setup()' hasn't been called; + this is the case of sql_select.cc:return_zero_rows. + */ + sum= 0.0; + if (tree) + tree->walk(sum_sum_distinct, (void *) this); + return sum; +} + +/* end of Item_sum_sum_distinct */ + Item *Item_sum_count::copy_or_same(THD* thd) { return new (&thd->mem_root) Item_sum_count(thd, *this); @@ -474,13 +593,13 @@ Item_sum_hybrid::val_str(String *str) case STRING_RESULT: return &value; case REAL_RESULT: - str->set(sum,decimals,default_charset()); + str->set(sum,decimals, &my_charset_bin); break; case INT_RESULT: if (unsigned_flag) - str->set((ulonglong) sum_int,default_charset()); + str->set((ulonglong) sum_int, &my_charset_bin); else - str->set((longlong) sum_int,default_charset()); + str->set((longlong) sum_int, &my_charset_bin); break; case ROW_RESULT: default: @@ -776,9 +895,16 @@ void Item_sum_avg::reset_field() void Item_sum_bit::reset_field() { + reset(); + int8store(result_field->ptr, bits); +} + +void Item_sum_bit::update_field() +{ char *res=result_field->ptr; - ulonglong nr=(ulonglong) args[0]->val_int(); - int8store(res,nr); + bits= uint8korr(res); + add(); + int8store(res, bits); } /* @@ -916,37 +1042,6 @@ Item_sum_hybrid::min_max_update_int_field() } -void Item_sum_or::update_field() -{ - ulonglong nr; - char *res=result_field->ptr; - - nr=uint8korr(res); - nr|= (ulonglong) args[0]->val_int(); - int8store(res,nr); -} - -void Item_sum_xor::update_field() -{ - ulonglong nr; - char *res=result_field->ptr; - - nr=uint8korr(res); - nr^= (ulonglong) args[0]->val_int(); - int8store(res,nr); -} - -void Item_sum_and::update_field() -{ - ulonglong nr; - char *res=result_field->ptr; - - nr=uint8korr(res); - nr&= (ulonglong) args[0]->val_int(); - int8store(res,nr); -} - - Item_avg_field::Item_avg_field(Item_sum_avg *item) { name=item->name; @@ -956,6 +1051,7 @@ Item_avg_field::Item_avg_field(Item_sum_avg *item) maybe_null=1; } + double Item_avg_field::val() { double nr; @@ -978,7 +1074,7 @@ String *Item_avg_field::val_str(String *str) double nr=Item_avg_field::val(); if (null_value) return 0; - str->set(nr,decimals,default_charset()); + str->set(nr,decimals, &my_charset_bin); return str; } @@ -1026,7 +1122,7 @@ String *Item_variance_field::val_str(String *str) double nr=val(); if (null_value) return 0; - str->set(nr,decimals,default_charset()); + str->set(nr,decimals, &my_charset_bin); return str; } @@ -1036,11 +1132,6 @@ String *Item_variance_field::val_str(String *str) #include "sql_select.h" -int simple_raw_key_cmp(void* arg, byte* key1, byte* key2) -{ - return memcmp(key1, key2, *(uint*) arg); -} - int simple_str_key_cmp(void* arg, byte* key1, byte* key2) { Item_sum_count_distinct* item = (Item_sum_count_distinct*)arg; @@ -1415,8 +1506,7 @@ String *Item_sum_udf_float::val_str(String *str) double nr=val(); if (null_value) return 0; /* purecov: inspected */ - else - str->set(nr,decimals,default_charset()); + str->set(nr,decimals, &my_charset_bin); return str; } @@ -1441,8 +1531,7 @@ String *Item_sum_udf_int::val_str(String *str) longlong nr=val_int(); if (null_value) return 0; - else - str->set(nr,default_charset()); + str->set(nr, &my_charset_bin); return str; } diff --git a/sql/item_sum.h b/sql/item_sum.h index d454f06ccde..afed152bb0e 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -27,9 +27,9 @@ class Item_sum :public Item_result_field { public: enum Sumfunctype - { COUNT_FUNC,COUNT_DISTINCT_FUNC,SUM_FUNC,AVG_FUNC,MIN_FUNC, - MAX_FUNC, UNIQUE_USERS_FUNC,STD_FUNC,VARIANCE_FUNC,SUM_BIT_FUNC, - UDF_SUM_FUNC, GROUP_CONCAT_FUNC + { COUNT_FUNC, COUNT_DISTINCT_FUNC, SUM_FUNC, SUM_DISTINCT_FUNC, AVG_FUNC, + MIN_FUNC, MAX_FUNC, UNIQUE_USERS_FUNC, STD_FUNC, VARIANCE_FUNC, + SUM_BIT_FUNC, UDF_SUM_FUNC, GROUP_CONCAT_FUNC }; Item **args,*tmp_args[2]; @@ -65,7 +65,18 @@ public: inline bool reset() { clear(); return add(); }; virtual void clear()= 0; virtual bool add()=0; + /* + Called when new group is started and results are being saved in + a temporary table. Similar to reset(), but must also store value in + result_field. Like reset() it is supposed to reset start value to + default. + */ virtual void reset_field()=0; + /* + Called for each new value in the group, when temporary table is in use. + Similar to add(), but uses temporary table field to obtain current value, + Updated value is then saved in the field. + */ virtual void update_field()=0; virtual bool keep_field_type(void) const { return 0; } virtual void fix_length_and_dec() { maybe_null=1; null_value=1; } @@ -138,6 +149,39 @@ class Item_sum_sum :public Item_sum_num }; +/* + Item_sum_sum_distinct - SELECT SUM(DISTINCT expr) FROM ... + support. See also: MySQL manual, chapter 'Adding New Functions To MySQL' + and comments in item_sum.cc. +*/ + +class Unique; + +class Item_sum_sum_distinct :public Item_sum_num +{ + double sum; + Unique *tree; +private: + Item_sum_sum_distinct(THD *thd, Item_sum_sum_distinct &item); +public: + Item_sum_sum_distinct(Item *item_par); + ~Item_sum_sum_distinct(); + + bool setup(THD *thd); + void clear(); + bool add(); + double val(); + + inline void add(double val) { sum+= val; } + enum Sumfunctype sum_func () const { return SUM_DISTINCT_FUNC; } + void reset_field() {} // not used + void update_field() {} // not used + const char *func_name() const { return "sum_distinct"; } + Item *copy_or_same(THD* thd); + virtual void no_rows_in_result() {} +}; + + class Item_sum_count :public Item_sum_int { longlong count; @@ -445,10 +489,10 @@ public: class Item_sum_bit :public Item_sum_int { - protected: +protected: ulonglong reset_bits,bits; - public: +public: Item_sum_bit(Item *item_par,ulonglong reset_arg) :Item_sum_int(item_par),reset_bits(reset_arg),bits(reset_arg) {} Item_sum_bit(THD *thd, Item_sum_bit &item): @@ -457,6 +501,7 @@ class Item_sum_bit :public Item_sum_int void clear(); longlong val_int(); void reset_field(); + void update_field(); void fix_length_and_dec() { decimals=0; max_length=21; unsigned_flag=1; maybe_null=null_value=0; } }; @@ -464,11 +509,10 @@ class Item_sum_bit :public Item_sum_int class Item_sum_or :public Item_sum_bit { - public: +public: Item_sum_or(Item *item_par) :Item_sum_bit(item_par,LL(0)) {} Item_sum_or(THD *thd, Item_sum_or &item) :Item_sum_bit(thd, item) {} bool add(); - void update_field(); const char *func_name() const { return "bit_or"; } Item *copy_or_same(THD* thd); }; @@ -477,10 +521,9 @@ class Item_sum_or :public Item_sum_bit class Item_sum_and :public Item_sum_bit { public: - Item_sum_and(Item *item_par) :Item_sum_bit(item_par, ~(ulonglong) LL(0)) {} + Item_sum_and(Item *item_par) :Item_sum_bit(item_par, ULONGLONG_MAX) {} Item_sum_and(THD *thd, Item_sum_and &item) :Item_sum_bit(thd, item) {} bool add(); - void update_field(); const char *func_name() const { return "bit_and"; } Item *copy_or_same(THD* thd); }; @@ -491,7 +534,6 @@ class Item_sum_xor :public Item_sum_bit Item_sum_xor(Item *item_par) :Item_sum_bit(item_par,LL(0)) {} Item_sum_xor(THD *thd, Item_sum_xor &item) :Item_sum_bit(thd, item) {} bool add(); - void update_field(); const char *func_name() const { return "bit_xor"; } Item *copy_or_same(THD* thd); }; diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 7936006acc4..7d28cd10b81 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -526,8 +526,11 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time, uint year; if (type == TIMESTAMP_TIME) return 1; - length= int10_to_str(calc_week(l_time, 0, (*ptr) == 'U', &year), - intbuff, 10) - intbuff; + length= int10_to_str(calc_week(l_time, + (*ptr) == 'U' ? + WEEK_FIRST_WEEKDAY : WEEK_MONDAY_FIRST, + &year), + intbuff, 10) - intbuff; str->append_with_prefill(intbuff, length, 2, '0'); } break; @@ -537,8 +540,12 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time, uint year; if (type == TIMESTAMP_TIME) return 1; - length= int10_to_str(calc_week(l_time, 1, (*ptr) == 'V', &year), - intbuff, 10) - intbuff; + length= int10_to_str(calc_week(l_time, + ((*ptr) == 'V' ? + (WEEK_YEAR | WEEK_FIRST_WEEKDAY) : + (WEEK_YEAR | WEEK_MONDAY_FIRST)), + &year), + intbuff, 10) - intbuff; str->append_with_prefill(intbuff, length, 2, '0'); } break; @@ -548,7 +555,11 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time, uint year; if (type == TIMESTAMP_TIME) return 1; - (void) calc_week(l_time, 1, (*ptr) == 'X', &year); + (void) calc_week(l_time, + ((*ptr) == 'X' ? + WEEK_YEAR | WEEK_FIRST_WEEKDAY : + WEEK_YEAR | WEEK_MONDAY_FIRST), + &year); length= int10_to_str(year, intbuff, 10) - intbuff; str->append_with_prefill(intbuff, length, 4, '0'); } @@ -718,27 +729,51 @@ longlong Item_func_second::val_int() } -/* - Returns the week of year. +uint week_mode(uint mode) +{ + uint week_format= (mode & 7); + if (!(week_format & WEEK_MONDAY_FIRST)) + week_format^= WEEK_FIRST_WEEKDAY; + return week_format; +} - The bits in week_format has the following meaning: - 0 If not set: USA format: Sunday is first day of week - If set: ISO format: Monday is first day of week - 1 If not set: Week is in range 0-53 - If set Week is in range 1-53. +/* + The bits in week_format(for calc_week() function) has the following meaning: + WEEK_MONDAY_FIRST (0) If not set Sunday is first day of week + If set Monday is first day of week + WEEK_YEAR (1) If not set Week is in range 0-53 + + Week 0 is returned for the the last week of the previous year (for + a date at start of january) In this case one can get 53 for the + first week of next year. This flag ensures that the week is + relevant for the given year. Note that this flag is only + releveant if WEEK_JANUARY is not set. + + If set Week is in range 1-53. + + In this case one may get week 53 for a date in January (when + the week is that last week of previous year) and week 1 for a + date in December. + + WEEK_FIRST_WEEKDAY (2) If not set Weeks are numbered according + to ISO 8601:1988 + If set The week that contains the first + 'first-day-of-week' is week 1. + + ISO 8601:1988 means that if the week containing January 1 has + four or more days in the new year, then it is week 1; + Otherwise it is the last week of the previous year, and the + next week is week 1. */ longlong Item_func_week::val_int() { uint year; - uint week_format; TIME ltime; if (get_arg0_date(<ime,0)) return 0; - week_format= (uint) args[1]->val_int(); - return (longlong) calc_week(<ime, - (week_format & 2) != 0, - (week_format & 1) == 0, + return (longlong) calc_week(<ime, + week_mode((uint) args[1]->val_int()), &year); } @@ -749,7 +784,9 @@ longlong Item_func_yearweek::val_int() TIME ltime; if (get_arg0_date(<ime,0)) return 0; - week=calc_week(<ime, 1, (args[1]->val_int() & 1) == 0, &year); + week= calc_week(<ime, + (week_mode((uint) args[1]->val_int()) | WEEK_YEAR), + &year); return week+year*100; } @@ -1721,10 +1758,7 @@ longlong Item_extract::val_int() case INTERVAL_WEEK: { week_format= current_thd->variables.default_week_format; - return calc_week(<ime, - (week_format & 2) != 0, - (week_format & 1) == 0, - &year); + return calc_week(<ime, week_mode(week_format), &year); } case INTERVAL_DAY: return ltime.day; case INTERVAL_DAY_HOUR: return (long) (ltime.day*100L+ltime.hour)*neg; diff --git a/sql/lex.h b/sql/lex.h index 7f7a27289b1..114e1a6b960 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -156,6 +156,7 @@ static SYMBOL symbols[] = { { "ENCLOSED", SYM(ENCLOSED),0,0}, { "END", SYM(END),0,0}, { "ENGINE", SYM(ENGINE_SYM),0,0}, + { "ENGINES", SYM(ENGINES_SYM),0,0}, { "ENUM", SYM(ENUM),0,0}, { "ERRORS", SYM(ERRORS),0,0}, { "ESCAPE", SYM(ESCAPE_SYM),0,0}, @@ -421,6 +422,7 @@ static SYMBOL symbols[] = { { "STARTING", SYM(STARTING),0,0}, { "STATUS", SYM(STATUS_SYM),0,0}, { "STOP", SYM(STOP_SYM),0,0}, + { "STORAGE", SYM(STORAGE_SYM),0,0}, { "STRAIGHT_JOIN", SYM(STRAIGHT_JOIN),0,0}, { "STRING", SYM(STRING_SYM),0,0}, { "STRIPED", SYM(RAID_STRIPED_SYM),0,0}, diff --git a/sql/log.cc b/sql/log.cc index 95ee4928971..59bc7c7fae2 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -964,7 +964,7 @@ void MYSQL_LOG::new_file(bool need_lock) We log the whole file name for log file as the user may decide to change base names at some point. */ - THD* thd = current_thd; + THD *thd = current_thd; /* may be 0 if we are reacting to SIGHUP */ Rotate_log_event r(thd,new_name+dirname_length(new_name)); r.set_log_pos(this); r.write(&log_file); @@ -1231,8 +1231,6 @@ bool MYSQL_LOG::write(Log_event* event_info) Intvar_log_event e(thd,(uchar) LAST_INSERT_ID_EVENT, thd->current_insert_id); e.set_log_pos(this); - if (thd->server_id) - e.server_id = thd->server_id; if (e.write(file)) goto err; } @@ -1240,8 +1238,6 @@ bool MYSQL_LOG::write(Log_event* event_info) { Intvar_log_event e(thd,(uchar) INSERT_ID_EVENT,thd->last_insert_id); e.set_log_pos(this); - if (thd->server_id) - e.server_id = thd->server_id; if (e.write(file)) goto err; } diff --git a/sql/log_event.cc b/sql/log_event.cc index 8c93a22cf6e..ca1b296009d 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -239,6 +239,13 @@ Log_event::Log_event(THD* thd_arg, uint16 flags_arg, bool using_trans) } +/* + This minimal constructor is for when you are not even sure that there is a + valid THD. For example in the server when we are shutting down or flushing + logs after receiving a SIGHUP (then we must write a Rotate to the binlog but + we have no THD, so we need this minimal constructor). +*/ + Log_event::Log_event() :temp_buf(0), exec_time(0), cached_event_len(0), flags(0), cache_stmt(0), thd(0) @@ -1032,7 +1039,7 @@ Default database: '%s'", thd->variables.convert_set = 0; #endif close_thread_tables(thd); - free_root(&thd->mem_root,0); + free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC)); return (thd->query_error ? thd->query_error : Log_event::exec_event(rli)); } #endif @@ -1794,10 +1801,10 @@ Slave: load data infile on table '%s' at log position %s in log \ slave_print_error(rli,sql_errno,"\ Error '%s' running LOAD DATA INFILE on table '%s'. Default database: '%s'", err, (char*)table_name, print_slave_db_safe(db)); - free_root(&thd->mem_root,0); + free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC)); return 1; } - free_root(&thd->mem_root,0); + free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC)); if (thd->is_fatal_error) { diff --git a/sql/log_event.h b/sql/log_event.h index 6cc8a7ca06d..d615c0e361b 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -698,7 +698,7 @@ public: #ifndef MYSQL_CLIENT Intvar_log_event(THD* thd_arg,uchar type_arg, ulonglong val_arg) - :Log_event(),val(val_arg),type(type_arg) + :Log_event(thd_arg,0,0),val(val_arg),type(type_arg) {} #ifdef HAVE_REPLICATION void pack_info(Protocol* protocol); @@ -841,7 +841,7 @@ public: Rotate_log_event(THD* thd_arg, const char* new_log_ident_arg, uint ident_len_arg = 0, ulonglong pos_arg = LOG_EVENT_OFFSET) - :Log_event(thd_arg,0,0), new_log_ident(new_log_ident_arg), + :Log_event(), new_log_ident(new_log_ident_arg), pos(pos_arg),ident_len(ident_len_arg ? ident_len_arg : (uint) strlen(new_log_ident_arg)), alloced(0) {} diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index e827e79af48..839a1f5f4a8 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -303,6 +303,11 @@ void debug_sync_point(const char* lock_name, uint lock_timeout); #define tmp_file_prefix "#sql" /* Prefix for tmp tables */ #define tmp_file_prefix_length 4 +/* Flags for calc_week() function. */ +#define WEEK_MONDAY_FIRST 1 +#define WEEK_YEAR 2 +#define WEEK_FIRST_WEEKDAY 4 + struct st_table; class THD; @@ -438,6 +443,7 @@ int mysql_execute_command(THD *thd); bool do_command(THD *thd); bool dispatch_command(enum enum_server_command command, THD *thd, char* packet, uint packet_length); +bool check_dup(const char *db, const char *name, TABLE_LIST *tables); #ifndef EMBEDDED_LIBRARY bool check_stack_overrun(THD *thd,char *dummy); #else @@ -451,17 +457,11 @@ void kill_mysql(void); void close_connection(THD *thd, uint errcode, bool lock); bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, bool *write_to_binlog); -#ifndef NO_EMBEDDED_ACCESS_CHECKS bool check_access(THD *thd, ulong access, const char *db, ulong *save_priv, bool no_grant, bool no_errors); bool check_table_access(THD *thd, ulong want_access, TABLE_LIST *tables, bool no_errors); bool check_global_access(THD *thd, ulong want_access); -#else -#define check_access(thd, access, db, save_priv, no_grant, no_errors) false -#define check_table_access(thd, want_access, tables, no_errors) false -#define check_global_access(thd, want_access) false -#endif int mysql_backup_table(THD* thd, TABLE_LIST* table_list); int mysql_restore_table(THD* thd, TABLE_LIST* table_list); @@ -626,7 +626,7 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables, pthread_mutex_t *mutex); int mysqld_show_charsets(THD *thd,const char *wild); int mysqld_show_collations(THD *thd,const char *wild); -int mysqld_show_table_types(THD *thd); +int mysqld_show_storage_engines(THD *thd); int mysqld_show_privileges(THD *thd); int mysqld_show_column_types(THD *thd); int mysqld_help (THD *thd, const char *text); @@ -997,8 +997,7 @@ void filesort_free_buffers(TABLE *table); void change_double_for_sort(double nr,byte *to); int get_quick_record(SQL_SELECT *select); int calc_weekday(long daynr,bool sunday_first_day_of_week); -uint calc_week(TIME *ltime, bool with_year, bool sunday_first_day_of_week, - uint *year); +uint calc_week(TIME *l_time, uint week_behaviour, uint *year); void find_date(char *pos,uint *vek,uint flag); TYPELIB *convert_strings_to_array_type(my_string *typelibs, my_string *end); TYPELIB *typelib(List<String> &strings); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 7b3d8411e32..6e286dcd01e 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(); #ifndef EMBEDDED_LIBRARY /**************************************************************************** @@ -1061,7 +1063,7 @@ static void set_user(const char *user) } return; } - else if (!user) + if (!user) { if (!opt_bootstrap) { @@ -1276,7 +1278,7 @@ static void server_init(void) void yyerror(const char *s) { THD *thd=current_thd; - char *yytext=(char*) thd->lex->tok_start; + char *yytext= (char*) thd->lex->tok_start; /* "parse error" changed into "syntax error" between bison 1.75 and 1.875 */ if (strcmp(s,"parse error") == 0 || strcmp(s,"syntax error") == 0) s=ER(ER_SYNTAX_ERROR); @@ -1483,16 +1485,7 @@ static void start_signal_handler(void) { // Save vm id of this process if (!opt_bootstrap) - { - File pidFile; - if ((pidFile = my_create(pidfile_name,0664, O_WRONLY, MYF(MY_WME))) >= 0) - { - char buff[21]; - sprintf(buff,"%lu",(ulong) getpid()); - (void) my_write(pidFile, buff,strlen(buff),MYF(MY_WME)); - (void) my_close(pidFile,MYF(0)); - } - } + create_pid_file(); // no signal handler } @@ -1778,16 +1771,8 @@ extern "C" void *signal_hand(void *arg __attribute__((unused))) /* Save pid to this process (or thread on Linux) */ if (!opt_bootstrap) - { - File pidFile; - if ((pidFile = my_create(pidfile_name,0664, O_WRONLY, MYF(MY_WME))) >= 0) - { - char buff[21]; - ulong length= my_sprintf(buff, (buff,"%lu",(ulong) getpid())); - (void) my_write(pidFile, buff, length, MYF(MY_WME)); - (void) my_close(pidFile,MYF(0)); - } - } + create_pid_file(); + #ifdef HAVE_STACK_TRACE_ON_SEGV if (opt_do_pstack) { @@ -1900,7 +1885,7 @@ extern "C" int my_message_sql(uint error, const char *str, DBUG_RETURN(0); } /* - thd->lex.current_select == 0 if lex structure is not inited + thd->lex->current_select == 0 if lex structure is not inited (not query command (COM_QUERY)) */ if (thd->lex->current_select && @@ -2809,7 +2794,7 @@ default_service_handling(char **argv, } /* We must have servicename last */ *pos++= ' '; - strmake(pos, servicename, (uint) (end+2 - pos)); + (void) add_quoted_string(pos, servicename, end); if (Service.got_service_option(argv, "install")) { @@ -3600,7 +3585,7 @@ enum options_mysqld OPT_SKIP_HOST_CACHE, OPT_SHORT_LOG_FORMAT, OPT_FLUSH, OPT_SAFE, OPT_BOOTSTRAP, OPT_SKIP_SHOW_DB, - OPT_TABLE_TYPE, OPT_INIT_FILE, + OPT_STORAGE_ENGINE, OPT_INIT_FILE, OPT_DELAY_KEY_WRITE_ALL, OPT_SLOW_QUERY_LOG, OPT_DELAY_KEY_WRITE, OPT_CHARSETS_DIR, OPT_BDB_HOME, OPT_BDB_LOG, @@ -3809,8 +3794,11 @@ Disable with --skip-bdb (will save memory).", {"default-collation", OPT_DEFAULT_COLLATION, "Set the default collation.", (gptr*) &default_collation_name, (gptr*) &default_collation_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, - {"default-table-type", OPT_TABLE_TYPE, - "Set the default table type for tables.", 0, 0, + {"default-storage-engine", OPT_STORAGE_ENGINE, + "Set the default storage engine (table tyoe) for tables.", 0, 0, + 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"default-table-type", OPT_STORAGE_ENGINE, + "(deprecated) Use default-storage-engine.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"delay-key-write", OPT_DELAY_KEY_WRITE, "Type of DELAY_KEY_WRITE.", 0,0,0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, @@ -4646,7 +4634,7 @@ The minimum value for this variable is 4096.", 1, 0}, {"table_cache", OPT_TABLE_CACHE, "The number of open tables for all threads.", (gptr*) &table_cache_size, - (gptr*) &table_cache_size, 0, GET_ULONG, REQUIRED_ARG, 64, 1, 16384, 0, 1, + (gptr*) &table_cache_size, 0, GET_ULONG, REQUIRED_ARG, 64, 1, ~0L, 0, 1, 0}, {"thread_concurrency", OPT_THREAD_CONCURRENCY, "Permits the application to give the threads system a hint for the desired number of threads that should be run at the same time.", @@ -4664,7 +4652,7 @@ The minimum value for this variable is 4096.", {"thread_stack", OPT_THREAD_STACK, "The stack size for each thread.", (gptr*) &thread_stack, (gptr*) &thread_stack, 0, GET_ULONG, REQUIRED_ARG,DEFAULT_THREAD_STACK, - 1024*32, ~0L, 0, 1024, 0}, + 1024L*128L, ~0L, 0, 1024, 0}, {"transaction_alloc_block_size", OPT_TRANS_ALLOC_BLOCK_SIZE, "Allocation block size for transactions to be stored in binary log", (gptr*) &global_system_variables.trans_alloc_block_size, @@ -4689,7 +4677,7 @@ The minimum value for this variable is 4096.", "The default week format used by WEEK() functions.", (gptr*) &global_system_variables.default_week_format, (gptr*) &max_system_variables.default_week_format, - 0, GET_ULONG, REQUIRED_ARG, 0, 0, 3L, 0, 1, 0}, + 0, GET_ULONG, REQUIRED_ARG, 0, 0, 7L, 0, 1, 0}, { "date-format", OPT_DATE_FORMAT, "The DATE format (For future).", (gptr*) &opt_date_time_formats[TIMESTAMP_DATE], @@ -4788,8 +4776,8 @@ struct show_var_st status_vars[]= { {"Com_show_slave_hosts", (char*) (com_stat+(uint) SQLCOM_SHOW_SLAVE_HOSTS),SHOW_LONG}, {"Com_show_slave_status", (char*) (com_stat+(uint) SQLCOM_SHOW_SLAVE_STAT),SHOW_LONG}, {"Com_show_status", (char*) (com_stat+(uint) SQLCOM_SHOW_STATUS),SHOW_LONG}, + {"Com_show_storage_engines", (char*) (com_stat+(uint) SQLCOM_SHOW_STORAGE_ENGINES),SHOW_LONG}, {"Com_show_tables", (char*) (com_stat+(uint) SQLCOM_SHOW_TABLES),SHOW_LONG}, - {"Com_show_table_types", (char*) (com_stat+(uint) SQLCOM_SHOW_TABLE_TYPES),SHOW_LONG}, {"Com_show_variables", (char*) (com_stat+(uint) SQLCOM_SHOW_VARIABLES),SHOW_LONG}, {"Com_show_warnings", (char*) (com_stat+(uint) SQLCOM_SHOW_WARNS),SHOW_LONG}, {"Com_slave_start", (char*) (com_stat+(uint) SQLCOM_SLAVE_START),SHOW_LONG}, @@ -5427,11 +5415,10 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), my_use_symdir=0; break; case (int) OPT_BIND_ADDRESS: - if (!argument || - (my_bind_addr= (ulong) inet_addr(argument)) == INADDR_NONE) + if ((my_bind_addr= (ulong) inet_addr(argument)) == INADDR_NONE) { struct hostent *ent; - if (argument || argument[0]) + if (argument[0]) ent=gethostbyname(argument); else { @@ -5476,7 +5463,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), case OPT_BOOTSTRAP: opt_noacl=opt_bootstrap=1; break; - case OPT_TABLE_TYPE: + case OPT_STORAGE_ENGINE: { if ((enum db_type)((global_system_variables.table_type= ha_resolve_by_name(argument, strlen(argument)))) == DB_TYPE_UNKNOWN) @@ -5841,6 +5828,18 @@ static void fix_paths(void) exit(1); } #endif /* HAVE_REPLICATION */ + + /* + Ensure that lower_case_table_names is set on system where we have case + insensitive names. If this is not done the users MyISAM tables will + get corrupted if accesses with names of different case. + */ + if (!lower_case_table_names && + test_if_case_insensitive(mysql_real_data_home) == 1) + { + sql_print_error("Warning: Setting lower_case_table_names=1 becasue file system %s is case insensitive", mysql_real_data_home); + lower_case_table_names= 1; + } } @@ -5994,6 +5993,61 @@ 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], *end; + end= int2str((long) getpid(), buff, 10); + *end++= '\n'; + (void) my_write(file, (byte*) buff, (uint) (end-buff),MYF(MY_WME)); + (void) my_close(file, MYF(0)); + } +} + + /***************************************************************************** Instantiate templates *****************************************************************************/ diff --git a/sql/net_serv.cc b/sql/net_serv.cc index 0120ad80c0a..5e5d4b14c89 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -54,6 +54,12 @@ #ifdef EMBEDDED_LIBRARY +#undef MYSQL_SERVER + +#ifndef MYSQL_CLIENT +#define MYSQL_CLIENT +#endif + #undef net_flush extern "C" { diff --git a/sql/nt_servc.cc b/sql/nt_servc.cc index 25fc010d9a5..3e9d68d5fdb 100644 --- a/sql/nt_servc.cc +++ b/sql/nt_servc.cc @@ -496,9 +496,9 @@ BOOL NTService::IsService(LPCSTR ServiceName) BOOL ret_value=FALSE; SC_HANDLE service, scm; - if (scm = OpenSCManager(0, 0,SC_MANAGER_ENUMERATE_SERVICE)) + if ((scm= OpenSCManager(0, 0,SC_MANAGER_ENUMERATE_SERVICE))) { - if ((service = OpenService(scm,ServiceName, SERVICE_ALL_ACCESS ))) + if ((service = OpenService(scm,ServiceName, SERVICE_QUERY_STATUS ))) { ret_value=TRUE; CloseServiceHandle(service); diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 3a5278bdfac..8bba9382f85 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -1699,9 +1699,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) @@ -1802,16 +1803,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, field->charset(),key_part->image_type); - if (!(tree=new SEL_ARG(field,str,str))) + if (copies == 2) + { + /* + The key is stored as 2 byte length + key + key doesn't match end space. In other words, a key 'X ' should match + all rows between 'X' and 'X ...' + */ + uint length= uint2korr(str+maybe_null); + 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) { @@ -2279,7 +2302,7 @@ key_or(SEL_ARG *key1,SEL_ARG *key2) } return 0; } - else if (!key2) + if (!key2) { key1->use_count--; key1->free_tree(); @@ -3038,7 +3061,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 @@ -3194,7 +3218,8 @@ get_quick_keys(PARAM *param,QUICK_RANGE_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, @@ -3242,7 +3267,7 @@ bool QUICK_RANGE_SELECT::unique_key_range() if ((tmp->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); } } @@ -3278,6 +3303,7 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, QUICK_RANGE_SELECT *quick=new QUICK_RANGE_SELECT(thd, table, ref->key, 1); KEY *key_info = &table->key_info[ref->key]; KEY_PART *key_part; + QUICK_RANGE *range; uint part; if (!quick) @@ -3291,17 +3317,17 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, if (cp_buffer_from_ref(ref)) { if (thd->is_fatal_error) - return 0; // out of memory + goto err; // out of memory } - QUICK_RANGE *range= new QUICK_RANGE(); - if (!range) + if (!(range= new QUICK_RANGE())) goto err; // out of memory range->min_key=range->max_key=(char*) ref->key_buff; range->min_length=range->max_length=ref->key_length; range->flag= ((ref->key_length == key_info->key_length && - (key_info->flags & HA_NOSAME)) ? EQ_RANGE : 0); + (key_info->flags & (HA_NOSAME | HA_END_SPACE_KEY)) == + HA_NOSAME) ? EQ_RANGE : 0); if (!(quick->key_parts=key_part=(KEY_PART *) alloc_root(&quick->alloc,sizeof(KEY_PART)*ref->key_parts))) diff --git a/sql/records.cc b/sql/records.cc index b29b113a1bc..cd1de5af6aa 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -118,11 +118,12 @@ void init_read_record(READ_RECORD *info,THD *thd, TABLE *table, info->read_record=rr_sequential; table->file->rnd_init(); /* We can use record cache if we don't update dynamic length tables */ - if (use_record_cache > 0 || - (int) table->reginfo.lock_type <= (int) TL_READ_HIGH_PRIORITY || - !(table->db_options_in_use & HA_OPTION_PACK_RECORD) || - (use_record_cache < 0 && - !(table->file->table_flags() & HA_NOT_DELETE_WITH_CACHE))) + if (!table->no_cache && + (use_record_cache > 0 || + (int) table->reginfo.lock_type <= (int) TL_READ_HIGH_PRIORITY || + !(table->db_options_in_use & HA_OPTION_PACK_RECORD) || + (use_record_cache < 0 && + !(table->file->table_flags() & HA_NOT_DELETE_WITH_CACHE)))) VOID(table->file->extra_opt(HA_EXTRA_CACHE, thd->variables.read_buff_size)); } diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index 0efe57af0b0..81ea9d9e2ac 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -52,6 +52,13 @@ static Slave_log_event* find_slave_event(IO_CACHE* log, const char* log_file_name, char* errmsg); +/* + All of the functions defined in this file which are not used (the ones to + handle failsafe) are not used; their code has not been updated for more than + one year now so should be considered as BADLY BROKEN. Do not enable it. + The used functions (to handle LOAD DATA FROM MASTER, plus some small + functions like register_slave()) are working. +*/ static int init_failsafe_rpl_thread(THD* thd) { @@ -418,7 +425,6 @@ static Slave_log_event* find_slave_event(IO_CACHE* log, my_snprintf(errmsg, SLAVE_ERRMSG_SIZE, "Could not find slave event in log '%s'", (char*)log_file_name); - delete ev; return 0; } @@ -435,7 +441,7 @@ int show_new_master(THD* thd) DBUG_ENTER("show_new_master"); List<Item> field_list; char errmsg[SLAVE_ERRMSG_SIZE]; - LEX_MASTER_INFO* lex_mi = &thd->lex->mi; + LEX_MASTER_INFO* lex_mi= &thd->lex->mi; errmsg[0]=0; // Safety if (translate_master(thd, lex_mi, errmsg)) diff --git a/sql/set_var.cc b/sql/set_var.cc index 092533a49e2..4cf9f07b4ba 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -295,6 +295,8 @@ sys_var_thd_sql_mode sys_sql_mode("sql_mode", &SV::sql_mode); sys_var_thd_table_type sys_table_type("table_type", &SV::table_type); +sys_var_thd_storage_engine sys_storage_engine("storage_engine", + &SV::table_type); sys_var_long_ptr sys_table_cache_size("table_cache", &table_cache_size); sys_var_long_ptr sys_thread_cache_size("thread_cache_size", @@ -527,6 +529,7 @@ sys_var *sys_variables[]= &sys_sql_max_join_size, &sys_sql_mode, &sys_sql_warnings, + &sys_storage_engine, &sys_table_cache_size, &sys_table_type, &sys_thread_cache_size, @@ -732,6 +735,7 @@ struct show_var_st init_vars[]= { #endif {sys_sort_buffer.name, (char*) &sys_sort_buffer, SHOW_SYS}, {sys_sql_mode.name, (char*) &sys_sql_mode, SHOW_SYS}, + {sys_storage_engine.name, (char*) &sys_storage_engine, SHOW_SYS}, {"table_cache", (char*) &table_cache_size, SHOW_LONG}, {sys_table_type.name, (char*) &sys_table_type, SHOW_SYS}, {sys_thread_cache_size.name,(char*) &sys_thread_cache_size, SHOW_SYS}, @@ -788,9 +792,8 @@ bool update_sys_var_str(sys_var_str *var_str, rw_lock_t *var_mutex, /* If the string is "", delete old init command */ if (var && (new_length= var->value->str_value.length())) { - if (!(res= my_strdup_with_length(var->value->str_value.ptr(), - new_length, - MYF(0)))) + if (!(res= my_strdup_with_length((byte*) var->value->str_value.ptr(), + new_length, MYF(0)))) return 1; } /* @@ -2510,7 +2513,7 @@ int set_var_password::update(THD *thd) /* Based upon sys_var::check_enum() */ -bool sys_var_thd_table_type::check(THD *thd, set_var *var) +bool sys_var_thd_storage_engine::check(THD *thd, set_var *var) { char buff[80]; const char *value; @@ -2527,25 +2530,26 @@ bool sys_var_thd_table_type::check(THD *thd, set_var *var) } return 0; } + value= "unknown"; err: - my_error(ER_UNKNOWN_TABLE_ENGINE, MYF(0), value); + my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), value); return 1; } -byte *sys_var_thd_table_type::value_ptr(THD *thd, enum_var_type type, - LEX_STRING *base) +byte *sys_var_thd_storage_engine::value_ptr(THD *thd, enum_var_type type, + LEX_STRING *base) { ulong val; val= ((type == OPT_GLOBAL) ? global_system_variables.*offset : thd->variables.*offset); - const char *table_type= ha_get_table_type((enum db_type)val); + const char *table_type= ha_get_storage_engine((enum db_type)val); return (byte *) table_type; } -void sys_var_thd_table_type::set_default(THD *thd, enum_var_type type) +void sys_var_thd_storage_engine::set_default(THD *thd, enum_var_type type) { if (type == OPT_GLOBAL) global_system_variables.*offset= (ulong) DB_TYPE_MYISAM; @@ -2554,7 +2558,7 @@ void sys_var_thd_table_type::set_default(THD *thd, enum_var_type type) } -bool sys_var_thd_table_type::update(THD *thd, set_var *var) +bool sys_var_thd_storage_engine::update(THD *thd, set_var *var) { if (var->type == OPT_GLOBAL) global_system_variables.*offset= var->save_result.ulong_value; @@ -2563,6 +2567,25 @@ bool sys_var_thd_table_type::update(THD *thd, set_var *var) return 0; } +void sys_var_thd_table_type::warn_deprecated(THD *thd) +{ + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WARN_DEPRECATED_SYNTAX, + ER(ER_WARN_DEPRECATED_SYNTAX), "table_type", "storage_engine"); +} + +void sys_var_thd_table_type::set_default(THD *thd, enum_var_type type) +{ + warn_deprecated(thd); + sys_var_thd_storage_engine::set_default(thd, type); +} + +bool sys_var_thd_table_type::update(THD *thd, set_var *var) +{ + warn_deprecated(thd); + return sys_var_thd_storage_engine::update(thd, var); +} + /**************************************************************************** Functions to handle sql_mode diff --git a/sql/set_var.h b/sql/set_var.h index fc7610ee500..85871c90ebb 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -344,12 +344,12 @@ public: }; -class sys_var_thd_table_type :public sys_var_thd +class sys_var_thd_storage_engine :public sys_var_thd { protected: ulong SV::*offset; public: - sys_var_thd_table_type(const char *name_arg, ulong SV::*offset_arg) + sys_var_thd_storage_engine(const char *name_arg, ulong SV::*offset_arg) :sys_var_thd(name_arg), offset(offset_arg) {} bool check(THD *thd, set_var *var); @@ -363,6 +363,16 @@ SHOW_TYPE type() { return SHOW_CHAR; } byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); }; +class sys_var_thd_table_type :public sys_var_thd_storage_engine +{ +public: + sys_var_thd_table_type(const char *name_arg, ulong SV::*offset_arg) + :sys_var_thd_storage_engine(name_arg, offset_arg) + {} + void warn_deprecated(THD *thd); + void set_default(THD *thd, enum_var_type type); + bool update(THD *thd, set_var *var); +}; class sys_var_thd_bit :public sys_var_thd { diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index 94ed6410f30..ae040fd92ac 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -213,7 +213,7 @@ character-set=latin2 "This operation cannot be performed with a running slave, run STOP SLAVE first", "This operation requires a running slave, configure slave and do START SLAVE", "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", @@ -272,8 +272,8 @@ character-set=latin2 "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index 8e2e4fac919..b7f947d346e 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -266,8 +266,8 @@ character-set=latin1 "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index 8f8d5dcabfb..9e2bb859a45 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -274,8 +274,8 @@ character-set=latin1 "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index 9750b47ab7f..cffbdeeeca2 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -204,7 +204,7 @@ character-set=latin1 "This operation cannot be performed with a running slave, run STOP SLAVE first", "This operation requires a running slave, configure slave and do START SLAVE", "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", @@ -263,8 +263,8 @@ character-set=latin1 "ZLIB: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "ZLIB: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index ed45006ad0d..34158b491b2 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -209,7 +209,7 @@ character-set=latin7 "This operation cannot be performed with a running slave, run STOP SLAVE first", "This operation requires a running slave, configure slave and do START SLAVE", "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", @@ -268,8 +268,8 @@ character-set=latin7 "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index 84ae6d995cf..9a2b3a5ec6a 100644 --- a/sql/share/french/errmsg.txt +++ b/sql/share/french/errmsg.txt @@ -204,7 +204,7 @@ character-set=latin1 "Cette opération ne peut être réalisée avec un esclave actif, faites STOP SLAVE d'abord", "Cette opération nécessite un esclave actif, configurez les esclaves et faites START SLAVE", "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", @@ -263,8 +263,8 @@ character-set=latin1 "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index 94b9476b0ff..95c00ec2dd9 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -204,7 +204,7 @@ character-set=greek "This operation cannot be performed with a running slave, run STOP SLAVE first", "This operation requires a running slave, configure slave and do START SLAVE", "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", @@ -263,8 +263,8 @@ character-set=greek "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index 67a20b1c63b..4a10797e1d1 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -206,7 +206,7 @@ character-set=latin2 "This operation cannot be performed with a running slave, run STOP SLAVE first", "This operation requires a running slave, configure slave and do START SLAVE", "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", @@ -265,8 +265,8 @@ character-set=latin2 "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt index b2186baf558..2b8a7ea5632 100644 --- a/sql/share/italian/errmsg.txt +++ b/sql/share/italian/errmsg.txt @@ -263,8 +263,8 @@ character-set=latin1 "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index aea9c84b6e6..752ed402190 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -206,7 +206,7 @@ character-set=ujis "This operation cannot be performed with a running slave, run STOP SLAVE first", "This operation requires a running slave, configure slave and do START SLAVE", "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", @@ -265,8 +265,8 @@ character-set=ujis "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index 69bf4043b44..8d98d5cb610 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -204,7 +204,7 @@ character-set=euckr "This operation cannot be performed with a running slave, run STOP SLAVE first", "This operation requires a running slave, configure slave and do START SLAVE", "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", @@ -263,8 +263,8 @@ character-set=euckr "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index 8abc62814ca..f1dd2cb8371 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -206,7 +206,7 @@ character-set=latin1 "This operation cannot be performed with a running slave, run STOP SLAVE first", "This operation requires a running slave, configure slave and do START SLAVE", "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", @@ -265,8 +265,8 @@ character-set=latin1 "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index ed4540c377d..44705db0af5 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -206,7 +206,7 @@ character-set=latin1 "This operation cannot be performed with a running slave, run STOP SLAVE first", "This operation requires a running slave, configure slave and do START SLAVE", "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", @@ -265,8 +265,8 @@ character-set=latin1 "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt index d0891a8080d..622e127dc5e 100644 --- a/sql/share/polish/errmsg.txt +++ b/sql/share/polish/errmsg.txt @@ -208,7 +208,7 @@ character-set=latin2 "This operation cannot be performed with a running slave, run STOP SLAVE first", "This operation requires a running slave, configure slave and do START SLAVE", "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", @@ -267,8 +267,8 @@ character-set=latin2 "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index 341747620d9..a37f29b8a33 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -208,7 +208,7 @@ character-set=latin2 "This operation cannot be performed with a running slave, run STOP SLAVE first", "This operation requires a running slave, configure slave and do START SLAVE", "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", @@ -267,8 +267,8 @@ character-set=latin2 "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt index 61c03f2f960..2dbe6b9184c 100644 --- a/sql/share/russian/errmsg.txt +++ b/sql/share/russian/errmsg.txt @@ -265,8 +265,8 @@ character-set=koi8r "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt index ef9ffab981b..97bef4e1714 100644 --- a/sql/share/serbian/errmsg.txt +++ b/sql/share/serbian/errmsg.txt @@ -258,8 +258,8 @@ character-set=cp1250 "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index daf9e0bd200..e841214ba1c 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -212,7 +212,7 @@ character-set=latin2 "This operation cannot be performed with a running slave, run STOP SLAVE first", "This operation requires a running slave, configure slave and do START SLAVE", "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", @@ -271,8 +271,8 @@ character-set=latin2 "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index 9acc80a2211..cdabd339e1e 100644 --- a/sql/share/spanish/errmsg.txt +++ b/sql/share/spanish/errmsg.txt @@ -265,8 +265,8 @@ character-set=latin1 "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index d8e3291a9f6..aab70294ec8 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -263,8 +263,8 @@ character-set=latin1 "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d rad(er) kapades av group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt index a336eb3e159..828c0a46cad 100644 --- a/sql/share/ukrainian/errmsg.txt +++ b/sql/share/ukrainian/errmsg.txt @@ -268,8 +268,8 @@ character-set=koi8u "Z_BUF_ERROR: Not enough room in the output buffer for zlib (probably, length of uncompressed data was corrupted)", "Z_DATA_ERROR: Input data was corrupted for zlib", "%d line(s) was(were) cut by group_concat()", -"Record count is fewer than the column count at row %ld", -"Record count is more than the column count at row %ld", +"Row %ld doesn't contain data for all columns", +"Row %ld was truncated; It contained more data than there where input columns", "Data truncated, NULL supplied to NOT NULL column '%s' at row %ld", "Data truncated, out of range for column '%s' at row %ld", "Data truncated for column '%s' at row %ld", diff --git a/sql/slave.cc b/sql/slave.cc index 3f8a3c37618..42a1e4e9061 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1388,6 +1388,7 @@ int init_relay_log_info(RELAY_LOG_INFO* rli, const char* info_fname) 1 /* no auto events */, max_relay_log_size ? max_relay_log_size : max_binlog_size)) { + pthread_mutex_unlock(&rli->data_lock); sql_print_error("Failed in open_log() called from init_relay_log_info()"); DBUG_RETURN(1); } @@ -2351,7 +2352,9 @@ improper_arguments: %d timed_out: %d", static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type) { DBUG_ENTER("init_slave_thread"); - thd->system_thread = thd->bootstrap = 1; + thd->system_thread = (thd_type == SLAVE_THD_SQL) ? + SYSTEM_THREAD_SLAVE_SQL : SYSTEM_THREAD_SLAVE_IO; + thd->bootstrap= 1; thd->host_or_ip= ""; thd->client_capabilities = 0; my_net_init(&thd->net, 0); @@ -4034,8 +4037,20 @@ Before assert, my_b_tell(cur_log)=%s rli->event_relay_log_pos=%s", sizeof(rli->event_relay_log_name)-1); flush_relay_log_info(rli); } - - // next log is hot + + /* + Now we want to open this next log. To know if it's a hot log (the one + being written by the I/O thread now) or a cold log, we can use + is_active(); if it is hot, we use the I/O cache; if it's cold we open + the file normally. But if is_active() reports that the log is hot, this + may change between the test and the consequence of the test. So we may + open the I/O cache whereas the log is now cold, which is nonsense. + To guard against this, we need to have LOCK_log. + */ + + DBUG_PRINT("info",("hot_log: %d",hot_log)); + if (!hot_log) /* if hot_log, we already have this mutex */ + pthread_mutex_lock(log_lock); if (rli->relay_log.is_active(rli->linfo.log_file_name)) { #ifdef EXTRA_DEBUG @@ -4048,15 +4063,24 @@ Before assert, my_b_tell(cur_log)=%s rli->event_relay_log_pos=%s", /* Read pointer has to be at the start since we are the only - reader + reader. + We must keep the LOCK_log to read the 4 first bytes, as this is a hot + log (same as when we call read_log_event() above: for a hot log we + take the mutex). */ if (check_binlog_magic(cur_log,&errmsg)) + { + if (!hot_log) pthread_mutex_unlock(log_lock); goto err; + } + if (!hot_log) pthread_mutex_unlock(log_lock); continue; } + if (!hot_log) pthread_mutex_unlock(log_lock); /* - if we get here, the log was not hot, so we will have to - open it ourselves + if we get here, the log was not hot, so we will have to open it + ourselves. We are sure that the log is still not hot now (a log can get + from hot to cold, but not from cold to hot). No need for LOCK_log. */ #ifdef EXTRA_DEBUG sql_print_error("next log '%s' is not active", diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 2527edc1643..2feb9594715 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -697,6 +697,7 @@ int acl_getroot(THD *thd, USER_RESOURCES *mqh, If cipher name is specified, we compare it to actual cipher in use. */ + X509 *cert; if (vio_type(vio) != VIO_TYPE_SSL || SSL_get_verify_result(ssl) != X509_V_OK) break; @@ -717,7 +718,11 @@ int acl_getroot(THD *thd, USER_RESOURCES *mqh, } /* Prepare certificate (if exists) */ DBUG_PRINT("info",("checkpoint 1")); - X509* cert=SSL_get_peer_certificate(ssl); + if (!(cert= SSL_get_peer_certificate(ssl))) + { + user_access=NO_ACCESS; + break; + } DBUG_PRINT("info",("checkpoint 2")); /* If X509 issuer is speified, we check it... */ if (acl_user->x509_issuer) @@ -1246,6 +1251,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(); Query_log_event qinfo(thd, buff, query_length, 0); mysql_bin_log.write(&qinfo); DBUG_RETURN(0); @@ -1317,11 +1323,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 } } @@ -1567,7 +1573,7 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, break; } - USER_RESOURCES mqh = thd->lex->mqh; + USER_RESOURCES mqh= thd->lex->mqh; if (mqh.bits & 1) table->field[28]->store((longlong) mqh.questions); if (mqh.bits & 2) diff --git a/sql/sql_acl.h b/sql/sql_acl.h index 9858b403d27..f17c9781e8c 100644 --- a/sql/sql_acl.h +++ b/sql/sql_acl.h @@ -58,8 +58,6 @@ #define EXTRA_ACL (1L << 29) #define NO_ACCESS (1L << 30) -#ifndef NO_EMBEDDED_ACCESS_CHECKS - /* Defines to change the above bits to how things are stored in tables This is needed as the 'host' and 'db' table is missing a few privileges @@ -127,8 +125,6 @@ public: char *user,*db; }; - - /* prototypes */ bool hostname_requires_resolving(const char *hostname); @@ -153,7 +149,7 @@ my_bool grant_init(THD *thd); void grant_free(void); void grant_reload(THD *thd); bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, - uint show_command=0, bool dont_print_error=0); + uint show_command, bool dont_print_error); bool check_grant_column (THD *thd,TABLE *table, const char *name, uint length, uint show_command=0); bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table); @@ -166,5 +162,7 @@ void get_mqh(const char *user, const char *host, USER_CONN *uc); int mysql_drop_user(THD *thd, List <LEX_USER> &list); int mysql_revoke_all(THD *thd, List <LEX_USER> &list); -#endif /*!NO_EMBEDDED_ACCESS_CHECKS*/ - +#ifdef NO_EMBEDDED_ACCESS_CHECKS +#define check_grant(A,B,C,D,E) 0 +#define check_grant_db(A,B) 0 +#endif diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc index a6c24a25d6e..9e73e06d9c6 100644 --- a/sql/sql_analyse.cc +++ b/sql/sql_analyse.cc @@ -213,8 +213,7 @@ bool test_if_number(NUM_INFO *info, const char *str, uint str_len) info->is_float = 1; // we can't use variable decimals here return 1; } - else - return 0; + return 0; } for (str++; *(end - 1) == '0'; end--); // jump over zeros at the end if (str == end) // number was something like '123.000' @@ -229,11 +228,8 @@ bool test_if_number(NUM_INFO *info, const char *str, uint str_len) info->dval = atod(begin); return 1; } - else - return 0; } - else - return 0; + return 0; } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 5b347267adb..02ecb158ebe 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -513,8 +513,8 @@ void close_temporary_tables(THD *thd) if (query && found_user_tables && mysql_bin_log.is_open()) { /* The -1 is to remove last ',' */ + thd->clear_error(); Query_log_event qinfo(thd, query, (ulong)(end-query)-1, 0); - qinfo.error_code=0; mysql_bin_log.write(&qinfo); } thd->temporary_tables=0; @@ -1752,6 +1752,19 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, const char *table_name=item->table_name; const char *name=item->field_name; uint length=(uint) strlen(name); + char name_buff[NAME_LEN+1]; + + if (db && lower_case_table_names) + { + /* + convert database to lower case for comparision. + We can't do this in Item_field as this would change the + 'name' of the item which may be used in the select list + */ + strmake(name_buff, db, sizeof(name_buff)-1); + my_casedn_str(files_charset_info, name_buff); + db= name_buff; + } if (table_name && table_name[0]) { /* Qualified field */ @@ -1969,7 +1982,8 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields, while ( wild_num && (item= it++)) { if (item->type() == Item::FIELD_ITEM && ((Item_field*) item)->field_name && - ((Item_field*) item)->field_name[0] == '*') + ((Item_field*) item)->field_name[0] == '*' && + !((Item_field*) item)->field) { uint elem= fields.elements; if (insert_fields(thd,tables,((Item_field*) item)->db_name, @@ -2255,7 +2269,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) } } cond_and->used_tables_cache= t1->map | t2->map; - thd->lex->current_select->cond_count+=cond_and->list.elements; + thd->lex->current_select->cond_count+= cond_and->list.elements; if (!table->outer_join) // Not left join { if (!(*conds=and_conds(*conds, cond_and))) diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index edc61acb117..02df644f3b4 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -289,7 +289,7 @@ TODO list: if (thd->temp_tables || global_merge_table_count) - - Another option would be to set thd->lex.safe_to_cache_query to 0 + - Another option would be to set thd->lex->safe_to_cache_query to 0 in 'get_lock_data' if any of the tables was a tmp table or a MRG_ISAM table. (This could be done with almost no speed penalty) @@ -1211,9 +1211,29 @@ void Query_cache::invalidate(char *db) if (query_cache_size > 0) { DUMP(this); - /* invalidate_table reduce list while only root of list remain */ - while (tables_blocks !=0 ) - invalidate_table(tables_blocks); + restart_search: + if (tables_blocks) + { + Query_cache_block *curr= tables_blocks; + Query_cache_block *next; + do + { + next= curr->next; + if (strcmp(db, (char*)(curr->table()->db())) == 0) + invalidate_table(curr); + /* + invalidate_table can freed block on which point 'next' (if + table of this block used only in queries which was deleted + by invalidate_table). As far as we do not allocate new blocks + and mark all headers of freed blocks as 'FREE' (even if they are + merged with other blocks) we can just test type of block + to be sure that block is not deleted + */ + if (next->type == Query_cache_block::FREE) + goto restart_search; + curr= next; + } while (curr != tables_blocks); + } } STRUCT_UNLOCK(&structure_guard_mutex); } @@ -2223,9 +2243,11 @@ void Query_cache::free_memory_block(Query_cache_block *block) { DBUG_ENTER("Query_cache::free_memory_block"); block->used=0; - DBUG_PRINT("qcache",("first_block 0x%lx, block 0x%lx, pnext 0x%lx pprev 0x%lx", - (ulong) first_block, (ulong) block,block->pnext, - (ulong) block->pprev)); + block->type= Query_cache_block::FREE; // mark block as free in any case + DBUG_PRINT("qcache", + ("first_block 0x%lx, block 0x%lx, pnext 0x%lx pprev 0x%lx", + (ulong) first_block, (ulong) block, (ulong) block->pnext, + (ulong) block->pprev)); if (block->pnext != first_block && block->pnext->is_free()) block = join_free_blocks(block, block->pnext); diff --git a/sql/sql_class.h b/sql/sql_class.h index e6b2af317e2..325271822ab 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -711,7 +711,7 @@ public: long dbug_thread_id; pthread_t real_id; uint current_tablenr,tmp_table; - uint server_status,open_options; + uint server_status,open_options,system_thread; uint32 db_length; uint select_number; //number of select (used for EXPLAIN) /* variables.transaction_isolation is reset to this after each commit */ @@ -728,7 +728,7 @@ public: bool last_cuted_field; bool no_errors, password, is_fatal_error; bool query_start_used,last_insert_id_used,insert_id_used,rand_used; - bool system_thread,in_lock_tables,global_read_lock; + bool in_lock_tables,global_read_lock; bool query_error, bootstrap, cleanup_done; enum killed_state { NOT_KILLED=0, KILL_CONNECTION=ER_SERVER_SHUTDOWN, KILL_QUERY=ER_QUERY_INTERRUPTED }; @@ -885,6 +885,11 @@ public: void update_charset(); }; +/* Flags for the THD::system_thread (bitmap) variable */ +#define SYSTEM_THREAD_DELAYED_INSERT 1 +#define SYSTEM_THREAD_SLAVE_IO 2 +#define SYSTEM_THREAD_SLAVE_SQL 4 + /* Used to hold information about file and file structure in exchainge via non-DB file (...INTO OUTFILE..., ...LOAD DATA...) @@ -896,7 +901,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() {} }; @@ -1207,8 +1212,13 @@ class user_var_entry DTCollation collation; }; - -/* Class for unique (removing of duplicates) */ +/* + Unique -- class for unique (removing of duplicates). + Puts all values to the TREE. If the tree becomes too big, + it's dumped to the file. User can request sorted values, or + just iterate through them. In the last case tree merging is performed in + memory simultaneously with iteration, so it should be ~2-3x faster. + */ class Unique :public Sql_alloc { @@ -1222,10 +1232,10 @@ class Unique :public Sql_alloc public: ulong elements; - Unique(qsort_cmp2 comp_func, void * comp_func_fixed_arg, + Unique(qsort_cmp2 comp_func, void *comp_func_fixed_arg, uint size_arg, ulong max_in_memory_size_arg); ~Unique(); - inline bool unique_add(gptr ptr) + inline bool unique_add(void *ptr) { if (tree.elements_in_tree > max_elements && flush()) return 1; @@ -1243,6 +1253,9 @@ public: return sizeof(uint)*(1 + nkeys/max_elems_in_tree); } + void reset(); + bool walk(tree_walk_action action, void *walk_action_arg); + friend int unique_write_to_file(gptr key, element_count count, Unique *unique); friend int unique_write_to_ptrs(gptr key, element_count count, Unique *unique); }; @@ -1253,7 +1266,7 @@ class multi_delete :public select_result TABLE_LIST *delete_tables, *table_being_deleted; Unique **tempfiles; THD *thd; - ha_rows deleted; + ha_rows deleted, found; uint num_of_tables; int error; bool do_delete, transactional_tables, log_delayed, normal_tables; diff --git a/sql/sql_client.cc b/sql/sql_client.cc index 1ae9a23a924..49d0d3087ad 100644 --- a/sql/sql_client.cc +++ b/sql/sql_client.cc @@ -37,9 +37,3 @@ void my_net_local_init(NET *net) #endif } } - -extern "C" { -void mysql_once_init(void) -{ -} -} diff --git a/sql/sql_db.cc b/sql/sql_db.cc index a057e0be967..2d636c51dd4 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -62,7 +62,7 @@ static bool write_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create) ulong length; CHARSET_INFO *cs= (create && create->default_table_charset) ? create->default_table_charset : - thd->variables.collation_database; + thd->variables.collation_server; length= my_sprintf(buf,(buf, "default-character-set=%s\ndefault-collation=%s\n", cs->csname,cs->name)); @@ -101,7 +101,7 @@ static bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create) uint nbytes; bzero((char*) create,sizeof(*create)); - create->default_table_charset= global_system_variables.collation_database; + create->default_table_charset= thd->variables.collation_server; if ((file=my_open(path, O_RDONLY | O_SHARE, MYF(0))) >= 0) { IO_CACHE cache; @@ -289,13 +289,14 @@ int mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info) { thd->db_charset= (create_info && create_info->default_table_charset) ? create_info->default_table_charset : - global_system_variables.collation_database; + thd->variables.collation_server; thd->variables.collation_database= thd->db_charset; } if (mysql_bin_log.is_open()) { Query_log_event qinfo(thd, thd->query, thd->query_length, 0); + thd->clear_error(); mysql_bin_log.write(&qinfo); } send_ok(thd, result); @@ -381,6 +382,7 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) if (mysql_bin_log.is_open()) { Query_log_event qinfo(thd, query, query_length, 0); + thd->clear_error(); mysql_bin_log.write(&qinfo); } send_ok(thd,(ulong) deleted); @@ -660,7 +662,7 @@ bool mysql_change_db(THD *thd, const char *name) load_db_opt(thd, path, &create); thd->db_charset= create.default_table_charset ? create.default_table_charset : - global_system_variables.collation_database; + thd->variables.collation_server; thd->variables.collation_database= thd->db_charset; DBUG_RETURN(0); } diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 3abb09a5d60..03f952f3ff5 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -135,14 +135,20 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order, fields, all_fields, order) || !(sortorder=make_unireg_sortorder(order, &length)) || (table->sort.found_records = filesort(thd, table, sortorder, length, - (SQL_SELECT *) 0, HA_POS_ERROR, + select, HA_POS_ERROR, &examined_rows)) == HA_POS_ERROR) { delete select; free_underlaid_joins(thd, &thd->lex->select_lex); - DBUG_RETURN(-1); // This will force out message + DBUG_RETURN(-1); // This will force out message } + /* + Filesort has already found and selected the rows we want to delete, + so we don't need the where clause + */ + delete select; + select= 0; } init_read_record(&info,thd,table,select,1,1); @@ -204,6 +210,8 @@ cleanup: { 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) @@ -250,7 +258,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) { @@ -354,6 +362,7 @@ bool multi_delete::send_data(List<Item> &values) continue; table->file->position(table->record[0]); + found++; if (secure_counter < 0) { @@ -429,7 +438,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) @@ -439,6 +448,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++) @@ -508,6 +519,8 @@ bool multi_delete::send_eof() { 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) @@ -618,6 +631,7 @@ end: { 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 1de86f486b4..88585db34ce 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -366,6 +366,8 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, { 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) @@ -630,7 +632,7 @@ public: thd.lex->current_select= 0; /* for my_message_sql */ bzero((char*) &thd.net,sizeof(thd.net)); // Safety - thd.system_thread=1; + thd.system_thread= SYSTEM_THREAD_DELAYED_INSERT; thd.host_or_ip= ""; bzero((char*) &info,sizeof(info)); pthread_mutex_init(&mutex,MY_MUTEX_INIT_FAST); @@ -1495,6 +1497,8 @@ bool select_insert::send_eof() /* Write to binlog before commiting transaction */ 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); @@ -1508,7 +1512,6 @@ bool select_insert::send_eof() ::send_error(thd); DBUG_RETURN(1); } - char buff[160]; if (info.handle_duplicates == DUP_IGNORE) sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records, diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index a67ee2385b9..b0381ae1d30 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -455,7 +455,7 @@ int yylex(void *arg, void *yythd) int tokval, result_state; uint length; enum my_lex_states state; - LEX *lex= (((THD *)yythd)->lex); + LEX *lex= ((THD *)yythd)->lex; YYSTYPE *yylval=(YYSTYPE*) arg; CHARSET_INFO *cs= ((THD *) yythd)->charset(); uchar *state_map= cs->state_map; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 181db61013f..fb7d8415e91 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -76,7 +76,7 @@ enum enum_sql_command { SQLCOM_SHOW_SLAVE_HOSTS, SQLCOM_DELETE_MULTI, SQLCOM_UPDATE_MULTI, SQLCOM_SHOW_BINLOG_EVENTS, SQLCOM_SHOW_NEW_MASTER, SQLCOM_DO, SQLCOM_SHOW_WARNS, SQLCOM_EMPTY_QUERY, SQLCOM_SHOW_ERRORS, - SQLCOM_SHOW_COLUMN_TYPES, SQLCOM_SHOW_TABLE_TYPES, SQLCOM_SHOW_PRIVILEGES, + SQLCOM_SHOW_COLUMN_TYPES, SQLCOM_SHOW_STORAGE_ENGINES, SQLCOM_SHOW_PRIVILEGES, SQLCOM_HELP, SQLCOM_DROP_USER, SQLCOM_REVOKE_ALL, SQLCOM_CHECKSUM, SQLCOM_CREATE_PROCEDURE, SQLCOM_CREATE_SPFUNCTION, SQLCOM_CALL, SQLCOM_DROP_PROCEDURE, SQLCOM_ALTER_PROCEDURE,SQLCOM_ALTER_FUNCTION, diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 41d9f0b6c4d..2f8a979b5ee 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -72,10 +72,11 @@ public: }; static int read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table, - List<Item> &fields, READ_INFO &read_info); + List<Item> &fields, READ_INFO &read_info, + ulong skip_lines); static int read_sep_field(THD *thd,COPY_INFO &info,TABLE *table, List<Item> &fields, READ_INFO &read_info, - String &enclosed); + String &enclosed, ulong skip_lines); int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, List<Item> &fields, enum enum_duplicates handle_duplicates, @@ -85,8 +86,8 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, File file; TABLE *table; int error; - String *field_term=ex->field_term,*escaped=ex->escaped, - *enclosed=ex->enclosed; + String *field_term=ex->field_term,*escaped=ex->escaped; + String *enclosed=ex->enclosed; bool is_fifo=0; #ifndef EMBEDDED_LIBRARY LOAD_FILE_INFO lf_info; @@ -95,6 +96,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, /* If no current database, use database where table is located */ char *tdb= thd->db ? thd->db : db; bool transactional_table, log_delayed; + ulong skip_lines= ex->skip_lines; DBUG_ENTER("mysql_load"); #ifdef EMBEDDED_LIBRARY @@ -254,16 +256,18 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, thd->count_cuted_fields= CHECK_FIELD_WARN; /* calc cuted fields */ thd->cuted_fields=0L; - if (ex->line_term->length() && field_term->length()) + /* Skip lines if there is a line terminator */ + if (ex->line_term->length()) { - // ex->skip_lines needs to be preserved for logging - uint skip_lines = ex->skip_lines; - while (skip_lines--) + /* ex->skip_lines needs to be preserved for logging */ + while (skip_lines > 0) { + skip_lines--; if (read_info.next_line()) break; } } + if (!(error=test(read_info.error))) { uint save_time_stamp=table->time_stamp; @@ -279,9 +283,11 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, table->file->deactivate_non_unique_index((ha_rows) 0); table->copy_blobs=1; if (!field_term->length() && !enclosed->length()) - error=read_fixed_length(thd,info,table,fields,read_info); + error=read_fixed_length(thd,info,table,fields,read_info, + skip_lines); else - error=read_sep_field(thd,info,table,fields,read_info,*enclosed); + error=read_sep_field(thd,info,table,fields,read_info,*enclosed, + skip_lines); if (table->file->extra(HA_EXTRA_NO_CACHE)) error=1; /* purecov: inspected */ if (table->file->activate_all_index(thd)) @@ -290,7 +296,8 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, table->time_stamp=save_time_stamp; table->next_number_field=0; } - if (file >= 0) my_close(file,MYF(0)); + if (file >= 0) + my_close(file,MYF(0)); free_blobs(table); /* if pack_blob was used */ table->copy_blobs=0; thd->count_cuted_fields= CHECK_FIELD_IGNORE; @@ -392,7 +399,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; @@ -412,6 +419,17 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields, thd->send_kill_message(); 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 @@ -482,7 +500,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; @@ -533,6 +551,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()) @@ -872,7 +896,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 1ff4d721924..4b1e2397ffd 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -63,14 +63,9 @@ extern "C" int gethostname(char *name, int namelen); static int check_for_max_user_connections(THD *thd, USER_CONN *uc); static void decrease_user_connections(USER_CONN *uc); static bool check_db_used(THD *thd,TABLE_LIST *tables); -#ifndef NO_EMBEDDED_ACCESS_CHECKS static bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *tables); static bool single_table_command_access(THD *thd, ulong privilege, TABLE_LIST *tables, int *res); -#else -#define check_merge_table_access(thd, db, tables) false -#define single_table_command_access(thd, privilege, tables, res) false -#endif static void remove_escape(char *name); static void refresh_status(void); static bool append_file_to_dir(THD *thd, char **filename_ptr, @@ -189,7 +184,6 @@ end: } -#ifndef NO_EMBEDDED_ACCESS_CHECKS /* Check if user exist and password supplied is correct. @@ -222,6 +216,11 @@ int check_user(THD *thd, enum enum_server_command command, { DBUG_ENTER("check_user"); +#ifdef NO_EMBEDDED_ACCESS_CHECKS + thd->master_access= GLOBAL_ACLS; // Full rights + return 0; +#else + my_bool opt_secure_auth_local; pthread_mutex_lock(&LOCK_global_system_variables); opt_secure_auth_local= opt_secure_auth; @@ -346,7 +345,7 @@ int check_user(THD *thd, enum enum_server_command command, } } else - send_ok(thd); + send_ok(thd); thd->password= test(passwd_len); // remember for error messages /* Ready to handle queries */ DBUG_RETURN(0); @@ -367,11 +366,9 @@ int check_user(THD *thd, enum enum_server_command command, thd->host_or_ip, passwd_len ? ER(ER_YES) : ER(ER_NO)); DBUG_RETURN(-1); +#endif /* NO_EMBEDDED_ACCESS_CHECKS */ } -#endif /*!NO_EMBEDDED_ACCESS_CHECKS*/ - - /* Check for maximum allowable user connections, if the mysqld server is started with corresponding variable that is greater then 0. @@ -522,7 +519,6 @@ bool is_update_query(enum enum_sql_command command) return uc_update_queries[command]; } -#ifndef NO_EMBEDDED_ACCESS_CHECKS /* Check if maximum queries per hour limit has been reached returns 0 if OK. @@ -541,6 +537,9 @@ static bool check_mqh(THD *thd, uint check_command) DBUG_ENTER("check_mqh"); DBUG_ASSERT(uc != 0); +#ifdef NO_EMBEDDED_ACCESS_CHECKS + DBUG_RETURN(0); +#else /* If more than a hour since last check, reset resource checking */ if (check_time - uc->intime >= 3600) { @@ -574,12 +573,13 @@ static bool check_mqh(THD *thd, uint check_command) } end: DBUG_RETURN(error); +#endif /* NO_EMBEDDED_ACCESS_CHECKS */ } static void reset_mqh(THD *thd, LEX_USER *lu, bool get_them= 0) { - +#ifndef NO_EMBEDDED_ACCESS_CHECKS (void) pthread_mutex_lock(&LOCK_user_conn); if (lu) // for GRANT { @@ -603,7 +603,8 @@ static void reset_mqh(THD *thd, LEX_USER *lu, bool get_them= 0) { for (uint idx=0;idx < hash_user_connections.records; idx++) { - USER_CONN *uc=(struct user_conn *) hash_element(&hash_user_connections, idx); + USER_CONN *uc=(struct user_conn *) hash_element(&hash_user_connections, + idx); if (get_them) get_mqh(uc->user,uc->host,uc); uc->questions=0; @@ -612,8 +613,8 @@ static void reset_mqh(THD *thd, LEX_USER *lu, bool get_them= 0) } } (void) pthread_mutex_unlock(&LOCK_user_conn); +#endif /* NO_EMBEDDED_ACCESS_CHECKS */ } -#endif /*!NO_EMBEDDED_ACCESS_CHECKS*/ /* Perform handshake, authorize client and update thd ACL variables. @@ -1075,7 +1076,6 @@ extern "C" pthread_handler_decl(handle_bootstrap,arg) thd->query= thd->memdup_w_gap(buff, length+1, thd->db_length+1); thd->query[length] = '\0'; thd->query_id=query_id++; -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (mqh_used && thd->user_connect && check_mqh(thd, SQLCOM_END)) { thd->net.error = 0; @@ -1083,7 +1083,6 @@ extern "C" pthread_handler_decl(handle_bootstrap,arg) free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC)); break; } -#endif mysql_parse(thd,thd->query,length); close_thread_tables(thd); // Free tables if (thd->is_fatal_error) @@ -1147,12 +1146,10 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd) if (!(table=open_ltable(thd, table_list, TL_READ_NO_INSERT))) DBUG_RETURN(1); -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (check_access(thd, SELECT_ACL, db, &table_list->grant.privilege,0,0)) goto err; - if (grant_option && check_grant(thd, SELECT_ACL, table_list)) + if (grant_option && check_grant(thd, SELECT_ACL, table_list, 0, 0)) goto err; -#endif thd->free_list = 0; thd->query_length=(uint) strlen(tbl_name); thd->query = tbl_name; @@ -1459,13 +1456,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd, my_casedn_str(files_charset_info, table_list.real_name); remove_escape(table_list.real_name); // This can't have wildcards -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (check_access(thd,SELECT_ACL,table_list.db,&thd->col_access,0,0)) break; table_list.grant.privilege=thd->col_access; - if (grant_option && check_grant(thd,SELECT_ACL,&table_list,2)) + if (grant_option && check_grant(thd,SELECT_ACL,&table_list,2,0)) break; -#endif /*DONT_ALLOW_SHOW_COMMANDS*/ mysqld_list_fields(thd,&table_list,fields); free_items(thd->free_list); break; @@ -1609,19 +1604,12 @@ bool dispatch_command(enum enum_server_command command, THD *thd, break; case COM_PROCESS_INFO: statistic_increment(com_stat[SQLCOM_SHOW_PROCESSLIST],&LOCK_status); -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (!thd->priv_user[0] && check_global_access(thd,PROCESS_ACL)) break; -#endif mysql_log.write(thd,command,NullS); mysqld_list_processes(thd, -#ifndef NO_EMBEDDED_ACCESS_CHECKS thd->master_access & PROCESS_ACL ? - NullS : thd->priv_user -#else - NullS -#endif - ,0); + NullS : thd->priv_user, 0); break; case COM_PROCESS_KILL: { @@ -1834,6 +1822,7 @@ mysql_execute_command(THD *thd) } } if (&lex->select_lex != lex->all_selects_list && + lex->sql_command != SQLCOM_CREATE_TABLE && lex->unit.create_total_list(thd, lex, &tables, 0)) DBUG_RETURN(0); @@ -1842,11 +1831,7 @@ mysql_execute_command(THD *thd) Except for the replication thread and the 'super' users. */ if (opt_readonly && - !(thd->slave_thread -#ifndef NO_EMBEDDED_ACCESS_CHECKS - || (thd->master_access & SUPER_ACL) -#endif - ) && + !(thd->slave_thread || (thd->master_access & SUPER_ACL)) && (uc_update_queries[lex->sql_command] > 0)) { send_error(thd, ER_CANT_UPDATE_WITH_READLOCK); @@ -1858,7 +1843,6 @@ mysql_execute_command(THD *thd) case SQLCOM_SELECT: { select_result *result=lex->result; -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (tables) { res=check_table_access(thd, @@ -1874,7 +1858,6 @@ mysql_execute_command(THD *thd) res=0; break; // Error message is given } -#endif /* In case of single SELECT unit->global_parameters points on first SELECT TODO: move counters to SELECT_LEX @@ -2111,7 +2094,6 @@ mysql_execute_command(THD *thd) { if (!tables->db) tables->db=thd->db; -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (check_access(thd,CREATE_ACL,tables->db,&tables->grant.privilege,0,0)) goto error; /* purecov: inspected */ if (grant_option) @@ -2119,12 +2101,11 @@ mysql_execute_command(THD *thd) /* Check that the first table has CREATE privilege */ TABLE_LIST *tmp_table_list=tables->next; tables->next=0; - bool error=check_grant(thd,CREATE_ACL,tables); + bool error=check_grant(thd,CREATE_ACL,tables,0,0); tables->next=tmp_table_list; if (error) goto error; } -#endif if (strlen(tables->real_name) > NAME_LEN) { net_printf(thd,ER_WRONG_TABLE_NAME, tables->real_name); @@ -2147,43 +2128,34 @@ mysql_execute_command(THD *thd) case SQLCOM_CREATE_TABLE: { -#ifndef NO_EMBEDDED_ACCESS_CHECKS + /* Skip first table, which is the table we are creating */ + TABLE_LIST *create_table= tables; + tables= tables->next; + lex->select_lex.table_list.first= (byte*) (tables); + create_table->next= 0; + if (&lex->select_lex != lex->all_selects_list && + lex->unit.create_total_list(thd, lex, &tables, 0)) + DBUG_RETURN(-1); + ulong want_priv= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) ? CREATE_TMP_ACL : CREATE_ACL); -#endif - if (!tables->db) - tables->db=thd->db; -#ifndef NO_EMBEDDED_ACCESS_CHECKS - if (check_access(thd,want_priv,tables->db,&tables->grant.privilege,0,0) || - check_merge_table_access(thd, tables->db, + if (check_access(thd, want_priv, create_table->db, + &create_table->grant.privilege, 0, 0) || + check_merge_table_access(thd, create_table->db, (TABLE_LIST *) lex->create_info.merge_list.first)) goto error; /* purecov: inspected */ - if (grant_option && want_priv != CREATE_TMP_ACL) - { - /* Check that the first table has CREATE privilege */ - TABLE_LIST *tmp_table_list=tables->next; - tables->next=0; - bool error=check_grant(thd, want_priv, tables); - tables->next=tmp_table_list; - if (error) + if (grant_option && want_priv != CREATE_TMP_ACL && + check_grant(thd, want_priv, create_table,0,0)) goto error; - } -#endif - if (strlen(tables->real_name) > NAME_LEN) - { - net_printf(thd, ER_WRONG_TABLE_NAME, tables->alias); - res=0; - break; - } #ifndef HAVE_READLINK lex->create_info.data_file_name=lex->create_info.index_file_name=0; #else /* Fix names if symlinked tables */ if (append_file_to_dir(thd, &lex->create_info.data_file_name, - tables->real_name) || + create_table->real_name) || append_file_to_dir(thd,&lex->create_info.index_file_name, - tables->real_name)) + create_table->real_name)) { res=-1; break; @@ -2207,49 +2179,42 @@ mysql_execute_command(THD *thd) select_result *result; if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) && - find_real_table_in_list(tables->next, tables->db, tables->real_name)) + find_real_table_in_list(tables, create_table->db, + create_table->real_name)) { - net_printf(thd,ER_UPDATE_TABLE_USED,tables->real_name); + net_printf(thd,ER_UPDATE_TABLE_USED, create_table->real_name); DBUG_RETURN(-1); } -#ifndef NO_EMBEDDED_ACCESS_CHECKS - if (tables->next) - { - if (check_table_access(thd, SELECT_ACL, tables->next,0)) - goto error; // Error message is given - } -#endif + if (tables && check_table_access(thd, SELECT_ACL, tables,0)) + goto error; // Error message is given select_lex->options|= SELECT_NO_UNLOCK; unit->offset_limit_cnt= select_lex->offset_limit; unit->select_limit_cnt= select_lex->select_limit+ select_lex->offset_limit; if (unit->select_limit_cnt < select_lex->select_limit) - unit->select_limit_cnt= HA_POS_ERROR; // No limit + unit->select_limit_cnt= HA_POS_ERROR; // No limit - /* Skip first table, which is the table we are creating */ - lex->select_lex.table_list.first= - (byte*) (((TABLE_LIST *) lex->select_lex.table_list.first)->next); - if (!(res=open_and_lock_tables(thd,tables->next))) + if (!(res=open_and_lock_tables(thd,tables))) { - if ((result=new select_create(tables->db ? tables->db : thd->db, - tables->real_name, &lex->create_info, + res= -1; // If error + if ((result=new select_create(create_table->db, + create_table->real_name, + &lex->create_info, lex->create_list, lex->key_list, select_lex->item_list,lex->duplicates))) res=handle_select(thd, lex, result); - else - res= -1; } } else // regular create { if (lex->name) - res= mysql_create_like_table(thd, tables, &lex->create_info, + res= mysql_create_like_table(thd, create_table, &lex->create_info, (Table_ident *)lex->name); else { - res= mysql_create_table(thd,tables->db ? tables->db : thd->db, - tables->real_name, &lex->create_info, + res= mysql_create_table(thd,create_table->db, + create_table->real_name, &lex->create_info, lex->create_list, lex->key_list,0,0,0); // do logging } @@ -2261,12 +2226,10 @@ mysql_execute_command(THD *thd) case SQLCOM_CREATE_INDEX: if (!tables->db) tables->db=thd->db; -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (check_access(thd,INDEX_ACL,tables->db,&tables->grant.privilege,0,0)) goto error; /* purecov: inspected */ - if (grant_option && check_grant(thd,INDEX_ACL,tables)) + if (grant_option && check_grant(thd,INDEX_ACL,tables,0,0)) goto error; -#endif thd->slow_command=TRUE; if (end_active_trans(thd)) res= -1; @@ -2334,10 +2297,9 @@ mysql_execute_command(THD *thd) goto error; /* purecov: inspected */ if (!tables->db) tables->db=thd->db; -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (grant_option) { - if (check_grant(thd,ALTER_ACL,tables)) + if (check_grant(thd,ALTER_ACL,tables,0,0)) goto error; if (lex->name && !test_all_bits(priv,INSERT_ACL | CREATE_ACL)) { // Rename of table @@ -2346,11 +2308,10 @@ mysql_execute_command(THD *thd) tmp_table.real_name=lex->name; tmp_table.db=select_lex->db; tmp_table.grant.privilege=priv; - if (check_grant(thd,INSERT_ACL | CREATE_ACL,tables)) + if (check_grant(thd,INSERT_ACL | CREATE_ACL,tables,0,0)) goto error; } } -#endif /* Don't yet allow changing of symlinks with ALTER TABLE */ lex->create_info.data_file_name=lex->create_info.index_file_name=0; /* ALTER TABLE ends previous transaction */ @@ -2378,7 +2339,6 @@ mysql_execute_command(THD *thd) TABLE_LIST *table; if (check_db_used(thd,tables)) goto error; -#ifndef NO_EMBEDDED_ACCESS_CHECKS for (table=tables ; table ; table=table->next->next) { if (check_access(thd, ALTER_ACL | DROP_ACL, table->db, @@ -2392,14 +2352,13 @@ mysql_execute_command(THD *thd) old_list=table[0]; new_list=table->next[0]; old_list.next=new_list.next=0; - if (check_grant(thd,ALTER_ACL,&old_list) || + if (check_grant(thd,ALTER_ACL,&old_list,0,0) || (!test_all_bits(table->next->grant.privilege, INSERT_ACL | CREATE_ACL) && - check_grant(thd,INSERT_ACL | CREATE_ACL, &new_list))) + check_grant(thd,INSERT_ACL | CREATE_ACL, &new_list,0,0))) goto error; } } -#endif query_cache_invalidate3(thd, tables, 0); if (end_active_trans(thd)) res= -1; @@ -2550,12 +2509,10 @@ mysql_execute_command(THD *thd) res= -1; break; case SQLCOM_UPDATE_MULTI: -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (check_access(thd,UPDATE_ACL,tables->db,&tables->grant.privilege,0,0)) goto error; - if (grant_option && check_grant(thd,UPDATE_ACL,tables)) + if (grant_option && check_grant(thd,UPDATE_ACL,tables,0,0)) goto error; -#endif if (select_lex->item_list.elements != lex->value_list.elements) { send_error(thd,ER_WRONG_VALUE_COUNT); @@ -2585,16 +2542,12 @@ mysql_execute_command(THD *thd) case SQLCOM_REPLACE: case SQLCOM_INSERT: { -#ifndef NO_EMBEDDED_ACCESS_CHECKS my_bool update=(lex->value_list.elements ? UPDATE_ACL : 0); ulong privilege= (lex->duplicates == DUP_REPLACE ? INSERT_ACL | DELETE_ACL : INSERT_ACL | update); if (single_table_command_access(thd, privilege, tables, &res)) goto error; -#else - my_bool update=(lex->value_list.elements ? 1 : 0); -#endif if (select_lex->item_list.elements != lex->value_list.elements) { send_error(thd,ER_WRONG_VALUE_COUNT); @@ -2610,12 +2563,10 @@ mysql_execute_command(THD *thd) case SQLCOM_REPLACE_SELECT: case SQLCOM_INSERT_SELECT: { - /* Check that we have modify privileges for the first table and select privileges for the rest */ -#ifndef NO_EMBEDDED_ACCESS_CHECKS { ulong privilege= (lex->duplicates == DUP_REPLACE ? INSERT_ACL | DELETE_ACL : INSERT_ACL); @@ -2623,14 +2574,18 @@ mysql_execute_command(THD *thd) tables->next=0; if (check_access(thd, privilege, tables->db,&tables->grant.privilege,0,0) || - (grant_option && check_grant(thd, privilege, tables))) + (grant_option && check_grant(thd, privilege, tables,0,0))) goto error; tables->next=save_next; if ((res=check_table_access(thd, SELECT_ACL, save_next,0))) goto error; } -#endif + + /* Fix lock for first table */ + if (tables->lock_type == TL_WRITE_DELAYED) + tables->lock_type= TL_WRITE; + /* Don't unlock tables until command is written to binary log */ select_lex->options|= SELECT_NO_UNLOCK; @@ -2664,12 +2619,10 @@ mysql_execute_command(THD *thd) break; } case SQLCOM_TRUNCATE: -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (check_access(thd,DELETE_ACL,tables->db,&tables->grant.privilege,0,0)) goto error; /* purecov: inspected */ - if (grant_option && check_grant(thd,DELETE_ACL,tables)) + if (grant_option && check_grant(thd,DELETE_ACL,tables,0,0)) goto error; -#endif /* Don't allow this within a transaction because we want to use re-generate table @@ -2683,12 +2636,10 @@ mysql_execute_command(THD *thd) break; case SQLCOM_DELETE: { -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (single_table_command_access(thd, DELETE_ACL, tables, &res)) goto error; // Set privilege for the WHERE clause tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege); -#endif res = mysql_delete(thd,tables, select_lex->where, (ORDER*) select_lex->order_list.first, select_lex->select_limit, select_lex->options); @@ -2698,7 +2649,7 @@ mysql_execute_command(THD *thd) } case SQLCOM_DELETE_MULTI: { - TABLE_LIST *aux_tables=(TABLE_LIST *)thd->lex->auxilliary_table_list.first; + TABLE_LIST *aux_tables= (TABLE_LIST *)thd->lex->auxilliary_table_list.first; TABLE_LIST *auxi; uint table_count=0; multi_delete *result; @@ -2810,12 +2761,10 @@ mysql_execute_command(THD *thd) case SQLCOM_DROP_INDEX: if (!tables->db) tables->db=thd->db; -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (check_access(thd,INDEX_ACL,tables->db,&tables->grant.privilege,0,0)) goto error; /* purecov: inspected */ - if (grant_option && check_grant(thd,INDEX_ACL,tables)) + if (grant_option && check_grant(thd,INDEX_ACL,tables,0,0)) goto error; -#endif if (end_active_trans(thd)) res= -1; else @@ -2833,21 +2782,14 @@ mysql_execute_command(THD *thd) break; #endif case SQLCOM_SHOW_PROCESSLIST: -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (!thd->priv_user[0] && check_global_access(thd,PROCESS_ACL)) break; -#endif mysqld_list_processes(thd, -#ifndef NO_EMBEDDED_ACCESS_CHECKS thd->master_access & PROCESS_ACL ? NullS : - thd->priv_user -#else - NullS -#endif - ,lex->verbose); + thd->priv_user,lex->verbose); break; - case SQLCOM_SHOW_TABLE_TYPES: - res= mysqld_show_table_types(thd); + case SQLCOM_SHOW_STORAGE_ENGINES: + res= mysqld_show_storage_engines(thd); break; case SQLCOM_SHOW_PRIVILEGES: res= mysqld_show_privileges(thd); @@ -2870,10 +2812,8 @@ mysql_execute_command(THD *thd) goto error; #else { -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (grant_option && check_access(thd, FILE_ACL, any_db,0,0,0)) goto error; -#endif res= mysqld_show_logs(thd); break; } @@ -2897,7 +2837,6 @@ mysql_execute_command(THD *thd) net_printf(thd,ER_WRONG_DB_NAME, db); goto error; } -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (check_access(thd,SELECT_ACL,db,&thd->col_access,0,0)) goto error; /* purecov: inspected */ if (!thd->col_access && check_grant_db(thd,db)) @@ -2908,7 +2847,6 @@ mysql_execute_command(THD *thd) db); goto error; } -#endif /* grant is checked in mysqld_show_tables */ if (select_lex->options & SELECT_DESCRIBE) res= mysqld_extend_show_tables(thd,db, @@ -2942,13 +2880,11 @@ mysql_execute_command(THD *thd) } remove_escape(db); // Fix escaped '_' remove_escape(tables->real_name); -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (check_access(thd,SELECT_ACL | EXTRA_ACL,db,&thd->col_access,0,0)) goto error; /* purecov: inspected */ tables->grant.privilege=thd->col_access; - if (grant_option && check_grant(thd,SELECT_ACL,tables,2)) + if (grant_option && check_grant(thd,SELECT_ACL,tables,2,0)) goto error; -#endif res= mysqld_show_fields(thd,tables, (lex->wild ? lex->wild->ptr() : NullS), lex->verbose); @@ -2971,13 +2907,11 @@ mysql_execute_command(THD *thd) remove_escape(tables->real_name); if (!tables->db) tables->db=thd->db; -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (check_access(thd,SELECT_ACL,db,&thd->col_access,0,0)) goto error; /* purecov: inspected */ tables->grant.privilege=thd->col_access; - if (grant_option && check_grant(thd,SELECT_ACL,tables,2)) + if (grant_option && check_grant(thd,SELECT_ACL,tables,2,0)) goto error; -#endif res= mysqld_show_keys(thd,tables); break; } @@ -2988,7 +2922,6 @@ mysql_execute_command(THD *thd) case SQLCOM_LOAD: { -#ifndef NO_EMBEDDED_ACCESS_CHECKS uint privilege= (lex->duplicates == DUP_REPLACE ? INSERT_ACL | DELETE_ACL : INSERT_ACL); @@ -3005,11 +2938,11 @@ mysql_execute_command(THD *thd) send_error(thd,ER_NOT_ALLOWED_COMMAND); goto error; } - if (check_access(thd,privilege,tables->db,&tables->grant.privilege,0,0) || - grant_option && check_grant(thd,privilege,tables)) + if (check_access(thd,privilege,tables->db,&tables->grant.privilege,0, + 0) || + grant_option && check_grant(thd,privilege,tables,0,0)) goto error; } -#endif /*NO_EMBEDDED_ACCESS_CHECKS*/ res=mysql_load(thd, lex->exchange, tables, lex->field_list, lex->duplicates, (bool) lex->local_file, lex->lock_option); break; @@ -3249,13 +3182,14 @@ mysql_execute_command(THD *thd) if (grant_option && check_grant(thd, (lex->grant | lex->grant_tot_col | GRANT_ACL), - tables)) + tables,0,0)) goto error; if (!(res = mysql_table_grant(thd,tables,lex->users_list, lex->columns, lex->grant, lex->sql_command == SQLCOM_REVOKE)) && mysql_bin_log.is_open()) { + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, 0); mysql_bin_log.write(&qinfo); } @@ -3274,6 +3208,7 @@ mysql_execute_command(THD *thd) { 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); } @@ -3708,7 +3643,6 @@ error: } -#ifndef NO_EMBEDDED_ACCESS_CHECKS /* Check grants for commands which work only with one table and all other tables belong to subselects. @@ -3729,23 +3663,23 @@ static bool single_table_command_access(THD *thd, ulong privilege, TABLE_LIST *tables, int *res) { - if (check_access(thd, privilege, tables->db, &tables->grant.privilege,0,0)) - return 1; + if (check_access(thd, privilege, tables->db, &tables->grant.privilege,0,0)) + return 1; - // Show only 1 table for check_grant - TABLE_LIST *subselects_tables= tables->next; - tables->next= 0; - if (grant_option && check_grant(thd, privilege, tables)) - return 1; + // Show only 1 table for check_grant + TABLE_LIST *subselects_tables= tables->next; + tables->next= 0; + if (grant_option && check_grant(thd, privilege, tables, 0, 0)) + return 1; - // check rights on tables of subselect (if exists) - if (subselects_tables) - { - tables->next= subselects_tables; - if ((*res= check_table_access(thd, SELECT_ACL, subselects_tables,0))) - return 1; - } - return 0; + // check rights on tables of subselect (if exists) + if (subselects_tables) + { + tables->next= subselects_tables; + if ((*res= check_table_access(thd, SELECT_ACL, subselects_tables,0))) + return 1; + } + return 0; } @@ -3788,6 +3722,9 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, DBUG_RETURN(TRUE); /* purecov: tested */ } +#ifdef NO_EMBEDDED_ACCESS_CHECKS + DBUG_RETURN(0); +#else if ((thd->master_access & want_access) == want_access) { /* @@ -3837,6 +3774,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, thd->priv_host, db ? db : thd->db ? thd->db : "unknown"); /* purecov: tested */ DBUG_RETURN(TRUE); /* purecov: tested */ +#endif /* NO_EMBEDDED_ACCESS_CHECKS */ } @@ -3861,6 +3799,9 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, bool check_global_access(THD *thd, ulong want_access) { +#ifdef NO_EMBEDDED_ACCESS_CHECKS + return 0; +#else char command[128]; if ((thd->master_access & want_access)) return 0; @@ -3868,6 +3809,7 @@ bool check_global_access(THD *thd, ulong want_access) net_printf(thd,ER_SPECIFIC_ACCESS_DENIED_ERROR, command); return 1; +#endif /* NO_EMBEDDED_ACCESS_CHECKS */ } @@ -3932,7 +3874,6 @@ static bool check_merge_table_access(THD *thd, char *db, return error; } -#endif /*!NO_EMBEDDED_ACCESS_CHECKS*/ static bool check_db_used(THD *thd,TABLE_LIST *tables) { @@ -4016,7 +3957,7 @@ void mysql_init_query(THD *thd, bool lexonly) { DBUG_ENTER("mysql_init_query"); - LEX *lex=thd->lex; + LEX *lex= thd->lex; lex->unit.init_query(); lex->unit.init_select(); lex->unit.thd= thd; @@ -4048,7 +3989,9 @@ mysql_init_query(THD *thd, bool lexonly) thd->last_insert_id_used= thd->query_start_used= thd->insert_id_used=0; thd->sent_row_count= thd->examined_row_count= 0; thd->is_fatal_error= thd->rand_used= 0; - thd->server_status &= ~SERVER_MORE_RESULTS_EXISTS; + thd->server_status&= ~ (SERVER_MORE_RESULTS_EXISTS | + SERVER_QUERY_NO_INDEX_USED | + SERVER_QUERY_NO_GOOD_INDEX_USED); thd->tmp_table_used= 0; if (opt_bin_log) reset_dynamic(&thd->user_var_events); @@ -4203,9 +4146,7 @@ mysql_parse(THD *thd, char *inBuf, uint length) else { mysql_execute_command(thd); -#ifndef EMBEDDED_LIBRARY /* TODO query cache in embedded library*/ query_cache_end_of_result(&thd->net); -#endif } } } @@ -4213,7 +4154,6 @@ mysql_parse(THD *thd, char *inBuf, uint length) { DBUG_PRINT("info",("Command aborted. Fatal_error: %d", thd->is_fatal_error)); -#ifndef EMBEDDED_LIBRARY /* TODO query cache in embedded library*/ query_cache_abort(&thd->net); if (thd->lex->sphead) { @@ -4222,7 +4162,6 @@ mysql_parse(THD *thd, char *inBuf, uint length) delete thd->lex->sphead; thd->lex->sphead= NULL; } -#endif } thd->proc_info="freeing items"; free_items(thd->free_list); /* Free strings used by items */ @@ -4272,7 +4211,12 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, if (default_value) { - if (default_value->type() == Item::NULL_ITEM) + if (type == FIELD_TYPE_TIMESTAMP) + { + net_printf(thd, ER_INVALID_DEFAULT, field_name); + DBUG_RETURN(1); + } + else if (default_value->type() == Item::NULL_ITEM) { default_value=0; if ((type_modifier & (NOT_NULL_FLAG | AUTO_INCREMENT_FLAG)) == @@ -4937,10 +4881,8 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, UNLOCK_ACTIVE_MI; } #endif -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (options & REFRESH_USER_RESOURCES) reset_mqh(thd,(LEX_USER *) NULL); -#endif if (write_to_binlog) *write_to_binlog= tmp_write_to_binlog; return result; @@ -4975,18 +4917,14 @@ void kill_one_thread(THD *thd, ulong id, bool only_kill_query) VOID(pthread_mutex_unlock(&LOCK_thread_count)); if (tmp) { -#ifndef NO_EMBEDDED_ACCESS_CHECKS if ((thd->master_access & SUPER_ACL) || !strcmp(thd->user,tmp->user)) -#endif { tmp->awake(only_kill_query ? THD::KILL_QUERY : THD::KILL_CONNECTION); error=0; } -#ifndef NO_EMBEDDED_ACCESS_CHECKS else error=ER_KILL_DENIED_ERROR; -#endif pthread_mutex_unlock(&tmp->LOCK_delete); } diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index bf7da934a2d..964cf55f942 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -545,7 +545,7 @@ static bool mysql_test_insert_fields(PREP_STMT *stmt, if (check_access(thd,privilege,table_list->db, &table_list->grant.privilege,0,0) || - (grant_option && check_grant(thd,privilege,table_list))) + (grant_option && check_grant(thd,privilege,table_list,0,0))) DBUG_RETURN(1); #endif if (open_and_lock_tables(thd, table_list)) @@ -600,7 +600,7 @@ static bool mysql_test_upd_fields(PREP_STMT *stmt, TABLE_LIST *table_list, #ifndef NO_EMBEDDED_ACCESS_CHECKS if (check_access(thd,UPDATE_ACL,table_list->db, &table_list->grant.privilege,0,0) || - (grant_option && check_grant(thd,UPDATE_ACL,table_list))) + (grant_option && check_grant(thd,UPDATE_ACL,table_list,0,0))) DBUG_RETURN(1); #endif if (open_and_lock_tables(thd, table_list)) @@ -641,7 +641,7 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables, SELECT_LEX *select_lex) { THD *thd= stmt->thd; - LEX *lex= thd->lex; + LEX *lex= &thd->main_lex; select_result *result= thd->lex->result; DBUG_ENTER("mysql_test_select_fields"); @@ -703,7 +703,7 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables, static bool send_prepare_results(PREP_STMT *stmt) { THD *thd= stmt->thd; - LEX *lex= thd->lex; + LEX *lex= &thd->main_lex; enum enum_sql_command sql_command= thd->lex->sql_command; DBUG_ENTER("send_prepare_results"); DBUG_PRINT("enter",("command: %d, param_count: %ld", @@ -812,7 +812,7 @@ static bool init_param_items(PREP_STMT *stmt) Item_param **to; uint32 length= thd->query_length; - stmt->lex= *thd->lex; + stmt->lex= thd->main_lex; if (mysql_bin_log.is_open()) { @@ -972,8 +972,8 @@ void mysql_stmt_execute(THD *thd, char *packet) DBUG_VOID_RETURN; } - LEX *thd_lex= thd->lex; - thd->lex= &stmt->lex; + LEX thd_lex= thd->main_lex; + thd->main_lex= stmt->lex; for (sl= stmt->lex.all_selects_list; sl; @@ -1012,7 +1012,7 @@ void mysql_stmt_execute(THD *thd, char *packet) if (!(specialflag & SPECIAL_NO_PRIOR)) my_pthread_setprio(pthread_self(), WAIT_PRIOR); - thd->lex= thd_lex; + thd->main_lex= thd_lex; DBUG_VOID_RETURN; } diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index 5ef8d5d1c1d..29b4f2f4a01 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -81,6 +81,7 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list) { 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_repl.cc b/sql/sql_repl.cc index c0ee4277128..d3c033d985c 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -679,7 +679,7 @@ int start_slave(THD* thd , MASTER_INFO* mi, bool net_report) bit to 0 for the other thread */ if (thd->lex->slave_thd_opt) - thread_mask &= thd->lex->slave_thd_opt; + thread_mask&= thd->lex->slave_thd_opt; if (thread_mask) //some threads are stopped, start them { if (init_master_info(mi,master_info_file,relay_log_info_file, 0)) @@ -700,7 +700,7 @@ int start_slave(THD* thd , MASTER_INFO* mi, bool net_report) mi->rli.until_condition= RELAY_LOG_INFO::UNTIL_MASTER_POS; mi->rli.until_log_pos= thd->lex->mi.pos; /* - We don't check thd->lex.mi.log_file_name for NULL here + We don't check thd->lex->mi.log_file_name for NULL here since it is checked in sql_yacc.yy */ strmake(mi->rli.until_log_name, thd->lex->mi.log_file_name, @@ -975,7 +975,7 @@ int change_master(THD* thd, MASTER_INFO* mi) } thd->proc_info = "Changing master"; - LEX_MASTER_INFO* lex_mi = &thd->lex->mi; + LEX_MASTER_INFO* lex_mi= &thd->lex->mi; // TODO: see if needs re-write if (init_master_info(mi, master_info_file, relay_log_info_file, 0)) { @@ -1204,7 +1204,7 @@ int show_binlog_events(THD* thd) if (mysql_bin_log.is_open()) { - LEX_MASTER_INFO *lex_mi = &thd->lex->mi; + LEX_MASTER_INFO *lex_mi= &thd->lex->mi; ha_rows event_count, limit_start, limit_end; my_off_t pos = max(BIN_LOG_HEADER_SIZE, lex_mi->pos); // user-friendly char search_file_name[FN_REFLEN], *name; @@ -1213,8 +1213,8 @@ int show_binlog_events(THD* thd) LOG_INFO linfo; Log_event* ev; - limit_start = thd->lex->current_select->offset_limit; - limit_end = thd->lex->current_select->select_limit + limit_start; + limit_start= thd->lex->current_select->offset_limit; + limit_end= thd->lex->current_select->select_limit + limit_start; name= search_file_name; if (log_file_name) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 10c4603875d..9f26d7458d0 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1121,8 +1121,21 @@ JOIN::exec() if (select_options & SELECT_DESCRIBE) { - if (!order && !no_order) - order=group_list; + /* + Check if we managed to optimize ORDER BY away and don't use temporary + table to resolve ORDER BY: in that case, we only may need to do + filesort for GROUP BY. + */ + if (!order && !no_order && (!skip_sort_order || !need_tmp)) + { + /* + Reset 'order' to 'group_list' and reinit variables describing + 'order' + */ + order= group_list; + simple_order= simple_group; + skip_sort_order= 0; + } if (order && (const_tables == tables || ((simple_order || skip_sort_order) && @@ -1861,7 +1874,8 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds, } while (keyuse->table == table && keyuse->key == key); if (eq_part.is_prefix(table->key_info[key].key_parts) && - (table->key_info[key].flags & HA_NOSAME) && + ((table->key_info[key].flags & (HA_NOSAME | HA_END_SPACE_KEY)) == + HA_NOSAME) && !table->fulltext_searched) { if (const_ref == eq_part) @@ -2345,10 +2359,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; } @@ -2447,15 +2457,28 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab, SELECT_LEX *select_lex) { uint and_level,i,found_eq_constant; - KEY_FIELD *key_fields,*end; + KEY_FIELD *key_fields, *end, *field; if (!(key_fields=(KEY_FIELD*) thd->alloc(sizeof(key_fields[0])* (thd->lex->current_select->cond_count+1)*2))) return TRUE; /* purecov: inspected */ - and_level=0; end=key_fields; + and_level= 0; + field= end= key_fields; + if (my_init_dynamic_array(keyuse,sizeof(KEYUSE),20,64)) + return TRUE; if (cond) + { add_key_fields(join_tab,&end,&and_level,cond,normal_tables); + for (; field != end ; field++) + { + add_key_part(keyuse,field); + /* Mark that we can optimize LEFT JOIN */ + if (field->val->type() == Item::NULL_ITEM && + !field->field->real_maybe_null()) + field->field->table->reginfo.not_exists_optimize=1; + } + } for (i=0 ; i < tables ; i++) { if (join_tab[i].on_expr) @@ -2464,10 +2487,8 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab, join_tab[i].table->map); } } - if (my_init_dynamic_array(keyuse,sizeof(KEYUSE),20,64)) - return TRUE; /* fill keyuse with found key parts */ - for (KEY_FIELD *field=key_fields ; field != end ; field++) + for ( ; field != end ; field++) add_key_part(keyuse,field); if (select_lex->ftfunc_list->elements) @@ -2717,7 +2738,8 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, !found_ref_or_null) { /* use eq key */ max_key_part= (uint) ~0; - if ((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME) + if ((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY | + HA_END_SPACE_KEY)) == HA_NOSAME) { tmp=prev_record_reads(join,found_ref); records=1.0; @@ -3230,9 +3252,9 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse, return 0; if (j->type == JT_CONST) j->table->const_table= 1; - else if (((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY)) - != HA_NOSAME) || keyparts != keyinfo->key_parts || - null_ref_key) + else if (((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY | + HA_END_SPACE_KEY)) != HA_NOSAME) || + keyparts != keyinfo->key_parts || null_ref_key) { /* Must read with repeat */ j->type= null_ref_key ? JT_REF_OR_NULL : JT_REF; @@ -3529,7 +3551,7 @@ static void make_join_readinfo(JOIN *join, uint options) { uint i; - SELECT_LEX *select_lex = &(join->thd->lex->select_lex); + SELECT_LEX *select_lex= &join->thd->lex->select_lex; DBUG_ENTER("make_join_readinfo"); for (i=join->const_tables ; i < join->tables ; i++) @@ -4053,6 +4075,8 @@ return_zero_rows(JOIN *join, select_result *result,TABLE_LIST *tables, } result->send_eof(); // Should be safe } + /* Update results for FOUND_ROWS */ + join->thd->limit_found_rows= join->thd->examined_row_count= 0; DBUG_RETURN(0); } @@ -6766,7 +6790,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; @@ -8933,7 +8957,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, List<Item> field_list; List<Item> item_list; THD *thd=join->thd; - SELECT_LEX *select_lex = &(join->thd->lex->select_lex); + SELECT_LEX *select_lex= &join->thd->lex->select_lex; select_result *result=join->result; Item *item_null= new Item_null(); CHARSET_INFO *cs= &my_charset_latin1; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 1816e68b706..3dfef4b7189 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -173,11 +173,11 @@ int mysqld_show_tables(THD *thd,const char *db,const char *wild) ** List all table types supported ***************************************************************************/ -int mysqld_show_table_types(THD *thd) +int mysqld_show_storage_engines(THD *thd) { List<Item> field_list; Protocol *protocol= thd->protocol; - DBUG_ENTER("mysqld_show_table_types"); + DBUG_ENTER("mysqld_show_storage_engines"); field_list.push_back(new Item_empty_string("Type",10)); field_list.push_back(new Item_empty_string("Support",10)); @@ -187,7 +187,7 @@ int mysqld_show_table_types(THD *thd) DBUG_RETURN(1); const char *default_type_name= - ha_get_table_type((enum db_type)thd->variables.table_type); + ha_get_storage_engine((enum db_type)thd->variables.table_type); show_table_type_st *types; for (types= sys_table_types; types->type; types++) @@ -384,11 +384,23 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path, #ifdef USE_SYMDIR char *ext; if (my_use_symdir && !strcmp(ext=fn_ext(file->name), ".sym")) + { + /* Only show the sym file if it points to a directory */ + char buff[FN_REFLEN], *end; + MY_STAT status; *ext=0; /* Remove extension */ + unpack_dirname(buff, file->name); + end= strend(buff); + if (end != buff && end[-1] == FN_LIBCHAR) + end[-1]= 0; // Remove end FN_LIBCHAR + if (!my_stat(buff, &status, MYF(0)) || + !MY_S_ISDIR(status.st_mode)) + continue; + } else #endif { - if (file->name[0] == '.' || !MY_S_ISDIR(file->mystat.st_mode) || + if (file->name[0] == '.' || !MY_S_ISDIR(file->mystat->st_mode) || (wild && wild_compare(file->name,wild,0))) continue; } diff --git a/sql/sql_sort.h b/sql/sql_sort.h index 9f95ffa4884..1831c4a2f3d 100644 --- a/sql/sql_sort.h +++ b/sql/sql_sort.h @@ -78,3 +78,4 @@ int merge_buffers(SORTPARAM *param,IO_CACHE *from_file, IO_CACHE *to_file, uchar *sort_buffer, BUFFPEK *lastbuff,BUFFPEK *Fb, BUFFPEK *Tb,int flag); +void reuse_freed_buff(QUEUE *queue, BUFFPEK *reuse, uint key_length); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 9405004abbd..fe2cfcf2b41 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -257,6 +257,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, query_cache_invalidate3(thd, tables, 0); if (!dont_log_query && 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); @@ -306,10 +307,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; @@ -400,7 +401,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_USING_OTHER_HANDLER, ER(ER_WARN_USING_OTHER_HANDLER), - ha_get_table_type(new_db_type), + ha_get_storage_engine(new_db_type), table_name); } db_options=create_info->table_options; @@ -984,8 +985,8 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, thd->tmp_table_used= 1; } if (!tmp_table && !no_log && mysql_bin_log.is_open()) - // Must be written before unlock { + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, test(create_info->options & HA_LEX_CREATE_TMP_TABLE)); @@ -1236,7 +1237,7 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table, } else { - char* backup_dir = thd->lex->backup_dir; + char* backup_dir= thd->lex->backup_dir; char src_path[FN_REFLEN], dst_path[FN_REFLEN]; char* table_name = table->real_name; char* db = thd->db ? thd->db : table->db; @@ -2007,7 +2008,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_USING_OTHER_HANDLER, ER(ER_WARN_USING_OTHER_HANDLER), - ha_get_table_type(new_db_type), + ha_get_storage_engine(new_db_type), new_name); } if (create_info->row_type == ROW_TYPE_NOT_USED) @@ -2072,6 +2073,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, { 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); } @@ -2454,6 +2456,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, } 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); } @@ -2584,6 +2587,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, thd->proc_info="end"; 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 f256506593e..2f4c6b55963 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -359,6 +359,8 @@ int mysql_update(THD *thd, { 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) @@ -480,7 +482,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) {} @@ -584,6 +586,27 @@ int multi_update::prepare(List<Item> ¬_used_values, for (i=0 ; i < table_count ; i++) set_if_bigger(max_fields, fields_for_table[i]->elements); copy_field= new Copy_field[max_fields]; + + /* + Mark all copies of tables that are updates to ensure that + init_read_record() will not try to enable a cache on them + + The problem is that for queries like + + UPDATE t1, t1 AS t2 SET t1.b=t2.c WHERE t1.a=t2.a; + + the row buffer may contain things that doesn't match what is on disk + which will cause an error when reading a row. + (This issue is mostly relevent for MyISAM tables) + */ + for (table_ref= all_tables; table_ref; table_ref=table_ref->next) + { + TABLE *table=table_ref->table; + if (!(tables_to_update & table->map) && + find_real_table_in_list(update_tables, table_ref->db, + table_ref->real_name)) + table->no_cache= 1; // Disable row cache + } DBUG_RETURN(thd->is_fatal_error != 0); } @@ -743,7 +766,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) { @@ -878,8 +901,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; @@ -1005,6 +1031,8 @@ bool multi_update::send_eof() { if (mysql_bin_log.is_open()) { + if (local_error <= 0) + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, log_delayed); if (mysql_bin_log.write(&qinfo) && trans_safe) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index a16fc60dfbd..a5ec1a20959 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -28,7 +28,7 @@ #define MYSQL_YACC #define YYINITDEPTH 100 #define YYMAXDEPTH 3200 /* Because of 64K stack */ -#define Lex ((YYTHD->lex)) +#define Lex (YYTHD->lex) #define Select Lex->current_select #include "mysql_priv.h" #include "slave.h" @@ -390,6 +390,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token SSL_SYM %token STARTING %token STATUS_SYM +%token STORAGE_SYM %token STRAIGHT_JOIN %token SUBJECT_SYM %token TABLES @@ -506,6 +507,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token ELT_FUNC %token ENCODE_SYM %token ENGINE_SYM +%token ENGINES_SYM %token ENCRYPT %token EXPORT_SET %token EXTRACT_SYM @@ -627,9 +629,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %left SHIFT_LEFT SHIFT_RIGHT %left '-' '+' %left '*' '/' '%' DIV_SYM MOD_SYM -%left NEG '~' %left XOR %left '^' +%left NEG '~' %right NOT %right BINARY COLLATE_SYM @@ -706,7 +708,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %type <interval_time_st> interval_time_st -%type <db_type> table_types +%type <db_type> storage_engines %type <row_type> row_types @@ -798,7 +800,7 @@ query: } else { - thd->lex->sql_command = SQLCOM_EMPTY_QUERY; + thd->lex->sql_command= SQLCOM_EMPTY_QUERY; } } | verb_clause END_OF_INPUT {}; @@ -2103,8 +2105,8 @@ create_table_options: | create_table_option ',' create_table_options; create_table_option: - ENGINE_SYM opt_equal table_types { Lex->create_info.db_type= $3; } - | TYPE_SYM opt_equal table_types { Lex->create_info.db_type= $3; WARN_DEPRECATED("TYPE=database_engine","ENGINE=database_engine"); } + ENGINE_SYM opt_equal storage_engines { Lex->create_info.db_type= $3; } + | TYPE_SYM opt_equal storage_engines { Lex->create_info.db_type= $3; WARN_DEPRECATED("TYPE=database_engine","ENGINE=database_engine"); } | MAX_ROWS opt_equal ulonglong_num { Lex->create_info.max_rows= $3; Lex->create_info.used_fields|= HA_CREATE_USED_MAX_ROWS;} | MIN_ROWS opt_equal ulonglong_num { Lex->create_info.min_rows= $3; Lex->create_info.used_fields|= HA_CREATE_USED_MIN_ROWS;} | AVG_ROW_LENGTH opt_equal ULONG_NUM { Lex->create_info.avg_row_length=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AVG_ROW_LENGTH;} @@ -2157,12 +2159,12 @@ create_table_option: { Lex->create_info.data_file_name= $4.str; } | INDEX DIRECTORY_SYM opt_equal TEXT_STRING_sys { Lex->create_info.index_file_name= $4.str; }; -table_types: +storage_engines: ident_or_text { $$ = ha_resolve_by_name($1.str,$1.length); if ($$ == DB_TYPE_UNKNOWN) { - net_printf(YYTHD, ER_UNKNOWN_TABLE_ENGINE, $1.str); + net_printf(YYTHD, ER_UNKNOWN_STORAGE_ENGINE, $1.str); YYABORT; } }; @@ -4053,14 +4055,25 @@ sum_expr: { $$= new Item_sum_unique_users($3,atoi($5.str),atoi($7.str),$9); } | MIN_SYM '(' in_sum_expr ')' { $$=new Item_sum_min($3); } +/* + According to ANSI SQL, DISTINCT is allowed and has + no sence inside MIN and MAX grouping functions; so MIN|MAX(DISTINCT ...) + is processed like an ordinary MIN | MAX() + */ + | MIN_SYM '(' DISTINCT in_sum_expr ')' + { $$=new Item_sum_min($4); } | MAX_SYM '(' in_sum_expr ')' { $$=new Item_sum_max($3); } + | MAX_SYM '(' DISTINCT in_sum_expr ')' + { $$=new Item_sum_max($4); } | STD_SYM '(' in_sum_expr ')' { $$=new Item_sum_std($3); } | VARIANCE_SYM '(' in_sum_expr ')' { $$=new Item_sum_variance($3); } | SUM_SYM '(' in_sum_expr ')' { $$=new Item_sum_sum($3); } + | SUM_SYM '(' DISTINCT in_sum_expr ')' + { $$=new Item_sum_sum_distinct($4); } | GROUP_CONCAT_SYM '(' opt_distinct expr_list opt_gorder_clause opt_gconcat_separator ')' { @@ -5112,7 +5125,7 @@ show_param: lex->select_lex.db= $3; lex->select_lex.options= 0; } - | ENGINE_SYM table_types + | ENGINE_SYM storage_engines { Lex->create_info.db_type= $2; } show_engine_param | opt_full COLUMNS from_or_in table_ident opt_db wild @@ -5162,7 +5175,13 @@ show_param: | TABLE_SYM TYPES_SYM { LEX *lex=Lex; - lex->sql_command= SQLCOM_SHOW_TABLE_TYPES; + lex->sql_command= SQLCOM_SHOW_STORAGE_ENGINES; + WARN_DEPRECATED("SHOW TABLE TYPES", "SHOW [STORAGE] ENGINES"); + } + | opt_storage ENGINES_SYM + { + LEX *lex=Lex; + lex->sql_command= SQLCOM_SHOW_STORAGE_ENGINES; } | PRIVILEGES { @@ -5271,6 +5290,10 @@ master_or_binary: MASTER_SYM | BINARY; +opt_storage: + /* empty */ + | STORAGE_SYM; + opt_db: /* empty */ { $$= 0; } | from_or_in ident { $$= $2.str; }; @@ -5846,6 +5869,7 @@ keyword: | END {} | ENUM {} | ENGINE_SYM {} + | ENGINES_SYM {} | ERRORS {} | ESCAPE_SYM {} | EVENTS_SYM {} @@ -5978,6 +6002,7 @@ keyword: | START_SYM {} | STATUS_SYM {} | STOP_SYM {} + | STORAGE_SYM {} | STRING_SYM {} | SUBDATE_SYM {} | SUBJECT_SYM {} @@ -5992,6 +6017,7 @@ keyword: | TIMESTAMP_DIFF {} | TIME_SYM {} | TYPE_SYM {} + | TYPES_SYM {} | FUNCTION_SYM {} | UNCOMMITTED_SYM {} | UNICODE_SYM {} @@ -6713,6 +6739,7 @@ order_or_limit: union_option: /* empty */ {} + | DISTINCT {} | ALL {Select->master_unit()->union_option|= UNION_ALL;}; singlerow_subselect: diff --git a/sql/table.cc b/sql/table.cc index 7c12762d9c4..912c133e571 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -507,14 +507,17 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, if (primary_key >= MAX_KEY && (keyinfo->flags & HA_NOSAME)) { /* - If the UNIQUE key don't have NULL columns, declare this as - a primary key. + If the UNIQUE key doesn't have NULL columns and is not a part key + declare this as a primary key. */ primary_key=key; for (i=0 ; i < keyinfo->key_parts ;i++) { - if (!key_part[i].fieldnr || - outparam->field[key_part[i].fieldnr-1]->null_ptr) + uint fieldnr= key_part[i].fieldnr; + if (!fieldnr || + outparam->field[fieldnr-1]->null_ptr || + outparam->field[fieldnr-1]->key_length() != + key_part[i].length) { primary_key=MAX_KEY; // Can't be used break; @@ -554,6 +557,12 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, keyinfo->extra_length+=HA_KEY_BLOB_LENGTH; key_part->store_length+=HA_KEY_BLOB_LENGTH; keyinfo->key_length+= HA_KEY_BLOB_LENGTH; + /* + Mark that there may be many matching values for one key + combination ('a', 'a ', 'a '...) + */ + if (!(field->flags & BINARY_FLAG)) + keyinfo->flags|= HA_END_SPACE_KEY; } if (i == 0 && key != primary_key) field->flags |= @@ -591,7 +600,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, } if (field->key_length() != key_part->length) { - key_part->key_part_flag|= HA_PART_KEY; + key_part->key_part_flag|= HA_PART_KEY_SEG; if (!(field->flags & BLOB_FLAG)) { // Create a new field field=key_part->field=field->new_field(&outparam->mem_root, @@ -605,7 +614,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, as we need to test for NULL = NULL. */ if (field->real_maybe_null()) - key_part->key_part_flag|= HA_PART_KEY; + key_part->key_part_flag|= HA_PART_KEY_SEG; } else { // Error: shorten key @@ -1237,14 +1246,17 @@ bool get_field(MEM_ROOT *mem, Field *field, String *res) char *get_field(MEM_ROOT *mem, Field *field) { - char buff[MAX_FIELD_WIDTH]; + char buff[MAX_FIELD_WIDTH], *to; String str(buff,sizeof(buff),&my_charset_bin); uint length; field->val_str(&str,&str); - if (!(length= str.length())) + length= str.length(); + if (!length || !(to= (char*) alloc_root(mem,length+1))) return NullS; - return strmake_root(mem, str.ptr(), length); + memcpy(to,str.ptr(),(uint) length); + to[length]=0; + return to; } diff --git a/sql/table.h b/sql/table.h index e492398ed17..ba7349d33fc 100644 --- a/sql/table.h +++ b/sql/table.h @@ -117,7 +117,7 @@ struct st_table { my_bool fulltext_searched; my_bool crashed; my_bool is_view; - my_bool no_keyread; + my_bool no_keyread, no_cache; my_bool clear_query_id; /* To reset query_id for tables and cols */ my_bool auto_increment_field_not_null; Field *next_number_field, /* Set if next_number is activated */ diff --git a/sql/time.cc b/sql/time.cc index fe22b80d59d..9a18a150c50 100644 --- a/sql/time.cc +++ b/sql/time.cc @@ -124,6 +124,8 @@ long my_gmt_sec(TIME *t, long *my_timezone) tmp-=t->minute*60 + t->second; // Move to previous hour } *my_timezone= current_timezone; + if (tmp < 0 && t->year <= 1900+YY_PART_YEAR) + tmp= 0; return (long) tmp; } /* my_gmt_sec */ @@ -174,42 +176,72 @@ uint calc_days_in_year(uint year) 366 : 365; } -/* Calculate week. If 'with_year' is not set, then return a week 0-53, where - 0 means that it's the last week of the previous year. - If 'with_year' is set then the week will always be in the range 1-53 and - the year out parameter will contain the year for the week */ -uint calc_week(TIME *l_time, bool with_year, bool sunday_first_day_of_week, - uint *year) +/* + The bits in week_format has the following meaning: + WEEK_MONDAY_FIRST (0) If not set Sunday is first day of week + If set Monday is first day of week + WEEK_YEAR (1) If not set Week is in range 0-53 + + Week 0 is returned for the the last week of the previous year (for + a date at start of january) In this case one can get 53 for the + first week of next year. This flag ensures that the week is + relevant for the given year. Note that this flag is only + releveant if WEEK_JANUARY is not set. + + If set Week is in range 1-53. + + In this case one may get week 53 for a date in January (when + the week is that last week of previous year) and week 1 for a + date in December. + + WEEK_FIRST_WEEKDAY (2) If not set Weeks are numbered according + to ISO 8601:1988 + If set The week that contains the first + 'first-day-of-week' is week 1. + + ISO 8601:1988 means that if the week containing January 1 has + four or more days in the new year, then it is week 1; + Otherwise it is the last week of the previous year, and the + next week is week 1. +*/ + +uint calc_week(TIME *l_time, uint week_behaviour, uint *year) { uint days; ulong daynr=calc_daynr(l_time->year,l_time->month,l_time->day); ulong first_daynr=calc_daynr(l_time->year,1,1); - uint weekday=calc_weekday(first_daynr,sunday_first_day_of_week); + bool monday_first= test(week_behaviour & WEEK_MONDAY_FIRST); + bool week_year= test(week_behaviour & WEEK_YEAR); + bool first_weekday= test(week_behaviour & WEEK_FIRST_WEEKDAY); + + uint weekday=calc_weekday(first_daynr, !monday_first); *year=l_time->year; - if (l_time->month == 1 && l_time->day <= 7-weekday && - ((!sunday_first_day_of_week && weekday >= 4) || - (sunday_first_day_of_week && weekday != 0))) + + if (l_time->month == 1 && l_time->day <= 7-weekday) { - /* Last week of the previous year */ - if (!with_year) + if (!week_year && + (first_weekday && weekday != 0 || + !first_weekday && weekday >= 4)) return 0; - with_year=0; // Don't check the week again + week_year= 1; (*year)--; first_daynr-= (days=calc_days_in_year(*year)); weekday= (weekday + 53*7- days) % 7; } - if ((sunday_first_day_of_week && weekday != 0) || - (!sunday_first_day_of_week && weekday >= 4)) + + if ((first_weekday && weekday != 0) || + (!first_weekday && weekday >= 4)) days= daynr - (first_daynr+ (7-weekday)); else days= daynr - (first_daynr - weekday); - if (with_year && days >= 52*7) + + if (week_year && days >= 52*7) { - /* Check if we are on the first week of the next year (or week 53) */ weekday= (weekday + calc_days_in_year(*year)) % 7; - if (weekday < 4) - { // We are at first week on next year + if (!first_weekday && weekday < 4 || + first_weekday && weekday == 0) + { (*year)++; return 1; } @@ -605,7 +637,7 @@ time_t str_to_timestamp(const char *str,uint length) if (str_to_TIME(str,length,&l_time,0) <= TIMESTAMP_DATETIME_ERROR) return(0); - if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR) + if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR-1) { current_thd->cuted_fields++; return(0); diff --git a/sql/udf_example.cc b/sql/udf_example.cc index 6748be5a06f..f0f33ed6fd7 100644 --- a/sql/udf_example.cc +++ b/sql/udf_example.cc @@ -685,7 +685,7 @@ my_bool lookup_init(UDF_INIT *initid, UDF_ARGS *args, char *message) } initid->max_length=11; initid->maybe_null=1; -#if !defined(HAVE_GETHOSTBYADDR_R) && defined(HAVE_SOLARIS_STYLE_GETHOST) +#if !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_SOLARIS_STYLE_GETHOST) (void) pthread_mutex_init(&LOCK_hostname,MY_MUTEX_INIT_SLOW); #endif return 0; @@ -693,7 +693,7 @@ my_bool lookup_init(UDF_INIT *initid, UDF_ARGS *args, char *message) void lookup_deinit(UDF_INIT *initid) { -#if !defined(HAVE_GETHOSTBYADDR_R) && defined(HAVE_SOLARIS_STYLE_GETHOST) +#if !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_SOLARIS_STYLE_GETHOST) (void) pthread_mutex_destroy(&LOCK_hostname); #endif } @@ -760,7 +760,7 @@ my_bool reverse_lookup_init(UDF_INIT *initid, UDF_ARGS *args, char *message) } initid->max_length=32; initid->maybe_null=1; -#if !defined(HAVE_GETHOSTBYADDR_R) && defined(HAVE_SOLARIS_STYLE_GETHOST) +#if !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_SOLARIS_STYLE_GETHOST) (void) pthread_mutex_init(&LOCK_hostname,MY_MUTEX_INIT_SLOW); #endif return 0; @@ -768,7 +768,7 @@ my_bool reverse_lookup_init(UDF_INIT *initid, UDF_ARGS *args, char *message) void reverse_lookup_deinit(UDF_INIT *initid) { -#if !defined(HAVE_GETHOSTBYADDR_R) && defined(HAVE_SOLARIS_STYLE_GETHOST) +#if !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_SOLARIS_STYLE_GETHOST) (void) pthread_mutex_destroy(&LOCK_hostname); #endif } diff --git a/sql/uniques.cc b/sql/uniques.cc index 17c412873d4..037474fae5d 100644 --- a/sql/uniques.cc +++ b/sql/uniques.cc @@ -328,6 +328,7 @@ bool Unique::flush() elements+= tree.elements_in_tree; file_ptr.count=tree.elements_in_tree; file_ptr.file_pos=my_b_tell(&file); + if (tree_walk(&tree, (tree_walk_action) unique_write_to_file, (void*) this, left_root_right) || insert_dynamic(&file_ptrs, (gptr) &file_ptr)) @@ -338,6 +339,237 @@ bool Unique::flush() /* + Clear the tree and the file. + You must call reset() if you want to reuse Unique after walk(). +*/ + +void +Unique::reset() +{ + reset_tree(&tree); + /* + If elements != 0, some trees were stored in the file (see how + flush() works). Note, that we can not count on my_b_tell(&file) == 0 + here, because it can return 0 right after walk(), and walk() does not + reset any Unique member. + */ + if (elements) + { + reset_dynamic(&file_ptrs); + reinit_io_cache(&file, WRITE_CACHE, 0L, 0, 1); + } + elements= 0; +} + +/* + The comparison function, passed to queue_init() in merge_walk() must + use comparison function of Uniques::tree, but compare members of struct + BUFFPEK. +*/ + +struct BUFFPEK_COMPARE_CONTEXT +{ + qsort_cmp2 key_compare; + void *key_compare_arg; +}; + +C_MODE_START + +static int buffpek_compare(void *arg, byte *key_ptr1, byte *key_ptr2) +{ + BUFFPEK_COMPARE_CONTEXT *ctx= (BUFFPEK_COMPARE_CONTEXT *) arg; + return ctx->key_compare(ctx->key_compare_arg, + *((byte **) key_ptr1), *((byte **)key_ptr2)); +} + +C_MODE_END + + +/* + DESCRIPTION + Function is very similar to merge_buffers, but instead of writing sorted + unique keys to the output file, it invokes walk_action for each key. + This saves I/O if you need to pass through all unique keys only once. + SYNOPSIS + merge_walk() + All params are 'IN' (but see comment for begin, end): + merge_buffer buffer to perform cached piece-by-piece loading + of trees; initially the buffer is empty + merge_buffer_size size of merge_buffer. Must be aligned with + key_length + key_length size of tree element; key_length * (end - begin) + must be less or equal than merge_buffer_size. + begin pointer to BUFFPEK struct for the first tree. + end pointer to BUFFPEK struct for the last tree; + end > begin and [begin, end) form a consecutive + range. BUFFPEKs structs in that range are used and + overwritten in merge_walk(). + walk_action element visitor. Action is called for each unique + key. + walk_action_arg argument to walk action. Passed to it on each call. + compare elements comparison function + compare_arg comparison function argument + file file with all trees dumped. Trees in the file + must contain sorted unique values. Cache must be + initialized in read mode. + RETURN VALUE + 0 ok + <> 0 error +*/ + +static bool merge_walk(uchar *merge_buffer, uint merge_buffer_size, + uint key_length, BUFFPEK *begin, BUFFPEK *end, + tree_walk_action walk_action, void *walk_action_arg, + qsort_cmp2 compare, void *compare_arg, + IO_CACHE *file) +{ + BUFFPEK_COMPARE_CONTEXT compare_context = { compare, compare_arg }; + QUEUE queue; + if (end <= begin || + merge_buffer_size < key_length * (end - begin + 1) || + init_queue(&queue, end - begin, offsetof(BUFFPEK, key), 0, + buffpek_compare, &compare_context)) + return 1; + /* we need space for one key when a piece of merge buffer is re-read */ + merge_buffer_size-= key_length; + uchar *save_key_buff= merge_buffer + merge_buffer_size; + uint max_key_count_per_piece= merge_buffer_size/(end-begin)/key_length; + /* if piece_size is aligned reuse_freed_buffer will always hit */ + uint piece_size= max_key_count_per_piece * key_length; + uint bytes_read; /* to hold return value of read_to_buffer */ + BUFFPEK *top; + int res= 1; + /* + Invariant: queue must contain top element from each tree, until a tree + is not completely walked through. + Here we're forcing the invariant, inserting one element from each tree + to the queue. + */ + for (top= begin; top != end; ++top) + { + top->base= merge_buffer + (top - begin) * piece_size; + top->max_keys= max_key_count_per_piece; + bytes_read= read_to_buffer(file, top, key_length); + if (bytes_read == (uint) (-1)) + goto end; + DBUG_ASSERT(bytes_read); + queue_insert(&queue, (byte *) top); + } + top= (BUFFPEK *) queue_top(&queue); + while (queue.elements > 1) + { + /* + Every iteration one element is removed from the queue, and one is + inserted by the rules of the invariant. If two adjacent elements on + the top of the queue are not equal, biggest one is unique, because all + elements in each tree are unique. Action is applied only to unique + elements. + */ + void *old_key= top->key; + /* + read next key from the cache or from the file and push it to the + queue; this gives new top. + */ + top->key+= key_length; + if (--top->mem_count) + queue_replaced(&queue); + else /* next piece should be read */ + { + /* save old_key not to overwrite it in read_to_buffer */ + memcpy(save_key_buff, old_key, key_length); + old_key= save_key_buff; + bytes_read= read_to_buffer(file, top, key_length); + if (bytes_read == (uint) (-1)) + goto end; + else if (bytes_read > 0) /* top->key, top->mem_count are reset */ + queue_replaced(&queue); /* in read_to_buffer */ + else + { + /* + Tree for old 'top' element is empty: remove it from the queue and + give all its memory to the nearest tree. + */ + queue_remove(&queue, 0); + reuse_freed_buff(&queue, top, key_length); + } + } + top= (BUFFPEK *) queue_top(&queue); + /* new top has been obtained; if old top is unique, apply the action */ + if (compare(compare_arg, old_key, top->key)) + { + if (walk_action(old_key, 1, walk_action_arg)) + goto end; + } + } + /* + Applying walk_action to the tail of the last tree: this is safe because + either we had only one tree in the beginning, either we work with the + last tree in the queue. + */ + do + { + do + { + if (walk_action(top->key, 1, walk_action_arg)) + goto end; + top->key+= key_length; + } + while (--top->mem_count); + bytes_read= read_to_buffer(file, top, key_length); + if (bytes_read == (uint) (-1)) + goto end; + } + while (bytes_read); + res= 0; +end: + delete_queue(&queue); + return res; +} + + +/* + DESCRIPTION + Walks consecutively through all unique elements: + if all elements are in memory, then it simply invokes 'tree_walk', else + all flushed trees are loaded to memory piece-by-piece, pieces are + sorted, and action is called for each unique value. + Note: so as merging resets file_ptrs state, this method can change + internal Unique state to undefined: if you want to reuse Unique after + walk() you must call reset() first! + SYNOPSIS + Unique:walk() + All params are 'IN': + action function-visitor, typed in include/my_tree.h + function is called for each unique element + arg argument for visitor, which is passed to it on each call + RETURN VALUE + 0 OK + <> 0 error + */ + +bool Unique::walk(tree_walk_action action, void *walk_action_arg) +{ + if (elements == 0) /* the whole tree is in memory */ + return tree_walk(&tree, action, walk_action_arg, left_root_right); + + /* flush current tree to the file to have some memory for merge buffer */ + if (flush()) + return 1; + if (flush_io_cache(&file) || reinit_io_cache(&file, READ_CACHE, 0L, 0, 0)) + return 1; + uchar *merge_buffer= (uchar *) my_malloc(max_in_memory_size, MYF(0)); + if (merge_buffer == 0) + return 1; + int res= merge_walk(merge_buffer, max_in_memory_size, size, + (BUFFPEK *) file_ptrs.buffer, + (BUFFPEK *) file_ptrs.buffer + file_ptrs.elements, + action, walk_action_arg, + tree.compare, tree.custom_arg, &file); + x_free(merge_buffer); + return res; +} + +/* Modify the TABLE element so that when one calls init_records() the rows will be read in priority order. */ @@ -358,7 +590,7 @@ bool Unique::get(TABLE *table) return 0; } } - /* Not enough memory; Save the result to file */ + /* Not enough memory; Save the result to file && free memory used by tree */ if (flush()) return 1; @@ -382,7 +614,7 @@ bool Unique::get(TABLE *table) bzero((char*) &sort_param,sizeof(sort_param)); sort_param.max_rows= elements; sort_param.sort_form=table; - sort_param.rec_length= sort_param.sort_length=sort_param.ref_length= + sort_param.rec_length= sort_param.sort_length= sort_param.ref_length= size; sort_param.keys= max_in_memory_size / sort_param.sort_length; sort_param.not_killable=1; diff --git a/strings/strto.c b/strings/strto.c index 0c215ff270c..6f12656cb20 100644 --- a/strings/strto.c +++ b/strings/strto.c @@ -35,8 +35,6 @@ it can be compiled with the UNSIGNED and/or LONGLONG flag set */ -#define strtoll glob_strtoll /* Fix for True64 */ - #include <my_global.h> #include "m_string.h" #include "m_ctype.h" diff --git a/strings/strtoll.c b/strings/strtoll.c index 8d0ba21d576..b0b4ef328fc 100644 --- a/strings/strtoll.c +++ b/strings/strtoll.c @@ -16,8 +16,9 @@ /* This is defines strtoll() if neaded */ +#define strtoll glob_strtoll /* Fix for True64 */ + #include <my_global.h> -#include <m_string.h> #if !defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG) #define USE_LONGLONG #include "strto.c" diff --git a/strings/strtoull.c b/strings/strtoull.c index 25201e546ce..f4f3ce19bf7 100644 --- a/strings/strtoull.c +++ b/strings/strtoull.c @@ -17,7 +17,6 @@ /* This is defines strtoull() */ #include <my_global.h> -#include <m_string.h> #if !defined(HAVE_STRTOULL) && defined(HAVE_LONG_LONG) #define USE_UNSIGNED #define USE_LONGLONG diff --git a/support-files/MacOSX/MySQL b/support-files/MacOSX/MySQL index dfba5f8f982..f6579700384 100755 --- a/support-files/MacOSX/MySQL +++ b/support-files/MacOSX/MySQL @@ -11,6 +11,13 @@ # Written by Lenz Grimmer <lenz@mysql.com> # +# Suppress the annoying "$1: unbound variable" error when no option +# was given +if [ -z $1 ] ; then + echo "Usage: $0 [start|stop|restart] " + exit 1 +fi + # Source the common setup functions for startup scripts test -r /etc/rc.common || exit 1 . /etc/rc.common diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh index 30ee4ab545f..5911ecd942b 100644 --- a/support-files/mysql.server.sh +++ b/support-files/mysql.server.sh @@ -145,7 +145,7 @@ case "$mode" in then # Give extra arguments to mysqld with the my.cnf file. This script may # be overwritten at next upgrade. - $bindir/mysqld_safe --datadir=$datadir --pid-file=$pid_file & + $bindir/mysqld_safe --datadir=$datadir --pid-file=$pid_file >/dev/null 2>&1 & # Make lock for RedHat / SuSE if test -w /var/lock/subsys then diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 0eb642650d7..5a9fbf64b1c 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -260,7 +260,7 @@ export PATH # If we want to compile with RAID using gcc 3, we need to use # gcc instead of g++ to avoid linking problems (RAID code is written in C++) -if gcc -v 2>&1 | grep 'version 3' > /dev/null 2>&1 +test -z $CXX && test -z $CC && if gcc -v 2>&1 | grep 'gcc version 3' > /dev/null 2>&1 then export CXX="gcc" fi @@ -443,11 +443,12 @@ fi [ "$RBR" != "/" ] && [ -d $RBR ] && rm -rf $RBR; %files server -%defattr(755 root, root) +%defattr(-,root,root,0755) -%doc %attr(644, root, root) COPYING README -%doc %attr(644, root, root) Docs/manual.{html,ps,texi,txt} Docs/manual_toc.html -%doc %attr(644, root, root) support-files/my-*.cnf +%doc COPYING README +%doc Docs/manual.{html,ps,texi,txt} +%doc Docs/manual_toc.html +%doc support-files/my-*.cnf %doc %attr(644, root, root) %{_infodir}/mysql.info* @@ -500,6 +501,7 @@ fi %attr(755, root, root) %{_datadir}/mysql/ %files client +%defattr(-, root, root, 0755) %attr(755, root, root) %{_bindir}/msql2mysql %attr(755, root, root) %{_bindir}/mysql %attr(755, root, root) %{_bindir}/mysql_find_rows @@ -527,7 +529,7 @@ fi /sbin/ldconfig %files devel -%defattr(644 root, root) +%defattr(-, root, root, 0755) %attr(755, root, root) %{_bindir}/comp_err %attr(755, root, root) %{_bindir}/mysql_config %dir %attr(755, root, root) %{_includedir}/mysql @@ -548,11 +550,12 @@ fi %{_libdir}/mysql/libvio.a %files shared -%defattr(755 root, root) +%defattr(-, root, root, 0755) # Shared libraries (omit for architectures that don't support them) %{_libdir}/*.so* %files bench +%defattr(-, root, root, 0755) %attr(-, root, root) %{_datadir}/sql-bench %attr(-, root, root) %{_datadir}/mysql-test %attr(755, root, root) %{_bindir}/mysqlmanager @@ -560,15 +563,25 @@ fi %attr(755, root, root) %{_bindir}/mysqlmanagerc %files Max +%defattr(-, root, root, 0755) %attr(755, root, root) %{_sbindir}/mysqld-max %attr(644, root, root) %{_libdir}/mysql/mysqld-max.sym %files embedded +%defattr(-, root, root, 0755) %attr(644, root, root) %{_libdir}/mysql/libmysqld.a # The spec file changelog only includes changes made to the spec file # itself %changelog +* Fri Dec 13 2003 Lenz Grimmer <lenz@mysql.com> + +- fixed file permissions (BUG 1672) + +* Thu Dec 11 2003 Lenz Grimmer <lenz@mysql.com> + +- made testing for gcc3 a bit more robust + * Fri Dec 05 2003 Lenz Grimmer <lenz@mysql.com> - added missing file mysql_create_system_tables to the server subpackage |