diff options
271 files changed, 25893 insertions, 3784 deletions
diff --git a/BUILD/compile-solaris-amd64 b/BUILD/compile-solaris-amd64 index f128fb12973..9204170b908 100755 --- a/BUILD/compile-solaris-amd64 +++ b/BUILD/compile-solaris-amd64 @@ -1,55 +1,10 @@ -#!/usr/bin/bash - -function _find_mysql_root () ( - while [ "x$PWD" != "x/" ]; do - # Check if some directories are present - if [ -d BUILD -a -d sql -a -d mysys ]; then - echo "$PWD" - return 0 - fi - cd .. - done - return 1 -) - -make -k clean || true -/bin/rm -f */.deps/*.P config.cache - +#! /bin/sh path=`dirname $0` -. "$path/autorun.sh" - -warning_flags="-Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wparentheses -Wsign-compare -Wwrite-strings -Wunused" -compiler_flags="-g -O3 -fno-omit-frame-pointer" - -export CC CXX CFLAGS CXXFLAGS LDFLAGS LIBS -CC="gcc" -CXX="gcc" -CFLAGS="$warning_flags $compiler_flags" -CXXFLAGS="" -LDFLAGS="-O3 -g -static-libgcc" -LIBS=-lmtmalloc -root=$(_find_mysql_root) - -$root/configure \ - --prefix=/usr/local/mysql \ - --localstatedir=/usr/local/mysql/data \ - --libexecdir=/usr/local/mysql/bin \ - --with-extra-charsets=complex \ - --enable-thread-safe-client \ - --enable-local-infile \ - --with-zlib-dir=bundled \ - --with-big-tables \ - --with-readline \ - --with-archive-storage-engine \ - --with-named-curses=-lcurses \ - --with-big-tables \ - --with-innodb \ - --with-berkeley-db \ - --with-example-storage-engine \ - --with-blackhole-storage-engine \ - --with-ndbcluster \ - --with-federated-storage-engine \ - --with-csv-storage-engine \ - --with-ssl \ - --with-embedded-server \ - --disable-shared +. "$path/SETUP.sh" +amd64_cflags="-m64 -mtune=athlon64" +extra_flags="$amd64_cflags $max_cflags" +c_warnings="$c_warnings" +cxx_warnings="$cxx_warnings" +extra_configs="$amd64_configs $debug_configs $max_configs --enable-thread-safe-client" + +. "$path/FINISH.sh" diff --git a/BUILD/compile-solaris-amd64-debug b/BUILD/compile-solaris-amd64-debug new file mode 100644 index 00000000000..ad1c298907f --- /dev/null +++ b/BUILD/compile-solaris-amd64-debug @@ -0,0 +1,10 @@ +#! /bin/sh +path=`dirname $0` +. "$path/SETUP.sh" +amd64_cflags="-m64 -mtune=athlon64" +extra_flags="$amd64_cflags $debug_cflags $max_cflags" +c_warnings="$c_warnings $debug_extra_warnings" +cxx_warnings="$cxx_warnings $debug_extra_warnings" +extra_configs="$amd64_configs $debug_configs $max_configs --enable-thread-safe-client" + +. "$path/FINISH.sh" diff --git a/BUILD/compile-solaris-amd64-forte b/BUILD/compile-solaris-amd64-forte new file mode 100644 index 00000000000..63aceb16c04 --- /dev/null +++ b/BUILD/compile-solaris-amd64-forte @@ -0,0 +1,52 @@ +#! /bin/sh + +gmake -k clean || true +/bin/rm -f */.deps/*.P config.cache + +path=`dirname $0` +. "$path/autorun.sh" + +# For "optimal" code for this computer add -fast to EXTRA +# To compile 64 bit, add -xarch=v9 to EXTRA_64_BIT + +EXTRA_64_BIT="-xarch=amd64" +EXTRA="-fast" + +# +# The following should not need to be touched +# + +export CC CXX CFLAGS CXXFLAGS +STD="-g -mt -D_FORTEC_ $EXTRA $EXTRA_64_BIT" +ASFLAGS="$EXTRA_64_BIT" +CC=cc-5.0 +CFLAGS="-Xa -xstrconst $STD" +CXX=CC +CXXFLAGS="-noex $STD" +./configure \ + --prefix=/usr/local/mysql \ + --localstatedir=/usr/local/mysql/data \ + --libexecdir=/usr/local/mysql/bin \ + --with-extra-charsets=complex \ + --enable-thread-safe-client \ + --enable-local-infile \ + --with-zlib-dir=bundled \ + --with-big-tables \ + --with-readline \ + --with-archive-storage-engine \ + --with-named-curses=-lcurses \ + --with-big-tables \ + --with-innodb \ + --with-example-storage-engine \ + --with-blackhole-storage-engine \ + --with-federated-storage-engine \ + --with-csv-storage-engine \ + --with-ssl \ + --enable-assembler + +# Not including: +# --with-ndbcluster +# --with-berkeley-db + +gmake -j4 +test $? = 0 && make test diff --git a/BUILD/compile-solaris-amd64-forte-debug b/BUILD/compile-solaris-amd64-forte-debug new file mode 100644 index 00000000000..8e3ade9b429 --- /dev/null +++ b/BUILD/compile-solaris-amd64-forte-debug @@ -0,0 +1,54 @@ +#! /bin/sh + +gmake -k clean || true +/bin/rm -f */.deps/*.P config.cache + +path=`dirname $0` +. "$path/autorun.sh" + +# To compile 64 bit, add -xarch=amd64 to EXTRA_64_BIT +EXTRA_64_BIT="-xarch=amd64" + +# For "optimal" code for this computer add -fast to EXTRA. Note that +# this causes problem with debugging the program since -fast implies +# -xO5. +EXTRA="" + +# +# The following should not need to be touched +# + +export CC CXX CFLAGS CXXFLAGS +STD="-g -mt -D_FORTEC_ $EXTRA $EXTRA_64_BIT $debug_cflags" +ASFLAGS="$EXTRA_64_BIT" +CC=cc-5.0 +CFLAGS="-Xa -xstrconst $STD" +CXX=CC +CXXFLAGS="-noex $STD" +./configure \ + --prefix=/usr/local/mysql \ + --localstatedir=/usr/local/mysql/data \ + --libexecdir=/usr/local/mysql/bin \ + --with-extra-charsets=complex \ + --enable-thread-safe-client \ + --enable-local-infile \ + --with-zlib-dir=bundled \ + --with-big-tables \ + --with-readline \ + --with-archive-storage-engine \ + --with-named-curses=-lcurses \ + --with-big-tables \ + --with-innodb \ + --with-example-storage-engine \ + --with-blackhole-storage-engine \ + --with-federated-storage-engine \ + --with-csv-storage-engine \ + --with-ssl \ + --with-debug \ + --enable-assembler + +# Not including: +# --with-ndbcluster +# --with-berkeley-db + +gmake -j4 diff --git a/BitKeeper/triggers/post-commit.innodb.pl b/BitKeeper/triggers/post-commit.innodb.pl new file mode 100755 index 00000000000..44d98b04838 --- /dev/null +++ b/BitKeeper/triggers/post-commit.innodb.pl @@ -0,0 +1,22 @@ +#! /usr/bin/perl + +use strict; +use warnings; + +use FindBin; +require "$FindBin::Bin/triggers-lib.pl"; + +# Don't run unless commit was successful +check_status() || exit 0; + +my $cset = latest_cset(); + +# Read most recent ChangeSet's changed files. Send merge changes along, since +# they'll need to be incorporated in InnoDB's source tree eventually. +my $changes = innodb_get_changes('cset', $cset, 'yes') + or exit 0; + +innodb_send_changes_email($cset, $changes) + or exit 1; + +exit 0; diff --git a/BitKeeper/triggers/post-incoming.innodb.pl b/BitKeeper/triggers/post-incoming.innodb.pl new file mode 100755 index 00000000000..4b100d88037 --- /dev/null +++ b/BitKeeper/triggers/post-incoming.innodb.pl @@ -0,0 +1,30 @@ +#! /usr/bin/perl + +use strict; +use warnings; + +use FindBin; +require "$FindBin::Bin/triggers-lib.pl"; + +# Don't run unless push/pull was successful +check_status() or exit 0; + +# Don't run if push/pull is in local clones +exit 0 if repository_type() eq 'local'; + +# For each pushed ChangeSet, check it for InnoDB files and send +# diff of entire ChangeSet to InnoDB developers if such changes +# exist. + +my $error = 0; + +foreach my $cset (read_bk_csetlist()) +{ + my $changes = innodb_get_changes('cset', $cset, 'yes') + or next; + + innodb_send_changes_email($cset, $changes) + or $error = 1; +} + +exit ($error == 0 ? 0 : 1); diff --git a/BitKeeper/triggers/pre-commit.innodb.pl b/BitKeeper/triggers/pre-commit.innodb.pl new file mode 100755 index 00000000000..6e2b65113b0 --- /dev/null +++ b/BitKeeper/triggers/pre-commit.innodb.pl @@ -0,0 +1,21 @@ +#! /usr/bin/perl + +use strict; +use warnings; + +use FindBin; +require "$FindBin::Bin/triggers-lib.pl"; + +die "$0: Script error: \$BK_PENDING is not set in pre-commit trigger\n" + unless defined $ENV{BK_PENDING}; + +# Read changed files from $BK_PENDING directly. Do not bother user about +# merge changes; they don't have any choice, the merge must be done. +my $changes = innodb_get_changes('file', $ENV{BK_PENDING}, undef) + or exit 0; + +innodb_inform_and_query_user($changes) + or exit 1; # Abort commit + +# OK, continue with commit +exit 0; diff --git a/BitKeeper/triggers/triggers-lib.pl b/BitKeeper/triggers/triggers-lib.pl new file mode 100644 index 00000000000..1c5f7a85726 --- /dev/null +++ b/BitKeeper/triggers/triggers-lib.pl @@ -0,0 +1,360 @@ +# To use this convenience library in a trigger, simply require it at +# at the top of the script. For example: +# +# #! /usr/bin/perl +# +# use FindBin; +# require "$FindBin::Bin/triggers-lib.pl"; +# +# FindBin is needed, because sometimes a trigger is called from the +# RESYNC directory, and the trigger dir is ../BitKeeper/triggers + +use strict; +use warnings; + +use Carp; +use FindBin; + + +my $mysql_version = "5.0"; + +# These addresses must be kept current in all MySQL versions. +# See the wiki page InnoDBandOracle. +#my @innodb_to_email = ('dev_innodb_ww@oracle.com'); +#my @innodb_cc_email = ('dev-innodb@mysql.com'); +# FIXME: Keep this for testing; remove it once it's been used for a +# week or two. +my @innodb_to_email = ('tim@mysql.com'); +my @innodb_cc_email = (); + +# This is for MySQL <= 5.0. Regex which defines the InnoDB files +# which should generally not be touched by MySQL developers. +my $innodb_files_description = <<EOF; + innobase/* + mysql-test/t/innodb* (except mysql-test/t/innodb_mysql*) + mysql-test/r/innodb* (except mysql-test/r/innodb_mysql*) + sql/ha_innodb* +EOF +my $innodb_files_regex = qr{ + ^ + ( + # Case 1: innobase/* + innobase/ + | + # Case 2: mysql-test/[tr]/innodb* (except innodb_mysql*) + mysql-test/(t|r)/SCCS/s.innodb + # The mysql-test/[tr]/innodb_mysql* are OK to edit + (?!_mysql) + | + # Case 3: sql/ha_innodb* + sql/SCCS/s.ha_innodb + ) +}x; + + +# See 'bk help log', and the format of, e.g., $BK_PENDING. +# Important: this already contains the terminating newline! +my $file_rev_dspec = ':SFILE:|:REV:\n'; + +my $bktmp = "$FindBin::Bin/../tmp"; + +my $sendmail; +foreach ('/usr/sbin/sendmail', 'sendmail') { + $sendmail = $_; + last if -x $sendmail; +} +my $from = $ENV{REAL_EMAIL} || $ENV{USER} . '@mysql.com'; + + +# close_or_warn +# $fh file handle to be closed +# $description description of the file handle +# RETURN Return value of close($fh) +# +# Print a nice warning message if close() isn't successful. See +# perldoc perlvar and perldoc -f close for details. + +sub close_or_warn (*$) +{ + my ($fh, $description) = @_; + + my $status = close $fh; + if (not $status) { + warn "$0: error on close of '$description': ", + ($! ? "$!" : "exit status " . ($? >> 8)), "\n"; + } + + return $status; +} + + +# check_status +# $warn If true, warn about bad status +# RETURN TRUE, if $BK_STATUS is "OK"; FALSE otherwise +# +# Also checks the undocumented $BK_COMMIT env variable + +sub check_status +{ + my ($warn) = @_; + + my $status = (grep { defined $_ } + $ENV{BK_STATUS}, $ENV{BK_COMMIT}, '<undef>')[0]; + + unless ($status eq 'OK') + { + warn "Bad BK_STATUS '$status'\n" if $warn; + return undef; + } + + return 1; +} + + +# repository_location +# +# RETURN ('HOST', 'ROOT') for the repository being modified + +sub repository_location +{ + if ($ENV{BK_SIDE} eq 'client') { + return ($ENV{BK_HOST}, $ENV{BK_ROOT}); + } else { + return ($ENV{BKD_HOST}, $ENV{BKD_ROOT}); + } +} + + +# repository_type +# RETURN: +# 'main' for repo on bk-internal with post-incoming.bugdb trigger +# 'team' for repo on bk-internal with post-incoming.queuepush.pl trigger +# 'local' otherwise +# +# This definition may need to be modified if the host name or triggers change. + +sub repository_type +{ + my ($host, $root) = repository_location(); + + return 'local' + unless uc($host) eq 'BK-INTERNAL.MYSQL.COM' + and -e "$root/BitKeeper/triggers/post-incoming.queuepush.pl"; + + return 'main' if -e "$root/BitKeeper/triggers/post-incoming.bugdb"; + + return 'team'; +} + + +# latest_cset +# RETURN Key for most recent ChangeSet + +sub latest_cset { + chomp(my $retval = `bk changes -r+ -k`); + return $retval; +} + + +# read_bk_csetlist +# RETURN list of cset keys from $BK_CSETLIST file +sub read_bk_csetlist +{ + die "$0: script error: \$BK_CSETLIST not set\n" + unless defined $ENV{BK_CSETLIST}; + + open CSETS, '<', $ENV{BK_CSETLIST} + or die "$0: can't read \$BK_CSETLIST='$ENV{BK_CSETLIST}': $!\n"; + chomp(my @csets = <CSETS>); + close_or_warn(CSETS, "\$BK_CSETLIST='$ENV{BK_CSETLIST}'"); + + return @csets; +} + + +# innodb_get_changes +# $type 'file' or 'cset' +# $value file name (e.g., $BK_PENDING) or ChangeSet key +# $want_merge_changes flag; if false, merge changes will be ignored +# RETURN A string describing the InnoDB changes, or undef if no changes +# +# The return value does *not* include ChangeSet comments, only per-file +# comments. + +sub innodb_get_changes +{ + my ($type, $value, $want_merge_changes) = @_; + + if ($type eq 'file') + { + open CHANGES, '<', $value + or die "$0: can't read '$value': $!\n"; + } + elsif ($type eq 'cset') + { + open CHANGES, '-|', "bk changes -r'$value' -v -d'$file_rev_dspec'" + or die "$0: can't exec 'bk changes': $!\n"; + } + else + { + croak "$0: script error: invalid type '$type'"; + } + + my @changes = grep { /$innodb_files_regex/ } <CHANGES>; + + close_or_warn(CHANGES, "($type, '$value')"); + + return undef unless @changes; + + + # Set up a pipeline of 'bk log' commands to weed out unwanted deltas. We + # never want deltas which contain no actual changes. We may not want deltas + # which are merges. + + my @filters; + + # This tests if :LI: (lines inserted) or :LD: (lines deleted) is + # non-zero. That is, did this delta change the file contents? + push @filters, + "bk log -d'" + . "\$if(:LI: -gt 0){$file_rev_dspec}" + . "\$if(:LI: -eq 0){\$if(:LD: -gt 0){$file_rev_dspec}}" + . "' -"; + + push @filters, "bk log -d'\$unless(:MERGE:){$file_rev_dspec}' -" + unless $want_merge_changes; + + my $tmpname = "$bktmp/ibchanges.txt"; + my $pipeline = join(' | ', @filters) . " > $tmpname"; + open TMP, '|-', $pipeline + or die "$0: can't exec [[$pipeline]]: $!\n"; + + print TMP @changes; + close_or_warn(TMP, "| $pipeline"); + + # Use bk log to describe the changes + open LOG, "bk log - < $tmpname |" + or die "$0: can't exec 'bk log - < $tmpname': $!\n"; + my @log = <LOG>; + close_or_warn(LOG, "bk log - < $tmpname |"); + + unlink $tmpname; + + return undef unless @log; + + return join('', @log); +} + + +# Ask user if they really want to commit. +# RETURN TRUE = YES, commit; FALSE = NO, do not commit + +sub innodb_inform_and_query_user +{ + my ($description) = @_; + + my $tmpname = "$bktmp/ibquery.txt"; + + open MESSAGE, "> $tmpname" + or die "$0: can't write message to '$tmpname': $!"; + + print MESSAGE <<EOF; +This ChangeSet modifies some files which should normally be changed by +InnoDB developers only. In general, MySQL developers should not change: + +$innodb_files_description +The following InnoDB files were modified: +========================================================= +$description +========================================================= + +If you understand this, you may Commit these changes. The changes +will be sent to the InnoDB developers at @{[join ', ', @innodb_to_email]}, +CC @{[join ', ', @innodb_cc_email]}. +EOF + + close_or_warn(MESSAGE, "$tmpname"); + + my $status = system('bk', 'prompt', '-w', + '-yCommit these changes', '-nDo not Commit', "-f$tmpname"); + + unlink $tmpname; + + return ($status == 0 ? 1 : undef); +} + + +# innodb_send_changes_email +# $cset The ChangeSet key +# $description A (maybe brief) description of the changes +# RETURN TRUE = Success, e-mail sent; FALSE = Failure +# +# Sends a complete diff of changes in $cset by e-mail. + +sub innodb_send_changes_email +{ + my ($cset, $description) = @_; + + # FIXME: Much of this is duplicated in the 'post-commit' Bourne shell + # trigger + + my $cset_short = `bk changes -r'$cset' -d':P:::I:'`; + my $cset_key = `bk changes -r'$cset' -d':KEY:'`; + + my ($host, $bk_root) = repository_location(); + my $type = repository_type(); + (my $treename = $bk_root) =~ s,^.*/,,; + + print "Nofifying InnoDB developers at ", + (join ', ', @innodb_to_email, @innodb_cc_email), "\n"; + + open SENDMAIL, '|-', "$sendmail -t" + or die "Can't exec '$sendmail -t': $!\n"; + + my @headers; + push @headers, "List-ID: <bk.innodb-$mysql_version>"; + push @headers, "From: $from"; + push @headers, "To: " . (join ', ', @innodb_to_email); + push @headers, "Cc: " . (join ', ', @innodb_cc_email) if @innodb_cc_email; + push @headers, + "Subject: InnoDB changes in $type $mysql_version tree ($cset_short)"; + push @headers, "X-CSetKey: <$cset_key>"; + + print SENDMAIL map { "$_\n" } @headers, ''; + + if ($type eq 'main') + { + print SENDMAIL <<EOF; +Changes pushed to $treename by $ENV{USER} affect the following +files. These changes are in a $mysql_version main tree. They +will be available publicly within 24 hours. +EOF + } + elsif ($type eq 'team') + { + print SENDMAIL <<EOF; +Changes added to $treename by $ENV{USER} affect the +following files. These changes are in a $mysql_version team tree. +EOF + } + else + { + print SENDMAIL <<EOF; +A local commit by $ENV{USER} affects the following files. These +changes are in a clone of a $mysql_version tree. +EOF + } + print SENDMAIL "\n"; + print SENDMAIL qx(bk changes -r'$cset'); + print SENDMAIL "$description"; + print SENDMAIL "The complete ChangeSet diffs follow.\n\n"; + print SENDMAIL qx(bk rset -r'$cset' -ah | bk gnupatch -h -dup -T); + + close_or_warn(SENDMAIL, "$sendmail -t") + or return undef; + + return 1; +} + + +1; diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 89675138750..a419da5eabf 100755 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -32,7 +32,8 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ADD_EXECUTABLE(mysql completion_hash.cc mysql.cc readline.cc sql_string.cc ../mysys/my_conio.c) TARGET_LINK_LIBRARIES(mysql mysqlclient_notls wsock32) -ADD_EXECUTABLE(mysqltest mysqltest.c ../mysys/my_getsystime.c ../mysys/my_copy.c) +ADD_EXECUTABLE(mysqltest mysqltest.c ../mysys/my_getsystime.c + ../mysys/my_copy.c ../mysys/my_mkdir.c) TARGET_LINK_LIBRARIES(mysqltest mysqlclient_notls regex wsock32) ADD_EXECUTABLE(mysqlcheck mysqlcheck.c) diff --git a/client/Makefile.am b/client/Makefile.am index c7663c7da82..672bb2e0c47 100644 --- a/client/Makefile.am +++ b/client/Makefile.am @@ -34,7 +34,8 @@ mysqladmin_SOURCES = mysqladmin.cc mysql_LDADD = @readline_link@ @TERMCAP_LIB@ $(LDADD) $(CXXLDFLAGS) mysqltest_SOURCES= mysqltest.c \ $(top_srcdir)/mysys/my_getsystime.c \ - $(top_srcdir)/mysys/my_copy.c + $(top_srcdir)/mysys/my_copy.c \ + $(top_srcdir)/mysys/my_mkdir.c mysqltest_LDADD = $(top_builddir)/regex/libregex.a $(LDADD) mysqlbinlog_SOURCES = mysqlbinlog.cc \ diff --git a/client/mysql.cc b/client/mysql.cc index af28dce2cdd..483b1829ec0 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright (C) 2000-2008 MySQL AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -283,13 +283,6 @@ static COMMANDS commands[] = { /* Get bash-like expansion for some commands */ { "create table", 0, 0, 0, ""}, { "create database", 0, 0, 0, ""}, - { "drop", 0, 0, 0, ""}, - { "select", 0, 0, 0, ""}, - { "insert", 0, 0, 0, ""}, - { "replace", 0, 0, 0, ""}, - { "update", 0, 0, 0, ""}, - { "delete", 0, 0, 0, ""}, - { "explain", 0, 0, 0, ""}, { "show databases", 0, 0, 0, ""}, { "show fields from", 0, 0, 0, ""}, { "show keys from", 0, 0, 0, ""}, @@ -299,6 +292,718 @@ static COMMANDS commands[] = { { "set option", 0, 0, 0, ""}, { "lock tables", 0, 0, 0, ""}, { "unlock tables", 0, 0, 0, ""}, + /* generated 2006-12-28. Refresh occasionally from lexer. */ + { "ACTION", 0, 0, 0, ""}, + { "ADD", 0, 0, 0, ""}, + { "AFTER", 0, 0, 0, ""}, + { "AGAINST", 0, 0, 0, ""}, + { "AGGREGATE", 0, 0, 0, ""}, + { "ALL", 0, 0, 0, ""}, + { "ALGORITHM", 0, 0, 0, ""}, + { "ALTER", 0, 0, 0, ""}, + { "ANALYZE", 0, 0, 0, ""}, + { "AND", 0, 0, 0, ""}, + { "ANY", 0, 0, 0, ""}, + { "AS", 0, 0, 0, ""}, + { "ASC", 0, 0, 0, ""}, + { "ASCII", 0, 0, 0, ""}, + { "ASENSITIVE", 0, 0, 0, ""}, + { "AUTO_INCREMENT", 0, 0, 0, ""}, + { "AVG", 0, 0, 0, ""}, + { "AVG_ROW_LENGTH", 0, 0, 0, ""}, + { "BACKUP", 0, 0, 0, ""}, + { "BDB", 0, 0, 0, ""}, + { "BEFORE", 0, 0, 0, ""}, + { "BEGIN", 0, 0, 0, ""}, + { "BERKELEYDB", 0, 0, 0, ""}, + { "BETWEEN", 0, 0, 0, ""}, + { "BIGINT", 0, 0, 0, ""}, + { "BINARY", 0, 0, 0, ""}, + { "BINLOG", 0, 0, 0, ""}, + { "BIT", 0, 0, 0, ""}, + { "BLOB", 0, 0, 0, ""}, + { "BOOL", 0, 0, 0, ""}, + { "BOOLEAN", 0, 0, 0, ""}, + { "BOTH", 0, 0, 0, ""}, + { "BTREE", 0, 0, 0, ""}, + { "BY", 0, 0, 0, ""}, + { "BYTE", 0, 0, 0, ""}, + { "CACHE", 0, 0, 0, ""}, + { "CALL", 0, 0, 0, ""}, + { "CASCADE", 0, 0, 0, ""}, + { "CASCADED", 0, 0, 0, ""}, + { "CASE", 0, 0, 0, ""}, + { "CHAIN", 0, 0, 0, ""}, + { "CHANGE", 0, 0, 0, ""}, + { "CHANGED", 0, 0, 0, ""}, + { "CHAR", 0, 0, 0, ""}, + { "CHARACTER", 0, 0, 0, ""}, + { "CHARSET", 0, 0, 0, ""}, + { "CHECK", 0, 0, 0, ""}, + { "CHECKSUM", 0, 0, 0, ""}, + { "CIPHER", 0, 0, 0, ""}, + { "CLIENT", 0, 0, 0, ""}, + { "CLOSE", 0, 0, 0, ""}, + { "CODE", 0, 0, 0, ""}, + { "COLLATE", 0, 0, 0, ""}, + { "COLLATION", 0, 0, 0, ""}, + { "COLUMN", 0, 0, 0, ""}, + { "COLUMNS", 0, 0, 0, ""}, + { "COMMENT", 0, 0, 0, ""}, + { "COMMIT", 0, 0, 0, ""}, + { "COMMITTED", 0, 0, 0, ""}, + { "COMPACT", 0, 0, 0, ""}, + { "COMPRESSED", 0, 0, 0, ""}, + { "CONCURRENT", 0, 0, 0, ""}, + { "CONDITION", 0, 0, 0, ""}, + { "CONNECTION", 0, 0, 0, ""}, + { "CONSISTENT", 0, 0, 0, ""}, + { "CONSTRAINT", 0, 0, 0, ""}, + { "CONTAINS", 0, 0, 0, ""}, + { "CONTINUE", 0, 0, 0, ""}, + { "CONVERT", 0, 0, 0, ""}, + { "CREATE", 0, 0, 0, ""}, + { "CROSS", 0, 0, 0, ""}, + { "CUBE", 0, 0, 0, ""}, + { "CURRENT_DATE", 0, 0, 0, ""}, + { "CURRENT_TIME", 0, 0, 0, ""}, + { "CURRENT_TIMESTAMP", 0, 0, 0, ""}, + { "CURRENT_USER", 0, 0, 0, ""}, + { "CURSOR", 0, 0, 0, ""}, + { "DATA", 0, 0, 0, ""}, + { "DATABASE", 0, 0, 0, ""}, + { "DATABASES", 0, 0, 0, ""}, + { "DATE", 0, 0, 0, ""}, + { "DATETIME", 0, 0, 0, ""}, + { "DAY", 0, 0, 0, ""}, + { "DAY_HOUR", 0, 0, 0, ""}, + { "DAY_MICROSECOND", 0, 0, 0, ""}, + { "DAY_MINUTE", 0, 0, 0, ""}, + { "DAY_SECOND", 0, 0, 0, ""}, + { "DEALLOCATE", 0, 0, 0, ""}, + { "DEC", 0, 0, 0, ""}, + { "DECIMAL", 0, 0, 0, ""}, + { "DECLARE", 0, 0, 0, ""}, + { "DEFAULT", 0, 0, 0, ""}, + { "DEFINER", 0, 0, 0, ""}, + { "DELAYED", 0, 0, 0, ""}, + { "DELAY_KEY_WRITE", 0, 0, 0, ""}, + { "DELETE", 0, 0, 0, ""}, + { "DESC", 0, 0, 0, ""}, + { "DESCRIBE", 0, 0, 0, ""}, + { "DES_KEY_FILE", 0, 0, 0, ""}, + { "DETERMINISTIC", 0, 0, 0, ""}, + { "DIRECTORY", 0, 0, 0, ""}, + { "DISABLE", 0, 0, 0, ""}, + { "DISCARD", 0, 0, 0, ""}, + { "DISTINCT", 0, 0, 0, ""}, + { "DISTINCTROW", 0, 0, 0, ""}, + { "DIV", 0, 0, 0, ""}, + { "DO", 0, 0, 0, ""}, + { "DOUBLE", 0, 0, 0, ""}, + { "DROP", 0, 0, 0, ""}, + { "DUAL", 0, 0, 0, ""}, + { "DUMPFILE", 0, 0, 0, ""}, + { "DUPLICATE", 0, 0, 0, ""}, + { "DYNAMIC", 0, 0, 0, ""}, + { "EACH", 0, 0, 0, ""}, + { "ELSE", 0, 0, 0, ""}, + { "ELSEIF", 0, 0, 0, ""}, + { "ENABLE", 0, 0, 0, ""}, + { "ENCLOSED", 0, 0, 0, ""}, + { "END", 0, 0, 0, ""}, + { "ENGINE", 0, 0, 0, ""}, + { "ENGINES", 0, 0, 0, ""}, + { "ENUM", 0, 0, 0, ""}, + { "ERRORS", 0, 0, 0, ""}, + { "ESCAPE", 0, 0, 0, ""}, + { "ESCAPED", 0, 0, 0, ""}, + { "EVENTS", 0, 0, 0, ""}, + { "EXECUTE", 0, 0, 0, ""}, + { "EXISTS", 0, 0, 0, ""}, + { "EXIT", 0, 0, 0, ""}, + { "EXPANSION", 0, 0, 0, ""}, + { "EXPLAIN", 0, 0, 0, ""}, + { "EXTENDED", 0, 0, 0, ""}, + { "FALSE", 0, 0, 0, ""}, + { "FAST", 0, 0, 0, ""}, + { "FETCH", 0, 0, 0, ""}, + { "FIELDS", 0, 0, 0, ""}, + { "FILE", 0, 0, 0, ""}, + { "FIRST", 0, 0, 0, ""}, + { "FIXED", 0, 0, 0, ""}, + { "FLOAT", 0, 0, 0, ""}, + { "FLOAT4", 0, 0, 0, ""}, + { "FLOAT8", 0, 0, 0, ""}, + { "FLUSH", 0, 0, 0, ""}, + { "FOR", 0, 0, 0, ""}, + { "FORCE", 0, 0, 0, ""}, + { "FOREIGN", 0, 0, 0, ""}, + { "FOUND", 0, 0, 0, ""}, + { "FRAC_SECOND", 0, 0, 0, ""}, + { "FROM", 0, 0, 0, ""}, + { "FULL", 0, 0, 0, ""}, + { "FULLTEXT", 0, 0, 0, ""}, + { "FUNCTION", 0, 0, 0, ""}, + { "GEOMETRY", 0, 0, 0, ""}, + { "GEOMETRYCOLLECTION", 0, 0, 0, ""}, + { "GET_FORMAT", 0, 0, 0, ""}, + { "GLOBAL", 0, 0, 0, ""}, + { "GRANT", 0, 0, 0, ""}, + { "GRANTS", 0, 0, 0, ""}, + { "GROUP", 0, 0, 0, ""}, + { "HANDLER", 0, 0, 0, ""}, + { "HASH", 0, 0, 0, ""}, + { "HAVING", 0, 0, 0, ""}, + { "HELP", 0, 0, 0, ""}, + { "HIGH_PRIORITY", 0, 0, 0, ""}, + { "HOSTS", 0, 0, 0, ""}, + { "HOUR", 0, 0, 0, ""}, + { "HOUR_MICROSECOND", 0, 0, 0, ""}, + { "HOUR_MINUTE", 0, 0, 0, ""}, + { "HOUR_SECOND", 0, 0, 0, ""}, + { "IDENTIFIED", 0, 0, 0, ""}, + { "IF", 0, 0, 0, ""}, + { "IGNORE", 0, 0, 0, ""}, + { "IMPORT", 0, 0, 0, ""}, + { "IN", 0, 0, 0, ""}, + { "INDEX", 0, 0, 0, ""}, + { "INDEXES", 0, 0, 0, ""}, + { "INFILE", 0, 0, 0, ""}, + { "INNER", 0, 0, 0, ""}, + { "INNOBASE", 0, 0, 0, ""}, + { "INNODB", 0, 0, 0, ""}, + { "INOUT", 0, 0, 0, ""}, + { "INSENSITIVE", 0, 0, 0, ""}, + { "INSERT", 0, 0, 0, ""}, + { "INSERT_METHOD", 0, 0, 0, ""}, + { "INT", 0, 0, 0, ""}, + { "INT1", 0, 0, 0, ""}, + { "INT2", 0, 0, 0, ""}, + { "INT3", 0, 0, 0, ""}, + { "INT4", 0, 0, 0, ""}, + { "INT8", 0, 0, 0, ""}, + { "INTEGER", 0, 0, 0, ""}, + { "INTERVAL", 0, 0, 0, ""}, + { "INTO", 0, 0, 0, ""}, + { "IO_THREAD", 0, 0, 0, ""}, + { "IS", 0, 0, 0, ""}, + { "ISOLATION", 0, 0, 0, ""}, + { "ISSUER", 0, 0, 0, ""}, + { "ITERATE", 0, 0, 0, ""}, + { "INVOKER", 0, 0, 0, ""}, + { "JOIN", 0, 0, 0, ""}, + { "KEY", 0, 0, 0, ""}, + { "KEYS", 0, 0, 0, ""}, + { "KILL", 0, 0, 0, ""}, + { "LANGUAGE", 0, 0, 0, ""}, + { "LAST", 0, 0, 0, ""}, + { "LEADING", 0, 0, 0, ""}, + { "LEAVE", 0, 0, 0, ""}, + { "LEAVES", 0, 0, 0, ""}, + { "LEFT", 0, 0, 0, ""}, + { "LEVEL", 0, 0, 0, ""}, + { "LIKE", 0, 0, 0, ""}, + { "LIMIT", 0, 0, 0, ""}, + { "LINES", 0, 0, 0, ""}, + { "LINESTRING", 0, 0, 0, ""}, + { "LOAD", 0, 0, 0, ""}, + { "LOCAL", 0, 0, 0, ""}, + { "LOCALTIME", 0, 0, 0, ""}, + { "LOCALTIMESTAMP", 0, 0, 0, ""}, + { "LOCK", 0, 0, 0, ""}, + { "LOCKS", 0, 0, 0, ""}, + { "LOGS", 0, 0, 0, ""}, + { "LONG", 0, 0, 0, ""}, + { "LONGBLOB", 0, 0, 0, ""}, + { "LONGTEXT", 0, 0, 0, ""}, + { "LOOP", 0, 0, 0, ""}, + { "LOW_PRIORITY", 0, 0, 0, ""}, + { "MASTER", 0, 0, 0, ""}, + { "MASTER_CONNECT_RETRY", 0, 0, 0, ""}, + { "MASTER_HOST", 0, 0, 0, ""}, + { "MASTER_LOG_FILE", 0, 0, 0, ""}, + { "MASTER_LOG_POS", 0, 0, 0, ""}, + { "MASTER_PASSWORD", 0, 0, 0, ""}, + { "MASTER_PORT", 0, 0, 0, ""}, + { "MASTER_SERVER_ID", 0, 0, 0, ""}, + { "MASTER_SSL", 0, 0, 0, ""}, + { "MASTER_SSL_CA", 0, 0, 0, ""}, + { "MASTER_SSL_CAPATH", 0, 0, 0, ""}, + { "MASTER_SSL_CERT", 0, 0, 0, ""}, + { "MASTER_SSL_CIPHER", 0, 0, 0, ""}, + { "MASTER_SSL_KEY", 0, 0, 0, ""}, + { "MASTER_USER", 0, 0, 0, ""}, + { "MATCH", 0, 0, 0, ""}, + { "MAX_CONNECTIONS_PER_HOUR", 0, 0, 0, ""}, + { "MAX_QUERIES_PER_HOUR", 0, 0, 0, ""}, + { "MAX_ROWS", 0, 0, 0, ""}, + { "MAX_UPDATES_PER_HOUR", 0, 0, 0, ""}, + { "MAX_USER_CONNECTIONS", 0, 0, 0, ""}, + { "MEDIUM", 0, 0, 0, ""}, + { "MEDIUMBLOB", 0, 0, 0, ""}, + { "MEDIUMINT", 0, 0, 0, ""}, + { "MEDIUMTEXT", 0, 0, 0, ""}, + { "MERGE", 0, 0, 0, ""}, + { "MICROSECOND", 0, 0, 0, ""}, + { "MIDDLEINT", 0, 0, 0, ""}, + { "MIGRATE", 0, 0, 0, ""}, + { "MINUTE", 0, 0, 0, ""}, + { "MINUTE_MICROSECOND", 0, 0, 0, ""}, + { "MINUTE_SECOND", 0, 0, 0, ""}, + { "MIN_ROWS", 0, 0, 0, ""}, + { "MOD", 0, 0, 0, ""}, + { "MODE", 0, 0, 0, ""}, + { "MODIFIES", 0, 0, 0, ""}, + { "MODIFY", 0, 0, 0, ""}, + { "MONTH", 0, 0, 0, ""}, + { "MULTILINESTRING", 0, 0, 0, ""}, + { "MULTIPOINT", 0, 0, 0, ""}, + { "MULTIPOLYGON", 0, 0, 0, ""}, + { "MUTEX", 0, 0, 0, ""}, + { "NAME", 0, 0, 0, ""}, + { "NAMES", 0, 0, 0, ""}, + { "NATIONAL", 0, 0, 0, ""}, + { "NATURAL", 0, 0, 0, ""}, + { "NDB", 0, 0, 0, ""}, + { "NDBCLUSTER", 0, 0, 0, ""}, + { "NCHAR", 0, 0, 0, ""}, + { "NEW", 0, 0, 0, ""}, + { "NEXT", 0, 0, 0, ""}, + { "NO", 0, 0, 0, ""}, + { "NONE", 0, 0, 0, ""}, + { "NOT", 0, 0, 0, ""}, + { "NO_WRITE_TO_BINLOG", 0, 0, 0, ""}, + { "NULL", 0, 0, 0, ""}, + { "NUMERIC", 0, 0, 0, ""}, + { "NVARCHAR", 0, 0, 0, ""}, + { "OFFSET", 0, 0, 0, ""}, + { "OLD_PASSWORD", 0, 0, 0, ""}, + { "ON", 0, 0, 0, ""}, + { "ONE", 0, 0, 0, ""}, + { "ONE_SHOT", 0, 0, 0, ""}, + { "OPEN", 0, 0, 0, ""}, + { "OPTIMIZE", 0, 0, 0, ""}, + { "OPTION", 0, 0, 0, ""}, + { "OPTIONALLY", 0, 0, 0, ""}, + { "OR", 0, 0, 0, ""}, + { "ORDER", 0, 0, 0, ""}, + { "OUT", 0, 0, 0, ""}, + { "OUTER", 0, 0, 0, ""}, + { "OUTFILE", 0, 0, 0, ""}, + { "PACK_KEYS", 0, 0, 0, ""}, + { "PARTIAL", 0, 0, 0, ""}, + { "PASSWORD", 0, 0, 0, ""}, + { "PHASE", 0, 0, 0, ""}, + { "POINT", 0, 0, 0, ""}, + { "POLYGON", 0, 0, 0, ""}, + { "PRECISION", 0, 0, 0, ""}, + { "PREPARE", 0, 0, 0, ""}, + { "PREV", 0, 0, 0, ""}, + { "PRIMARY", 0, 0, 0, ""}, + { "PRIVILEGES", 0, 0, 0, ""}, + { "PROCEDURE", 0, 0, 0, ""}, + { "PROCESS", 0, 0, 0, ""}, + { "PROCESSLIST", 0, 0, 0, ""}, + { "PURGE", 0, 0, 0, ""}, + { "QUARTER", 0, 0, 0, ""}, + { "QUERY", 0, 0, 0, ""}, + { "QUICK", 0, 0, 0, ""}, + { "RAID0", 0, 0, 0, ""}, + { "RAID_CHUNKS", 0, 0, 0, ""}, + { "RAID_CHUNKSIZE", 0, 0, 0, ""}, + { "RAID_TYPE", 0, 0, 0, ""}, + { "READ", 0, 0, 0, ""}, + { "READS", 0, 0, 0, ""}, + { "REAL", 0, 0, 0, ""}, + { "RECOVER", 0, 0, 0, ""}, + { "REDUNDANT", 0, 0, 0, ""}, + { "REFERENCES", 0, 0, 0, ""}, + { "REGEXP", 0, 0, 0, ""}, + { "RELAY_LOG_FILE", 0, 0, 0, ""}, + { "RELAY_LOG_POS", 0, 0, 0, ""}, + { "RELAY_THREAD", 0, 0, 0, ""}, + { "RELEASE", 0, 0, 0, ""}, + { "RELOAD", 0, 0, 0, ""}, + { "RENAME", 0, 0, 0, ""}, + { "REPAIR", 0, 0, 0, ""}, + { "REPEATABLE", 0, 0, 0, ""}, + { "REPLACE", 0, 0, 0, ""}, + { "REPLICATION", 0, 0, 0, ""}, + { "REPEAT", 0, 0, 0, ""}, + { "REQUIRE", 0, 0, 0, ""}, + { "RESET", 0, 0, 0, ""}, + { "RESTORE", 0, 0, 0, ""}, + { "RESTRICT", 0, 0, 0, ""}, + { "RESUME", 0, 0, 0, ""}, + { "RETURN", 0, 0, 0, ""}, + { "RETURNS", 0, 0, 0, ""}, + { "REVOKE", 0, 0, 0, ""}, + { "RIGHT", 0, 0, 0, ""}, + { "RLIKE", 0, 0, 0, ""}, + { "ROLLBACK", 0, 0, 0, ""}, + { "ROLLUP", 0, 0, 0, ""}, + { "ROUTINE", 0, 0, 0, ""}, + { "ROW", 0, 0, 0, ""}, + { "ROWS", 0, 0, 0, ""}, + { "ROW_FORMAT", 0, 0, 0, ""}, + { "RTREE", 0, 0, 0, ""}, + { "SAVEPOINT", 0, 0, 0, ""}, + { "SCHEMA", 0, 0, 0, ""}, + { "SCHEMAS", 0, 0, 0, ""}, + { "SECOND", 0, 0, 0, ""}, + { "SECOND_MICROSECOND", 0, 0, 0, ""}, + { "SECURITY", 0, 0, 0, ""}, + { "SELECT", 0, 0, 0, ""}, + { "SENSITIVE", 0, 0, 0, ""}, + { "SEPARATOR", 0, 0, 0, ""}, + { "SERIAL", 0, 0, 0, ""}, + { "SERIALIZABLE", 0, 0, 0, ""}, + { "SESSION", 0, 0, 0, ""}, + { "SET", 0, 0, 0, ""}, + { "SHARE", 0, 0, 0, ""}, + { "SHOW", 0, 0, 0, ""}, + { "SHUTDOWN", 0, 0, 0, ""}, + { "SIGNED", 0, 0, 0, ""}, + { "SIMPLE", 0, 0, 0, ""}, + { "SLAVE", 0, 0, 0, ""}, + { "SNAPSHOT", 0, 0, 0, ""}, + { "SMALLINT", 0, 0, 0, ""}, + { "SOME", 0, 0, 0, ""}, + { "SONAME", 0, 0, 0, ""}, + { "SOUNDS", 0, 0, 0, ""}, + { "SPATIAL", 0, 0, 0, ""}, + { "SPECIFIC", 0, 0, 0, ""}, + { "SQL", 0, 0, 0, ""}, + { "SQLEXCEPTION", 0, 0, 0, ""}, + { "SQLSTATE", 0, 0, 0, ""}, + { "SQLWARNING", 0, 0, 0, ""}, + { "SQL_BIG_RESULT", 0, 0, 0, ""}, + { "SQL_BUFFER_RESULT", 0, 0, 0, ""}, + { "SQL_CACHE", 0, 0, 0, ""}, + { "SQL_CALC_FOUND_ROWS", 0, 0, 0, ""}, + { "SQL_NO_CACHE", 0, 0, 0, ""}, + { "SQL_SMALL_RESULT", 0, 0, 0, ""}, + { "SQL_THREAD", 0, 0, 0, ""}, + { "SQL_TSI_FRAC_SECOND", 0, 0, 0, ""}, + { "SQL_TSI_SECOND", 0, 0, 0, ""}, + { "SQL_TSI_MINUTE", 0, 0, 0, ""}, + { "SQL_TSI_HOUR", 0, 0, 0, ""}, + { "SQL_TSI_DAY", 0, 0, 0, ""}, + { "SQL_TSI_WEEK", 0, 0, 0, ""}, + { "SQL_TSI_MONTH", 0, 0, 0, ""}, + { "SQL_TSI_QUARTER", 0, 0, 0, ""}, + { "SQL_TSI_YEAR", 0, 0, 0, ""}, + { "SSL", 0, 0, 0, ""}, + { "START", 0, 0, 0, ""}, + { "STARTING", 0, 0, 0, ""}, + { "STATUS", 0, 0, 0, ""}, + { "STOP", 0, 0, 0, ""}, + { "STORAGE", 0, 0, 0, ""}, + { "STRAIGHT_JOIN", 0, 0, 0, ""}, + { "STRING", 0, 0, 0, ""}, + { "STRIPED", 0, 0, 0, ""}, + { "SUBJECT", 0, 0, 0, ""}, + { "SUPER", 0, 0, 0, ""}, + { "SUSPEND", 0, 0, 0, ""}, + { "TABLE", 0, 0, 0, ""}, + { "TABLES", 0, 0, 0, ""}, + { "TABLESPACE", 0, 0, 0, ""}, + { "TEMPORARY", 0, 0, 0, ""}, + { "TEMPTABLE", 0, 0, 0, ""}, + { "TERMINATED", 0, 0, 0, ""}, + { "TEXT", 0, 0, 0, ""}, + { "THEN", 0, 0, 0, ""}, + { "TIME", 0, 0, 0, ""}, + { "TIMESTAMP", 0, 0, 0, ""}, + { "TIMESTAMPADD", 0, 0, 0, ""}, + { "TIMESTAMPDIFF", 0, 0, 0, ""}, + { "TINYBLOB", 0, 0, 0, ""}, + { "TINYINT", 0, 0, 0, ""}, + { "TINYTEXT", 0, 0, 0, ""}, + { "TO", 0, 0, 0, ""}, + { "TRAILING", 0, 0, 0, ""}, + { "TRANSACTION", 0, 0, 0, ""}, + { "TRIGGER", 0, 0, 0, ""}, + { "TRIGGERS", 0, 0, 0, ""}, + { "TRUE", 0, 0, 0, ""}, + { "TRUNCATE", 0, 0, 0, ""}, + { "TYPE", 0, 0, 0, ""}, + { "TYPES", 0, 0, 0, ""}, + { "UNCOMMITTED", 0, 0, 0, ""}, + { "UNDEFINED", 0, 0, 0, ""}, + { "UNDO", 0, 0, 0, ""}, + { "UNICODE", 0, 0, 0, ""}, + { "UNION", 0, 0, 0, ""}, + { "UNIQUE", 0, 0, 0, ""}, + { "UNKNOWN", 0, 0, 0, ""}, + { "UNLOCK", 0, 0, 0, ""}, + { "UNSIGNED", 0, 0, 0, ""}, + { "UNTIL", 0, 0, 0, ""}, + { "UPDATE", 0, 0, 0, ""}, + { "UPGRADE", 0, 0, 0, ""}, + { "USAGE", 0, 0, 0, ""}, + { "USE", 0, 0, 0, ""}, + { "USER", 0, 0, 0, ""}, + { "USER_RESOURCES", 0, 0, 0, ""}, + { "USE_FRM", 0, 0, 0, ""}, + { "USING", 0, 0, 0, ""}, + { "UTC_DATE", 0, 0, 0, ""}, + { "UTC_TIME", 0, 0, 0, ""}, + { "UTC_TIMESTAMP", 0, 0, 0, ""}, + { "VALUE", 0, 0, 0, ""}, + { "VALUES", 0, 0, 0, ""}, + { "VARBINARY", 0, 0, 0, ""}, + { "VARCHAR", 0, 0, 0, ""}, + { "VARCHARACTER", 0, 0, 0, ""}, + { "VARIABLES", 0, 0, 0, ""}, + { "VARYING", 0, 0, 0, ""}, + { "WARNINGS", 0, 0, 0, ""}, + { "WEEK", 0, 0, 0, ""}, + { "WHEN", 0, 0, 0, ""}, + { "WHERE", 0, 0, 0, ""}, + { "WHILE", 0, 0, 0, ""}, + { "VIEW", 0, 0, 0, ""}, + { "WITH", 0, 0, 0, ""}, + { "WORK", 0, 0, 0, ""}, + { "WRITE", 0, 0, 0, ""}, + { "X509", 0, 0, 0, ""}, + { "XOR", 0, 0, 0, ""}, + { "XA", 0, 0, 0, ""}, + { "YEAR", 0, 0, 0, ""}, + { "YEAR_MONTH", 0, 0, 0, ""}, + { "ZEROFILL", 0, 0, 0, ""}, + { "ABS", 0, 0, 0, ""}, + { "ACOS", 0, 0, 0, ""}, + { "ADDDATE", 0, 0, 0, ""}, + { "ADDTIME", 0, 0, 0, ""}, + { "AES_ENCRYPT", 0, 0, 0, ""}, + { "AES_DECRYPT", 0, 0, 0, ""}, + { "AREA", 0, 0, 0, ""}, + { "ASIN", 0, 0, 0, ""}, + { "ASBINARY", 0, 0, 0, ""}, + { "ASTEXT", 0, 0, 0, ""}, + { "ASWKB", 0, 0, 0, ""}, + { "ASWKT", 0, 0, 0, ""}, + { "ATAN", 0, 0, 0, ""}, + { "ATAN2", 0, 0, 0, ""}, + { "BENCHMARK", 0, 0, 0, ""}, + { "BIN", 0, 0, 0, ""}, + { "BIT_COUNT", 0, 0, 0, ""}, + { "BIT_OR", 0, 0, 0, ""}, + { "BIT_AND", 0, 0, 0, ""}, + { "BIT_XOR", 0, 0, 0, ""}, + { "CAST", 0, 0, 0, ""}, + { "CEIL", 0, 0, 0, ""}, + { "CEILING", 0, 0, 0, ""}, + { "BIT_LENGTH", 0, 0, 0, ""}, + { "CENTROID", 0, 0, 0, ""}, + { "CHAR_LENGTH", 0, 0, 0, ""}, + { "CHARACTER_LENGTH", 0, 0, 0, ""}, + { "COALESCE", 0, 0, 0, ""}, + { "COERCIBILITY", 0, 0, 0, ""}, + { "COMPRESS", 0, 0, 0, ""}, + { "CONCAT", 0, 0, 0, ""}, + { "CONCAT_WS", 0, 0, 0, ""}, + { "CONNECTION_ID", 0, 0, 0, ""}, + { "CONV", 0, 0, 0, ""}, + { "CONVERT_TZ", 0, 0, 0, ""}, + { "COUNT", 0, 0, 0, ""}, + { "COS", 0, 0, 0, ""}, + { "COT", 0, 0, 0, ""}, + { "CRC32", 0, 0, 0, ""}, + { "CROSSES", 0, 0, 0, ""}, + { "CURDATE", 0, 0, 0, ""}, + { "CURTIME", 0, 0, 0, ""}, + { "DATE_ADD", 0, 0, 0, ""}, + { "DATEDIFF", 0, 0, 0, ""}, + { "DATE_FORMAT", 0, 0, 0, ""}, + { "DATE_SUB", 0, 0, 0, ""}, + { "DAYNAME", 0, 0, 0, ""}, + { "DAYOFMONTH", 0, 0, 0, ""}, + { "DAYOFWEEK", 0, 0, 0, ""}, + { "DAYOFYEAR", 0, 0, 0, ""}, + { "DECODE", 0, 0, 0, ""}, + { "DEGREES", 0, 0, 0, ""}, + { "DES_ENCRYPT", 0, 0, 0, ""}, + { "DES_DECRYPT", 0, 0, 0, ""}, + { "DIMENSION", 0, 0, 0, ""}, + { "DISJOINT", 0, 0, 0, ""}, + { "ELT", 0, 0, 0, ""}, + { "ENCODE", 0, 0, 0, ""}, + { "ENCRYPT", 0, 0, 0, ""}, + { "ENDPOINT", 0, 0, 0, ""}, + { "ENVELOPE", 0, 0, 0, ""}, + { "EQUALS", 0, 0, 0, ""}, + { "EXTERIORRING", 0, 0, 0, ""}, + { "EXTRACT", 0, 0, 0, ""}, + { "EXP", 0, 0, 0, ""}, + { "EXPORT_SET", 0, 0, 0, ""}, + { "FIELD", 0, 0, 0, ""}, + { "FIND_IN_SET", 0, 0, 0, ""}, + { "FLOOR", 0, 0, 0, ""}, + { "FORMAT", 0, 0, 0, ""}, + { "FOUND_ROWS", 0, 0, 0, ""}, + { "FROM_DAYS", 0, 0, 0, ""}, + { "FROM_UNIXTIME", 0, 0, 0, ""}, + { "GET_LOCK", 0, 0, 0, ""}, + { "GEOMETRYN", 0, 0, 0, ""}, + { "GEOMETRYTYPE", 0, 0, 0, ""}, + { "GEOMCOLLFROMTEXT", 0, 0, 0, ""}, + { "GEOMCOLLFROMWKB", 0, 0, 0, ""}, + { "GEOMETRYCOLLECTIONFROMTEXT", 0, 0, 0, ""}, + { "GEOMETRYCOLLECTIONFROMWKB", 0, 0, 0, ""}, + { "GEOMETRYFROMTEXT", 0, 0, 0, ""}, + { "GEOMETRYFROMWKB", 0, 0, 0, ""}, + { "GEOMFROMTEXT", 0, 0, 0, ""}, + { "GEOMFROMWKB", 0, 0, 0, ""}, + { "GLENGTH", 0, 0, 0, ""}, + { "GREATEST", 0, 0, 0, ""}, + { "GROUP_CONCAT", 0, 0, 0, ""}, + { "GROUP_UNIQUE_USERS", 0, 0, 0, ""}, + { "HEX", 0, 0, 0, ""}, + { "IFNULL", 0, 0, 0, ""}, + { "INET_ATON", 0, 0, 0, ""}, + { "INET_NTOA", 0, 0, 0, ""}, + { "INSTR", 0, 0, 0, ""}, + { "INTERIORRINGN", 0, 0, 0, ""}, + { "INTERSECTS", 0, 0, 0, ""}, + { "ISCLOSED", 0, 0, 0, ""}, + { "ISEMPTY", 0, 0, 0, ""}, + { "ISNULL", 0, 0, 0, ""}, + { "IS_FREE_LOCK", 0, 0, 0, ""}, + { "IS_USED_LOCK", 0, 0, 0, ""}, + { "LAST_INSERT_ID", 0, 0, 0, ""}, + { "ISSIMPLE", 0, 0, 0, ""}, + { "LAST_DAY", 0, 0, 0, ""}, + { "LCASE", 0, 0, 0, ""}, + { "LEAST", 0, 0, 0, ""}, + { "LENGTH", 0, 0, 0, ""}, + { "LN", 0, 0, 0, ""}, + { "LINEFROMTEXT", 0, 0, 0, ""}, + { "LINEFROMWKB", 0, 0, 0, ""}, + { "LINESTRINGFROMTEXT", 0, 0, 0, ""}, + { "LINESTRINGFROMWKB", 0, 0, 0, ""}, + { "LOAD_FILE", 0, 0, 0, ""}, + { "LOCATE", 0, 0, 0, ""}, + { "LOG", 0, 0, 0, ""}, + { "LOG2", 0, 0, 0, ""}, + { "LOG10", 0, 0, 0, ""}, + { "LOWER", 0, 0, 0, ""}, + { "LPAD", 0, 0, 0, ""}, + { "LTRIM", 0, 0, 0, ""}, + { "MAKE_SET", 0, 0, 0, ""}, + { "MAKEDATE", 0, 0, 0, ""}, + { "MAKETIME", 0, 0, 0, ""}, + { "MASTER_POS_WAIT", 0, 0, 0, ""}, + { "MAX", 0, 0, 0, ""}, + { "MBRCONTAINS", 0, 0, 0, ""}, + { "MBRDISJOINT", 0, 0, 0, ""}, + { "MBREQUAL", 0, 0, 0, ""}, + { "MBRINTERSECTS", 0, 0, 0, ""}, + { "MBROVERLAPS", 0, 0, 0, ""}, + { "MBRTOUCHES", 0, 0, 0, ""}, + { "MBRWITHIN", 0, 0, 0, ""}, + { "MD5", 0, 0, 0, ""}, + { "MID", 0, 0, 0, ""}, + { "MIN", 0, 0, 0, ""}, + { "MLINEFROMTEXT", 0, 0, 0, ""}, + { "MLINEFROMWKB", 0, 0, 0, ""}, + { "MPOINTFROMTEXT", 0, 0, 0, ""}, + { "MPOINTFROMWKB", 0, 0, 0, ""}, + { "MPOLYFROMTEXT", 0, 0, 0, ""}, + { "MPOLYFROMWKB", 0, 0, 0, ""}, + { "MONTHNAME", 0, 0, 0, ""}, + { "MULTILINESTRINGFROMTEXT", 0, 0, 0, ""}, + { "MULTILINESTRINGFROMWKB", 0, 0, 0, ""}, + { "MULTIPOINTFROMTEXT", 0, 0, 0, ""}, + { "MULTIPOINTFROMWKB", 0, 0, 0, ""}, + { "MULTIPOLYGONFROMTEXT", 0, 0, 0, ""}, + { "MULTIPOLYGONFROMWKB", 0, 0, 0, ""}, + { "NAME_CONST", 0, 0, 0, ""}, + { "NOW", 0, 0, 0, ""}, + { "NULLIF", 0, 0, 0, ""}, + { "NUMGEOMETRIES", 0, 0, 0, ""}, + { "NUMINTERIORRINGS", 0, 0, 0, ""}, + { "NUMPOINTS", 0, 0, 0, ""}, + { "OCTET_LENGTH", 0, 0, 0, ""}, + { "OCT", 0, 0, 0, ""}, + { "ORD", 0, 0, 0, ""}, + { "OVERLAPS", 0, 0, 0, ""}, + { "PERIOD_ADD", 0, 0, 0, ""}, + { "PERIOD_DIFF", 0, 0, 0, ""}, + { "PI", 0, 0, 0, ""}, + { "POINTFROMTEXT", 0, 0, 0, ""}, + { "POINTFROMWKB", 0, 0, 0, ""}, + { "POINTN", 0, 0, 0, ""}, + { "POLYFROMTEXT", 0, 0, 0, ""}, + { "POLYFROMWKB", 0, 0, 0, ""}, + { "POLYGONFROMTEXT", 0, 0, 0, ""}, + { "POLYGONFROMWKB", 0, 0, 0, ""}, + { "POSITION", 0, 0, 0, ""}, + { "POW", 0, 0, 0, ""}, + { "POWER", 0, 0, 0, ""}, + { "QUOTE", 0, 0, 0, ""}, + { "RADIANS", 0, 0, 0, ""}, + { "RAND", 0, 0, 0, ""}, + { "RELEASE_LOCK", 0, 0, 0, ""}, + { "REVERSE", 0, 0, 0, ""}, + { "ROUND", 0, 0, 0, ""}, + { "ROW_COUNT", 0, 0, 0, ""}, + { "RPAD", 0, 0, 0, ""}, + { "RTRIM", 0, 0, 0, ""}, + { "SEC_TO_TIME", 0, 0, 0, ""}, + { "SESSION_USER", 0, 0, 0, ""}, + { "SUBDATE", 0, 0, 0, ""}, + { "SIGN", 0, 0, 0, ""}, + { "SIN", 0, 0, 0, ""}, + { "SHA", 0, 0, 0, ""}, + { "SHA1", 0, 0, 0, ""}, + { "SLEEP", 0, 0, 0, ""}, + { "SOUNDEX", 0, 0, 0, ""}, + { "SPACE", 0, 0, 0, ""}, + { "SQRT", 0, 0, 0, ""}, + { "SRID", 0, 0, 0, ""}, + { "STARTPOINT", 0, 0, 0, ""}, + { "STD", 0, 0, 0, ""}, + { "STDDEV", 0, 0, 0, ""}, + { "STDDEV_POP", 0, 0, 0, ""}, + { "STDDEV_SAMP", 0, 0, 0, ""}, + { "STR_TO_DATE", 0, 0, 0, ""}, + { "STRCMP", 0, 0, 0, ""}, + { "SUBSTR", 0, 0, 0, ""}, + { "SUBSTRING", 0, 0, 0, ""}, + { "SUBSTRING_INDEX", 0, 0, 0, ""}, + { "SUBTIME", 0, 0, 0, ""}, + { "SUM", 0, 0, 0, ""}, + { "SYSDATE", 0, 0, 0, ""}, + { "SYSTEM_USER", 0, 0, 0, ""}, + { "TAN", 0, 0, 0, ""}, + { "TIME_FORMAT", 0, 0, 0, ""}, + { "TIME_TO_SEC", 0, 0, 0, ""}, + { "TIMEDIFF", 0, 0, 0, ""}, + { "TO_DAYS", 0, 0, 0, ""}, + { "TOUCHES", 0, 0, 0, ""}, + { "TRIM", 0, 0, 0, ""}, + { "UCASE", 0, 0, 0, ""}, + { "UNCOMPRESS", 0, 0, 0, ""}, + { "UNCOMPRESSED_LENGTH", 0, 0, 0, ""}, + { "UNHEX", 0, 0, 0, ""}, + { "UNIQUE_USERS", 0, 0, 0, ""}, + { "UNIX_TIMESTAMP", 0, 0, 0, ""}, + { "UPPER", 0, 0, 0, ""}, + { "UUID", 0, 0, 0, ""}, + { "VARIANCE", 0, 0, 0, ""}, + { "VAR_POP", 0, 0, 0, ""}, + { "VAR_SAMP", 0, 0, 0, ""}, + { "VERSION", 0, 0, 0, ""}, + { "WEEKDAY", 0, 0, 0, ""}, + { "WEEKOFYEAR", 0, 0, 0, ""}, + { "WITHIN", 0, 0, 0, ""}, + { "X", 0, 0, 0, ""}, + { "Y", 0, 0, 0, ""}, + { "YEARWEEK", 0, 0, 0, ""}, + /* end sentinel */ { (char *)NULL, 0, 0, 0, ""} }; @@ -795,7 +1500,7 @@ static void usage(int version) if (version) return; printf("\ -Copyright (C) 2002 MySQL AB\n\ +Copyright (C) 2000-2008 MySQL AB\n\ This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n\ and you are welcome to modify and redistribute it under the GPL license\n"); printf("Usage: %s [OPTIONS] [database]\n", my_progname); @@ -1750,12 +2455,6 @@ static void build_completion_hash(bool rehash, bool write_info) if (status.batch || quick || !current_db) DBUG_VOID_RETURN; // We don't need completion in batches - - /* hash SQL commands */ - while (cmd->name) { - add_word(&ht,(char*) cmd->name); - cmd++; - } if (!rehash) DBUG_VOID_RETURN; @@ -1765,6 +2464,12 @@ static void build_completion_hash(bool rehash, bool write_info) completion_hash_clean(&ht); free_root(&hash_mem_root,MYF(0)); + /* hash this file's known subset of SQL commands */ + while (cmd->name) { + add_word(&ht,(char*) cmd->name); + cmd++; + } + /* hash MySQL functions (to be implemented) */ /* hash all database names */ @@ -2146,7 +2851,8 @@ com_charset(String *buffer __attribute__((unused)), char *line) static int com_go(String *buffer,char *line __attribute__((unused))) { - char buff[200], time_buff[32], *pos; + char buff[200]; /* about 110 chars used so far */ + char time_buff[52+3+1]; /* time max + space&parens + NUL */ MYSQL_RES *result; ulong timer, warnings; uint error= 0; @@ -2212,6 +2918,8 @@ com_go(String *buffer,char *line __attribute__((unused))) do { + char *pos; + if (quick) { if (!(result=mysql_use_result(&mysql)) && mysql_field_count(&mysql)) @@ -2233,7 +2941,9 @@ com_go(String *buffer,char *line __attribute__((unused))) if (verbose >= 3 || !opt_silent) mysql_end_timer(timer,time_buff); else - time_buff[0]=0; + time_buff[0]= '\0'; + + /* Every branch must truncate buff . */ if (result) { if (!mysql_num_rows(result) && ! quick && !info_flag) @@ -3792,6 +4502,11 @@ static ulong start_timer(void) } +/** + Write as many as 52+1 bytes to buff, in the form of a legible duration of time. + + len("4294967296 days, 23 hours, 59 minutes, 60.00 seconds") -> 52 +*/ static void nice_time(double sec,char *buff,bool part_second) { ulong tmp; diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 3d06a21c243..b4086b59c01 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -465,6 +465,31 @@ Create_file event for file_id: %u\n",ae->file_id); Load_log_processor load_processor; +/** + Replace windows-style backslashes by forward slashes so it can be + consumed by the mysql client, which requires Unix path. + + @todo This is only useful under windows, so may be ifdef'ed out on + other systems. /Sven + + @todo If a Create_file_log_event contains a filename with a + backslash (valid under unix), then we have problems under windows. + /Sven + + @param[in,out] fname Filename to modify. The filename is modified + in-place. +*/ +static void convert_path_to_forward_slashes(char *fname) +{ + while (*fname) + { + if (*fname == '\\') + *fname= '/'; + fname++; + } +} + + static bool check_database(const char *log_dbname) { return one_database && @@ -582,6 +607,11 @@ int process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev, */ if (ce) { + /* + We must not convert earlier, since the file is used by + my_open() in Load_log_processor::append(). + */ + convert_path_to_forward_slashes((char*) ce->fname); ce->print(result_file, print_event_info, TRUE); my_free((char*)ce->fname,MYF(MY_WME)); delete ce; @@ -622,6 +652,7 @@ Create_file event for file_id: %u\n",exv->file_id); if (fname) { + convert_path_to_forward_slashes(fname); exlq->print(result_file, print_event_info, fname); my_free(fname, MYF(MY_WME)); } diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index 3b504eb50b0..473e172adf9 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -483,14 +483,17 @@ static int process_all_tables_in_db(char *database) { MYSQL_RES *res; MYSQL_ROW row; + uint num_columns; LINT_INIT(res); if (use_db(database)) return 1; - if (mysql_query(sock, "SHOW TABLE STATUS") || + if (mysql_query(sock, "SHOW /*!50002 FULL*/ TABLES") || !((res= mysql_store_result(sock)))) return 1; + num_columns= mysql_num_fields(res); + if (opt_all_in_1) { /* @@ -513,12 +516,11 @@ static int process_all_tables_in_db(char *database) } for (end = tables + 1; (row = mysql_fetch_row(res)) ;) { - /* Skip tables with an engine of NULL (probably a view). */ - if (row[1]) - { - end= fix_table_name(end, row[0]); - *end++= ','; - } + if ((num_columns == 2) && (strcmp(row[1], "VIEW") == 0)) + continue; + + end= fix_table_name(end, row[0]); + *end++= ','; } *--end = 0; if (tot_length) @@ -531,6 +533,9 @@ static int process_all_tables_in_db(char *database) /* Skip tables with an engine of NULL (probably a view). */ if (row[1]) { + if ((num_columns == 2) && (strcmp(row[1], "VIEW") == 0)) + continue; + handle_request_for_tables(row[0], fixed_name_length(row[0])); } } diff --git a/client/mysqldump.c b/client/mysqldump.c index 980013d539a..e8129a6fd73 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -3285,6 +3285,7 @@ static int do_show_master_status(MYSQL *mysql_con) my_printf_error(0, "Error: Binlogging on server not active", MYF(0)); mysql_free_result(master); + maybe_exit(EX_MYSQLERR); return 1; } mysql_free_result(master); diff --git a/client/mysqltest.c b/client/mysqltest.c index 88575c26bc6..05c9ced3848 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -51,6 +51,10 @@ #ifdef HAVE_SYS_WAIT_H #include <sys/wait.h> #endif +#ifdef __WIN__ +#include <direct.h> +#endif + #ifndef WEXITSTATUS # ifdef __WIN__ @@ -277,7 +281,7 @@ enum enum_commands { Q_REPLACE_REGEX, Q_REMOVE_FILE, Q_FILE_EXIST, Q_WRITE_FILE, Q_COPY_FILE, Q_PERL, Q_DIE, Q_EXIT, Q_SKIP, Q_CHMOD_FILE, Q_APPEND_FILE, Q_CAT_FILE, Q_DIFF_FILES, - Q_SEND_QUIT, + Q_SEND_QUIT, Q_CHANGE_USER, Q_MKDIR, Q_RMDIR, Q_UNKNOWN, /* Unknown command. */ Q_COMMENT, /* Comments, ignored. */ @@ -366,6 +370,10 @@ const char *command_names[]= "cat_file", "diff_files", "send_quit", + "change_user", + "mkdir", + "rmdir", + 0 }; @@ -2742,6 +2750,67 @@ void do_file_exist(struct st_command *command) /* + SYNOPSIS + do_mkdir + command called command + + DESCRIPTION + mkdir <dir_name> + Create the directory <dir_name> +*/ + +void do_mkdir(struct st_command *command) +{ + int error; + static DYNAMIC_STRING ds_dirname; + const struct command_arg mkdir_args[] = { + "dirname", ARG_STRING, TRUE, &ds_dirname, "Directory to create" + }; + DBUG_ENTER("do_mkdir"); + + check_command_args(command, command->first_argument, + mkdir_args, sizeof(mkdir_args)/sizeof(struct command_arg), + ' '); + + DBUG_PRINT("info", ("creating directory: %s", ds_dirname.str)); + error= my_mkdir(ds_dirname.str, 0777, MYF(0)) != 0; + handle_command_error(command, error); + dynstr_free(&ds_dirname); + DBUG_VOID_RETURN; +} + +/* + SYNOPSIS + do_rmdir + command called command + + DESCRIPTION + rmdir <dir_name> + Remove the empty directory <dir_name> +*/ + +void do_rmdir(struct st_command *command) +{ + int error; + static DYNAMIC_STRING ds_dirname; + const struct command_arg rmdir_args[] = { + "dirname", ARG_STRING, TRUE, &ds_dirname, "Directory to remove" + }; + DBUG_ENTER("do_rmdir"); + + check_command_args(command, command->first_argument, + rmdir_args, sizeof(rmdir_args)/sizeof(struct command_arg), + ' '); + + DBUG_PRINT("info", ("removing directory: %s", ds_dirname.str)); + error= rmdir(ds_dirname.str) != 0; + handle_command_error(command, error); + dynstr_free(&ds_dirname); + DBUG_VOID_RETURN; +} + + +/* Read characters from line buffer or file. This is needed to allow my_ungetc() to buffer MAX_DELIMITER_LENGTH characters for a file @@ -3048,6 +3117,69 @@ void do_send_quit(struct st_command *command) /* SYNOPSIS + do_change_user + command called command + + DESCRIPTION + change_user [<user>], [<passwd>], [<db>] + <user> - user to change to + <passwd> - user password + <db> - default database + + Changes the user and causes the database specified by db to become + the default (current) database for the the current connection. + +*/ + +void do_change_user(struct st_command *command) +{ + MYSQL *mysql = &cur_con->mysql; + /* static keyword to make the NetWare compiler happy. */ + static DYNAMIC_STRING ds_user, ds_passwd, ds_db; + const struct command_arg change_user_args[] = { + { "user", ARG_STRING, FALSE, &ds_user, "User to connect as" }, + { "password", ARG_STRING, FALSE, &ds_passwd, "Password used when connecting" }, + { "database", ARG_STRING, FALSE, &ds_db, "Database to select after connect" }, + }; + + DBUG_ENTER("do_change_user"); + + check_command_args(command, command->first_argument, + change_user_args, + sizeof(change_user_args)/sizeof(struct command_arg), + ','); + + if (cur_con->stmt) + { + mysql_stmt_close(cur_con->stmt); + cur_con->stmt= NULL; + } + + if (!ds_user.length) + dynstr_set(&ds_user, mysql->user); + + if (!ds_passwd.length) + dynstr_set(&ds_passwd, mysql->passwd); + + if (!ds_db.length) + dynstr_set(&ds_db, mysql->db); + + DBUG_PRINT("info",("connection: '%s' user: '%s' password: '%s' database: '%s'", + cur_con->name, ds_user.str, ds_passwd.str, ds_db.str)); + + if (mysql_change_user(mysql, ds_user.str, ds_passwd.str, ds_db.str)) + die("change user failed: %s", mysql_error(mysql)); + + dynstr_free(&ds_user); + dynstr_free(&ds_passwd); + dynstr_free(&ds_db); + + DBUG_VOID_RETURN; +} + + +/* + SYNOPSIS do_perl command command handle @@ -6847,11 +6979,14 @@ int main(int argc, char **argv) case Q_ECHO: do_echo(command); command_executed++; break; case Q_SYSTEM: do_system(command); break; case Q_REMOVE_FILE: do_remove_file(command); break; + case Q_MKDIR: do_mkdir(command); break; + case Q_RMDIR: do_rmdir(command); break; case Q_FILE_EXIST: do_file_exist(command); break; case Q_WRITE_FILE: do_write_file(command); break; case Q_APPEND_FILE: do_append_file(command); break; case Q_DIFF_FILES: do_diff_files(command); break; case Q_SEND_QUIT: do_send_quit(command); break; + case Q_CHANGE_USER: do_change_user(command); break; case Q_CAT_FILE: do_cat_file(command); break; case Q_COPY_FILE: do_copy_file(command); break; case Q_CHMOD_FILE: do_chmod_file(command); break; diff --git a/cmd-line-utils/readline/bind.c b/cmd-line-utils/readline/bind.c index 08c906bfcc3..baed1dfad49 100644 --- a/cmd-line-utils/readline/bind.c +++ b/cmd-line-utils/readline/bind.c @@ -27,7 +27,7 @@ #endif #if defined (HAVE_CONFIG_H) -# include <config.h> +# include "config_readline.h" #endif #include <stdio.h> diff --git a/cmd-line-utils/readline/callback.c b/cmd-line-utils/readline/callback.c index ada04d8593b..2f7e4b78057 100644 --- a/cmd-line-utils/readline/callback.c +++ b/cmd-line-utils/readline/callback.c @@ -22,7 +22,7 @@ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) -# include <config.h> +# include "config_readline.h" #endif #include "rlconf.h" diff --git a/cmd-line-utils/readline/compat.c b/cmd-line-utils/readline/compat.c index a66d210fd2e..3949bf6a16b 100644 --- a/cmd-line-utils/readline/compat.c +++ b/cmd-line-utils/readline/compat.c @@ -22,7 +22,7 @@ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) -# include <config.h> +# include "config_readline.h" #endif #include <stdio.h> diff --git a/cmd-line-utils/readline/complete.c b/cmd-line-utils/readline/complete.c index 73f834a68a7..d0c9e772f0f 100644 --- a/cmd-line-utils/readline/complete.c +++ b/cmd-line-utils/readline/complete.c @@ -22,7 +22,7 @@ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) -# include <config.h> +# include "config_readline.h" #endif #include <sys/types.h> diff --git a/cmd-line-utils/readline/display.c b/cmd-line-utils/readline/display.c index 47ff0615974..6f63faa9738 100644 --- a/cmd-line-utils/readline/display.c +++ b/cmd-line-utils/readline/display.c @@ -22,7 +22,7 @@ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) -# include <config.h> +# include "config_readline.h" #endif #include <sys/types.h> diff --git a/cmd-line-utils/readline/funmap.c b/cmd-line-utils/readline/funmap.c index 9c760cc3475..2d2a35ed0c8 100644 --- a/cmd-line-utils/readline/funmap.c +++ b/cmd-line-utils/readline/funmap.c @@ -22,7 +22,7 @@ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) -# include <config.h> +# include "config_readline.h" #endif #if !defined (BUFSIZ) diff --git a/cmd-line-utils/readline/histexpand.c b/cmd-line-utils/readline/histexpand.c index f46c0b2a45d..45377fc3b5e 100644 --- a/cmd-line-utils/readline/histexpand.c +++ b/cmd-line-utils/readline/histexpand.c @@ -23,7 +23,7 @@ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) -# include <config.h> +# include "config_readline.h" #endif #include <stdio.h> diff --git a/cmd-line-utils/readline/histfile.c b/cmd-line-utils/readline/histfile.c index 2f051a32563..d98293d933c 100644 --- a/cmd-line-utils/readline/histfile.c +++ b/cmd-line-utils/readline/histfile.c @@ -31,7 +31,7 @@ #endif #if defined (HAVE_CONFIG_H) -# include <config.h> +# include "config_readline.h" #endif #include <stdio.h> diff --git a/cmd-line-utils/readline/history.c b/cmd-line-utils/readline/history.c index 1ccf4db786c..5cd5788d1da 100644 --- a/cmd-line-utils/readline/history.c +++ b/cmd-line-utils/readline/history.c @@ -26,7 +26,7 @@ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) -# include <config.h> +# include "config_readline.h" #endif #include <stdio.h> diff --git a/cmd-line-utils/readline/histsearch.c b/cmd-line-utils/readline/histsearch.c index 1cc5875a4b4..b71965135cc 100644 --- a/cmd-line-utils/readline/histsearch.c +++ b/cmd-line-utils/readline/histsearch.c @@ -23,7 +23,7 @@ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) -# include <config.h> +# include "config_readline.h" #endif #include <stdio.h> diff --git a/cmd-line-utils/readline/input.c b/cmd-line-utils/readline/input.c index da5d771c481..62c0443d890 100644 --- a/cmd-line-utils/readline/input.c +++ b/cmd-line-utils/readline/input.c @@ -26,7 +26,7 @@ #endif #if defined (HAVE_CONFIG_H) -# include <config.h> +# include "config_readline.h" #endif #include <sys/types.h> diff --git a/cmd-line-utils/readline/isearch.c b/cmd-line-utils/readline/isearch.c index 9f67bfc0801..8060adb97cd 100644 --- a/cmd-line-utils/readline/isearch.c +++ b/cmd-line-utils/readline/isearch.c @@ -27,7 +27,7 @@ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) -# include <config.h> +# include "config_readline.h" #endif #include <sys/types.h> diff --git a/cmd-line-utils/readline/keymaps.c b/cmd-line-utils/readline/keymaps.c index 70d0cc08d3f..562c22d7558 100644 --- a/cmd-line-utils/readline/keymaps.c +++ b/cmd-line-utils/readline/keymaps.c @@ -21,7 +21,7 @@ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) -# include <config.h> +# include "config_readline.h" #endif #if defined (HAVE_STDLIB_H) diff --git a/cmd-line-utils/readline/kill.c b/cmd-line-utils/readline/kill.c index 031ddf47c5b..42c53948689 100644 --- a/cmd-line-utils/readline/kill.c +++ b/cmd-line-utils/readline/kill.c @@ -22,7 +22,7 @@ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) -# include <config.h> +# include "config_readline.h" #endif #include <sys/types.h> diff --git a/cmd-line-utils/readline/macro.c b/cmd-line-utils/readline/macro.c index 00cd58d628c..3473f705335 100644 --- a/cmd-line-utils/readline/macro.c +++ b/cmd-line-utils/readline/macro.c @@ -22,7 +22,7 @@ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) -# include <config.h> +# include "config_readline.h" #endif #include <sys/types.h> diff --git a/cmd-line-utils/readline/mbutil.c b/cmd-line-utils/readline/mbutil.c index 17dde53ed7b..e21708fb748 100644 --- a/cmd-line-utils/readline/mbutil.c +++ b/cmd-line-utils/readline/mbutil.c @@ -22,7 +22,7 @@ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) -# include <config.h> +# include "config_readline.h" #endif #include <sys/types.h> diff --git a/cmd-line-utils/readline/misc.c b/cmd-line-utils/readline/misc.c index 94ecb25900a..e0e6893c60e 100644 --- a/cmd-line-utils/readline/misc.c +++ b/cmd-line-utils/readline/misc.c @@ -22,7 +22,7 @@ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) -# include <config.h> +# include "config_readline.h" #endif #if defined (HAVE_UNISTD_H) diff --git a/cmd-line-utils/readline/nls.c b/cmd-line-utils/readline/nls.c index bcee87561aa..6ec685ed9ea 100644 --- a/cmd-line-utils/readline/nls.c +++ b/cmd-line-utils/readline/nls.c @@ -22,7 +22,7 @@ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) -# include <config.h> +# include "config_readline.h" #endif #include <sys/types.h> diff --git a/cmd-line-utils/readline/parens.c b/cmd-line-utils/readline/parens.c index 737f7675e93..fe1578ed3e2 100644 --- a/cmd-line-utils/readline/parens.c +++ b/cmd-line-utils/readline/parens.c @@ -28,7 +28,7 @@ #include "rlconf.h" #if defined (HAVE_CONFIG_H) -# include <config.h> +# include "config_readline.h" #endif #include <stdio.h> diff --git a/cmd-line-utils/readline/readline.c b/cmd-line-utils/readline/readline.c index c2b74006b05..8c3cad52d36 100644 --- a/cmd-line-utils/readline/readline.c +++ b/cmd-line-utils/readline/readline.c @@ -23,7 +23,7 @@ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) -# include <config.h> +# include "config_readline.h" #endif #include <sys/types.h> diff --git a/cmd-line-utils/readline/rldefs.h b/cmd-line-utils/readline/rldefs.h index 0f6c87446dd..dcdfc49fbbc 100644 --- a/cmd-line-utils/readline/rldefs.h +++ b/cmd-line-utils/readline/rldefs.h @@ -27,7 +27,7 @@ #define _RLDEFS_H_ #if defined (HAVE_CONFIG_H) -# include "config.h" +# include "config_readline.h" #endif #include "rlstdc.h" diff --git a/cmd-line-utils/readline/rltty.c b/cmd-line-utils/readline/rltty.c index 0a570f85840..b5bc5d367a5 100644 --- a/cmd-line-utils/readline/rltty.c +++ b/cmd-line-utils/readline/rltty.c @@ -23,7 +23,7 @@ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) -# include <config.h> +# include "config_readline.h" #endif #include <sys/types.h> diff --git a/cmd-line-utils/readline/rlwinsize.h b/cmd-line-utils/readline/rlwinsize.h index 7838154d023..60729b0f549 100644 --- a/cmd-line-utils/readline/rlwinsize.h +++ b/cmd-line-utils/readline/rlwinsize.h @@ -26,7 +26,7 @@ #define _RLWINSIZE_H_ #if defined (HAVE_CONFIG_H) -# include "config.h" +# include "config_readline.h" #endif /* Try to find the definitions of `struct winsize' and TIOGCWINSZ */ diff --git a/cmd-line-utils/readline/savestring.c b/cmd-line-utils/readline/savestring.c index 820428d8881..d42bcadf5d7 100644 --- a/cmd-line-utils/readline/savestring.c +++ b/cmd-line-utils/readline/savestring.c @@ -21,7 +21,7 @@ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY -#include <config.h> +#include "config_readline.h" #ifdef HAVE_STRING_H # include <string.h> #endif diff --git a/cmd-line-utils/readline/search.c b/cmd-line-utils/readline/search.c index 33cc4fc1e73..cfa5db1dc17 100644 --- a/cmd-line-utils/readline/search.c +++ b/cmd-line-utils/readline/search.c @@ -23,7 +23,7 @@ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) -# include <config.h> +# include "config_readline.h" #endif #include <sys/types.h> diff --git a/cmd-line-utils/readline/shell.c b/cmd-line-utils/readline/shell.c index 346f8113d43..5d084476bed 100644 --- a/cmd-line-utils/readline/shell.c +++ b/cmd-line-utils/readline/shell.c @@ -23,7 +23,7 @@ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) -# include <config.h> +# include "config_readline.h" #endif #include <sys/types.h> diff --git a/cmd-line-utils/readline/signals.c b/cmd-line-utils/readline/signals.c index 54f2a642846..65c2ff308f6 100644 --- a/cmd-line-utils/readline/signals.c +++ b/cmd-line-utils/readline/signals.c @@ -22,7 +22,7 @@ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) -# include <config.h> +# include "config_readline.h" #endif #include <stdio.h> /* Just for NULL. Yuck. */ diff --git a/cmd-line-utils/readline/tcap.h b/cmd-line-utils/readline/tcap.h index 58ab894d93e..04252e72f2d 100644 --- a/cmd-line-utils/readline/tcap.h +++ b/cmd-line-utils/readline/tcap.h @@ -25,7 +25,7 @@ #define _RLTCAP_H_ #if defined (HAVE_CONFIG_H) -# include "config.h" +# include "config_readline.h" #endif #if defined (HAVE_TERMCAP_H) diff --git a/cmd-line-utils/readline/terminal.c b/cmd-line-utils/readline/terminal.c index 547f6f5dfe5..a630bc02e05 100644 --- a/cmd-line-utils/readline/terminal.c +++ b/cmd-line-utils/readline/terminal.c @@ -22,7 +22,7 @@ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) -# include <config.h> +# include "config_readline.h" #endif #include <sys/types.h> diff --git a/cmd-line-utils/readline/text.c b/cmd-line-utils/readline/text.c index 399a48c5f1e..b26afeda525 100644 --- a/cmd-line-utils/readline/text.c +++ b/cmd-line-utils/readline/text.c @@ -22,7 +22,7 @@ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) -# include <config.h> +# include "config_readline.h" #endif #if defined (HAVE_UNISTD_H) diff --git a/cmd-line-utils/readline/tilde.c b/cmd-line-utils/readline/tilde.c index 1b76c9f2404..d50f7a0ffa4 100644 --- a/cmd-line-utils/readline/tilde.c +++ b/cmd-line-utils/readline/tilde.c @@ -20,7 +20,7 @@ Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #if defined (HAVE_CONFIG_H) -# include <config.h> +# include "config_readline.h" #endif #if defined (HAVE_UNISTD_H) diff --git a/cmd-line-utils/readline/undo.c b/cmd-line-utils/readline/undo.c index 9d9bd25ba8f..5699193b14c 100644 --- a/cmd-line-utils/readline/undo.c +++ b/cmd-line-utils/readline/undo.c @@ -23,7 +23,7 @@ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) -# include <config.h> +# include "config_readline.h" #endif #include <sys/types.h> diff --git a/cmd-line-utils/readline/util.c b/cmd-line-utils/readline/util.c index e44ef64349d..935c9c927c2 100644 --- a/cmd-line-utils/readline/util.c +++ b/cmd-line-utils/readline/util.c @@ -22,7 +22,7 @@ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) -# include <config.h> +# include "config_readline.h" #endif #include <sys/types.h> diff --git a/cmd-line-utils/readline/vi_mode.c b/cmd-line-utils/readline/vi_mode.c index d0b7e330adc..25213cb762f 100644 --- a/cmd-line-utils/readline/vi_mode.c +++ b/cmd-line-utils/readline/vi_mode.c @@ -32,7 +32,7 @@ #if defined (VI_MODE) #if defined (HAVE_CONFIG_H) -# include <config.h> +# include "config_readline.h" #endif #include <sys/types.h> diff --git a/cmd-line-utils/readline/xmalloc.c b/cmd-line-utils/readline/xmalloc.c index 8985d340d39..cf52da351a8 100644 --- a/cmd-line-utils/readline/xmalloc.c +++ b/cmd-line-utils/readline/xmalloc.c @@ -21,7 +21,7 @@ #define READLINE_LIBRARY #if defined (HAVE_CONFIG_H) -#include <config.h> +#include "config_readline.h" #endif #include <stdio.h> diff --git a/configure.in b/configure.in index 63d3976aa3c..2ee722b4905 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 5.0.56) +AM_INIT_AUTOMAKE(mysql, 5.0.60) AM_CONFIG_HEADER([include/config.h:config.h.in]) PROTOCOL_VERSION=10 @@ -23,7 +23,7 @@ NDB_SHARED_LIB_VERSION=$NDB_SHARED_LIB_MAJOR_VERSION:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=56 +NDB_VERSION_BUILD=60 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? @@ -838,6 +838,8 @@ AC_CHECK_FUNC(p2open, , AC_CHECK_LIB(gen, p2open)) AC_CHECK_FUNC(bind, , AC_CHECK_LIB(bind, bind)) # Check if crypt() exists in libc or libcrypt, sets LIBS if needed AC_SEARCH_LIBS(crypt, crypt, AC_DEFINE(HAVE_CRYPT, 1, [crypt])) +# See if we need a library for address lookup. +AC_SEARCH_LIBS(inet_aton, [socket nsl resolv]) # For the sched_yield() function on Solaris AC_CHECK_FUNC(sched_yield, , AC_CHECK_LIB(posix4, sched_yield)) diff --git a/extra/CMakeLists.txt b/extra/CMakeLists.txt index a909bc93820..c1477e41a81 100755 --- a/extra/CMakeLists.txt +++ b/extra/CMakeLists.txt @@ -44,6 +44,9 @@ TARGET_LINK_LIBRARIES(my_print_defaults strings mysys debug dbug taocrypt wsock3 ADD_EXECUTABLE(perror perror.c) TARGET_LINK_LIBRARIES(perror strings mysys debug dbug wsock32) +ADD_EXECUTABLE(resolveip resolveip.c) +TARGET_LINK_LIBRARIES(resolveip strings mysys debug dbug wsock32) + ADD_EXECUTABLE(replace replace.c) TARGET_LINK_LIBRARIES(replace strings mysys debug dbug wsock32) diff --git a/extra/resolveip.c b/extra/resolveip.c index 1061cafe380..aedc2cc3418 100644 --- a/extra/resolveip.c +++ b/extra/resolveip.c @@ -21,13 +21,15 @@ #include <m_ctype.h> #include <my_sys.h> #include <m_string.h> -#include <sys/types.h> -#include <sys/socket.h> -#ifndef HAVE_BROKEN_NETINET_INCLUDES -#include <netinet/in.h> +#ifndef WIN32 +# include <sys/types.h> +# include <sys/socket.h> +# ifndef HAVE_BROKEN_NETINET_INCLUDES +# include <netinet/in.h> +# endif +# include <arpa/inet.h> +# include <netdb.h> #endif -#include <arpa/inet.h> -#include <netdb.h> #include <my_net.h> #include <my_getopt.h> @@ -116,11 +118,21 @@ int main(int argc, char **argv) while (argc--) { +#ifndef WIN32 + struct in_addr addr; +#endif ip = *argv++; - if (my_isdigit(&my_charset_latin1,ip[0])) + /* Not compatible with IPv6! Probably should use getnameinfo(). */ +#ifdef WIN32 + taddr = inet_addr(ip); + if(taddr != INADDR_NONE) + { +#else + if (inet_aton(ip, &addr) != 0) { - taddr = inet_addr(ip); + taddr= addr.s_addr; +#endif if (taddr == htonl(INADDR_BROADCAST)) { puts("Broadcast"); diff --git a/extra/yassl/src/handshake.cpp b/extra/yassl/src/handshake.cpp index 1d5a95820bb..262b5cb3b8b 100644 --- a/extra/yassl/src/handshake.cpp +++ b/extra/yassl/src/handshake.cpp @@ -527,6 +527,11 @@ void ProcessOldClientHello(input_buffer& input, SSL& ssl) input.read(len, sizeof(len)); uint16 randomLen; ato16(len, randomLen); + if (ch.suite_len_ > MAX_SUITE_SZ || sessionLen > ID_LEN || + randomLen > RAN_LEN) { + ssl.SetError(bad_input); + return; + } int j = 0; for (uint16 i = 0; i < ch.suite_len_; i += 3) { diff --git a/extra/yassl/src/template_instnt.cpp b/extra/yassl/src/template_instnt.cpp index f82f7924359..fe3a251b865 100644 --- a/extra/yassl/src/template_instnt.cpp +++ b/extra/yassl/src/template_instnt.cpp @@ -101,6 +101,7 @@ template void ysArrayDelete<unsigned char>(unsigned char*); template void ysArrayDelete<char>(char*); template int min<int>(int, int); +template uint16 min<uint16>(uint16, uint16); template unsigned int min<unsigned int>(unsigned int, unsigned int); template unsigned long min<unsigned long>(unsigned long, unsigned long); } diff --git a/extra/yassl/src/yassl_imp.cpp b/extra/yassl/src/yassl_imp.cpp index 0bc95f64abc..b43d9c27355 100644 --- a/extra/yassl/src/yassl_imp.cpp +++ b/extra/yassl/src/yassl_imp.cpp @@ -621,6 +621,10 @@ void HandShakeHeader::Process(input_buffer& input, SSL& ssl) } uint len = c24to32(length_); + if (len > input.get_remaining()) { + ssl.SetError(bad_input); + return; + } hashHandShake(ssl, input, len); hs->set_length(len); @@ -1391,10 +1395,15 @@ input_buffer& operator>>(input_buffer& input, ClientHello& hello) // Suites byte tmp[2]; + uint16 len; tmp[0] = input[AUTO]; tmp[1] = input[AUTO]; - ato16(tmp, hello.suite_len_); + ato16(tmp, len); + + hello.suite_len_ = min(len, static_cast<uint16>(MAX_SUITE_SZ)); input.read(hello.cipher_suites_, hello.suite_len_); + if (len > hello.suite_len_) // ignore extra suites + input.set_current(input.get_current() + len - hello.suite_len_); // Compression hello.comp_len_ = input[AUTO]; diff --git a/include/my_sys.h b/include/my_sys.h index f72aef13989..d656326e968 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -530,6 +530,12 @@ typedef int (*qsort2_cmp)(const void *, const void *, const void *); #define my_b_tell(info) ((info)->pos_in_file + \ (uint) (*(info)->current_pos - (info)->request_pos)) +#define my_b_get_buffer_start(info) (info)->request_pos +#define my_b_get_bytes_in_buffer(info) (char*) (info)->read_end - \ + (char*) my_b_get_buffer_start(info) +#define my_b_get_pos_in_file(info) (info)->pos_in_file + + /* tell write offset in the SEQ_APPEND cache */ my_off_t my_b_append_tell(IO_CACHE* info); my_off_t my_b_safe_tell(IO_CACHE* info); /* picks the correct tell() */ diff --git a/mysql-test/include/have_local_infile.inc b/mysql-test/include/have_local_infile.inc new file mode 100644 index 00000000000..4a1362c6e30 --- /dev/null +++ b/mysql-test/include/have_local_infile.inc @@ -0,0 +1,4 @@ +--require r/have_local_infile.require +disable_query_log; +show variables like 'local_infile'; +enable_query_log; diff --git a/mysql-test/include/ndb_wait_connected.inc b/mysql-test/include/ndb_wait_connected.inc new file mode 100644 index 00000000000..cfea94db1f1 --- /dev/null +++ b/mysql-test/include/ndb_wait_connected.inc @@ -0,0 +1,26 @@ +# Check that mysqld has reconnected to ndbd after +# restart of ndbd +# +--disable_query_log +--disable_result_log +let $mysql_errno= 1; +let $counter= 600; +while ($mysql_errno) +{ + --error 0,157 + CREATE TABLE ndb_wait_connected (a int primary key); + if ($mysql_errno) + { + if (!$counter) + { + die Failed waiting for mysqld to reconnect to ndbd; + } + dec $counter; + --sleep 0.1 + } +} +DROP TABLE ndb_wait_connected; +--enable_query_log +--enable_result_log + + diff --git a/mysql-test/include/show_binlog_events2.inc b/mysql-test/include/show_binlog_events2.inc new file mode 100644 index 00000000000..fa244c5a5a3 --- /dev/null +++ b/mysql-test/include/show_binlog_events2.inc @@ -0,0 +1,5 @@ +--let $binlog_start=98 +--replace_result $binlog_start <binlog_start> +--replace_column 2 # 5 # +--replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/ +--eval show binlog events from $binlog_start diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 29c5648090c..7c4677b8274 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -3765,12 +3765,11 @@ sub mysqld_arguments ($$$$) { # When mysqld is run by a root user(euid is 0), it will fail - # to start unless we specify what user to run as. If not running - # as root it will be ignored, see BUG#30630 + # to start unless we specify what user to run as, see BUG#30630 my $euid= $>; if (!$glob_win32 and $euid == 0 and grep(/^--user/, @$extra_opt, @opt_extra_mysqld_opt) == 0) { - mtr_add_arg($args, "%s--user=root"); + mtr_add_arg($args, "%s--user=root", $prefix); } if ( $opt_valgrind_mysqld ) diff --git a/mysql-test/r/bdb.result b/mysql-test/r/bdb.result index 3356d23053f..fefeeb405c5 100644 --- a/mysql-test/r/bdb.result +++ b/mysql-test/r/bdb.result @@ -1325,6 +1325,7 @@ set @a=repeat(' ',20); insert into t1 values (concat('+',@a),concat('+',@a),concat('+',@a)); Warnings: Note 1265 Data truncated for column 'v' at row 1 +Note 1265 Data truncated for column 'c' at row 1 select concat('*',v,'*',c,'*',t,'*') from t1; concat('*',v,'*',c,'*',t,'*') *+ *+*+ * diff --git a/mysql-test/r/bdb_notembedded.result b/mysql-test/r/bdb_notembedded.result index 14cb5fad915..2367e0d3fda 100644 --- a/mysql-test/r/bdb_notembedded.result +++ b/mysql-test/r/bdb_notembedded.result @@ -24,12 +24,18 @@ show binlog events; Log_name Pos Event_type Server_id End_log_pos Info f n Format_desc 1 n Server ver: VERSION, Binlog ver: 4 f n Query 1 n use `test`; create table bug16206 (a int) engine= bdb +f n Query 1 n use `test`; BEGIN f n Query 1 n use `test`; insert into bug16206 values(0) +f n Query 1 n use `test`; COMMIT +f n Query 1 n use `test`; BEGIN f n Query 1 n use `test`; insert into bug16206 values(1) +f n Query 1 n use `test`; COMMIT f n Query 1 n use `test`; BEGIN f n Query 1 n use `test`; insert into bug16206 values(2) f n Query 1 n use `test`; COMMIT +f n Query 1 n use `test`; BEGIN f n Query 1 n use `test`; insert into bug16206 values(3) +f n Query 1 n use `test`; COMMIT drop table bug16206; set autocommit=0; End of 5.0 tests diff --git a/mysql-test/r/binlog.result b/mysql-test/r/binlog.result index 0a199c87545..e6c5e3222de 100644 --- a/mysql-test/r/binlog.result +++ b/mysql-test/r/binlog.result @@ -567,4 +567,19 @@ master-bin.000001 36585 Rotate 1 36629 master-bin.000002;pos=4 drop table t1; set global binlog_cache_size=@bcs; set session autocommit = @ac; +drop table if exists t1; +reset master; +create table t1 (a bigint unsigned, b bigint(20) unsigned); +prepare stmt from "insert into t1 values (?,?)"; +set @a= 9999999999999999; +set @b= 14632475938453979136; +execute stmt using @a, @b; +deallocate prepare stmt; +drop table t1; +show binlog events from 0; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 4 Format_desc 1 98 Server version, Binlog ver: 4 +master-bin.000001 98 Query 1 219 use `test`; create table t1 (a bigint unsigned, b bigint(20) unsigned) +master-bin.000001 219 Query 1 343 use `test`; insert into t1 values (9999999999999999,14632475938453979136) +master-bin.000001 343 Query 1 419 use `test`; drop table t1 End of 5.0 tests diff --git a/mysql-test/r/binlog_innodb.result b/mysql-test/r/binlog_innodb.result index 93414a13ba1..18b4b7c1c93 100644 --- a/mysql-test/r/binlog_innodb.result +++ b/mysql-test/r/binlog_innodb.result @@ -21,3 +21,19 @@ show status like "binlog_cache_disk_use"; Variable_name Value Binlog_cache_disk_use 1 drop table t1; +CREATE TABLE t1 (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY) ENGINE=MyISAM; +CREATE TABLE t2 (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB; +CREATE FUNCTION bug23333() +RETURNS int(11) +DETERMINISTIC +BEGIN +INSERT INTO t1 VALUES (NULL); +SELECT COUNT(*) FROM t1 INTO @a; +RETURN @a; +END| +INSERT INTO t2 VALUES (2),(10+bug23333()); +SHOW MASTER STATUS; +File Position Binlog_Do_DB Binlog_Ignore_DB +# 184136 +DROP FUNCTION bug23333; +DROP TABLE t1, t2; diff --git a/mysql-test/r/binlog_start_comment.result b/mysql-test/r/binlog_start_comment.result new file mode 100644 index 00000000000..162968195f2 --- /dev/null +++ b/mysql-test/r/binlog_start_comment.result @@ -0,0 +1,15 @@ +reset master; +drop table if exists t1,t2; +create table t1 (word varchar(20)) -- create table t1; +create table t2 (word varchar(20)) -- create table t2; +load data infile '../std_data_ln/words.dat' into table t1 -- load data to t1; +insert into t2 values ("Ada"); +flush logs; +select * from t2; +word +Ada +flush logs; +select * from t2; +word +Ada +drop table t1,t2; diff --git a/mysql-test/r/blackhole.result b/mysql-test/r/blackhole.result index 5ab4931b53b..a4b780f9db5 100644 --- a/mysql-test/r/blackhole.result +++ b/mysql-test/r/blackhole.result @@ -115,8 +115,8 @@ master-bin.000001 # Query 1 # use `test`; insert into t1 values(1) master-bin.000001 # Query 1 # use `test`; insert ignore into t1 values(1) master-bin.000001 # Query 1 # use `test`; replace into t1 values(100) master-bin.000001 # Query 1 # use `test`; create table t2 (a varchar(200)) engine=blackhole -master-bin.000001 # Begin_load_query 1 # ;file_id=1;block_len=581 -master-bin.000001 # Execute_load_query 1 # use `test`; load data infile '../std_data_ln/words.dat' into table t2 ;file_id=1 +master-bin.000001 # Begin_load_query 1 # ;file_id=#;block_len=581 +master-bin.000001 # Execute_load_query 1 # use `test`; load data infile '../std_data_ln/words.dat' into table t2 ;file_id=# master-bin.000001 # Query 1 # use `test`; alter table t1 add b int master-bin.000001 # Query 1 # use `test`; alter table t1 drop b master-bin.000001 # Query 1 # use `test`; create table t3 like t1 diff --git a/mysql-test/r/compare.result b/mysql-test/r/compare.result index c141b255716..c9ef41e0582 100644 --- a/mysql-test/r/compare.result +++ b/mysql-test/r/compare.result @@ -53,3 +53,41 @@ a b Warnings: Warning 1292 Truncated incorrect DOUBLE value: '' drop table if exists t1; +CREATE TABLE t1 (b int(2) zerofill, c int(2) zerofill); +INSERT INTO t1 (b,c) VALUES (1,2), (1,1), (2,2); +SELECT CONCAT(b,c), CONCAT(b,c) = '0101' FROM t1; +CONCAT(b,c) CONCAT(b,c) = '0101' +0102 0 +0101 1 +0202 0 +EXPLAIN EXTENDED SELECT b,c FROM t1 WHERE b = 1 AND CONCAT(b,c) = '0101'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using where +Warnings: +Note 1003 select `test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where ((`test`.`t1`.`b` = 1) and (concat(_binary'01',`test`.`t1`.`c`) = _latin1'0101')) +SELECT b,c FROM t1 WHERE b = 1 AND CONCAT(b,c) = '0101'; +b c +01 01 +CREATE TABLE t2 (a int); +INSERT INTO t2 VALUES (1),(2); +SELECT a, +(SELECT COUNT(*) FROM t1 +WHERE b = t2.a AND CONCAT(b,c) = CONCAT('0',t2.a,'01')) x +FROM t2 ORDER BY a; +a x +1 1 +2 0 +EXPLAIN EXTENDED +SELECT a, +(SELECT COUNT(*) FROM t1 +WHERE b = t2.a AND CONCAT(b,c) = CONCAT('0',t2.a,'01')) x +FROM t2 ORDER BY a; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using filesort +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 Using where +Warnings: +Note 1276 Field or reference 'test.t2.a' of SELECT #2 was resolved in SELECT #1 +Note 1276 Field or reference 'test.t2.a' of SELECT #2 was resolved in SELECT #1 +Note 1003 select `test`.`t2`.`a` AS `a`,(select count(0) AS `COUNT(*)` from `test`.`t1` where ((`test`.`t1`.`b` = `test`.`t2`.`a`) and (concat(`test`.`t1`.`b`,`test`.`t1`.`c`) = concat(_latin1'0',`test`.`t2`.`a`,_latin1'01')))) AS `x` from `test`.`t2` order by `test`.`t2`.`a` +DROP TABLE t1,t2; +End of 5.0 tests diff --git a/mysql-test/r/ctype_cp932_binlog.result b/mysql-test/r/ctype_cp932_binlog.result index 3385cd20ec4..0b4ca93a0dd 100644 --- a/mysql-test/r/ctype_cp932_binlog.result +++ b/mysql-test/r/ctype_cp932_binlog.result @@ -40,6 +40,6 @@ IN ind DECIMAL(10,2)) BEGIN INSERT INTO t4 VALUES (ins1, ins2, ind); END -master-bin.000001 776 Query 1 995 use `test`; INSERT INTO t4 VALUES ( NAME_CONST('ins1',_latin1 0x466F6F2773206120426172), NAME_CONST('ins2',_cp932 0xED40ED41ED42), NAME_CONST('ind',47.93)) -master-bin.000001 995 Query 1 1084 use `test`; DROP PROCEDURE bug18293 -master-bin.000001 1084 Query 1 1163 use `test`; DROP TABLE t4 +master-bin.000001 776 Query 1 987 use `test`; INSERT INTO t4 VALUES ( NAME_CONST('ins1',_latin1 0x466F6F2773206120426172), NAME_CONST('ins2',_cp932 0xED40ED41ED42), NAME_CONST('ind',47.93)) +master-bin.000001 987 Query 1 1076 use `test`; DROP PROCEDURE bug18293 +master-bin.000001 1076 Query 1 1155 use `test`; DROP TABLE t4 diff --git a/mysql-test/r/ctype_ucs_binlog.result b/mysql-test/r/ctype_ucs_binlog.result index 2657bf60c04..721a1ae51b7 100644 --- a/mysql-test/r/ctype_ucs_binlog.result +++ b/mysql-test/r/ctype_ucs_binlog.result @@ -18,7 +18,8 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -insert into t2 values (@v)/*!*/; +insert into t2 values (@v) +/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result index 19b5f03de6b..77d11831842 100644 --- a/mysql-test/r/func_gconcat.result +++ b/mysql-test/r/func_gconcat.result @@ -931,4 +931,19 @@ SELECT GROUP_CONCAT(DISTINCT b, a ORDER BY b) FROM t1; GROUP_CONCAT(DISTINCT b, a ORDER BY b) 11,22,32 DROP TABLE t1, t2, t3; +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES (),(); +SELECT s1.d1 FROM +( +SELECT +t1.a as d1, +GROUP_CONCAT(DISTINCT t1.a) AS d2 +FROM +t1 AS t1, +t1 AS t2 +GROUP BY 1 +) AS s1; +d1 +NULL +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/r/func_misc.result b/mysql-test/r/func_misc.result index 4f6b6d3a0d8..cccdd391497 100644 --- a/mysql-test/r/func_misc.result +++ b/mysql-test/r/func_misc.result @@ -207,6 +207,25 @@ test SELECT NAME_CONST('test', 'test'); test test +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2),(3); +SELECT NAME_CONST('flag',1) * MAX(a) FROM t1; +NAME_CONST('flag',1) * MAX(a) +3 +SELECT NAME_CONST('flag',1.5) * MAX(a) FROM t1; +NAME_CONST('flag',1.5) * MAX(a) +4.5 +SELECT NAME_CONST('flag',-1) * MAX(a) FROM t1; +NAME_CONST('flag',-1) * MAX(a) +-3 +SELECT NAME_CONST('flag',-1.5) * MAX(a) FROM t1; +NAME_CONST('flag',-1.5) * MAX(a) +-4.5 +SELECT NAME_CONST('flag', SQRT(4)) * MAX(a) FROM t1; +ERROR HY000: Incorrect arguments to NAME_CONST +SELECT NAME_CONST('flag',-SQRT(4)) * MAX(a) FROM t1; +ERROR HY000: Incorrect arguments to NAME_CONST +DROP TABLE t1; CREATE TABLE t1 (a int); INSERT INTO t1 VALUES (5), (2); SELECT NAME_CONST(x,2) FROM (SELECT a x FROM t1) t; diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index f25f9ed9e0a..d397947d7ca 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -666,6 +666,8 @@ timestampadd(SQL_TSI_SECOND, 1, date) select timestampadd(SQL_TSI_FRAC_SECOND, 1, date) from t1; timestampadd(SQL_TSI_FRAC_SECOND, 1, date) 2003-01-02 00:00:00.000001 +Warnings: +Warning 1287 'FRAC_SECOND' is deprecated; use 'MICROSECOND' instead select timestampdiff(MONTH, '2001-02-01', '2001-05-01') as a; a 3 @@ -699,6 +701,8 @@ a select timestampdiff(SQL_TSI_FRAC_SECOND, '2001-02-01 12:59:59.120000', '2001-05-01 12:58:58.119999') as a; a 7689538999999 +Warnings: +Warning 1287 'FRAC_SECOND' is deprecated; use 'MICROSECOND' instead select timestampdiff(SQL_TSI_DAY, '1986-02-01', '1986-03-01') as a1, timestampdiff(SQL_TSI_DAY, '1900-02-01', '1900-03-01') as a2, timestampdiff(SQL_TSI_DAY, '1996-02-01', '1996-03-01') as a3, @@ -1069,6 +1073,7 @@ timestampdiff(SQL_TSI_FRAC_SECOND, '2001-02-01 12:59:59.120000', '2001-05-01 12: id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: +Warning 1287 'FRAC_SECOND' is deprecated; use 'MICROSECOND' instead Note 1003 select timestampdiff(WEEK,_latin1'2001-02-01',_latin1'2001-05-01') AS `a1`,timestampdiff(SECOND_FRAC,_latin1'2001-02-01 12:59:59.120000',_latin1'2001-05-01 12:58:58.119999') AS `a2` select last_day('2005-00-00'); last_day('2005-00-00') @@ -1285,4 +1290,22 @@ DATE_ADD(20071108, INTERVAL 1 DAY) select LAST_DAY('2007-12-06 08:59:19.05') - INTERVAL 1 SECOND; LAST_DAY('2007-12-06 08:59:19.05') - INTERVAL 1 SECOND 2007-12-30 23:59:59 +SELECT TIMESTAMPADD(FRAC_SECOND, 1, '2008-02-18'); +TIMESTAMPADD(FRAC_SECOND, 1, '2008-02-18') +2008-02-18 00:00:00.000001 +Warnings: +Warning 1287 'FRAC_SECOND' is deprecated; use 'MICROSECOND' instead +SELECT TIMESTAMPDIFF(FRAC_SECOND, '2008-02-17', '2008-02-18'); +TIMESTAMPDIFF(FRAC_SECOND, '2008-02-17', '2008-02-18') +86400000000 +Warnings: +Warning 1287 'FRAC_SECOND' is deprecated; use 'MICROSECOND' instead +SELECT DATE_ADD('2008-02-18', INTERVAL 1 FRAC_SECOND); +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 'FRAC_SECOND)' at line 1 +SELECT DATE_SUB('2008-02-18', INTERVAL 1 FRAC_SECOND); +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 'FRAC_SECOND)' at line 1 +SELECT '2008-02-18' + INTERVAL 1 FRAC_SECOND; +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 'FRAC_SECOND' at line 1 +SELECT '2008-02-18' - INTERVAL 1 FRAC_SECOND; +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 'FRAC_SECOND' at line 1 End of 5.0 tests diff --git a/mysql-test/r/grant3.result b/mysql-test/r/grant3.result index cc7f46855b2..f38848111ad 100644 --- a/mysql-test/r/grant3.result +++ b/mysql-test/r/grant3.result @@ -138,3 +138,20 @@ SELECT user, host, db, select_priv FROM mysql.db where user = 'CUser2' order by user host db select_priv DROP USER CUser2@localhost; DROP USER CUser2@LOCALHOST; +CREATE DATABASE mysqltest_1; +CREATE TABLE mysqltest_1.t1 (a INT); +CREATE USER 'mysqltest1'@'%'; +GRANT SELECT, UPDATE ON `mysqltest_1`.* TO 'mysqltest1'@'%'; +REVOKE SELECT ON `mysqltest_1`.* FROM 'mysqltest1'@'%'; +GRANT SELECT, UPDATE ON `mysqltest\_1`.* TO 'mysqltest1'@'%'; +FLUSH PRIVILEGES; +SHOW GRANTS; +Grants for mysqltest1@% +GRANT USAGE ON *.* TO 'mysqltest1'@'%' +GRANT SELECT, UPDATE ON `mysqltest\_1`.* TO 'mysqltest1'@'%' +GRANT UPDATE ON `mysqltest_1`.* TO 'mysqltest1'@'%' +SELECT * FROM mysqltest_1.t1; +a +DROP USER 'mysqltest1'@'%'; +DROP DATABASE mysqltest_1; +End of 5.0 tests diff --git a/mysql-test/r/have_local_infile.require b/mysql-test/r/have_local_infile.require new file mode 100644 index 00000000000..124540f7b77 --- /dev/null +++ b/mysql-test/r/have_local_infile.require @@ -0,0 +1,2 @@ +Variable_name Value +local_infile ON diff --git a/mysql-test/r/heap.result b/mysql-test/r/heap.result index 906c431b834..adfcc00174f 100644 --- a/mysql-test/r/heap.result +++ b/mysql-test/r/heap.result @@ -256,6 +256,7 @@ set @a=repeat(' ',20); insert into t1 values (concat('+',@a),concat('+',@a),concat('+',@a)); Warnings: Note 1265 Data truncated for column 'v' at row 1 +Note 1265 Data truncated for column 'c' at row 1 select concat('*',v,'*',c,'*',t,'*') from t1; concat('*',v,'*',c,'*',t,'*') *+ *+*+ * diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 854712fdb1d..774e0bd167b 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -1901,6 +1901,7 @@ set @a=repeat(' ',20); insert into t1 values (concat('+',@a),concat('+',@a),concat('+',@a)); Warnings: Note 1265 Data truncated for column 'v' at row 1 +Note 1265 Data truncated for column 'c' at row 1 select concat('*',v,'*',c,'*',t,'*') from t1; concat('*',v,'*',c,'*',t,'*') *+ *+*+ * diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index 2ab463e7f85..b487cfd9a4b 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -1240,4 +1240,10 @@ t1 CREATE TABLE `t1` ( UNIQUE KEY `aa` (`a`(1)) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 drop table t1; +set @my_innodb_autoextend_increment=@@global.innodb_autoextend_increment; +set global innodb_autoextend_increment=8; +set global innodb_autoextend_increment=@my_innodb_autoextend_increment; +set @my_innodb_commit_concurrency=@@global.innodb_commit_concurrency; +set global innodb_commit_concurrency=0; +set global innodb_commit_concurrency=@my_innodb_commit_concurrency; End of 5.0 tests diff --git a/mysql-test/r/limit.result b/mysql-test/r/limit.result index 01d7d7ca218..2acf74162a4 100644 --- a/mysql-test/r/limit.result +++ b/mysql-test/r/limit.result @@ -94,6 +94,9 @@ drop table t1; prepare s from "select 1 limit ?"; set @a='qwe'; execute s using @a; +1 +set @a=-1; +execute s using @a; ERROR HY000: Incorrect arguments to EXECUTE prepare s from "select 1 limit 1, ?"; execute s using @a; @@ -101,4 +104,10 @@ ERROR HY000: Incorrect arguments to EXECUTE prepare s from "select 1 limit ?, ?"; execute s using @a, @a; ERROR HY000: Incorrect arguments to EXECUTE +set @a=14632475938453979136; +execute s using @a, @a; +1 +set @a=-14632475938453979136; +execute s using @a, @a; +ERROR HY000: Incorrect arguments to EXECUTE End of 5.0 tests diff --git a/mysql-test/r/mix_innodb_myisam_binlog.result b/mysql-test/r/mix_innodb_myisam_binlog.result index 89ee82e9655..e1968ac7ef8 100644 --- a/mysql-test/r/mix_innodb_myisam_binlog.result +++ b/mysql-test/r/mix_innodb_myisam_binlog.result @@ -100,9 +100,10 @@ insert into t1 values(9); insert into t2 select * from t1; show binlog events from 98; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 98 Query 1 # use `test`; insert into t1 values(9) -master-bin.000001 185 Xid 1 # COMMIT /* XID */ -master-bin.000001 212 Query 1 # use `test`; insert into t2 select * from t1 +master-bin.000001 98 Query 1 # use `test`; BEGIN +master-bin.000001 166 Query 1 # use `test`; insert into t1 values(9) +master-bin.000001 253 Xid 1 # COMMIT /* XID */ +master-bin.000001 280 Query 1 # use `test`; insert into t2 select * from t1 delete from t1; delete from t2; reset master; @@ -111,19 +112,21 @@ begin; insert into t2 select * from t1; show binlog events from 98; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 98 Query 1 # use `test`; insert into t1 values(10) -master-bin.000001 186 Xid 1 # COMMIT /* XID */ -master-bin.000001 213 Query 1 # use `test`; insert into t2 select * from t1 +master-bin.000001 98 Query 1 # use `test`; BEGIN +master-bin.000001 166 Query 1 # use `test`; insert into t1 values(10) +master-bin.000001 254 Xid 1 # COMMIT /* XID */ +master-bin.000001 281 Query 1 # use `test`; insert into t2 select * from t1 insert into t1 values(11); commit; show binlog events from 98; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 98 Query 1 # use `test`; insert into t1 values(10) -master-bin.000001 186 Xid 1 # COMMIT /* XID */ -master-bin.000001 213 Query 1 # use `test`; insert into t2 select * from t1 -master-bin.000001 307 Query 1 # use `test`; BEGIN -master-bin.000001 375 Query 1 # use `test`; insert into t1 values(11) -master-bin.000001 463 Xid 1 # COMMIT /* XID */ +master-bin.000001 98 Query 1 # use `test`; BEGIN +master-bin.000001 166 Query 1 # use `test`; insert into t1 values(10) +master-bin.000001 254 Xid 1 # COMMIT /* XID */ +master-bin.000001 281 Query 1 # use `test`; insert into t2 select * from t1 +master-bin.000001 375 Query 1 # use `test`; BEGIN +master-bin.000001 443 Query 1 # use `test`; insert into t1 values(11) +master-bin.000001 531 Xid 1 # COMMIT /* XID */ alter table t2 engine=INNODB; delete from t1; delete from t2; @@ -235,25 +238,29 @@ master-bin.000001 98 Query 1 # use `test`; BEGIN master-bin.000001 166 Query 1 # use `test`; insert into t1 values(16) master-bin.000001 254 Query 1 # use `test`; insert into t1 values(18) master-bin.000001 342 Xid 1 # COMMIT /* XID */ -master-bin.000001 369 Query 1 # use `test`; delete from t1 -master-bin.000001 446 Xid 1 # COMMIT /* XID */ -master-bin.000001 473 Query 1 # use `test`; delete from t2 -master-bin.000001 550 Xid 1 # COMMIT /* XID */ -master-bin.000001 577 Query 1 # use `test`; alter table t2 type=MyISAM -master-bin.000001 666 Query 1 # use `test`; insert into t1 values (1) -master-bin.000001 754 Xid 1 # COMMIT /* XID */ -master-bin.000001 781 Query 1 # use `test`; insert into t2 values (20) -master-bin.000001 870 Query 1 # use `test`; drop table t1,t2 -master-bin.000001 949 Query 1 # use `test`; create temporary table ti (a int) engine=innodb -master-bin.000001 1059 Query 1 # use `test`; insert into ti values(1) -master-bin.000001 1146 Xid 1 # COMMIT /* XID */ -master-bin.000001 1173 Query 1 # use `test`; create temporary table t1 (a int) engine=myisam -master-bin.000001 1283 Query 1 # use `test`; insert t1 values (1) -master-bin.000001 1366 Query 1 # use `test`; create table t0 (n int) -master-bin.000001 1452 Query 1 # use `test`; insert t0 select * from t1 -master-bin.000001 1541 Query 1 # use `test`; insert into t0 select GET_LOCK("lock1",null) -master-bin.000001 1648 Query 1 # use `test`; create table t2 (n int) engine=innodb -master-bin.000001 1748 Query 1 # use `test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `test`.`t1`,`test`.`ti` +master-bin.000001 369 Query 1 # use `test`; BEGIN +master-bin.000001 437 Query 1 # use `test`; delete from t1 +master-bin.000001 514 Xid 1 # COMMIT /* XID */ +master-bin.000001 541 Query 1 # use `test`; BEGIN +master-bin.000001 609 Query 1 # use `test`; delete from t2 +master-bin.000001 686 Xid 1 # COMMIT /* XID */ +master-bin.000001 713 Query 1 # use `test`; alter table t2 type=MyISAM +master-bin.000001 802 Query 1 # use `test`; BEGIN +master-bin.000001 870 Query 1 # use `test`; insert into t1 values (1) +master-bin.000001 958 Xid 1 # COMMIT /* XID */ +master-bin.000001 985 Query 1 # use `test`; insert into t2 values (20) +master-bin.000001 1074 Query 1 # use `test`; drop table t1,t2 +master-bin.000001 1153 Query 1 # use `test`; create temporary table ti (a int) engine=innodb +master-bin.000001 1263 Query 1 # use `test`; BEGIN +master-bin.000001 1331 Query 1 # use `test`; insert into ti values(1) +master-bin.000001 1418 Xid 1 # COMMIT /* XID */ +master-bin.000001 1445 Query 1 # use `test`; create temporary table t1 (a int) engine=myisam +master-bin.000001 1555 Query 1 # use `test`; insert t1 values (1) +master-bin.000001 1638 Query 1 # use `test`; create table t0 (n int) +master-bin.000001 1724 Query 1 # use `test`; insert t0 select * from t1 +master-bin.000001 1813 Query 1 # use `test`; insert into t0 select GET_LOCK("lock1",null) +master-bin.000001 1920 Query 1 # use `test`; create table t2 (n int) engine=innodb +master-bin.000001 2020 Query 1 # use `test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `test`.`t1`,`test`.`ti` do release_lock("lock1"); drop table t0,t2; reset master; @@ -275,9 +282,11 @@ is not null; is not null 1 select -@a like "%#%error_code=0%ROLLBACK/*!*/;%ROLLBACK /* added by mysqlbinlog */;%", +@a like "%#%error_code=0%ROLLBACK\n/*!*/;%ROLLBACK /* added by mysqlbinlog */;%" OR +@a like "%#%error_code=0%ROLLBACK\r\n/*!*/;%ROLLBACK /* added by mysqlbinlog */;%", @a not like "%#%error_code=%error_code=%"; -@a like "%#%error_code=0%ROLLBACK/*!*/;%ROLLBACK /* added by mysqlbinlog */;%" @a not like "%#%error_code=%error_code=%" +@a like "%#%error_code=0%ROLLBACK\n/*!*/;%ROLLBACK /* added by mysqlbinlog */;%" OR +@a like "%#%error_code=0%ROLLBACK\r\n/*!*/;%ROLLBACK /* added by mysqlbinlog */;%" @a not like "%#%error_code=%error_code=%" 1 1 drop table t1, t2; create temporary table tt (a int unique); @@ -402,7 +411,7 @@ insert into t2 values (bug27417(1)); ERROR 23000: Duplicate entry '1' for key 1 show master status /* the offset must denote there is the query */; File Position Binlog_Do_DB Binlog_Ignore_DB -master-bin.000001 267 +master-bin.000001 335 select count(*) from t1 /* must be 1 */; count(*) 1 @@ -414,7 +423,7 @@ insert into t2 select bug27417(1) union select bug27417(2); ERROR 23000: Duplicate entry '2' for key 1 show master status /* the offset must denote there is the query */; File Position Binlog_Do_DB Binlog_Ignore_DB -master-bin.000001 290 +master-bin.000001 358 select count(*) from t1 /* must be 2 */; count(*) 2 @@ -438,7 +447,7 @@ UPDATE t4,t3 SET t4.a=t3.a + bug27417(1) /* top level non-ta table */; ERROR 23000: Duplicate entry '2' for key 1 show master status /* the offset must denote there is the query */; File Position Binlog_Do_DB Binlog_Ignore_DB -master-bin.000001 301 +master-bin.000001 369 select count(*) from t1 /* must be 4 */; count(*) 4 @@ -466,7 +475,7 @@ delete from t2; ERROR 23000: Duplicate entry '1' for key 1 show master status /* the offset must denote there is the query */; File Position Binlog_Do_DB Binlog_Ignore_DB -master-bin.000001 246 +master-bin.000001 314 select count(*) from t1 /* must be 1 */; count(*) 1 @@ -483,7 +492,7 @@ delete t2.* from t2,t5 where t2.a=t5.a + 1; ERROR 23000: Duplicate entry '1' for key 1 show master status /* the offset must denote there is the query */; File Position Binlog_Do_DB Binlog_Ignore_DB -master-bin.000001 274 +master-bin.000001 342 select count(*) from t1 /* must be 1 */; count(*) 1 @@ -501,7 +510,7 @@ count(*) 2 show master status /* the offset must denote there is the query */; File Position Binlog_Do_DB Binlog_Ignore_DB -master-bin.000001 376 +master-bin.000001 444 drop trigger trg_del_t2; drop table t1,t2,t3,t4,t5; drop function bug27417; diff --git a/mysql-test/r/multi_update.result b/mysql-test/r/multi_update.result index d95036090a5..8a0eacd9eeb 100644 --- a/mysql-test/r/multi_update.result +++ b/mysql-test/r/multi_update.result @@ -545,7 +545,7 @@ a b 4 4 show master status /* there must be the UPDATE query event */; File Position Binlog_Do_DB Binlog_Ignore_DB -master-bin.000001 260 +master-bin.000001 328 delete from t1; delete from t2; insert into t1 values (1,2),(3,4),(4,4); @@ -555,7 +555,7 @@ UPDATE t2,t1 SET t2.a=t2.b where t2.a=t1.a; ERROR 23000: Duplicate entry '4' for key 1 show master status /* there must be the UPDATE query event */; File Position Binlog_Do_DB Binlog_Ignore_DB -master-bin.000001 275 +master-bin.000001 343 drop table t1, t2; drop table if exists t1, t2, t3; CREATE TABLE t1 (a int, PRIMARY KEY (a)); diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index 33f64d600bb..24c1cecfb4f 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -1104,6 +1104,7 @@ set @a=repeat(' ',20); insert into t1 values (concat('+',@a),concat('+',@a),concat('+',@a)); Warnings: Note 1265 Data truncated for column 'v' at row 1 +Note 1265 Data truncated for column 'c' at row 1 select concat('*',v,'*',c,'*',t,'*') from t1; concat('*',v,'*',c,'*',t,'*') *+ *+*+ * diff --git a/mysql-test/r/mysqlbinlog.result b/mysql-test/r/mysqlbinlog.result index 9f001c293de..469250a6fa2 100644 --- a/mysql-test/r/mysqlbinlog.result +++ b/mysql-test/r/mysqlbinlog.result @@ -23,24 +23,33 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -drop table if exists t1,t2,t3,t4,t5,t03,t04/*!*/; +drop table if exists t1,t2,t3,t4,t5,t03,t04 +/*!*/; SET TIMESTAMP=1000000000/*!*/; -create table t1 (word varchar(20))/*!*/; +create table t1 (word varchar(20)) +/*!*/; SET TIMESTAMP=1000000000/*!*/; -create table t2 (id int auto_increment not null primary key)/*!*/; +create table t2 (id int auto_increment not null primary key) +/*!*/; SET TIMESTAMP=1000000000/*!*/; -insert into t1 values ("abirvalg")/*!*/; +insert into t1 values ("abirvalg") +/*!*/; SET INSERT_ID=1/*!*/; SET TIMESTAMP=1000000000/*!*/; -insert into t2 values ()/*!*/; +insert into t2 values () +/*!*/; SET TIMESTAMP=1000000000/*!*/; -load data LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-1-0' INTO table t1/*!*/; +load data LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO table t1 +/*!*/; SET TIMESTAMP=1000000000/*!*/; -load data LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-2-0' INTO table t1/*!*/; +load data LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO table t1 +/*!*/; SET TIMESTAMP=1000000000/*!*/; -load data LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-3-0' INTO table t1/*!*/; +load data LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO table t1 +/*!*/; SET TIMESTAMP=1000000000/*!*/; -load data LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-4-0' INTO table t1/*!*/; +load data LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO table t1 +/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; @@ -56,7 +65,8 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -insert into t1 values ("Alas")/*!*/; +insert into t1 values ("Alas") +/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; @@ -83,7 +93,8 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -insert into t1 values ("Alas")/*!*/; +insert into t1 values ("Alas") +/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; @@ -100,24 +111,33 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -drop table if exists t1,t2,t3,t4,t5,t03,t04/*!*/; +drop table if exists t1,t2,t3,t4,t5,t03,t04 +/*!*/; SET TIMESTAMP=1000000000/*!*/; -create table t1 (word varchar(20))/*!*/; +create table t1 (word varchar(20)) +/*!*/; SET TIMESTAMP=1000000000/*!*/; -create table t2 (id int auto_increment not null primary key)/*!*/; +create table t2 (id int auto_increment not null primary key) +/*!*/; SET TIMESTAMP=1000000000/*!*/; -insert into t1 values ("abirvalg")/*!*/; +insert into t1 values ("abirvalg") +/*!*/; SET INSERT_ID=1/*!*/; SET TIMESTAMP=1000000000/*!*/; -insert into t2 values ()/*!*/; +insert into t2 values () +/*!*/; SET TIMESTAMP=1000000000/*!*/; -load data LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-1-2' INTO table t1/*!*/; +load data LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO table t1 +/*!*/; SET TIMESTAMP=1000000000/*!*/; -load data LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-2-2' INTO table t1/*!*/; +load data LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO table t1 +/*!*/; SET TIMESTAMP=1000000000/*!*/; -load data LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-3-2' INTO table t1/*!*/; +load data LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO table t1 +/*!*/; SET TIMESTAMP=1000000000/*!*/; -load data LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-4-2' INTO table t1/*!*/; +load data LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO table t1 +/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; @@ -133,7 +153,8 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -insert into t1 values ("Alas")/*!*/; +insert into t1 values ("Alas") +/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; @@ -160,7 +181,8 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -insert into t1 values ("Alas")/*!*/; +insert into t1 values ("Alas") +/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; @@ -173,9 +195,11 @@ DELIMITER /*!*/; ROLLBACK/*!*/; use test/*!*/; SET TIMESTAMP=1108844556/*!*/; -BEGIN/*!*/; +BEGIN +/*!*/; SET TIMESTAMP=1108844555/*!*/; -insert t1 values (1)/*!*/; +insert t1 values (1) +/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; @@ -185,9 +209,11 @@ ROLLBACK /* added by mysqlbinlog */; DELIMITER /*!*/; use test/*!*/; SET TIMESTAMP=1108844556/*!*/; -BEGIN/*!*/; +BEGIN +/*!*/; SET TIMESTAMP=1108844555/*!*/; -insert t1 values (1)/*!*/; +insert t1 values (1) +/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; @@ -245,7 +271,8 @@ SET @@session.character_set_client=8,@@session.collation_connection=8,@@session. CREATE DEFINER=`root`@`localhost` procedure p1() begin select 1; -end/*!*/; +end +/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; @@ -287,27 +314,36 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -create table t1 (a varchar(64) character set utf8)/*!*/; +create table t1 (a varchar(64) character set utf8) +/*!*/; SET TIMESTAMP=1000000000/*!*/; -load data LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-6-0' INTO table t1/*!*/; +load data LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO table t1 +/*!*/; SET TIMESTAMP=1000000000/*!*/; SET @@session.collation_database=7/*!*/; -load data LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-7-0' INTO table t1/*!*/; +load data LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO table t1 +/*!*/; SET TIMESTAMP=1000000000/*!*/; SET @@session.collation_database=DEFAULT/*!*/; -load data LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-8-0' INTO table t1/*!*/; +load data LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO table t1 +/*!*/; SET TIMESTAMP=1000000000/*!*/; -load data LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-9-0' INTO table t1/*!*/; +load data LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-#-#' INTO table t1 +/*!*/; SET TIMESTAMP=1000000000/*!*/; SET @@session.collation_database=7/*!*/; -load data LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-a-0' INTO table t1/*!*/; +load data LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-a-0' INTO table t1 +/*!*/; SET TIMESTAMP=1000000000/*!*/; SET @@session.collation_database=DEFAULT/*!*/; -load data LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-b-0' INTO table t1/*!*/; +load data LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-b-0' INTO table t1 +/*!*/; SET TIMESTAMP=1000000000/*!*/; -load data LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-c-0' INTO table t1 character set koi8r/*!*/; +load data LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/SQL_LOAD_MB-c-0' INTO table t1 character set koi8r +/*!*/; SET TIMESTAMP=1000000000/*!*/; -drop table t1/*!*/; +drop table t1 +/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; diff --git a/mysql-test/r/mysqlbinlog2.result b/mysql-test/r/mysqlbinlog2.result index 03b0e16d32a..f4755338da3 100644 --- a/mysql-test/r/mysqlbinlog2.result +++ b/mysql-test/r/mysqlbinlog2.result @@ -25,22 +25,28 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -create table t1 (a int auto_increment not null primary key, b char(3))/*!*/; +create table t1 (a int auto_increment not null primary key, b char(3)) +/*!*/; SET INSERT_ID=1/*!*/; SET TIMESTAMP=1579609942/*!*/; -insert into t1 values(null, "a")/*!*/; +insert into t1 values(null, "a") +/*!*/; SET INSERT_ID=2/*!*/; SET TIMESTAMP=1579609942/*!*/; -insert into t1 values(null, "b")/*!*/; +insert into t1 values(null, "b") +/*!*/; SET INSERT_ID=3/*!*/; SET TIMESTAMP=1579609944/*!*/; -insert into t1 values(null, "c")/*!*/; +insert into t1 values(null, "c") +/*!*/; SET INSERT_ID=4/*!*/; SET TIMESTAMP=1579609946/*!*/; -insert into t1 values(null, "d")/*!*/; +insert into t1 values(null, "d") +/*!*/; SET INSERT_ID=5/*!*/; SET TIMESTAMP=1579609946/*!*/; -insert into t1 values(null, "e")/*!*/; +insert into t1 values(null, "e") +/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; @@ -58,19 +64,24 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -insert into t1 values(null, "a")/*!*/; +insert into t1 values(null, "a") +/*!*/; SET INSERT_ID=2/*!*/; SET TIMESTAMP=1579609942/*!*/; -insert into t1 values(null, "b")/*!*/; +insert into t1 values(null, "b") +/*!*/; SET INSERT_ID=3/*!*/; SET TIMESTAMP=1579609944/*!*/; -insert into t1 values(null, "c")/*!*/; +insert into t1 values(null, "c") +/*!*/; SET INSERT_ID=4/*!*/; SET TIMESTAMP=1579609946/*!*/; -insert into t1 values(null, "d")/*!*/; +insert into t1 values(null, "d") +/*!*/; SET INSERT_ID=5/*!*/; SET TIMESTAMP=1579609946/*!*/; -insert into t1 values(null, "e")/*!*/; +insert into t1 values(null, "e") +/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; @@ -87,10 +98,12 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -insert into t1 values(null, "d")/*!*/; +insert into t1 values(null, "d") +/*!*/; SET INSERT_ID=5/*!*/; SET TIMESTAMP=1579609946/*!*/; -insert into t1 values(null, "e")/*!*/; +insert into t1 values(null, "e") +/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; @@ -107,16 +120,20 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -create table t1 (a int auto_increment not null primary key, b char(3))/*!*/; +create table t1 (a int auto_increment not null primary key, b char(3)) +/*!*/; SET INSERT_ID=1/*!*/; SET TIMESTAMP=1579609942/*!*/; -insert into t1 values(null, "a")/*!*/; +insert into t1 values(null, "a") +/*!*/; SET INSERT_ID=2/*!*/; SET TIMESTAMP=1579609942/*!*/; -insert into t1 values(null, "b")/*!*/; +insert into t1 values(null, "b") +/*!*/; SET INSERT_ID=3/*!*/; SET TIMESTAMP=1579609944/*!*/; -insert into t1 values(null, "c")/*!*/; +insert into t1 values(null, "c") +/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; @@ -133,7 +150,8 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -insert into t1 values(null, "d")/*!*/; +insert into t1 values(null, "d") +/*!*/; SET INSERT_ID=5/*!*/; DELIMITER ; # End of log file @@ -152,13 +170,16 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -insert into t1 values(null, "c")/*!*/; +insert into t1 values(null, "c") +/*!*/; SET INSERT_ID=4/*!*/; SET TIMESTAMP=1579609946/*!*/; -insert into t1 values(null, "d")/*!*/; +insert into t1 values(null, "d") +/*!*/; SET INSERT_ID=5/*!*/; SET TIMESTAMP=1579609946/*!*/; -insert into t1 values(null, "e")/*!*/; +insert into t1 values(null, "e") +/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; @@ -175,13 +196,16 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -create table t1 (a int auto_increment not null primary key, b char(3))/*!*/; +create table t1 (a int auto_increment not null primary key, b char(3)) +/*!*/; SET INSERT_ID=1/*!*/; SET TIMESTAMP=1579609942/*!*/; -insert into t1 values(null, "a")/*!*/; +insert into t1 values(null, "a") +/*!*/; SET INSERT_ID=2/*!*/; SET TIMESTAMP=1579609942/*!*/; -insert into t1 values(null, "b")/*!*/; +insert into t1 values(null, "b") +/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; @@ -198,22 +222,28 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -create table t1 (a int auto_increment not null primary key, b char(3))/*!*/; +create table t1 (a int auto_increment not null primary key, b char(3)) +/*!*/; SET INSERT_ID=1/*!*/; SET TIMESTAMP=1579609942/*!*/; -insert into t1 values(null, "a")/*!*/; +insert into t1 values(null, "a") +/*!*/; SET INSERT_ID=2/*!*/; SET TIMESTAMP=1579609942/*!*/; -insert into t1 values(null, "b")/*!*/; +insert into t1 values(null, "b") +/*!*/; SET INSERT_ID=3/*!*/; SET TIMESTAMP=1579609944/*!*/; -insert into t1 values(null, "c")/*!*/; +insert into t1 values(null, "c") +/*!*/; SET INSERT_ID=4/*!*/; SET TIMESTAMP=1579609946/*!*/; -insert into t1 values(null, "d")/*!*/; +insert into t1 values(null, "d") +/*!*/; SET INSERT_ID=5/*!*/; SET TIMESTAMP=1579609946/*!*/; -insert into t1 values(null, "e")/*!*/; +insert into t1 values(null, "e") +/*!*/; DELIMITER ; DELIMITER /*!*/; SET INSERT_ID=6/*!*/; @@ -223,7 +253,8 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -insert into t1 values(null, "f")/*!*/; +insert into t1 values(null, "f") +/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; @@ -241,19 +272,24 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -insert into t1 values(null, "a")/*!*/; +insert into t1 values(null, "a") +/*!*/; SET INSERT_ID=2/*!*/; SET TIMESTAMP=1579609942/*!*/; -insert into t1 values(null, "b")/*!*/; +insert into t1 values(null, "b") +/*!*/; SET INSERT_ID=3/*!*/; SET TIMESTAMP=1579609944/*!*/; -insert into t1 values(null, "c")/*!*/; +insert into t1 values(null, "c") +/*!*/; SET INSERT_ID=4/*!*/; SET TIMESTAMP=1579609946/*!*/; -insert into t1 values(null, "d")/*!*/; +insert into t1 values(null, "d") +/*!*/; SET INSERT_ID=5/*!*/; SET TIMESTAMP=1579609946/*!*/; -insert into t1 values(null, "e")/*!*/; +insert into t1 values(null, "e") +/*!*/; DELIMITER ; DELIMITER /*!*/; SET INSERT_ID=6/*!*/; @@ -263,7 +299,8 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -insert into t1 values(null, "f")/*!*/; +insert into t1 values(null, "f") +/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; @@ -280,10 +317,12 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -insert into t1 values(null, "d")/*!*/; +insert into t1 values(null, "d") +/*!*/; SET INSERT_ID=5/*!*/; SET TIMESTAMP=1579609946/*!*/; -insert into t1 values(null, "e")/*!*/; +insert into t1 values(null, "e") +/*!*/; DELIMITER ; DELIMITER /*!*/; SET INSERT_ID=6/*!*/; @@ -293,7 +332,8 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -insert into t1 values(null, "f")/*!*/; +insert into t1 values(null, "f") +/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; @@ -310,22 +350,28 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -create table t1 (a int auto_increment not null primary key, b char(3))/*!*/; +create table t1 (a int auto_increment not null primary key, b char(3)) +/*!*/; SET INSERT_ID=1/*!*/; SET TIMESTAMP=1579609942/*!*/; -insert into t1 values(null, "a")/*!*/; +insert into t1 values(null, "a") +/*!*/; SET INSERT_ID=2/*!*/; SET TIMESTAMP=1579609942/*!*/; -insert into t1 values(null, "b")/*!*/; +insert into t1 values(null, "b") +/*!*/; SET INSERT_ID=3/*!*/; SET TIMESTAMP=1579609944/*!*/; -insert into t1 values(null, "c")/*!*/; +insert into t1 values(null, "c") +/*!*/; SET INSERT_ID=4/*!*/; SET TIMESTAMP=1579609946/*!*/; -insert into t1 values(null, "d")/*!*/; +insert into t1 values(null, "d") +/*!*/; SET INSERT_ID=5/*!*/; SET TIMESTAMP=1579609946/*!*/; -insert into t1 values(null, "e")/*!*/; +insert into t1 values(null, "e") +/*!*/; DELIMITER ; DELIMITER /*!*/; SET INSERT_ID=6/*!*/; @@ -346,13 +392,16 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -insert into t1 values(null, "c")/*!*/; +insert into t1 values(null, "c") +/*!*/; SET INSERT_ID=4/*!*/; SET TIMESTAMP=1579609946/*!*/; -insert into t1 values(null, "d")/*!*/; +insert into t1 values(null, "d") +/*!*/; SET INSERT_ID=5/*!*/; SET TIMESTAMP=1579609946/*!*/; -insert into t1 values(null, "e")/*!*/; +insert into t1 values(null, "e") +/*!*/; DELIMITER ; DELIMITER /*!*/; SET INSERT_ID=6/*!*/; @@ -362,7 +411,8 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -insert into t1 values(null, "f")/*!*/; +insert into t1 values(null, "f") +/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; @@ -379,13 +429,16 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -create table t1 (a int auto_increment not null primary key, b char(3))/*!*/; +create table t1 (a int auto_increment not null primary key, b char(3)) +/*!*/; SET INSERT_ID=1/*!*/; SET TIMESTAMP=1579609942/*!*/; -insert into t1 values(null, "a")/*!*/; +insert into t1 values(null, "a") +/*!*/; SET INSERT_ID=2/*!*/; SET TIMESTAMP=1579609942/*!*/; -insert into t1 values(null, "b")/*!*/; +insert into t1 values(null, "b") +/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; @@ -402,22 +455,28 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -create table t1 (a int auto_increment not null primary key, b char(3))/*!*/; +create table t1 (a int auto_increment not null primary key, b char(3)) +/*!*/; SET INSERT_ID=1/*!*/; SET TIMESTAMP=1579609942/*!*/; -insert into t1 values(null, "a")/*!*/; +insert into t1 values(null, "a") +/*!*/; SET INSERT_ID=2/*!*/; SET TIMESTAMP=1579609942/*!*/; -insert into t1 values(null, "b")/*!*/; +insert into t1 values(null, "b") +/*!*/; SET INSERT_ID=3/*!*/; SET TIMESTAMP=1579609944/*!*/; -insert into t1 values(null, "c")/*!*/; +insert into t1 values(null, "c") +/*!*/; SET INSERT_ID=4/*!*/; SET TIMESTAMP=1579609946/*!*/; -insert into t1 values(null, "d")/*!*/; +insert into t1 values(null, "d") +/*!*/; SET INSERT_ID=5/*!*/; SET TIMESTAMP=1579609946/*!*/; -insert into t1 values(null, "e")/*!*/; +insert into t1 values(null, "e") +/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; @@ -435,19 +494,24 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -insert into t1 values(null, "a")/*!*/; +insert into t1 values(null, "a") +/*!*/; SET INSERT_ID=2/*!*/; SET TIMESTAMP=1579609942/*!*/; -insert into t1 values(null, "b")/*!*/; +insert into t1 values(null, "b") +/*!*/; SET INSERT_ID=3/*!*/; SET TIMESTAMP=1579609944/*!*/; -insert into t1 values(null, "c")/*!*/; +insert into t1 values(null, "c") +/*!*/; SET INSERT_ID=4/*!*/; SET TIMESTAMP=1579609946/*!*/; -insert into t1 values(null, "d")/*!*/; +insert into t1 values(null, "d") +/*!*/; SET INSERT_ID=5/*!*/; SET TIMESTAMP=1579609946/*!*/; -insert into t1 values(null, "e")/*!*/; +insert into t1 values(null, "e") +/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; @@ -464,10 +528,12 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -insert into t1 values(null, "d")/*!*/; +insert into t1 values(null, "d") +/*!*/; SET INSERT_ID=5/*!*/; SET TIMESTAMP=1579609946/*!*/; -insert into t1 values(null, "e")/*!*/; +insert into t1 values(null, "e") +/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; @@ -484,16 +550,20 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -create table t1 (a int auto_increment not null primary key, b char(3))/*!*/; +create table t1 (a int auto_increment not null primary key, b char(3)) +/*!*/; SET INSERT_ID=1/*!*/; SET TIMESTAMP=1579609942/*!*/; -insert into t1 values(null, "a")/*!*/; +insert into t1 values(null, "a") +/*!*/; SET INSERT_ID=2/*!*/; SET TIMESTAMP=1579609942/*!*/; -insert into t1 values(null, "b")/*!*/; +insert into t1 values(null, "b") +/*!*/; SET INSERT_ID=3/*!*/; SET TIMESTAMP=1579609944/*!*/; -insert into t1 values(null, "c")/*!*/; +insert into t1 values(null, "c") +/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; @@ -510,7 +580,8 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -insert into t1 values(null, "d")/*!*/; +insert into t1 values(null, "d") +/*!*/; SET INSERT_ID=5/*!*/; DELIMITER ; # End of log file @@ -529,13 +600,16 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -insert into t1 values(null, "c")/*!*/; +insert into t1 values(null, "c") +/*!*/; SET INSERT_ID=4/*!*/; SET TIMESTAMP=1579609946/*!*/; -insert into t1 values(null, "d")/*!*/; +insert into t1 values(null, "d") +/*!*/; SET INSERT_ID=5/*!*/; SET TIMESTAMP=1579609946/*!*/; -insert into t1 values(null, "e")/*!*/; +insert into t1 values(null, "e") +/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; @@ -552,13 +626,16 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -create table t1 (a int auto_increment not null primary key, b char(3))/*!*/; +create table t1 (a int auto_increment not null primary key, b char(3)) +/*!*/; SET INSERT_ID=1/*!*/; SET TIMESTAMP=1579609942/*!*/; -insert into t1 values(null, "a")/*!*/; +insert into t1 values(null, "a") +/*!*/; SET INSERT_ID=2/*!*/; SET TIMESTAMP=1579609942/*!*/; -insert into t1 values(null, "b")/*!*/; +insert into t1 values(null, "b") +/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; @@ -575,22 +652,28 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -create table t1 (a int auto_increment not null primary key, b char(3))/*!*/; +create table t1 (a int auto_increment not null primary key, b char(3)) +/*!*/; SET INSERT_ID=1/*!*/; SET TIMESTAMP=1579609942/*!*/; -insert into t1 values(null, "a")/*!*/; +insert into t1 values(null, "a") +/*!*/; SET INSERT_ID=2/*!*/; SET TIMESTAMP=1579609942/*!*/; -insert into t1 values(null, "b")/*!*/; +insert into t1 values(null, "b") +/*!*/; SET INSERT_ID=3/*!*/; SET TIMESTAMP=1579609944/*!*/; -insert into t1 values(null, "c")/*!*/; +insert into t1 values(null, "c") +/*!*/; SET INSERT_ID=4/*!*/; SET TIMESTAMP=1579609946/*!*/; -insert into t1 values(null, "d")/*!*/; +insert into t1 values(null, "d") +/*!*/; SET INSERT_ID=5/*!*/; SET TIMESTAMP=1579609946/*!*/; -insert into t1 values(null, "e")/*!*/; +insert into t1 values(null, "e") +/*!*/; DELIMITER ; DELIMITER /*!*/; SET INSERT_ID=6/*!*/; @@ -600,7 +683,8 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -insert into t1 values(null, "f")/*!*/; +insert into t1 values(null, "f") +/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; @@ -618,19 +702,24 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -insert into t1 values(null, "a")/*!*/; +insert into t1 values(null, "a") +/*!*/; SET INSERT_ID=2/*!*/; SET TIMESTAMP=1579609942/*!*/; -insert into t1 values(null, "b")/*!*/; +insert into t1 values(null, "b") +/*!*/; SET INSERT_ID=3/*!*/; SET TIMESTAMP=1579609944/*!*/; -insert into t1 values(null, "c")/*!*/; +insert into t1 values(null, "c") +/*!*/; SET INSERT_ID=4/*!*/; SET TIMESTAMP=1579609946/*!*/; -insert into t1 values(null, "d")/*!*/; +insert into t1 values(null, "d") +/*!*/; SET INSERT_ID=5/*!*/; SET TIMESTAMP=1579609946/*!*/; -insert into t1 values(null, "e")/*!*/; +insert into t1 values(null, "e") +/*!*/; DELIMITER ; DELIMITER /*!*/; SET INSERT_ID=6/*!*/; @@ -640,7 +729,8 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -insert into t1 values(null, "f")/*!*/; +insert into t1 values(null, "f") +/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; @@ -657,10 +747,12 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -insert into t1 values(null, "d")/*!*/; +insert into t1 values(null, "d") +/*!*/; SET INSERT_ID=5/*!*/; SET TIMESTAMP=1579609946/*!*/; -insert into t1 values(null, "e")/*!*/; +insert into t1 values(null, "e") +/*!*/; DELIMITER ; DELIMITER /*!*/; SET INSERT_ID=6/*!*/; @@ -670,7 +762,8 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -insert into t1 values(null, "f")/*!*/; +insert into t1 values(null, "f") +/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; @@ -687,22 +780,28 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -create table t1 (a int auto_increment not null primary key, b char(3))/*!*/; +create table t1 (a int auto_increment not null primary key, b char(3)) +/*!*/; SET INSERT_ID=1/*!*/; SET TIMESTAMP=1579609942/*!*/; -insert into t1 values(null, "a")/*!*/; +insert into t1 values(null, "a") +/*!*/; SET INSERT_ID=2/*!*/; SET TIMESTAMP=1579609942/*!*/; -insert into t1 values(null, "b")/*!*/; +insert into t1 values(null, "b") +/*!*/; SET INSERT_ID=3/*!*/; SET TIMESTAMP=1579609944/*!*/; -insert into t1 values(null, "c")/*!*/; +insert into t1 values(null, "c") +/*!*/; SET INSERT_ID=4/*!*/; SET TIMESTAMP=1579609946/*!*/; -insert into t1 values(null, "d")/*!*/; +insert into t1 values(null, "d") +/*!*/; SET INSERT_ID=5/*!*/; SET TIMESTAMP=1579609946/*!*/; -insert into t1 values(null, "e")/*!*/; +insert into t1 values(null, "e") +/*!*/; DELIMITER ; DELIMITER /*!*/; SET INSERT_ID=6/*!*/; @@ -723,13 +822,16 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -insert into t1 values(null, "c")/*!*/; +insert into t1 values(null, "c") +/*!*/; SET INSERT_ID=4/*!*/; SET TIMESTAMP=1579609946/*!*/; -insert into t1 values(null, "d")/*!*/; +insert into t1 values(null, "d") +/*!*/; SET INSERT_ID=5/*!*/; SET TIMESTAMP=1579609946/*!*/; -insert into t1 values(null, "e")/*!*/; +insert into t1 values(null, "e") +/*!*/; DELIMITER ; DELIMITER /*!*/; SET INSERT_ID=6/*!*/; @@ -739,7 +841,8 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -insert into t1 values(null, "f")/*!*/; +insert into t1 values(null, "f") +/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; @@ -756,13 +859,16 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -create table t1 (a int auto_increment not null primary key, b char(3))/*!*/; +create table t1 (a int auto_increment not null primary key, b char(3)) +/*!*/; SET INSERT_ID=1/*!*/; SET TIMESTAMP=1579609942/*!*/; -insert into t1 values(null, "a")/*!*/; +insert into t1 values(null, "a") +/*!*/; SET INSERT_ID=2/*!*/; SET TIMESTAMP=1579609942/*!*/; -insert into t1 values(null, "b")/*!*/; +insert into t1 values(null, "b") +/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; @@ -779,25 +885,32 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -create table t1 (a int auto_increment not null primary key, b char(3))/*!*/; +create table t1 (a int auto_increment not null primary key, b char(3)) +/*!*/; SET INSERT_ID=1/*!*/; SET TIMESTAMP=1579609942/*!*/; -insert into t1 values(null, "a")/*!*/; +insert into t1 values(null, "a") +/*!*/; SET INSERT_ID=2/*!*/; SET TIMESTAMP=1579609942/*!*/; -insert into t1 values(null, "b")/*!*/; +insert into t1 values(null, "b") +/*!*/; SET INSERT_ID=3/*!*/; SET TIMESTAMP=1579609944/*!*/; -insert into t1 values(null, "c")/*!*/; +insert into t1 values(null, "c") +/*!*/; SET INSERT_ID=4/*!*/; SET TIMESTAMP=1579609946/*!*/; -insert into t1 values(null, "d")/*!*/; +insert into t1 values(null, "d") +/*!*/; SET INSERT_ID=5/*!*/; SET TIMESTAMP=1579609946/*!*/; -insert into t1 values(null, "e")/*!*/; +insert into t1 values(null, "e") +/*!*/; SET INSERT_ID=6/*!*/; SET TIMESTAMP=1579609943/*!*/; -insert into t1 values(null, "f")/*!*/; +insert into t1 values(null, "f") +/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; diff --git a/mysql-test/r/mysqlcheck.result b/mysql-test/r/mysqlcheck.result index f8a28009c42..8d7a2d41649 100644 --- a/mysql-test/r/mysqlcheck.result +++ b/mysql-test/r/mysqlcheck.result @@ -46,4 +46,15 @@ create table `t 1`(a int); test.t 1 OK test.t`1 OK drop table `t``1`, `t 1`; +create database d_bug25347; +use d_bug25347; +create table t_bug25347 (a int); +create view v_bug25347 as select * from t_bug25347; +flush tables; +removing and creating +d_bug25347.t_bug25347 OK +drop view v_bug25347; +drop table t_bug25347; +drop database d_bug25347; +use test; End of 5.0 tests diff --git a/mysql-test/r/mysqldump-no-binlog.result b/mysql-test/r/mysqldump-no-binlog.result new file mode 100644 index 00000000000..78bc19b7cba --- /dev/null +++ b/mysql-test/r/mysqldump-no-binlog.result @@ -0,0 +1 @@ +mysqldump: Error: Binlogging on server not active diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result index d03e21b1bb0..a7df1a523cf 100644 --- a/mysql-test/r/mysqltest.result +++ b/mysql-test/r/mysqltest.result @@ -722,4 +722,7 @@ a int(11) YES NULL b varchar(255) YES NULL c datetime YES NULL drop table t1; +mysqltest: At line 1: change user failed: Unknown database 'inexistent' +mysqltest: At line 1: change user failed: Access denied for user 'inexistent'@'localhost' (using password: NO) +mysqltest: At line 1: change user failed: Access denied for user 'root'@'localhost' (using password: YES) End of tests diff --git a/mysql-test/r/ndb_alter_table2.result b/mysql-test/r/ndb_alter_table2.result index 399578dc97b..886c300d53d 100644 --- a/mysql-test/r/ndb_alter_table2.result +++ b/mysql-test/r/ndb_alter_table2.result @@ -40,3 +40,22 @@ a b c select * from t1; a b c drop table t1; +DROP TABLE IF EXISTS truncate_test; +CREATE TABLE truncate_test ( +i INT PRIMARY KEY, +a INT, +b VARCHAR(11), +UNIQUE KEY (a) +) ENGINE = NDB; +INSERT INTO truncate_test VALUES (1, 1, 'test') ON DUPLICATE KEY UPDATE b = 'new'; +INSERT INTO truncate_test VALUES (1, 1, 'test') ON DUPLICATE KEY UPDATE b = 'new'; +TRUNCATE truncate_test; +INSERT INTO truncate_test VALUES (1, 1, 'test') ON DUPLICATE KEY UPDATE b = 'new'; +SELECT * FROM truncate_test; +i a b +1 1 test +INSERT INTO truncate_test VALUES (1, 1, 'test') ON DUPLICATE KEY UPDATE b = 'new'; +SELECT * FROM truncate_test; +i a b +1 1 new +DROP TABLE truncate_test; diff --git a/mysql-test/r/ndb_auto_increment.result b/mysql-test/r/ndb_auto_increment.result index b7c9fa8e2b5..f8ef5af2770 100644 --- a/mysql-test/r/ndb_auto_increment.result +++ b/mysql-test/r/ndb_auto_increment.result @@ -421,10 +421,10 @@ select * from t1 order by a; a 1 20 -21 33 34 35 +65 insert into t1 values (100); insert into t1 values (NULL); insert into t1 values (NULL); @@ -432,11 +432,11 @@ select * from t1 order by a; a 1 20 -21 -22 33 34 35 +65 +66 100 101 set auto_increment_offset = @old_auto_increment_offset; diff --git a/mysql-test/r/ndb_bug31477.result b/mysql-test/r/ndb_bug31477.result new file mode 100644 index 00000000000..002a928b485 --- /dev/null +++ b/mysql-test/r/ndb_bug31477.result @@ -0,0 +1,98 @@ +drop table if exists t1; +create table t1(a int primary key, b int, c int, unique(b)) engine = ndb; +insert into t1 values (2,2,2); +insert into t1 values (3,3,3); +insert into t1 values (4,4,4); +begin; +insert into t1 values (1,1,1); +begin; +update t1 set c = 2 where b = 1; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +rollback; +rollback; +drop table t1; +create table t1(a int primary key, b int, c int, key(b)) engine = ndb; +insert into t1 values (2,2,2); +insert into t1 values (3,3,3); +insert into t1 values (4,4,4); +begin; +insert into t1 values (1,1,1); +begin; +update t1 set c = 2 where b = 1; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +rollback; +rollback; +drop table t1; +--con1 +create table t1(a int primary key, b int, c int, key(b)) engine = ndb; +insert into t1 values (1,1,1); +insert into t1 values (2,2,2); +insert into t1 values (3,3,3); +insert into t1 values (4,4,4); +begin; +update t1 set c = 10 where a = 1; +update t1 set c = 20 where a = 1; +update t1 set c = 30 where a = 1; +--con1 c=30 +select * from t1 where b >= 1 order by b; +a b c +1 1 30 +2 2 2 +3 3 3 +4 4 4 +--con2 c=1 +select * from t1 where b >= 1 order by b; +a b c +1 1 1 +2 2 2 +3 3 3 +4 4 4 +--con1 +delete from t1 where a = 1; +--con1 c=none +select * from t1 where b >= 1 order by b; +a b c +2 2 2 +3 3 3 +4 4 4 +--con2 c=1 +select * from t1 where b >= 1 order by b; +a b c +1 1 1 +2 2 2 +3 3 3 +4 4 4 +--con1 +commit; +--con1 c=none +select * from t1 where b >= 1 order by b; +a b c +2 2 2 +3 3 3 +4 4 4 +--con2 c=none +select * from t1 where b >= 1 order by b; +a b c +2 2 2 +3 3 3 +4 4 4 +--con1 +begin; +insert into t1 values (1,1,1); +update t1 set c = 10 where a = 1; +update t1 set c = 20 where a = 1; +update t1 set c = 30 where a = 1; +--con1 c=30 +select * from t1 where b >= 1 order by b; +a b c +1 1 30 +2 2 2 +3 3 3 +4 4 4 +--con2 c=none +select * from t1 where b >= 1 order by b; +a b c +2 2 2 +3 3 3 +4 4 4 +drop table t1; diff --git a/mysql-test/r/ndb_condition_pushdown.result b/mysql-test/r/ndb_condition_pushdown.result index d49c0cd983e..b211b9079d0 100644 --- a/mysql-test/r/ndb_condition_pushdown.result +++ b/mysql-test/r/ndb_condition_pushdown.result @@ -1904,6 +1904,12 @@ a b d 10 1 4369 20 2 8738 50 5 21845 +-- big filter just below limit +a b d +10 1 4369 +20 2 8738 +50 5 21845 +-- big filter just above limit a b d 10 1 4369 20 2 8738 diff --git a/mysql-test/r/ndb_restore.result b/mysql-test/r/ndb_restore.result index 9faac2df0a4..c48333f6ea8 100644 --- a/mysql-test/r/ndb_restore.result +++ b/mysql-test/r/ndb_restore.result @@ -266,21 +266,41 @@ a 2000 3000 10000 -show table status like 't1_c'; -Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -X X X X X X X X X X 3001 X X X X X X X -show table status like 't2_c'; -Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -X X X X X X X X X X 501 X X X X X X X -show table status like 't4_c'; -Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -X X X X X X X X X X 290000001 X X X X X X X -show table status like 't7_c'; -Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -X X X X X X X X X X 29 X X X X X X X -show table status like 't10_c'; -Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -X X X X X X X X X X 10001 X X X X X X X +select max(capgoaledatta) from t1_c; +max(capgoaledatta) +3000 +select auto_increment from information_schema.tables +where table_name = 't1_c'; +auto_increment +3001 +select max(capgotod) from t2_c; +max(capgotod) +500 +select auto_increment from information_schema.tables +where table_name = 't2_c'; +auto_increment +501 +select max(capfa) from t4_c; +max(capfa) +290000000 +select auto_increment from information_schema.tables +where table_name = 't4_c'; +auto_increment +290000001 +select max(dardtestard) from t7_c; +max(dardtestard) +28 +select auto_increment from information_schema.tables +where table_name = 't7_c'; +auto_increment +29 +select max(a) from t10_c; +max(a) +10000 +select auto_increment from information_schema.tables +where table_name = 't10_c'; +auto_increment +10001 drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9, t10; drop table if exists t1_c,t2_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c, t10_c; 520093696,<the_backup_id> diff --git a/mysql-test/r/null_key.result b/mysql-test/r/null_key.result index 8a440284c53..58c587fe588 100644 --- a/mysql-test/r/null_key.result +++ b/mysql-test/r/null_key.result @@ -429,3 +429,21 @@ Handler_read_prev 0 Handler_read_rnd 0 Handler_read_rnd_next 5 DROP TABLE t1,t2,t3,t4; +CREATE TABLE t1 ( +a int(11) default NULL, +b int(11) default NULL, +KEY a (a,b) +); +INSERT INTO t1 VALUES (0,10),(0,11),(0,12); +CREATE TABLE t2 ( +a int(11) default NULL, +b int(11) default NULL, +KEY a (a) +); +INSERT INTO t2 VALUES (3,NULL),(3,11),(3,12); +SELECT * FROM t2 inner join t1 WHERE ( t1.a = 0 OR t1.a IS NULL) AND t2.a = 3 AND t2.b = t1.b; +a b a b +3 11 0 11 +3 12 0 12 +drop table t1, t2; +End of 5.0 tests diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result index eedc2fa476b..9f6a1b3932c 100644 --- a/mysql-test/r/order_by.result +++ b/mysql-test/r/order_by.result @@ -1064,3 +1064,15 @@ a b 10 00:00:10 0 00:00:00 DROP TABLE t1; +# +# Bug#31590: Wrong error message on sort buffer being too small. +# +create table t1(a int, b tinytext); +insert into t1 values (1,2),(3,2); +set session sort_buffer_size= 30000; +Warnings: +Warning 1292 Truncated incorrect sort_buffer_size value: '30000' +set session max_sort_length= 2180; +select * from t1 order by b; +ERROR HY001: Out of sort memory; increase server sort buffer size +drop table t1; diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index f547654bed1..9aef58d5702 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -1693,4 +1693,202 @@ t1 CREATE TABLE `t1` ( `?` decimal(2,1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; +drop table if exists t1; +create table t1 (a bigint unsigned, b bigint(20) unsigned); +prepare stmt from "insert into t1 values (?,?)"; +set @a= 9999999999999999; +set @b= 14632475938453979136; +insert into t1 values (@a, @b); +select * from t1 where a = @a and b = @b; +a b +9999999999999999 14632475938453979136 +execute stmt using @a, @b; +select * from t1 where a = @a and b = @b; +a b +9999999999999999 14632475938453979136 +9999999999999999 14632475938453979136 +deallocate prepare stmt; +drop table t1; +drop view if exists v1; +drop table if exists t1; +create table t1 (a int, b int); +insert into t1 values (1,1), (2,2), (3,3); +insert into t1 values (3,1), (1,2), (2,3); +prepare stmt from "create view v1 as select * from t1"; +execute stmt; +drop table t1; +create table t1 (a int, b int); +drop view v1; +execute stmt; +show create view v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `a`,`t1`.`b` AS `b` from `t1` +drop view v1; +prepare stmt from "create view v1 (c,d) as select a,b from t1"; +execute stmt; +show create view v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `c`,`t1`.`b` AS `d` from `t1` +select * from v1; +c d +drop view v1; +execute stmt; +deallocate prepare stmt; +show create view v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `c`,`t1`.`b` AS `d` from `t1` +select * from v1; +c d +drop view v1; +prepare stmt from "create view v1 (c) as select b+1 from t1"; +execute stmt; +show create view v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select (`t1`.`b` + 1) AS `c` from `t1` +select * from v1; +c +drop view v1; +execute stmt; +deallocate prepare stmt; +show create view v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select (`t1`.`b` + 1) AS `c` from `t1` +select * from v1; +c +drop view v1; +prepare stmt from "create view v1 (c,d,e,f) as select a,b,a in (select a+2 from t1), a = all (select a from t1) from t1"; +execute stmt; +show create view v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `c`,`t1`.`b` AS `d`,`t1`.`a` in (select (`t1`.`a` + 2) AS `a+2` from `t1`) AS `e`,`t1`.`a` = all (select `t1`.`a` AS `a` from `t1`) AS `f` from `t1` +select * from v1; +c d e f +drop view v1; +execute stmt; +deallocate prepare stmt; +show create view v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `c`,`t1`.`b` AS `d`,`t1`.`a` in (select (`t1`.`a` + 2) AS `a+2` from `t1`) AS `e`,`t1`.`a` = all (select `t1`.`a` AS `a` from `t1`) AS `f` from `t1` +select * from v1; +c d e f +drop view v1; +prepare stmt from "create or replace view v1 as select 1"; +execute stmt; +show create view v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select 1 AS `1` +select * from v1; +1 +1 +execute stmt; +show create view v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select 1 AS `1` +deallocate prepare stmt; +show create view v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select 1 AS `1` +select * from v1; +1 +1 +drop view v1; +prepare stmt from "create view v1 as select 1, 1"; +execute stmt; +show create view v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select 1 AS `1`,1 AS `My_exp_1` +select * from v1; +1 My_exp_1 +1 1 +drop view v1; +execute stmt; +deallocate prepare stmt; +show create view v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select 1 AS `1`,1 AS `My_exp_1` +select * from v1; +1 My_exp_1 +1 1 +drop view v1; +prepare stmt from "create view v1 (x) as select a from t1 where a > 1"; +execute stmt; +show create view v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `x` from `t1` where (`t1`.`a` > 1) +select * from v1; +x +drop view v1; +execute stmt; +deallocate prepare stmt; +show create view v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `x` from `t1` where (`t1`.`a` > 1) +select * from v1; +x +drop view v1; +prepare stmt from "create view v1 as select * from `t1` `b`"; +execute stmt; +show create view v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `b`.`a` AS `a`,`b`.`b` AS `b` from `t1` `b` +select * from v1; +a b +drop view v1; +execute stmt; +deallocate prepare stmt; +show create view v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `b`.`a` AS `a`,`b`.`b` AS `b` from `t1` `b` +select * from v1; +a b +drop view v1; +prepare stmt from "create view v1 (a,b,c) as select * from t1"; +execute stmt; +ERROR HY000: View's SELECT and view's field list have different column counts +execute stmt; +ERROR HY000: View's SELECT and view's field list have different column counts +deallocate prepare stmt; +drop table t1; +create temporary table t1 (a int, b int); +prepare stmt from "create view v1 as select * from t1"; +execute stmt; +ERROR HY000: View's SELECT refers to a temporary table 't1' +execute stmt; +ERROR HY000: View's SELECT refers to a temporary table 't1' +deallocate prepare stmt; +drop table t1; +prepare stmt from "create view v1 as select * from t1"; +ERROR 42S02: Table 'test.t1' doesn't exist +prepare stmt from "create view v1 as select * from `t1` `b`"; +ERROR 42S02: Table 'test.t1' doesn't exist +prepare stmt from "select ?"; +set @arg= 123456789.987654321; +select @arg; +@arg +123456789.987654321 +execute stmt using @arg; +? +123456789.987654321 +set @arg= "string"; +select @arg; +@arg +string +execute stmt using @arg; +? +string +set @arg= 123456; +select @arg; +@arg +123456 +execute stmt using @arg; +? +123456 +set @arg= cast(-12345.54321 as decimal(20, 10)); +select @arg; +@arg +-12345.5432100000 +execute stmt using @arg; +? +-12345.5432100000 +deallocate prepare stmt; End of 5.0 tests. diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result index f666030465e..0c4c332395a 100644 --- a/mysql-test/r/range.result +++ b/mysql-test/r/range.result @@ -1153,6 +1153,19 @@ explain select * from t1 where dateval >= '2007-01-01 00:00:00' and dateval <= ' id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range dateval dateval 4 NULL 2 Using where drop table t1; +CREATE TABLE t1 ( +a varchar(32), index (a) +) DEFAULT CHARSET=latin1 COLLATE=latin1_bin; +INSERT INTO t1 VALUES +('B'), ('A'), ('A'), ('C'), ('B'), ('A'), ('A'); +SELECT a FROM t1 WHERE a='b' OR a='B'; +a +B +B +EXPLAIN SELECT a FROM t1 WHERE a='b' OR a='B'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range a a 35 NULL 3 Using where; Using index +DROP TABLE t1; CREATE TABLE t1 (f1 TINYINT(11) UNSIGNED NOT NULL, PRIMARY KEY (f1)); INSERT INTO t1 VALUES (127),(254),(0),(1),(255); SELECT SQL_NO_CACHE COUNT(*) FROM t1 WHERE f1 < 256; diff --git a/mysql-test/r/row.result b/mysql-test/r/row.result index 702e66fea62..98c79d4bc00 100644 --- a/mysql-test/r/row.result +++ b/mysql-test/r/row.result @@ -434,3 +434,12 @@ SELECT @x; @x 99 DROP TABLE t1; +CREATE TABLE t1 (a INT, b INT); +INSERT INTO t1 VALUES (1,1); +SELECT ROW(a, 1) IN (SELECT SUM(b), 1) FROM t1 GROUP BY a; +ROW(a, 1) IN (SELECT SUM(b), 1) +1 +SELECT ROW(a, 1) IN (SELECT SUM(b), 3) FROM t1 GROUP BY a; +ROW(a, 1) IN (SELECT SUM(b), 3) +0 +DROP TABLE t1; diff --git a/mysql-test/r/rpl_charset.result b/mysql-test/r/rpl_charset.result index 4b6d9f44a2b..c77818d34ee 100644 --- a/mysql-test/r/rpl_charset.result +++ b/mysql-test/r/rpl_charset.result @@ -183,78 +183,101 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -drop database if exists mysqltest2/*!*/; +drop database if exists mysqltest2 +/*!*/; SET TIMESTAMP=1000000000/*!*/; -drop database if exists mysqltest3/*!*/; +drop database if exists mysqltest3 +/*!*/; SET TIMESTAMP=1000000000/*!*/; -create database mysqltest2 character set latin2/*!*/; +create database mysqltest2 character set latin2 +/*!*/; SET TIMESTAMP=1000000000/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=30/*!*/; -create database mysqltest3/*!*/; +create database mysqltest3 +/*!*/; SET TIMESTAMP=1000000000/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=64/*!*/; -drop database mysqltest3/*!*/; +drop database mysqltest3 +/*!*/; SET TIMESTAMP=1000000000/*!*/; -create database mysqltest3/*!*/; +create database mysqltest3 +/*!*/; use mysqltest2/*!*/; SET TIMESTAMP=1000000000/*!*/; -create table t1 (a int auto_increment primary key, b varchar(100))/*!*/; +create table t1 (a int auto_increment primary key, b varchar(100)) +/*!*/; SET INSERT_ID=1/*!*/; SET TIMESTAMP=1000000000/*!*/; /*!\C cp850 *//*!*/; SET @@session.character_set_client=4,@@session.collation_connection=27,@@session.collation_server=64/*!*/; -insert into t1 (b) values(@@character_set_server)/*!*/; +insert into t1 (b) values(@@character_set_server) +/*!*/; SET INSERT_ID=2/*!*/; SET TIMESTAMP=1000000000/*!*/; -insert into t1 (b) values(@@collation_server)/*!*/; +insert into t1 (b) values(@@collation_server) +/*!*/; SET INSERT_ID=3/*!*/; SET TIMESTAMP=1000000000/*!*/; -insert into t1 (b) values(@@character_set_client)/*!*/; +insert into t1 (b) values(@@character_set_client) +/*!*/; SET INSERT_ID=4/*!*/; SET TIMESTAMP=1000000000/*!*/; -insert into t1 (b) values(@@character_set_connection)/*!*/; +insert into t1 (b) values(@@character_set_connection) +/*!*/; SET INSERT_ID=5/*!*/; SET TIMESTAMP=1000000000/*!*/; -insert into t1 (b) values(@@collation_connection)/*!*/; +insert into t1 (b) values(@@collation_connection) +/*!*/; SET TIMESTAMP=1000000000/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=5,@@session.collation_server=64/*!*/; -truncate table t1/*!*/; +truncate table t1 +/*!*/; SET INSERT_ID=1/*!*/; SET TIMESTAMP=1000000000/*!*/; -insert into t1 (b) values(@@collation_connection)/*!*/; +insert into t1 (b) values(@@collation_connection) +/*!*/; SET INSERT_ID=2/*!*/; SET TIMESTAMP=1000000000/*!*/; -insert into t1 (b) values(LEAST("Müller","Muffler"))/*!*/; +insert into t1 (b) values(LEAST("Müller","Muffler")) +/*!*/; SET INSERT_ID=3/*!*/; SET TIMESTAMP=1000000000/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=31,@@session.collation_server=64/*!*/; -insert into t1 (b) values(@@collation_connection)/*!*/; +insert into t1 (b) values(@@collation_connection) +/*!*/; SET INSERT_ID=4/*!*/; SET TIMESTAMP=1000000000/*!*/; -insert into t1 (b) values(LEAST("Müller","Muffler"))/*!*/; +insert into t1 (b) values(LEAST("Müller","Muffler")) +/*!*/; SET TIMESTAMP=1000000000/*!*/; -truncate table t1/*!*/; +truncate table t1 +/*!*/; SET INSERT_ID=1/*!*/; SET @`a`:=_cp850 0x4DFC6C6C6572 COLLATE `cp850_general_ci`/*!*/; SET TIMESTAMP=1000000000/*!*/; -insert into t1 (b) values(collation(@a))/*!*/; +insert into t1 (b) values(collation(@a)) +/*!*/; SET TIMESTAMP=1000000000/*!*/; -drop database mysqltest2/*!*/; +drop database mysqltest2 +/*!*/; SET TIMESTAMP=1000000000/*!*/; -drop database mysqltest3/*!*/; +drop database mysqltest3 +/*!*/; use test/*!*/; SET TIMESTAMP=1000000000/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=30/*!*/; -CREATE TABLE t1 (c1 VARBINARY(255), c2 VARBINARY(255))/*!*/; +CREATE TABLE t1 (c1 VARBINARY(255), c2 VARBINARY(255)) +/*!*/; SET TIMESTAMP=1000000000/*!*/; /*!\C koi8r *//*!*/; SET @@session.character_set_client=7,@@session.collation_connection=51,@@session.collation_server=30/*!*/; -INSERT INTO t1 (c1, c2) VALUES ('îÕ, ÚÁ ÒÙÂÁÌËÕ','îÕ, ÚÁ ÒÙÂÁÌËÕ')/*!*/; +INSERT INTO t1 (c1, c2) VALUES ('îÕ, ÚÁ ÒÙÂÁÌËÕ','îÕ, ÚÁ ÒÙÂÁÌËÕ') +/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; diff --git a/mysql-test/r/rpl_drop_view.result b/mysql-test/r/rpl_drop_view.result new file mode 100644 index 00000000000..ef625464881 --- /dev/null +++ b/mysql-test/r/rpl_drop_view.result @@ -0,0 +1,27 @@ +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; +drop table if exists t1, t2; +drop view if exists v1, v2, v3, not_exist_view; +create table t1 (a int); +create table t2 (b int); +create table t3 (c int); +create view v1 as select * from t1; +create view v2 as select * from t2; +create view v3 as select * from t3; +drop view not_exist_view; +ERROR 42S02: Unknown table 'not_exist_view' +drop view v1, not_exist_view; +ERROR 42S02: Unknown table 'not_exist_view' +select * from v1; +ERROR 42S02: Table 'test.v1' doesn't exist +drop view v2, v3; +select * from v1; +ERROR 42S02: Table 'test.v1' doesn't exist +select * from v2; +ERROR 42S02: Table 'test.v2' doesn't exist +select * from v3; +ERROR 42S02: Table 'test.v3' doesn't exist diff --git a/mysql-test/r/rpl_grant.result b/mysql-test/r/rpl_grant.result index 4d7ad298ce4..17bceb339c8 100644 --- a/mysql-test/r/rpl_grant.result +++ b/mysql-test/r/rpl_grant.result @@ -48,7 +48,7 @@ Master_User root Master_Port MASTER_PORT Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 609 +Read_Master_Log_Pos 515 Relay_Log_File # Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 @@ -63,7 +63,7 @@ Replicate_Wild_Ignore_Table Last_Errno 0 Last_Error Skip_Counter 0 -Exec_Master_Log_Pos 609 +Exec_Master_Log_Pos 515 Relay_Log_Space # Until_Condition None Until_Log_File diff --git a/mysql-test/r/rpl_loaddata_map.result b/mysql-test/r/rpl_loaddata_map.result new file mode 100644 index 00000000000..c2159adef6a --- /dev/null +++ b/mysql-test/r/rpl_loaddata_map.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 t2 (id int not null primary key auto_increment); +select @@session.read_buffer_size - @@session.max_allowed_packet > 0 ; +@@session.read_buffer_size - @@session.max_allowed_packet > 0 +1 +load data infile 'MYSQLTEST_VARDIR/tmp/bug30435_5k.txt' into table t2; +select count(*) from t2 /* 5 000 */; +count(*) +5000 +show binlog events in 'master-bin.000002' from 98; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000002 98 Query 1 # use `test`; create table t2 (id int not null primary key auto_increment) +master-bin.000002 221 Begin_load_query 1 # ;file_id=#;block_len=8192 +master-bin.000002 8436 Append_block 1 # ;file_id=#;block_len=8192 +master-bin.000002 16651 Append_block 1 # ;file_id=#;block_len=7509 +master-bin.000002 24183 Execute_load_query 1 # use `test`; load data infile 'MYSQLTEST_VARDIR/tmp/bug30435_5k.txt' into table t2 ;file_id=# +select count(*) from t2 /* 5 000 */; +count(*) +5000 +drop table t1, t2; +end of the tests diff --git a/mysql-test/r/rpl_server_id.result b/mysql-test/r/rpl_server_id.result new file mode 100644 index 00000000000..1e74394c122 --- /dev/null +++ b/mysql-test/r/rpl_server_id.result @@ -0,0 +1,34 @@ +set global server_id=1; +reset master; +drop table if exists t1,t2,t3; +create table t1 (a int); +select @@server_id; +@@server_id +1 +show binlog events from <binlog_start>; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query 1 # use `test`; drop table if exists t1,t2,t3 +master-bin.000001 # Query 1 # use `test`; create table t1 (a int) +set global server_id=2; +create table t2 (b int); +select @@server_id; +@@server_id +2 +show binlog events from <binlog_start>; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query 1 # use `test`; drop table if exists t1,t2,t3 +master-bin.000001 # Query 1 # use `test`; create table t1 (a int) +master-bin.000001 # Query 2 # use `test`; create table t2 (b int) +set global server_id=3; +create table t3 (c int); +select @@server_id; +@@server_id +3 +show binlog events from <binlog_start>; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query 1 # use `test`; drop table if exists t1,t2,t3 +master-bin.000001 # Query 1 # use `test`; create table t1 (a int) +master-bin.000001 # Query 2 # use `test`; create table t2 (b int) +master-bin.000001 # Query 3 # use `test`; create table t3 (c int) +set global server_id=1; +drop table t1,t2,t3; diff --git a/mysql-test/r/rpl_slave_skip.result b/mysql-test/r/rpl_slave_skip.result index a59ac3eb884..0e06e0951b3 100644 --- a/mysql-test/r/rpl_slave_skip.result +++ b/mysql-test/r/rpl_slave_skip.result @@ -5,8 +5,10 @@ reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; **** On Master **** -CREATE TABLE t1 (a INT, b SET('master','slave')) ENGINE=INNODB; -CREATE TABLE t2 (a INT, b SET('master','slave')) ENGINE=MYISAM; +CREATE TABLE t1 (a INT, b SET('master','slave')) ENGINE=InnoDB; +CREATE TABLE t2 (a INT, b SET('master','slave')) ENGINE=MyISAM; +CREATE TABLE t3 (a CHAR(20), b SET('master','slave')) ENGINE=InnoDB; +CREATE TABLE t4 (a CHAR(20), b SET('master','slave')) ENGINE=MyISAM; ==== Skipping normal transactions ==== **** On Slave **** STOP SLAVE; @@ -139,6 +141,102 @@ a b SELECT * FROM t2 ORDER BY a; a b 5 master,slave +==== Skipping first event of a LOAD DATA for a transactional table ==== +**** On Slave **** +STOP SLAVE; +**** On Master **** +SET AUTOCOMMIT=1; +LOAD DATA INFILE '../std_data_ln/words.dat' INTO TABLE t3(a) SET b = 'master'; +INSERT INTO t3 VALUES ('Go Rin No Sho', 'master,slave'); +SELECT COUNT(*) FROM t3; +COUNT(*) +71 +**** On Slave **** +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; +START SLAVE; +-- Should only contain records marked 'master,slave' +SELECT * FROM t3 ORDER BY a; +a b +Go Rin No Sho master,slave +**** On Master **** +DELETE FROM t3; +==== Skipping first event of a LOAD DATA for a non-transactional table ==== +**** On Slave **** +STOP SLAVE; +**** On Master **** +SET AUTOCOMMIT=1; +LOAD DATA INFILE '../std_data_ln/words.dat' INTO TABLE t4(a) SET b = 'master'; +INSERT INTO t4 VALUES ('Go Rin No Sho', 'master,slave'); +SELECT COUNT(*) FROM t4; +COUNT(*) +71 +**** On Slave **** +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; +START SLAVE; +-- Should only contain records marked 'master,slave' +SELECT * FROM t4 ORDER BY a; +a b +Go Rin No Sho master,slave +**** On Master **** +DELETE FROM t4; +==== Try with a big file so that we get an append_block event as well +**** On Slave **** +STOP SLAVE; +**** On Master **** +SET AUTOCOMMIT=1; +SET SQL_LOG_BIN=0; +LOAD DATA INFILE '../std_data_ln/words.dat' INTO TABLE t4(a) SET b = 'master'; +INSERT INTO t4 SELECT * FROM t4; +INSERT INTO t4 SELECT * FROM t4; +INSERT INTO t4 SELECT * FROM t4; +INSERT INTO t4 SELECT * FROM t4; +INSERT INTO t4 SELECT * FROM t4; +INSERT INTO t4 SELECT * FROM t4; +INSERT INTO t4 SELECT * FROM t4; +INSERT INTO t4 SELECT * FROM t4; +INSERT INTO t4 SELECT * FROM t4; +INSERT INTO t4 SELECT * FROM t4; +INSERT INTO t4 SELECT * FROM t4; +SELECT a FROM t4 INTO OUTFILE 'rpl_slave_skip_words.dat'; +SET SQL_LOG_BIN=1; +LOAD DATA INFILE 'rpl_slave_skip_words.dat' INTO TABLE t4(a) SET b = 'master'; +INSERT INTO t4 VALUES ('Go Rin No Sho', 'master,slave'); +SELECT COUNT(*) FROM t4; +COUNT(*) +286721 +**** On Slave **** +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; +START SLAVE; +-- Should only contain records marked 'master,slave' +SELECT * FROM t4 ORDER BY a; +a b +Go Rin No Sho master,slave +**** On Master **** +DELETE FROM t4; +**** On Master **** +CREATE TABLE t5 (a int, b int, c SET('master','slave'), PRIMARY KEY (a,b)) ENGINE=MyISAM; +LOAD DATA INFILE '../std_data_ln/loaddata5.dat' INTO TABLE t5 FIELDS TERMINATED BY '' ENCLOSED BY '' (a,b) SET c='master,slave'; +**** On Slave **** +STOP SLAVE; +**** On Master **** +LOAD DATA INFILE '../std_data_ln/loaddata5.dat' INTO TABLE t5 FIELDS TERMINATED BY '' ENCLOSED BY '' (a,b) SET c=''; +ERROR 23000: Duplicate entry '1-2' for key 1 +INSERT INTO t5 VALUES (42, 42, 'master,slave'); +SELECT * FROM t5; +a b c +1 2 master,slave +3 4 master,slave +5 6 master,slave +42 42 master,slave +**** On Slave **** +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; +START SLAVE; +SELECT * FROM t5; +a b c +1 2 master,slave +3 4 master,slave +5 6 master,slave +42 42 master,slave ==== Cleanup ==== **** On Master **** -DROP TABLE t1, t2; +DROP TABLE t1, t2, t3, t4, t5; diff --git a/mysql-test/r/rpl_timezone.result b/mysql-test/r/rpl_timezone.result index 7a18a26afd3..7a5d09ea6a7 100644 --- a/mysql-test/r/rpl_timezone.result +++ b/mysql-test/r/rpl_timezone.result @@ -52,20 +52,26 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -create table t1 (t timestamp)/*!*/; +create table t1 (t timestamp) +/*!*/; SET TIMESTAMP=100000000/*!*/; -create table t2 (t char(32))/*!*/; +create table t2 (t char(32)) +/*!*/; SET TIMESTAMP=100000000/*!*/; SET @@session.time_zone='Europe/Moscow'/*!*/; -insert into t1 values ('20050101000000'), ('20050611093902')/*!*/; +insert into t1 values ('20050101000000'), ('20050611093902') +/*!*/; SET TIMESTAMP=100000000/*!*/; SET @@session.time_zone='UTC'/*!*/; -insert into t1 values ('20040101000000'), ('20040611093902')/*!*/; +insert into t1 values ('20040101000000'), ('20040611093902') +/*!*/; SET TIMESTAMP=100000000/*!*/; -delete from t1/*!*/; +delete from t1 +/*!*/; SET TIMESTAMP=100000000/*!*/; SET @@session.time_zone='Europe/Moscow'/*!*/; -insert into t1 values ('20040101000000'), ('20040611093902')/*!*/; +insert into t1 values ('20040101000000'), ('20040611093902') +/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; diff --git a/mysql-test/r/rpl_transaction.result b/mysql-test/r/rpl_transaction.result new file mode 100644 index 00000000000..9ea0c8f7afd --- /dev/null +++ b/mysql-test/r/rpl_transaction.result @@ -0,0 +1,95 @@ +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 tmyisam (a int) ENGINE = MYISAM; +CREATE TABLE tinnodb (a int) ENGINE = INNODB; +SHOW CREATE TABLE tmyisam; +Table Create Table +tmyisam CREATE TABLE `tmyisam` ( + `a` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SHOW CREATE TABLE tinnodb; +Table Create Table +tinnodb CREATE TABLE `tinnodb` ( + `a` int(11) default NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +==== Test 1: Non-XA Engines ==== +--- on master --- +SET AUTOCOMMIT = 1; +INSERT INTO tmyisam VALUES (1); +BEGIN; +INSERT INTO tmyisam VALUES (2); +INSERT INTO tmyisam VALUES (3); +COMMIT; +BEGIN; +INSERT INTO tmyisam VALUES (5); +INSERT INTO tmyisam VALUES (6); +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +SELECT * FROM tmyisam ORDER BY a; +a +1 +2 +3 +5 +6 +--- on slave --- +SELECT * FROM tmyisam ORDER BY a; +a +1 +2 +3 +5 +6 +==== Test 2: Master crash before writing XID event on XA engine ==== +--- on master --- +INSERT INTO tinnodb VALUES (1); +SELECT * FROM tinnodb ORDER BY a; +a +1 +--- on slave --- +STOP SLAVE; +SHOW SLAVE STATUS; +Slave_IO_State +Master_Host 127.0.0.1 +Master_User root +Master_Port # +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running No +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table # +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +SELECT * FROM tinnodb ORDER BY a; +a +DROP TABLE tmyisam; +DROP TABLE tinnodb; +DROP TABLE tmyisam; +DROP TABLE tinnodb; diff --git a/mysql-test/r/rpl_user.result b/mysql-test/r/rpl_user.result new file mode 100644 index 00000000000..25e0f310f55 --- /dev/null +++ b/mysql-test/r/rpl_user.result @@ -0,0 +1,45 @@ +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; +set sql_log_bin=0; +delete from mysql.user where Host='fakehost'; +set sql_log_bin=1; +set sql_log_bin=0; +delete from mysql.user where Host='fakehost'; +set sql_log_bin=1; +create user 'foo'@'fakehost'; +create user 'foo'@'fakehost', 'bar'@'fakehost'; +ERROR HY000: Operation CREATE USER failed for 'foo'@'fakehost' +create user 'foo'@'fakehost', 'bar'@'fakehost'; +ERROR HY000: Operation CREATE USER failed for 'foo'@'fakehost','bar'@'fakehost' +select Host,User from mysql.user where Host='fakehost'; +Host User +fakehost bar +fakehost foo +rename user 'foo'@'fakehost' to 'foofoo'@'fakehost'; +rename user 'not_exist_user1'@'fakehost' to 'foobar'@'fakehost', 'bar'@'fakehost' to 'barbar'@'fakehost'; +ERROR HY000: Operation RENAME USER failed for 'not_exist_user1'@'fakehost' +rename user 'not_exist_user1'@'fakehost' to 'foobar'@'fakehost', 'not_exist_user2'@'fakehost' to 'barfoo'@'fakehost'; +ERROR HY000: Operation RENAME USER failed for 'not_exist_user1'@'fakehost','not_exist_user2'@'fakehost' +select Host,User from mysql.user where Host='fakehost'; +Host User +fakehost barbar +fakehost foofoo +drop user 'foofoo'@'fakehost'; +drop user 'not_exist_user1'@'fakehost', 'barbar'@'fakehost'; +ERROR HY000: Operation DROP USER failed for 'not_exist_user1'@'fakehost' +drop user 'not_exist_user1'@'fakehost', 'not_exist_user2'@'fakehost'; +ERROR HY000: Operation DROP USER failed for 'not_exist_user1'@'fakehost','not_exist_user2'@'fakehost' +select Host,User from mysql.user where Host='fakehost'; +Host User +show binlog events from 98; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 98 Query 1 # use `test`; create user 'foo'@'fakehost' +master-bin.000001 189 Query 1 # use `test`; create user 'foo'@'fakehost', 'bar'@'fakehost' +master-bin.000001 298 Query 1 # use `test`; rename user 'foo'@'fakehost' to 'foofoo'@'fakehost' +master-bin.000001 412 Query 1 # use `test`; rename user 'not_exist_user1'@'fakehost' to 'foobar'@'fakehost', 'bar'@'fakehost' to 'barbar'@'fakehost' +master-bin.000001 579 Query 1 # use `test`; drop user 'foofoo'@'fakehost' +master-bin.000001 671 Query 1 # use `test`; drop user 'not_exist_user1'@'fakehost', 'barbar'@'fakehost' diff --git a/mysql-test/r/rpl_user_variables.result b/mysql-test/r/rpl_user_variables.result index 26ac2b26aaa..b8032a9c362 100644 --- a/mysql-test/r/rpl_user_variables.result +++ b/mysql-test/r/rpl_user_variables.result @@ -290,6 +290,22 @@ select * from t1; a b 2 1 drop table t1; +create table t1(a int); +insert into t1 values (1),(2); +prepare s1 from 'insert into t1 select a from t1 limit ?'; +set @x='1.1'; +execute s1 using @x; +select * from t1; +a +1 +2 +1 +select * from t1; +a +1 +2 +1 +drop table t1; End of 5.0 tests. DROP FUNCTION IF EXISTS f1; DROP FUNCTION IF EXISTS f2; diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 3ca84bcf34b..c2cd2129a32 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -4328,4 +4328,31 @@ SELECT * FROM t1 WHERE c1 > NULL + 1; c1 DROP TABLE t1; +CREATE TABLE t1 (a VARCHAR(10) NOT NULL PRIMARY KEY); +INSERT INTO t1 (a) VALUES ('foo0'), ('bar0'), ('baz0'); +SELECT * FROM t1 WHERE a IN (CONCAT('foo', 0), 'bar'); +a +foo0 +DROP TABLE t1; +CREATE TABLE t1 (a INT, b INT); +CREATE TABLE t2 (a INT, c INT, KEY(a)); +INSERT INTO t1 VALUES (1, 1), (2, 2); +INSERT INTO t2 VALUES (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), +(2, 1), (2, 2), (2, 3), (2, 4), (2, 5), +(3, 1), (3, 2), (3, 3), (3, 4), (3, 5), +(4, 1), (4, 2), (4, 3), (4, 4), (4, 5); +FLUSH STATUS; +SELECT DISTINCT b FROM t1 LEFT JOIN t2 USING(a) WHERE c <= 3; +b +1 +2 +SHOW STATUS LIKE 'Handler_read%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 2 +Handler_read_next 0 +Handler_read_prev 0 +Handler_read_rnd 0 +Handler_read_rnd_next 6 +DROP TABLE t1, t2; End of 5.0 tests diff --git a/mysql-test/r/sp-code.result b/mysql-test/r/sp-code.result index 219f3c9b37a..855cabc25d8 100644 --- a/mysql-test/r/sp-code.result +++ b/mysql-test/r/sp-code.result @@ -733,4 +733,113 @@ optimizer: keep hreturn drop table t1; drop procedure proc_26977_broken; drop procedure proc_26977_works; +drop procedure if exists proc_33618_h; +drop procedure if exists proc_33618_c; +create procedure proc_33618_h(num int) +begin +declare count1 int default '0'; +declare vb varchar(30); +declare last_row int; +while(num>=1) do +set num=num-1; +begin +declare cur1 cursor for select `a` from t_33618; +declare continue handler for not found set last_row = 1; +set last_row:=0; +open cur1; +rep1: +repeat +begin +declare exit handler for 1062 begin end; +fetch cur1 into vb; +if (last_row = 1) then +## should generate a hpop instruction here +leave rep1; +end if; +end; +until last_row=1 +end repeat; +close cur1; +end; +end while; +end// +create procedure proc_33618_c(num int) +begin +declare count1 int default '0'; +declare vb varchar(30); +declare last_row int; +while(num>=1) do +set num=num-1; +begin +declare cur1 cursor for select `a` from t_33618; +declare continue handler for not found set last_row = 1; +set last_row:=0; +open cur1; +rep1: +repeat +begin +declare cur2 cursor for select `b` from t_33618; +fetch cur1 into vb; +if (last_row = 1) then +## should generate a cpop instruction here +leave rep1; +end if; +end; +until last_row=1 +end repeat; +close cur1; +end; +end while; +end// +show procedure code proc_33618_h; +Pos Instruction +0 set count1@1 _latin1'0' +1 set vb@2 NULL +2 set last_row@3 NULL +3 jump_if_not 24(24) (num@0 >= 1) +4 set num@0 (num@0 - 1) +5 cpush cur1@0 +6 hpush_jump 9 4 CONTINUE +7 set last_row@3 1 +8 hreturn 4 +9 set last_row@3 0 +10 copen cur1@0 +11 hpush_jump 13 4 EXIT +12 hreturn 0 17 +13 cfetch cur1@0 vb@2 +14 jump_if_not 17(17) (last_row@3 = 1) +15 hpop 1 +16 jump 19 +17 hpop 1 +18 jump_if_not 11(19) (last_row@3 = 1) +19 cclose cur1@0 +20 hpop 1 +21 cpop 1 +22 jump 3 +show procedure code proc_33618_c; +Pos Instruction +0 set count1@1 _latin1'0' +1 set vb@2 NULL +2 set last_row@3 NULL +3 jump_if_not 23(23) (num@0 >= 1) +4 set num@0 (num@0 - 1) +5 cpush cur1@0 +6 hpush_jump 9 4 CONTINUE +7 set last_row@3 1 +8 hreturn 4 +9 set last_row@3 0 +10 copen cur1@0 +11 cpush cur2@1 +12 cfetch cur1@0 vb@2 +13 jump_if_not 16(16) (last_row@3 = 1) +14 cpop 1 +15 jump 18 +16 cpop 1 +17 jump_if_not 11(18) (last_row@3 = 1) +18 cclose cur1@0 +19 hpop 1 +20 cpop 1 +21 jump 3 +drop procedure proc_33618_h; +drop procedure proc_33618_c; End of 5.0 tests. diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index b4bcfbdc7f7..0fc0adc89ad 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -1465,3 +1465,51 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp SELECT ..inexistent(); 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 '.inexistent()' at line 1 USE test; +drop procedure if exists proc_33983_a; +drop procedure if exists proc_33983_b; +drop procedure if exists proc_33983_c; +drop procedure if exists proc_33983_d; +create procedure proc_33983_a() +begin +label1: +begin +label2: +begin +select 1; +end label1; +end; +end| +ERROR 42000: End-label label1 without match +create procedure proc_33983_b() +begin +label1: +repeat +label2: +repeat +select 1; +until FALSE end repeat label1; +until FALSE end repeat; +end| +ERROR 42000: End-label label1 without match +create procedure proc_33983_c() +begin +label1: +while TRUE do +label2: +while TRUE do +select 1; +end while label1; +end while; +end| +ERROR 42000: End-label label1 without match +create procedure proc_33983_d() +begin +label1: +loop +label2: +loop +select 1; +end loop label1; +end loop; +end| +ERROR 42000: End-label label1 without match diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 061bbafd9a1..562102f0ea7 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -6578,6 +6578,74 @@ DROP PROCEDURE db28318_a.t1; DROP PROCEDURE db28318_b.t2; DROP DATABASE db28318_a; DROP DATABASE db28318_b; +USE test; +DROP TABLE IF EXISTS t1; +DROP PROCEDURE IF EXISTS bug29770; +CREATE TABLE t1(a int); +CREATE PROCEDURE bug29770() +BEGIN +DECLARE CONTINUE HANDLER FOR SQLSTATE '42S22' SET @state:= 'run'; +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET @exception:= 'run'; +SELECT x FROM t1; +END| +CALL bug29770(); +SELECT @state, @exception; +@state @exception +run NULL +DROP TABLE t1; +DROP PROCEDURE bug29770; +use test; +drop table if exists t_33618; +drop procedure if exists proc_33618; +create table t_33618 (`a` int, unique(`a`), `b` varchar(30)) engine=myisam; +insert into t_33618 (`a`,`b`) values (1,'1'),(2,'2'); +create procedure proc_33618(num int) +begin +declare count1 int default '0'; +declare vb varchar(30); +declare last_row int; +while(num>=1) do +set num=num-1; +begin +declare cur1 cursor for select `a` from t_33618; +declare continue handler for not found set last_row = 1; +set last_row:=0; +open cur1; +rep1: +repeat +begin +declare exit handler for 1062 begin end; +fetch cur1 into vb; +if (last_row = 1) then +leave rep1; +end if; +end; +until last_row=1 +end repeat; +close cur1; +end; +end while; +end// +call proc_33618(20); +drop table t_33618; +drop procedure proc_33618; +# +# Bug#30787: Stored function ignores user defined alias. +# +use test; +drop function if exists func30787; +create table t1(f1 int); +insert into t1 values(1),(2); +create function func30787(p1 int) returns int +begin +return p1; +end | +select (select func30787(f1)) as ttt from t1; +ttt +1 +2 +drop function func30787; +drop table t1; # ------------------------------------------------------------------ # -- End of 5.0 tests # ------------------------------------------------------------------ diff --git a/mysql-test/r/sp_trans_log.result b/mysql-test/r/sp_trans_log.result index 9b644798079..eb0770cb0a1 100644 --- a/mysql-test/r/sp_trans_log.result +++ b/mysql-test/r/sp_trans_log.result @@ -16,6 +16,7 @@ show binlog events from 98 /* with fixes for #23333 will show there are 2 querie Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query 1 # # master-bin.000001 # Query 1 # # +master-bin.000001 # Query 1 # # select count(*),@a from t1 /* must be 1,1 */| count(*) @a 1 1 diff --git a/mysql-test/r/strict.result b/mysql-test/r/strict.result index 34869862a63..0a714635f70 100644 --- a/mysql-test/r/strict.result +++ b/mysql-test/r/strict.result @@ -934,6 +934,8 @@ NULL NULL DROP TABLE t1; CREATE TABLE t1 (col1 CHAR(5), col2 VARCHAR(6)); INSERT INTO t1 VALUES ('hello', 'hello'),('he', 'he'),('hello ', 'hello '); +Warnings: +Note 1265 Data truncated for column 'col1' at row 3 INSERT INTO t1 (col1) VALUES ('hellobob'); ERROR 22001: Data too long for column 'col1' at row 1 INSERT INTO t1 (col2) VALUES ('hellobob'); diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 527c45671f4..2de2589fc92 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -4147,103 +4147,37 @@ DROP TABLE t1,t2; create table t1(a int,b int,key(a),key(b)); insert into t1(a,b) values (1,2),(2,1),(2,3),(3,4),(5,4),(5,5), (6,7),(7,4),(5,3); -select sum(a),a from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 -)group by b limit 1)group by b limit 1 -)group by b limit 1)group by b limit 1)group by b limit 1 -)group by b limit 1)group by b limit 1)group by b limit 1 -)group by b limit 1)group by b limit 1)group by b limit 1) -group by a; -sum(a) a -select sum(a),a from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 -)group by b limit 1)group by b limit 1)group by b limit 1 -)group by b limit 1)group by b limit 1)group by b limit 1 -)group by b limit 1)group by b limit 1)group by b limit 1 -)group by b limit 1)group by b limit 1)group by b limit 1 -)group by b limit 1)group by b limit 1)group by b limit 1 -)group by b limit 1)group by b limit 1)group by b limit 1 -)group by b limit 1)group by b limit 1)group by b limit 1 -)group by b limit 1)group by b limit 1)group by b limit 1 -)group by b limit 1)group by b limit 1)group by b limit 1 -)group by b limit 1)group by b limit 1)group by b limit 1) -group by a; -ERROR HY000: Thread stack overrun detected -explain select sum(a),a from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 -)group by b limit 1)group by b limit 1 -)group by b limit 1)group by b limit 1)group by b limit 1 -)group by b limit 1)group by b limit 1)group by b limit 1 -)group by b limit 1)group by b limit 1)group by b limit 1) -group by a; -id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 index a a 5 NULL 9 Using where; Using index -2 SUBQUERY t1 range a a 5 NULL 9 Using where; Using temporary; Using filesort -3 SUBQUERY t1 range a a 5 NULL 9 Using where; Using temporary; Using filesort -4 SUBQUERY t1 range a a 5 NULL 9 Using where; Using temporary; Using filesort -5 SUBQUERY t1 range a a 5 NULL 9 Using where; Using temporary; Using filesort -6 SUBQUERY t1 range a a 5 NULL 9 Using where; Using temporary; Using filesort -7 SUBQUERY t1 range a a 5 NULL 9 Using where; Using temporary; Using filesort -8 SUBQUERY t1 range a a 5 NULL 9 Using where; Using temporary; Using filesort -9 SUBQUERY t1 range a a 5 NULL 9 Using where; Using temporary; Using filesort -10 SUBQUERY t1 range a a 5 NULL 9 Using where; Using temporary; Using filesort -11 SUBQUERY t1 range a a 5 NULL 9 Using where; Using temporary; Using filesort -12 SUBQUERY t1 range a a 5 NULL 1 Using where; Using temporary; Using filesort -13 SUBQUERY t1 index NULL a 5 NULL 9 Using index -explain select sum(a),a from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 -)group by b limit 1)group by b limit 1)group by b limit 1 -)group by b limit 1)group by b limit 1)group by b limit 1 -)group by b limit 1)group by b limit 1)group by b limit 1 -)group by b limit 1)group by b limit 1)group by b limit 1 -)group by b limit 1)group by b limit 1)group by b limit 1 -)group by b limit 1)group by b limit 1)group by b limit 1 -)group by b limit 1)group by b limit 1)group by b limit 1 -)group by b limit 1)group by b limit 1)group by b limit 1 -)group by b limit 1)group by b limit 1)group by b limit 1 -)group by b limit 1)group by b limit 1)group by b limit 1) -group by a; -ERROR HY000: Thread stack overrun detected +5 +4 +3 +2 +1 +26 +25 +24 +23 +22 +21 +20 +19 +18 +17 +16 +15 +14 +13 +12 +11 +10 +9 +8 +7 +6 +5 +4 +3 +2 +1 drop table t1; CREATE TABLE t1 (a1 INT, a2 INT); CREATE TABLE t2 (b1 INT, b2 INT); diff --git a/mysql-test/r/symlink.result b/mysql-test/r/symlink.result index 833adbeb851..689aa724935 100644 --- a/mysql-test/r/symlink.result +++ b/mysql-test/r/symlink.result @@ -100,23 +100,15 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; CREATE TABLE t1(a INT) -DATA DIRECTORY='TEST_DIR/master-data/mysql' -INDEX DIRECTORY='TEST_DIR/master-data/mysql'; -RENAME TABLE t1 TO user; -ERROR HY000: Can't create/write to file 'TEST_DIR/master-data/mysql/user.MYI' (Errcode: 17) -DROP TABLE t1; -show create table t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `i` int(11) default NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 -drop table t1; -show create table t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `i` int(11) default NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 -drop table t1; +DATA DIRECTORY='TEST_DIR/tmp' +INDEX DIRECTORY='TEST_DIR/tmp'; +ERROR HY000: Can't create/write to file 'TEST_DIR/tmp/t1.MYI' (Errcode: 17) +CREATE TABLE t2(a INT) +DATA DIRECTORY='TEST_DIR/tmp' +INDEX DIRECTORY='TEST_DIR/tmp'; +RENAME TABLE t2 TO t1; +ERROR HY000: Can't create/write to file 'TEST_DIR/tmp/t1.MYI' (Errcode: 17) +DROP TABLE t2; show create table t1; Table Create Table t1 CREATE TEMPORARY TABLE `t1` ( @@ -138,27 +130,38 @@ select * from t1; a 42 drop table t1; +execute stmt; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` char(10) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 DATA DIRECTORY='MYSQLTEST_VARDIR/tmp/' +drop table t1; +execute stmt; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` char(10) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 DATA DIRECTORY='MYSQLTEST_VARDIR/tmp/' +drop table t1; +deallocate prepare stmt; +CREATE TABLE t1(a INT) +DATA DIRECTORY='TEST_DIR/var/master-data/test'; +Got one of the listed errors +CREATE TABLE t1(a INT) +DATA DIRECTORY='TEST_DIR/var/master-data/'; +Got one of the listed errors +CREATE TABLE t1(a INT) +INDEX DIRECTORY='TEST_DIR/var/master-data'; +Got one of the listed errors +CREATE TABLE t1(a INT) +INDEX DIRECTORY='TEST_DIR/var/master-data_var'; +Got one of the listed errors End of 4.1 tests -CREATE DATABASE db1; -CREATE DATABASE db2; -USE db2; -INSERT INTO db2.t1 VALUES (1); -SELECT * FROM db2.t1; -b -1 -RESET QUERY CACHE; -USE db1; SET SESSION keep_files_on_create = TRUE; CREATE TABLE t1 (a INT) ENGINE MYISAM; -ERROR HY000: Can't create/write to file './db1/t1.MYD' (Errcode: 17) -CREATE TABLE t3 (a INT) Engine=MyISAM; -INSERT INTO t3 VALUES (1),(2),(3); -TRUNCATE TABLE t3; -SELECT * from t3; -a -SET SESSION keep_files_on_create = DEFAULT; -DROP TABLE db2.t1, db1.t3; -DROP DATABASE db1; -DROP DATABASE db2; -USE test; +ERROR HY000: Can't create/write to file './test/t1.MYD' (Errcode: 17) +SET SESSION keep_files_on_create = FALSE; +CREATE TABLE t1 (a INT) ENGINE MYISAM; +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/r/tablelock.result b/mysql-test/r/tablelock.result index 2ffd8f928a9..6923ad40916 100644 --- a/mysql-test/r/tablelock.result +++ b/mysql-test/r/tablelock.result @@ -46,3 +46,12 @@ CREATE TABLE t2 (a int); lock tables t1 write,t1 as b write, t2 write, t2 as c read; drop table t2,t1; unlock tables; +create temporary table t1(f1 int); +lock tables t1 write; +insert into t1 values (1); +show columns from t1; +Field Type Null Key Default Extra +f1 int(11) YES NULL +insert into t1 values(2); +drop table t1; +unlock tables; diff --git a/mysql-test/r/type_binary.result b/mysql-test/r/type_binary.result index debf4ff8fb8..aaa46ab415e 100644 --- a/mysql-test/r/type_binary.result +++ b/mysql-test/r/type_binary.result @@ -125,6 +125,7 @@ create table t1 (c char(2), vc varchar(2)); insert into t1 values(0x4120, 0x4120); insert into t1 values(0x412020, 0x412020); Warnings: +Note 1265 Data truncated for column 'c' at row 1 Note 1265 Data truncated for column 'vc' at row 1 drop table t1; set @old_sql_mode= @@sql_mode, sql_mode= 'traditional'; diff --git a/mysql-test/r/type_set.result b/mysql-test/r/type_set.result index 03de20baef2..9829d4951c9 100644 --- a/mysql-test/r/type_set.result +++ b/mysql-test/r/type_set.result @@ -85,3 +85,11 @@ t1 CREATE TABLE `t1` ( `f1` set('1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','23','24','25','26','27','28','29','30','31','32','33','34','35','36','37','38','39','40','41','42','43','44','45','46','47','48','49','50','51','52','53','54','55','56','57','58','59','60','61','62','63','64','1') default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; +CREATE TABLE t1(c set('1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','23','24','25','26','27','28','29','30','31','32','33','34','35','36','37','38','39','40','41','42','43','44','45','46','47','48','49','50','51','52','53','54','55','56','57','58','59','60','61','62','63','64')); +INSERT INTO t1 VALUES(7); +INSERT INTO t1 VALUES(9223372036854775808); +SELECT * FROM t1; +c +1,2,3 +64 +DROP TABLE t1; diff --git a/mysql-test/r/user_var-binlog.result b/mysql-test/r/user_var-binlog.result index 2b37a4b1d9a..b8df68b8f28 100644 --- a/mysql-test/r/user_var-binlog.result +++ b/mysql-test/r/user_var-binlog.result @@ -24,11 +24,13 @@ SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.uniq SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; -INSERT INTO t1 VALUES(@`a b`)/*!*/; +INSERT INTO t1 VALUES(@`a b`) +/*!*/; SET @`var1`:=_latin1 0x273B616161 COLLATE `latin1_swedish_ci`/*!*/; SET @`var2`:=_binary 0x61 COLLATE `binary`/*!*/; SET TIMESTAMP=10000/*!*/; -insert into t1 values (@var1),(@var2)/*!*/; +insert into t1 values (@var1),(@var2) +/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; diff --git a/mysql-test/r/variables-big.result b/mysql-test/r/variables-big.result index d7906869276..c441f27d82d 100644 --- a/mysql-test/r/variables-big.result +++ b/mysql-test/r/variables-big.result @@ -1,20 +1,24 @@ set session transaction_prealloc_size=1024*1024*1024*1; show processlist; Id User Host db Command Time State Info -1 root localhost test Query 0 NULL show processlist +6 root localhost test Query 0 NULL show processlist set session transaction_prealloc_size=1024*1024*1024*2; show processlist; Id User Host db Command Time State Info -1 root localhost test Query 2 NULL show processlist +6 root localhost test Query 1 NULL show processlist set session transaction_prealloc_size=1024*1024*1024*3; show processlist; Id User Host db Command Time State Info -1 root localhost test Query 0 NULL show processlist +6 root localhost test Query 0 NULL show processlist set session transaction_prealloc_size=1024*1024*1024*4; +Warnings: +Warning 1292 Truncated incorrect transaction_prealloc_size value: '4294967296' show processlist; Id User Host db Command Time State Info -1 root localhost test Query 0 NULL show processlist +6 root localhost test Query 0 NULL show processlist set session transaction_prealloc_size=1024*1024*1024*5; +Warnings: +Warning 1292 Truncated incorrect transaction_prealloc_size value: '5368709120' show processlist; Id User Host db Command Time State Info -1 root localhost test Query 0 NULL show processlist +6 root localhost test Query 0 NULL show processlist diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index 9c360ef4ab3..376a8ffa38e 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -182,7 +182,7 @@ show global variables like 'myisam_max_sort_file_size'; Variable_name Value myisam_max_sort_file_size 1048576 set GLOBAL myisam_max_sort_file_size=default; -show variables like 'myisam_max_sort_file_size'; +show global variables like 'myisam_max_sort_file_size'; Variable_name Value myisam_max_sort_file_size FILE_SIZE set global net_retry_count=10, session net_retry_count=10; diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index fb36304e562..520bf9426b8 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -3618,4 +3618,47 @@ ERROR HY000: Field of view 'test.v1' underlying table doesn't have a default val set @@sql_mode=@old_mode; drop view v1; drop table t1; -End of 5.0 tests. +create table t1 (a int, key(a)); +create table t2 (c int); +create view v1 as select a b from t1; +create view v2 as select 1 a from t2, v1 where c in +(select 1 from t1 where b = a); +insert into t1 values (1), (1); +insert into t2 values (1), (1); +prepare stmt from "select * from v2 where a = 1"; +execute stmt; +a +1 +1 +1 +1 +drop view v1, v2; +drop table t1, t2; +CREATE TABLE t1 (a INT); +CREATE VIEW v1 AS SELECT p.a AS a FROM t1 p, t1 q; +INSERT INTO t1 VALUES (1), (1); +SELECT MAX(a), COUNT(DISTINCT a) FROM v1 GROUP BY a; +MAX(a) COUNT(DISTINCT a) +1 1 +DROP VIEW v1; +DROP TABLE t1; +# ----------------------------------------------------------------- +# -- Bug#34337: Server crash when Altering a view using a table name. +# ----------------------------------------------------------------- + +DROP TABLE IF EXISTS t1; + +CREATE TABLE t1(c1 INT); + +SELECT * FROM t1; +c1 +ALTER ALGORITHM=TEMPTABLE SQL SECURITY INVOKER VIEW t1 (c2) AS SELECT (1); +ERROR HY000: 'test.t1' is not VIEW + +DROP TABLE t1; + +# -- End of test case for Bug#34337. + +# ----------------------------------------------------------------- +# -- End of 5.0 tests. +# ----------------------------------------------------------------- diff --git a/mysql-test/r/view_grant.result b/mysql-test/r/view_grant.result index eef61c65fb8..53ad8642ba4 100644 --- a/mysql-test/r/view_grant.result +++ b/mysql-test/r/view_grant.result @@ -467,6 +467,7 @@ use test; REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_1@localhost; drop database mysqltest; drop view if exists v1; +drop table if exists t1; create table t1 as select * from mysql.user where user=''; delete from mysql.user where user=''; flush privileges; diff --git a/mysql-test/r/warnings.result b/mysql-test/r/warnings.result index 9ce1f9c825d..e74f92205aa 100644 --- a/mysql-test/r/warnings.result +++ b/mysql-test/r/warnings.result @@ -298,4 +298,42 @@ DROP TABLE t3; DROP PROCEDURE sp1; DROP PROCEDURE sp2; DROP PROCEDURE sp3; +create table t1 (c_char char(255), c_varchar varchar(255), c_tinytext tinytext); +create table t2 (c_tinyblob tinyblob); +set @c = repeat(' ', 256); +set @q = repeat('q', 256); +set sql_mode = ''; +insert into t1 values(@c, @c, @c); +Warnings: +Note 1265 Data truncated for column 'c_char' at row 1 +Note 1265 Data truncated for column 'c_varchar' at row 1 +Note 1265 Data truncated for column 'c_tinytext' at row 1 +insert into t2 values(@c); +Warnings: +Warning 1265 Data truncated for column 'c_tinyblob' at row 1 +insert into t1 values(@q, @q, @q); +Warnings: +Warning 1265 Data truncated for column 'c_char' at row 1 +Warning 1265 Data truncated for column 'c_varchar' at row 1 +Warning 1265 Data truncated for column 'c_tinytext' at row 1 +insert into t2 values(@q); +Warnings: +Warning 1265 Data truncated for column 'c_tinyblob' at row 1 +set sql_mode = 'traditional'; +insert into t1 values(@c, @c, @c); +Warnings: +Note 1265 Data truncated for column 'c_char' at row 1 +Note 1265 Data truncated for column 'c_varchar' at row 1 +Note 1265 Data truncated for column 'c_tinytext' at row 1 +insert into t2 values(@c); +ERROR 22001: Data too long for column 'c_tinyblob' at row 1 +insert into t1 values(@q, NULL, NULL); +ERROR 22001: Data too long for column 'c_char' at row 1 +insert into t1 values(NULL, @q, NULL); +ERROR 22001: Data too long for column 'c_varchar' at row 1 +insert into t1 values(NULL, NULL, @q); +ERROR 22001: Data too long for column 'c_tinytext' at row 1 +insert into t2 values(@q); +ERROR 22001: Data too long for column 'c_tinyblob' at row 1 +drop table t1, t2; End of 5.0 tests diff --git a/mysql-test/std_data/bug30435_10k_items.txt b/mysql-test/std_data/bug30435_10k_items.txt new file mode 100644 index 00000000000..9812045fd89 --- /dev/null +++ b/mysql-test/std_data/bug30435_10k_items.txt @@ -0,0 +1,10000 @@ +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448 +449 +450 +451 +452 +453 +454 +455 +456 +457 +458 +459 +460 +461 +462 +463 +464 +465 +466 +467 +468 +469 +470 +471 +472 +473 +474 +475 +476 +477 +478 +479 +480 +481 +482 +483 +484 +485 +486 +487 +488 +489 +490 +491 +492 +493 +494 +495 +496 +497 +498 +499 +500 +501 +502 +503 +504 +505 +506 +507 +508 +509 +510 +511 +512 +513 +514 +515 +516 +517 +518 +519 +520 +521 +522 +523 +524 +525 +526 +527 +528 +529 +530 +531 +532 +533 +534 +535 +536 +537 +538 +539 +540 +541 +542 +543 +544 +545 +546 +547 +548 +549 +550 +551 +552 +553 +554 +555 +556 +557 +558 +559 +560 +561 +562 +563 +564 +565 +566 +567 +568 +569 +570 +571 +572 +573 +574 +575 +576 +577 +578 +579 +580 +581 +582 +583 +584 +585 +586 +587 +588 +589 +590 +591 +592 +593 +594 +595 +596 +597 +598 +599 +600 +601 +602 +603 +604 +605 +606 +607 +608 +609 +610 +611 +612 +613 +614 +615 +616 +617 +618 +619 +620 +621 +622 +623 +624 +625 +626 +627 +628 +629 +630 +631 +632 +633 +634 +635 +636 +637 +638 +639 +640 +641 +642 +643 +644 +645 +646 +647 +648 +649 +650 +651 +652 +653 +654 +655 +656 +657 +658 +659 +660 +661 +662 +663 +664 +665 +666 +667 +668 +669 +670 +671 +672 +673 +674 +675 +676 +677 +678 +679 +680 +681 +682 +683 +684 +685 +686 +687 +688 +689 +690 +691 +692 +693 +694 +695 +696 +697 +698 +699 +700 +701 +702 +703 +704 +705 +706 +707 +708 +709 +710 +711 +712 +713 +714 +715 +716 +717 +718 +719 +720 +721 +722 +723 +724 +725 +726 +727 +728 +729 +730 +731 +732 +733 +734 +735 +736 +737 +738 +739 +740 +741 +742 +743 +744 +745 +746 +747 +748 +749 +750 +751 +752 +753 +754 +755 +756 +757 +758 +759 +760 +761 +762 +763 +764 +765 +766 +767 +768 +769 +770 +771 +772 +773 +774 +775 +776 +777 +778 +779 +780 +781 +782 +783 +784 +785 +786 +787 +788 +789 +790 +791 +792 +793 +794 +795 +796 +797 +798 +799 +800 +801 +802 +803 +804 +805 +806 +807 +808 +809 +810 +811 +812 +813 +814 +815 +816 +817 +818 +819 +820 +821 +822 +823 +824 +825 +826 +827 +828 +829 +830 +831 +832 +833 +834 +835 +836 +837 +838 +839 +840 +841 +842 +843 +844 +845 +846 +847 +848 +849 +850 +851 +852 +853 +854 +855 +856 +857 +858 +859 +860 +861 +862 +863 +864 +865 +866 +867 +868 +869 +870 +871 +872 +873 +874 +875 +876 +877 +878 +879 +880 +881 +882 +883 +884 +885 +886 +887 +888 +889 +890 +891 +892 +893 +894 +895 +896 +897 +898 +899 +900 +901 +902 +903 +904 +905 +906 +907 +908 +909 +910 +911 +912 +913 +914 +915 +916 +917 +918 +919 +920 +921 +922 +923 +924 +925 +926 +927 +928 +929 +930 +931 +932 +933 +934 +935 +936 +937 +938 +939 +940 +941 +942 +943 +944 +945 +946 +947 +948 +949 +950 +951 +952 +953 +954 +955 +956 +957 +958 +959 +960 +961 +962 +963 +964 +965 +966 +967 +968 +969 +970 +971 +972 +973 +974 +975 +976 +977 +978 +979 +980 +981 +982 +983 +984 +985 +986 +987 +988 +989 +990 +991 +992 +993 +994 +995 +996 +997 +998 +999 +1000 +1001 +1002 +1003 +1004 +1005 +1006 +1007 +1008 +1009 +1010 +1011 +1012 +1013 +1014 +1015 +1016 +1017 +1018 +1019 +1020 +1021 +1022 +1023 +1024 +1025 +1026 +1027 +1028 +1029 +1030 +1031 +1032 +1033 +1034 +1035 +1036 +1037 +1038 +1039 +1040 +1041 +1042 +1043 +1044 +1045 +1046 +1047 +1048 +1049 +1050 +1051 +1052 +1053 +1054 +1055 +1056 +1057 +1058 +1059 +1060 +1061 +1062 +1063 +1064 +1065 +1066 +1067 +1068 +1069 +1070 +1071 +1072 +1073 +1074 +1075 +1076 +1077 +1078 +1079 +1080 +1081 +1082 +1083 +1084 +1085 +1086 +1087 +1088 +1089 +1090 +1091 +1092 +1093 +1094 +1095 +1096 +1097 +1098 +1099 +1100 +1101 +1102 +1103 +1104 +1105 +1106 +1107 +1108 +1109 +1110 +1111 +1112 +1113 +1114 +1115 +1116 +1117 +1118 +1119 +1120 +1121 +1122 +1123 +1124 +1125 +1126 +1127 +1128 +1129 +1130 +1131 +1132 +1133 +1134 +1135 +1136 +1137 +1138 +1139 +1140 +1141 +1142 +1143 +1144 +1145 +1146 +1147 +1148 +1149 +1150 +1151 +1152 +1153 +1154 +1155 +1156 +1157 +1158 +1159 +1160 +1161 +1162 +1163 +1164 +1165 +1166 +1167 +1168 +1169 +1170 +1171 +1172 +1173 +1174 +1175 +1176 +1177 +1178 +1179 +1180 +1181 +1182 +1183 +1184 +1185 +1186 +1187 +1188 +1189 +1190 +1191 +1192 +1193 +1194 +1195 +1196 +1197 +1198 +1199 +1200 +1201 +1202 +1203 +1204 +1205 +1206 +1207 +1208 +1209 +1210 +1211 +1212 +1213 +1214 +1215 +1216 +1217 +1218 +1219 +1220 +1221 +1222 +1223 +1224 +1225 +1226 +1227 +1228 +1229 +1230 +1231 +1232 +1233 +1234 +1235 +1236 +1237 +1238 +1239 +1240 +1241 +1242 +1243 +1244 +1245 +1246 +1247 +1248 +1249 +1250 +1251 +1252 +1253 +1254 +1255 +1256 +1257 +1258 +1259 +1260 +1261 +1262 +1263 +1264 +1265 +1266 +1267 +1268 +1269 +1270 +1271 +1272 +1273 +1274 +1275 +1276 +1277 +1278 +1279 +1280 +1281 +1282 +1283 +1284 +1285 +1286 +1287 +1288 +1289 +1290 +1291 +1292 +1293 +1294 +1295 +1296 +1297 +1298 +1299 +1300 +1301 +1302 +1303 +1304 +1305 +1306 +1307 +1308 +1309 +1310 +1311 +1312 +1313 +1314 +1315 +1316 +1317 +1318 +1319 +1320 +1321 +1322 +1323 +1324 +1325 +1326 +1327 +1328 +1329 +1330 +1331 +1332 +1333 +1334 +1335 +1336 +1337 +1338 +1339 +1340 +1341 +1342 +1343 +1344 +1345 +1346 +1347 +1348 +1349 +1350 +1351 +1352 +1353 +1354 +1355 +1356 +1357 +1358 +1359 +1360 +1361 +1362 +1363 +1364 +1365 +1366 +1367 +1368 +1369 +1370 +1371 +1372 +1373 +1374 +1375 +1376 +1377 +1378 +1379 +1380 +1381 +1382 +1383 +1384 +1385 +1386 +1387 +1388 +1389 +1390 +1391 +1392 +1393 +1394 +1395 +1396 +1397 +1398 +1399 +1400 +1401 +1402 +1403 +1404 +1405 +1406 +1407 +1408 +1409 +1410 +1411 +1412 +1413 +1414 +1415 +1416 +1417 +1418 +1419 +1420 +1421 +1422 +1423 +1424 +1425 +1426 +1427 +1428 +1429 +1430 +1431 +1432 +1433 +1434 +1435 +1436 +1437 +1438 +1439 +1440 +1441 +1442 +1443 +1444 +1445 +1446 +1447 +1448 +1449 +1450 +1451 +1452 +1453 +1454 +1455 +1456 +1457 +1458 +1459 +1460 +1461 +1462 +1463 +1464 +1465 +1466 +1467 +1468 +1469 +1470 +1471 +1472 +1473 +1474 +1475 +1476 +1477 +1478 +1479 +1480 +1481 +1482 +1483 +1484 +1485 +1486 +1487 +1488 +1489 +1490 +1491 +1492 +1493 +1494 +1495 +1496 +1497 +1498 +1499 +1500 +1501 +1502 +1503 +1504 +1505 +1506 +1507 +1508 +1509 +1510 +1511 +1512 +1513 +1514 +1515 +1516 +1517 +1518 +1519 +1520 +1521 +1522 +1523 +1524 +1525 +1526 +1527 +1528 +1529 +1530 +1531 +1532 +1533 +1534 +1535 +1536 +1537 +1538 +1539 +1540 +1541 +1542 +1543 +1544 +1545 +1546 +1547 +1548 +1549 +1550 +1551 +1552 +1553 +1554 +1555 +1556 +1557 +1558 +1559 +1560 +1561 +1562 +1563 +1564 +1565 +1566 +1567 +1568 +1569 +1570 +1571 +1572 +1573 +1574 +1575 +1576 +1577 +1578 +1579 +1580 +1581 +1582 +1583 +1584 +1585 +1586 +1587 +1588 +1589 +1590 +1591 +1592 +1593 +1594 +1595 +1596 +1597 +1598 +1599 +1600 +1601 +1602 +1603 +1604 +1605 +1606 +1607 +1608 +1609 +1610 +1611 +1612 +1613 +1614 +1615 +1616 +1617 +1618 +1619 +1620 +1621 +1622 +1623 +1624 +1625 +1626 +1627 +1628 +1629 +1630 +1631 +1632 +1633 +1634 +1635 +1636 +1637 +1638 +1639 +1640 +1641 +1642 +1643 +1644 +1645 +1646 +1647 +1648 +1649 +1650 +1651 +1652 +1653 +1654 +1655 +1656 +1657 +1658 +1659 +1660 +1661 +1662 +1663 +1664 +1665 +1666 +1667 +1668 +1669 +1670 +1671 +1672 +1673 +1674 +1675 +1676 +1677 +1678 +1679 +1680 +1681 +1682 +1683 +1684 +1685 +1686 +1687 +1688 +1689 +1690 +1691 +1692 +1693 +1694 +1695 +1696 +1697 +1698 +1699 +1700 +1701 +1702 +1703 +1704 +1705 +1706 +1707 +1708 +1709 +1710 +1711 +1712 +1713 +1714 +1715 +1716 +1717 +1718 +1719 +1720 +1721 +1722 +1723 +1724 +1725 +1726 +1727 +1728 +1729 +1730 +1731 +1732 +1733 +1734 +1735 +1736 +1737 +1738 +1739 +1740 +1741 +1742 +1743 +1744 +1745 +1746 +1747 +1748 +1749 +1750 +1751 +1752 +1753 +1754 +1755 +1756 +1757 +1758 +1759 +1760 +1761 +1762 +1763 +1764 +1765 +1766 +1767 +1768 +1769 +1770 +1771 +1772 +1773 +1774 +1775 +1776 +1777 +1778 +1779 +1780 +1781 +1782 +1783 +1784 +1785 +1786 +1787 +1788 +1789 +1790 +1791 +1792 +1793 +1794 +1795 +1796 +1797 +1798 +1799 +1800 +1801 +1802 +1803 +1804 +1805 +1806 +1807 +1808 +1809 +1810 +1811 +1812 +1813 +1814 +1815 +1816 +1817 +1818 +1819 +1820 +1821 +1822 +1823 +1824 +1825 +1826 +1827 +1828 +1829 +1830 +1831 +1832 +1833 +1834 +1835 +1836 +1837 +1838 +1839 +1840 +1841 +1842 +1843 +1844 +1845 +1846 +1847 +1848 +1849 +1850 +1851 +1852 +1853 +1854 +1855 +1856 +1857 +1858 +1859 +1860 +1861 +1862 +1863 +1864 +1865 +1866 +1867 +1868 +1869 +1870 +1871 +1872 +1873 +1874 +1875 +1876 +1877 +1878 +1879 +1880 +1881 +1882 +1883 +1884 +1885 +1886 +1887 +1888 +1889 +1890 +1891 +1892 +1893 +1894 +1895 +1896 +1897 +1898 +1899 +1900 +1901 +1902 +1903 +1904 +1905 +1906 +1907 +1908 +1909 +1910 +1911 +1912 +1913 +1914 +1915 +1916 +1917 +1918 +1919 +1920 +1921 +1922 +1923 +1924 +1925 +1926 +1927 +1928 +1929 +1930 +1931 +1932 +1933 +1934 +1935 +1936 +1937 +1938 +1939 +1940 +1941 +1942 +1943 +1944 +1945 +1946 +1947 +1948 +1949 +1950 +1951 +1952 +1953 +1954 +1955 +1956 +1957 +1958 +1959 +1960 +1961 +1962 +1963 +1964 +1965 +1966 +1967 +1968 +1969 +1970 +1971 +1972 +1973 +1974 +1975 +1976 +1977 +1978 +1979 +1980 +1981 +1982 +1983 +1984 +1985 +1986 +1987 +1988 +1989 +1990 +1991 +1992 +1993 +1994 +1995 +1996 +1997 +1998 +1999 +2000 +2001 +2002 +2003 +2004 +2005 +2006 +2007 +2008 +2009 +2010 +2011 +2012 +2013 +2014 +2015 +2016 +2017 +2018 +2019 +2020 +2021 +2022 +2023 +2024 +2025 +2026 +2027 +2028 +2029 +2030 +2031 +2032 +2033 +2034 +2035 +2036 +2037 +2038 +2039 +2040 +2041 +2042 +2043 +2044 +2045 +2046 +2047 +2048 +2049 +2050 +2051 +2052 +2053 +2054 +2055 +2056 +2057 +2058 +2059 +2060 +2061 +2062 +2063 +2064 +2065 +2066 +2067 +2068 +2069 +2070 +2071 +2072 +2073 +2074 +2075 +2076 +2077 +2078 +2079 +2080 +2081 +2082 +2083 +2084 +2085 +2086 +2087 +2088 +2089 +2090 +2091 +2092 +2093 +2094 +2095 +2096 +2097 +2098 +2099 +2100 +2101 +2102 +2103 +2104 +2105 +2106 +2107 +2108 +2109 +2110 +2111 +2112 +2113 +2114 +2115 +2116 +2117 +2118 +2119 +2120 +2121 +2122 +2123 +2124 +2125 +2126 +2127 +2128 +2129 +2130 +2131 +2132 +2133 +2134 +2135 +2136 +2137 +2138 +2139 +2140 +2141 +2142 +2143 +2144 +2145 +2146 +2147 +2148 +2149 +2150 +2151 +2152 +2153 +2154 +2155 +2156 +2157 +2158 +2159 +2160 +2161 +2162 +2163 +2164 +2165 +2166 +2167 +2168 +2169 +2170 +2171 +2172 +2173 +2174 +2175 +2176 +2177 +2178 +2179 +2180 +2181 +2182 +2183 +2184 +2185 +2186 +2187 +2188 +2189 +2190 +2191 +2192 +2193 +2194 +2195 +2196 +2197 +2198 +2199 +2200 +2201 +2202 +2203 +2204 +2205 +2206 +2207 +2208 +2209 +2210 +2211 +2212 +2213 +2214 +2215 +2216 +2217 +2218 +2219 +2220 +2221 +2222 +2223 +2224 +2225 +2226 +2227 +2228 +2229 +2230 +2231 +2232 +2233 +2234 +2235 +2236 +2237 +2238 +2239 +2240 +2241 +2242 +2243 +2244 +2245 +2246 +2247 +2248 +2249 +2250 +2251 +2252 +2253 +2254 +2255 +2256 +2257 +2258 +2259 +2260 +2261 +2262 +2263 +2264 +2265 +2266 +2267 +2268 +2269 +2270 +2271 +2272 +2273 +2274 +2275 +2276 +2277 +2278 +2279 +2280 +2281 +2282 +2283 +2284 +2285 +2286 +2287 +2288 +2289 +2290 +2291 +2292 +2293 +2294 +2295 +2296 +2297 +2298 +2299 +2300 +2301 +2302 +2303 +2304 +2305 +2306 +2307 +2308 +2309 +2310 +2311 +2312 +2313 +2314 +2315 +2316 +2317 +2318 +2319 +2320 +2321 +2322 +2323 +2324 +2325 +2326 +2327 +2328 +2329 +2330 +2331 +2332 +2333 +2334 +2335 +2336 +2337 +2338 +2339 +2340 +2341 +2342 +2343 +2344 +2345 +2346 +2347 +2348 +2349 +2350 +2351 +2352 +2353 +2354 +2355 +2356 +2357 +2358 +2359 +2360 +2361 +2362 +2363 +2364 +2365 +2366 +2367 +2368 +2369 +2370 +2371 +2372 +2373 +2374 +2375 +2376 +2377 +2378 +2379 +2380 +2381 +2382 +2383 +2384 +2385 +2386 +2387 +2388 +2389 +2390 +2391 +2392 +2393 +2394 +2395 +2396 +2397 +2398 +2399 +2400 +2401 +2402 +2403 +2404 +2405 +2406 +2407 +2408 +2409 +2410 +2411 +2412 +2413 +2414 +2415 +2416 +2417 +2418 +2419 +2420 +2421 +2422 +2423 +2424 +2425 +2426 +2427 +2428 +2429 +2430 +2431 +2432 +2433 +2434 +2435 +2436 +2437 +2438 +2439 +2440 +2441 +2442 +2443 +2444 +2445 +2446 +2447 +2448 +2449 +2450 +2451 +2452 +2453 +2454 +2455 +2456 +2457 +2458 +2459 +2460 +2461 +2462 +2463 +2464 +2465 +2466 +2467 +2468 +2469 +2470 +2471 +2472 +2473 +2474 +2475 +2476 +2477 +2478 +2479 +2480 +2481 +2482 +2483 +2484 +2485 +2486 +2487 +2488 +2489 +2490 +2491 +2492 +2493 +2494 +2495 +2496 +2497 +2498 +2499 +2500 +2501 +2502 +2503 +2504 +2505 +2506 +2507 +2508 +2509 +2510 +2511 +2512 +2513 +2514 +2515 +2516 +2517 +2518 +2519 +2520 +2521 +2522 +2523 +2524 +2525 +2526 +2527 +2528 +2529 +2530 +2531 +2532 +2533 +2534 +2535 +2536 +2537 +2538 +2539 +2540 +2541 +2542 +2543 +2544 +2545 +2546 +2547 +2548 +2549 +2550 +2551 +2552 +2553 +2554 +2555 +2556 +2557 +2558 +2559 +2560 +2561 +2562 +2563 +2564 +2565 +2566 +2567 +2568 +2569 +2570 +2571 +2572 +2573 +2574 +2575 +2576 +2577 +2578 +2579 +2580 +2581 +2582 +2583 +2584 +2585 +2586 +2587 +2588 +2589 +2590 +2591 +2592 +2593 +2594 +2595 +2596 +2597 +2598 +2599 +2600 +2601 +2602 +2603 +2604 +2605 +2606 +2607 +2608 +2609 +2610 +2611 +2612 +2613 +2614 +2615 +2616 +2617 +2618 +2619 +2620 +2621 +2622 +2623 +2624 +2625 +2626 +2627 +2628 +2629 +2630 +2631 +2632 +2633 +2634 +2635 +2636 +2637 +2638 +2639 +2640 +2641 +2642 +2643 +2644 +2645 +2646 +2647 +2648 +2649 +2650 +2651 +2652 +2653 +2654 +2655 +2656 +2657 +2658 +2659 +2660 +2661 +2662 +2663 +2664 +2665 +2666 +2667 +2668 +2669 +2670 +2671 +2672 +2673 +2674 +2675 +2676 +2677 +2678 +2679 +2680 +2681 +2682 +2683 +2684 +2685 +2686 +2687 +2688 +2689 +2690 +2691 +2692 +2693 +2694 +2695 +2696 +2697 +2698 +2699 +2700 +2701 +2702 +2703 +2704 +2705 +2706 +2707 +2708 +2709 +2710 +2711 +2712 +2713 +2714 +2715 +2716 +2717 +2718 +2719 +2720 +2721 +2722 +2723 +2724 +2725 +2726 +2727 +2728 +2729 +2730 +2731 +2732 +2733 +2734 +2735 +2736 +2737 +2738 +2739 +2740 +2741 +2742 +2743 +2744 +2745 +2746 +2747 +2748 +2749 +2750 +2751 +2752 +2753 +2754 +2755 +2756 +2757 +2758 +2759 +2760 +2761 +2762 +2763 +2764 +2765 +2766 +2767 +2768 +2769 +2770 +2771 +2772 +2773 +2774 +2775 +2776 +2777 +2778 +2779 +2780 +2781 +2782 +2783 +2784 +2785 +2786 +2787 +2788 +2789 +2790 +2791 +2792 +2793 +2794 +2795 +2796 +2797 +2798 +2799 +2800 +2801 +2802 +2803 +2804 +2805 +2806 +2807 +2808 +2809 +2810 +2811 +2812 +2813 +2814 +2815 +2816 +2817 +2818 +2819 +2820 +2821 +2822 +2823 +2824 +2825 +2826 +2827 +2828 +2829 +2830 +2831 +2832 +2833 +2834 +2835 +2836 +2837 +2838 +2839 +2840 +2841 +2842 +2843 +2844 +2845 +2846 +2847 +2848 +2849 +2850 +2851 +2852 +2853 +2854 +2855 +2856 +2857 +2858 +2859 +2860 +2861 +2862 +2863 +2864 +2865 +2866 +2867 +2868 +2869 +2870 +2871 +2872 +2873 +2874 +2875 +2876 +2877 +2878 +2879 +2880 +2881 +2882 +2883 +2884 +2885 +2886 +2887 +2888 +2889 +2890 +2891 +2892 +2893 +2894 +2895 +2896 +2897 +2898 +2899 +2900 +2901 +2902 +2903 +2904 +2905 +2906 +2907 +2908 +2909 +2910 +2911 +2912 +2913 +2914 +2915 +2916 +2917 +2918 +2919 +2920 +2921 +2922 +2923 +2924 +2925 +2926 +2927 +2928 +2929 +2930 +2931 +2932 +2933 +2934 +2935 +2936 +2937 +2938 +2939 +2940 +2941 +2942 +2943 +2944 +2945 +2946 +2947 +2948 +2949 +2950 +2951 +2952 +2953 +2954 +2955 +2956 +2957 +2958 +2959 +2960 +2961 +2962 +2963 +2964 +2965 +2966 +2967 +2968 +2969 +2970 +2971 +2972 +2973 +2974 +2975 +2976 +2977 +2978 +2979 +2980 +2981 +2982 +2983 +2984 +2985 +2986 +2987 +2988 +2989 +2990 +2991 +2992 +2993 +2994 +2995 +2996 +2997 +2998 +2999 +3000 +3001 +3002 +3003 +3004 +3005 +3006 +3007 +3008 +3009 +3010 +3011 +3012 +3013 +3014 +3015 +3016 +3017 +3018 +3019 +3020 +3021 +3022 +3023 +3024 +3025 +3026 +3027 +3028 +3029 +3030 +3031 +3032 +3033 +3034 +3035 +3036 +3037 +3038 +3039 +3040 +3041 +3042 +3043 +3044 +3045 +3046 +3047 +3048 +3049 +3050 +3051 +3052 +3053 +3054 +3055 +3056 +3057 +3058 +3059 +3060 +3061 +3062 +3063 +3064 +3065 +3066 +3067 +3068 +3069 +3070 +3071 +3072 +3073 +3074 +3075 +3076 +3077 +3078 +3079 +3080 +3081 +3082 +3083 +3084 +3085 +3086 +3087 +3088 +3089 +3090 +3091 +3092 +3093 +3094 +3095 +3096 +3097 +3098 +3099 +3100 +3101 +3102 +3103 +3104 +3105 +3106 +3107 +3108 +3109 +3110 +3111 +3112 +3113 +3114 +3115 +3116 +3117 +3118 +3119 +3120 +3121 +3122 +3123 +3124 +3125 +3126 +3127 +3128 +3129 +3130 +3131 +3132 +3133 +3134 +3135 +3136 +3137 +3138 +3139 +3140 +3141 +3142 +3143 +3144 +3145 +3146 +3147 +3148 +3149 +3150 +3151 +3152 +3153 +3154 +3155 +3156 +3157 +3158 +3159 +3160 +3161 +3162 +3163 +3164 +3165 +3166 +3167 +3168 +3169 +3170 +3171 +3172 +3173 +3174 +3175 +3176 +3177 +3178 +3179 +3180 +3181 +3182 +3183 +3184 +3185 +3186 +3187 +3188 +3189 +3190 +3191 +3192 +3193 +3194 +3195 +3196 +3197 +3198 +3199 +3200 +3201 +3202 +3203 +3204 +3205 +3206 +3207 +3208 +3209 +3210 +3211 +3212 +3213 +3214 +3215 +3216 +3217 +3218 +3219 +3220 +3221 +3222 +3223 +3224 +3225 +3226 +3227 +3228 +3229 +3230 +3231 +3232 +3233 +3234 +3235 +3236 +3237 +3238 +3239 +3240 +3241 +3242 +3243 +3244 +3245 +3246 +3247 +3248 +3249 +3250 +3251 +3252 +3253 +3254 +3255 +3256 +3257 +3258 +3259 +3260 +3261 +3262 +3263 +3264 +3265 +3266 +3267 +3268 +3269 +3270 +3271 +3272 +3273 +3274 +3275 +3276 +3277 +3278 +3279 +3280 +3281 +3282 +3283 +3284 +3285 +3286 +3287 +3288 +3289 +3290 +3291 +3292 +3293 +3294 +3295 +3296 +3297 +3298 +3299 +3300 +3301 +3302 +3303 +3304 +3305 +3306 +3307 +3308 +3309 +3310 +3311 +3312 +3313 +3314 +3315 +3316 +3317 +3318 +3319 +3320 +3321 +3322 +3323 +3324 +3325 +3326 +3327 +3328 +3329 +3330 +3331 +3332 +3333 +3334 +3335 +3336 +3337 +3338 +3339 +3340 +3341 +3342 +3343 +3344 +3345 +3346 +3347 +3348 +3349 +3350 +3351 +3352 +3353 +3354 +3355 +3356 +3357 +3358 +3359 +3360 +3361 +3362 +3363 +3364 +3365 +3366 +3367 +3368 +3369 +3370 +3371 +3372 +3373 +3374 +3375 +3376 +3377 +3378 +3379 +3380 +3381 +3382 +3383 +3384 +3385 +3386 +3387 +3388 +3389 +3390 +3391 +3392 +3393 +3394 +3395 +3396 +3397 +3398 +3399 +3400 +3401 +3402 +3403 +3404 +3405 +3406 +3407 +3408 +3409 +3410 +3411 +3412 +3413 +3414 +3415 +3416 +3417 +3418 +3419 +3420 +3421 +3422 +3423 +3424 +3425 +3426 +3427 +3428 +3429 +3430 +3431 +3432 +3433 +3434 +3435 +3436 +3437 +3438 +3439 +3440 +3441 +3442 +3443 +3444 +3445 +3446 +3447 +3448 +3449 +3450 +3451 +3452 +3453 +3454 +3455 +3456 +3457 +3458 +3459 +3460 +3461 +3462 +3463 +3464 +3465 +3466 +3467 +3468 +3469 +3470 +3471 +3472 +3473 +3474 +3475 +3476 +3477 +3478 +3479 +3480 +3481 +3482 +3483 +3484 +3485 +3486 +3487 +3488 +3489 +3490 +3491 +3492 +3493 +3494 +3495 +3496 +3497 +3498 +3499 +3500 +3501 +3502 +3503 +3504 +3505 +3506 +3507 +3508 +3509 +3510 +3511 +3512 +3513 +3514 +3515 +3516 +3517 +3518 +3519 +3520 +3521 +3522 +3523 +3524 +3525 +3526 +3527 +3528 +3529 +3530 +3531 +3532 +3533 +3534 +3535 +3536 +3537 +3538 +3539 +3540 +3541 +3542 +3543 +3544 +3545 +3546 +3547 +3548 +3549 +3550 +3551 +3552 +3553 +3554 +3555 +3556 +3557 +3558 +3559 +3560 +3561 +3562 +3563 +3564 +3565 +3566 +3567 +3568 +3569 +3570 +3571 +3572 +3573 +3574 +3575 +3576 +3577 +3578 +3579 +3580 +3581 +3582 +3583 +3584 +3585 +3586 +3587 +3588 +3589 +3590 +3591 +3592 +3593 +3594 +3595 +3596 +3597 +3598 +3599 +3600 +3601 +3602 +3603 +3604 +3605 +3606 +3607 +3608 +3609 +3610 +3611 +3612 +3613 +3614 +3615 +3616 +3617 +3618 +3619 +3620 +3621 +3622 +3623 +3624 +3625 +3626 +3627 +3628 +3629 +3630 +3631 +3632 +3633 +3634 +3635 +3636 +3637 +3638 +3639 +3640 +3641 +3642 +3643 +3644 +3645 +3646 +3647 +3648 +3649 +3650 +3651 +3652 +3653 +3654 +3655 +3656 +3657 +3658 +3659 +3660 +3661 +3662 +3663 +3664 +3665 +3666 +3667 +3668 +3669 +3670 +3671 +3672 +3673 +3674 +3675 +3676 +3677 +3678 +3679 +3680 +3681 +3682 +3683 +3684 +3685 +3686 +3687 +3688 +3689 +3690 +3691 +3692 +3693 +3694 +3695 +3696 +3697 +3698 +3699 +3700 +3701 +3702 +3703 +3704 +3705 +3706 +3707 +3708 +3709 +3710 +3711 +3712 +3713 +3714 +3715 +3716 +3717 +3718 +3719 +3720 +3721 +3722 +3723 +3724 +3725 +3726 +3727 +3728 +3729 +3730 +3731 +3732 +3733 +3734 +3735 +3736 +3737 +3738 +3739 +3740 +3741 +3742 +3743 +3744 +3745 +3746 +3747 +3748 +3749 +3750 +3751 +3752 +3753 +3754 +3755 +3756 +3757 +3758 +3759 +3760 +3761 +3762 +3763 +3764 +3765 +3766 +3767 +3768 +3769 +3770 +3771 +3772 +3773 +3774 +3775 +3776 +3777 +3778 +3779 +3780 +3781 +3782 +3783 +3784 +3785 +3786 +3787 +3788 +3789 +3790 +3791 +3792 +3793 +3794 +3795 +3796 +3797 +3798 +3799 +3800 +3801 +3802 +3803 +3804 +3805 +3806 +3807 +3808 +3809 +3810 +3811 +3812 +3813 +3814 +3815 +3816 +3817 +3818 +3819 +3820 +3821 +3822 +3823 +3824 +3825 +3826 +3827 +3828 +3829 +3830 +3831 +3832 +3833 +3834 +3835 +3836 +3837 +3838 +3839 +3840 +3841 +3842 +3843 +3844 +3845 +3846 +3847 +3848 +3849 +3850 +3851 +3852 +3853 +3854 +3855 +3856 +3857 +3858 +3859 +3860 +3861 +3862 +3863 +3864 +3865 +3866 +3867 +3868 +3869 +3870 +3871 +3872 +3873 +3874 +3875 +3876 +3877 +3878 +3879 +3880 +3881 +3882 +3883 +3884 +3885 +3886 +3887 +3888 +3889 +3890 +3891 +3892 +3893 +3894 +3895 +3896 +3897 +3898 +3899 +3900 +3901 +3902 +3903 +3904 +3905 +3906 +3907 +3908 +3909 +3910 +3911 +3912 +3913 +3914 +3915 +3916 +3917 +3918 +3919 +3920 +3921 +3922 +3923 +3924 +3925 +3926 +3927 +3928 +3929 +3930 +3931 +3932 +3933 +3934 +3935 +3936 +3937 +3938 +3939 +3940 +3941 +3942 +3943 +3944 +3945 +3946 +3947 +3948 +3949 +3950 +3951 +3952 +3953 +3954 +3955 +3956 +3957 +3958 +3959 +3960 +3961 +3962 +3963 +3964 +3965 +3966 +3967 +3968 +3969 +3970 +3971 +3972 +3973 +3974 +3975 +3976 +3977 +3978 +3979 +3980 +3981 +3982 +3983 +3984 +3985 +3986 +3987 +3988 +3989 +3990 +3991 +3992 +3993 +3994 +3995 +3996 +3997 +3998 +3999 +4000 +4001 +4002 +4003 +4004 +4005 +4006 +4007 +4008 +4009 +4010 +4011 +4012 +4013 +4014 +4015 +4016 +4017 +4018 +4019 +4020 +4021 +4022 +4023 +4024 +4025 +4026 +4027 +4028 +4029 +4030 +4031 +4032 +4033 +4034 +4035 +4036 +4037 +4038 +4039 +4040 +4041 +4042 +4043 +4044 +4045 +4046 +4047 +4048 +4049 +4050 +4051 +4052 +4053 +4054 +4055 +4056 +4057 +4058 +4059 +4060 +4061 +4062 +4063 +4064 +4065 +4066 +4067 +4068 +4069 +4070 +4071 +4072 +4073 +4074 +4075 +4076 +4077 +4078 +4079 +4080 +4081 +4082 +4083 +4084 +4085 +4086 +4087 +4088 +4089 +4090 +4091 +4092 +4093 +4094 +4095 +4096 +4097 +4098 +4099 +4100 +4101 +4102 +4103 +4104 +4105 +4106 +4107 +4108 +4109 +4110 +4111 +4112 +4113 +4114 +4115 +4116 +4117 +4118 +4119 +4120 +4121 +4122 +4123 +4124 +4125 +4126 +4127 +4128 +4129 +4130 +4131 +4132 +4133 +4134 +4135 +4136 +4137 +4138 +4139 +4140 +4141 +4142 +4143 +4144 +4145 +4146 +4147 +4148 +4149 +4150 +4151 +4152 +4153 +4154 +4155 +4156 +4157 +4158 +4159 +4160 +4161 +4162 +4163 +4164 +4165 +4166 +4167 +4168 +4169 +4170 +4171 +4172 +4173 +4174 +4175 +4176 +4177 +4178 +4179 +4180 +4181 +4182 +4183 +4184 +4185 +4186 +4187 +4188 +4189 +4190 +4191 +4192 +4193 +4194 +4195 +4196 +4197 +4198 +4199 +4200 +4201 +4202 +4203 +4204 +4205 +4206 +4207 +4208 +4209 +4210 +4211 +4212 +4213 +4214 +4215 +4216 +4217 +4218 +4219 +4220 +4221 +4222 +4223 +4224 +4225 +4226 +4227 +4228 +4229 +4230 +4231 +4232 +4233 +4234 +4235 +4236 +4237 +4238 +4239 +4240 +4241 +4242 +4243 +4244 +4245 +4246 +4247 +4248 +4249 +4250 +4251 +4252 +4253 +4254 +4255 +4256 +4257 +4258 +4259 +4260 +4261 +4262 +4263 +4264 +4265 +4266 +4267 +4268 +4269 +4270 +4271 +4272 +4273 +4274 +4275 +4276 +4277 +4278 +4279 +4280 +4281 +4282 +4283 +4284 +4285 +4286 +4287 +4288 +4289 +4290 +4291 +4292 +4293 +4294 +4295 +4296 +4297 +4298 +4299 +4300 +4301 +4302 +4303 +4304 +4305 +4306 +4307 +4308 +4309 +4310 +4311 +4312 +4313 +4314 +4315 +4316 +4317 +4318 +4319 +4320 +4321 +4322 +4323 +4324 +4325 +4326 +4327 +4328 +4329 +4330 +4331 +4332 +4333 +4334 +4335 +4336 +4337 +4338 +4339 +4340 +4341 +4342 +4343 +4344 +4345 +4346 +4347 +4348 +4349 +4350 +4351 +4352 +4353 +4354 +4355 +4356 +4357 +4358 +4359 +4360 +4361 +4362 +4363 +4364 +4365 +4366 +4367 +4368 +4369 +4370 +4371 +4372 +4373 +4374 +4375 +4376 +4377 +4378 +4379 +4380 +4381 +4382 +4383 +4384 +4385 +4386 +4387 +4388 +4389 +4390 +4391 +4392 +4393 +4394 +4395 +4396 +4397 +4398 +4399 +4400 +4401 +4402 +4403 +4404 +4405 +4406 +4407 +4408 +4409 +4410 +4411 +4412 +4413 +4414 +4415 +4416 +4417 +4418 +4419 +4420 +4421 +4422 +4423 +4424 +4425 +4426 +4427 +4428 +4429 +4430 +4431 +4432 +4433 +4434 +4435 +4436 +4437 +4438 +4439 +4440 +4441 +4442 +4443 +4444 +4445 +4446 +4447 +4448 +4449 +4450 +4451 +4452 +4453 +4454 +4455 +4456 +4457 +4458 +4459 +4460 +4461 +4462 +4463 +4464 +4465 +4466 +4467 +4468 +4469 +4470 +4471 +4472 +4473 +4474 +4475 +4476 +4477 +4478 +4479 +4480 +4481 +4482 +4483 +4484 +4485 +4486 +4487 +4488 +4489 +4490 +4491 +4492 +4493 +4494 +4495 +4496 +4497 +4498 +4499 +4500 +4501 +4502 +4503 +4504 +4505 +4506 +4507 +4508 +4509 +4510 +4511 +4512 +4513 +4514 +4515 +4516 +4517 +4518 +4519 +4520 +4521 +4522 +4523 +4524 +4525 +4526 +4527 +4528 +4529 +4530 +4531 +4532 +4533 +4534 +4535 +4536 +4537 +4538 +4539 +4540 +4541 +4542 +4543 +4544 +4545 +4546 +4547 +4548 +4549 +4550 +4551 +4552 +4553 +4554 +4555 +4556 +4557 +4558 +4559 +4560 +4561 +4562 +4563 +4564 +4565 +4566 +4567 +4568 +4569 +4570 +4571 +4572 +4573 +4574 +4575 +4576 +4577 +4578 +4579 +4580 +4581 +4582 +4583 +4584 +4585 +4586 +4587 +4588 +4589 +4590 +4591 +4592 +4593 +4594 +4595 +4596 +4597 +4598 +4599 +4600 +4601 +4602 +4603 +4604 +4605 +4606 +4607 +4608 +4609 +4610 +4611 +4612 +4613 +4614 +4615 +4616 +4617 +4618 +4619 +4620 +4621 +4622 +4623 +4624 +4625 +4626 +4627 +4628 +4629 +4630 +4631 +4632 +4633 +4634 +4635 +4636 +4637 +4638 +4639 +4640 +4641 +4642 +4643 +4644 +4645 +4646 +4647 +4648 +4649 +4650 +4651 +4652 +4653 +4654 +4655 +4656 +4657 +4658 +4659 +4660 +4661 +4662 +4663 +4664 +4665 +4666 +4667 +4668 +4669 +4670 +4671 +4672 +4673 +4674 +4675 +4676 +4677 +4678 +4679 +4680 +4681 +4682 +4683 +4684 +4685 +4686 +4687 +4688 +4689 +4690 +4691 +4692 +4693 +4694 +4695 +4696 +4697 +4698 +4699 +4700 +4701 +4702 +4703 +4704 +4705 +4706 +4707 +4708 +4709 +4710 +4711 +4712 +4713 +4714 +4715 +4716 +4717 +4718 +4719 +4720 +4721 +4722 +4723 +4724 +4725 +4726 +4727 +4728 +4729 +4730 +4731 +4732 +4733 +4734 +4735 +4736 +4737 +4738 +4739 +4740 +4741 +4742 +4743 +4744 +4745 +4746 +4747 +4748 +4749 +4750 +4751 +4752 +4753 +4754 +4755 +4756 +4757 +4758 +4759 +4760 +4761 +4762 +4763 +4764 +4765 +4766 +4767 +4768 +4769 +4770 +4771 +4772 +4773 +4774 +4775 +4776 +4777 +4778 +4779 +4780 +4781 +4782 +4783 +4784 +4785 +4786 +4787 +4788 +4789 +4790 +4791 +4792 +4793 +4794 +4795 +4796 +4797 +4798 +4799 +4800 +4801 +4802 +4803 +4804 +4805 +4806 +4807 +4808 +4809 +4810 +4811 +4812 +4813 +4814 +4815 +4816 +4817 +4818 +4819 +4820 +4821 +4822 +4823 +4824 +4825 +4826 +4827 +4828 +4829 +4830 +4831 +4832 +4833 +4834 +4835 +4836 +4837 +4838 +4839 +4840 +4841 +4842 +4843 +4844 +4845 +4846 +4847 +4848 +4849 +4850 +4851 +4852 +4853 +4854 +4855 +4856 +4857 +4858 +4859 +4860 +4861 +4862 +4863 +4864 +4865 +4866 +4867 +4868 +4869 +4870 +4871 +4872 +4873 +4874 +4875 +4876 +4877 +4878 +4879 +4880 +4881 +4882 +4883 +4884 +4885 +4886 +4887 +4888 +4889 +4890 +4891 +4892 +4893 +4894 +4895 +4896 +4897 +4898 +4899 +4900 +4901 +4902 +4903 +4904 +4905 +4906 +4907 +4908 +4909 +4910 +4911 +4912 +4913 +4914 +4915 +4916 +4917 +4918 +4919 +4920 +4921 +4922 +4923 +4924 +4925 +4926 +4927 +4928 +4929 +4930 +4931 +4932 +4933 +4934 +4935 +4936 +4937 +4938 +4939 +4940 +4941 +4942 +4943 +4944 +4945 +4946 +4947 +4948 +4949 +4950 +4951 +4952 +4953 +4954 +4955 +4956 +4957 +4958 +4959 +4960 +4961 +4962 +4963 +4964 +4965 +4966 +4967 +4968 +4969 +4970 +4971 +4972 +4973 +4974 +4975 +4976 +4977 +4978 +4979 +4980 +4981 +4982 +4983 +4984 +4985 +4986 +4987 +4988 +4989 +4990 +4991 +4992 +4993 +4994 +4995 +4996 +4997 +4998 +4999 +5000 +5001 +5002 +5003 +5004 +5005 +5006 +5007 +5008 +5009 +5010 +5011 +5012 +5013 +5014 +5015 +5016 +5017 +5018 +5019 +5020 +5021 +5022 +5023 +5024 +5025 +5026 +5027 +5028 +5029 +5030 +5031 +5032 +5033 +5034 +5035 +5036 +5037 +5038 +5039 +5040 +5041 +5042 +5043 +5044 +5045 +5046 +5047 +5048 +5049 +5050 +5051 +5052 +5053 +5054 +5055 +5056 +5057 +5058 +5059 +5060 +5061 +5062 +5063 +5064 +5065 +5066 +5067 +5068 +5069 +5070 +5071 +5072 +5073 +5074 +5075 +5076 +5077 +5078 +5079 +5080 +5081 +5082 +5083 +5084 +5085 +5086 +5087 +5088 +5089 +5090 +5091 +5092 +5093 +5094 +5095 +5096 +5097 +5098 +5099 +5100 +5101 +5102 +5103 +5104 +5105 +5106 +5107 +5108 +5109 +5110 +5111 +5112 +5113 +5114 +5115 +5116 +5117 +5118 +5119 +5120 +5121 +5122 +5123 +5124 +5125 +5126 +5127 +5128 +5129 +5130 +5131 +5132 +5133 +5134 +5135 +5136 +5137 +5138 +5139 +5140 +5141 +5142 +5143 +5144 +5145 +5146 +5147 +5148 +5149 +5150 +5151 +5152 +5153 +5154 +5155 +5156 +5157 +5158 +5159 +5160 +5161 +5162 +5163 +5164 +5165 +5166 +5167 +5168 +5169 +5170 +5171 +5172 +5173 +5174 +5175 +5176 +5177 +5178 +5179 +5180 +5181 +5182 +5183 +5184 +5185 +5186 +5187 +5188 +5189 +5190 +5191 +5192 +5193 +5194 +5195 +5196 +5197 +5198 +5199 +5200 +5201 +5202 +5203 +5204 +5205 +5206 +5207 +5208 +5209 +5210 +5211 +5212 +5213 +5214 +5215 +5216 +5217 +5218 +5219 +5220 +5221 +5222 +5223 +5224 +5225 +5226 +5227 +5228 +5229 +5230 +5231 +5232 +5233 +5234 +5235 +5236 +5237 +5238 +5239 +5240 +5241 +5242 +5243 +5244 +5245 +5246 +5247 +5248 +5249 +5250 +5251 +5252 +5253 +5254 +5255 +5256 +5257 +5258 +5259 +5260 +5261 +5262 +5263 +5264 +5265 +5266 +5267 +5268 +5269 +5270 +5271 +5272 +5273 +5274 +5275 +5276 +5277 +5278 +5279 +5280 +5281 +5282 +5283 +5284 +5285 +5286 +5287 +5288 +5289 +5290 +5291 +5292 +5293 +5294 +5295 +5296 +5297 +5298 +5299 +5300 +5301 +5302 +5303 +5304 +5305 +5306 +5307 +5308 +5309 +5310 +5311 +5312 +5313 +5314 +5315 +5316 +5317 +5318 +5319 +5320 +5321 +5322 +5323 +5324 +5325 +5326 +5327 +5328 +5329 +5330 +5331 +5332 +5333 +5334 +5335 +5336 +5337 +5338 +5339 +5340 +5341 +5342 +5343 +5344 +5345 +5346 +5347 +5348 +5349 +5350 +5351 +5352 +5353 +5354 +5355 +5356 +5357 +5358 +5359 +5360 +5361 +5362 +5363 +5364 +5365 +5366 +5367 +5368 +5369 +5370 +5371 +5372 +5373 +5374 +5375 +5376 +5377 +5378 +5379 +5380 +5381 +5382 +5383 +5384 +5385 +5386 +5387 +5388 +5389 +5390 +5391 +5392 +5393 +5394 +5395 +5396 +5397 +5398 +5399 +5400 +5401 +5402 +5403 +5404 +5405 +5406 +5407 +5408 +5409 +5410 +5411 +5412 +5413 +5414 +5415 +5416 +5417 +5418 +5419 +5420 +5421 +5422 +5423 +5424 +5425 +5426 +5427 +5428 +5429 +5430 +5431 +5432 +5433 +5434 +5435 +5436 +5437 +5438 +5439 +5440 +5441 +5442 +5443 +5444 +5445 +5446 +5447 +5448 +5449 +5450 +5451 +5452 +5453 +5454 +5455 +5456 +5457 +5458 +5459 +5460 +5461 +5462 +5463 +5464 +5465 +5466 +5467 +5468 +5469 +5470 +5471 +5472 +5473 +5474 +5475 +5476 +5477 +5478 +5479 +5480 +5481 +5482 +5483 +5484 +5485 +5486 +5487 +5488 +5489 +5490 +5491 +5492 +5493 +5494 +5495 +5496 +5497 +5498 +5499 +5500 +5501 +5502 +5503 +5504 +5505 +5506 +5507 +5508 +5509 +5510 +5511 +5512 +5513 +5514 +5515 +5516 +5517 +5518 +5519 +5520 +5521 +5522 +5523 +5524 +5525 +5526 +5527 +5528 +5529 +5530 +5531 +5532 +5533 +5534 +5535 +5536 +5537 +5538 +5539 +5540 +5541 +5542 +5543 +5544 +5545 +5546 +5547 +5548 +5549 +5550 +5551 +5552 +5553 +5554 +5555 +5556 +5557 +5558 +5559 +5560 +5561 +5562 +5563 +5564 +5565 +5566 +5567 +5568 +5569 +5570 +5571 +5572 +5573 +5574 +5575 +5576 +5577 +5578 +5579 +5580 +5581 +5582 +5583 +5584 +5585 +5586 +5587 +5588 +5589 +5590 +5591 +5592 +5593 +5594 +5595 +5596 +5597 +5598 +5599 +5600 +5601 +5602 +5603 +5604 +5605 +5606 +5607 +5608 +5609 +5610 +5611 +5612 +5613 +5614 +5615 +5616 +5617 +5618 +5619 +5620 +5621 +5622 +5623 +5624 +5625 +5626 +5627 +5628 +5629 +5630 +5631 +5632 +5633 +5634 +5635 +5636 +5637 +5638 +5639 +5640 +5641 +5642 +5643 +5644 +5645 +5646 +5647 +5648 +5649 +5650 +5651 +5652 +5653 +5654 +5655 +5656 +5657 +5658 +5659 +5660 +5661 +5662 +5663 +5664 +5665 +5666 +5667 +5668 +5669 +5670 +5671 +5672 +5673 +5674 +5675 +5676 +5677 +5678 +5679 +5680 +5681 +5682 +5683 +5684 +5685 +5686 +5687 +5688 +5689 +5690 +5691 +5692 +5693 +5694 +5695 +5696 +5697 +5698 +5699 +5700 +5701 +5702 +5703 +5704 +5705 +5706 +5707 +5708 +5709 +5710 +5711 +5712 +5713 +5714 +5715 +5716 +5717 +5718 +5719 +5720 +5721 +5722 +5723 +5724 +5725 +5726 +5727 +5728 +5729 +5730 +5731 +5732 +5733 +5734 +5735 +5736 +5737 +5738 +5739 +5740 +5741 +5742 +5743 +5744 +5745 +5746 +5747 +5748 +5749 +5750 +5751 +5752 +5753 +5754 +5755 +5756 +5757 +5758 +5759 +5760 +5761 +5762 +5763 +5764 +5765 +5766 +5767 +5768 +5769 +5770 +5771 +5772 +5773 +5774 +5775 +5776 +5777 +5778 +5779 +5780 +5781 +5782 +5783 +5784 +5785 +5786 +5787 +5788 +5789 +5790 +5791 +5792 +5793 +5794 +5795 +5796 +5797 +5798 +5799 +5800 +5801 +5802 +5803 +5804 +5805 +5806 +5807 +5808 +5809 +5810 +5811 +5812 +5813 +5814 +5815 +5816 +5817 +5818 +5819 +5820 +5821 +5822 +5823 +5824 +5825 +5826 +5827 +5828 +5829 +5830 +5831 +5832 +5833 +5834 +5835 +5836 +5837 +5838 +5839 +5840 +5841 +5842 +5843 +5844 +5845 +5846 +5847 +5848 +5849 +5850 +5851 +5852 +5853 +5854 +5855 +5856 +5857 +5858 +5859 +5860 +5861 +5862 +5863 +5864 +5865 +5866 +5867 +5868 +5869 +5870 +5871 +5872 +5873 +5874 +5875 +5876 +5877 +5878 +5879 +5880 +5881 +5882 +5883 +5884 +5885 +5886 +5887 +5888 +5889 +5890 +5891 +5892 +5893 +5894 +5895 +5896 +5897 +5898 +5899 +5900 +5901 +5902 +5903 +5904 +5905 +5906 +5907 +5908 +5909 +5910 +5911 +5912 +5913 +5914 +5915 +5916 +5917 +5918 +5919 +5920 +5921 +5922 +5923 +5924 +5925 +5926 +5927 +5928 +5929 +5930 +5931 +5932 +5933 +5934 +5935 +5936 +5937 +5938 +5939 +5940 +5941 +5942 +5943 +5944 +5945 +5946 +5947 +5948 +5949 +5950 +5951 +5952 +5953 +5954 +5955 +5956 +5957 +5958 +5959 +5960 +5961 +5962 +5963 +5964 +5965 +5966 +5967 +5968 +5969 +5970 +5971 +5972 +5973 +5974 +5975 +5976 +5977 +5978 +5979 +5980 +5981 +5982 +5983 +5984 +5985 +5986 +5987 +5988 +5989 +5990 +5991 +5992 +5993 +5994 +5995 +5996 +5997 +5998 +5999 +6000 +6001 +6002 +6003 +6004 +6005 +6006 +6007 +6008 +6009 +6010 +6011 +6012 +6013 +6014 +6015 +6016 +6017 +6018 +6019 +6020 +6021 +6022 +6023 +6024 +6025 +6026 +6027 +6028 +6029 +6030 +6031 +6032 +6033 +6034 +6035 +6036 +6037 +6038 +6039 +6040 +6041 +6042 +6043 +6044 +6045 +6046 +6047 +6048 +6049 +6050 +6051 +6052 +6053 +6054 +6055 +6056 +6057 +6058 +6059 +6060 +6061 +6062 +6063 +6064 +6065 +6066 +6067 +6068 +6069 +6070 +6071 +6072 +6073 +6074 +6075 +6076 +6077 +6078 +6079 +6080 +6081 +6082 +6083 +6084 +6085 +6086 +6087 +6088 +6089 +6090 +6091 +6092 +6093 +6094 +6095 +6096 +6097 +6098 +6099 +6100 +6101 +6102 +6103 +6104 +6105 +6106 +6107 +6108 +6109 +6110 +6111 +6112 +6113 +6114 +6115 +6116 +6117 +6118 +6119 +6120 +6121 +6122 +6123 +6124 +6125 +6126 +6127 +6128 +6129 +6130 +6131 +6132 +6133 +6134 +6135 +6136 +6137 +6138 +6139 +6140 +6141 +6142 +6143 +6144 +6145 +6146 +6147 +6148 +6149 +6150 +6151 +6152 +6153 +6154 +6155 +6156 +6157 +6158 +6159 +6160 +6161 +6162 +6163 +6164 +6165 +6166 +6167 +6168 +6169 +6170 +6171 +6172 +6173 +6174 +6175 +6176 +6177 +6178 +6179 +6180 +6181 +6182 +6183 +6184 +6185 +6186 +6187 +6188 +6189 +6190 +6191 +6192 +6193 +6194 +6195 +6196 +6197 +6198 +6199 +6200 +6201 +6202 +6203 +6204 +6205 +6206 +6207 +6208 +6209 +6210 +6211 +6212 +6213 +6214 +6215 +6216 +6217 +6218 +6219 +6220 +6221 +6222 +6223 +6224 +6225 +6226 +6227 +6228 +6229 +6230 +6231 +6232 +6233 +6234 +6235 +6236 +6237 +6238 +6239 +6240 +6241 +6242 +6243 +6244 +6245 +6246 +6247 +6248 +6249 +6250 +6251 +6252 +6253 +6254 +6255 +6256 +6257 +6258 +6259 +6260 +6261 +6262 +6263 +6264 +6265 +6266 +6267 +6268 +6269 +6270 +6271 +6272 +6273 +6274 +6275 +6276 +6277 +6278 +6279 +6280 +6281 +6282 +6283 +6284 +6285 +6286 +6287 +6288 +6289 +6290 +6291 +6292 +6293 +6294 +6295 +6296 +6297 +6298 +6299 +6300 +6301 +6302 +6303 +6304 +6305 +6306 +6307 +6308 +6309 +6310 +6311 +6312 +6313 +6314 +6315 +6316 +6317 +6318 +6319 +6320 +6321 +6322 +6323 +6324 +6325 +6326 +6327 +6328 +6329 +6330 +6331 +6332 +6333 +6334 +6335 +6336 +6337 +6338 +6339 +6340 +6341 +6342 +6343 +6344 +6345 +6346 +6347 +6348 +6349 +6350 +6351 +6352 +6353 +6354 +6355 +6356 +6357 +6358 +6359 +6360 +6361 +6362 +6363 +6364 +6365 +6366 +6367 +6368 +6369 +6370 +6371 +6372 +6373 +6374 +6375 +6376 +6377 +6378 +6379 +6380 +6381 +6382 +6383 +6384 +6385 +6386 +6387 +6388 +6389 +6390 +6391 +6392 +6393 +6394 +6395 +6396 +6397 +6398 +6399 +6400 +6401 +6402 +6403 +6404 +6405 +6406 +6407 +6408 +6409 +6410 +6411 +6412 +6413 +6414 +6415 +6416 +6417 +6418 +6419 +6420 +6421 +6422 +6423 +6424 +6425 +6426 +6427 +6428 +6429 +6430 +6431 +6432 +6433 +6434 +6435 +6436 +6437 +6438 +6439 +6440 +6441 +6442 +6443 +6444 +6445 +6446 +6447 +6448 +6449 +6450 +6451 +6452 +6453 +6454 +6455 +6456 +6457 +6458 +6459 +6460 +6461 +6462 +6463 +6464 +6465 +6466 +6467 +6468 +6469 +6470 +6471 +6472 +6473 +6474 +6475 +6476 +6477 +6478 +6479 +6480 +6481 +6482 +6483 +6484 +6485 +6486 +6487 +6488 +6489 +6490 +6491 +6492 +6493 +6494 +6495 +6496 +6497 +6498 +6499 +6500 +6501 +6502 +6503 +6504 +6505 +6506 +6507 +6508 +6509 +6510 +6511 +6512 +6513 +6514 +6515 +6516 +6517 +6518 +6519 +6520 +6521 +6522 +6523 +6524 +6525 +6526 +6527 +6528 +6529 +6530 +6531 +6532 +6533 +6534 +6535 +6536 +6537 +6538 +6539 +6540 +6541 +6542 +6543 +6544 +6545 +6546 +6547 +6548 +6549 +6550 +6551 +6552 +6553 +6554 +6555 +6556 +6557 +6558 +6559 +6560 +6561 +6562 +6563 +6564 +6565 +6566 +6567 +6568 +6569 +6570 +6571 +6572 +6573 +6574 +6575 +6576 +6577 +6578 +6579 +6580 +6581 +6582 +6583 +6584 +6585 +6586 +6587 +6588 +6589 +6590 +6591 +6592 +6593 +6594 +6595 +6596 +6597 +6598 +6599 +6600 +6601 +6602 +6603 +6604 +6605 +6606 +6607 +6608 +6609 +6610 +6611 +6612 +6613 +6614 +6615 +6616 +6617 +6618 +6619 +6620 +6621 +6622 +6623 +6624 +6625 +6626 +6627 +6628 +6629 +6630 +6631 +6632 +6633 +6634 +6635 +6636 +6637 +6638 +6639 +6640 +6641 +6642 +6643 +6644 +6645 +6646 +6647 +6648 +6649 +6650 +6651 +6652 +6653 +6654 +6655 +6656 +6657 +6658 +6659 +6660 +6661 +6662 +6663 +6664 +6665 +6666 +6667 +6668 +6669 +6670 +6671 +6672 +6673 +6674 +6675 +6676 +6677 +6678 +6679 +6680 +6681 +6682 +6683 +6684 +6685 +6686 +6687 +6688 +6689 +6690 +6691 +6692 +6693 +6694 +6695 +6696 +6697 +6698 +6699 +6700 +6701 +6702 +6703 +6704 +6705 +6706 +6707 +6708 +6709 +6710 +6711 +6712 +6713 +6714 +6715 +6716 +6717 +6718 +6719 +6720 +6721 +6722 +6723 +6724 +6725 +6726 +6727 +6728 +6729 +6730 +6731 +6732 +6733 +6734 +6735 +6736 +6737 +6738 +6739 +6740 +6741 +6742 +6743 +6744 +6745 +6746 +6747 +6748 +6749 +6750 +6751 +6752 +6753 +6754 +6755 +6756 +6757 +6758 +6759 +6760 +6761 +6762 +6763 +6764 +6765 +6766 +6767 +6768 +6769 +6770 +6771 +6772 +6773 +6774 +6775 +6776 +6777 +6778 +6779 +6780 +6781 +6782 +6783 +6784 +6785 +6786 +6787 +6788 +6789 +6790 +6791 +6792 +6793 +6794 +6795 +6796 +6797 +6798 +6799 +6800 +6801 +6802 +6803 +6804 +6805 +6806 +6807 +6808 +6809 +6810 +6811 +6812 +6813 +6814 +6815 +6816 +6817 +6818 +6819 +6820 +6821 +6822 +6823 +6824 +6825 +6826 +6827 +6828 +6829 +6830 +6831 +6832 +6833 +6834 +6835 +6836 +6837 +6838 +6839 +6840 +6841 +6842 +6843 +6844 +6845 +6846 +6847 +6848 +6849 +6850 +6851 +6852 +6853 +6854 +6855 +6856 +6857 +6858 +6859 +6860 +6861 +6862 +6863 +6864 +6865 +6866 +6867 +6868 +6869 +6870 +6871 +6872 +6873 +6874 +6875 +6876 +6877 +6878 +6879 +6880 +6881 +6882 +6883 +6884 +6885 +6886 +6887 +6888 +6889 +6890 +6891 +6892 +6893 +6894 +6895 +6896 +6897 +6898 +6899 +6900 +6901 +6902 +6903 +6904 +6905 +6906 +6907 +6908 +6909 +6910 +6911 +6912 +6913 +6914 +6915 +6916 +6917 +6918 +6919 +6920 +6921 +6922 +6923 +6924 +6925 +6926 +6927 +6928 +6929 +6930 +6931 +6932 +6933 +6934 +6935 +6936 +6937 +6938 +6939 +6940 +6941 +6942 +6943 +6944 +6945 +6946 +6947 +6948 +6949 +6950 +6951 +6952 +6953 +6954 +6955 +6956 +6957 +6958 +6959 +6960 +6961 +6962 +6963 +6964 +6965 +6966 +6967 +6968 +6969 +6970 +6971 +6972 +6973 +6974 +6975 +6976 +6977 +6978 +6979 +6980 +6981 +6982 +6983 +6984 +6985 +6986 +6987 +6988 +6989 +6990 +6991 +6992 +6993 +6994 +6995 +6996 +6997 +6998 +6999 +7000 +7001 +7002 +7003 +7004 +7005 +7006 +7007 +7008 +7009 +7010 +7011 +7012 +7013 +7014 +7015 +7016 +7017 +7018 +7019 +7020 +7021 +7022 +7023 +7024 +7025 +7026 +7027 +7028 +7029 +7030 +7031 +7032 +7033 +7034 +7035 +7036 +7037 +7038 +7039 +7040 +7041 +7042 +7043 +7044 +7045 +7046 +7047 +7048 +7049 +7050 +7051 +7052 +7053 +7054 +7055 +7056 +7057 +7058 +7059 +7060 +7061 +7062 +7063 +7064 +7065 +7066 +7067 +7068 +7069 +7070 +7071 +7072 +7073 +7074 +7075 +7076 +7077 +7078 +7079 +7080 +7081 +7082 +7083 +7084 +7085 +7086 +7087 +7088 +7089 +7090 +7091 +7092 +7093 +7094 +7095 +7096 +7097 +7098 +7099 +7100 +7101 +7102 +7103 +7104 +7105 +7106 +7107 +7108 +7109 +7110 +7111 +7112 +7113 +7114 +7115 +7116 +7117 +7118 +7119 +7120 +7121 +7122 +7123 +7124 +7125 +7126 +7127 +7128 +7129 +7130 +7131 +7132 +7133 +7134 +7135 +7136 +7137 +7138 +7139 +7140 +7141 +7142 +7143 +7144 +7145 +7146 +7147 +7148 +7149 +7150 +7151 +7152 +7153 +7154 +7155 +7156 +7157 +7158 +7159 +7160 +7161 +7162 +7163 +7164 +7165 +7166 +7167 +7168 +7169 +7170 +7171 +7172 +7173 +7174 +7175 +7176 +7177 +7178 +7179 +7180 +7181 +7182 +7183 +7184 +7185 +7186 +7187 +7188 +7189 +7190 +7191 +7192 +7193 +7194 +7195 +7196 +7197 +7198 +7199 +7200 +7201 +7202 +7203 +7204 +7205 +7206 +7207 +7208 +7209 +7210 +7211 +7212 +7213 +7214 +7215 +7216 +7217 +7218 +7219 +7220 +7221 +7222 +7223 +7224 +7225 +7226 +7227 +7228 +7229 +7230 +7231 +7232 +7233 +7234 +7235 +7236 +7237 +7238 +7239 +7240 +7241 +7242 +7243 +7244 +7245 +7246 +7247 +7248 +7249 +7250 +7251 +7252 +7253 +7254 +7255 +7256 +7257 +7258 +7259 +7260 +7261 +7262 +7263 +7264 +7265 +7266 +7267 +7268 +7269 +7270 +7271 +7272 +7273 +7274 +7275 +7276 +7277 +7278 +7279 +7280 +7281 +7282 +7283 +7284 +7285 +7286 +7287 +7288 +7289 +7290 +7291 +7292 +7293 +7294 +7295 +7296 +7297 +7298 +7299 +7300 +7301 +7302 +7303 +7304 +7305 +7306 +7307 +7308 +7309 +7310 +7311 +7312 +7313 +7314 +7315 +7316 +7317 +7318 +7319 +7320 +7321 +7322 +7323 +7324 +7325 +7326 +7327 +7328 +7329 +7330 +7331 +7332 +7333 +7334 +7335 +7336 +7337 +7338 +7339 +7340 +7341 +7342 +7343 +7344 +7345 +7346 +7347 +7348 +7349 +7350 +7351 +7352 +7353 +7354 +7355 +7356 +7357 +7358 +7359 +7360 +7361 +7362 +7363 +7364 +7365 +7366 +7367 +7368 +7369 +7370 +7371 +7372 +7373 +7374 +7375 +7376 +7377 +7378 +7379 +7380 +7381 +7382 +7383 +7384 +7385 +7386 +7387 +7388 +7389 +7390 +7391 +7392 +7393 +7394 +7395 +7396 +7397 +7398 +7399 +7400 +7401 +7402 +7403 +7404 +7405 +7406 +7407 +7408 +7409 +7410 +7411 +7412 +7413 +7414 +7415 +7416 +7417 +7418 +7419 +7420 +7421 +7422 +7423 +7424 +7425 +7426 +7427 +7428 +7429 +7430 +7431 +7432 +7433 +7434 +7435 +7436 +7437 +7438 +7439 +7440 +7441 +7442 +7443 +7444 +7445 +7446 +7447 +7448 +7449 +7450 +7451 +7452 +7453 +7454 +7455 +7456 +7457 +7458 +7459 +7460 +7461 +7462 +7463 +7464 +7465 +7466 +7467 +7468 +7469 +7470 +7471 +7472 +7473 +7474 +7475 +7476 +7477 +7478 +7479 +7480 +7481 +7482 +7483 +7484 +7485 +7486 +7487 +7488 +7489 +7490 +7491 +7492 +7493 +7494 +7495 +7496 +7497 +7498 +7499 +7500 +7501 +7502 +7503 +7504 +7505 +7506 +7507 +7508 +7509 +7510 +7511 +7512 +7513 +7514 +7515 +7516 +7517 +7518 +7519 +7520 +7521 +7522 +7523 +7524 +7525 +7526 +7527 +7528 +7529 +7530 +7531 +7532 +7533 +7534 +7535 +7536 +7537 +7538 +7539 +7540 +7541 +7542 +7543 +7544 +7545 +7546 +7547 +7548 +7549 +7550 +7551 +7552 +7553 +7554 +7555 +7556 +7557 +7558 +7559 +7560 +7561 +7562 +7563 +7564 +7565 +7566 +7567 +7568 +7569 +7570 +7571 +7572 +7573 +7574 +7575 +7576 +7577 +7578 +7579 +7580 +7581 +7582 +7583 +7584 +7585 +7586 +7587 +7588 +7589 +7590 +7591 +7592 +7593 +7594 +7595 +7596 +7597 +7598 +7599 +7600 +7601 +7602 +7603 +7604 +7605 +7606 +7607 +7608 +7609 +7610 +7611 +7612 +7613 +7614 +7615 +7616 +7617 +7618 +7619 +7620 +7621 +7622 +7623 +7624 +7625 +7626 +7627 +7628 +7629 +7630 +7631 +7632 +7633 +7634 +7635 +7636 +7637 +7638 +7639 +7640 +7641 +7642 +7643 +7644 +7645 +7646 +7647 +7648 +7649 +7650 +7651 +7652 +7653 +7654 +7655 +7656 +7657 +7658 +7659 +7660 +7661 +7662 +7663 +7664 +7665 +7666 +7667 +7668 +7669 +7670 +7671 +7672 +7673 +7674 +7675 +7676 +7677 +7678 +7679 +7680 +7681 +7682 +7683 +7684 +7685 +7686 +7687 +7688 +7689 +7690 +7691 +7692 +7693 +7694 +7695 +7696 +7697 +7698 +7699 +7700 +7701 +7702 +7703 +7704 +7705 +7706 +7707 +7708 +7709 +7710 +7711 +7712 +7713 +7714 +7715 +7716 +7717 +7718 +7719 +7720 +7721 +7722 +7723 +7724 +7725 +7726 +7727 +7728 +7729 +7730 +7731 +7732 +7733 +7734 +7735 +7736 +7737 +7738 +7739 +7740 +7741 +7742 +7743 +7744 +7745 +7746 +7747 +7748 +7749 +7750 +7751 +7752 +7753 +7754 +7755 +7756 +7757 +7758 +7759 +7760 +7761 +7762 +7763 +7764 +7765 +7766 +7767 +7768 +7769 +7770 +7771 +7772 +7773 +7774 +7775 +7776 +7777 +7778 +7779 +7780 +7781 +7782 +7783 +7784 +7785 +7786 +7787 +7788 +7789 +7790 +7791 +7792 +7793 +7794 +7795 +7796 +7797 +7798 +7799 +7800 +7801 +7802 +7803 +7804 +7805 +7806 +7807 +7808 +7809 +7810 +7811 +7812 +7813 +7814 +7815 +7816 +7817 +7818 +7819 +7820 +7821 +7822 +7823 +7824 +7825 +7826 +7827 +7828 +7829 +7830 +7831 +7832 +7833 +7834 +7835 +7836 +7837 +7838 +7839 +7840 +7841 +7842 +7843 +7844 +7845 +7846 +7847 +7848 +7849 +7850 +7851 +7852 +7853 +7854 +7855 +7856 +7857 +7858 +7859 +7860 +7861 +7862 +7863 +7864 +7865 +7866 +7867 +7868 +7869 +7870 +7871 +7872 +7873 +7874 +7875 +7876 +7877 +7878 +7879 +7880 +7881 +7882 +7883 +7884 +7885 +7886 +7887 +7888 +7889 +7890 +7891 +7892 +7893 +7894 +7895 +7896 +7897 +7898 +7899 +7900 +7901 +7902 +7903 +7904 +7905 +7906 +7907 +7908 +7909 +7910 +7911 +7912 +7913 +7914 +7915 +7916 +7917 +7918 +7919 +7920 +7921 +7922 +7923 +7924 +7925 +7926 +7927 +7928 +7929 +7930 +7931 +7932 +7933 +7934 +7935 +7936 +7937 +7938 +7939 +7940 +7941 +7942 +7943 +7944 +7945 +7946 +7947 +7948 +7949 +7950 +7951 +7952 +7953 +7954 +7955 +7956 +7957 +7958 +7959 +7960 +7961 +7962 +7963 +7964 +7965 +7966 +7967 +7968 +7969 +7970 +7971 +7972 +7973 +7974 +7975 +7976 +7977 +7978 +7979 +7980 +7981 +7982 +7983 +7984 +7985 +7986 +7987 +7988 +7989 +7990 +7991 +7992 +7993 +7994 +7995 +7996 +7997 +7998 +7999 +8000 +8001 +8002 +8003 +8004 +8005 +8006 +8007 +8008 +8009 +8010 +8011 +8012 +8013 +8014 +8015 +8016 +8017 +8018 +8019 +8020 +8021 +8022 +8023 +8024 +8025 +8026 +8027 +8028 +8029 +8030 +8031 +8032 +8033 +8034 +8035 +8036 +8037 +8038 +8039 +8040 +8041 +8042 +8043 +8044 +8045 +8046 +8047 +8048 +8049 +8050 +8051 +8052 +8053 +8054 +8055 +8056 +8057 +8058 +8059 +8060 +8061 +8062 +8063 +8064 +8065 +8066 +8067 +8068 +8069 +8070 +8071 +8072 +8073 +8074 +8075 +8076 +8077 +8078 +8079 +8080 +8081 +8082 +8083 +8084 +8085 +8086 +8087 +8088 +8089 +8090 +8091 +8092 +8093 +8094 +8095 +8096 +8097 +8098 +8099 +8100 +8101 +8102 +8103 +8104 +8105 +8106 +8107 +8108 +8109 +8110 +8111 +8112 +8113 +8114 +8115 +8116 +8117 +8118 +8119 +8120 +8121 +8122 +8123 +8124 +8125 +8126 +8127 +8128 +8129 +8130 +8131 +8132 +8133 +8134 +8135 +8136 +8137 +8138 +8139 +8140 +8141 +8142 +8143 +8144 +8145 +8146 +8147 +8148 +8149 +8150 +8151 +8152 +8153 +8154 +8155 +8156 +8157 +8158 +8159 +8160 +8161 +8162 +8163 +8164 +8165 +8166 +8167 +8168 +8169 +8170 +8171 +8172 +8173 +8174 +8175 +8176 +8177 +8178 +8179 +8180 +8181 +8182 +8183 +8184 +8185 +8186 +8187 +8188 +8189 +8190 +8191 +8192 +8193 +8194 +8195 +8196 +8197 +8198 +8199 +8200 +8201 +8202 +8203 +8204 +8205 +8206 +8207 +8208 +8209 +8210 +8211 +8212 +8213 +8214 +8215 +8216 +8217 +8218 +8219 +8220 +8221 +8222 +8223 +8224 +8225 +8226 +8227 +8228 +8229 +8230 +8231 +8232 +8233 +8234 +8235 +8236 +8237 +8238 +8239 +8240 +8241 +8242 +8243 +8244 +8245 +8246 +8247 +8248 +8249 +8250 +8251 +8252 +8253 +8254 +8255 +8256 +8257 +8258 +8259 +8260 +8261 +8262 +8263 +8264 +8265 +8266 +8267 +8268 +8269 +8270 +8271 +8272 +8273 +8274 +8275 +8276 +8277 +8278 +8279 +8280 +8281 +8282 +8283 +8284 +8285 +8286 +8287 +8288 +8289 +8290 +8291 +8292 +8293 +8294 +8295 +8296 +8297 +8298 +8299 +8300 +8301 +8302 +8303 +8304 +8305 +8306 +8307 +8308 +8309 +8310 +8311 +8312 +8313 +8314 +8315 +8316 +8317 +8318 +8319 +8320 +8321 +8322 +8323 +8324 +8325 +8326 +8327 +8328 +8329 +8330 +8331 +8332 +8333 +8334 +8335 +8336 +8337 +8338 +8339 +8340 +8341 +8342 +8343 +8344 +8345 +8346 +8347 +8348 +8349 +8350 +8351 +8352 +8353 +8354 +8355 +8356 +8357 +8358 +8359 +8360 +8361 +8362 +8363 +8364 +8365 +8366 +8367 +8368 +8369 +8370 +8371 +8372 +8373 +8374 +8375 +8376 +8377 +8378 +8379 +8380 +8381 +8382 +8383 +8384 +8385 +8386 +8387 +8388 +8389 +8390 +8391 +8392 +8393 +8394 +8395 +8396 +8397 +8398 +8399 +8400 +8401 +8402 +8403 +8404 +8405 +8406 +8407 +8408 +8409 +8410 +8411 +8412 +8413 +8414 +8415 +8416 +8417 +8418 +8419 +8420 +8421 +8422 +8423 +8424 +8425 +8426 +8427 +8428 +8429 +8430 +8431 +8432 +8433 +8434 +8435 +8436 +8437 +8438 +8439 +8440 +8441 +8442 +8443 +8444 +8445 +8446 +8447 +8448 +8449 +8450 +8451 +8452 +8453 +8454 +8455 +8456 +8457 +8458 +8459 +8460 +8461 +8462 +8463 +8464 +8465 +8466 +8467 +8468 +8469 +8470 +8471 +8472 +8473 +8474 +8475 +8476 +8477 +8478 +8479 +8480 +8481 +8482 +8483 +8484 +8485 +8486 +8487 +8488 +8489 +8490 +8491 +8492 +8493 +8494 +8495 +8496 +8497 +8498 +8499 +8500 +8501 +8502 +8503 +8504 +8505 +8506 +8507 +8508 +8509 +8510 +8511 +8512 +8513 +8514 +8515 +8516 +8517 +8518 +8519 +8520 +8521 +8522 +8523 +8524 +8525 +8526 +8527 +8528 +8529 +8530 +8531 +8532 +8533 +8534 +8535 +8536 +8537 +8538 +8539 +8540 +8541 +8542 +8543 +8544 +8545 +8546 +8547 +8548 +8549 +8550 +8551 +8552 +8553 +8554 +8555 +8556 +8557 +8558 +8559 +8560 +8561 +8562 +8563 +8564 +8565 +8566 +8567 +8568 +8569 +8570 +8571 +8572 +8573 +8574 +8575 +8576 +8577 +8578 +8579 +8580 +8581 +8582 +8583 +8584 +8585 +8586 +8587 +8588 +8589 +8590 +8591 +8592 +8593 +8594 +8595 +8596 +8597 +8598 +8599 +8600 +8601 +8602 +8603 +8604 +8605 +8606 +8607 +8608 +8609 +8610 +8611 +8612 +8613 +8614 +8615 +8616 +8617 +8618 +8619 +8620 +8621 +8622 +8623 +8624 +8625 +8626 +8627 +8628 +8629 +8630 +8631 +8632 +8633 +8634 +8635 +8636 +8637 +8638 +8639 +8640 +8641 +8642 +8643 +8644 +8645 +8646 +8647 +8648 +8649 +8650 +8651 +8652 +8653 +8654 +8655 +8656 +8657 +8658 +8659 +8660 +8661 +8662 +8663 +8664 +8665 +8666 +8667 +8668 +8669 +8670 +8671 +8672 +8673 +8674 +8675 +8676 +8677 +8678 +8679 +8680 +8681 +8682 +8683 +8684 +8685 +8686 +8687 +8688 +8689 +8690 +8691 +8692 +8693 +8694 +8695 +8696 +8697 +8698 +8699 +8700 +8701 +8702 +8703 +8704 +8705 +8706 +8707 +8708 +8709 +8710 +8711 +8712 +8713 +8714 +8715 +8716 +8717 +8718 +8719 +8720 +8721 +8722 +8723 +8724 +8725 +8726 +8727 +8728 +8729 +8730 +8731 +8732 +8733 +8734 +8735 +8736 +8737 +8738 +8739 +8740 +8741 +8742 +8743 +8744 +8745 +8746 +8747 +8748 +8749 +8750 +8751 +8752 +8753 +8754 +8755 +8756 +8757 +8758 +8759 +8760 +8761 +8762 +8763 +8764 +8765 +8766 +8767 +8768 +8769 +8770 +8771 +8772 +8773 +8774 +8775 +8776 +8777 +8778 +8779 +8780 +8781 +8782 +8783 +8784 +8785 +8786 +8787 +8788 +8789 +8790 +8791 +8792 +8793 +8794 +8795 +8796 +8797 +8798 +8799 +8800 +8801 +8802 +8803 +8804 +8805 +8806 +8807 +8808 +8809 +8810 +8811 +8812 +8813 +8814 +8815 +8816 +8817 +8818 +8819 +8820 +8821 +8822 +8823 +8824 +8825 +8826 +8827 +8828 +8829 +8830 +8831 +8832 +8833 +8834 +8835 +8836 +8837 +8838 +8839 +8840 +8841 +8842 +8843 +8844 +8845 +8846 +8847 +8848 +8849 +8850 +8851 +8852 +8853 +8854 +8855 +8856 +8857 +8858 +8859 +8860 +8861 +8862 +8863 +8864 +8865 +8866 +8867 +8868 +8869 +8870 +8871 +8872 +8873 +8874 +8875 +8876 +8877 +8878 +8879 +8880 +8881 +8882 +8883 +8884 +8885 +8886 +8887 +8888 +8889 +8890 +8891 +8892 +8893 +8894 +8895 +8896 +8897 +8898 +8899 +8900 +8901 +8902 +8903 +8904 +8905 +8906 +8907 +8908 +8909 +8910 +8911 +8912 +8913 +8914 +8915 +8916 +8917 +8918 +8919 +8920 +8921 +8922 +8923 +8924 +8925 +8926 +8927 +8928 +8929 +8930 +8931 +8932 +8933 +8934 +8935 +8936 +8937 +8938 +8939 +8940 +8941 +8942 +8943 +8944 +8945 +8946 +8947 +8948 +8949 +8950 +8951 +8952 +8953 +8954 +8955 +8956 +8957 +8958 +8959 +8960 +8961 +8962 +8963 +8964 +8965 +8966 +8967 +8968 +8969 +8970 +8971 +8972 +8973 +8974 +8975 +8976 +8977 +8978 +8979 +8980 +8981 +8982 +8983 +8984 +8985 +8986 +8987 +8988 +8989 +8990 +8991 +8992 +8993 +8994 +8995 +8996 +8997 +8998 +8999 +9000 +9001 +9002 +9003 +9004 +9005 +9006 +9007 +9008 +9009 +9010 +9011 +9012 +9013 +9014 +9015 +9016 +9017 +9018 +9019 +9020 +9021 +9022 +9023 +9024 +9025 +9026 +9027 +9028 +9029 +9030 +9031 +9032 +9033 +9034 +9035 +9036 +9037 +9038 +9039 +9040 +9041 +9042 +9043 +9044 +9045 +9046 +9047 +9048 +9049 +9050 +9051 +9052 +9053 +9054 +9055 +9056 +9057 +9058 +9059 +9060 +9061 +9062 +9063 +9064 +9065 +9066 +9067 +9068 +9069 +9070 +9071 +9072 +9073 +9074 +9075 +9076 +9077 +9078 +9079 +9080 +9081 +9082 +9083 +9084 +9085 +9086 +9087 +9088 +9089 +9090 +9091 +9092 +9093 +9094 +9095 +9096 +9097 +9098 +9099 +9100 +9101 +9102 +9103 +9104 +9105 +9106 +9107 +9108 +9109 +9110 +9111 +9112 +9113 +9114 +9115 +9116 +9117 +9118 +9119 +9120 +9121 +9122 +9123 +9124 +9125 +9126 +9127 +9128 +9129 +9130 +9131 +9132 +9133 +9134 +9135 +9136 +9137 +9138 +9139 +9140 +9141 +9142 +9143 +9144 +9145 +9146 +9147 +9148 +9149 +9150 +9151 +9152 +9153 +9154 +9155 +9156 +9157 +9158 +9159 +9160 +9161 +9162 +9163 +9164 +9165 +9166 +9167 +9168 +9169 +9170 +9171 +9172 +9173 +9174 +9175 +9176 +9177 +9178 +9179 +9180 +9181 +9182 +9183 +9184 +9185 +9186 +9187 +9188 +9189 +9190 +9191 +9192 +9193 +9194 +9195 +9196 +9197 +9198 +9199 +9200 +9201 +9202 +9203 +9204 +9205 +9206 +9207 +9208 +9209 +9210 +9211 +9212 +9213 +9214 +9215 +9216 +9217 +9218 +9219 +9220 +9221 +9222 +9223 +9224 +9225 +9226 +9227 +9228 +9229 +9230 +9231 +9232 +9233 +9234 +9235 +9236 +9237 +9238 +9239 +9240 +9241 +9242 +9243 +9244 +9245 +9246 +9247 +9248 +9249 +9250 +9251 +9252 +9253 +9254 +9255 +9256 +9257 +9258 +9259 +9260 +9261 +9262 +9263 +9264 +9265 +9266 +9267 +9268 +9269 +9270 +9271 +9272 +9273 +9274 +9275 +9276 +9277 +9278 +9279 +9280 +9281 +9282 +9283 +9284 +9285 +9286 +9287 +9288 +9289 +9290 +9291 +9292 +9293 +9294 +9295 +9296 +9297 +9298 +9299 +9300 +9301 +9302 +9303 +9304 +9305 +9306 +9307 +9308 +9309 +9310 +9311 +9312 +9313 +9314 +9315 +9316 +9317 +9318 +9319 +9320 +9321 +9322 +9323 +9324 +9325 +9326 +9327 +9328 +9329 +9330 +9331 +9332 +9333 +9334 +9335 +9336 +9337 +9338 +9339 +9340 +9341 +9342 +9343 +9344 +9345 +9346 +9347 +9348 +9349 +9350 +9351 +9352 +9353 +9354 +9355 +9356 +9357 +9358 +9359 +9360 +9361 +9362 +9363 +9364 +9365 +9366 +9367 +9368 +9369 +9370 +9371 +9372 +9373 +9374 +9375 +9376 +9377 +9378 +9379 +9380 +9381 +9382 +9383 +9384 +9385 +9386 +9387 +9388 +9389 +9390 +9391 +9392 +9393 +9394 +9395 +9396 +9397 +9398 +9399 +9400 +9401 +9402 +9403 +9404 +9405 +9406 +9407 +9408 +9409 +9410 +9411 +9412 +9413 +9414 +9415 +9416 +9417 +9418 +9419 +9420 +9421 +9422 +9423 +9424 +9425 +9426 +9427 +9428 +9429 +9430 +9431 +9432 +9433 +9434 +9435 +9436 +9437 +9438 +9439 +9440 +9441 +9442 +9443 +9444 +9445 +9446 +9447 +9448 +9449 +9450 +9451 +9452 +9453 +9454 +9455 +9456 +9457 +9458 +9459 +9460 +9461 +9462 +9463 +9464 +9465 +9466 +9467 +9468 +9469 +9470 +9471 +9472 +9473 +9474 +9475 +9476 +9477 +9478 +9479 +9480 +9481 +9482 +9483 +9484 +9485 +9486 +9487 +9488 +9489 +9490 +9491 +9492 +9493 +9494 +9495 +9496 +9497 +9498 +9499 +9500 +9501 +9502 +9503 +9504 +9505 +9506 +9507 +9508 +9509 +9510 +9511 +9512 +9513 +9514 +9515 +9516 +9517 +9518 +9519 +9520 +9521 +9522 +9523 +9524 +9525 +9526 +9527 +9528 +9529 +9530 +9531 +9532 +9533 +9534 +9535 +9536 +9537 +9538 +9539 +9540 +9541 +9542 +9543 +9544 +9545 +9546 +9547 +9548 +9549 +9550 +9551 +9552 +9553 +9554 +9555 +9556 +9557 +9558 +9559 +9560 +9561 +9562 +9563 +9564 +9565 +9566 +9567 +9568 +9569 +9570 +9571 +9572 +9573 +9574 +9575 +9576 +9577 +9578 +9579 +9580 +9581 +9582 +9583 +9584 +9585 +9586 +9587 +9588 +9589 +9590 +9591 +9592 +9593 +9594 +9595 +9596 +9597 +9598 +9599 +9600 +9601 +9602 +9603 +9604 +9605 +9606 +9607 +9608 +9609 +9610 +9611 +9612 +9613 +9614 +9615 +9616 +9617 +9618 +9619 +9620 +9621 +9622 +9623 +9624 +9625 +9626 +9627 +9628 +9629 +9630 +9631 +9632 +9633 +9634 +9635 +9636 +9637 +9638 +9639 +9640 +9641 +9642 +9643 +9644 +9645 +9646 +9647 +9648 +9649 +9650 +9651 +9652 +9653 +9654 +9655 +9656 +9657 +9658 +9659 +9660 +9661 +9662 +9663 +9664 +9665 +9666 +9667 +9668 +9669 +9670 +9671 +9672 +9673 +9674 +9675 +9676 +9677 +9678 +9679 +9680 +9681 +9682 +9683 +9684 +9685 +9686 +9687 +9688 +9689 +9690 +9691 +9692 +9693 +9694 +9695 +9696 +9697 +9698 +9699 +9700 +9701 +9702 +9703 +9704 +9705 +9706 +9707 +9708 +9709 +9710 +9711 +9712 +9713 +9714 +9715 +9716 +9717 +9718 +9719 +9720 +9721 +9722 +9723 +9724 +9725 +9726 +9727 +9728 +9729 +9730 +9731 +9732 +9733 +9734 +9735 +9736 +9737 +9738 +9739 +9740 +9741 +9742 +9743 +9744 +9745 +9746 +9747 +9748 +9749 +9750 +9751 +9752 +9753 +9754 +9755 +9756 +9757 +9758 +9759 +9760 +9761 +9762 +9763 +9764 +9765 +9766 +9767 +9768 +9769 +9770 +9771 +9772 +9773 +9774 +9775 +9776 +9777 +9778 +9779 +9780 +9781 +9782 +9783 +9784 +9785 +9786 +9787 +9788 +9789 +9790 +9791 +9792 +9793 +9794 +9795 +9796 +9797 +9798 +9799 +9800 +9801 +9802 +9803 +9804 +9805 +9806 +9807 +9808 +9809 +9810 +9811 +9812 +9813 +9814 +9815 +9816 +9817 +9818 +9819 +9820 +9821 +9822 +9823 +9824 +9825 +9826 +9827 +9828 +9829 +9830 +9831 +9832 +9833 +9834 +9835 +9836 +9837 +9838 +9839 +9840 +9841 +9842 +9843 +9844 +9845 +9846 +9847 +9848 +9849 +9850 +9851 +9852 +9853 +9854 +9855 +9856 +9857 +9858 +9859 +9860 +9861 +9862 +9863 +9864 +9865 +9866 +9867 +9868 +9869 +9870 +9871 +9872 +9873 +9874 +9875 +9876 +9877 +9878 +9879 +9880 +9881 +9882 +9883 +9884 +9885 +9886 +9887 +9888 +9889 +9890 +9891 +9892 +9893 +9894 +9895 +9896 +9897 +9898 +9899 +9900 +9901 +9902 +9903 +9904 +9905 +9906 +9907 +9908 +9909 +9910 +9911 +9912 +9913 +9914 +9915 +9916 +9917 +9918 +9919 +9920 +9921 +9922 +9923 +9924 +9925 +9926 +9927 +9928 +9929 +9930 +9931 +9932 +9933 +9934 +9935 +9936 +9937 +9938 +9939 +9940 +9941 +9942 +9943 +9944 +9945 +9946 +9947 +9948 +9949 +9950 +9951 +9952 +9953 +9954 +9955 +9956 +9957 +9958 +9959 +9960 +9961 +9962 +9963 +9964 +9965 +9966 +9967 +9968 +9969 +9970 +9971 +9972 +9973 +9974 +9975 +9976 +9977 +9978 +9979 +9980 +9981 +9982 +9983 +9984 +9985 +9986 +9987 +9988 +9989 +9990 +9991 +9992 +9993 +9994 +9995 +9996 +9997 +9998 +9999 +10000 diff --git a/mysql-test/std_data/bug30435_5k.txt b/mysql-test/std_data/bug30435_5k.txt new file mode 100644 index 00000000000..7d1714969fc --- /dev/null +++ b/mysql-test/std_data/bug30435_5k.txt @@ -0,0 +1,5000 @@ +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448 +449 +450 +451 +452 +453 +454 +455 +456 +457 +458 +459 +460 +461 +462 +463 +464 +465 +466 +467 +468 +469 +470 +471 +472 +473 +474 +475 +476 +477 +478 +479 +480 +481 +482 +483 +484 +485 +486 +487 +488 +489 +490 +491 +492 +493 +494 +495 +496 +497 +498 +499 +500 +501 +502 +503 +504 +505 +506 +507 +508 +509 +510 +511 +512 +513 +514 +515 +516 +517 +518 +519 +520 +521 +522 +523 +524 +525 +526 +527 +528 +529 +530 +531 +532 +533 +534 +535 +536 +537 +538 +539 +540 +541 +542 +543 +544 +545 +546 +547 +548 +549 +550 +551 +552 +553 +554 +555 +556 +557 +558 +559 +560 +561 +562 +563 +564 +565 +566 +567 +568 +569 +570 +571 +572 +573 +574 +575 +576 +577 +578 +579 +580 +581 +582 +583 +584 +585 +586 +587 +588 +589 +590 +591 +592 +593 +594 +595 +596 +597 +598 +599 +600 +601 +602 +603 +604 +605 +606 +607 +608 +609 +610 +611 +612 +613 +614 +615 +616 +617 +618 +619 +620 +621 +622 +623 +624 +625 +626 +627 +628 +629 +630 +631 +632 +633 +634 +635 +636 +637 +638 +639 +640 +641 +642 +643 +644 +645 +646 +647 +648 +649 +650 +651 +652 +653 +654 +655 +656 +657 +658 +659 +660 +661 +662 +663 +664 +665 +666 +667 +668 +669 +670 +671 +672 +673 +674 +675 +676 +677 +678 +679 +680 +681 +682 +683 +684 +685 +686 +687 +688 +689 +690 +691 +692 +693 +694 +695 +696 +697 +698 +699 +700 +701 +702 +703 +704 +705 +706 +707 +708 +709 +710 +711 +712 +713 +714 +715 +716 +717 +718 +719 +720 +721 +722 +723 +724 +725 +726 +727 +728 +729 +730 +731 +732 +733 +734 +735 +736 +737 +738 +739 +740 +741 +742 +743 +744 +745 +746 +747 +748 +749 +750 +751 +752 +753 +754 +755 +756 +757 +758 +759 +760 +761 +762 +763 +764 +765 +766 +767 +768 +769 +770 +771 +772 +773 +774 +775 +776 +777 +778 +779 +780 +781 +782 +783 +784 +785 +786 +787 +788 +789 +790 +791 +792 +793 +794 +795 +796 +797 +798 +799 +800 +801 +802 +803 +804 +805 +806 +807 +808 +809 +810 +811 +812 +813 +814 +815 +816 +817 +818 +819 +820 +821 +822 +823 +824 +825 +826 +827 +828 +829 +830 +831 +832 +833 +834 +835 +836 +837 +838 +839 +840 +841 +842 +843 +844 +845 +846 +847 +848 +849 +850 +851 +852 +853 +854 +855 +856 +857 +858 +859 +860 +861 +862 +863 +864 +865 +866 +867 +868 +869 +870 +871 +872 +873 +874 +875 +876 +877 +878 +879 +880 +881 +882 +883 +884 +885 +886 +887 +888 +889 +890 +891 +892 +893 +894 +895 +896 +897 +898 +899 +900 +901 +902 +903 +904 +905 +906 +907 +908 +909 +910 +911 +912 +913 +914 +915 +916 +917 +918 +919 +920 +921 +922 +923 +924 +925 +926 +927 +928 +929 +930 +931 +932 +933 +934 +935 +936 +937 +938 +939 +940 +941 +942 +943 +944 +945 +946 +947 +948 +949 +950 +951 +952 +953 +954 +955 +956 +957 +958 +959 +960 +961 +962 +963 +964 +965 +966 +967 +968 +969 +970 +971 +972 +973 +974 +975 +976 +977 +978 +979 +980 +981 +982 +983 +984 +985 +986 +987 +988 +989 +990 +991 +992 +993 +994 +995 +996 +997 +998 +999 +1000 +1001 +1002 +1003 +1004 +1005 +1006 +1007 +1008 +1009 +1010 +1011 +1012 +1013 +1014 +1015 +1016 +1017 +1018 +1019 +1020 +1021 +1022 +1023 +1024 +1025 +1026 +1027 +1028 +1029 +1030 +1031 +1032 +1033 +1034 +1035 +1036 +1037 +1038 +1039 +1040 +1041 +1042 +1043 +1044 +1045 +1046 +1047 +1048 +1049 +1050 +1051 +1052 +1053 +1054 +1055 +1056 +1057 +1058 +1059 +1060 +1061 +1062 +1063 +1064 +1065 +1066 +1067 +1068 +1069 +1070 +1071 +1072 +1073 +1074 +1075 +1076 +1077 +1078 +1079 +1080 +1081 +1082 +1083 +1084 +1085 +1086 +1087 +1088 +1089 +1090 +1091 +1092 +1093 +1094 +1095 +1096 +1097 +1098 +1099 +1100 +1101 +1102 +1103 +1104 +1105 +1106 +1107 +1108 +1109 +1110 +1111 +1112 +1113 +1114 +1115 +1116 +1117 +1118 +1119 +1120 +1121 +1122 +1123 +1124 +1125 +1126 +1127 +1128 +1129 +1130 +1131 +1132 +1133 +1134 +1135 +1136 +1137 +1138 +1139 +1140 +1141 +1142 +1143 +1144 +1145 +1146 +1147 +1148 +1149 +1150 +1151 +1152 +1153 +1154 +1155 +1156 +1157 +1158 +1159 +1160 +1161 +1162 +1163 +1164 +1165 +1166 +1167 +1168 +1169 +1170 +1171 +1172 +1173 +1174 +1175 +1176 +1177 +1178 +1179 +1180 +1181 +1182 +1183 +1184 +1185 +1186 +1187 +1188 +1189 +1190 +1191 +1192 +1193 +1194 +1195 +1196 +1197 +1198 +1199 +1200 +1201 +1202 +1203 +1204 +1205 +1206 +1207 +1208 +1209 +1210 +1211 +1212 +1213 +1214 +1215 +1216 +1217 +1218 +1219 +1220 +1221 +1222 +1223 +1224 +1225 +1226 +1227 +1228 +1229 +1230 +1231 +1232 +1233 +1234 +1235 +1236 +1237 +1238 +1239 +1240 +1241 +1242 +1243 +1244 +1245 +1246 +1247 +1248 +1249 +1250 +1251 +1252 +1253 +1254 +1255 +1256 +1257 +1258 +1259 +1260 +1261 +1262 +1263 +1264 +1265 +1266 +1267 +1268 +1269 +1270 +1271 +1272 +1273 +1274 +1275 +1276 +1277 +1278 +1279 +1280 +1281 +1282 +1283 +1284 +1285 +1286 +1287 +1288 +1289 +1290 +1291 +1292 +1293 +1294 +1295 +1296 +1297 +1298 +1299 +1300 +1301 +1302 +1303 +1304 +1305 +1306 +1307 +1308 +1309 +1310 +1311 +1312 +1313 +1314 +1315 +1316 +1317 +1318 +1319 +1320 +1321 +1322 +1323 +1324 +1325 +1326 +1327 +1328 +1329 +1330 +1331 +1332 +1333 +1334 +1335 +1336 +1337 +1338 +1339 +1340 +1341 +1342 +1343 +1344 +1345 +1346 +1347 +1348 +1349 +1350 +1351 +1352 +1353 +1354 +1355 +1356 +1357 +1358 +1359 +1360 +1361 +1362 +1363 +1364 +1365 +1366 +1367 +1368 +1369 +1370 +1371 +1372 +1373 +1374 +1375 +1376 +1377 +1378 +1379 +1380 +1381 +1382 +1383 +1384 +1385 +1386 +1387 +1388 +1389 +1390 +1391 +1392 +1393 +1394 +1395 +1396 +1397 +1398 +1399 +1400 +1401 +1402 +1403 +1404 +1405 +1406 +1407 +1408 +1409 +1410 +1411 +1412 +1413 +1414 +1415 +1416 +1417 +1418 +1419 +1420 +1421 +1422 +1423 +1424 +1425 +1426 +1427 +1428 +1429 +1430 +1431 +1432 +1433 +1434 +1435 +1436 +1437 +1438 +1439 +1440 +1441 +1442 +1443 +1444 +1445 +1446 +1447 +1448 +1449 +1450 +1451 +1452 +1453 +1454 +1455 +1456 +1457 +1458 +1459 +1460 +1461 +1462 +1463 +1464 +1465 +1466 +1467 +1468 +1469 +1470 +1471 +1472 +1473 +1474 +1475 +1476 +1477 +1478 +1479 +1480 +1481 +1482 +1483 +1484 +1485 +1486 +1487 +1488 +1489 +1490 +1491 +1492 +1493 +1494 +1495 +1496 +1497 +1498 +1499 +1500 +1501 +1502 +1503 +1504 +1505 +1506 +1507 +1508 +1509 +1510 +1511 +1512 +1513 +1514 +1515 +1516 +1517 +1518 +1519 +1520 +1521 +1522 +1523 +1524 +1525 +1526 +1527 +1528 +1529 +1530 +1531 +1532 +1533 +1534 +1535 +1536 +1537 +1538 +1539 +1540 +1541 +1542 +1543 +1544 +1545 +1546 +1547 +1548 +1549 +1550 +1551 +1552 +1553 +1554 +1555 +1556 +1557 +1558 +1559 +1560 +1561 +1562 +1563 +1564 +1565 +1566 +1567 +1568 +1569 +1570 +1571 +1572 +1573 +1574 +1575 +1576 +1577 +1578 +1579 +1580 +1581 +1582 +1583 +1584 +1585 +1586 +1587 +1588 +1589 +1590 +1591 +1592 +1593 +1594 +1595 +1596 +1597 +1598 +1599 +1600 +1601 +1602 +1603 +1604 +1605 +1606 +1607 +1608 +1609 +1610 +1611 +1612 +1613 +1614 +1615 +1616 +1617 +1618 +1619 +1620 +1621 +1622 +1623 +1624 +1625 +1626 +1627 +1628 +1629 +1630 +1631 +1632 +1633 +1634 +1635 +1636 +1637 +1638 +1639 +1640 +1641 +1642 +1643 +1644 +1645 +1646 +1647 +1648 +1649 +1650 +1651 +1652 +1653 +1654 +1655 +1656 +1657 +1658 +1659 +1660 +1661 +1662 +1663 +1664 +1665 +1666 +1667 +1668 +1669 +1670 +1671 +1672 +1673 +1674 +1675 +1676 +1677 +1678 +1679 +1680 +1681 +1682 +1683 +1684 +1685 +1686 +1687 +1688 +1689 +1690 +1691 +1692 +1693 +1694 +1695 +1696 +1697 +1698 +1699 +1700 +1701 +1702 +1703 +1704 +1705 +1706 +1707 +1708 +1709 +1710 +1711 +1712 +1713 +1714 +1715 +1716 +1717 +1718 +1719 +1720 +1721 +1722 +1723 +1724 +1725 +1726 +1727 +1728 +1729 +1730 +1731 +1732 +1733 +1734 +1735 +1736 +1737 +1738 +1739 +1740 +1741 +1742 +1743 +1744 +1745 +1746 +1747 +1748 +1749 +1750 +1751 +1752 +1753 +1754 +1755 +1756 +1757 +1758 +1759 +1760 +1761 +1762 +1763 +1764 +1765 +1766 +1767 +1768 +1769 +1770 +1771 +1772 +1773 +1774 +1775 +1776 +1777 +1778 +1779 +1780 +1781 +1782 +1783 +1784 +1785 +1786 +1787 +1788 +1789 +1790 +1791 +1792 +1793 +1794 +1795 +1796 +1797 +1798 +1799 +1800 +1801 +1802 +1803 +1804 +1805 +1806 +1807 +1808 +1809 +1810 +1811 +1812 +1813 +1814 +1815 +1816 +1817 +1818 +1819 +1820 +1821 +1822 +1823 +1824 +1825 +1826 +1827 +1828 +1829 +1830 +1831 +1832 +1833 +1834 +1835 +1836 +1837 +1838 +1839 +1840 +1841 +1842 +1843 +1844 +1845 +1846 +1847 +1848 +1849 +1850 +1851 +1852 +1853 +1854 +1855 +1856 +1857 +1858 +1859 +1860 +1861 +1862 +1863 +1864 +1865 +1866 +1867 +1868 +1869 +1870 +1871 +1872 +1873 +1874 +1875 +1876 +1877 +1878 +1879 +1880 +1881 +1882 +1883 +1884 +1885 +1886 +1887 +1888 +1889 +1890 +1891 +1892 +1893 +1894 +1895 +1896 +1897 +1898 +1899 +1900 +1901 +1902 +1903 +1904 +1905 +1906 +1907 +1908 +1909 +1910 +1911 +1912 +1913 +1914 +1915 +1916 +1917 +1918 +1919 +1920 +1921 +1922 +1923 +1924 +1925 +1926 +1927 +1928 +1929 +1930 +1931 +1932 +1933 +1934 +1935 +1936 +1937 +1938 +1939 +1940 +1941 +1942 +1943 +1944 +1945 +1946 +1947 +1948 +1949 +1950 +1951 +1952 +1953 +1954 +1955 +1956 +1957 +1958 +1959 +1960 +1961 +1962 +1963 +1964 +1965 +1966 +1967 +1968 +1969 +1970 +1971 +1972 +1973 +1974 +1975 +1976 +1977 +1978 +1979 +1980 +1981 +1982 +1983 +1984 +1985 +1986 +1987 +1988 +1989 +1990 +1991 +1992 +1993 +1994 +1995 +1996 +1997 +1998 +1999 +2000 +2001 +2002 +2003 +2004 +2005 +2006 +2007 +2008 +2009 +2010 +2011 +2012 +2013 +2014 +2015 +2016 +2017 +2018 +2019 +2020 +2021 +2022 +2023 +2024 +2025 +2026 +2027 +2028 +2029 +2030 +2031 +2032 +2033 +2034 +2035 +2036 +2037 +2038 +2039 +2040 +2041 +2042 +2043 +2044 +2045 +2046 +2047 +2048 +2049 +2050 +2051 +2052 +2053 +2054 +2055 +2056 +2057 +2058 +2059 +2060 +2061 +2062 +2063 +2064 +2065 +2066 +2067 +2068 +2069 +2070 +2071 +2072 +2073 +2074 +2075 +2076 +2077 +2078 +2079 +2080 +2081 +2082 +2083 +2084 +2085 +2086 +2087 +2088 +2089 +2090 +2091 +2092 +2093 +2094 +2095 +2096 +2097 +2098 +2099 +2100 +2101 +2102 +2103 +2104 +2105 +2106 +2107 +2108 +2109 +2110 +2111 +2112 +2113 +2114 +2115 +2116 +2117 +2118 +2119 +2120 +2121 +2122 +2123 +2124 +2125 +2126 +2127 +2128 +2129 +2130 +2131 +2132 +2133 +2134 +2135 +2136 +2137 +2138 +2139 +2140 +2141 +2142 +2143 +2144 +2145 +2146 +2147 +2148 +2149 +2150 +2151 +2152 +2153 +2154 +2155 +2156 +2157 +2158 +2159 +2160 +2161 +2162 +2163 +2164 +2165 +2166 +2167 +2168 +2169 +2170 +2171 +2172 +2173 +2174 +2175 +2176 +2177 +2178 +2179 +2180 +2181 +2182 +2183 +2184 +2185 +2186 +2187 +2188 +2189 +2190 +2191 +2192 +2193 +2194 +2195 +2196 +2197 +2198 +2199 +2200 +2201 +2202 +2203 +2204 +2205 +2206 +2207 +2208 +2209 +2210 +2211 +2212 +2213 +2214 +2215 +2216 +2217 +2218 +2219 +2220 +2221 +2222 +2223 +2224 +2225 +2226 +2227 +2228 +2229 +2230 +2231 +2232 +2233 +2234 +2235 +2236 +2237 +2238 +2239 +2240 +2241 +2242 +2243 +2244 +2245 +2246 +2247 +2248 +2249 +2250 +2251 +2252 +2253 +2254 +2255 +2256 +2257 +2258 +2259 +2260 +2261 +2262 +2263 +2264 +2265 +2266 +2267 +2268 +2269 +2270 +2271 +2272 +2273 +2274 +2275 +2276 +2277 +2278 +2279 +2280 +2281 +2282 +2283 +2284 +2285 +2286 +2287 +2288 +2289 +2290 +2291 +2292 +2293 +2294 +2295 +2296 +2297 +2298 +2299 +2300 +2301 +2302 +2303 +2304 +2305 +2306 +2307 +2308 +2309 +2310 +2311 +2312 +2313 +2314 +2315 +2316 +2317 +2318 +2319 +2320 +2321 +2322 +2323 +2324 +2325 +2326 +2327 +2328 +2329 +2330 +2331 +2332 +2333 +2334 +2335 +2336 +2337 +2338 +2339 +2340 +2341 +2342 +2343 +2344 +2345 +2346 +2347 +2348 +2349 +2350 +2351 +2352 +2353 +2354 +2355 +2356 +2357 +2358 +2359 +2360 +2361 +2362 +2363 +2364 +2365 +2366 +2367 +2368 +2369 +2370 +2371 +2372 +2373 +2374 +2375 +2376 +2377 +2378 +2379 +2380 +2381 +2382 +2383 +2384 +2385 +2386 +2387 +2388 +2389 +2390 +2391 +2392 +2393 +2394 +2395 +2396 +2397 +2398 +2399 +2400 +2401 +2402 +2403 +2404 +2405 +2406 +2407 +2408 +2409 +2410 +2411 +2412 +2413 +2414 +2415 +2416 +2417 +2418 +2419 +2420 +2421 +2422 +2423 +2424 +2425 +2426 +2427 +2428 +2429 +2430 +2431 +2432 +2433 +2434 +2435 +2436 +2437 +2438 +2439 +2440 +2441 +2442 +2443 +2444 +2445 +2446 +2447 +2448 +2449 +2450 +2451 +2452 +2453 +2454 +2455 +2456 +2457 +2458 +2459 +2460 +2461 +2462 +2463 +2464 +2465 +2466 +2467 +2468 +2469 +2470 +2471 +2472 +2473 +2474 +2475 +2476 +2477 +2478 +2479 +2480 +2481 +2482 +2483 +2484 +2485 +2486 +2487 +2488 +2489 +2490 +2491 +2492 +2493 +2494 +2495 +2496 +2497 +2498 +2499 +2500 +2501 +2502 +2503 +2504 +2505 +2506 +2507 +2508 +2509 +2510 +2511 +2512 +2513 +2514 +2515 +2516 +2517 +2518 +2519 +2520 +2521 +2522 +2523 +2524 +2525 +2526 +2527 +2528 +2529 +2530 +2531 +2532 +2533 +2534 +2535 +2536 +2537 +2538 +2539 +2540 +2541 +2542 +2543 +2544 +2545 +2546 +2547 +2548 +2549 +2550 +2551 +2552 +2553 +2554 +2555 +2556 +2557 +2558 +2559 +2560 +2561 +2562 +2563 +2564 +2565 +2566 +2567 +2568 +2569 +2570 +2571 +2572 +2573 +2574 +2575 +2576 +2577 +2578 +2579 +2580 +2581 +2582 +2583 +2584 +2585 +2586 +2587 +2588 +2589 +2590 +2591 +2592 +2593 +2594 +2595 +2596 +2597 +2598 +2599 +2600 +2601 +2602 +2603 +2604 +2605 +2606 +2607 +2608 +2609 +2610 +2611 +2612 +2613 +2614 +2615 +2616 +2617 +2618 +2619 +2620 +2621 +2622 +2623 +2624 +2625 +2626 +2627 +2628 +2629 +2630 +2631 +2632 +2633 +2634 +2635 +2636 +2637 +2638 +2639 +2640 +2641 +2642 +2643 +2644 +2645 +2646 +2647 +2648 +2649 +2650 +2651 +2652 +2653 +2654 +2655 +2656 +2657 +2658 +2659 +2660 +2661 +2662 +2663 +2664 +2665 +2666 +2667 +2668 +2669 +2670 +2671 +2672 +2673 +2674 +2675 +2676 +2677 +2678 +2679 +2680 +2681 +2682 +2683 +2684 +2685 +2686 +2687 +2688 +2689 +2690 +2691 +2692 +2693 +2694 +2695 +2696 +2697 +2698 +2699 +2700 +2701 +2702 +2703 +2704 +2705 +2706 +2707 +2708 +2709 +2710 +2711 +2712 +2713 +2714 +2715 +2716 +2717 +2718 +2719 +2720 +2721 +2722 +2723 +2724 +2725 +2726 +2727 +2728 +2729 +2730 +2731 +2732 +2733 +2734 +2735 +2736 +2737 +2738 +2739 +2740 +2741 +2742 +2743 +2744 +2745 +2746 +2747 +2748 +2749 +2750 +2751 +2752 +2753 +2754 +2755 +2756 +2757 +2758 +2759 +2760 +2761 +2762 +2763 +2764 +2765 +2766 +2767 +2768 +2769 +2770 +2771 +2772 +2773 +2774 +2775 +2776 +2777 +2778 +2779 +2780 +2781 +2782 +2783 +2784 +2785 +2786 +2787 +2788 +2789 +2790 +2791 +2792 +2793 +2794 +2795 +2796 +2797 +2798 +2799 +2800 +2801 +2802 +2803 +2804 +2805 +2806 +2807 +2808 +2809 +2810 +2811 +2812 +2813 +2814 +2815 +2816 +2817 +2818 +2819 +2820 +2821 +2822 +2823 +2824 +2825 +2826 +2827 +2828 +2829 +2830 +2831 +2832 +2833 +2834 +2835 +2836 +2837 +2838 +2839 +2840 +2841 +2842 +2843 +2844 +2845 +2846 +2847 +2848 +2849 +2850 +2851 +2852 +2853 +2854 +2855 +2856 +2857 +2858 +2859 +2860 +2861 +2862 +2863 +2864 +2865 +2866 +2867 +2868 +2869 +2870 +2871 +2872 +2873 +2874 +2875 +2876 +2877 +2878 +2879 +2880 +2881 +2882 +2883 +2884 +2885 +2886 +2887 +2888 +2889 +2890 +2891 +2892 +2893 +2894 +2895 +2896 +2897 +2898 +2899 +2900 +2901 +2902 +2903 +2904 +2905 +2906 +2907 +2908 +2909 +2910 +2911 +2912 +2913 +2914 +2915 +2916 +2917 +2918 +2919 +2920 +2921 +2922 +2923 +2924 +2925 +2926 +2927 +2928 +2929 +2930 +2931 +2932 +2933 +2934 +2935 +2936 +2937 +2938 +2939 +2940 +2941 +2942 +2943 +2944 +2945 +2946 +2947 +2948 +2949 +2950 +2951 +2952 +2953 +2954 +2955 +2956 +2957 +2958 +2959 +2960 +2961 +2962 +2963 +2964 +2965 +2966 +2967 +2968 +2969 +2970 +2971 +2972 +2973 +2974 +2975 +2976 +2977 +2978 +2979 +2980 +2981 +2982 +2983 +2984 +2985 +2986 +2987 +2988 +2989 +2990 +2991 +2992 +2993 +2994 +2995 +2996 +2997 +2998 +2999 +3000 +3001 +3002 +3003 +3004 +3005 +3006 +3007 +3008 +3009 +3010 +3011 +3012 +3013 +3014 +3015 +3016 +3017 +3018 +3019 +3020 +3021 +3022 +3023 +3024 +3025 +3026 +3027 +3028 +3029 +3030 +3031 +3032 +3033 +3034 +3035 +3036 +3037 +3038 +3039 +3040 +3041 +3042 +3043 +3044 +3045 +3046 +3047 +3048 +3049 +3050 +3051 +3052 +3053 +3054 +3055 +3056 +3057 +3058 +3059 +3060 +3061 +3062 +3063 +3064 +3065 +3066 +3067 +3068 +3069 +3070 +3071 +3072 +3073 +3074 +3075 +3076 +3077 +3078 +3079 +3080 +3081 +3082 +3083 +3084 +3085 +3086 +3087 +3088 +3089 +3090 +3091 +3092 +3093 +3094 +3095 +3096 +3097 +3098 +3099 +3100 +3101 +3102 +3103 +3104 +3105 +3106 +3107 +3108 +3109 +3110 +3111 +3112 +3113 +3114 +3115 +3116 +3117 +3118 +3119 +3120 +3121 +3122 +3123 +3124 +3125 +3126 +3127 +3128 +3129 +3130 +3131 +3132 +3133 +3134 +3135 +3136 +3137 +3138 +3139 +3140 +3141 +3142 +3143 +3144 +3145 +3146 +3147 +3148 +3149 +3150 +3151 +3152 +3153 +3154 +3155 +3156 +3157 +3158 +3159 +3160 +3161 +3162 +3163 +3164 +3165 +3166 +3167 +3168 +3169 +3170 +3171 +3172 +3173 +3174 +3175 +3176 +3177 +3178 +3179 +3180 +3181 +3182 +3183 +3184 +3185 +3186 +3187 +3188 +3189 +3190 +3191 +3192 +3193 +3194 +3195 +3196 +3197 +3198 +3199 +3200 +3201 +3202 +3203 +3204 +3205 +3206 +3207 +3208 +3209 +3210 +3211 +3212 +3213 +3214 +3215 +3216 +3217 +3218 +3219 +3220 +3221 +3222 +3223 +3224 +3225 +3226 +3227 +3228 +3229 +3230 +3231 +3232 +3233 +3234 +3235 +3236 +3237 +3238 +3239 +3240 +3241 +3242 +3243 +3244 +3245 +3246 +3247 +3248 +3249 +3250 +3251 +3252 +3253 +3254 +3255 +3256 +3257 +3258 +3259 +3260 +3261 +3262 +3263 +3264 +3265 +3266 +3267 +3268 +3269 +3270 +3271 +3272 +3273 +3274 +3275 +3276 +3277 +3278 +3279 +3280 +3281 +3282 +3283 +3284 +3285 +3286 +3287 +3288 +3289 +3290 +3291 +3292 +3293 +3294 +3295 +3296 +3297 +3298 +3299 +3300 +3301 +3302 +3303 +3304 +3305 +3306 +3307 +3308 +3309 +3310 +3311 +3312 +3313 +3314 +3315 +3316 +3317 +3318 +3319 +3320 +3321 +3322 +3323 +3324 +3325 +3326 +3327 +3328 +3329 +3330 +3331 +3332 +3333 +3334 +3335 +3336 +3337 +3338 +3339 +3340 +3341 +3342 +3343 +3344 +3345 +3346 +3347 +3348 +3349 +3350 +3351 +3352 +3353 +3354 +3355 +3356 +3357 +3358 +3359 +3360 +3361 +3362 +3363 +3364 +3365 +3366 +3367 +3368 +3369 +3370 +3371 +3372 +3373 +3374 +3375 +3376 +3377 +3378 +3379 +3380 +3381 +3382 +3383 +3384 +3385 +3386 +3387 +3388 +3389 +3390 +3391 +3392 +3393 +3394 +3395 +3396 +3397 +3398 +3399 +3400 +3401 +3402 +3403 +3404 +3405 +3406 +3407 +3408 +3409 +3410 +3411 +3412 +3413 +3414 +3415 +3416 +3417 +3418 +3419 +3420 +3421 +3422 +3423 +3424 +3425 +3426 +3427 +3428 +3429 +3430 +3431 +3432 +3433 +3434 +3435 +3436 +3437 +3438 +3439 +3440 +3441 +3442 +3443 +3444 +3445 +3446 +3447 +3448 +3449 +3450 +3451 +3452 +3453 +3454 +3455 +3456 +3457 +3458 +3459 +3460 +3461 +3462 +3463 +3464 +3465 +3466 +3467 +3468 +3469 +3470 +3471 +3472 +3473 +3474 +3475 +3476 +3477 +3478 +3479 +3480 +3481 +3482 +3483 +3484 +3485 +3486 +3487 +3488 +3489 +3490 +3491 +3492 +3493 +3494 +3495 +3496 +3497 +3498 +3499 +3500 +3501 +3502 +3503 +3504 +3505 +3506 +3507 +3508 +3509 +3510 +3511 +3512 +3513 +3514 +3515 +3516 +3517 +3518 +3519 +3520 +3521 +3522 +3523 +3524 +3525 +3526 +3527 +3528 +3529 +3530 +3531 +3532 +3533 +3534 +3535 +3536 +3537 +3538 +3539 +3540 +3541 +3542 +3543 +3544 +3545 +3546 +3547 +3548 +3549 +3550 +3551 +3552 +3553 +3554 +3555 +3556 +3557 +3558 +3559 +3560 +3561 +3562 +3563 +3564 +3565 +3566 +3567 +3568 +3569 +3570 +3571 +3572 +3573 +3574 +3575 +3576 +3577 +3578 +3579 +3580 +3581 +3582 +3583 +3584 +3585 +3586 +3587 +3588 +3589 +3590 +3591 +3592 +3593 +3594 +3595 +3596 +3597 +3598 +3599 +3600 +3601 +3602 +3603 +3604 +3605 +3606 +3607 +3608 +3609 +3610 +3611 +3612 +3613 +3614 +3615 +3616 +3617 +3618 +3619 +3620 +3621 +3622 +3623 +3624 +3625 +3626 +3627 +3628 +3629 +3630 +3631 +3632 +3633 +3634 +3635 +3636 +3637 +3638 +3639 +3640 +3641 +3642 +3643 +3644 +3645 +3646 +3647 +3648 +3649 +3650 +3651 +3652 +3653 +3654 +3655 +3656 +3657 +3658 +3659 +3660 +3661 +3662 +3663 +3664 +3665 +3666 +3667 +3668 +3669 +3670 +3671 +3672 +3673 +3674 +3675 +3676 +3677 +3678 +3679 +3680 +3681 +3682 +3683 +3684 +3685 +3686 +3687 +3688 +3689 +3690 +3691 +3692 +3693 +3694 +3695 +3696 +3697 +3698 +3699 +3700 +3701 +3702 +3703 +3704 +3705 +3706 +3707 +3708 +3709 +3710 +3711 +3712 +3713 +3714 +3715 +3716 +3717 +3718 +3719 +3720 +3721 +3722 +3723 +3724 +3725 +3726 +3727 +3728 +3729 +3730 +3731 +3732 +3733 +3734 +3735 +3736 +3737 +3738 +3739 +3740 +3741 +3742 +3743 +3744 +3745 +3746 +3747 +3748 +3749 +3750 +3751 +3752 +3753 +3754 +3755 +3756 +3757 +3758 +3759 +3760 +3761 +3762 +3763 +3764 +3765 +3766 +3767 +3768 +3769 +3770 +3771 +3772 +3773 +3774 +3775 +3776 +3777 +3778 +3779 +3780 +3781 +3782 +3783 +3784 +3785 +3786 +3787 +3788 +3789 +3790 +3791 +3792 +3793 +3794 +3795 +3796 +3797 +3798 +3799 +3800 +3801 +3802 +3803 +3804 +3805 +3806 +3807 +3808 +3809 +3810 +3811 +3812 +3813 +3814 +3815 +3816 +3817 +3818 +3819 +3820 +3821 +3822 +3823 +3824 +3825 +3826 +3827 +3828 +3829 +3830 +3831 +3832 +3833 +3834 +3835 +3836 +3837 +3838 +3839 +3840 +3841 +3842 +3843 +3844 +3845 +3846 +3847 +3848 +3849 +3850 +3851 +3852 +3853 +3854 +3855 +3856 +3857 +3858 +3859 +3860 +3861 +3862 +3863 +3864 +3865 +3866 +3867 +3868 +3869 +3870 +3871 +3872 +3873 +3874 +3875 +3876 +3877 +3878 +3879 +3880 +3881 +3882 +3883 +3884 +3885 +3886 +3887 +3888 +3889 +3890 +3891 +3892 +3893 +3894 +3895 +3896 +3897 +3898 +3899 +3900 +3901 +3902 +3903 +3904 +3905 +3906 +3907 +3908 +3909 +3910 +3911 +3912 +3913 +3914 +3915 +3916 +3917 +3918 +3919 +3920 +3921 +3922 +3923 +3924 +3925 +3926 +3927 +3928 +3929 +3930 +3931 +3932 +3933 +3934 +3935 +3936 +3937 +3938 +3939 +3940 +3941 +3942 +3943 +3944 +3945 +3946 +3947 +3948 +3949 +3950 +3951 +3952 +3953 +3954 +3955 +3956 +3957 +3958 +3959 +3960 +3961 +3962 +3963 +3964 +3965 +3966 +3967 +3968 +3969 +3970 +3971 +3972 +3973 +3974 +3975 +3976 +3977 +3978 +3979 +3980 +3981 +3982 +3983 +3984 +3985 +3986 +3987 +3988 +3989 +3990 +3991 +3992 +3993 +3994 +3995 +3996 +3997 +3998 +3999 +4000 +4001 +4002 +4003 +4004 +4005 +4006 +4007 +4008 +4009 +4010 +4011 +4012 +4013 +4014 +4015 +4016 +4017 +4018 +4019 +4020 +4021 +4022 +4023 +4024 +4025 +4026 +4027 +4028 +4029 +4030 +4031 +4032 +4033 +4034 +4035 +4036 +4037 +4038 +4039 +4040 +4041 +4042 +4043 +4044 +4045 +4046 +4047 +4048 +4049 +4050 +4051 +4052 +4053 +4054 +4055 +4056 +4057 +4058 +4059 +4060 +4061 +4062 +4063 +4064 +4065 +4066 +4067 +4068 +4069 +4070 +4071 +4072 +4073 +4074 +4075 +4076 +4077 +4078 +4079 +4080 +4081 +4082 +4083 +4084 +4085 +4086 +4087 +4088 +4089 +4090 +4091 +4092 +4093 +4094 +4095 +4096 +4097 +4098 +4099 +4100 +4101 +4102 +4103 +4104 +4105 +4106 +4107 +4108 +4109 +4110 +4111 +4112 +4113 +4114 +4115 +4116 +4117 +4118 +4119 +4120 +4121 +4122 +4123 +4124 +4125 +4126 +4127 +4128 +4129 +4130 +4131 +4132 +4133 +4134 +4135 +4136 +4137 +4138 +4139 +4140 +4141 +4142 +4143 +4144 +4145 +4146 +4147 +4148 +4149 +4150 +4151 +4152 +4153 +4154 +4155 +4156 +4157 +4158 +4159 +4160 +4161 +4162 +4163 +4164 +4165 +4166 +4167 +4168 +4169 +4170 +4171 +4172 +4173 +4174 +4175 +4176 +4177 +4178 +4179 +4180 +4181 +4182 +4183 +4184 +4185 +4186 +4187 +4188 +4189 +4190 +4191 +4192 +4193 +4194 +4195 +4196 +4197 +4198 +4199 +4200 +4201 +4202 +4203 +4204 +4205 +4206 +4207 +4208 +4209 +4210 +4211 +4212 +4213 +4214 +4215 +4216 +4217 +4218 +4219 +4220 +4221 +4222 +4223 +4224 +4225 +4226 +4227 +4228 +4229 +4230 +4231 +4232 +4233 +4234 +4235 +4236 +4237 +4238 +4239 +4240 +4241 +4242 +4243 +4244 +4245 +4246 +4247 +4248 +4249 +4250 +4251 +4252 +4253 +4254 +4255 +4256 +4257 +4258 +4259 +4260 +4261 +4262 +4263 +4264 +4265 +4266 +4267 +4268 +4269 +4270 +4271 +4272 +4273 +4274 +4275 +4276 +4277 +4278 +4279 +4280 +4281 +4282 +4283 +4284 +4285 +4286 +4287 +4288 +4289 +4290 +4291 +4292 +4293 +4294 +4295 +4296 +4297 +4298 +4299 +4300 +4301 +4302 +4303 +4304 +4305 +4306 +4307 +4308 +4309 +4310 +4311 +4312 +4313 +4314 +4315 +4316 +4317 +4318 +4319 +4320 +4321 +4322 +4323 +4324 +4325 +4326 +4327 +4328 +4329 +4330 +4331 +4332 +4333 +4334 +4335 +4336 +4337 +4338 +4339 +4340 +4341 +4342 +4343 +4344 +4345 +4346 +4347 +4348 +4349 +4350 +4351 +4352 +4353 +4354 +4355 +4356 +4357 +4358 +4359 +4360 +4361 +4362 +4363 +4364 +4365 +4366 +4367 +4368 +4369 +4370 +4371 +4372 +4373 +4374 +4375 +4376 +4377 +4378 +4379 +4380 +4381 +4382 +4383 +4384 +4385 +4386 +4387 +4388 +4389 +4390 +4391 +4392 +4393 +4394 +4395 +4396 +4397 +4398 +4399 +4400 +4401 +4402 +4403 +4404 +4405 +4406 +4407 +4408 +4409 +4410 +4411 +4412 +4413 +4414 +4415 +4416 +4417 +4418 +4419 +4420 +4421 +4422 +4423 +4424 +4425 +4426 +4427 +4428 +4429 +4430 +4431 +4432 +4433 +4434 +4435 +4436 +4437 +4438 +4439 +4440 +4441 +4442 +4443 +4444 +4445 +4446 +4447 +4448 +4449 +4450 +4451 +4452 +4453 +4454 +4455 +4456 +4457 +4458 +4459 +4460 +4461 +4462 +4463 +4464 +4465 +4466 +4467 +4468 +4469 +4470 +4471 +4472 +4473 +4474 +4475 +4476 +4477 +4478 +4479 +4480 +4481 +4482 +4483 +4484 +4485 +4486 +4487 +4488 +4489 +4490 +4491 +4492 +4493 +4494 +4495 +4496 +4497 +4498 +4499 +4500 +4501 +4502 +4503 +4504 +4505 +4506 +4507 +4508 +4509 +4510 +4511 +4512 +4513 +4514 +4515 +4516 +4517 +4518 +4519 +4520 +4521 +4522 +4523 +4524 +4525 +4526 +4527 +4528 +4529 +4530 +4531 +4532 +4533 +4534 +4535 +4536 +4537 +4538 +4539 +4540 +4541 +4542 +4543 +4544 +4545 +4546 +4547 +4548 +4549 +4550 +4551 +4552 +4553 +4554 +4555 +4556 +4557 +4558 +4559 +4560 +4561 +4562 +4563 +4564 +4565 +4566 +4567 +4568 +4569 +4570 +4571 +4572 +4573 +4574 +4575 +4576 +4577 +4578 +4579 +4580 +4581 +4582 +4583 +4584 +4585 +4586 +4587 +4588 +4589 +4590 +4591 +4592 +4593 +4594 +4595 +4596 +4597 +4598 +4599 +4600 +4601 +4602 +4603 +4604 +4605 +4606 +4607 +4608 +4609 +4610 +4611 +4612 +4613 +4614 +4615 +4616 +4617 +4618 +4619 +4620 +4621 +4622 +4623 +4624 +4625 +4626 +4627 +4628 +4629 +4630 +4631 +4632 +4633 +4634 +4635 +4636 +4637 +4638 +4639 +4640 +4641 +4642 +4643 +4644 +4645 +4646 +4647 +4648 +4649 +4650 +4651 +4652 +4653 +4654 +4655 +4656 +4657 +4658 +4659 +4660 +4661 +4662 +4663 +4664 +4665 +4666 +4667 +4668 +4669 +4670 +4671 +4672 +4673 +4674 +4675 +4676 +4677 +4678 +4679 +4680 +4681 +4682 +4683 +4684 +4685 +4686 +4687 +4688 +4689 +4690 +4691 +4692 +4693 +4694 +4695 +4696 +4697 +4698 +4699 +4700 +4701 +4702 +4703 +4704 +4705 +4706 +4707 +4708 +4709 +4710 +4711 +4712 +4713 +4714 +4715 +4716 +4717 +4718 +4719 +4720 +4721 +4722 +4723 +4724 +4725 +4726 +4727 +4728 +4729 +4730 +4731 +4732 +4733 +4734 +4735 +4736 +4737 +4738 +4739 +4740 +4741 +4742 +4743 +4744 +4745 +4746 +4747 +4748 +4749 +4750 +4751 +4752 +4753 +4754 +4755 +4756 +4757 +4758 +4759 +4760 +4761 +4762 +4763 +4764 +4765 +4766 +4767 +4768 +4769 +4770 +4771 +4772 +4773 +4774 +4775 +4776 +4777 +4778 +4779 +4780 +4781 +4782 +4783 +4784 +4785 +4786 +4787 +4788 +4789 +4790 +4791 +4792 +4793 +4794 +4795 +4796 +4797 +4798 +4799 +4800 +4801 +4802 +4803 +4804 +4805 +4806 +4807 +4808 +4809 +4810 +4811 +4812 +4813 +4814 +4815 +4816 +4817 +4818 +4819 +4820 +4821 +4822 +4823 +4824 +4825 +4826 +4827 +4828 +4829 +4830 +4831 +4832 +4833 +4834 +4835 +4836 +4837 +4838 +4839 +4840 +4841 +4842 +4843 +4844 +4845 +4846 +4847 +4848 +4849 +4850 +4851 +4852 +4853 +4854 +4855 +4856 +4857 +4858 +4859 +4860 +4861 +4862 +4863 +4864 +4865 +4866 +4867 +4868 +4869 +4870 +4871 +4872 +4873 +4874 +4875 +4876 +4877 +4878 +4879 +4880 +4881 +4882 +4883 +4884 +4885 +4886 +4887 +4888 +4889 +4890 +4891 +4892 +4893 +4894 +4895 +4896 +4897 +4898 +4899 +4900 +4901 +4902 +4903 +4904 +4905 +4906 +4907 +4908 +4909 +4910 +4911 +4912 +4913 +4914 +4915 +4916 +4917 +4918 +4919 +4920 +4921 +4922 +4923 +4924 +4925 +4926 +4927 +4928 +4929 +4930 +4931 +4932 +4933 +4934 +4935 +4936 +4937 +4938 +4939 +4940 +4941 +4942 +4943 +4944 +4945 +4946 +4947 +4948 +4949 +4950 +4951 +4952 +4953 +4954 +4955 +4956 +4957 +4958 +4959 +4960 +4961 +4962 +4963 +4964 +4965 +4966 +4967 +4968 +4969 +4970 +4971 +4972 +4973 +4974 +4975 +4976 +4977 +4978 +4979 +4980 +4981 +4982 +4983 +4984 +4985 +4986 +4987 +4988 +4989 +4990 +4991 +4992 +4993 +4994 +4995 +4996 +4997 +4998 +4999 +5000 diff --git a/mysql-test/t/binlog.test b/mysql-test/t/binlog.test index 5d1399925c3..b35c81b3b18 100644 --- a/mysql-test/t/binlog.test +++ b/mysql-test/t/binlog.test @@ -106,4 +106,21 @@ drop table t1; set global binlog_cache_size=@bcs; set session autocommit = @ac; +# +# Bug#33798: prepared statements improperly handle large unsigned ints +# +--disable_warnings +drop table if exists t1; +--enable_warnings +reset master; +create table t1 (a bigint unsigned, b bigint(20) unsigned); +prepare stmt from "insert into t1 values (?,?)"; +set @a= 9999999999999999; +set @b= 14632475938453979136; +execute stmt using @a, @b; +deallocate prepare stmt; +drop table t1; +--replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/ /Server ver: [^,]*,/Server version,/ +show binlog events from 0; + --echo End of 5.0 tests diff --git a/mysql-test/t/binlog_innodb.test b/mysql-test/t/binlog_innodb.test index 2da7b2b0895..47b09719ef5 100644 --- a/mysql-test/t/binlog_innodb.test +++ b/mysql-test/t/binlog_innodb.test @@ -37,3 +37,28 @@ show status like "binlog_cache_disk_use"; drop table t1; +# +# Bug #30604: different flagging of time_zone_used in normal and ps-protocol +# + +CREATE TABLE t1 (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY) ENGINE=MyISAM; +CREATE TABLE t2 (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB; + +DELIMITER |; +# the function does not deal with time objects +CREATE FUNCTION bug23333() +RETURNS int(11) +DETERMINISTIC +BEGIN + INSERT INTO t1 VALUES (NULL); + SELECT COUNT(*) FROM t1 INTO @a; + RETURN @a; +END| + +DELIMITER ;| + +INSERT INTO t2 VALUES (2),(10+bug23333()); +--replace_column 1 # +SHOW MASTER STATUS; +DROP FUNCTION bug23333; +DROP TABLE t1, t2; diff --git a/mysql-test/t/binlog_start_comment.test b/mysql-test/t/binlog_start_comment.test new file mode 100644 index 00000000000..84889167cd2 --- /dev/null +++ b/mysql-test/t/binlog_start_comment.test @@ -0,0 +1,24 @@ +# Test case for bug#32205 Replaying statements from mysqlbinlog fails +# with a syntax error, replicates fine + +source include/have_log_bin.inc; +source include/have_local_infile.inc; + +reset master; +--disable_warnings +drop table if exists t1,t2; +--enable_warnings +create table t1 (word varchar(20)) -- create table t1; +create table t2 (word varchar(20)) -- create table t2; +load data infile '../std_data_ln/words.dat' into table t1 -- load data to t1; +insert into t2 values ("Ada"); +flush logs; +select * from t2; +--exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ $MYSQLTEST_VARDIR/log/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/binlog_start_comment.binlog +--exec $MYSQL --local-infile=1 < $MYSQLTEST_VARDIR/tmp/binlog_start_comment.binlog +flush logs; +select * from t2; + +# clean up +drop table t1,t2; +#--system rm $MYSQLTEST_VARDIR/tmp/binlog_start_comment.binlog diff --git a/mysql-test/t/blackhole.test b/mysql-test/t/blackhole.test index d8ffdeb8312..ba77b7b7f6a 100644 --- a/mysql-test/t/blackhole.test +++ b/mysql-test/t/blackhole.test @@ -128,6 +128,7 @@ select * from t3; let $VERSION=`select version()`; --replace_result $VERSION VERSION --replace_column 2 # 5 # +--replace_regex /file_id=[0-9]+/file_id=#/ show binlog events; drop table t1,t2,t3; diff --git a/mysql-test/t/compare.test b/mysql-test/t/compare.test index 337035a8095..8863ed825c2 100644 --- a/mysql-test/t/compare.test +++ b/mysql-test/t/compare.test @@ -46,3 +46,34 @@ insert into t1 values (0x01,0x01); select * from t1 where a=b; select * from t1 where a=b and b=0x01; drop table if exists t1; + +# +# Bug #31887: DML Select statement not returning same results when executed +# in version 5 +# + +CREATE TABLE t1 (b int(2) zerofill, c int(2) zerofill); +INSERT INTO t1 (b,c) VALUES (1,2), (1,1), (2,2); + +SELECT CONCAT(b,c), CONCAT(b,c) = '0101' FROM t1; + +EXPLAIN EXTENDED SELECT b,c FROM t1 WHERE b = 1 AND CONCAT(b,c) = '0101'; +SELECT b,c FROM t1 WHERE b = 1 AND CONCAT(b,c) = '0101'; + +CREATE TABLE t2 (a int); +INSERT INTO t2 VALUES (1),(2); + +SELECT a, + (SELECT COUNT(*) FROM t1 + WHERE b = t2.a AND CONCAT(b,c) = CONCAT('0',t2.a,'01')) x +FROM t2 ORDER BY a; + +EXPLAIN EXTENDED +SELECT a, + (SELECT COUNT(*) FROM t1 + WHERE b = t2.a AND CONCAT(b,c) = CONCAT('0',t2.a,'01')) x +FROM t2 ORDER BY a; + +DROP TABLE t1,t2; + +--echo End of 5.0 tests diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test index 84c286e516b..87632fbdbb8 100644 --- a/mysql-test/t/func_gconcat.test +++ b/mysql-test/t/func_gconcat.test @@ -640,4 +640,21 @@ SELECT GROUP_CONCAT(DISTINCT b, a ORDER BY b) FROM t1; DROP TABLE t1, t2, t3; +# +# Bug #34747: crash in debug assertion check after derived table +# +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES (),(); +SELECT s1.d1 FROM +( + SELECT + t1.a as d1, + GROUP_CONCAT(DISTINCT t1.a) AS d2 + FROM + t1 AS t1, + t1 AS t2 + GROUP BY 1 +) AS s1; +DROP TABLE t1; + --echo End of 5.0 tests diff --git a/mysql-test/t/func_misc.test b/mysql-test/t/func_misc.test index ccb59df5677..17c147f7193 100644 --- a/mysql-test/t/func_misc.test +++ b/mysql-test/t/func_misc.test @@ -205,6 +205,24 @@ SELECT NAME_CONST('test', -1.0); SELECT NAME_CONST('test', 'test'); # +# Bug #34749: Server crash when using NAME_CONST() with an aggregate function +# + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2),(3); +# NAME_CONST() + aggregate. +SELECT NAME_CONST('flag',1) * MAX(a) FROM t1; +SELECT NAME_CONST('flag',1.5) * MAX(a) FROM t1; +# Now, wrap the INT_ITEM in Item_func_neg and watch the pretty explosions +SELECT NAME_CONST('flag',-1) * MAX(a) FROM t1; +SELECT NAME_CONST('flag',-1.5) * MAX(a) FROM t1; +--error ER_WRONG_ARGUMENTS +SELECT NAME_CONST('flag', SQRT(4)) * MAX(a) FROM t1; +--error ER_WRONG_ARGUMENTS +SELECT NAME_CONST('flag',-SQRT(4)) * MAX(a) FROM t1; +DROP TABLE t1; + +# # Bug #27545: erroneous usage of NAME_CONST with a name as the first parameter # resolved against a column name of a derived table hangs the client # diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index b0f47e0ad56..ef22adb4251 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -336,7 +336,7 @@ select date_add(date,INTERVAL "1" QUARTER) from t1; select timestampadd(MINUTE, 1, date) from t1; select timestampadd(WEEK, 1, date) from t1; select timestampadd(SQL_TSI_SECOND, 1, date) from t1; -# Prepared statements doesn't support FRAC_SECOND yet +# mysqltest.c discards an expected 'deprecated' warning on prepare stage --disable_ps_protocol select timestampadd(SQL_TSI_FRAC_SECOND, 1, date) from t1; --enable_ps_protocol @@ -351,7 +351,10 @@ select timestampdiff(SQL_TSI_HOUR, '2001-02-01', '2001-05-01') as a; select timestampdiff(SQL_TSI_DAY, '2001-02-01', '2001-05-01') as a; select timestampdiff(SQL_TSI_MINUTE, '2001-02-01 12:59:59', '2001-05-01 12:58:59') as a; select timestampdiff(SQL_TSI_SECOND, '2001-02-01 12:59:59', '2001-05-01 12:58:58') as a; +# mysqltest.c discards an expected 'deprecated' warning on prepare stage +--disable_ps_protocol select timestampdiff(SQL_TSI_FRAC_SECOND, '2001-02-01 12:59:59.120000', '2001-05-01 12:58:58.119999') as a; +--enable_ps_protocol select timestampdiff(SQL_TSI_DAY, '1986-02-01', '1986-03-01') as a1, timestampdiff(SQL_TSI_DAY, '1900-02-01', '1900-03-01') as a2, @@ -804,4 +807,26 @@ select DATE_ADD(20071108, INTERVAL 1 DAY); select LAST_DAY('2007-12-06 08:59:19.05') - INTERVAL 1 SECOND; +# +# Bug#33834: FRAC_SECOND: Applicability not clear in documentation +# +# Show that he use of FRAC_SECOND, for anything other than +# TIMESTAMPADD / TIMESTAMPDIFF, is a server error. + +# mysqltest.c discards an expected 'deprecated' warning on prepare stage +--disable_ps_protocol +SELECT TIMESTAMPADD(FRAC_SECOND, 1, '2008-02-18'); +SELECT TIMESTAMPDIFF(FRAC_SECOND, '2008-02-17', '2008-02-18'); +--enable_ps_protocol + +--error ER_PARSE_ERROR +SELECT DATE_ADD('2008-02-18', INTERVAL 1 FRAC_SECOND); +--error ER_PARSE_ERROR +SELECT DATE_SUB('2008-02-18', INTERVAL 1 FRAC_SECOND); + +--error ER_PARSE_ERROR +SELECT '2008-02-18' + INTERVAL 1 FRAC_SECOND; +--error ER_PARSE_ERROR +SELECT '2008-02-18' - INTERVAL 1 FRAC_SECOND; + --echo End of 5.0 tests diff --git a/mysql-test/t/grant3.test b/mysql-test/t/grant3.test index fac577ef0ff..8eceb851c29 100644 --- a/mysql-test/t/grant3.test +++ b/mysql-test/t/grant3.test @@ -134,3 +134,29 @@ SELECT user, host, db, select_priv FROM mysql.db where user = 'CUser2' order by DROP USER CUser2@localhost; DROP USER CUser2@LOCALHOST; + + +# +# Bug#31194: Privilege ordering does not order properly for wildcard values +# + +CREATE DATABASE mysqltest_1; +CREATE TABLE mysqltest_1.t1 (a INT); +CREATE USER 'mysqltest1'@'%'; +GRANT SELECT, UPDATE ON `mysqltest_1`.* TO 'mysqltest1'@'%'; +REVOKE SELECT ON `mysqltest_1`.* FROM 'mysqltest1'@'%'; +GRANT SELECT, UPDATE ON `mysqltest\_1`.* TO 'mysqltest1'@'%'; +FLUSH PRIVILEGES; + +connect (conn1,localhost,mysqltest1,,); +connection conn1; +SHOW GRANTS; +SELECT * FROM mysqltest_1.t1; +disconnect conn1; + +connection default; +DROP USER 'mysqltest1'@'%'; +DROP DATABASE mysqltest_1; + + +--echo End of 5.0 tests diff --git a/mysql-test/t/innodb_mysql.test b/mysql-test/t/innodb_mysql.test index 020295684b0..59ee7c274bb 100644 --- a/mysql-test/t/innodb_mysql.test +++ b/mysql-test/t/innodb_mysql.test @@ -982,4 +982,18 @@ desc t1; show create table t1; drop table t1; + +# +# Bug #34223: Assertion failed: (optp->var_type & 127) == 8, +# file .\my_getopt.c, line 830 +# + +set @my_innodb_autoextend_increment=@@global.innodb_autoextend_increment; +set global innodb_autoextend_increment=8; +set global innodb_autoextend_increment=@my_innodb_autoextend_increment; + +set @my_innodb_commit_concurrency=@@global.innodb_commit_concurrency; +set global innodb_commit_concurrency=0; +set global innodb_commit_concurrency=@my_innodb_commit_concurrency; + --echo End of 5.0 tests diff --git a/mysql-test/t/limit.test b/mysql-test/t/limit.test index 286c04785ff..9cccca1adc3 100644 --- a/mysql-test/t/limit.test +++ b/mysql-test/t/limit.test @@ -76,15 +76,22 @@ drop table t1; # Bug #28464: a string argument to 'limit ?' PS # -prepare s from "select 1 limit ?"; -set @a='qwe'; ---error 1210 +prepare s from "select 1 limit ?"; +set @a='qwe'; +execute s using @a; +set @a=-1; +--error ER_WRONG_ARGUMENTS execute s using @a; prepare s from "select 1 limit 1, ?"; ---error 1210 +--error ER_WRONG_ARGUMENTS execute s using @a; prepare s from "select 1 limit ?, ?"; ---error 1210 +--error ER_WRONG_ARGUMENTS +execute s using @a, @a; +set @a=14632475938453979136; +execute s using @a, @a; +set @a=-14632475938453979136; +--error ER_WRONG_ARGUMENTS execute s using @a, @a; --echo End of 5.0 tests diff --git a/mysql-test/t/mix_innodb_myisam_binlog.test b/mysql-test/t/mix_innodb_myisam_binlog.test index e0ce802254a..8ab639661b8 100644 --- a/mysql-test/t/mix_innodb_myisam_binlog.test +++ b/mysql-test/t/mix_innodb_myisam_binlog.test @@ -262,7 +262,8 @@ eval select is not null; --replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR eval select -@a like "%#%error_code=0%ROLLBACK/*!*/;%ROLLBACK /* added by mysqlbinlog */;%", +@a like "%#%error_code=0%ROLLBACK\\n/*!*/;%ROLLBACK /* added by mysqlbinlog */;%" OR +@a like "%#%error_code=0%ROLLBACK\\r\\n/*!*/;%ROLLBACK /* added by mysqlbinlog */;%", @a not like "%#%error_code=%error_code=%"; drop table t1, t2; diff --git a/mysql-test/t/mysqlbinlog.test b/mysql-test/t/mysqlbinlog.test index c83fe94f2eb..5b4a43c8fe8 100644 --- a/mysql-test/t/mysqlbinlog.test +++ b/mysql-test/t/mysqlbinlog.test @@ -41,6 +41,7 @@ select "--- Local --" as ""; # --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/ --exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ $MYSQLTEST_VARDIR/log/master-bin.000001 # this should not fail but shouldn't produce any working statements @@ -48,6 +49,7 @@ select "--- Local --" as ""; select "--- Broken LOAD DATA --" as ""; --enable_query_log --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/ --exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ $MYSQLTEST_VARDIR/log/master-bin.000002 2> /dev/null # this should show almost nothing @@ -55,6 +57,7 @@ select "--- Broken LOAD DATA --" as ""; select "--- --database --" as ""; --enable_query_log --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/ --exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --database=nottest $MYSQLTEST_VARDIR/log/master-bin.000001 2> /dev/null # this test for position option @@ -62,6 +65,7 @@ select "--- --database --" as ""; select "--- --position --" as ""; --enable_query_log --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/ --exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --position=231 $MYSQLTEST_VARDIR/log/master-bin.000002 # These are tests for remote binlog. @@ -73,6 +77,7 @@ select "--- Remote --" as ""; # This is broken now --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/ --exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 # This is broken too @@ -80,6 +85,7 @@ select "--- Remote --" as ""; select "--- Broken LOAD DATA --" as ""; --enable_query_log --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/ --exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000002 2> /dev/null # And this too ! (altough it is documented) @@ -87,6 +93,7 @@ select "--- Broken LOAD DATA --" as ""; select "--- --database --" as ""; --enable_query_log --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/ --exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT --database=nottest master-bin.000001 2> /dev/null # Strangely but this works @@ -94,6 +101,7 @@ select "--- --database --" as ""; select "--- --position --" as ""; --enable_query_log --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/ --exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --read-from-remote-server --position=231 --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000002 # Bug#7853 (mysqlbinlog does not accept input from stdin) @@ -101,9 +109,11 @@ select "--- --position --" as ""; select "--- reading stdin --" as ""; --enable_query_log --replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR +--replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/ --exec $MYSQL_BINLOG --short-form - < $MYSQL_TEST_DIR/std_data/trunc_binlog.000001 --replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR +--replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/ --exec $MYSQL_BINLOG --short-form --position=79 - < $MYSQL_TEST_DIR/std_data/trunc_binlog.000001 drop table t1,t2; @@ -166,6 +176,7 @@ call p1(); drop procedure p1; --error 1305 call p1(); +--replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/ --exec $MYSQL_BINLOG --short-form $MYSQLTEST_VARDIR/log/master-bin.000007 --exec $MYSQL_BINLOG --short-form $MYSQLTEST_VARDIR/log/master-bin.000007 | $MYSQL call p1(); @@ -201,6 +212,7 @@ select hex(a) from t1; drop table t1; flush logs; --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/ --exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ $MYSQLTEST_VARDIR/log/master-bin.000009 # diff --git a/mysql-test/t/mysqlcheck.test b/mysql-test/t/mysqlcheck.test index 04e7b6b4bdb..8d5e1a1c4c5 100644 --- a/mysql-test/t/mysqlcheck.test +++ b/mysql-test/t/mysqlcheck.test @@ -40,4 +40,22 @@ create table `t 1`(a int); --exec $MYSQL_CHECK --databases test drop table `t``1`, `t 1`; +# +# Bug#25347: mysqlcheck -A -r doesn't repair table marked as crashed +# +create database d_bug25347; +use d_bug25347; +create table t_bug25347 (a int); +create view v_bug25347 as select * from t_bug25347; +flush tables; +--echo removing and creating +--remove_file $MYSQLTEST_VARDIR/master-data/d_bug25347/t_bug25347.MYI +--write_file $MYSQLTEST_VARDIR/master-data/d_bug25347/t_bug25347.MYI +EOF +--exec $MYSQL_CHECK --repair --databases --use-frm d_bug25347 +drop view v_bug25347; +drop table t_bug25347; +drop database d_bug25347; +use test; + --echo End of 5.0 tests diff --git a/mysql-test/t/mysqldump-no-binlog-master.opt b/mysql-test/t/mysqldump-no-binlog-master.opt new file mode 100644 index 00000000000..789275fa25e --- /dev/null +++ b/mysql-test/t/mysqldump-no-binlog-master.opt @@ -0,0 +1 @@ +--skip-log-bin diff --git a/mysql-test/t/mysqldump-no-binlog.test b/mysql-test/t/mysqldump-no-binlog.test new file mode 100644 index 00000000000..434b2931792 --- /dev/null +++ b/mysql-test/t/mysqldump-no-binlog.test @@ -0,0 +1,6 @@ +# Embedded server doesn't support external clients +--source include/not_embedded.inc + +--replace_regex /MASTER_LOG_POS=[0-9]+/XX/ +--error 2 +--exec $MYSQL_DUMP --compact --master-data=2 test 2>&1 diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test index ec188af0244..5856bfff036 100644 --- a/mysql-test/t/mysqltest.test +++ b/mysql-test/t/mysqltest.test @@ -2083,5 +2083,46 @@ eval $show_statement; drop table t1; +# ---------------------------------------------------------------------------- +# Test change_user command +# ---------------------------------------------------------------------------- + +--error 1 +--exec echo "--change_user root,,inexistent" | $MYSQL_TEST 2>&1 + +--error 1 +--exec echo "--change_user inexistent,,test" | $MYSQL_TEST 2>&1 + +--error 1 +--exec echo "--change_user root,inexistent,test" | $MYSQL_TEST 2>&1 + +--change_user +--change_user root +--change_user root,, +--change_user root,,test + +# ---------------------------------------------------------------------------- +# Test mkdir and rmdir command +# ---------------------------------------------------------------------------- + +mkdir $MYSQLTEST_VARDIR/tmp/testdir; +rmdir $MYSQLTEST_VARDIR/tmp/testdir; + +# Directory already exist +mkdir $MYSQLTEST_VARDIR/tmp/testdir; +--error 1 +mkdir $MYSQLTEST_VARDIR/tmp/testdir; + +# Remove dir with file inside +write_file $MYSQLTEST_VARDIR/tmp/testdir/file1.txt; +hello +EOF +--error 1 +rmdir $MYSQLTEST_VARDIR/tmp/testdir; + +remove_file $MYSQLTEST_VARDIR/tmp/testdir/file1.txt; +rmdir $MYSQLTEST_VARDIR/tmp/testdir; + + --echo End of tests diff --git a/mysql-test/t/ndb_alter_table2.test b/mysql-test/t/ndb_alter_table2.test index 3861fcc6c9d..99c201f7370 100644 --- a/mysql-test/t/ndb_alter_table2.test +++ b/mysql-test/t/ndb_alter_table2.test @@ -81,3 +81,34 @@ select * from t1; select * from t1; drop table t1; + +#For BUG#29851 TRUNCATE causes error 4350 from cluster in INSERT... ON DUPLICATE KEY UPDATE + +connection con1; + +--disable_warnings +DROP TABLE IF EXISTS truncate_test; +--enable_warnings + +CREATE TABLE truncate_test ( + i INT PRIMARY KEY, + a INT, + b VARCHAR(11), + UNIQUE KEY (a) +) ENGINE = NDB; + +INSERT INTO truncate_test VALUES (1, 1, 'test') ON DUPLICATE KEY UPDATE b = 'new'; +INSERT INTO truncate_test VALUES (1, 1, 'test') ON DUPLICATE KEY UPDATE b = 'new'; + +connection con2; +TRUNCATE truncate_test; + +connection con1; +INSERT INTO truncate_test VALUES (1, 1, 'test') ON DUPLICATE KEY UPDATE b = 'new'; +SELECT * FROM truncate_test; + +connection con2; +INSERT INTO truncate_test VALUES (1, 1, 'test') ON DUPLICATE KEY UPDATE b = 'new'; +SELECT * FROM truncate_test; + +DROP TABLE truncate_test; diff --git a/mysql-test/t/ndb_autodiscover.test b/mysql-test/t/ndb_autodiscover.test index 6eb039c2df2..049dcd9755e 100644 --- a/mysql-test/t/ndb_autodiscover.test +++ b/mysql-test/t/ndb_autodiscover.test @@ -491,6 +491,7 @@ select * from t1; select * from t1; --exec $NDB_MGM --no-defaults -e "all start" > /dev/null --exec $NDB_TOOLS_DIR/ndb_waiter --no-defaults > /dev/null +--source include/ndb_wait_connected.inc use test; drop database test_only_ndb_tables; diff --git a/mysql-test/t/ndb_autodiscover3.test b/mysql-test/t/ndb_autodiscover3.test index 259da6e3501..4a20e7dd430 100644 --- a/mysql-test/t/ndb_autodiscover3.test +++ b/mysql-test/t/ndb_autodiscover3.test @@ -25,6 +25,13 @@ insert into t1 values (1); --exec $NDB_MGM --no-defaults -e "all restart" >> $NDB_TOOLS_OUTPUT --exec $NDB_TOOLS_DIR/ndb_waiter --no-defaults -c $connect_str >> $NDB_TOOLS_OUTPUT +# Create separate connection and use that for detecting +# when mysqld has reconnected to ndbd +connect (ndb_wait_con,127.0.0.1,root,,test,$MASTER_MYPORT,); +--source include/ndb_wait_connected.inc +disconnect ndb_wait_con; +connection server1; + --error 1297 insert into t1 values (2); --error 1296 @@ -44,6 +51,7 @@ select * from t2 order by a limit 3; --exec $NDB_TOOLS_DIR/ndb_waiter --no-defaults -c $connect_str >> $NDB_TOOLS_OUTPUT --connection server2 +--source include/ndb_wait_connected.inc create table t2 (a int key) engine=ndbcluster; insert into t2 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); select * from t2 order by a limit 3; @@ -58,6 +66,7 @@ select * from t2 order by a limit 3; --exec $NDB_TOOLS_DIR/ndb_waiter --no-defaults -c $connect_str >> $NDB_TOOLS_OUTPUT --connection server1 +--source include/ndb_wait_connected.inc show tables; create table t2 (a int key) engine=ndbcluster; insert into t2 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); diff --git a/mysql-test/t/ndb_bug31477.test b/mysql-test/t/ndb_bug31477.test new file mode 100644 index 00000000000..41c519e56fd --- /dev/null +++ b/mysql-test/t/ndb_bug31477.test @@ -0,0 +1,109 @@ +--source include/have_ndb.inc + +--disable_warnings +drop table if exists t1; +--enable_warnings + +# setup + +connect (con1,localhost,root,,test); +connect (con2,localhost,root,,test); + +# unique index +connection con1; +create table t1(a int primary key, b int, c int, unique(b)) engine = ndb; +insert into t1 values (2,2,2); +insert into t1 values (3,3,3); +insert into t1 values (4,4,4); + +begin; +insert into t1 values (1,1,1); + +connection con2; +begin; +--error 1205 +update t1 set c = 2 where b = 1; +rollback; + +connection con1; +rollback; +drop table t1; +# ordered index + +connection con1; +create table t1(a int primary key, b int, c int, key(b)) engine = ndb; +insert into t1 values (2,2,2); +insert into t1 values (3,3,3); +insert into t1 values (4,4,4); + +begin; +insert into t1 values (1,1,1); + +connection con2; +begin; +--error 1205 +update t1 set c = 2 where b = 1; +rollback; + +connection con1; +rollback; +drop table t1; + +# multiple versions + +--echo --con1 +connection con1; +create table t1(a int primary key, b int, c int, key(b)) engine = ndb; +insert into t1 values (1,1,1); +insert into t1 values (2,2,2); +insert into t1 values (3,3,3); +insert into t1 values (4,4,4); + +begin; +update t1 set c = 10 where a = 1; +update t1 set c = 20 where a = 1; +update t1 set c = 30 where a = 1; + +--echo --con1 c=30 +select * from t1 where b >= 1 order by b; +--echo --con2 c=1 +connection con2; +select * from t1 where b >= 1 order by b; + +--echo --con1 +connection con1; +delete from t1 where a = 1; + +--echo --con1 c=none +select * from t1 where b >= 1 order by b; +--echo --con2 c=1 +connection con2; +select * from t1 where b >= 1 order by b; + +--echo --con1 +connection con1; +commit; + +--echo --con1 c=none +select * from t1 where b >= 1 order by b; +--echo --con2 c=none +connection con2; +select * from t1 where b >= 1 order by b; + +--echo --con1 +connection con1; +begin; +insert into t1 values (1,1,1); +update t1 set c = 10 where a = 1; +update t1 set c = 20 where a = 1; +update t1 set c = 30 where a = 1; + +--echo --con1 c=30 +select * from t1 where b >= 1 order by b; +--echo --con2 c=none +connection con2; +select * from t1 where b >= 1 order by b; + +# this fails with "no such table" via con2 ??? +connection con1; +drop table t1; diff --git a/mysql-test/t/ndb_condition_pushdown.test b/mysql-test/t/ndb_condition_pushdown.test index b5b7e41fb21..ebfd9c7231a 100644 --- a/mysql-test/t/ndb_condition_pushdown.test +++ b/mysql-test/t/ndb_condition_pushdown.test @@ -1719,6 +1719,7 @@ set engine_condition_pushdown = 1; SELECT fname, lname FROM t1 WHERE (fname like 'Y%') or (lname like 'F%'); # bug#29390 (scan filter is too large, discarded) +# bug#34107 (previous limit was too large for TUP) drop table t1; @@ -1737,9 +1738,11 @@ select a,b,d from t1 where b in (0,1,2,5) order by b; +--echo -- big filter just below limit --disable_query_log select a,b,d from t1 where b in ( +0,1,2,5,0,1,2,5,0,1, 0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, 0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, 0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, @@ -1870,745 +1873,15 @@ select a,b,d from t1 0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, 0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, 0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, -0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, +0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2) + order by b; +--enable_query_log + +--echo -- big filter just above limit +--disable_query_log +select a,b,d from t1 + where b in ( +0,1,2,5,0,1,2,5,0,1,2, 0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, 0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, 0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2,5,0,1,2, diff --git a/mysql-test/t/ndb_restore.test b/mysql-test/t/ndb_restore.test index 266a0c7fbc1..940b53adbe1 100644 --- a/mysql-test/t/ndb_restore.test +++ b/mysql-test/t/ndb_restore.test @@ -231,16 +231,21 @@ select count(*) select * from t10_c order by a; # Bug #27775 cont'd # - auto inc info should be correct ---replace_column 1 X 2 X 3 X 4 X 5 X 6 X 7 X 8 X 9 X 10 X 12 X 13 X 14 X 15 X 16 X 17 X 18 X -show table status like 't1_c'; ---replace_column 1 X 2 X 3 X 4 X 5 X 6 X 7 X 8 X 9 X 10 X 12 X 13 X 14 X 15 X 16 X 17 X 18 X -show table status like 't2_c'; ---replace_column 1 X 2 X 3 X 4 X 5 X 6 X 7 X 8 X 9 X 10 X 12 X 13 X 14 X 15 X 16 X 17 X 18 X -show table status like 't4_c'; ---replace_column 1 X 2 X 3 X 4 X 5 X 6 X 7 X 8 X 9 X 10 X 12 X 13 X 14 X 15 X 16 X 17 X 18 X -show table status like 't7_c'; ---replace_column 1 X 2 X 3 X 4 X 5 X 6 X 7 X 8 X 9 X 10 X 12 X 13 X 14 X 15 X 16 X 17 X 18 X -show table status like 't10_c'; +select max(capgoaledatta) from t1_c; +select auto_increment from information_schema.tables +where table_name = 't1_c'; +select max(capgotod) from t2_c; +select auto_increment from information_schema.tables +where table_name = 't2_c'; +select max(capfa) from t4_c; +select auto_increment from information_schema.tables +where table_name = 't4_c'; +select max(dardtestard) from t7_c; +select auto_increment from information_schema.tables +where table_name = 't7_c'; +select max(a) from t10_c; +select auto_increment from information_schema.tables +where table_name = 't10_c'; --disable_warnings drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9, t10; diff --git a/mysql-test/t/null_key.test b/mysql-test/t/null_key.test index e15aec01d2a..1400c643203 100644 --- a/mysql-test/t/null_key.test +++ b/mysql-test/t/null_key.test @@ -240,3 +240,26 @@ SHOW STATUS LIKE "handler_read%"; DROP TABLE t1,t2,t3,t4; # End of 4.1 tests + +# +# BUG#34945 "ref_or_null queries that are null_rejecting and have a null value crash mysql" +# +CREATE TABLE t1 ( + a int(11) default NULL, + b int(11) default NULL, + KEY a (a,b) +); +INSERT INTO t1 VALUES (0,10),(0,11),(0,12); + +CREATE TABLE t2 ( + a int(11) default NULL, + b int(11) default NULL, + KEY a (a) +); +INSERT INTO t2 VALUES (3,NULL),(3,11),(3,12); + +SELECT * FROM t2 inner join t1 WHERE ( t1.a = 0 OR t1.a IS NULL) AND t2.a = 3 AND t2.b = t1.b; + +drop table t1, t2; +-- echo End of 5.0 tests + diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test index 29a290c7fbf..9a55c27df99 100644 --- a/mysql-test/t/order_by.test +++ b/mysql-test/t/order_by.test @@ -726,3 +726,15 @@ SELECT a, b FROM t1 ORDER BY b DESC; SELECT a, b FROM t1 ORDER BY SEC_TO_TIME(a) DESC; DROP TABLE t1; + +--echo # +--echo # Bug#31590: Wrong error message on sort buffer being too small. +--echo # +create table t1(a int, b tinytext); +insert into t1 values (1,2),(3,2); +set session sort_buffer_size= 30000; +set session max_sort_length= 2180; +--error 1038 +select * from t1 order by b; +drop table t1; + diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index c1505ffd645..6c3f98f6a1a 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -1807,4 +1807,163 @@ execute stmt using @a; show create table t1; drop table t1; +# +# Bug#33798: prepared statements improperly handle large unsigned ints +# +--disable_warnings +drop table if exists t1; +--enable_warnings +create table t1 (a bigint unsigned, b bigint(20) unsigned); +prepare stmt from "insert into t1 values (?,?)"; +set @a= 9999999999999999; +set @b= 14632475938453979136; +insert into t1 values (@a, @b); +select * from t1 where a = @a and b = @b; +execute stmt using @a, @b; +select * from t1 where a = @a and b = @b; +deallocate prepare stmt; +drop table t1; + +# +# Bug#32890 Crash after repeated create and drop of tables and views +# + +--disable_warnings +drop view if exists v1; +drop table if exists t1; +--enable_warnings + +create table t1 (a int, b int); +insert into t1 values (1,1), (2,2), (3,3); +insert into t1 values (3,1), (1,2), (2,3); + +prepare stmt from "create view v1 as select * from t1"; +execute stmt; +drop table t1; +create table t1 (a int, b int); +drop view v1; +execute stmt; +show create view v1; +drop view v1; + +prepare stmt from "create view v1 (c,d) as select a,b from t1"; +execute stmt; +show create view v1; +select * from v1; +drop view v1; +execute stmt; +deallocate prepare stmt; +show create view v1; +select * from v1; +drop view v1; + +prepare stmt from "create view v1 (c) as select b+1 from t1"; +execute stmt; +show create view v1; +select * from v1; +drop view v1; +execute stmt; +deallocate prepare stmt; +show create view v1; +select * from v1; +drop view v1; + +prepare stmt from "create view v1 (c,d,e,f) as select a,b,a in (select a+2 from t1), a = all (select a from t1) from t1"; +execute stmt; +show create view v1; +select * from v1; +drop view v1; +execute stmt; +deallocate prepare stmt; +show create view v1; +select * from v1; +drop view v1; + +prepare stmt from "create or replace view v1 as select 1"; +execute stmt; +show create view v1; +select * from v1; +execute stmt; +show create view v1; +deallocate prepare stmt; +show create view v1; +select * from v1; +drop view v1; + +prepare stmt from "create view v1 as select 1, 1"; +execute stmt; +show create view v1; +select * from v1; +drop view v1; +execute stmt; +deallocate prepare stmt; +show create view v1; +select * from v1; +drop view v1; + +prepare stmt from "create view v1 (x) as select a from t1 where a > 1"; +execute stmt; +show create view v1; +select * from v1; +drop view v1; +execute stmt; +deallocate prepare stmt; +show create view v1; +select * from v1; +drop view v1; + +prepare stmt from "create view v1 as select * from `t1` `b`"; +execute stmt; +show create view v1; +select * from v1; +drop view v1; +execute stmt; +deallocate prepare stmt; +show create view v1; +select * from v1; +drop view v1; + +prepare stmt from "create view v1 (a,b,c) as select * from t1"; +--error ER_VIEW_WRONG_LIST +execute stmt; +--error ER_VIEW_WRONG_LIST +execute stmt; +deallocate prepare stmt; + +drop table t1; +create temporary table t1 (a int, b int); + +prepare stmt from "create view v1 as select * from t1"; +--error ER_VIEW_SELECT_TMPTABLE +execute stmt; +--error ER_VIEW_SELECT_TMPTABLE +execute stmt; +deallocate prepare stmt; + +drop table t1; + +--error ER_NO_SUCH_TABLE +prepare stmt from "create view v1 as select * from t1"; +--error ER_NO_SUCH_TABLE +prepare stmt from "create view v1 as select * from `t1` `b`"; + +# +# Bug#33851: Passing UNSIGNED param to EXECUTE returns ERROR 1210 +# + +prepare stmt from "select ?"; +set @arg= 123456789.987654321; +select @arg; +execute stmt using @arg; +set @arg= "string"; +select @arg; +execute stmt using @arg; +set @arg= 123456; +select @arg; +execute stmt using @arg; +set @arg= cast(-12345.54321 as decimal(20, 10)); +select @arg; +execute stmt using @arg; +deallocate prepare stmt; + --echo End of 5.0 tests. diff --git a/mysql-test/t/range.test b/mysql-test/t/range.test index 95e0d31ff8f..cdbedb1f848 100644 --- a/mysql-test/t/range.test +++ b/mysql-test/t/range.test @@ -955,6 +955,22 @@ explain select * from t1 where dateval >= '2007-01-01 00:00:00' and dateval <= ' drop table t1; +# +# Bug #33833: different or-ed predicates were erroneously merged into one that +# resulted in ref access instead of range access and a wrong result set +# + +CREATE TABLE t1 ( + a varchar(32), index (a) +) DEFAULT CHARSET=latin1 COLLATE=latin1_bin; + +INSERT INTO t1 VALUES + ('B'), ('A'), ('A'), ('C'), ('B'), ('A'), ('A'); + +SELECT a FROM t1 WHERE a='b' OR a='B'; +EXPLAIN SELECT a FROM t1 WHERE a='b' OR a='B'; + +DROP TABLE t1; # # Bug #34731: highest possible value for INT erroneously filtered by WHERE diff --git a/mysql-test/t/row.test b/mysql-test/t/row.test index 20d044306a6..1601f7afd0e 100644 --- a/mysql-test/t/row.test +++ b/mysql-test/t/row.test @@ -224,3 +224,16 @@ SET @x:= (SELECT h FROM t1 WHERE (a,b,c,d,e,f,g)=(1,2,3,4,5,6,7)); SELECT @x; DROP TABLE t1; + +# +# Bug #34620: item_row.cc:50: Item_row::illegal_method_call(const char*): +# Assertion `0' failed +# + +CREATE TABLE t1 (a INT, b INT); +INSERT INTO t1 VALUES (1,1); + +SELECT ROW(a, 1) IN (SELECT SUM(b), 1) FROM t1 GROUP BY a; +SELECT ROW(a, 1) IN (SELECT SUM(b), 3) FROM t1 GROUP BY a; + +DROP TABLE t1; diff --git a/mysql-test/t/rpl_drop_view.test b/mysql-test/t/rpl_drop_view.test new file mode 100644 index 00000000000..8d826b8214d --- /dev/null +++ b/mysql-test/t/rpl_drop_view.test @@ -0,0 +1,31 @@ +# test case for bug#30998 +# Drop View breaks replication if view does not exist +# + +source include/master-slave.inc; +--disable_warnings +drop table if exists t1, t2; +drop view if exists v1, v2, v3, not_exist_view; +--enable_warnings +create table t1 (a int); +create table t2 (b int); +create table t3 (c int); +create view v1 as select * from t1; +create view v2 as select * from t2; +create view v3 as select * from t3; +--error 1051 +drop view not_exist_view; +--error 1051 +drop view v1, not_exist_view; +--error 1146 +select * from v1; +drop view v2, v3; +save_master_pos; +connection slave; +sync_with_master; +--error 1146 +select * from v1; +--error 1146 +select * from v2; +--error 1146 +select * from v3; diff --git a/mysql-test/t/rpl_loaddata_map-master.opt b/mysql-test/t/rpl_loaddata_map-master.opt new file mode 100644 index 00000000000..f3c797b19c8 --- /dev/null +++ b/mysql-test/t/rpl_loaddata_map-master.opt @@ -0,0 +1 @@ +--read_buffer_size=9K --max_allowed_packet=8K diff --git a/mysql-test/t/rpl_loaddata_map-slave.opt b/mysql-test/t/rpl_loaddata_map-slave.opt new file mode 100644 index 00000000000..95f55bcf7d8 --- /dev/null +++ b/mysql-test/t/rpl_loaddata_map-slave.opt @@ -0,0 +1 @@ +--max_allowed_packet=8K diff --git a/mysql-test/t/rpl_loaddata_map.test b/mysql-test/t/rpl_loaddata_map.test new file mode 100644 index 00000000000..0a2883bfcca --- /dev/null +++ b/mysql-test/t/rpl_loaddata_map.test @@ -0,0 +1,52 @@ +# +# check replication of load data with the server parameters subjected to +# read_buffer_size > max_allowed_packet +# +# BUG#30435 loading large LOAD DATA INFILE breaks slave with +# read_buffer_size set on master +# BUG#33413 show binlog events fails if binlog has event size of close +# to max_allowed_packet + +source include/master-slave.inc; +source include/have_innodb.inc; + +--disable_query_log +let $rows= 5000; +create table t1 (id int not null primary key auto_increment); + +while($rows) +{ + eval insert into t1 values (null); + dec $rows; +} +eval select * into outfile '$MYSQLTEST_VARDIR/tmp/bug30435_5k.txt' from t1; +flush logs; +--enable_query_log + +connection master; +create table t2 (id int not null primary key auto_increment); + +select @@session.read_buffer_size - @@session.max_allowed_packet > 0 ; + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +eval load data infile '$MYSQLTEST_VARDIR/tmp/bug30435_5k.txt' into table t2; +select count(*) from t2 /* 5 000 */; + +# the binglog will show fragmented Append_block events +--let $binlog_start=98 +--replace_column 5 # +--replace_regex /\/\* xid=.* \*\//\/* XID *\// /file_id=[0-9]+/file_id=#/ +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--eval show binlog events in 'master-bin.000002' from $binlog_start + + +sync_slave_with_master; +#connection slave; +select count(*) from t2 /* 5 000 */; + +connection master; +drop table t1, t2; +sync_slave_with_master; +remove_file $MYSQLTEST_VARDIR/tmp/bug30435_5k.txt; + +--echo end of the tests diff --git a/mysql-test/t/rpl_server_id.test b/mysql-test/t/rpl_server_id.test new file mode 100644 index 00000000000..6e98ec6ee6d --- /dev/null +++ b/mysql-test/t/rpl_server_id.test @@ -0,0 +1,29 @@ +# Test for BUG#28908 Replication: set global server_id is not setting the session server_id + +-- source include/have_log_bin.inc + +let $saved_server_id=`select @@server_id`; +set global server_id=1; +reset master; + +-- disable_warnings +drop table if exists t1,t2,t3; +-- enable_warnings + +create table t1 (a int); +select @@server_id; +source include/show_binlog_events2.inc; + +set global server_id=2; +create table t2 (b int); +select @@server_id; +source include/show_binlog_events2.inc; + +set global server_id=3; +create table t3 (c int); +select @@server_id; +source include/show_binlog_events2.inc; + +# cleanup +eval set global server_id=$saved_server_id; +drop table t1,t2,t3; diff --git a/mysql-test/t/rpl_slave_skip.test b/mysql-test/t/rpl_slave_skip.test index 04aafc51129..71e951aceea 100644 --- a/mysql-test/t/rpl_slave_skip.test +++ b/mysql-test/t/rpl_slave_skip.test @@ -13,8 +13,10 @@ source include/master-slave.inc; # it back to get the non-transactional change into the table. --echo **** On Master **** -CREATE TABLE t1 (a INT, b SET('master','slave')) ENGINE=INNODB; -CREATE TABLE t2 (a INT, b SET('master','slave')) ENGINE=MYISAM; +CREATE TABLE t1 (a INT, b SET('master','slave')) ENGINE=InnoDB; +CREATE TABLE t2 (a INT, b SET('master','slave')) ENGINE=MyISAM; +CREATE TABLE t3 (a CHAR(20), b SET('master','slave')) ENGINE=InnoDB; +CREATE TABLE t4 (a CHAR(20), b SET('master','slave')) ENGINE=MyISAM; --echo ==== Skipping normal transactions ==== @@ -195,9 +197,170 @@ sync_with_master; SELECT * FROM t1 ORDER BY a; SELECT * FROM t2 ORDER BY a; +--echo ==== Skipping first event of a LOAD DATA for a transactional table ==== + +--echo **** On Slave **** +connection slave; +STOP SLAVE; +source include/wait_for_slave_to_stop.inc; + +--echo **** On Master **** +connection master; +SET AUTOCOMMIT=1; + +LOAD DATA INFILE '../std_data_ln/words.dat' INTO TABLE t3(a) SET b = 'master'; +INSERT INTO t3 VALUES ('Go Rin No Sho', 'master,slave'); + +save_master_pos; + +SELECT COUNT(*) FROM t3; + +# This will skip a begin event and the first INSERT of the +# transaction, and it should keep skipping until it has reached the +# transaction terminator. + +--echo **** On Slave **** +connection slave; +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; +START SLAVE; +source include/wait_for_slave_to_start.inc; +sync_with_master; +--echo -- Should only contain records marked 'master,slave' +SELECT * FROM t3 ORDER BY a; + +--echo **** On Master **** +connection master; +DELETE FROM t3; +sync_slave_with_master; + +--echo ==== Skipping first event of a LOAD DATA for a non-transactional table ==== + +--echo **** On Slave **** +connection slave; +STOP SLAVE; +source include/wait_for_slave_to_stop.inc; + +--echo **** On Master **** +connection master; +SET AUTOCOMMIT=1; + +LOAD DATA INFILE '../std_data_ln/words.dat' INTO TABLE t4(a) SET b = 'master'; +INSERT INTO t4 VALUES ('Go Rin No Sho', 'master,slave'); + +save_master_pos; + +SELECT COUNT(*) FROM t4; + +# This will skip a begin event and the first INSERT of the +# transaction, and it should keep skipping until it has reached the +# transaction terminator. + +--echo **** On Slave **** +connection slave; +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; +START SLAVE; +source include/wait_for_slave_to_start.inc; +sync_with_master; +--echo -- Should only contain records marked 'master,slave' +SELECT * FROM t4 ORDER BY a; + +--echo **** On Master **** +connection master; +DELETE FROM t4; +sync_slave_with_master; + +--echo ==== Try with a big file so that we get an append_block event as well + +--echo **** On Slave **** +connection slave; +STOP SLAVE; +source include/wait_for_slave_to_stop.inc; + +--echo **** On Master **** +connection master; +SET AUTOCOMMIT=1; + +# This contain about 70 words, so we double it a few times to get more than 128 KiB +SET SQL_LOG_BIN=0; +LOAD DATA INFILE '../std_data_ln/words.dat' INTO TABLE t4(a) SET b = 'master'; +INSERT INTO t4 SELECT * FROM t4; +INSERT INTO t4 SELECT * FROM t4; +INSERT INTO t4 SELECT * FROM t4; +INSERT INTO t4 SELECT * FROM t4; +INSERT INTO t4 SELECT * FROM t4; +INSERT INTO t4 SELECT * FROM t4; +INSERT INTO t4 SELECT * FROM t4; +INSERT INTO t4 SELECT * FROM t4; +INSERT INTO t4 SELECT * FROM t4; +INSERT INTO t4 SELECT * FROM t4; +INSERT INTO t4 SELECT * FROM t4; +SELECT a FROM t4 INTO OUTFILE 'rpl_slave_skip_words.dat'; +SET SQL_LOG_BIN=1; + +# Start the real job +LOAD DATA INFILE 'rpl_slave_skip_words.dat' INTO TABLE t4(a) SET b = 'master'; +INSERT INTO t4 VALUES ('Go Rin No Sho', 'master,slave'); + +#SHOW BINLOG EVENTS; + +save_master_pos; + +SELECT COUNT(*) FROM t4; + +# This will skip a begin event and the first INSERT of the +# transaction, and it should keep skipping until it has reached the +# transaction terminator. + +--echo **** On Slave **** +connection slave; +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; +START SLAVE; +source include/wait_for_slave_to_start.inc; +sync_with_master; +--echo -- Should only contain records marked 'master,slave' +SELECT * FROM t4 ORDER BY a; + +--echo **** On Master **** +connection master; +DELETE FROM t4; +sync_slave_with_master; + +# Test to generate a Delete_file log event, and see that it works as well. +--echo **** On Master **** +connection master; +CREATE TABLE t5 (a int, b int, c SET('master','slave'), PRIMARY KEY (a,b)) ENGINE=MyISAM; +LOAD DATA INFILE '../std_data_ln/loaddata5.dat' INTO TABLE t5 FIELDS TERMINATED BY '' ENCLOSED BY '' (a,b) SET c='master,slave'; + +--echo **** On Slave **** +sync_slave_with_master; +STOP SLAVE; +source include/wait_for_slave_to_stop.inc; + +--echo **** On Master **** +connection master; +error ER_DUP_ENTRY; +LOAD DATA INFILE '../std_data_ln/loaddata5.dat' INTO TABLE t5 FIELDS TERMINATED BY '' ENCLOSED BY '' (a,b) SET c=''; +INSERT INTO t5 VALUES (42, 42, 'master,slave'); +save_master_pos; + +#SHOW BINLOG EVENTS; + +SELECT * FROM t5; + +--echo **** On Slave **** +connection slave; +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; +START SLAVE; +source include/wait_for_slave_to_start.inc; + +sync_with_master; +SELECT * FROM t5; + +connection slave; + --echo ==== Cleanup ==== --echo **** On Master **** connection master; -DROP TABLE t1, t2; +DROP TABLE t1, t2, t3, t4, t5; sync_slave_with_master; diff --git a/mysql-test/t/rpl_sp.test b/mysql-test/t/rpl_sp.test index fc17c5615ef..f7cd8907e34 100644 --- a/mysql-test/t/rpl_sp.test +++ b/mysql-test/t/rpl_sp.test @@ -560,7 +560,6 @@ set @a:= mysqltest2.f1(); sync_slave_with_master; connection master; - # Final inspection which verifies how all statements of this test file # were written to the binary log. --replace_column 2 # 5 # @@ -577,3 +576,4 @@ set global log_bin_trust_function_creators=0; # Clean up drop database mysqltest; drop database mysqltest2; +sync_slave_with_master; diff --git a/mysql-test/t/rpl_transaction-master.opt b/mysql-test/t/rpl_transaction-master.opt new file mode 100644 index 00000000000..5411960b4aa --- /dev/null +++ b/mysql-test/t/rpl_transaction-master.opt @@ -0,0 +1 @@ +--innodb --debug=d,do_not_write_xid diff --git a/mysql-test/t/rpl_transaction-slave.opt b/mysql-test/t/rpl_transaction-slave.opt new file mode 100644 index 00000000000..627becdbfb5 --- /dev/null +++ b/mysql-test/t/rpl_transaction-slave.opt @@ -0,0 +1 @@ +--innodb diff --git a/mysql-test/t/rpl_transaction.test b/mysql-test/t/rpl_transaction.test new file mode 100644 index 00000000000..07ba2ea8281 --- /dev/null +++ b/mysql-test/t/rpl_transaction.test @@ -0,0 +1,107 @@ +# Tests that transactions are replicated correctly, with various +# combinations of non-transactional and transactional non-XA tables. +# Also tests that an XA transaction where the master crashes just +# before writing the XID log event is executed correctly. See below +# for implementation details. + +# Note: this test should not exist in 5.1 or higher. It has been +# replaced by rpl_ndb_transaction.test, which tests a superset of what +# this test tests. + +source include/have_innodb.inc; +source include/have_debug.inc; +source include/master-slave.inc; + + +CREATE TABLE tmyisam (a int) ENGINE = MYISAM; +CREATE TABLE tinnodb (a int) ENGINE = INNODB; + +SHOW CREATE TABLE tmyisam; +SHOW CREATE TABLE tinnodb; + + +--echo ==== Test 1: Non-XA Engines ==== +# Test that everything works fine with non-XA engines. We just try +# all ways to do transactions involving ndb and/or myisam, with +# rollback or commit. + +--echo --- on master --- + +SET AUTOCOMMIT = 1; + +INSERT INTO tmyisam VALUES (1); + +BEGIN; +INSERT INTO tmyisam VALUES (2); +INSERT INTO tmyisam VALUES (3); +COMMIT; + +BEGIN; +INSERT INTO tmyisam VALUES (5); +INSERT INTO tmyisam VALUES (6); +--warning 1196 +ROLLBACK; + +SELECT * FROM tmyisam ORDER BY a; + +--echo --- on slave --- +--sync_slave_with_master +SELECT * FROM tmyisam ORDER BY a; + + +--echo ==== Test 2: Master crash before writing XID event on XA engine ==== +# We now want to test the following scenario, to verify that BUG#26395 +# has been fixed: + +# "master and slave have a transactional table that uses XA. Master +# has AUTOCOMMIT on and executes a statement (in this case an +# INSERT). Master crashes just before writing the XID event." + +# In this scenario, master will roll back, so slave should not execute +# the statement, and slave should roll back later when master is +# restarted. + +# However, we the master to be alive so that we are sure it replicates +# the statement to the slave. So in the test case, we must therefore +# not crash the master. Instead, we fake the crash by just not writing +# the XID event to the binlog. This is done by the +# --debug=d,do_not_write_xid flag in the .opt file. + +# So, unlike if the master had crashed, the master *will* execute the +# statement. But the slave should not execute it. Hence, after the +# first test is executed, the expected result on master is a table +# with one row, and on slave a table with no rows. + +# To simulate the slave correctly, we wait until everything up to the +# XID is replicated. We cannot sync_slave_with_master, because that +# would wait for the transaction to end. Instead, we wait for +# "sufficiently long time". Then we stop the slave. + +# Note: since this puts the master binlog in an inconsistent state, +# this should be the last test of the file. + +--echo --- on master --- +--connection master + +INSERT INTO tinnodb VALUES (1); +SELECT * FROM tinnodb ORDER BY a; + +--echo --- on slave --- +--connection slave +--sleep 3 +STOP SLAVE; +source include/wait_for_slave_to_stop.inc; +--replace_column 4 # 7 # 8 # 9 # 16 # 22 # 23 # 33 # +query_vertical SHOW SLAVE STATUS; +# the following statement should show that nothing has been replicated +SELECT * FROM tinnodb ORDER BY a; + + +# clean up +connection master; +DROP TABLE tmyisam; +DROP TABLE tinnodb; + +connection slave; +DROP TABLE tmyisam; +DROP TABLE tinnodb; diff --git a/mysql-test/t/rpl_user.test b/mysql-test/t/rpl_user.test new file mode 100644 index 00000000000..a0aeeac62c2 --- /dev/null +++ b/mysql-test/t/rpl_user.test @@ -0,0 +1,62 @@ +# BUG#33862 completely failed DROP USER statement gets replicated + +--source include/master-slave.inc + +# +# remove all users will be used in the test +# +connection master; +set sql_log_bin=0; +delete from mysql.user where Host='fakehost'; +set sql_log_bin=1; + +connection slave; +set sql_log_bin=0; +delete from mysql.user where Host='fakehost'; +set sql_log_bin=1; + + +# +# Test create user +# +connection master; +create user 'foo'@'fakehost'; +--error ER_CANNOT_USER +create user 'foo'@'fakehost', 'bar'@'fakehost'; +--error ER_CANNOT_USER +create user 'foo'@'fakehost', 'bar'@'fakehost'; + +sync_slave_with_master; +select Host,User from mysql.user where Host='fakehost'; + +# +# Test rename user +# +connection master; +rename user 'foo'@'fakehost' to 'foofoo'@'fakehost'; +--error ER_CANNOT_USER +rename user 'not_exist_user1'@'fakehost' to 'foobar'@'fakehost', 'bar'@'fakehost' to 'barbar'@'fakehost'; +--error ER_CANNOT_USER +rename user 'not_exist_user1'@'fakehost' to 'foobar'@'fakehost', 'not_exist_user2'@'fakehost' to 'barfoo'@'fakehost'; + +sync_slave_with_master; +select Host,User from mysql.user where Host='fakehost'; + +# +# Test drop user +# +connection master; +drop user 'foofoo'@'fakehost'; +--error ER_CANNOT_USER +drop user 'not_exist_user1'@'fakehost', 'barbar'@'fakehost'; +--error ER_CANNOT_USER +drop user 'not_exist_user1'@'fakehost', 'not_exist_user2'@'fakehost'; + +sync_slave_with_master; +select Host,User from mysql.user where Host='fakehost'; + +# +# show the binlog events on the master +# +connection master; +source include/show_binlog_events.inc; diff --git a/mysql-test/t/rpl_user_variables.test b/mysql-test/t/rpl_user_variables.test index 8f8f0accbd1..70b708be258 100644 --- a/mysql-test/t/rpl_user_variables.test +++ b/mysql-test/t/rpl_user_variables.test @@ -337,6 +337,23 @@ select * from t1; connection master; drop table t1; +# +# Bug#33851: Passing UNSIGNED param to EXECUTE returns ERROR 1210 +# + +connection master; +create table t1(a int); +insert into t1 values (1),(2); +prepare s1 from 'insert into t1 select a from t1 limit ?'; +set @x='1.1'; +execute s1 using @x; +select * from t1; +sync_slave_with_master; +connection slave; +select * from t1; +connection master; +drop table t1; + --echo End of 5.0 tests. # This test uses a stored function that uses user-defined variables to return data diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index c48f2771aa8..1ee87957643 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -3672,4 +3672,33 @@ DROP TABLE t1; --echo +########################################################################### + +# +# Bug #33764: Wrong result with IN(), CONCAT() and implicit type conversion +# + +CREATE TABLE t1 (a VARCHAR(10) NOT NULL PRIMARY KEY); +INSERT INTO t1 (a) VALUES ('foo0'), ('bar0'), ('baz0'); +SELECT * FROM t1 WHERE a IN (CONCAT('foo', 0), 'bar'); +DROP TABLE t1; + +# +# Bug #32942 now() - interval '7200' second is NOT pre-calculated, causing "full table scan" +# + +CREATE TABLE t1 (a INT, b INT); +CREATE TABLE t2 (a INT, c INT, KEY(a)); + +INSERT INTO t1 VALUES (1, 1), (2, 2); +INSERT INTO t2 VALUES (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), + (2, 1), (2, 2), (2, 3), (2, 4), (2, 5), + (3, 1), (3, 2), (3, 3), (3, 4), (3, 5), + (4, 1), (4, 2), (4, 3), (4, 4), (4, 5); + +FLUSH STATUS; +SELECT DISTINCT b FROM t1 LEFT JOIN t2 USING(a) WHERE c <= 3; +SHOW STATUS LIKE 'Handler_read%'; +DROP TABLE t1, t2; + --echo End of 5.0 tests diff --git a/mysql-test/t/sp-code.test b/mysql-test/t/sp-code.test index 10755f2bf8a..751282c895a 100644 --- a/mysql-test/t/sp-code.test +++ b/mysql-test/t/sp-code.test @@ -520,5 +520,82 @@ drop table t1; drop procedure proc_26977_broken; drop procedure proc_26977_works; +# +# Bug#33618 Crash in sp_rcontext +# + +--disable_warnings +drop procedure if exists proc_33618_h; +drop procedure if exists proc_33618_c; +--enable_warnings + +delimiter //; + +create procedure proc_33618_h(num int) +begin + declare count1 int default '0'; + declare vb varchar(30); + declare last_row int; + + while(num>=1) do + set num=num-1; + begin + declare cur1 cursor for select `a` from t_33618; + declare continue handler for not found set last_row = 1; + set last_row:=0; + open cur1; + rep1: + repeat + begin + declare exit handler for 1062 begin end; + fetch cur1 into vb; + if (last_row = 1) then + ## should generate a hpop instruction here + leave rep1; + end if; + end; + until last_row=1 + end repeat; + close cur1; + end; + end while; +end// + +create procedure proc_33618_c(num int) +begin + declare count1 int default '0'; + declare vb varchar(30); + declare last_row int; + + while(num>=1) do + set num=num-1; + begin + declare cur1 cursor for select `a` from t_33618; + declare continue handler for not found set last_row = 1; + set last_row:=0; + open cur1; + rep1: + repeat + begin + declare cur2 cursor for select `b` from t_33618; + fetch cur1 into vb; + if (last_row = 1) then + ## should generate a cpop instruction here + leave rep1; + end if; + end; + until last_row=1 + end repeat; + close cur1; + end; + end while; +end// +delimiter ;// + +show procedure code proc_33618_h; +show procedure code proc_33618_c; + +drop procedure proc_33618_h; +drop procedure proc_33618_c; --echo End of 5.0 tests. diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index 8133a2271a1..c9b2b1dbd0e 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -2113,6 +2113,69 @@ SELECT ..inexistent(); USE test; # +# Bug#33983 (Stored Procedures: wrong end <label> syntax is accepted) +# + +--disable_warnings +drop procedure if exists proc_33983_a; +drop procedure if exists proc_33983_b; +drop procedure if exists proc_33983_c; +drop procedure if exists proc_33983_d; +--enable_warnings + +delimiter |; + +--error ER_SP_LABEL_MISMATCH +create procedure proc_33983_a() +begin + label1: + begin + label2: + begin + select 1; + end label1; + end; +end| + +--error ER_SP_LABEL_MISMATCH +create procedure proc_33983_b() +begin + label1: + repeat + label2: + repeat + select 1; + until FALSE end repeat label1; + until FALSE end repeat; +end| + +--error ER_SP_LABEL_MISMATCH +create procedure proc_33983_c() +begin + label1: + while TRUE do + label2: + while TRUE do + select 1; + end while label1; + end while; +end| + +--error ER_SP_LABEL_MISMATCH +create procedure proc_33983_d() +begin + label1: + loop + label2: + loop + select 1; + end loop label1; + end loop; +end| + +delimiter ;| + +# # BUG#NNNN: New bug synopsis # #--disable_warnings diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 785e7e3793c..48ef51e09aa 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -7698,6 +7698,100 @@ DROP PROCEDURE db28318_a.t1; DROP PROCEDURE db28318_b.t2; DROP DATABASE db28318_a; DROP DATABASE db28318_b; +USE test; + +# +# Bug#29770 Two handlers are allowed to catch an error in an stored procedure. +# + +--disable_warnings +DROP TABLE IF EXISTS t1; +DROP PROCEDURE IF EXISTS bug29770; +--enable_warnings + +CREATE TABLE t1(a int); +delimiter |; +CREATE PROCEDURE bug29770() +BEGIN + DECLARE CONTINUE HANDLER FOR SQLSTATE '42S22' SET @state:= 'run'; + DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET @exception:= 'run'; + SELECT x FROM t1; +END| +delimiter ;| +CALL bug29770(); +SELECT @state, @exception; +DROP TABLE t1; +DROP PROCEDURE bug29770; + +# +# Bug#33618 Crash in sp_rcontext +# + +use test; + +--disable_warnings +drop table if exists t_33618; +drop procedure if exists proc_33618; +--enable_warnings + +create table t_33618 (`a` int, unique(`a`), `b` varchar(30)) engine=myisam; +insert into t_33618 (`a`,`b`) values (1,'1'),(2,'2'); + +delimiter //; + +create procedure proc_33618(num int) +begin + declare count1 int default '0'; + declare vb varchar(30); + declare last_row int; + + while(num>=1) do + set num=num-1; + begin + declare cur1 cursor for select `a` from t_33618; + declare continue handler for not found set last_row = 1; + set last_row:=0; + open cur1; + rep1: + repeat + begin + declare exit handler for 1062 begin end; + fetch cur1 into vb; + if (last_row = 1) then + leave rep1; + end if; + end; + until last_row=1 + end repeat; + close cur1; + end; + end while; +end// + +delimiter ;// + +call proc_33618(20); + +drop table t_33618; +drop procedure proc_33618; +--echo # +--echo # Bug#30787: Stored function ignores user defined alias. +--echo # +use test; +--disable_warnings +drop function if exists func30787; +--enable_warnings +create table t1(f1 int); +insert into t1 values(1),(2); +delimiter |; +create function func30787(p1 int) returns int +begin + return p1; +end | +delimiter ;| +select (select func30787(f1)) as ttt from t1; +drop function func30787; +drop table t1; --echo # ------------------------------------------------------------------ diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 326d80f84c1..c5edd5414e3 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -3006,92 +3006,44 @@ DROP TABLE t1,t2; create table t1(a int,b int,key(a),key(b)); insert into t1(a,b) values (1,2),(2,1),(2,3),(3,4),(5,4),(5,5), (6,7),(7,4),(5,3); -# test for the stack overflow bug -select sum(a),a from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 - )group by b limit 1)group by b limit 1 - )group by b limit 1)group by b limit 1)group by b limit 1 - )group by b limit 1)group by b limit 1)group by b limit 1 - )group by b limit 1)group by b limit 1)group by b limit 1) -group by a; ---replace_regex /overrun.*$/overrun detected/ ---error 1436 -select sum(a),a from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 - )group by b limit 1)group by b limit 1)group by b limit 1 - )group by b limit 1)group by b limit 1)group by b limit 1 - )group by b limit 1)group by b limit 1)group by b limit 1 - )group by b limit 1)group by b limit 1)group by b limit 1 - )group by b limit 1)group by b limit 1)group by b limit 1 - )group by b limit 1)group by b limit 1)group by b limit 1 - )group by b limit 1)group by b limit 1)group by b limit 1 - )group by b limit 1)group by b limit 1)group by b limit 1 - )group by b limit 1)group by b limit 1)group by b limit 1 - )group by b limit 1)group by b limit 1)group by b limit 1) -group by a; -# test for the memory consumption & subquery slowness bug -explain select sum(a),a from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 - )group by b limit 1)group by b limit 1 - )group by b limit 1)group by b limit 1)group by b limit 1 - )group by b limit 1)group by b limit 1)group by b limit 1 - )group by b limit 1)group by b limit 1)group by b limit 1) -group by a; ---replace_regex /overrun.*$/overrun detected/ ---error 1436 -explain select sum(a),a from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 - )group by b limit 1)group by b limit 1)group by b limit 1 - )group by b limit 1)group by b limit 1)group by b limit 1 - )group by b limit 1)group by b limit 1)group by b limit 1 - )group by b limit 1)group by b limit 1)group by b limit 1 - )group by b limit 1)group by b limit 1)group by b limit 1 - )group by b limit 1)group by b limit 1)group by b limit 1 - )group by b limit 1)group by b limit 1)group by b limit 1 - )group by b limit 1)group by b limit 1)group by b limit 1 - )group by b limit 1)group by b limit 1)group by b limit 1 - )group by b limit 1)group by b limit 1)group by b limit 1) -group by a; + +let $nesting= 26; +let $should_work_nesting= 5; +let $start= select sum(a),a from t1 where a> ( select sum(a) from t1 ; +let $end= )group by a ; +let $start_app= where a> ( select sum(a) from t1 ; +let $end_pre= )group by b limit 1 ; + +--disable_result_log +--disable_query_log +# At least 4 level nesting should work without errors +while ($should_work_nesting) +{ +--echo $should_work_nesting + eval $start $end; + eval explain $start $end; + let $start= $start + $start_app; + let $end= $end_pre + $end; + dec $should_work_nesting; +} +# Other may fail with the 'stack overrun error' +while ($nesting) +{ +--echo $nesting +--error 0,1436 + eval $start $end; +--error 0,1436 + eval explain $start $end; + let $start= $start + $start_app; + let $end= $end_pre + $end; + dec $nesting; +} +--enable_result_log +--enable_query_log drop table t1; # diff --git a/mysql-test/t/symlink.test b/mysql-test/t/symlink.test index 7eaeaa00c0a..10d8f355c98 100644 --- a/mysql-test/t/symlink.test +++ b/mysql-test/t/symlink.test @@ -127,29 +127,22 @@ drop table t1; # # BUG#32111 - Security Breach via DATA/INDEX DIRECORY and RENAME TABLE # +--write_file $MYSQLTEST_VARDIR/tmp/t1.MYI +EOF --replace_result $MYSQLTEST_VARDIR TEST_DIR +--error 1 eval CREATE TABLE t1(a INT) -DATA DIRECTORY='$MYSQLTEST_VARDIR/master-data/mysql' -INDEX DIRECTORY='$MYSQLTEST_VARDIR/master-data/mysql'; +DATA DIRECTORY='$MYSQLTEST_VARDIR/tmp' +INDEX DIRECTORY='$MYSQLTEST_VARDIR/tmp'; +--replace_result $MYSQLTEST_VARDIR TEST_DIR +eval CREATE TABLE t2(a INT) +DATA DIRECTORY='$MYSQLTEST_VARDIR/tmp' +INDEX DIRECTORY='$MYSQLTEST_VARDIR/tmp'; --replace_result $MYSQLTEST_VARDIR TEST_DIR --error 1 -RENAME TABLE t1 TO user; -DROP TABLE t1; - -# -# Test specifying DATA DIRECTORY that is the same as what would normally -# have been chosen. (Bug #8707) -# -disable_query_log; -eval create table t1 (i int) data directory = "$MYSQLTEST_VARDIR/master-data/test/"; -enable_query_log; -show create table t1; -drop table t1; -disable_query_log; -eval create table t1 (i int) index directory = "$MYSQLTEST_VARDIR/master-data/test/"; -enable_query_log; -show create table t1; -drop table t1; +RENAME TABLE t2 TO t1; +DROP TABLE t2; +--remove_file $MYSQLTEST_VARDIR/tmp/t1.MYI # # Bug#8706 - temporary table with data directory option fails @@ -188,44 +181,61 @@ connection default; select * from t1; drop table t1; ---echo End of 4.1 tests - # -# Bug #29325: create table overwrites .MYD file of other table (datadir) +# CREATE TABLE with DATA DIRECTORY option # - -CREATE DATABASE db1; -CREATE DATABASE db2; - -USE db2; +# Protect ourselves from data left in tmp/ by a previos possibly failed +# test +--system rm -f $MYSQLTEST_VARDIR/tmp/t1.* --disable_query_log -eval CREATE TABLE t1 (b INT) ENGINE MYISAM -DATA DIRECTORY = '$MYSQLTEST_VARDIR/master-data/db1/'; +eval prepare stmt from "create table t1 (c char(10)) data directory='$MYSQLTEST_VARDIR/tmp'"; --enable_query_log +execute stmt; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +show create table t1; +drop table t1; +execute stmt; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +show create table t1; +drop table t1; +deallocate prepare stmt; -INSERT INTO db2.t1 VALUES (1); -SELECT * FROM db2.t1; -RESET QUERY CACHE; +# +# Bug#32167 another privilege bypass with DATA/INDEX DIRECORY +# +--replace_result $MYSQL_TEST_DIR TEST_DIR +--error 1,1210 +eval CREATE TABLE t1(a INT) +DATA DIRECTORY='$MYSQL_TEST_DIR/var/master-data/test'; +--replace_result $MYSQL_TEST_DIR TEST_DIR +--error 1,1210 +eval CREATE TABLE t1(a INT) +DATA DIRECTORY='$MYSQL_TEST_DIR/var/master-data/'; +--replace_result $MYSQL_TEST_DIR TEST_DIR +--error 1,1210 +eval CREATE TABLE t1(a INT) +INDEX DIRECTORY='$MYSQL_TEST_DIR/var/master-data'; +--replace_result $MYSQL_TEST_DIR TEST_DIR +--error 1,1210 +eval CREATE TABLE t1(a INT) +INDEX DIRECTORY='$MYSQL_TEST_DIR/var/master-data_var'; -USE db1; +--echo End of 4.1 tests -#no warning from create table +# +# Bug #29325: create table overwrites .MYD file of other table (datadir) +# SET SESSION keep_files_on_create = TRUE; +--write_file $MYSQLTEST_VARDIR/master-data/test/t1.MYD +EOF --disable_abort_on_error +--error 1 CREATE TABLE t1 (a INT) ENGINE MYISAM; +--error 0,1 +--remove_file $MYSQLTEST_VARDIR/master-data/test/t1.MYD; --enable_abort_on_error - -CREATE TABLE t3 (a INT) Engine=MyISAM; -INSERT INTO t3 VALUES (1),(2),(3); -TRUNCATE TABLE t3; -SELECT * from t3; - -SET SESSION keep_files_on_create = DEFAULT; - -DROP TABLE db2.t1, db1.t3; -DROP DATABASE db1; -DROP DATABASE db2; -USE test; - +SET SESSION keep_files_on_create = FALSE; +CREATE TABLE t1 (a INT) ENGINE MYISAM; +DROP TABLE t1; --echo End of 5.0 tests diff --git a/mysql-test/t/tablelock.test b/mysql-test/t/tablelock.test index 95533903b45..5ac93f09ac1 100644 --- a/mysql-test/t/tablelock.test +++ b/mysql-test/t/tablelock.test @@ -49,3 +49,16 @@ drop table t2,t1; unlock tables; # End of 4.1 tests + +# +# Bug#23588 SHOW COLUMNS on a temporary table causes locking issues +# +create temporary table t1(f1 int); +lock tables t1 write; +insert into t1 values (1); +show columns from t1; +insert into t1 values(2); +drop table t1; +unlock tables; + +# End of 5.0 tests diff --git a/mysql-test/t/type_set.test b/mysql-test/t/type_set.test index b1c816f3371..c7f8c59de28 100644 --- a/mysql-test/t/type_set.test +++ b/mysql-test/t/type_set.test @@ -56,3 +56,23 @@ set('1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17', '50','51','52','53','54','55','56','57','58','59','60','61','62','63','64','1')); show create table t1; drop table t1; + +# +# Bug#15409: Columns with SET datatype with 64-element sets +# may not be updated with integers +# + +let $i=64; +let $s='$i'; +dec $i; +while ($i) { + let $s='$i',$s; + dec $i; +} +--eval CREATE TABLE t1(c set($s)) +INSERT INTO t1 VALUES(7); +INSERT INTO t1 VALUES(9223372036854775808); +SELECT * FROM t1; +DROP TABLE t1; + +--# echo End of 5.0 tests diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index c86e7dfa7f3..1748b63ceb9 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -127,7 +127,7 @@ set GLOBAL myisam_max_sort_file_size=2000000; show global variables like 'myisam_max_sort_file_size'; set GLOBAL myisam_max_sort_file_size=default; --replace_result 9223372036853727232 FILE_SIZE 2146435072 FILE_SIZE -show variables like 'myisam_max_sort_file_size'; +show global variables like 'myisam_max_sort_file_size'; set global net_retry_count=10, session net_retry_count=10; set global net_buffer_length=1024, net_write_timeout=200, net_read_timeout=300; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 340a34db5a1..23e64b0546f 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -3470,5 +3470,73 @@ insert into v1 values(1); set @@sql_mode=@old_mode; drop view v1; drop table t1; ---echo End of 5.0 tests. +# +# Bug #33389: Selecting from a view into a table from within SP or trigger +# crashes server +# + +create table t1 (a int, key(a)); +create table t2 (c int); + +create view v1 as select a b from t1; +create view v2 as select 1 a from t2, v1 where c in + (select 1 from t1 where b = a); + +insert into t1 values (1), (1); +insert into t2 values (1), (1); + +prepare stmt from "select * from v2 where a = 1"; +execute stmt; + +drop view v1, v2; +drop table t1, t2; + +# +# Bug #33049: Assert while running test-as3ap test(mysql-bench suite) +# + +CREATE TABLE t1 (a INT); +CREATE VIEW v1 AS SELECT p.a AS a FROM t1 p, t1 q; + +INSERT INTO t1 VALUES (1), (1); +SELECT MAX(a), COUNT(DISTINCT a) FROM v1 GROUP BY a; + +DROP VIEW v1; +DROP TABLE t1; + +########################################################################### + +--echo # ----------------------------------------------------------------- +--echo # -- Bug#34337: Server crash when Altering a view using a table name. +--echo # ----------------------------------------------------------------- +--echo + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +--echo + +CREATE TABLE t1(c1 INT); + +--echo + +SELECT * FROM t1; + +--error ER_WRONG_OBJECT +ALTER ALGORITHM=TEMPTABLE SQL SECURITY INVOKER VIEW t1 (c2) AS SELECT (1); + +--echo + +DROP TABLE t1; + +--echo +--echo # -- End of test case for Bug#34337. +--echo + +########################################################################### + +--echo # ----------------------------------------------------------------- +--echo # -- End of 5.0 tests. +--echo # ----------------------------------------------------------------- diff --git a/mysql-test/t/view_grant.test b/mysql-test/t/view_grant.test index 7f9eb4e1cff..be9daacec4f 100644 --- a/mysql-test/t/view_grant.test +++ b/mysql-test/t/view_grant.test @@ -608,6 +608,7 @@ drop database mysqltest; # --disable_warnings drop view if exists v1; +drop table if exists t1; --enable_warnings # Backup anonymous users and remove them. (They get in the way of diff --git a/mysql-test/t/warnings.test b/mysql-test/t/warnings.test index 5e9d25aa09b..c42dd22024c 100644 --- a/mysql-test/t/warnings.test +++ b/mysql-test/t/warnings.test @@ -212,4 +212,37 @@ DROP PROCEDURE sp1; DROP PROCEDURE sp2; DROP PROCEDURE sp3; + +# +# Bug#30059: End-space truncation warnings are inconsistent or incorrect +# + +create table t1 (c_char char(255), c_varchar varchar(255), c_tinytext tinytext); +create table t2 (c_tinyblob tinyblob); # not affected by bug, for regression testing +set @c = repeat(' ', 256); +set @q = repeat('q', 256); + +set sql_mode = ''; + +insert into t1 values(@c, @c, @c); +insert into t2 values(@c); +insert into t1 values(@q, @q, @q); +insert into t2 values(@q); + +set sql_mode = 'traditional'; + +insert into t1 values(@c, @c, @c); +--error 1406 +insert into t2 values(@c); +--error 1406 +insert into t1 values(@q, NULL, NULL); +--error 1406 +insert into t1 values(NULL, @q, NULL); +--error 1406 +insert into t1 values(NULL, NULL, @q); +--error 1406 +insert into t2 values(@q); + +drop table t1, t2; + --echo End of 5.0 tests diff --git a/mysys/my_create.c b/mysys/my_create.c index d612926c1a5..c535ae73a0a 100644 --- a/mysys/my_create.c +++ b/mysys/my_create.c @@ -35,7 +35,7 @@ File my_create(const char *FileName, int CreateFlags, int access_flags, myf MyFlags) { - int fd; + int fd, rc; DBUG_ENTER("my_create"); DBUG_PRINT("my",("Name: '%s' CreateFlags: %d AccessFlags: %d MyFlags: %d", FileName, CreateFlags, access_flags, MyFlags)); @@ -60,6 +60,20 @@ File my_create(const char *FileName, int CreateFlags, int access_flags, fd = open(FileName, access_flags); #endif - DBUG_RETURN(my_register_filename(fd, FileName, FILE_BY_CREATE, - EE_CANTCREATEFILE, MyFlags)); + rc= my_register_filename(fd, FileName, FILE_BY_CREATE, + EE_CANTCREATEFILE, MyFlags); + /* + my_register_filename() may fail on some platforms even if the call to + *open() above succeeds. In this case, don't leave the stale file because + callers assume the file to not exist if my_create() fails, so they don't + do any cleanups. + */ + if (unlikely(fd >= 0 && rc < 0)) + { + int tmp= my_errno; + my_delete(FileName, MyFlags); + my_errno= tmp; + } + + DBUG_RETURN(rc); } /* my_create */ diff --git a/ndb/include/kernel/ndb_limits.h b/ndb/include/kernel/ndb_limits.h index c82288c762a..82fd0bd5d51 100644 --- a/ndb/include/kernel/ndb_limits.h +++ b/ndb/include/kernel/ndb_limits.h @@ -27,6 +27,17 @@ #define MAX_NDB_NODES 49 #define MAX_NODES 64 +/************************************************************************** + * IT SHOULD BE (MAX_NDB_NODES - 1). + * WHEN MAX_NDB_NODE IS CHANGED, IT SHOULD BE CHANGED ALSO + **************************************************************************/ +#define MAX_DATA_NODE_ID 48 +/************************************************************************** + * IT SHOULD BE (MAX_NODES - 1). + * WHEN MAX_NODES IS CHANGED, IT SHOULD BE CHANGED ALSO + **************************************************************************/ +#define MAX_NODES_ID 63 + /** * MAX_API_NODES = MAX_NODES - No of NDB Nodes in use */ diff --git a/ndb/include/mgmapi/ndb_logevent.h b/ndb/include/mgmapi/ndb_logevent.h index 76e4c31baa2..389004da06b 100644 --- a/ndb/include/mgmapi/ndb_logevent.h +++ b/ndb/include/mgmapi/ndb_logevent.h @@ -551,7 +551,13 @@ extern "C" { /** Log event specific data for for corresponding NDB_LE_ log event */ struct { int gth; - unsigned page_size_kb; + /* union is for compatibility backward. + * page_size_kb member variable should be removed in the future + */ + union { + unsigned page_size_kb; + unsigned page_size_bytes; + }; unsigned pages_used; unsigned pages_total; unsigned block; diff --git a/ndb/include/ndbapi/Ndb.hpp b/ndb/include/ndbapi/Ndb.hpp index 5f0da6ea83d..42f6302861c 100644 --- a/ndb/include/ndbapi/Ndb.hpp +++ b/ndb/include/ndbapi/Ndb.hpp @@ -1386,22 +1386,22 @@ public: * * @param cacheSize number of values to cache in this Ndb object * - * @return 0 or -1 on error, and tupleId in out parameter + * @return 0 or -1 on error, and autoValue in out parameter */ int getAutoIncrementValue(const char* aTableName, - Uint64 & tupleId, Uint32 cacheSize, + Uint64 & autoValue, Uint32 cacheSize, Uint64 step = 1, Uint64 start = 1); int getAutoIncrementValue(const NdbDictionary::Table * aTable, - Uint64 & tupleId, Uint32 cacheSize, + Uint64 & autoValue, Uint32 cacheSize, Uint64 step = 1, Uint64 start = 1); int readAutoIncrementValue(const char* aTableName, - Uint64 & tupleId); + Uint64 & autoValue); int readAutoIncrementValue(const NdbDictionary::Table * aTable, - Uint64 & tupleId); + Uint64 & autoValue); int setAutoIncrementValue(const char* aTableName, - Uint64 tupleId, bool increase); + Uint64 autoValue, bool modify); int setAutoIncrementValue(const NdbDictionary::Table * aTable, - Uint64 tupleId, bool increase); + Uint64 autoValue, bool modify); private: int getTupleIdFromNdb(Ndb_local_table_info* info, Uint64 & tupleId, Uint32 cacheSize, @@ -1409,7 +1409,9 @@ private: int readTupleIdFromNdb(Ndb_local_table_info* info, Uint64 & tupleId); int setTupleIdInNdb(Ndb_local_table_info* info, - Uint64 tupleId, bool increase); + Uint64 tupleId, bool modify); + int checkTupleIdInNdb(Ndb_local_table_info* info, + Uint64 tupleId); int opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 & opValue, Uint32 op); public: diff --git a/ndb/include/ndbapi/ndbapi_limits.h b/ndb/include/ndbapi/ndbapi_limits.h index e283913d059..98551866edc 100644 --- a/ndb/include/ndbapi/ndbapi_limits.h +++ b/ndb/include/ndbapi/ndbapi_limits.h @@ -26,6 +26,7 @@ #define NDB_MAX_TUPLE_SIZE (NDB_MAX_TUPLE_SIZE_IN_WORDS*4) #define NDB_MAX_ACTIVE_EVENTS 100 -#define NDB_MAX_SCANFILTER_SIZE_IN_WORDS 50000 +/* TUP ZATTR_BUFFER_SIZE 16384 (minus 1) minus place for getValue()s */ +#define NDB_MAX_SCANFILTER_SIZE_IN_WORDS (16384 - 1 - 1024) #endif diff --git a/ndb/include/util/Bitmask.hpp b/ndb/include/util/Bitmask.hpp index 3b3fe721cca..0383841a666 100644 --- a/ndb/include/util/Bitmask.hpp +++ b/ndb/include/util/Bitmask.hpp @@ -126,6 +126,7 @@ public: /** * setField - Set bitfield at given position and length (max 32 bits) + * Note : length == 0 not supported. */ static void setField(unsigned size, Uint32 data[], unsigned pos, unsigned len, Uint32 val); @@ -133,6 +134,7 @@ public: /** * getField - Get bitfield at given position and length + * Note : length == 0 not supported. */ static void getField(unsigned size, const Uint32 data[], unsigned pos, unsigned len, Uint32 dst[]); @@ -814,7 +816,10 @@ BitmaskImpl::getField(unsigned size, const Uint32 src[], unsigned pos, unsigned len, Uint32 dst[]) { assert(pos + len <= (size << 5)); - + assert (len != 0); + if (len == 0) + return; + src += (pos >> 5); Uint32 offset = pos & 31; * dst = (* src >> offset) & (len >= 32 ? ~0 : (1 << len) - 1); @@ -833,6 +838,9 @@ BitmaskImpl::setField(unsigned size, Uint32 dst[], unsigned pos, unsigned len, const Uint32 src[]) { assert(pos + len <= (size << 5)); + assert(len != 0); + if (len == 0) + return; dst += (pos >> 5); Uint32 offset = pos & 31; diff --git a/ndb/src/common/debugger/SignalLoggerManager.cpp b/ndb/src/common/debugger/SignalLoggerManager.cpp index 471bea64f64..48cacb6bc1a 100644 --- a/ndb/src/common/debugger/SignalLoggerManager.cpp +++ b/ndb/src/common/debugger/SignalLoggerManager.cpp @@ -129,7 +129,7 @@ SignalLoggerManager::log(LogMode logMode, const char * params) const int count = getParameter(blocks, "BLOCK=", params); int cnt = 0; - if((count == 1 && blocks[0] == "ALL") || + if((count == 1 && !strcmp(blocks[0], "ALL")) || count == 0){ for (int number = 0; number < NO_OF_BLOCKS; ++number){ diff --git a/ndb/src/common/debugger/signaldata/ScanTab.cpp b/ndb/src/common/debugger/signaldata/ScanTab.cpp index 39589542800..db9bbb52eab 100644 --- a/ndb/src/common/debugger/signaldata/ScanTab.cpp +++ b/ndb/src/common/debugger/signaldata/ScanTab.cpp @@ -69,7 +69,7 @@ printSCANTABCONF(FILE * output, const Uint32 * theData, Uint32 len, Uint16 recei sig->transId1, sig->transId2); fprintf(output, " requestInfo: Eod: %d OpCount: %d\n", - (requestInfo & ScanTabConf::EndOfData == ScanTabConf::EndOfData), + (requestInfo & ScanTabConf::EndOfData) == ScanTabConf::EndOfData, (requestInfo & (~ScanTabConf::EndOfData))); size_t op_count= requestInfo & (~ScanTabConf::EndOfData); if(op_count){ diff --git a/ndb/src/common/transporter/TCP_Transporter.cpp b/ndb/src/common/transporter/TCP_Transporter.cpp index c8095defd86..ea9e0944915 100644 --- a/ndb/src/common/transporter/TCP_Transporter.cpp +++ b/ndb/src/common/transporter/TCP_Transporter.cpp @@ -337,22 +337,32 @@ TCP_Transporter::doSend() { // Empty the SendBuffers - const char * const sendPtr = m_sendBuffer.sendPtr; - const Uint32 sizeToSend = m_sendBuffer.sendDataSize; - if (sizeToSend > 0){ + bool sent_any = true; + while (m_sendBuffer.dataSize > 0) + { + const char * const sendPtr = m_sendBuffer.sendPtr; + const Uint32 sizeToSend = m_sendBuffer.sendDataSize; const int nBytesSent = inet_send(theSocket, sendPtr, sizeToSend, 0); - if (nBytesSent > 0) { + if (nBytesSent > 0) + { + sent_any = true; m_sendBuffer.bytesSent(nBytesSent); sendCount ++; sendSize += nBytesSent; - if(sendCount == reportFreq){ + if(sendCount == reportFreq) + { reportSendLen(get_callback_obj(), remoteNodeId, sendCount, sendSize); sendCount = 0; sendSize = 0; } - } else { + } + else + { + if (nBytesSent < 0 && InetErrno == EAGAIN && sent_any) + break; + // Send failed #if defined DEBUG_TRANSPORTER ndbout_c("Send Failure(disconnect==%d) to node = %d nBytesSent = %d " diff --git a/ndb/src/common/util/Bitmask.cpp b/ndb/src/common/util/Bitmask.cpp index 4b90e5a01f4..22919fe585a 100644 --- a/ndb/src/common/util/Bitmask.cpp +++ b/ndb/src/common/util/Bitmask.cpp @@ -16,34 +16,63 @@ #include <Bitmask.hpp> #include <NdbOut.hpp> -#ifndef __TEST_BITMASK__ - void BitmaskImpl::getFieldImpl(const Uint32 src[], unsigned shiftL, unsigned len, Uint32 dst[]) { + /* Copy whole words of src to dst, shifting src left + * by shiftL. Undefined bits of the last written dst word + * should be zeroed. + */ assert(shiftL < 32); unsigned shiftR = 32 - shiftL; unsigned undefined = shiftL ? ~0 : 0; + /* Merge first word with previously set bits if there's a shift */ * dst = shiftL ? * dst : 0; - - while(len >= 32) - { - * dst++ |= (* src) << shiftL; - * dst = ((* src++) >> shiftR) & undefined; - len -= 32; - } - - if(len < shiftR) + + /* Treat the zero-shift case separately to avoid + * trampling or reading past the end of src + */ + if (shiftL == 0) { - * dst |= ((* src) & ((1 << len) - 1)) << shiftL; + while(len >= 32) + { + * dst++ = * src++; + len -=32; + } + + if (len != 0) + { + /* Last word has some bits set */ + Uint32 mask= ((1 << len) -1); // 0000111 + * dst = (* src) & mask; + } } - else + else // shiftL !=0, need to build each word from two words shifted { - * dst++ |= ((* src) << shiftL); - * dst = ((* src) >> shiftR) & ((1 << (len - shiftR)) - 1) & undefined; + while(len >= 32) + { + * dst++ |= (* src) << shiftL; + * dst = ((* src++) >> shiftR) & undefined; + len -= 32; + } + + /* Have space for shiftR more bits in the current dst word + * is that enough? + */ + if(len <= shiftR) + { + /* Fit the remaining bits in the current dst word */ + * dst |= ((* src) & ((1 << len) - 1)) << shiftL; + } + else + { + /* Need to write to two dst words */ + * dst++ |= ((* src) << shiftL); + * dst = ((* src) >> shiftR) & ((1 << (len - shiftR)) - 1) & undefined; + } } } @@ -66,301 +95,23 @@ BitmaskImpl::setFieldImpl(Uint32 dst[], len -= 32; } + /* Copy last bits */ Uint32 mask = ((1 << len) -1); * dst = (* dst & ~mask); - if(len < shiftR) + if(len <= shiftR) { + /* Remaining bits fit in current word */ * dst |= ((* src++) >> shiftL) & mask; } else { + /* Remaining bits update 2 words */ * dst |= ((* src++) >> shiftL); * dst |= ((* src) & ((1 << (len - shiftR)) - 1)) << shiftR ; } } -#else - -static -void print(const Uint32 src[], Uint32 len, Uint32 pos = 0) -{ - printf("b'"); - for(unsigned i = 0; i<len; i++) - { - if(BitmaskImpl::get((pos + len + 31) >> 5, src, i+pos)) - printf("1"); - else - printf("0"); - if((i & 31) == 31) - printf(" "); - } -} - -#define DEBUG 0 -#include <Vector.hpp> -static void do_test(int bitmask_size); - -int -main(int argc, char** argv) -{ - int loops = argc > 1 ? atoi(argv[1]) : 1000; - int max_size = argc > 2 ? atoi(argv[2]) : 1000; - - - for(int i = 0; i<loops; i++) - do_test(1 + (rand() % max_size)); -} - -struct Alloc -{ - Uint32 pos; - Uint32 size; - Vector<Uint32> data; -}; - -static void require(bool b) -{ - if(!b) abort(); -} - -static -bool cmp(const Uint32 b1[], const Uint32 b2[], Uint32 len) -{ - Uint32 sz32 = (len + 31) >> 5; - for(int i = 0; i<len; i++) - { - if(BitmaskImpl::get(sz32, b1, i) ^ BitmaskImpl::get(sz32, b2, i)) - return false; - } - return true; -} - - -static int val_pos = 0; -static int val[] = { 384, 241, 32, - 1,1,1,1, 0,0,0,0, 1,1,1,1, 0,0,0,0, - 241 }; - -static int lrand() -{ -#if 0 - return val[val_pos++]; -#else - return rand(); -#endif -} - -static -void rand(Uint32 dst[], Uint32 len) -{ - for(int i = 0; i<len; i++) - BitmaskImpl::set((len + 31) >> 5, dst, i, (lrand() % 1000) > 500); -} - -static -void simple(int pos, int size) -{ - ndbout_c("simple pos: %d size: %d", pos, size); - Vector<Uint32> _mask; - Vector<Uint32> _src; - Vector<Uint32> _dst; - Uint32 sz32 = (size + pos + 32) >> 5; - const Uint32 sz = 4 * sz32; - - Uint32 zero = 0; - _mask.fill(sz32+1, zero); - _src.fill(sz32+1, zero); - _dst.fill(sz32+1, zero); - - Uint32 * src = _src.getBase(); - Uint32 * dst = _dst.getBase(); - Uint32 * mask = _mask.getBase(); - - memset(src, 0x0, sz); - memset(dst, 0x0, sz); - memset(mask, 0xFF, sz); - rand(src, size); - BitmaskImpl::setField(sz32, mask, pos, size, src); - BitmaskImpl::getField(sz32, mask, pos, size, dst); - printf("src: "); print(src, size+31); printf("\n"); - printf("msk: "); print(mask, (sz32 << 5) + 31); printf("\n"); - printf("dst: "); print(dst, size+31); printf("\n"); - require(cmp(src, dst, size+31)); -}; - -static -void simple2(int size, int loops) -{ - ndbout_c("simple2 %d - ", size); - Vector<Uint32> _mask; - Vector<Uint32> _src; - Vector<Uint32> _dst; - - Uint32 sz32 = (size + 32) >> 5; - Uint32 sz = sz32 << 2; - - Uint32 zero = 0; - _mask.fill(sz32+1, zero); - _src.fill(sz32+1, zero); - _dst.fill(sz32+1, zero); - - Uint32 * src = _src.getBase(); - Uint32 * dst = _dst.getBase(); - Uint32 * mask = _mask.getBase(); - - Vector<Uint32> save; - for(int i = 0; i<loops; i++) - { - memset(mask, 0xFF, sz); - memset(dst, 0xFF, sz); - int len; - int pos = 0; - while(pos+1 < size) - { - memset(src, 0xFF, sz); - while(!(len = rand() % (size - pos))); - BitmaskImpl::setField(sz32, mask, pos, len, src); - if(memcmp(dst, mask, sz)) - { - ndbout_c("pos: %d len: %d", pos, len); - print(mask, size); - abort(); - } - printf("[ %d %d ]", pos, len); - save.push_back(pos); - save.push_back(len); - pos += len; - } - - for(int j = 0; j<save.size(); ) - { - pos = save[j++]; - len = save[j++]; - memset(src, 0xFF, sz); - BitmaskImpl::getField(sz32, mask, pos, len, src); - if(memcmp(dst, src, sz)) - { - ndbout_c("pos: %d len: %d", pos, len); - printf("src: "); print(src, size); printf("\n"); - printf("dst: "); print(dst, size); printf("\n"); - printf("msk: "); print(mask, size); printf("\n"); - abort(); - } - } - ndbout_c(""); - } -} - -static void -do_test(int bitmask_size) -{ -#if 1 - simple(rand() % 33, (rand() % 63)+1); -//#else - Vector<Alloc> alloc_list; - bitmask_size = (bitmask_size + 31) & ~31; - Uint32 sz32 = (bitmask_size >> 5); - Vector<Uint32> alloc_mask; - Vector<Uint32> test_mask; - - ndbout_c("Testing bitmask of size %d", bitmask_size); - Uint32 zero = 0; - alloc_mask.fill(sz32, zero); - test_mask.fill(sz32, zero); - - for(int i = 0; i<5000; i++) - { - Vector<Uint32> tmp; - tmp.fill(sz32, zero); - - int pos = lrand() % (bitmask_size - 1); - int free = 0; - if(BitmaskImpl::get(sz32, alloc_mask.getBase(), pos)) - { - // Bit was allocated - // 1) Look up allocation - // 2) Check data - // 3) free it - size_t j; - int min, max; - for(j = 0; j<alloc_list.size(); j++) - { - min = alloc_list[j].pos; - max = min + alloc_list[j].size; - if(pos >= min && pos < max) - { - break; - } - } - require(pos >= min && pos < max); - BitmaskImpl::getField(sz32, test_mask.getBase(), min, max-min, - tmp.getBase()); - if(DEBUG) - { - printf("freeing [ %d %d ]", min, max); - printf("- mask: "); - print(tmp.getBase(), max - min); - - printf(" save: "); - size_t k; - Alloc& a = alloc_list[j]; - for(k = 0; k<a.data.size(); k++) - printf("%.8x ", a.data[k]); - printf("\n"); - } - int bytes = (max - min + 7) >> 3; - if(!cmp(tmp.getBase(), alloc_list[j].data.getBase(), max - min)) - { - abort(); - } - while(min < max) - BitmaskImpl::clear(sz32, alloc_mask.getBase(), min++); - alloc_list.erase(j); - } - else - { - Vector<Uint32> tmp; - tmp.fill(sz32, zero); - - // Bit was free - // 1) Check how much space is avaiable - // 2) Create new allocation of lrandom size - // 3) Fill data with lrandom data - // 4) Update alloc mask - while(pos+free < bitmask_size && - !BitmaskImpl::get(sz32, alloc_mask.getBase(), pos+free)) - free++; - - Uint32 sz = - (free <= 64 && ((lrand() % 100) > 80)) ? free : (lrand() % free); - sz = sz ? sz : 1; - sz = pos + sz == bitmask_size ? sz - 1 : sz; - Alloc a; - a.pos = pos; - a.size = sz; - a.data.fill(((sz+31)>> 5)-1, zero); - if(DEBUG) - printf("pos %d -> alloc [ %d %d ]", pos, pos, pos+sz); - for(size_t j = 0; j<sz; j++) - { - BitmaskImpl::set(sz32, alloc_mask.getBase(), pos+j); - if((lrand() % 1000) > 500) - BitmaskImpl::set((sz + 31) >> 5, a.data.getBase(), j); - } - if(DEBUG) - { - printf("- mask: "); - print(a.data.getBase(), sz); - printf("\n"); - } - BitmaskImpl::setField(sz32, test_mask.getBase(), pos, sz, - a.data.getBase()); - alloc_list.push_back(a); - } - } -#endif -} - -template class Vector<Alloc>; -template class Vector<Uint32>; -#endif +/* Bitmask testcase code moved from here to + * storage/ndb/test/ndbapi/testBitfield.cpp + * to get coverage from automated testing + */ diff --git a/ndb/src/common/util/NdbOut.cpp b/ndb/src/common/util/NdbOut.cpp index 7ca7c91e266..61de2be7572 100644 --- a/ndb/src/common/util/NdbOut.cpp +++ b/ndb/src/common/util/NdbOut.cpp @@ -29,7 +29,7 @@ static const char * fms[] = { "%d", "0x%08x", // Int32 "%u", "0x%08x", // Uint32 "%lld", "0x%016llx", // Int64 - "%llu", "0x%016llx" // Uint64 + "%llu", "0x%016llx", // Uint64 "%llu", "0x%016llx" // UintPtr }; diff --git a/ndb/src/kernel/blocks/backup/Backup.cpp b/ndb/src/kernel/blocks/backup/Backup.cpp index 70721bfca56..52ab11b8388 100644 --- a/ndb/src/kernel/blocks/backup/Backup.cpp +++ b/ndb/src/kernel/blocks/backup/Backup.cpp @@ -374,16 +374,18 @@ Backup::execCONTINUEB(Signal* signal) ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr); FsBuffer & buf = filePtr.p->operation.dataBuffer; - if(buf.getFreeSize() + buf.getMinRead() < buf.getUsableSize()) { + if(buf.getFreeSize() < buf.getMaxWrite()) { jam(); TablePtr tabPtr LINT_SET_PTR; c_tablePool.getPtr(tabPtr, Tdata2); - DEBUG_OUT("Backup - Buffer full - " << buf.getFreeSize() - << " + " << buf.getMinRead() - << " < " << buf.getUsableSize() - << " - tableId = " << tabPtr.p->tableId); - + DEBUG_OUT("Backup - Buffer full - " + << buf.getFreeSize() + << " < " << buf.getMaxWrite() + << " (sz: " << buf.getUsableSize() + << " getMinRead: " << buf.getMinRead() + << ") - tableId = " << tabPtr.p->tableId); + signal->theData[0] = BackupContinueB::BUFFER_FULL_META; signal->theData[1] = Tdata1; signal->theData[2] = Tdata2; diff --git a/ndb/src/kernel/blocks/backup/Backup.hpp b/ndb/src/kernel/blocks/backup/Backup.hpp index 8b0c27727b0..e67d8f09f0e 100644 --- a/ndb/src/kernel/blocks/backup/Backup.hpp +++ b/ndb/src/kernel/blocks/backup/Backup.hpp @@ -518,7 +518,7 @@ public: Uint32 m_diskless; STATIC_CONST(NO_OF_PAGES_META_FILE = - (MAX_WORDS_META_FILE + BACKUP_WORDS_PER_PAGE - 1) / + (2*MAX_WORDS_META_FILE + BACKUP_WORDS_PER_PAGE - 1) / BACKUP_WORDS_PER_PAGE); /** diff --git a/ndb/src/kernel/blocks/dbtup/Dbtup.hpp b/ndb/src/kernel/blocks/dbtup/Dbtup.hpp index 6fe0eefcdb5..829156ef15a 100644 --- a/ndb/src/kernel/blocks/dbtup/Dbtup.hpp +++ b/ndb/src/kernel/blocks/dbtup/Dbtup.hpp @@ -198,6 +198,7 @@ #define ZUNSUPPORTED_BRANCH 892 #define ZSTORED_SEIZE_ATTRINBUFREC_ERROR 873 // Part of Scan +#define ZSTORED_TOO_MUCH_ATTRINFO_ERROR 874 #define ZREAD_ONLY_CONSTRAINT_VIOLATION 893 #define ZVAR_SIZED_NOT_SUPPORTED 894 @@ -1085,7 +1086,7 @@ public: /* * TUX checks if tuple is visible to scan. */ - bool tuxQueryTh(Uint32 fragPtrI, Uint32 tupAddr, Uint32 tupVersion, Uint32 transId1, Uint32 transId2, Uint32 savePointId); + bool tuxQueryTh(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32 tupVersion, Uint32 transId1, Uint32 transId2, bool dirty, Uint32 savePointId); private: BLOCK_DEFINES(Dbtup); @@ -1942,6 +1943,8 @@ private: bool getPageThroughSavePoint(Operationrec* const regOperPtr, Operationrec* const leaderOpPtr); + bool find_savepoint(OperationrecPtr& loopOpPtr, Uint32 savepointId); + Uint32 calculateChecksum(Page* const pagePtr, Uint32 tupHeadOffset, Uint32 tupHeadSize); void setChecksum(Page* const pagePtr, Uint32 tupHeadOffset, Uint32 tupHeadSize); @@ -2171,7 +2174,8 @@ private: Operationrec* regOperPtr, Uint32 lenAttrInfo); void storedSeizeAttrinbufrecErrorLab(Signal* signal, - Operationrec* regOperPtr); + Operationrec* regOperPtr, + Uint32 errorCode); bool storedProcedureAttrInfo(Signal* signal, Operationrec* regOperPtr, Uint32 length, @@ -2467,4 +2471,22 @@ bool Dbtup::isPageUndoLogged(Fragrecord* const regFragPtr, return false; }//Dbtup::isUndoLoggingNeeded() +inline +bool Dbtup::find_savepoint(OperationrecPtr& loopOpPtr, Uint32 savepointId) +{ + while (true) { + if (savepointId > loopOpPtr.p->savePointId) { + jam(); + return true; + } + // note 5.0 has reversed next/prev pointers + loopOpPtr.i = loopOpPtr.p->nextActiveOp; + if (loopOpPtr.i == RNIL) { + break; + } + ptrCheckGuard(loopOpPtr, cnoOfOprec, operationrec); + } + return false; +} + #endif diff --git a/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp b/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp index 298fb183bc3..9ab4fb34827 100644 --- a/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp +++ b/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp @@ -77,6 +77,14 @@ void Dbtup::copyAttrinfo(Signal* signal, RbufLen = copyAttrBufPtr.p->attrbuf[ZBUF_DATA_LEN]; Rnext = copyAttrBufPtr.p->attrbuf[ZBUF_NEXT]; Rfirst = cfirstfreeAttrbufrec; + /* + * ATTRINFO comes from 2 mutually exclusive places: + * 1) TUPKEYREQ (also interpreted part) + * 2) STORED_PROCREQ before scan start + * Assert here that both have a check for overflow. + * The "<" instead of "<=" is intentional. + */ + ndbrequire(RinBufIndex + RbufLen < ZATTR_BUFFER_SIZE); MEMCOPY_NO_WORDS(&inBuffer[RinBufIndex], ©AttrBufPtr.p->attrbuf[0], RbufLen); diff --git a/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp b/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp index 964d8578217..c03ca35bc6a 100644 --- a/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp +++ b/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp @@ -246,8 +246,18 @@ Dbtup::accReadPk(Uint32 tableId, Uint32 fragId, Uint32 fragPageId, Uint32 pageIn return ret; } +/* + * TUX index contains all tuple versions. A scan in TUX has scanned + * one of them and asks if it can be returned as scan result. This + * depends on trans id, dirty read flag, and savepoint within trans. + * + * Previously this faked a ZREAD operation and used getPage(). + * In TUP getPage() is run after ACC locking, but TUX comes here + * before ACC access. Instead of modifying getPage() it is more + * clear to do the full check here. + */ bool -Dbtup::tuxQueryTh(Uint32 fragPtrI, Uint32 tupAddr, Uint32 tupVersion, Uint32 transId1, Uint32 transId2, Uint32 savePointId) +Dbtup::tuxQueryTh(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32 tupVersion, Uint32 transId1, Uint32 transId2, bool dirty, Uint32 savePointId) { ljamEntry(); FragrecordPtr fragPtr; @@ -256,33 +266,73 @@ Dbtup::tuxQueryTh(Uint32 fragPtrI, Uint32 tupAddr, Uint32 tupVersion, Uint32 tra TablerecPtr tablePtr; tablePtr.i = fragPtr.p->fragTableId; ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec); - // get page PagePtr pagePtr; - Uint32 fragPageId = tupAddr >> MAX_TUPLES_BITS; - Uint32 pageIndex = tupAddr & ((1 << MAX_TUPLES_BITS ) - 1); - // use temp op rec - Operationrec tempOp; - tempOp.fragPageId = fragPageId; - tempOp.pageIndex = pageIndex; - tempOp.transid1 = transId1; - tempOp.transid2 = transId2; - tempOp.savePointId = savePointId; - tempOp.optype = ZREAD; - tempOp.dirtyOp = 1; - if (getPage(pagePtr, &tempOp, fragPtr.p, tablePtr.p)) { - /* - * We use the normal getPage which will return the tuple to be used - * for this transaction and savepoint id. If its tuple version - * equals the requested then we have a visible tuple otherwise not. - */ + pagePtr.i = pageId; + ptrCheckGuard(pagePtr, cnoOfPage, page); + + OperationrecPtr currOpPtr; + currOpPtr.i = pagePtr.p->pageWord[pageOffset]; + if (currOpPtr.i == RNIL) { + ljam(); + // tuple has no operation, any scan can see it + return true; + } + ptrCheckGuard(currOpPtr, cnoOfOprec, operationrec); + + const bool sameTrans = + transId1 == currOpPtr.p->transid1 && + transId2 == currOpPtr.p->transid2; + + bool res = false; + OperationrecPtr loopOpPtr = currOpPtr; + + if (!sameTrans) { ljam(); - Uint32 read_tupVersion = pagePtr.p->pageWord[tempOp.pageOffset + 1]; - if (read_tupVersion == tupVersion) { + if (!dirty) { ljam(); - return true; + if (currOpPtr.p->prevActiveOp == RNIL) { + ljam(); + // last op - TUX makes ACC lock request in same timeslice + res = true; + } + } + else { + // loop to first op (returns false) + find_savepoint(loopOpPtr, 0); + const Uint32 op_type = loopOpPtr.p->optype; + + if (op_type != ZINSERT) { + ljam(); + // read committed version from the page + const Uint32 origVersion = pagePtr.p->pageWord[pageOffset + 1]; + if (origVersion == tupVersion) { + ljam(); + res = true; + } + } } } - return false; + else { + ljam(); + // for own trans, ignore dirty flag + + if (find_savepoint(loopOpPtr, savePointId)) { + ljam(); + const Uint32 op_type = loopOpPtr.p->optype; + + if (op_type != ZDELETE) { + ljam(); + // check if this op has produced the scanned version + Uint32 loopVersion = loopOpPtr.p->tupVersion; + if (loopVersion == tupVersion) { + ljam(); + res = true; + } + } + } + } + + return res; } // ordered index build diff --git a/ndb/src/kernel/blocks/dbtup/DbtupStoredProcDef.cpp b/ndb/src/kernel/blocks/dbtup/DbtupStoredProcDef.cpp index 37fcd3df317..f4215b6da7d 100644 --- a/ndb/src/kernel/blocks/dbtup/DbtupStoredProcDef.cpp +++ b/ndb/src/kernel/blocks/dbtup/DbtupStoredProcDef.cpp @@ -108,6 +108,11 @@ void Dbtup::scanProcedure(Signal* signal, regOperPtr->attrinbufLen = lenAttrInfo; regOperPtr->currentAttrinbufLen = 0; regOperPtr->pageOffset = storedPtr.i; + if (lenAttrInfo >= ZATTR_BUFFER_SIZE) { // yes ">=" + jam(); + // send REF and change state to ignore the ATTRINFO to come + storedSeizeAttrinbufrecErrorLab(signal, regOperPtr, ZSTORED_TOO_MUCH_ATTRINFO_ERROR); + } }//Dbtup::scanProcedure() void Dbtup::copyProcedure(Signal* signal, @@ -146,7 +151,7 @@ bool Dbtup::storedProcedureAttrInfo(Signal* signal, Uint32 RnoFree = cnoFreeAttrbufrec; if (ERROR_INSERTED(4004) && !copyProcedure) { CLEAR_ERROR_INSERT_VALUE; - storedSeizeAttrinbufrecErrorLab(signal, regOperPtr); + storedSeizeAttrinbufrecErrorLab(signal, regOperPtr, ZSTORED_SEIZE_ATTRINBUFREC_ERROR); return false; }//if regOperPtr->currentAttrinbufLen += length; @@ -162,7 +167,7 @@ bool Dbtup::storedProcedureAttrInfo(Signal* signal, regAttrPtr.p->attrbuf[ZBUF_NEXT] = RNIL; } else { ljam(); - storedSeizeAttrinbufrecErrorLab(signal, regOperPtr); + storedSeizeAttrinbufrecErrorLab(signal, regOperPtr, ZSTORED_SEIZE_ATTRINBUFREC_ERROR); return false; }//if if (regOperPtr->firstAttrinbufrec == RNIL) { @@ -190,7 +195,7 @@ bool Dbtup::storedProcedureAttrInfo(Signal* signal, }//if if (ERROR_INSERTED(4005) && !copyProcedure) { CLEAR_ERROR_INSERT_VALUE; - storedSeizeAttrinbufrecErrorLab(signal, regOperPtr); + storedSeizeAttrinbufrecErrorLab(signal, regOperPtr, ZSTORED_SEIZE_ATTRINBUFREC_ERROR); return false; }//if @@ -211,7 +216,8 @@ bool Dbtup::storedProcedureAttrInfo(Signal* signal, }//Dbtup::storedProcedureAttrInfo() void Dbtup::storedSeizeAttrinbufrecErrorLab(Signal* signal, - Operationrec* regOperPtr) + Operationrec* regOperPtr, + Uint32 errorCode) { StoredProcPtr storedPtr; c_storedProcPool.getPtr(storedPtr, (Uint32)regOperPtr->pageOffset); @@ -222,7 +228,7 @@ void Dbtup::storedSeizeAttrinbufrecErrorLab(Signal* signal, regOperPtr->lastAttrinbufrec = RNIL; regOperPtr->transstate = ERROR_WAIT_STORED_PROCREQ; signal->theData[0] = regOperPtr->userpointer; - signal->theData[1] = ZSTORED_SEIZE_ATTRINBUFREC_ERROR; + signal->theData[1] = errorCode; signal->theData[2] = regOperPtr->pageOffset; sendSignal(regOperPtr->userblockref, GSN_STORED_PROCREF, signal, 3, JBB); }//Dbtup::storedSeizeAttrinbufrecErrorLab() diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp index 7eae1486d43..f72b1db1cc5 100644 --- a/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp +++ b/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp @@ -216,7 +216,8 @@ Dbtux::execTUX_BOUND_INFO(Signal* signal) // fill in any gap while (maxAttrId[j] <= attrId) { jam(); - BoundInfo& b = boundInfo[j][maxAttrId[j]++]; + BoundInfo& b = boundInfo[j][maxAttrId[j]]; + maxAttrId[j]++; b.type2 = -1; } BoundInfo& b = boundInfo[j][attrId]; @@ -984,7 +985,8 @@ Dbtux::scanVisible(ScanOpPtr scanPtr, TreeEnt ent) const Frag& frag = *c_fragPool.getPtr(scan.m_fragPtrI); Uint32 fragBit = ent.m_fragBit; Uint32 tableFragPtrI = frag.m_tupTableFragPtrI[fragBit]; - Uint32 tupAddr = getTupAddr(frag, ent); + Uint32 pageId = ent.m_tupLoc.getPageId(); + Uint32 pageOffset = ent.m_tupLoc.getPageOffset(); Uint32 tupVersion = ent.m_tupVersion; // check for same tuple twice in row if (scan.m_scanEnt.m_tupLoc == ent.m_tupLoc && @@ -994,8 +996,9 @@ Dbtux::scanVisible(ScanOpPtr scanPtr, TreeEnt ent) } Uint32 transId1 = scan.m_transId1; Uint32 transId2 = scan.m_transId2; + bool dirty = scan.m_readCommitted; Uint32 savePointId = scan.m_savePointId; - bool ret = c_tup->tuxQueryTh(tableFragPtrI, tupAddr, tupVersion, transId1, transId2, savePointId); + bool ret = c_tup->tuxQueryTh(tableFragPtrI, pageId, pageOffset, tupVersion, transId1, transId2, dirty, savePointId); jamEntry(); return ret; } diff --git a/ndb/src/kernel/vm/DLHashTable.hpp b/ndb/src/kernel/vm/DLHashTable.hpp index acf53944b07..cc6802db2bc 100644 --- a/ndb/src/kernel/vm/DLHashTable.hpp +++ b/ndb/src/kernel/vm/DLHashTable.hpp @@ -45,8 +45,8 @@ public: /** * Seize element from pool - return i * - * Note must be either added using <b>add</b> or released - * using <b>release</b> + * Note *must* be added using <b>add</b> (even before hash.release) + * or be released using pool */ bool seize(Ptr<T> &); @@ -374,7 +374,14 @@ DLHashTable<T>::remove(Ptr<T> & ptr){ prevP->nextHash = next; } else { const Uint32 hv = ptr.p->hashValue() & mask; - hashValues[hv] = next; + if (hashValues[hv] == ptr.i) + { + hashValues[hv] = next; + } + else + { + // Will add assert in 5.1 + } } if(next != RNIL){ @@ -395,7 +402,14 @@ DLHashTable<T>::release(Ptr<T> & ptr){ prevP->nextHash = next; } else { const Uint32 hv = ptr.p->hashValue() & mask; - hashValues[hv] = next; + if (hashValues[hv] == ptr.i) + { + hashValues[hv] = next; + } + else + { + // Will add assert in 5.1 + } } if(next != RNIL){ diff --git a/ndb/src/kernel/vm/DLHashTable2.hpp b/ndb/src/kernel/vm/DLHashTable2.hpp index ad03e8ed3ba..20515af8cf6 100644 --- a/ndb/src/kernel/vm/DLHashTable2.hpp +++ b/ndb/src/kernel/vm/DLHashTable2.hpp @@ -43,8 +43,8 @@ public: /** * Seize element from pool - return i * - * Note must be either added using <b>add</b> or released - * using <b>release</b> + * Note *must* be added using <b>add</b> (even before hash.release) + * or be released using pool */ bool seize(Ptr<T> &); @@ -375,7 +375,14 @@ DLHashTable2<T, U>::remove(Ptr<T> & ptr){ prevP->nextHash = next; } else { const Uint32 hv = ptr.p->hashValue() & mask; - hashValues[hv] = next; + if (hashValues[hv] == ptr.i) + { + hashValues[hv] = next; + } + else + { + // Will add assert in 5.1 + } } if(next != RNIL){ @@ -396,7 +403,14 @@ DLHashTable2<T, U>::release(Ptr<T> & ptr){ prevP->nextHash = next; } else { const Uint32 hv = ptr.p->hashValue() & mask; - hashValues[hv] = next; + if (hashValues[hv] == ptr.i) + { + hashValues[hv] = next; + } + else + { + // Will add assert in 5.1 + } } if(next != RNIL){ diff --git a/ndb/src/kernel/vm/pc.hpp b/ndb/src/kernel/vm/pc.hpp index 269719c44d0..ed592620a2e 100644 --- a/ndb/src/kernel/vm/pc.hpp +++ b/ndb/src/kernel/vm/pc.hpp @@ -49,7 +49,7 @@ theEmulatedJamBlockNumber = number(); \ Uint32 tEmulatedJamIndex = theEmulatedJamIndex; \ *(Uint32*)(theEmulatedJam + tEmulatedJamIndex) = \ - ((theEmulatedJamBlockNumber << 20) | line); \ + ((theEmulatedJamBlockNumber << 20) | (line)); \ theEmulatedJamIndex = (tEmulatedJamIndex + 4) & JAM_MASK; } #else @@ -72,7 +72,7 @@ theEmulatedJamBlockNumber = number(); \ Uint32 tEmulatedJamIndex = theEmulatedJamIndex; \ *(Uint32*)((UintPtr)theEmulatedJam + (Uint32)tEmulatedJamIndex) = \ - ((theEmulatedJamBlockNumber << 20) | line); \ + ((theEmulatedJamBlockNumber << 20) | (line)); \ theEmulatedJamIndex = (tEmulatedJamIndex + 4) & JAM_MASK; } #endif @@ -232,7 +232,7 @@ #define MEMCOPY_PAGE(to, from, page_size_in_bytes) \ memcpy((void*)(to), (void*)(from), (size_t)(page_size_in_bytes)); #define MEMCOPY_NO_WORDS(to, from, no_of_words) \ - memcpy((to), (void*)(from), (size_t)(no_of_words << 2)); + memcpy((to), (void*)(from), (size_t)((no_of_words) << 2)); template <class T> struct Ptr { diff --git a/ndb/src/mgmapi/ndb_logevent.cpp b/ndb/src/mgmapi/ndb_logevent.cpp index 3885bb79536..f0b7c26cf78 100644 --- a/ndb/src/mgmapi/ndb_logevent.cpp +++ b/ndb/src/mgmapi/ndb_logevent.cpp @@ -256,7 +256,7 @@ struct Ndb_logevent_body_row ndb_logevent_body[]= { ROW( ReceiveBytesStatistic, "mean_received_bytes", 2, mean_received_bytes), ROW( MemoryUsage, "gth", 1, gth), - ROW( MemoryUsage, "page_size_kb", 2, page_size_kb), + ROW( MemoryUsage, "page_size_bytes", 2, page_size_bytes), ROW( MemoryUsage, "pages_used", 3, pages_used), ROW( MemoryUsage, "pages_total", 4, pages_total), ROW( MemoryUsage, "block", 5, block), diff --git a/ndb/src/mgmclient/CommandInterpreter.cpp b/ndb/src/mgmclient/CommandInterpreter.cpp index 1036461d404..b72f7b12f9b 100644 --- a/ndb/src/mgmclient/CommandInterpreter.cpp +++ b/ndb/src/mgmclient/CommandInterpreter.cpp @@ -921,10 +921,14 @@ event_thread_run(void* p) { do_event_thread= 1; do { - if (ndb_logevent_get_next(log_handle, &log_event, 2000) <= 0) - continue; - Guard g(printmutex); - printLogEvent(&log_event); + int res= ndb_logevent_get_next(log_handle, &log_event, 2000); + if (res > 0) + { + Guard g(printmutex); + printLogEvent(&log_event); + } + else if (res < 0) + break; } while(do_event_thread); ndb_mgm_destroy_logevent_handle(&log_handle); } @@ -2722,8 +2726,9 @@ CommandInterpreter::executeStartBackup(char* parameters, bool interactive) { int count = 0; int retry = 0; + int res; do { - if (ndb_logevent_get_next(log_handle, &log_event, 60000) > 0) + if ((res= ndb_logevent_get_next(log_handle, &log_event, 60000)) > 0) { int print = 0; switch (log_event.type) { @@ -2753,7 +2758,7 @@ CommandInterpreter::executeStartBackup(char* parameters, bool interactive) { retry++; } - } while(count < 2 && retry < 3); + } while(res >= 0 && count < 2 && retry < 3); if (retry >= 3) ndbout << "get backup event failed for " << retry << " times" << endl; diff --git a/ndb/src/mgmsrv/ConfigInfo.cpp b/ndb/src/mgmsrv/ConfigInfo.cpp index 3600dfdeab3..2a22fc72183 100644 --- a/ndb/src/mgmsrv/ConfigInfo.cpp +++ b/ndb/src/mgmsrv/ConfigInfo.cpp @@ -398,7 +398,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::CI_INT, MANDATORY, "1", - STR_VALUE(MAX_NODES) }, + STR_VALUE(MAX_DATA_NODE_ID) }, { CFG_NODE_ID, @@ -410,7 +410,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::CI_INT, MANDATORY, "1", - STR_VALUE(MAX_NODES) }, + STR_VALUE(MAX_DATA_NODE_ID) }, { KEY_INTERNAL, @@ -1261,7 +1261,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::CI_INT, MANDATORY, "1", - STR_VALUE(MAX_NODES) }, + STR_VALUE(MAX_NODES_ID) }, { CFG_NODE_ID, @@ -1273,7 +1273,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::CI_INT, MANDATORY, "1", - STR_VALUE(MAX_NODES) }, + STR_VALUE(MAX_NODES_ID) }, { KEY_INTERNAL, @@ -1404,7 +1404,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::CI_INT, MANDATORY, "1", - STR_VALUE(MAX_NODES) }, + STR_VALUE(MAX_NODES_ID) }, { CFG_NODE_ID, @@ -1416,7 +1416,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::CI_INT, MANDATORY, "1", - STR_VALUE(MAX_NODES) }, + STR_VALUE(MAX_NODES_ID) }, { CFG_LOG_DESTINATION, diff --git a/ndb/src/ndbapi/DictCache.cpp b/ndb/src/ndbapi/DictCache.cpp index 6a815067233..9234b6b5219 100644 --- a/ndb/src/ndbapi/DictCache.cpp +++ b/ndb/src/ndbapi/DictCache.cpp @@ -46,6 +46,7 @@ Ndb_local_table_info::Ndb_local_table_info(NdbTableImpl *table_impl) m_table_impl= table_impl; m_first_tuple_id = ~(Uint64)0; m_last_tuple_id = ~(Uint64)0; + m_highest_seen = 0; } Ndb_local_table_info::~Ndb_local_table_info() diff --git a/ndb/src/ndbapi/DictCache.hpp b/ndb/src/ndbapi/DictCache.hpp index db90a07d487..6ada55cc05e 100644 --- a/ndb/src/ndbapi/DictCache.hpp +++ b/ndb/src/ndbapi/DictCache.hpp @@ -36,6 +36,7 @@ public: // range of cached tuple ids per thread Uint64 m_first_tuple_id; Uint64 m_last_tuple_id; + Uint64 m_highest_seen; Uint64 m_local_data[1]; // Must be last member. Used to access extra space. private: diff --git a/ndb/src/ndbapi/Ndb.cpp b/ndb/src/ndbapi/Ndb.cpp index dcdee3d4ea1..c784f557b4c 100644 --- a/ndb/src/ndbapi/Ndb.cpp +++ b/ndb/src/ndbapi/Ndb.cpp @@ -767,8 +767,8 @@ Ndb::getNodeId() } /**************************************************************************** -Uint64 getAutoIncrementValue( const char* aTableName, - Uint64 & tupleId, +int getAutoIncrementValue( const char* aTableName, + Uint64 & autoValue, Uint32 cacheSize, Uint64 step, Uint64 start); @@ -779,6 +779,7 @@ Parameters: aTableName (IN) : The table name. step (IN) : Specifies the step between the autoincrement values. start (IN) : Start value for first value +Returns: 0 if succesful, -1 if error encountered Remark: Returns a new autoincrement value to the application. The autoincrement values can be increased by steps (default 1) and a number of values can be prefetched @@ -892,9 +893,18 @@ Ndb::getTupleIdFromNdb(Ndb_local_table_info* info, DBUG_RETURN(0); } +/**************************************************************************** +int readAutoIncrementValue( const char* aTableName, + Uint64 & autoValue); + +Parameters: aTableName (IN) : The table name. + autoValue (OUT) : The current autoincrement value +Returns: 0 if succesful, -1 if error encountered +Remark: Returns the current autoincrement value to the application. +****************************************************************************/ int Ndb::readAutoIncrementValue(const char* aTableName, - Uint64 & tupleId) + Uint64 & autoValue) { DBUG_ENTER("Ndb::readAutoIncrementValue"); BaseString internal_tabname(internalize_table_name(aTableName)); @@ -905,15 +915,15 @@ Ndb::readAutoIncrementValue(const char* aTableName, theError.code = theDictionary->getNdbError().code; DBUG_RETURN(-1); } - if (readTupleIdFromNdb(info, tupleId) == -1) + if (readTupleIdFromNdb(info, autoValue) == -1) DBUG_RETURN(-1); - DBUG_PRINT("info", ("value %lu", (ulong)tupleId)); + DBUG_PRINT("info", ("value %lu", (ulong)autoValue)); DBUG_RETURN(0); } int Ndb::readAutoIncrementValue(const NdbDictionary::Table * aTable, - Uint64 & tupleId) + Uint64 & autoValue) { DBUG_ENTER("Ndb::readAutoIncrementValue"); assert(aTable != 0); @@ -926,9 +936,9 @@ Ndb::readAutoIncrementValue(const NdbDictionary::Table * aTable, theError.code = theDictionary->getNdbError().code; DBUG_RETURN(-1); } - if (readTupleIdFromNdb(info, tupleId) == -1) + if (readTupleIdFromNdb(info, autoValue) == -1) DBUG_RETURN(-1); - DBUG_PRINT("info", ("value %lu", (ulong)tupleId)); + DBUG_PRINT("info", ("value %lu", (ulong)autoValue)); DBUG_RETURN(0); } @@ -956,9 +966,20 @@ Ndb::readTupleIdFromNdb(Ndb_local_table_info* info, DBUG_RETURN(0); } +/**************************************************************************** +int setAutoIncrementValue( const char* aTableName, + Uint64 autoValue, + bool modify); + +Parameters: aTableName (IN) : The table name. + autoValue (IN) : The new autoincrement value + modify (IN) : Modify existing value (not initialization) +Returns: 0 if succesful, -1 if error encountered +Remark: Sets a new autoincrement value for the application. +****************************************************************************/ int Ndb::setAutoIncrementValue(const char* aTableName, - Uint64 tupleId, bool increase) + Uint64 autoValue, bool modify) { DBUG_ENTER("Ndb::setAutoIncrementValue"); BaseString internal_tabname(internalize_table_name(aTableName)); @@ -969,14 +990,14 @@ Ndb::setAutoIncrementValue(const char* aTableName, theError.code = theDictionary->getNdbError().code; DBUG_RETURN(-1); } - if (setTupleIdInNdb(info, tupleId, increase) == -1) + if (setTupleIdInNdb(info, autoValue, modify) == -1) DBUG_RETURN(-1); DBUG_RETURN(0); } int Ndb::setAutoIncrementValue(const NdbDictionary::Table * aTable, - Uint64 tupleId, bool increase) + Uint64 autoValue, bool modify) { DBUG_ENTER("Ndb::setAutoIncrementValue"); assert(aTable != 0); @@ -989,38 +1010,42 @@ Ndb::setAutoIncrementValue(const NdbDictionary::Table * aTable, theError.code = theDictionary->getNdbError().code; DBUG_RETURN(-1); } - if (setTupleIdInNdb(info, tupleId, increase) == -1) + if (setTupleIdInNdb(info, autoValue, modify) == -1) DBUG_RETURN(-1); DBUG_RETURN(0); } int Ndb::setTupleIdInNdb(Ndb_local_table_info* info, - Uint64 tupleId, bool increase) + Uint64 tupleId, bool modify) { DBUG_ENTER("Ndb::setTupleIdInNdb"); - if (increase) + if (modify) { - if (info->m_first_tuple_id != info->m_last_tuple_id) + if (checkTupleIdInNdb(info, tupleId)) { - assert(info->m_first_tuple_id < info->m_last_tuple_id); - if (tupleId <= info->m_first_tuple_id + 1) - DBUG_RETURN(0); - if (tupleId <= info->m_last_tuple_id) + if (info->m_first_tuple_id != info->m_last_tuple_id) { - info->m_first_tuple_id = tupleId - 1; - DBUG_PRINT("info", - ("Setting next auto increment cached value to %lu", - (ulong)tupleId)); - DBUG_RETURN(0); + assert(info->m_first_tuple_id < info->m_last_tuple_id); + if (tupleId <= info->m_first_tuple_id + 1) + DBUG_RETURN(0); + if (tupleId <= info->m_last_tuple_id) + { + info->m_first_tuple_id = tupleId - 1; + DBUG_PRINT("info", + ("Setting next auto increment cached value to %lu", + (ulong)tupleId)); + DBUG_RETURN(0); + } } + /* + * if tupleId <= NEXTID, do nothing. otherwise update NEXTID to + * tupleId and set cached range to first = last = tupleId - 1. + */ + Uint64 opValue = tupleId; + if (opTupleIdOnNdb(info, opValue, 2) == -1) + DBUG_RETURN(-1); } - /* - * if tupleId <= NEXTID, do nothing. otherwise update NEXTID to - * tupleId and set cached range to first = last = tupleId - 1. - */ - if (opTupleIdOnNdb(info, tupleId, 2) == -1) - DBUG_RETURN(-1); } else { @@ -1034,6 +1059,32 @@ Ndb::setTupleIdInNdb(Ndb_local_table_info* info, } int +Ndb::checkTupleIdInNdb(Ndb_local_table_info* info, Uint64 tupleId) +{ + DBUG_ENTER("Ndb::checkTupleIdIndNdb"); + if ((info->m_first_tuple_id != ~(Uint64)0) && + (info->m_first_tuple_id > tupleId)) + { + /* + * If we have ever cached a value in this object and this cached + * value is larger than the value we're trying to set then we + * need not check with the real value in the SYSTAB_0 table. + */ + DBUG_RETURN(0); + } + if (info->m_highest_seen > tupleId) + { + /* + * Although we've never cached any higher value we have read + * a higher value and again it isn't necessary to change the + * auto increment value. + */ + DBUG_RETURN(0); + } + DBUG_RETURN(1); +} + +int Ndb::opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 & opValue, Uint32 op) { DBUG_ENTER("Ndb::opTupleIdOnNdb"); @@ -1094,6 +1145,7 @@ Ndb::opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 & opValue, Uint32 op) info->m_first_tuple_id = ~(Uint64)0; info->m_last_tuple_id = ~(Uint64)0; + info->m_highest_seen = 0; break; case 2: tOperation->interpretedUpdateTuple(); @@ -1103,19 +1155,18 @@ Ndb::opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 & opValue, Uint32 op) // compare NEXTID >= opValue tOperation->branch_le(2, 1, 0); tOperation->write_attr("NEXTID", 1); - tOperation->interpret_exit_ok(); tOperation->def_label(0); - tOperation->interpret_exit_nok(9999); - + tOperation->interpret_exit_ok(); + tRecAttrResult = tOperation->getValue("NEXTID"); if (tConnection->execute( Commit ) == -1) { - if (tConnection->theError.code != 9999) - goto error_handler; + goto error_handler; } else { + info->m_highest_seen = tRecAttrResult->u_64_value(); DBUG_PRINT("info", - ("Setting next auto increment value (db) to %lu", + ("Setting auto increment value (db) to %lu", (ulong)opValue)); info->m_first_tuple_id = info->m_last_tuple_id = opValue - 1; } @@ -1126,7 +1177,7 @@ Ndb::opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 & opValue, Uint32 op) tRecAttrResult = tOperation->getValue("NEXTID"); if (tConnection->execute( Commit ) == -1 ) goto error_handler; - opValue = tRecAttrResult->u_64_value(); // out + info->m_highest_seen = opValue = tRecAttrResult->u_64_value(); // out break; default: goto error_handler; @@ -1415,11 +1466,7 @@ Ndb::printState(const char* fmt, ...) NdbMutex_Lock(ndb_print_state_mutex); bool dups = false; unsigned i; - ndbout << buf << " ndb=" << hex << this << dec; -#ifndef NDB_WIN32 - ndbout << " thread=" << (int)pthread_self(); -#endif - ndbout << endl; + ndbout << buf << " ndb=" << hex << (void*)this << endl; for (unsigned n = 0; n < MAX_NDB_NODES; n++) { NdbTransaction* con = theConnectionArray[n]; if (con != 0) { diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/ndb/src/ndbapi/NdbDictionaryImpl.cpp index bf0c02714db..ecbf527c9ae 100644 --- a/ndb/src/ndbapi/NdbDictionaryImpl.cpp +++ b/ndb/src/ndbapi/NdbDictionaryImpl.cpp @@ -35,6 +35,7 @@ #include "NdbBlobImpl.hpp" #include <AttributeHeader.hpp> #include <my_sys.h> +#include <NdbSleep.h> #define DEBUG_PRINT 0 #define INCOMPATIBLE_VERSION -2 @@ -886,7 +887,23 @@ NdbDictInterface::dictSignal(NdbApiSignal* signal, { DBUG_ENTER("NdbDictInterface::dictSignal"); DBUG_PRINT("enter", ("useMasterNodeId: %d", useMasterNodeId)); - for(Uint32 i = 0; i<RETRIES; i++){ + + int sleep = 50; + int mod = 5; + + for(Uint32 i = 0; i<RETRIES; i++) + { + if (i > 0) + NdbSleep_MilliSleep(sleep + 10 * (rand() % mod)); + if (i == RETRIES / 2) + { + mod = 10; + } + if (i == 3*RETRIES/4) + { + sleep = 100; + } + //if (useMasterNodeId == 0) m_buffer.clear(); diff --git a/ndb/src/ndbapi/ndberror.c b/ndb/src/ndbapi/ndberror.c index 4c60e384e6c..27b640489f6 100644 --- a/ndb/src/ndbapi/ndberror.c +++ b/ndb/src/ndbapi/ndberror.c @@ -291,6 +291,7 @@ ErrorBundle ErrorCodes[] = { { 242, AE, "Zero concurrency in scan"}, { 244, AE, "Too high concurrency in scan"}, { 269, AE, "No condition and attributes to read in scan"}, + { 874, AE, "Too much attrinfo (e.g. scan filter) for scan in tuple manager" }, { 4600, AE, "Transaction is already started"}, { 4601, AE, "Transaction is not started"}, { 4602, AE, "You must call getNdbOperation before executeScan" }, diff --git a/ndb/test/ndbapi/testBitfield.cpp b/ndb/test/ndbapi/testBitfield.cpp index 8ba8f3d92ef..40a7a9d4557 100644 --- a/ndb/test/ndbapi/testBitfield.cpp +++ b/ndb/test/ndbapi/testBitfield.cpp @@ -4,6 +4,8 @@ #include <NDBT.hpp> #include <NdbApi.hpp> #include <HugoTransactions.hpp> +#include <Bitmask.hpp> +#include <Vector.hpp> static const char* _dbname = "TEST_DB"; static int g_loops = 7; @@ -37,6 +39,7 @@ static int unique_indexes(Ndb*, const NdbDictionary::Table* tab); static int ordered_indexes(Ndb*, const NdbDictionary::Table* tab); static int node_restart(Ndb*, const NdbDictionary::Table* tab); static int system_restart(Ndb*, const NdbDictionary::Table* tab); +static int testBitmask(); int main(int argc, char** argv){ @@ -49,6 +52,15 @@ main(int argc, char** argv){ ndb_std_get_one_option))) return NDBT_ProgramExit(NDBT_WRONGARGS); + int res = NDBT_FAILED; + + /* Run cluster-independent tests */ + for (int i=0; i<(10*g_loops); i++) + { + if (NDBT_OK != (res= testBitmask())) + return NDBT_ProgramExit(res); + } + Ndb_cluster_connection con(opt_connect_str); if(con.connect(12, 5, 1)) { @@ -60,7 +72,6 @@ main(int argc, char** argv){ pNdb = new Ndb(&con, _dbname); pNdb->init(); while (pNdb->waitUntilReady() != 0); - int res = NDBT_FAILED; NdbDictionary::Dictionary * dict = pNdb->getDictionary(); @@ -121,14 +132,12 @@ create_random_table(Ndb* pNdb) do { NdbDictionary::Table tab; Uint32 cols = 1 + (rand() % (NDB_MAX_ATTRIBUTES_IN_TABLE - 1)); - Uint32 keys = NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY; Uint32 length = 4090; - Uint32 key_size = NDB_MAX_KEYSIZE_IN_WORDS; BaseString name; name.assfmt("TAB_%d", rand() & 65535); tab.setName(name.c_str()); - for(int i = 0; i<cols && length > 2; i++) + for(Uint32 i = 0; i<cols && length > 2; i++) { NdbDictionary::Column col; name.assfmt("COL_%d", i); @@ -206,3 +215,393 @@ system_restart(Ndb* pNdb, const NdbDictionary::Table* tab) { return 0; } + +/* Note : folowing classes test functionality of storage/ndb/src/common/util/Bitmask.cpp + * and were originally defined there. + * Set BITMASK_DEBUG to 1 to get more test debugging info. + */ +#define BITMASK_DEBUG 0 + +static +bool cmp(const Uint32 b1[], const Uint32 b2[], Uint32 len) +{ + Uint32 sz32 = (len + 31) >> 5; + for(Uint32 i = 0; i<len; i++) + { + if(BitmaskImpl::get(sz32, b1, i) ^ BitmaskImpl::get(sz32, b2, i)) + return false; + } + return true; +} + +static +void print(const Uint32 src[], Uint32 len, Uint32 pos = 0) +{ + printf("b'"); + for(unsigned i = 0; i<len; i++) + { + if(BitmaskImpl::get((pos + len + 31) >> 5, src, i+pos)) + printf("1"); + else + printf("0"); + if((i & 31) == 31) + printf(" "); + } +} + +static int lrand() +{ + return rand(); +} + +static +void rand(Uint32 dst[], Uint32 len) +{ + for(Uint32 i = 0; i<len; i++) + BitmaskImpl::set((len + 31) >> 5, dst, i, (lrand() % 1000) > 500); +} + +static +int checkNoTramplingGetSetField(const Uint32 totalTests) +{ + const Uint32 numWords= 67; + const Uint32 maxBitsToCopy= (numWords * 32); + Uint32 sourceBuf[numWords]; + Uint32 targetBuf[numWords]; + + ndbout << "Testing : Bitmask NoTrampling\n"; + + memset(sourceBuf, 0x00, (numWords*4)); + + for (Uint32 test=0; test<totalTests; test++) + { + /* Always copy at least 1 bit */ + Uint32 srcStart= rand() % (maxBitsToCopy -1); + Uint32 length= (rand() % ((maxBitsToCopy -1) - srcStart)) + 1; + + if (BITMASK_DEBUG) + ndbout << "Testing start %u, length %u \n" + << srcStart + << length; + // Set target to all ones. + memset(targetBuf, 0xff, (numWords*4)); + + BitmaskImpl::getField(numWords, sourceBuf, srcStart, length, targetBuf); + + // Check that there is no trampling + Uint32 firstUntrampledWord= (length + 31)/32; + + for (Uint32 word=0; word< numWords; word++) + { + Uint32 targetWord= targetBuf[word]; + if (BITMASK_DEBUG) + ndbout << "word=%d, targetWord=%u, firstUntrampledWord..=%u" + << word << targetWord << firstUntrampledWord; + + if (! (word < firstUntrampledWord) ? + (targetWord == 0) : + (targetWord == 0xffffffff)) + { + ndbout << "Notrampling getField failed for srcStart " + << srcStart + << " length " << length + << " at word " << word << "\n"; + ndbout << "word=%d, targetWord=%u, firstUntrampledWord..=%u" + << word << targetWord << firstUntrampledWord; + return -1; + } + + } + + /* Set target back to all ones. */ + memset(targetBuf, 0xff, (numWords*4)); + + BitmaskImpl::setField(numWords, targetBuf, srcStart, length, sourceBuf); + + /* Check we've got all ones, with zeros only where expected */ + for (Uint32 word=0; word< numWords; word++) + { + Uint32 targetWord= targetBuf[word]; + + for (Uint32 bit=0; bit< 32; bit++) + { + Uint32 bitNum= (word << 5) + bit; + bool expectedValue= !((bitNum >= srcStart) && + (bitNum < (srcStart + length))); + bool actualValue= (((targetWord >> bit) & 1) == 1); + if (BITMASK_DEBUG) + ndbout << "bitNum=%u expectedValue=%u, actual value=%u" + << bitNum << expectedValue << actualValue; + + if (actualValue != expectedValue) + { + ndbout << "Notrampling setField failed for srcStart " + << srcStart + << " length " << length + << " at word " << word << " bit " << bit << "\n"; + ndbout << "bitNum=%u expectedValue=%u, actual value=%u" + << bitNum << expectedValue << actualValue; + return -1; + } + } + } + + } + + return 0; +} + +static +int simple(int pos, int size) +{ + ndbout << "Testing : Bitmask simple pos: " << pos << " size: " << size << "\n"; + Vector<Uint32> _mask; + Vector<Uint32> _src; + Vector<Uint32> _dst; + Uint32 sz32 = (size + pos + 32) >> 5; + const Uint32 sz = 4 * sz32; + + Uint32 zero = 0; + _mask.fill(sz32+1, zero); + _src.fill(sz32+1, zero); + _dst.fill(sz32+1, zero); + + Uint32 * src = _src.getBase(); + Uint32 * dst = _dst.getBase(); + Uint32 * mask = _mask.getBase(); + + memset(src, 0x0, sz); + memset(dst, 0x0, sz); + memset(mask, 0xFF, sz); + rand(src, size); + BitmaskImpl::setField(sz32, mask, pos, size, src); + BitmaskImpl::getField(sz32, mask, pos, size, dst); + if (BITMASK_DEBUG) + { + printf("src: "); print(src, size+31); printf("\n"); + printf("msk: "); print(mask, (sz32 << 5) + 31); printf("\n"); + printf("dst: "); print(dst, size+31); printf("\n"); + } + return (cmp(src, dst, size+31)?0 : -1); +}; + +struct Alloc +{ + Uint32 pos; + Uint32 size; + Vector<Uint32> data; +}; + +static +int +testRanges(Uint32 bitmask_size) +{ + Vector<Alloc> alloc_list; + bitmask_size = (bitmask_size + 31) & ~31; + Uint32 sz32 = (bitmask_size >> 5); + Vector<Uint32> alloc_mask; + Vector<Uint32> test_mask; + + ndbout_c("Testing : Bitmask ranges for bitmask of size %d", bitmask_size); + Uint32 zero = 0; + alloc_mask.fill(sz32, zero); + test_mask.fill(sz32, zero); + + /* Loop a number of times, setting and clearing bits in the mask + * and tracking the modifications in a separate structure. + * Check that both structures remain in sync + */ + for(int i = 0; i<5000; i++) + { + Vector<Uint32> tmp; + tmp.fill(sz32, zero); + + Uint32 pos = lrand() % (bitmask_size - 1); + Uint32 free = 0; + if(BitmaskImpl::get(sz32, alloc_mask.getBase(), pos)) + { + // Bit was allocated + // 1) Look up allocation + // 2) Check data + // 3) free it + size_t j; + Uint32 min, max; + for(j = 0; j<alloc_list.size(); j++) + { + min = alloc_list[j].pos; + max = min + alloc_list[j].size; + if(pos >= min && pos < max) + { + break; + } + } + if (! ((pos >= min) && (pos < max))) + { + printf("Failed with pos %u, min %u, max %u\n", + pos, min, max); + return -1; + } + BitmaskImpl::getField(sz32, test_mask.getBase(), min, max-min, + tmp.getBase()); + if(BITMASK_DEBUG) + { + printf("freeing [ %d %d ]", min, max); + printf("- mask: "); + print(tmp.getBase(), max - min); + + printf(" save: "); + size_t k; + Alloc& a = alloc_list[j]; + for(k = 0; k<a.data.size(); k++) + printf("%.8x ", a.data[k]); + printf("\n"); + } + if(!cmp(tmp.getBase(), alloc_list[j].data.getBase(), max - min)) + { + return -1; + } + while(min < max) + BitmaskImpl::clear(sz32, alloc_mask.getBase(), min++); + alloc_list.erase(j); + } + else + { + Vector<Uint32> tmp; + tmp.fill(sz32, zero); + + // Bit was free + // 1) Check how much space is avaiable + // 2) Create new allocation of lrandom size + // 3) Fill data with lrandom data + // 4) Update alloc mask + while(pos+free < bitmask_size && + !BitmaskImpl::get(sz32, alloc_mask.getBase(), pos+free)) + free++; + + Uint32 sz = + (free <= 64 && ((lrand() % 100) > 80)) ? free : (lrand() % free); + sz = sz ? sz : 1; + sz = pos + sz == bitmask_size ? sz - 1 : sz; + Alloc a; + a.pos = pos; + a.size = sz; + a.data.fill(((sz+31)>> 5)-1, zero); + if(BITMASK_DEBUG) + printf("pos %d -> alloc [ %d %d ]", pos, pos, pos+sz); + for(size_t j = 0; j<sz; j++) + { + BitmaskImpl::set(sz32, alloc_mask.getBase(), pos+j); + if((lrand() % 1000) > 500) + BitmaskImpl::set((sz + 31) >> 5, a.data.getBase(), j); + } + if(BITMASK_DEBUG) + { + printf("- mask: "); + print(a.data.getBase(), sz); + printf("\n"); + } + BitmaskImpl::setField(sz32, test_mask.getBase(), pos, sz, + a.data.getBase()); + alloc_list.push_back(a); + } + } + +#ifdef NDB_BM_SUPPORT_RANGE + for(Uint32 i = 0; i<1000; i++) + { + Uint32 sz32 = 10+rand() % 100; + Uint32 zero = 0; + Vector<Uint32> map; + map.fill(sz32, zero); + + Uint32 sz = 32 * sz32; + Uint32 start = (rand() % sz); + Uint32 stop = start + ((rand() % (sz - start)) & 0xFFFFFFFF); + + Vector<Uint32> check; + check.fill(sz32, zero); + + /* Verify range setting method works correctly */ + for(Uint32 j = 0; j<sz; j++) + { + bool expect = (j >= start && j<stop); + if(expect) + BitmaskImpl::set(sz32, check.getBase(), j); + } + + BitmaskImpl::set_range(sz32, map.getBase(), start, stop); + if (!BitmaskImpl::equal(sz32, map.getBase(), check.getBase())) + { + ndbout_c(" FAIL 1 sz: %d [ %d %d ]", sz, start, stop); + printf("check: "); + for(Uint32 j = 0; j<sz32; j++) + printf("%.8x ", check[j]); + printf("\n"); + + printf("map : "); + for(Uint32 j = 0; j<sz32; j++) + printf("%.8x ", map[j]); + printf("\n"); + return -1; + } + + map.clear(); + check.clear(); + + /* Verify range clearing method works correctly */ + Uint32 one = ~(Uint32)0; + map.fill(sz32, one); + check.fill(sz32, one); + + for(Uint32 j = 0; j<sz; j++) + { + bool expect = (j >= start && j<stop); + if(expect) + BitmaskImpl::clear(sz32, check.getBase(), j); + } + + BitmaskImpl::clear_range(sz32, map.getBase(), start, stop); + if (!BitmaskImpl::equal(sz32, map.getBase(), check.getBase())) + { + ndbout_c(" FAIL 2 sz: %d [ %d %d ]", sz, start, stop); + printf("check: "); + for(Uint32 j = 0; j<sz32; j++) + printf("%.8x ", check[j]); + printf("\n"); + + printf("map : "); + for(Uint32 j = 0; j<sz32; j++) + printf("%.8x ", map[j]); + printf("\n"); + return -1; + } + } +#endif + + return 0; +} + +static +int +testBitmask() +{ + /* Some testcases from storage/ndb/src/common/util/Bitmask.cpp */ + int res= 0; + + if ((res= checkNoTramplingGetSetField(100 /* totalTests */)) != 0) + return res; + + if ((res= simple(rand() % 33, // position + (rand() % 63)+1) // size + ) != 0) + return res; + + if ((res= testRanges(1+(rand() % 1000) // bitmask size + )) != 0) + return res; + + return 0; +} + +template class Vector<Alloc>; +template class Vector<Uint32>; diff --git a/ndb/test/ndbapi/testInterpreter.cpp b/ndb/test/ndbapi/testInterpreter.cpp index 0dc032ba7aa..22b810107b4 100644 --- a/ndb/test/ndbapi/testInterpreter.cpp +++ b/ndb/test/ndbapi/testInterpreter.cpp @@ -77,6 +77,11 @@ int runTestIncValue32(NDBT_Context* ctx, NDBT_Step* step){ const NdbDictionary::Table * pTab = ctx->getTab(); Ndb* pNdb = GETNDB(step); + if (strcmp(pTab->getName(), "T1") != 0) { + g_err << "runTestBug19537: skip, table != T1" << endl; + return NDBT_OK; + } + NdbConnection* pTrans = pNdb->startTransaction(); if (pTrans == NULL){ @@ -258,6 +263,84 @@ int runTestBug19537(NDBT_Context* ctx, NDBT_Step* step){ } +int runTestBug34107(NDBT_Context* ctx, NDBT_Step* step){ + int result = NDBT_OK; + const NdbDictionary::Table * pTab = ctx->getTab(); + Ndb* pNdb = GETNDB(step); + + int i; + for (i = 0; i <= 1; i++) { + g_info << "bug34107:" << (i == 0 ? " small" : " too big") << endl; + + NdbConnection* pTrans = pNdb->startTransaction(); + if (pTrans == NULL){ + ERR(pNdb->getNdbError()); + return NDBT_FAILED; + } + + NdbScanOperation* pOp = pTrans->getNdbScanOperation(pTab->getName()); + if (pOp == NULL) { + ERR(pTrans->getNdbError()); + pNdb->closeTransaction(pTrans); + return NDBT_FAILED; + } + + if (pOp->readTuples() == -1) { + ERR(pOp->getNdbError()); + pNdb->closeTransaction(pTrans); + return NDBT_FAILED; + } + + int n = i == 0 ? 10000 : 30000; + int k; + + for (k = 0; k < n; k++) { + + // inserts 1 word ATTRINFO + + if (pOp->interpret_exit_ok() == -1) { + ERR(pOp->getNdbError()); + pNdb->closeTransaction(pTrans); + return NDBT_FAILED; + } + } + + if (pTrans->execute(NoCommit) == -1) { + ERR(pTrans->getNdbError()); + pNdb->closeTransaction(pTrans); + return NDBT_FAILED; + } + + int ret; + while ((ret = pOp->nextResult()) == 0) + ; + g_info << "ret=" << ret << " err=" << pOp->getNdbError().code << endl; + + if (i == 0 && ret != 1) { + ERR(pTrans->getNdbError()); + pNdb->closeTransaction(pTrans); + return NDBT_FAILED; + } + + if (i == 1 && ret != -1) { + g_err << "unexpected big filter success" << endl; + pNdb->closeTransaction(pTrans); + return NDBT_FAILED; + } + if (i == 1 && pOp->getNdbError().code != 874) { + g_err << "unexpected big filter error code, wanted 874" << endl; + ERR(pTrans->getNdbError()); + pNdb->closeTransaction(pTrans); + return NDBT_FAILED; + } + + pNdb->closeTransaction(pTrans); + } + + return NDBT_OK; +} + + NDBT_TESTSUITE(testInterpreter); TESTCASE("IncValue32", "Test incValue for 32 bit integer\n"){ @@ -277,6 +360,12 @@ TESTCASE("Bug19537", INITIALIZER(runTestBug19537); FINALIZER(runClearTable); } +TESTCASE("Bug34107", + "Test too big scan filter (error 874)\n"){ + INITIALIZER(runLoadTable); + INITIALIZER(runTestBug34107); + FINALIZER(runClearTable); +} #if 0 TESTCASE("MaxTransactions", "Start transactions until no more can be created\n"){ diff --git a/ndb/test/ndbapi/testOIBasic.cpp b/ndb/test/ndbapi/testOIBasic.cpp index 8f77f0bb062..4e1c8400768 100644 --- a/ndb/test/ndbapi/testOIBasic.cpp +++ b/ndb/test/ndbapi/testOIBasic.cpp @@ -36,10 +36,11 @@ struct Opt { // common options - unsigned m_batch; + uint m_batch; const char* m_bound; const char* m_case; bool m_collsp; + bool m_cont; bool m_core; const char* m_csname; CHARSET_INFO* m_cs; @@ -47,26 +48,29 @@ struct Opt { bool m_dups; NdbDictionary::Object::FragmentType m_fragtype; const char* m_index; - unsigned m_loop; + uint m_loop; bool m_msglock; bool m_nologging; bool m_noverify; - unsigned m_pctnull; - unsigned m_rows; - unsigned m_samples; - unsigned m_scanbatch; - unsigned m_scanpar; - unsigned m_scanstop; + uint m_pctnull; + uint m_rows; + uint m_samples; + uint m_scanbatch; + uint m_scanpar; + uint m_scanstop; int m_seed; - unsigned m_subloop; + const char* m_skip; + uint m_sloop; + uint m_ssloop; const char* m_table; - unsigned m_threads; + uint m_threads; int m_v; // int for lint Opt() : m_batch(32), m_bound("01234"), m_case(0), m_collsp(false), + m_cont(false), m_core(false), m_csname("random"), m_cs(0), @@ -85,7 +89,9 @@ struct Opt { m_scanpar(0), m_scanstop(0), m_seed(-1), - m_subloop(4), + m_skip(0), + m_sloop(4), + m_ssloop(4), m_table(0), m_threads(4), m_v(1) { @@ -107,6 +113,7 @@ printhelp() << " -bound xyz use only these bound types 0-4 [" << d.m_bound << "]" << endl << " -case abc only given test cases (letters a-z)" << endl << " -collsp use strnncollsp instead of strnxfrm" << endl + << " -cont on error continue to next test case [" << d.m_cont << "]" << endl << " -core core dump on error [" << d.m_core << "]" << endl << " -csname S charset or collation [" << d.m_csname << "]" << endl << " -die nnn exit immediately on NDB error code nnn" << endl @@ -122,7 +129,9 @@ printhelp() << " -scanbatch N scan batch 0=default [" << d.m_scanbatch << "]" << endl << " -scanpar N scan parallel 0=default [" << d.m_scanpar << "]" << endl << " -seed N srandom seed 0=loop number -1=random [" << d.m_seed << "]" << endl - << " -subloop N subtest (and subsubtest) loop count [" << d.m_subloop << "]" << endl + << " -skip abc skip given test cases (letters a-z)" << endl + << " -sloop N level 2 (sub)loop count [" << d.m_sloop << "]" << endl + << " -ssloop N level 3 (sub)loop count [" << d.m_ssloop << "]" << endl << " -table xyz only given table numbers (digits 0-9)" << endl << " -threads N number of threads [" << d.m_threads << "]" << endl << " -vN verbosity [" << d.m_v << "]" << endl @@ -142,17 +151,17 @@ static const char* hexstr = "0123456789abcdef"; // random ints -static unsigned -urandom(unsigned n) +static uint +urandom(uint n) { if (n == 0) return 0; - unsigned i = random() % n; + uint i = random() % n; return i; } static int -irandom(unsigned n) +irandom(uint n) { if (n == 0) return 0; @@ -163,7 +172,7 @@ irandom(unsigned n) } static bool -randompct(unsigned pct) +randompct(uint pct) { if (pct == 0) return false; @@ -172,15 +181,15 @@ randompct(unsigned pct) return urandom(100) < pct; } -static unsigned -random_coprime(unsigned n) +static uint +random_coprime(uint n) { - unsigned prime[] = { 101, 211, 307, 401, 503, 601, 701, 809, 907 }; - unsigned count = sizeof(prime) / sizeof(prime[0]); + uint prime[] = { 101, 211, 307, 401, 503, 601, 701, 809, 907 }; + uint count = sizeof(prime) / sizeof(prime[0]); if (n == 0) return 0; while (1) { - unsigned i = urandom(count); + uint i = urandom(count); if (n % prime[i] != 0) return prime[i]; } @@ -189,16 +198,16 @@ random_coprime(unsigned n) // random re-sequence of 0...(n-1) struct Rsq { - Rsq(unsigned n); - unsigned next(); + Rsq(uint n); + uint next(); private: - unsigned m_n; - unsigned m_i; - unsigned m_start; - unsigned m_prime; + uint m_n; + uint m_i; + uint m_start; + uint m_prime; }; -Rsq::Rsq(unsigned n) +Rsq::Rsq(uint n) { m_n = n; m_i = 0; @@ -206,7 +215,7 @@ Rsq::Rsq(unsigned n) m_prime = random_coprime(n); } -unsigned +uint Rsq::next() { assert(m_n != 0); @@ -216,30 +225,16 @@ Rsq::next() // log and error macros static NdbMutex *ndbout_mutex = NULL; - -static unsigned getthrno(); - -static const char* -getthrstr() -{ - static char buf[20]; - unsigned n = getthrno(); - if (n == (unsigned)-1) - strcpy(buf, ""); - else { - unsigned m = - g_opt.m_threads < 10 ? 1 : - g_opt.m_threads < 100 ? 2 : 3; - sprintf(buf, "[%0*u] ", m, n); - } - return buf; -} +static const char* getthrprefix(); #define LLN(n, s) \ do { \ if ((n) > g_opt.m_v) break; \ if (g_opt.m_msglock) NdbMutex_Lock(ndbout_mutex); \ - ndbout << getthrstr() << s << endl; \ + ndbout << getthrprefix(); \ + if ((n) > 2) \ + ndbout << "line " << __LINE__ << ": "; \ + ndbout << s << endl; \ if (g_opt.m_msglock) NdbMutex_Unlock(ndbout_mutex); \ } while(0) @@ -250,6 +245,8 @@ getthrstr() #define LL4(s) LLN(4, s) #define LL5(s) LLN(5, s) +#define HEX(x) hex << (x) << dec + // following check a condition and return -1 on failure #undef CHK // simple check @@ -281,53 +278,58 @@ getthrstr() class Thr; class Con; class Tab; +class ITab; class Set; class Tmr; struct Par : public Opt { - unsigned m_no; + uint m_no; Con* m_con; Con& con() const { assert(m_con != 0); return *m_con; } const Tab* m_tab; const Tab& tab() const { assert(m_tab != 0); return *m_tab; } + const ITab* m_itab; + const ITab& itab() const { assert(m_itab != 0); return *m_itab; } Set* m_set; Set& set() const { assert(m_set != 0); return *m_set; } Tmr* m_tmr; Tmr& tmr() const { assert(m_tmr != 0); return *m_tmr; } char m_currcase[2]; - unsigned m_lno; - unsigned m_slno; - unsigned m_totrows; + uint m_lno; + uint m_slno; + uint m_totrows; // value calculation - unsigned m_range; - unsigned m_pctrange; - unsigned m_pctbrange; + uint m_range; + uint m_pctrange; + uint m_pctbrange; int m_bdir; bool m_noindexkeyupdate; // choice of key bool m_randomkey; // do verify after read bool m_verify; - // deadlock possible - bool m_deadlock; - // abort percentabge - unsigned m_abortpct; + // errors to catch (see Con) + bool m_catcherr; + // abort percentage + uint m_abortpct; NdbOperation::LockMode m_lockmode; // scan options bool m_tupscan; bool m_ordered; bool m_descending; - // timer location + // threads used by current test case + uint m_usedthreads; Par(const Opt& opt) : Opt(opt), m_no(0), m_con(0), m_tab(0), + m_itab(0), m_set(0), m_tmr(0), m_lno(0), m_slno(0), - m_totrows(m_threads * m_rows), + m_totrows(0), m_range(m_rows), m_pctrange(40), m_pctbrange(80), @@ -335,39 +337,40 @@ struct Par : public Opt { m_noindexkeyupdate(false), m_randomkey(false), m_verify(false), - m_deadlock(false), + m_catcherr(0), m_abortpct(0), m_lockmode(NdbOperation::LM_Read), m_tupscan(false), m_ordered(false), - m_descending(false) + m_descending(false), + m_usedthreads(0) { m_currcase[0] = 0; } }; static bool -usetable(Par par, unsigned i) +usetable(Par par, uint i) { return par.m_table == 0 || strchr(par.m_table, '0' + i) != 0; } static bool -useindex(Par par, unsigned i) +useindex(Par par, uint i) { return par.m_index == 0 || strchr(par.m_index, '0' + i) != 0; } -static unsigned -thrrow(Par par, unsigned j) +static uint +thrrow(Par par, uint j) { - return par.m_threads * j + par.m_no; + return par.m_usedthreads * j + par.m_no; } static bool -isthrrow(Par par, unsigned i) +isthrrow(Par par, uint i) { - return i % par.m_threads == par.m_no; + return i % par.m_usedthreads == par.m_no; } // timer @@ -375,13 +378,13 @@ isthrrow(Par par, unsigned i) struct Tmr { void clr(); void on(); - void off(unsigned cnt = 0); + void off(uint cnt = 0); const char* time(); const char* pct(const Tmr& t1); const char* over(const Tmr& t1); NDB_TICKS m_on; - unsigned m_ms; - unsigned m_cnt; + uint m_ms; + uint m_cnt; char m_time[100]; char m_text[100]; Tmr() { clr(); } @@ -401,7 +404,7 @@ Tmr::on() } void -Tmr::off(unsigned cnt) +Tmr::off(uint cnt) { NDB_TICKS off = NdbTick_CurrentMillisecond(); assert(m_on != 0 && off >= m_on); @@ -446,53 +449,18 @@ Tmr::over(const Tmr& t1) return m_text; } -// list of ints - -struct Lst { - Lst(); - unsigned m_arr[1000]; - unsigned m_cnt; - void push(unsigned i); - unsigned cnt() const; - void reset(); -}; - -Lst::Lst() : - m_cnt(0) -{ -} - -void -Lst::push(unsigned i) -{ - assert(m_cnt < sizeof(m_arr)/sizeof(m_arr[0])); - m_arr[m_cnt++] = i; -} - -unsigned -Lst::cnt() const -{ - return m_cnt; -} - -void -Lst::reset() -{ - m_cnt = 0; -} - // character sets -static const unsigned maxcsnumber = 512; -static const unsigned maxcharcount = 32; -static const unsigned maxcharsize = 4; -static const unsigned maxxmulsize = 8; +static const uint maxcsnumber = 512; +static const uint maxcharcount = 32; +static const uint maxcharsize = 4; +static const uint maxxmulsize = 8; // single mb char struct Chr { - unsigned char m_bytes[maxcharsize]; - unsigned char m_xbytes[maxxmulsize * maxcharsize]; - unsigned m_size; + uchar m_bytes[maxcharsize]; + uchar m_xbytes[maxxmulsize * maxcharsize]; + uint m_size; Chr(); }; @@ -506,7 +474,7 @@ Chr::Chr() // charset and random valid chars to use struct Chs { CHARSET_INFO* m_cs; - unsigned m_xmul; + uint m_xmul; Chr* m_chr; Chs(CHARSET_INFO* cs); ~Chs(); @@ -523,22 +491,22 @@ Chs::Chs(CHARSET_INFO* cs) : m_xmul = 1; assert(m_xmul <= maxxmulsize); m_chr = new Chr [maxcharcount]; - unsigned i = 0; - unsigned miss1 = 0; - unsigned miss2 = 0; - unsigned miss3 = 0; - unsigned miss4 = 0; + uint i = 0; + uint miss1 = 0; + uint miss2 = 0; + uint miss3 = 0; + uint miss4 = 0; while (i < maxcharcount) { - unsigned char* bytes = m_chr[i].m_bytes; - unsigned char* xbytes = m_chr[i].m_xbytes; - unsigned& size = m_chr[i].m_size; + uchar* bytes = m_chr[i].m_bytes; + uchar* xbytes = m_chr[i].m_xbytes; + uint& size = m_chr[i].m_size; bool ok; size = m_cs->mbminlen + urandom(m_cs->mbmaxlen - m_cs->mbminlen + 1); assert(m_cs->mbminlen <= size && size <= m_cs->mbmaxlen); // prefer longer chars if (size == m_cs->mbminlen && m_cs->mbminlen < m_cs->mbmaxlen && urandom(5) != 0) continue; - for (unsigned j = 0; j < size; j++) { + for (uint j = 0; j < size; j++) { bytes[j] = urandom(256); } int not_used; @@ -550,13 +518,13 @@ Chs::Chs(CHARSET_INFO* cs) : } // check no proper prefix wellformed ok = true; - for (unsigned j = 1; j < size; j++) { + for (uint j = 1; j < size; j++) { if ((*cs->cset->well_formed_len)(cs, sbytes, sbytes + j, 1, ¬_used) == j) { ok = false; break; } } - if (! ok) { + if (!ok) { miss2++; continue; } @@ -566,37 +534,37 @@ Chs::Chs(CHARSET_INFO* cs) : int xlen = (*cs->coll->strnxfrm)(cs, xbytes, m_xmul * size, bytes, size); // check we got something ok = false; - for (unsigned j = 0; j < xlen; j++) { + for (uint j = 0; j < xlen; j++) { if (xbytes[j] != 0) { ok = true; break; } } - if (! ok) { + if (!ok) { miss3++; continue; } // check for duplicate (before normalize) ok = true; - for (unsigned j = 0; j < i; j++) { + for (uint j = 0; j < i; j++) { const Chr& chr = m_chr[j]; if (chr.m_size == size && memcmp(chr.m_bytes, bytes, size) == 0) { ok = false; break; } } - if (! ok) { + if (!ok) { miss4++; continue; } i++; } bool disorder = true; - unsigned bubbles = 0; + uint bubbles = 0; while (disorder) { disorder = false; - for (unsigned i = 1; i < maxcharcount; i++) { - unsigned len = sizeof(m_chr[i].m_xbytes); + for (uint i = 1; i < maxcharcount; i++) { + uint len = sizeof(m_chr[i].m_xbytes); if (memcmp(m_chr[i-1].m_xbytes, m_chr[i].m_xbytes, len) > 0) { Chr chr = m_chr[i]; m_chr[i] = m_chr[i-1]; @@ -627,7 +595,7 @@ static Chs* cslist[maxcsnumber]; static void resetcslist() { - for (unsigned i = 0; i < maxcsnumber; i++) { + for (uint i = 0; i < maxcsnumber; i++) { delete cslist[i]; cslist[i] = 0; } @@ -641,7 +609,7 @@ getcs(Par par) cs = par.m_cs; } else { while (1) { - unsigned n = urandom(maxcsnumber); + uint n = urandom(maxcsnumber); cs = get_charset(n, MYF(0)); if (cs != 0) { // prefer complex charsets @@ -667,24 +635,24 @@ struct Col { Longvarchar = NdbDictionary::Column::Longvarchar }; const class Tab& m_tab; - unsigned m_num; + uint m_num; const char* m_name; bool m_pk; Type m_type; - unsigned m_length; - unsigned m_bytelength; // multiplied by char width - unsigned m_attrsize; // base type size - unsigned m_headsize; // length bytes - unsigned m_bytesize; // full value size + uint m_length; + uint m_bytelength; // multiplied by char width + uint m_attrsize; // base type size + uint m_headsize; // length bytes + uint m_bytesize; // full value size bool m_nullable; const Chs* m_chs; - Col(const class Tab& tab, unsigned num, const char* name, bool pk, Type type, unsigned length, bool nullable, const Chs* chs); + Col(const class Tab& tab, uint num, const char* name, bool pk, Type type, uint length, bool nullable, const Chs* chs); ~Col(); bool equal(const Col& col2) const; void wellformed(const void* addr) const; }; -Col::Col(const class Tab& tab, unsigned num, const char* name, bool pk, Type type, unsigned length, bool nullable, const Chs* chs) : +Col::Col(const class Tab& tab, uint num, const char* name, bool pk, Type type, uint length, bool nullable, const Chs* chs) : m_tab(tab), m_num(num), m_name(strcpy(new char [strlen(name) + 1], name)), @@ -735,7 +703,7 @@ Col::wellformed(const void* addr) const { CHARSET_INFO* cs = m_chs->m_cs; const char* src = (const char*)addr; - unsigned len = m_bytelength; + uint len = m_bytelength; int not_used; assert((*cs->cset->well_formed_len)(cs, src, src + len, 0xffff, ¬_used) == len); } @@ -743,9 +711,9 @@ Col::wellformed(const void* addr) const case Col::Varchar: { CHARSET_INFO* cs = m_chs->m_cs; - const unsigned char* src = (const unsigned char*)addr; + const uchar* src = (const uchar*)addr; const char* ssrc = (const char*)src; - unsigned len = src[0]; + uint len = src[0]; int not_used; assert(len <= m_bytelength); assert((*cs->cset->well_formed_len)(cs, ssrc + 1, ssrc + 1 + len, 0xffff, ¬_used) == len); @@ -754,9 +722,9 @@ Col::wellformed(const void* addr) const case Col::Longvarchar: { CHARSET_INFO* cs = m_chs->m_cs; - const unsigned char* src = (const unsigned char*)addr; + const uchar* src = (const uchar*)addr; const char* ssrc = (const char*)src; - unsigned len = src[0] + (src[1] << 8); + uint len = src[0] + (src[1] << 8); int not_used; assert(len <= m_bytelength); assert((*cs->cset->well_formed_len)(cs, ssrc + 2, ssrc + 2 + len, 0xffff, ¬_used) == len); @@ -774,7 +742,7 @@ operator<<(NdbOut& out, const Col& col) out << "col[" << col.m_num << "] " << col.m_name; switch (col.m_type) { case Col::Unsigned: - out << " unsigned"; + out << " uint"; break; case Col::Char: { @@ -808,13 +776,13 @@ operator<<(NdbOut& out, const Col& col) struct ICol { const class ITab& m_itab; - unsigned m_num; + uint m_num; const Col& m_col; - ICol(const class ITab& itab, unsigned num, const Col& col); + ICol(const class ITab& itab, uint num, const Col& col); ~ICol(); }; -ICol::ICol(const class ITab& itab, unsigned num, const Col& col) : +ICol::ICol(const class ITab& itab, uint num, const Col& col) : m_itab(itab), m_num(num), m_col(col) @@ -842,47 +810,47 @@ struct ITab { const class Tab& m_tab; const char* m_name; Type m_type; - unsigned m_icols; + uint m_icols; const ICol** m_icol; - unsigned m_colmask; - ITab(const class Tab& tab, const char* name, Type type, unsigned icols); + uint m_keymask; + ITab(const class Tab& tab, const char* name, Type type, uint icols); ~ITab(); - void icoladd(unsigned k, const ICol* icolptr); + void icoladd(uint k, const ICol* icolptr); }; -ITab::ITab(const class Tab& tab, const char* name, Type type, unsigned icols) : +ITab::ITab(const class Tab& tab, const char* name, Type type, uint icols) : m_tab(tab), m_name(strcpy(new char [strlen(name) + 1], name)), m_type(type), m_icols(icols), m_icol(new const ICol* [icols + 1]), - m_colmask(0) + m_keymask(0) { - for (unsigned k = 0; k <= m_icols; k++) + for (uint k = 0; k <= m_icols; k++) m_icol[k] = 0; } ITab::~ITab() { delete [] m_name; - for (unsigned i = 0; i < m_icols; i++) + for (uint i = 0; i < m_icols; i++) delete m_icol[i]; delete [] m_icol; } void -ITab::icoladd(unsigned k, const ICol* icolptr) +ITab::icoladd(uint k, const ICol* icolptr) { assert(k == icolptr->m_num && k < m_icols && m_icol[k] == 0); m_icol[k] = icolptr; - m_colmask |= (1 << icolptr->m_col.m_num); + m_keymask |= (1 << icolptr->m_col.m_num); } static NdbOut& operator<<(NdbOut& out, const ITab& itab) { out << "itab " << itab.m_name << " icols=" << itab.m_icols; - for (unsigned k = 0; k < itab.m_icols; k++) { + for (uint k = 0; k < itab.m_icols; k++) { const ICol& icol = *itab.m_icol[k]; out << endl << icol; } @@ -893,56 +861,60 @@ operator<<(NdbOut& out, const ITab& itab) struct Tab { const char* m_name; - unsigned m_cols; + uint m_cols; const Col** m_col; - unsigned m_itabs; + uint m_pkmask; + uint m_itabs; const ITab** m_itab; - unsigned m_orderedindexes; - unsigned m_hashindexes; + uint m_orderedindexes; + uint m_hashindexes; // pk must contain an Unsigned column - unsigned m_keycol; - void coladd(unsigned k, Col* colptr); - void itabadd(unsigned j, ITab* itab); - Tab(const char* name, unsigned cols, unsigned itabs, unsigned keycol); + uint m_keycol; + void coladd(uint k, Col* colptr); + void itabadd(uint j, ITab* itab); + Tab(const char* name, uint cols, uint itabs, uint keycol); ~Tab(); }; -Tab::Tab(const char* name, unsigned cols, unsigned itabs, unsigned keycol) : +Tab::Tab(const char* name, uint cols, uint itabs, uint keycol) : m_name(strcpy(new char [strlen(name) + 1], name)), m_cols(cols), m_col(new const Col* [cols + 1]), + m_pkmask(0), m_itabs(itabs), m_itab(new const ITab* [itabs + 1]), m_orderedindexes(0), m_hashindexes(0), m_keycol(keycol) { - for (unsigned k = 0; k <= cols; k++) + for (uint k = 0; k <= cols; k++) m_col[k] = 0; - for (unsigned j = 0; j <= itabs; j++) + for (uint j = 0; j <= itabs; j++) m_itab[j] = 0; } Tab::~Tab() { delete [] m_name; - for (unsigned i = 0; i < m_cols; i++) + for (uint i = 0; i < m_cols; i++) delete m_col[i]; delete [] m_col; - for (unsigned i = 0; i < m_itabs; i++) + for (uint i = 0; i < m_itabs; i++) delete m_itab[i]; delete [] m_itab; } void -Tab::coladd(unsigned k, Col* colptr) +Tab::coladd(uint k, Col* colptr) { assert(k == colptr->m_num && k < m_cols && m_col[k] == 0); m_col[k] = colptr; + if (colptr->m_pk) + m_pkmask |= (1 << k); } void -Tab::itabadd(unsigned j, ITab* itabptr) +Tab::itabadd(uint j, ITab* itabptr) { assert(j < m_itabs && m_itab[j] == 0 && itabptr != 0); m_itab[j] = itabptr; @@ -956,11 +928,11 @@ static NdbOut& operator<<(NdbOut& out, const Tab& tab) { out << "tab " << tab.m_name << " cols=" << tab.m_cols; - for (unsigned k = 0; k < tab.m_cols; k++) { + for (uint k = 0; k < tab.m_cols; k++) { const Col& col = *tab.m_col[k]; out << endl << col; } - for (unsigned i = 0; i < tab.m_itabs; i++) { + for (uint i = 0; i < tab.m_itabs; i++) { if (tab.m_itab[i] == 0) continue; const ITab& itab = *tab.m_itab[i]; @@ -972,20 +944,20 @@ operator<<(NdbOut& out, const Tab& tab) // make table structs static const Tab** tablist = 0; -static unsigned tabcount = 0; +static uint tabcount = 0; static void verifytables() { - for (unsigned j = 0; j < tabcount; j++) { + for (uint j = 0; j < tabcount; j++) { const Tab* t = tablist[j]; if (t == 0) continue; assert(t->m_cols != 0 && t->m_col != 0); - for (unsigned k = 0; k < t->m_cols; k++) { + for (uint k = 0; k < t->m_cols; k++) { const Col* c = t->m_col[k]; assert(c != 0 && c->m_num == k); - assert(! (c->m_pk && c->m_nullable)); + assert(!(c->m_pk && c->m_nullable)); } assert(t->m_col[t->m_cols] == 0); { @@ -994,16 +966,16 @@ verifytables() assert(c->m_pk && c->m_type == Col::Unsigned); } assert(t->m_itabs != 0 && t->m_itab != 0); - for (unsigned i = 0; i < t->m_itabs; i++) { + for (uint i = 0; i < t->m_itabs; i++) { const ITab* x = t->m_itab[i]; if (x == 0) continue; assert(x != 0 && x->m_icols != 0 && x->m_icol != 0); - for (unsigned k = 0; k < x->m_icols; k++) { + for (uint k = 0; k < x->m_icols; k++) { const ICol* c = x->m_icol[k]; assert(c != 0 && c->m_num == k && c->m_col.m_num < t->m_cols); if (x->m_type == ITab::UniqueHashIndex) { - assert(! c->m_col.m_nullable); + assert(!c->m_col.m_nullable); } } } @@ -1019,11 +991,11 @@ makebuiltintables(Par par) tabcount = 3; if (tablist == 0) { tablist = new const Tab* [tabcount]; - for (unsigned j = 0; j < tabcount; j++) { + for (uint j = 0; j < tabcount; j++) { tablist[j] = 0; } } else { - for (unsigned j = 0; j < tabcount; j++) { + for (uint j = 0; j < tabcount; j++) { delete tablist[j]; tablist[j] = 0; } @@ -1202,7 +1174,8 @@ static Ndb_cluster_connection* g_ncc = 0; struct Con { Ndb* m_ndb; NdbDictionary::Dictionary* m_dic; - NdbConnection* m_tx; + NdbTransaction* m_tx; + Uint64 m_txid; NdbOperation* m_op; NdbIndexOperation* m_indexop; NdbScanOperation* m_scanop; @@ -1210,10 +1183,16 @@ struct Con { NdbScanFilter* m_scanfilter; enum ScanMode { ScanNo = 0, Committed, Latest, Exclusive }; ScanMode m_scanmode; - enum ErrType { ErrNone = 0, ErrDeadlock, ErrNospace, ErrOther }; + enum ErrType { + ErrNone = 0, + ErrDeadlock = 1, + ErrNospace = 2, + ErrOther = 4 + }; ErrType m_errtype; + char m_errname[100]; Con() : - m_ndb(0), m_dic(0), m_tx(0), m_op(0), m_indexop(0), + m_ndb(0), m_dic(0), m_tx(0), m_txid(0), m_op(0), m_indexop(0), m_scanop(0), m_indexscanop(0), m_scanfilter(0), m_scanmode(ScanNo), m_errtype(ErrNone) {} ~Con() { @@ -1237,18 +1216,20 @@ struct Con { int setBound(int num, int type, const void* value); int beginFilter(int group); int endFilter(); - int setFilter(int num, int cond, const void* value, unsigned len); - int execute(ExecType t); - int execute(ExecType t, bool& deadlock, bool& nospace); + int setFilter(int num, int cond, const void* value, uint len); + int execute(ExecType et); + int execute(ExecType et, uint& err); + int readTuple(Par par); int readTuples(Par par); int readIndexTuples(Par par); int executeScan(); int nextScanResult(bool fetchAllowed); - int nextScanResult(bool fetchAllowed, bool& deadlock); + int nextScanResult(bool fetchAllowed, uint& err); int updateScanTuple(Con& con2); int deleteScanTuple(Con& con2); void closeScan(); void closeTransaction(); + const char* errname(uint err); void printerror(NdbOut& out); }; @@ -1259,7 +1240,7 @@ Con::connect() m_ndb = new Ndb(g_ncc, "TEST_DB"); CHKCON(m_ndb->init() == 0, *this); CHKCON(m_ndb->waitUntilReady(30) == 0, *this); - m_tx = 0, m_op = 0; + m_tx = 0, m_txid = 0, m_op = 0; return 0; } @@ -1274,7 +1255,7 @@ void Con::disconnect() { delete m_ndb; - m_ndb = 0, m_dic = 0, m_tx = 0, m_op = 0; + m_ndb = 0, m_dic = 0, m_tx = 0, m_txid = 0, m_op = 0; } int @@ -1284,6 +1265,7 @@ Con::startTransaction() if (m_tx != 0) closeTransaction(); CHKCON((m_tx = m_ndb->startTransaction()) != 0, *this); + m_txid = m_tx->getTransactionId(); return 0; } @@ -1307,7 +1289,7 @@ int Con::getNdbIndexOperation(const ITab& itab, const Tab& tab) { assert(m_tx != 0); - unsigned tries = 0; + uint tries = 0; while (1) { if (getNdbIndexOperation1(itab, tab) == 0) break; @@ -1337,7 +1319,7 @@ int Con::getNdbIndexScanOperation(const ITab& itab, const Tab& tab) { assert(m_tx != 0); - unsigned tries = 0; + uint tries = 0; while (1) { if (getNdbIndexScanOperation1(itab, tab) == 0) break; @@ -1405,7 +1387,7 @@ Con::endFilter() } int -Con::setFilter(int num, int cond, const void* value, unsigned len) +Con::setFilter(int num, int cond, const void* value, uint len) { assert(m_tx != 0 && m_scanfilter != 0); CHKCON(m_scanfilter->cmp((NdbScanFilter::BinaryCondition)cond, num, value, len) == 0, *this); @@ -1413,34 +1395,46 @@ Con::setFilter(int num, int cond, const void* value, unsigned len) } int -Con::execute(ExecType t) +Con::execute(ExecType et) { assert(m_tx != 0); - CHKCON(m_tx->execute(t) == 0, *this); + CHKCON(m_tx->execute(et) == 0, *this); return 0; } int -Con::execute(ExecType t, bool& deadlock, bool& nospace) +Con::execute(ExecType et, uint& err) { - int ret = execute(t); - if (ret != 0 && deadlock && m_errtype == ErrDeadlock) { - LL3("caught deadlock"); - ret = 0; - } else { - deadlock = false; - } - if (ret != 0 && nospace && m_errtype == ErrNospace) { - LL3("caught nospace"); - ret = 0; - } else { - nospace = false; + int ret = execute(et); + // err in: errors to catch, out: error caught + const uint errin = err; + err = 0; + if (ret == -1) { + if (m_errtype == ErrDeadlock && (errin & ErrDeadlock)) { + LL3("caught deadlock"); + err = ErrDeadlock; + ret = 0; + } + if (m_errtype == ErrNospace && (errin & ErrNospace)) { + LL3("caught nospace"); + err = ErrNospace; + ret = 0; + } } CHK(ret == 0); return 0; } int +Con::readTuple(Par par) +{ + assert(m_tx != 0 && m_op != 0); + NdbOperation::LockMode lm = par.m_lockmode; + CHKCON(m_op->readTuple(lm) == 0, *this); + return 0; +} + +int Con::readTuples(Par par) { assert(m_tx != 0 && m_scanop != 0); @@ -1477,23 +1471,25 @@ Con::nextScanResult(bool fetchAllowed) int ret; assert(m_scanop != 0); CHKCON((ret = m_scanop->nextResult(fetchAllowed)) != -1, *this); - assert(ret == 0 || ret == 1 || (! fetchAllowed && ret == 2)); + assert(ret == 0 || ret == 1 || (!fetchAllowed && ret == 2)); return ret; } int -Con::nextScanResult(bool fetchAllowed, bool& deadlock) +Con::nextScanResult(bool fetchAllowed, uint& err) { int ret = nextScanResult(fetchAllowed); + // err in: errors to catch, out: error caught + const uint errin = err; + err = 0; if (ret == -1) { - if (deadlock && m_errtype == ErrDeadlock) { + if (m_errtype == ErrDeadlock && (errin & ErrDeadlock)) { LL3("caught deadlock"); + err = ErrDeadlock; ret = 0; } - } else { - deadlock = false; } - CHK(ret == 0 || ret == 1 || (! fetchAllowed && ret == 2)); + CHK(ret == 0 || ret == 1 || (!fetchAllowed && ret == 2)); return ret; } @@ -1502,6 +1498,7 @@ Con::updateScanTuple(Con& con2) { assert(con2.m_tx != 0); CHKCON((con2.m_op = m_scanop->updateCurrentTuple(con2.m_tx)) != 0, *this); + con2.m_txid = m_txid; // in the kernel return 0; } @@ -1510,6 +1507,7 @@ Con::deleteScanTuple(Con& con2) { assert(con2.m_tx != 0); CHKCON(m_scanop->deleteCurrentTuple(con2.m_tx) == 0, *this); + con2.m_txid = m_txid; // in the kernel return 0; } @@ -1527,15 +1525,26 @@ Con::closeTransaction() { assert(m_ndb != 0 && m_tx != 0); m_ndb->closeTransaction(m_tx); - m_tx = 0, m_op = 0; + m_tx = 0, m_txid = 0, m_op = 0; m_scanop = 0, m_indexscanop = 0; } +const char* +Con::errname(uint err) +{ + sprintf(m_errname, "0x%x", err); + if (err & ErrDeadlock) + strcat(m_errname, ",deadlock"); + if (err & ErrNospace) + strcat(m_errname, ",nospace"); + return m_errname; +} + void Con::printerror(NdbOut& out) { m_errtype = ErrOther; - unsigned any = 0; + uint any = 0; int code; int die = 0; if (m_ndb) { @@ -1563,7 +1572,7 @@ Con::printerror(NdbOut& out) } } } - if (! any) { + if (!any) { LL0("failed but no NDB error code"); } if (die) { @@ -1589,7 +1598,7 @@ invalidateindex(Par par) { Con& con = par.con(); const Tab& tab = par.tab(); - for (unsigned i = 0; i < tab.m_itabs; i++) { + for (uint i = 0; i < tab.m_itabs; i++) { if (tab.m_itab[i] == 0) continue; const ITab& itab = *tab.m_itab[i]; @@ -1639,7 +1648,7 @@ createtable(Par par) if (par.m_nologging) { t.setLogging(false); } - for (unsigned k = 0; k < tab.m_cols; k++) { + for (uint k = 0; k < tab.m_cols; k++) { const Col& col = *tab.m_col[k]; NdbDictionary::Column c(col.m_name); c.setType((NdbDictionary::Column::Type)col.m_type); @@ -1677,7 +1686,7 @@ static int dropindex(Par par) { const Tab& tab = par.tab(); - for (unsigned i = 0; i < tab.m_itabs; i++) { + for (uint i = 0; i < tab.m_itabs; i++) { if (tab.m_itab[i] == 0) continue; const ITab& itab = *tab.m_itab[i]; @@ -1699,7 +1708,7 @@ createindex(Par par, const ITab& itab) if (par.m_nologging || itab.m_type == ITab::OrderedIndex) { x.setLogging(false); } - for (unsigned k = 0; k < itab.m_icols; k++) { + for (uint k = 0; k < itab.m_icols; k++) { const ICol& icol = *itab.m_icol[k]; const Col& col = icol.m_col; x.addColumnName(col.m_name); @@ -1714,7 +1723,7 @@ static int createindex(Par par) { const Tab& tab = par.tab(); - for (unsigned i = 0; i < tab.m_itabs; i++) { + for (uint i = 0; i < tab.m_itabs; i++) { if (tab.m_itab[i] == 0) continue; const ITab& itab = *tab.m_itab[i]; @@ -1731,27 +1740,29 @@ struct Val { const Col& m_col; union { Uint32 m_uint32; - unsigned char* m_char; - unsigned char* m_varchar; - unsigned char* m_longvarchar; + uchar* m_char; + uchar* m_varchar; + uchar* m_longvarchar; }; + bool m_null; + // construct Val(const Col& col); ~Val(); void copy(const Val& val2); void copy(const void* addr); const void* dataaddr() const; - bool m_null; - int equal(Par par) const; - int equal(Par par, const ICol& icol) const; - int setval(Par par) const; - void calc(Par par, unsigned i); - void calckey(Par par, unsigned i); - void calckeychars(Par par, unsigned i, unsigned& n, unsigned char* buf); + void calc(Par par, uint i); + void calckey(Par par, uint i); + void calckeychars(Par par, uint i, uint& n, uchar* buf); void calcnokey(Par par); - void calcnokeychars(Par par, unsigned& n, unsigned char* buf); - int verify(Par par, const Val& val2) const; + void calcnokeychars(Par par, uint& n, uchar* buf); + // operations + int setval(Par par) const; + int setval(Par par, const ICol& icol) const; + // compare int cmp(Par par, const Val& val2) const; - int cmpchars(Par par, const unsigned char* buf1, unsigned len1, const unsigned char* buf2, unsigned len2) const; + int cmpchars(Par par, const uchar* buf1, uint len1, const uchar* buf2, uint len2) const; + int verify(Par par, const Val& val2) const; private: Val& operator=(const Val& val2); }; @@ -1759,20 +1770,26 @@ private: static NdbOut& operator<<(NdbOut& out, const Val& val); +// construct + Val::Val(const Col& col) : m_col(col) { switch (col.m_type) { case Col::Unsigned: + m_uint32 = 0x7e7e7e7e; break; case Col::Char: - m_char = new unsigned char [col.m_bytelength]; + m_char = new uchar [col.m_bytelength]; + memset(m_char, 0x7e, col.m_bytelength); break; case Col::Varchar: - m_varchar = new unsigned char [1 + col.m_bytelength]; + m_varchar = new uchar [1 + col.m_bytelength]; + memset(m_char, 0x7e, 1 + col.m_bytelength); break; case Col::Longvarchar: - m_longvarchar = new unsigned char [2 + col.m_bytelength]; + m_longvarchar = new uchar [2 + col.m_bytelength]; + memset(m_char, 0x7e, 2 + col.m_bytelength); break; default: assert(false); @@ -1858,52 +1875,17 @@ Val::dataaddr() const return 0; } -int -Val::equal(Par par) const -{ - Con& con = par.con(); - const Col& col = m_col; - assert(col.m_pk && ! m_null); - const char* addr = (const char*)dataaddr(); - LL5("equal [" << col << "] " << *this); - CHK(con.equal(col.m_num, addr) == 0); - return 0; -} - -int -Val::equal(Par par, const ICol& icol) const -{ - Con& con = par.con(); - assert(! m_null); - const char* addr = (const char*)dataaddr(); - LL5("equal [" << icol << "] " << *this); - CHK(con.equal(icol.m_num, addr) == 0); - return 0; -} - -int -Val::setval(Par par) const -{ - Con& con = par.con(); - const Col& col = m_col; - assert(! col.m_pk); - const char* addr = ! m_null ? (const char*)dataaddr() : 0; - LL5("setval [" << col << "] " << *this); - CHK(con.setValue(col.m_num, addr) == 0); - return 0; -} - void -Val::calc(Par par, unsigned i) +Val::calc(Par par, uint i) { const Col& col = m_col; col.m_pk ? calckey(par, i) : calcnokey(par); - if (! m_null) + if (!m_null) col.wellformed(dataaddr()); } void -Val::calckey(Par par, unsigned i) +Val::calckey(Par par, uint i) { const Col& col = m_col; m_null = false; @@ -1915,7 +1897,7 @@ Val::calckey(Par par, unsigned i) { const Chs* chs = col.m_chs; CHARSET_INFO* cs = chs->m_cs; - unsigned n = 0; + uint n = 0; calckeychars(par, i, n, m_char); // extend by appropriate space (*cs->cset->fill)(cs, (char*)&m_char[n], col.m_bytelength - n, 0x20); @@ -1923,7 +1905,7 @@ Val::calckey(Par par, unsigned i) break; case Col::Varchar: { - unsigned n = 0; + uint n = 0; calckeychars(par, i, n, m_varchar + 1); // set length and pad with nulls m_varchar[0] = n; @@ -1932,7 +1914,7 @@ Val::calckey(Par par, unsigned i) break; case Col::Longvarchar: { - unsigned n = 0; + uint n = 0; calckeychars(par, i, n, m_longvarchar + 2); // set length and pad with nulls m_longvarchar[0] = (n & 0xff); @@ -1947,13 +1929,13 @@ Val::calckey(Par par, unsigned i) } void -Val::calckeychars(Par par, unsigned i, unsigned& n, unsigned char* buf) +Val::calckeychars(Par par, uint i, uint& n, uchar* buf) { const Col& col = m_col; const Chs* chs = col.m_chs; CHARSET_INFO* cs = chs->m_cs; n = 0; - unsigned len = 0; + uint len = 0; while (len < col.m_length) { if (i % (1 + n) == 0) { break; @@ -1980,7 +1962,7 @@ Val::calcnokey(Par par) if (r < 0 && par.m_bdir > 0 || r > 0 && par.m_bdir < 0) r = -r; } - unsigned v = par.m_range + r; + uint v = par.m_range + r; switch (col.m_type) { case Col::Unsigned: m_uint32 = v; @@ -1989,7 +1971,7 @@ Val::calcnokey(Par par) { const Chs* chs = col.m_chs; CHARSET_INFO* cs = chs->m_cs; - unsigned n = 0; + uint n = 0; calcnokeychars(par, n, m_char); // extend by appropriate space (*cs->cset->fill)(cs, (char*)&m_char[n], col.m_bytelength - n, 0x20); @@ -1997,7 +1979,7 @@ Val::calcnokey(Par par) break; case Col::Varchar: { - unsigned n = 0; + uint n = 0; calcnokeychars(par, n, m_varchar + 1); // set length and pad with nulls m_varchar[0] = n; @@ -2006,7 +1988,7 @@ Val::calcnokey(Par par) break; case Col::Longvarchar: { - unsigned n = 0; + uint n = 0; calcnokeychars(par, n, m_longvarchar + 2); // set length and pad with nulls m_longvarchar[0] = (n & 0xff); @@ -2021,24 +2003,24 @@ Val::calcnokey(Par par) } void -Val::calcnokeychars(Par par, unsigned& n, unsigned char* buf) +Val::calcnokeychars(Par par, uint& n, uchar* buf) { const Col& col = m_col; const Chs* chs = col.m_chs; CHARSET_INFO* cs = chs->m_cs; n = 0; - unsigned len = 0; + uint len = 0; while (len < col.m_length) { if (urandom(1 + col.m_bytelength) == 0) { break; } - unsigned half = maxcharcount / 2; + uint half = maxcharcount / 2; int r = irandom((par.m_pctrange * half) / 100); if (par.m_bdir != 0 && urandom(10) != 0) { if (r < 0 && par.m_bdir > 0 || r > 0 && par.m_bdir < 0) r = -r; } - unsigned i = half + r; + uint i = half + r; assert(i < maxcharcount); const Chr& chr = chs->m_chr[i]; assert(n + chr.m_size <= col.m_bytelength); @@ -2048,13 +2030,39 @@ Val::calcnokeychars(Par par, unsigned& n, unsigned char* buf) } } +// operations + int -Val::verify(Par par, const Val& val2) const +Val::setval(Par par) const { - CHK(cmp(par, val2) == 0); + Con& con = par.con(); + const Col& col = m_col; + if (col.m_pk) { + assert(!m_null); + const char* addr = (const char*)dataaddr(); + LL5("setval pk [" << col << "] " << *this); + CHK(con.equal(col.m_num, addr) == 0); + } else { + const char* addr = !m_null ? (const char*)dataaddr() : 0; + LL5("setval non-pk [" << col << "] " << *this); + CHK(con.setValue(col.m_num, addr) == 0); + } + return 0; +} + +int +Val::setval(Par par, const ICol& icol) const +{ + Con& con = par.con(); + assert(!m_null); + const char* addr = (const char*)dataaddr(); + LL5("setval key [" << icol << "] " << *this); + CHK(con.equal(icol.m_num, addr) == 0); return 0; } +// compare + int Val::cmp(Par par, const Val& val2) const { @@ -2062,9 +2070,9 @@ Val::cmp(Par par, const Val& val2) const const Col& col2 = val2.m_col; assert(col.equal(col2)); if (m_null || val2.m_null) { - if (! m_null) + if (!m_null) return +1; - if (! val2.m_null) + if (!val2.m_null) return -1; return 0; } @@ -2084,21 +2092,21 @@ Val::cmp(Par par, const Val& val2) const break; case Col::Char: { - unsigned len = col.m_bytelength; + uint len = col.m_bytelength; return cmpchars(par, m_char, len, val2.m_char, len); } break; case Col::Varchar: { - unsigned len1 = m_varchar[0]; - unsigned len2 = val2.m_varchar[0]; + uint len1 = m_varchar[0]; + uint len2 = val2.m_varchar[0]; return cmpchars(par, m_varchar + 1, len1, val2.m_varchar + 1, len2); } break; case Col::Longvarchar: { - unsigned len1 = m_longvarchar[0] + (m_longvarchar[1] << 8); - unsigned len2 = val2.m_longvarchar[0] + (val2.m_longvarchar[1] << 8); + uint len1 = m_longvarchar[0] + (m_longvarchar[1] << 8); + uint len2 = val2.m_longvarchar[0] + (val2.m_longvarchar[1] << 8); return cmpchars(par, m_longvarchar + 2, len1, val2.m_longvarchar + 2, len2); } break; @@ -2110,17 +2118,17 @@ Val::cmp(Par par, const Val& val2) const } int -Val::cmpchars(Par par, const unsigned char* buf1, unsigned len1, const unsigned char* buf2, unsigned len2) const +Val::cmpchars(Par par, const uchar* buf1, uint len1, const uchar* buf2, uint len2) const { const Col& col = m_col; const Chs* chs = col.m_chs; CHARSET_INFO* cs = chs->m_cs; int k; - if (! par.m_collsp) { - unsigned char x1[maxxmulsize * 8000]; - unsigned char x2[maxxmulsize * 8000]; + if (!par.m_collsp) { + uchar x1[maxxmulsize * 8000]; + uchar x2[maxxmulsize * 8000]; // make strxfrm pad both to same length - unsigned len = maxxmulsize * col.m_bytelength; + uint len = maxxmulsize * col.m_bytelength; int n1 = NdbSqlUtil::strnxfrm_bug7284(cs, x1, chs->m_xmul * len, buf1, len1); int n2 = NdbSqlUtil::strnxfrm_bug7284(cs, x2, chs->m_xmul * len, buf2, len2); assert(n1 != -1 && n1 == n2); @@ -2131,8 +2139,17 @@ Val::cmpchars(Par par, const unsigned char* buf1, unsigned len1, const unsigned return k < 0 ? -1 : k > 0 ? +1 : 0; } +int +Val::verify(Par par, const Val& val2) const +{ + CHK(cmp(par, val2) == 0); + return 0; +} + +// print + static void -printstring(NdbOut& out, const unsigned char* str, unsigned len, bool showlen) +printstring(NdbOut& out, const uchar* str, uint len, bool showlen) { char buf[4 * 8000]; char *p = buf; @@ -2141,12 +2158,12 @@ printstring(NdbOut& out, const unsigned char* str, unsigned len, bool showlen) sprintf(p, "%u:", len); p += strlen(p); } - for (unsigned i = 0; i < len; i++) { - unsigned char c = str[i]; + for (uint i = 0; i < len; i++) { + uchar c = str[i]; if (c == '\\') { *p++ = '\\'; *p++ = c; - } else if (0x20 <= c && c < 0x7e) { + } else if (0x20 <= c && c <= 0x7e) { *p++ = c; } else { *p++ = '\\'; @@ -2173,19 +2190,19 @@ operator<<(NdbOut& out, const Val& val) break; case Col::Char: { - unsigned len = col.m_bytelength; + uint len = col.m_bytelength; printstring(out, val.m_char, len, false); } break; case Col::Varchar: { - unsigned len = val.m_varchar[0]; + uint len = val.m_varchar[0]; printstring(out, val.m_varchar + 1, len, true); } break; case Col::Longvarchar: { - unsigned len = val.m_longvarchar[0] + (val.m_longvarchar[1] << 8); + uint len = val.m_longvarchar[0] + (val.m_longvarchar[1] << 8); printstring(out, val.m_longvarchar + 2, len, true); } break; @@ -2202,16 +2219,36 @@ operator<<(NdbOut& out, const Val& val) struct Row { const Tab& m_tab; Val** m_val; - bool m_exist; - enum Op { NoOp = 0, ReadOp = 1, InsOp = 2, UpdOp = 4, DelOp = 8, AnyOp = 15 }; - Op m_pending; - Row* m_dbrow; // copy of db row before update + enum St { + StUndef = 0, + StDefine = 1, + StPrepare = 2, + StCommit = 3 + }; + enum Op { + OpNone = 0, + OpIns = 2, + OpUpd = 4, + OpDel = 8, + OpRead = 16, + OpReadEx = 32, + OpReadCom = 64, + OpDML = 2 | 4 | 8, + OpREAD = 16 | 32 | 64 + }; + St m_st; + Op m_op; + Uint64 m_txid; + Row* m_bi; + // construct Row(const Tab& tab); ~Row(); - void copy(const Row& row2); - void calc(Par par, unsigned i, unsigned mask = 0); - const Row& dbrow() const; - int verify(Par par, const Row& row2, bool pkonly) const; + void copy(const Row& row2, bool copy_bi); + void copyval(const Row& row2, uint colmask = ~0); + void calc(Par par, uint i, uint colmask = ~0); + // operations + int setval(Par par, uint colmask = ~0); + int setval(Par par, const ITab& itab); int insrow(Par par); int updrow(Par par); int updrow(Par par, const ITab& itab); @@ -2220,120 +2257,132 @@ struct Row { int selrow(Par par); int selrow(Par par, const ITab& itab); int setrow(Par par); + // compare int cmp(Par par, const Row& row2) const; int cmp(Par par, const Row& row2, const ITab& itab) const; + int verify(Par par, const Row& row2, bool pkonly) const; private: Row& operator=(const Row& row2); }; +static NdbOut& +operator<<(NdbOut& out, const Row* rowp); + +static NdbOut& +operator<<(NdbOut& out, const Row& row); + +// construct + Row::Row(const Tab& tab) : m_tab(tab) { m_val = new Val* [tab.m_cols]; - for (unsigned k = 0; k < tab.m_cols; k++) { + for (uint k = 0; k < tab.m_cols; k++) { const Col& col = *tab.m_col[k]; m_val[k] = new Val(col); } - m_exist = false; - m_pending = NoOp; - m_dbrow = 0; + m_st = StUndef; + m_op = OpNone; + m_txid = 0; + m_bi = 0; } Row::~Row() { const Tab& tab = m_tab; - for (unsigned k = 0; k < tab.m_cols; k++) { + for (uint k = 0; k < tab.m_cols; k++) { delete m_val[k]; } delete [] m_val; - delete m_dbrow; + delete m_bi; } void -Row::copy(const Row& row2) +Row::copy(const Row& row2, bool copy_bi) +{ + const Tab& tab = m_tab; + copyval(row2); + m_st = row2.m_st; + m_op = row2.m_op; + m_txid = row2.m_txid; + assert(m_bi == 0); + if (copy_bi && row2.m_bi != 0) { + m_bi = new Row(tab); + m_bi->copy(*row2.m_bi, copy_bi); + } +} + +void +Row::copyval(const Row& row2, uint colmask) { const Tab& tab = m_tab; assert(&tab == &row2.m_tab); - for (unsigned k = 0; k < tab.m_cols; k++) { + for (uint k = 0; k < tab.m_cols; k++) { Val& val = *m_val[k]; const Val& val2 = *row2.m_val[k]; - val.copy(val2); - } - m_exist = row2.m_exist; - m_pending = row2.m_pending; - if (row2.m_dbrow == 0) { - m_dbrow = 0; - } else { - assert(row2.m_dbrow->m_dbrow == 0); - if (m_dbrow == 0) - m_dbrow = new Row(tab); - m_dbrow->copy(*row2.m_dbrow); + if ((1 << k) & colmask) + val.copy(val2); } } void -Row::calc(Par par, unsigned i, unsigned mask) +Row::calc(Par par, uint i, uint colmask) { const Tab& tab = m_tab; - for (unsigned k = 0; k < tab.m_cols; k++) { - if (! (mask & (1 << k))) { + for (uint k = 0; k < tab.m_cols; k++) { + if ((1 << k) & colmask) { Val& val = *m_val[k]; val.calc(par, i); } } } -const Row& -Row::dbrow() const -{ - if (m_dbrow == 0) - return *this; - assert(m_pending == Row::UpdOp || m_pending == Row::DelOp); - return *m_dbrow; -} +// operations int -Row::verify(Par par, const Row& row2, bool pkonly) const +Row::setval(Par par, uint colmask) { const Tab& tab = m_tab; - const Row& row1 = *this; - assert(&row1.m_tab == &row2.m_tab && row1.m_exist && row2.m_exist); - for (unsigned k = 0; k < tab.m_cols; k++) { - const Col& col = row1.m_val[k]->m_col; - if (! pkonly || col.m_pk) { - const Val& val1 = *row1.m_val[k]; - const Val& val2 = *row2.m_val[k]; - CHK(val1.verify(par, val2) == 0); + Rsq rsq(tab.m_cols); + for (uint k = 0; k < tab.m_cols; k++) { + uint k2 = rsq.next(); + if ((1 << k2) & colmask) { + const Val& val = *m_val[k2]; + CHK(val.setval(par) == 0); } } return 0; } int +Row::setval(Par par, const ITab& itab) +{ + Con& con = par.con(); + Rsq rsq(itab.m_icols); + for (uint k = 0; k < itab.m_icols; k++) { + uint k2 = rsq.next(); + const ICol& icol = *itab.m_icol[k2]; + const Col& col = icol.m_col; + uint m = col.m_num; + const Val& val = *m_val[m]; + CHK(val.setval(par, icol) == 0); + } + return 0; +} + +int Row::insrow(Par par) { Con& con = par.con(); const Tab& tab = m_tab; - assert(! m_exist); CHK(con.getNdbOperation(tab) == 0); CHKCON(con.m_op->insertTuple() == 0, con); - Rsq rsq1(tab.m_cols); - for (unsigned k = 0; k < tab.m_cols; k++) { - unsigned k2 = rsq1.next(); - const Val& val = *m_val[k2]; - const Col& col = val.m_col; - if (col.m_pk) - CHK(val.equal(par) == 0); - } - Rsq rsq2(tab.m_cols); - for (unsigned k = 0; k < tab.m_cols; k++) { - unsigned k2 = rsq2.next(); - const Val& val = *m_val[k2]; - const Col& col = val.m_col; - if (! col.m_pk) - CHK(val.setval(par) == 0); - } - m_pending = InsOp; + CHK(setval(par, tab.m_pkmask) == 0); + CHK(setval(par, ~tab.m_pkmask) == 0); + assert(m_st == StUndef); + m_st = StDefine; + m_op = OpIns; + m_txid = con.m_txid; return 0; } @@ -2342,26 +2391,14 @@ Row::updrow(Par par) { Con& con = par.con(); const Tab& tab = m_tab; - assert(m_exist); CHK(con.getNdbOperation(tab) == 0); CHKCON(con.m_op->updateTuple() == 0, con); - Rsq rsq1(tab.m_cols); - for (unsigned k = 0; k < tab.m_cols; k++) { - unsigned k2 = rsq1.next(); - const Val& val = *m_val[k2]; - const Col& col = val.m_col; - if (col.m_pk) - CHK(val.equal(par) == 0); - } - Rsq rsq2(tab.m_cols); - for (unsigned k = 0; k < tab.m_cols; k++) { - unsigned k2 = rsq2.next(); - const Val& val = *m_val[k2]; - const Col& col = val.m_col; - if (! col.m_pk) - CHK(val.setval(par) == 0); - } - m_pending = UpdOp; + CHK(setval(par, tab.m_pkmask) == 0); + CHK(setval(par, ~tab.m_pkmask) == 0); + assert(m_st == StUndef); + m_st = StDefine; + m_op = OpUpd; + m_txid = con.m_txid; return 0; } @@ -2371,27 +2408,14 @@ Row::updrow(Par par, const ITab& itab) Con& con = par.con(); const Tab& tab = m_tab; assert(itab.m_type == ITab::UniqueHashIndex && &itab.m_tab == &tab); - assert(m_exist); CHK(con.getNdbIndexOperation(itab, tab) == 0); CHKCON(con.m_op->updateTuple() == 0, con); - Rsq rsq1(itab.m_icols); - for (unsigned k = 0; k < itab.m_icols; k++) { - unsigned k2 = rsq1.next(); - const ICol& icol = *itab.m_icol[k2]; - const Col& col = icol.m_col; - unsigned m = col.m_num; - const Val& val = *m_val[m]; - CHK(val.equal(par, icol) == 0); - } - Rsq rsq2(tab.m_cols); - for (unsigned k = 0; k < tab.m_cols; k++) { - unsigned k2 = rsq2.next(); - const Val& val = *m_val[k2]; - const Col& col = val.m_col; - if (! col.m_pk) - CHK(val.setval(par) == 0); - } - m_pending = UpdOp; + CHK(setval(par, itab) == 0); + CHK(setval(par, ~tab.m_pkmask) == 0); + assert(m_st == StUndef); + m_st = StDefine; + m_op = OpUpd; + m_txid = con.m_txid; return 0; } @@ -2400,18 +2424,13 @@ Row::delrow(Par par) { Con& con = par.con(); const Tab& tab = m_tab; - assert(m_exist); CHK(con.getNdbOperation(m_tab) == 0); CHKCON(con.m_op->deleteTuple() == 0, con); - Rsq rsq1(tab.m_cols); - for (unsigned k = 0; k < tab.m_cols; k++) { - unsigned k2 = rsq1.next(); - const Val& val = *m_val[k2]; - const Col& col = val.m_col; - if (col.m_pk) - CHK(val.equal(par) == 0); - } - m_pending = DelOp; + CHK(setval(par, tab.m_pkmask) == 0); + assert(m_st == StUndef); + m_st = StDefine; + m_op = OpDel; + m_txid = con.m_txid; return 0; } @@ -2421,19 +2440,13 @@ Row::delrow(Par par, const ITab& itab) Con& con = par.con(); const Tab& tab = m_tab; assert(itab.m_type == ITab::UniqueHashIndex && &itab.m_tab == &tab); - assert(m_exist); CHK(con.getNdbIndexOperation(itab, tab) == 0); CHKCON(con.m_op->deleteTuple() == 0, con); - Rsq rsq1(itab.m_icols); - for (unsigned k = 0; k < itab.m_icols; k++) { - unsigned k2 = rsq1.next(); - const ICol& icol = *itab.m_icol[k2]; - const Col& col = icol.m_col; - unsigned m = col.m_num; - const Val& val = *m_val[m]; - CHK(val.equal(par, icol) == 0); - } - m_pending = DelOp; + CHK(setval(par, itab) == 0); + assert(m_st == StUndef); + m_st = StDefine; + m_op = OpDel; + m_txid = con.m_txid; return 0; } @@ -2443,15 +2456,9 @@ Row::selrow(Par par) Con& con = par.con(); const Tab& tab = m_tab; CHK(con.getNdbOperation(m_tab) == 0); - CHKCON(con.m_op->readTuple() == 0, con); - Rsq rsq1(tab.m_cols); - for (unsigned k = 0; k < tab.m_cols; k++) { - unsigned k2 = rsq1.next(); - const Val& val = *m_val[k2]; - const Col& col = val.m_col; - if (col.m_pk) - CHK(val.equal(par) == 0); - } + CHKCON(con.readTuple(par) == 0, con); + CHK(setval(par, tab.m_pkmask) == 0); + // TODO state return 0; } @@ -2462,16 +2469,9 @@ Row::selrow(Par par, const ITab& itab) const Tab& tab = m_tab; assert(itab.m_type == ITab::UniqueHashIndex && &itab.m_tab == &tab); CHK(con.getNdbIndexOperation(itab, tab) == 0); - CHKCON(con.m_op->readTuple() == 0, con); - Rsq rsq1(itab.m_icols); - for (unsigned k = 0; k < itab.m_icols; k++) { - unsigned k2 = rsq1.next(); - const ICol& icol = *itab.m_icol[k2]; - const Col& col = icol.m_col; - unsigned m = col.m_num; - const Val& val = *m_val[m]; - CHK(val.equal(par, icol) == 0); - } + CHKCON(con.readTuple(par) == 0, con); + CHK(setval(par, itab) == 0); + // TODO state return 0; } @@ -2480,25 +2480,23 @@ Row::setrow(Par par) { Con& con = par.con(); const Tab& tab = m_tab; - Rsq rsq1(tab.m_cols); - for (unsigned k = 0; k < tab.m_cols; k++) { - unsigned k2 = rsq1.next(); - const Val& val = *m_val[k2]; - const Col& col = val.m_col; - if (! col.m_pk) - CHK(val.setval(par) == 0); - } - m_pending = UpdOp; + CHK(setval(par, ~tab.m_pkmask) == 0); + assert(m_st == StUndef); + m_st = StDefine; + m_op = OpUpd; + m_txid = con.m_txid; return 0; } +// compare + int Row::cmp(Par par, const Row& row2) const { const Tab& tab = m_tab; assert(&tab == &row2.m_tab); int c = 0; - for (unsigned k = 0; k < tab.m_cols; k++) { + for (uint k = 0; k < tab.m_cols; k++) { const Val& val = *m_val[k]; const Val& val2 = *row2.m_val[k]; if ((c = val.cmp(par, val2)) != 0) @@ -2512,10 +2510,10 @@ Row::cmp(Par par, const Row& row2, const ITab& itab) const { const Tab& tab = m_tab; int c = 0; - for (unsigned i = 0; i < itab.m_icols; i++) { + for (uint i = 0; i < itab.m_icols; i++) { const ICol& icol = *itab.m_icol[i]; const Col& col = icol.m_col; - unsigned k = col.m_num; + uint k = col.m_num; assert(k < tab.m_cols); const Val& val = *m_val[k]; const Val& val2 = *row2.m_val[k]; @@ -2525,19 +2523,70 @@ Row::cmp(Par par, const Row& row2, const ITab& itab) const return c; } +int +Row::verify(Par par, const Row& row2, bool pkonly) const +{ + const Tab& tab = m_tab; + const Row& row1 = *this; + assert(&row1.m_tab == &row2.m_tab); + for (uint k = 0; k < tab.m_cols; k++) { + const Col& col = row1.m_val[k]->m_col; + if (!pkonly || col.m_pk) { + const Val& val1 = *row1.m_val[k]; + const Val& val2 = *row2.m_val[k]; + CHK(val1.verify(par, val2) == 0); + } + } + return 0; +} + +// print + +static NdbOut& +operator<<(NdbOut& out, const Row::St st) +{ + if (st == Row::StUndef) + out << "StUndef"; + else if (st == Row::StDefine) + out << "StDefine"; + else if (st == Row::StPrepare) + out << "StPrepare"; + else if (st == Row::StCommit) + out << "StCommit"; + else + out << "st=" << st; + return out; +} + static NdbOut& operator<<(NdbOut& out, const Row::Op op) { - if (op == Row::NoOp) - out << "NoOp"; - else if (op == Row::InsOp) - out << "InsOp"; - else if (op == Row::UpdOp) - out << "UpdOp"; - else if (op == Row::DelOp) - out << "DelOp"; + if (op == Row::OpNone) + out << "OpNone"; + else if (op == Row::OpIns) + out << "OpIns"; + else if (op == Row::OpUpd) + out << "OpUpd"; + else if (op == Row::OpDel) + out << "OpDel"; + else if (op == Row::OpRead) + out << "OpRead"; + else if (op == Row::OpReadEx) + out << "OpReadEx"; + else if (op == Row::OpReadCom) + out << "OpReadCom"; else - out << op; + out << "op=" << op; + return out; +} + +static NdbOut& +operator<<(NdbOut& out, const Row* rowp) +{ + if (rowp == 0) + out << "[null]"; + else + out << *rowp; return out; } @@ -2545,26 +2594,18 @@ static NdbOut& operator<<(NdbOut& out, const Row& row) { const Tab& tab = row.m_tab; - for (unsigned i = 0; i < tab.m_cols; i++) { + out << "["; + for (uint i = 0; i < tab.m_cols; i++) { if (i > 0) out << " "; out << *row.m_val[i]; } - out << " exist=" << row.m_exist; - if (row.m_pending) - out << " pending=" << row.m_pending; - if (row.m_dbrow != 0) - out << " [dbrow=" << *row.m_dbrow << "]"; - return out; -} - -static NdbOut& -operator<<(NdbOut& out, const Row* rowptr) -{ - if (rowptr == 0) - out << "null"; - else - out << *rowptr; + out << " " << row.m_st; + out << " " << row.m_op; + out << " " << HEX(row.m_txid); + if (row.m_bi != 0) + out << " " << row.m_bi; + out << "]"; return out; } @@ -2572,45 +2613,38 @@ operator<<(NdbOut& out, const Row* rowptr) struct Set { const Tab& m_tab; - unsigned m_rows; + uint m_rows; Row** m_row; - unsigned* m_rowkey; // maps row number (from 0) in scan to tuple key + uint* m_rowkey; // maps row number (from 0) in scan to tuple key Row* m_keyrow; NdbRecAttr** m_rec; - Set(const Tab& tab, unsigned rows); + // construct + Set(const Tab& tab, uint rows); ~Set(); void reset(); - unsigned count() const; - // old and new values - bool exist(unsigned i) const; - void dbsave(unsigned i); - void calc(Par par, unsigned i, unsigned mask = 0); - bool pending(unsigned i, unsigned mask) const; - void notpending(unsigned i, ExecType et = Commit); - void notpending(const Lst& lst, ExecType et = Commit); - void dbdiscard(unsigned i); - void dbdiscard(const Lst& lst); - const Row& dbrow(unsigned i) const; + bool compat(Par par, uint i, const Row::Op op) const; + void push(uint i); + void copyval(uint i, uint colmask = ~0); // from bi + void calc(Par par, uint i, uint colmask = ~0); + uint count() const; + const Row* getrow(uint i, bool dirty = false) const; + // transaction + void post(Par par, ExecType et); // operations - int insrow(Par par, unsigned i); - int updrow(Par par, unsigned i); - int updrow(Par par, const ITab& itab, unsigned i); - int delrow(Par par, unsigned i); - int delrow(Par par, const ITab& itab, unsigned i); + int insrow(Par par, uint i); + int updrow(Par par, uint i); + int updrow(Par par, const ITab& itab, uint i); + int delrow(Par par, uint i); + int delrow(Par par, const ITab& itab, uint i); int selrow(Par par, const Row& keyrow); int selrow(Par par, const ITab& itab, const Row& keyrow); - // set and get - void setkey(Par par, const Row& keyrow); - void setkey(Par par, const ITab& itab, const Row& keyrow); - int setrow(Par par, unsigned i); + int setrow(Par par, uint i); int getval(Par par); - int getkey(Par par, unsigned* i); - int putval(unsigned i, bool force, unsigned n = ~0); - // sort rows in-place according to ordered index + int getkey(Par par, uint* i); + int putval(uint i, bool force, uint n = ~0); + // compare void sort(Par par, const ITab& itab); - void sort(Par par, const ITab& itab, unsigned lo, unsigned hi); - // verify - int verify(Par par, const Set& set2, bool pkonly) const; + int verify(Par par, const Set& set2, bool pkonly, bool dirty = false) const; int verifyorder(Par par, const ITab& itab, bool descending) const; // protect structure NdbMutex* m_mutex; @@ -2621,26 +2655,27 @@ struct Set { NdbMutex_Unlock(m_mutex); } private: + void sort(Par par, const ITab& itab, uint lo, uint hi); Set& operator=(const Set& set2); }; -Set::Set(const Tab& tab, unsigned rows) : +// construct + +Set::Set(const Tab& tab, uint rows) : m_tab(tab) { m_rows = rows; m_row = new Row* [m_rows]; - for (unsigned i = 0; i < m_rows; i++) { - // allocate on need to save space + for (uint i = 0; i < m_rows; i++) { m_row[i] = 0; } - m_rowkey = new unsigned [m_rows]; - for (unsigned n = 0; n < m_rows; n++) { - // initialize to null + m_rowkey = new uint [m_rows]; + for (uint n = 0; n < m_rows; n++) { m_rowkey[n] = ~0; } m_keyrow = new Row(tab); m_rec = new NdbRecAttr* [tab.m_cols]; - for (unsigned k = 0; k < tab.m_cols; k++) { + for (uint k = 0; k < tab.m_cols; k++) { m_rec[k] = 0; } m_mutex = NdbMutex_Create(); @@ -2649,7 +2684,7 @@ Set::Set(const Tab& tab, unsigned rows) : Set::~Set() { - for (unsigned i = 0; i < m_rows; i++) { + for (uint i = 0; i < m_rows; i++) { delete m_row[i]; } delete [] m_row; @@ -2662,132 +2697,203 @@ Set::~Set() void Set::reset() { - for (unsigned i = 0; i < m_rows; i++) { - if (m_row[i] != 0) { - Row& row = *m_row[i]; - row.m_exist = false; - } - } -} - -unsigned -Set::count() const -{ - unsigned count = 0; - for (unsigned i = 0; i < m_rows; i++) { - if (m_row[i] != 0) { - Row& row = *m_row[i]; - if (row.m_exist) - count++; - } + for (uint i = 0; i < m_rows; i++) { + m_row[i] = 0; } - return count; } -// old and new values - +// this sucks bool -Set::exist(unsigned i) const +Set::compat(Par par, uint i, const Row::Op op) const { - assert(i < m_rows); - if (m_row[i] == 0) // not allocated => not exist - return false; - return m_row[i]->m_exist; + Con& con = par.con(); + int ret = -1; + int place = 0; + do { + const Row* rowp = getrow(i); + if (rowp == 0) { + ret = op == Row::OpIns; + place = 1; + break; + } + const Row& row = *rowp; + if (!(op & Row::OpREAD)) { + if (row.m_st == Row::StDefine || row.m_st == Row::StPrepare) { + assert(row.m_op & Row::OpDML); + assert(row.m_txid != 0); + if (con.m_txid != row.m_txid) { + ret = false; + place = 2; + break; + } + if (row.m_op != Row::OpDel) { + ret = op == Row::OpUpd || op == Row::OpDel; + place = 3; + break; + } + ret = op == Row::OpIns; + place = 4; + break; + } + if (row.m_st == Row::StCommit) { + assert(row.m_op == Row::OpNone); + assert(row.m_txid == 0); + ret = op == Row::OpUpd || op == Row::OpDel; + place = 5; + break; + } + } + if (op & Row::OpREAD) { + bool dirty = + con.m_txid != row.m_txid && + par.m_lockmode == NdbOperation::LM_CommittedRead; + const Row* rowp2 = getrow(i, dirty); + if (rowp2 == 0 || rowp2->m_op == Row::OpDel) { + ret = false; + place = 6; + break; + } + ret = true; + place = 7; + break; + } + } while (0); + LL4("compat ret=" << ret << " place=" << place); + assert(ret == false || ret == true); + return ret; } void -Set::dbsave(unsigned i) +Set::push(uint i) { const Tab& tab = m_tab; - assert(i < m_rows && m_row[i] != 0); + assert(i < m_rows); + Row* bi = m_row[i]; + m_row[i] = new Row(tab); Row& row = *m_row[i]; - LL5("dbsave " << i << ": " << row); - assert(row.m_exist && ! row.m_pending && row.m_dbrow == 0); - // could swap pointers but making copy is safer - Row* rowptr = new Row(tab); - rowptr->copy(row); - row.m_dbrow = rowptr; + row.m_bi = bi; + if (bi != 0) + row.copyval(*bi); } void -Set::calc(Par par, unsigned i, unsigned mask) +Set::copyval(uint i, uint colmask) { - const Tab& tab = m_tab; - if (m_row[i] == 0) - m_row[i] = new Row(tab); + assert(m_row[i] != 0); Row& row = *m_row[i]; - row.calc(par, i, mask); -} - -bool -Set::pending(unsigned i, unsigned mask) const -{ - assert(i < m_rows); - if (m_row[i] == 0) // not allocated => not pending - return Row::NoOp; - return m_row[i]->m_pending & mask; + assert(row.m_bi != 0); + row.copyval(*row.m_bi, colmask); } void -Set::notpending(unsigned i, ExecType et) +Set::calc(Par par, uint i, uint colmask) { assert(m_row[i] != 0); Row& row = *m_row[i]; - if (et == Commit) { - if (row.m_pending == Row::InsOp) - row.m_exist = true; - if (row.m_pending == Row::DelOp) - row.m_exist = false; - } else { - if (row.m_pending == Row::InsOp) - row.m_exist = false; - if (row.m_pending == Row::DelOp) - row.m_exist = true; - } - row.m_pending = Row::NoOp; + row.calc(par, i, colmask); } -void -Set::notpending(const Lst& lst, ExecType et) +uint +Set::count() const { - for (unsigned j = 0; j < lst.m_cnt; j++) { - unsigned i = lst.m_arr[j]; - notpending(i, et); + uint count = 0; + for (uint i = 0; i < m_rows; i++) { + if (m_row[i] != 0) + count++; } + return count; } -void -Set::dbdiscard(unsigned i) +const Row* +Set::getrow(uint i, bool dirty) const { - assert(m_row[i] != 0); - Row& row = *m_row[i]; - LL5("dbdiscard " << i << ": " << row); - assert(row.m_dbrow != 0); - delete row.m_dbrow; - row.m_dbrow = 0; + assert(i < m_rows); + const Row* rowp = m_row[i]; + if (dirty) { + while (rowp != 0) { + bool b1 = rowp->m_op == Row::OpNone; + bool b2 = rowp->m_st == Row::StCommit; + assert(b1 == b2); + if (b1) { + assert(rowp->m_bi == 0); + break; + } + rowp = rowp->m_bi; + } + } + return rowp; } -const Row& -Set::dbrow(unsigned i) const -{ - assert(m_row[i] != 0); - Row& row = *m_row[i]; - return row.dbrow(); -} +// transaction void -Set::dbdiscard(const Lst& lst) +Set::post(Par par, ExecType et) { - for (unsigned j = 0; j < lst.m_cnt; j++) { - unsigned i = lst.m_arr[j]; - dbdiscard(i); + LL4("post"); + Con& con = par.con(); + assert(con.m_txid != 0); + uint i; + for (i = 0; i < m_rows; i++) { + Row* rowp = m_row[i]; + if (rowp == 0) { + LL5("skip " << i << " " << rowp); + continue; + } + if (rowp->m_st == Row::StCommit) { + assert(rowp->m_op == Row::OpNone); + assert(rowp->m_txid == 0); + assert(rowp->m_bi == 0); + LL5("skip committed " << i << " " << rowp); + continue; + } + assert(rowp->m_st == Row::StDefine || rowp->m_st == Row::StPrepare); + assert(rowp->m_txid != 0); + if (con.m_txid != rowp->m_txid) { + LL5("skip txid " << i << " " << HEX(con.m_txid) << " " << rowp); + continue; + } + // TODO read ops + assert(rowp->m_op & Row::OpDML); + LL4("post BEFORE " << rowp); + if (et == NoCommit) { + if (rowp->m_st == Row::StDefine) { + rowp->m_st = Row::StPrepare; + Row* bi = rowp->m_bi; + while (bi != 0 && bi->m_st == Row::StDefine) { + bi->m_st = Row::StPrepare; + bi = bi->m_bi; + } + } + } else if (et == Commit) { + if (rowp->m_op != Row::OpDel) { + rowp->m_st = Row::StCommit; + rowp->m_op = Row::OpNone; + rowp->m_txid = 0; + delete rowp->m_bi; + rowp->m_bi = 0; + } else { + delete rowp; + rowp = 0; + } + } else if (et == Rollback) { + while (rowp != 0 && rowp->m_st != Row::StCommit) { + Row* tmp = rowp; + rowp = rowp->m_bi; + tmp->m_bi = 0; + delete tmp; + } + } else { + assert(false); + } + m_row[i] = rowp; + LL4("post AFTER " << rowp); } } // operations int -Set::insrow(Par par, unsigned i) +Set::insrow(Par par, uint i) { assert(m_row[i] != 0); Row& row = *m_row[i]; @@ -2796,7 +2902,7 @@ Set::insrow(Par par, unsigned i) } int -Set::updrow(Par par, unsigned i) +Set::updrow(Par par, uint i) { assert(m_row[i] != 0); Row& row = *m_row[i]; @@ -2805,7 +2911,7 @@ Set::updrow(Par par, unsigned i) } int -Set::updrow(Par par, const ITab& itab, unsigned i) +Set::updrow(Par par, const ITab& itab, uint i) { assert(m_row[i] != 0); Row& row = *m_row[i]; @@ -2814,7 +2920,7 @@ Set::updrow(Par par, const ITab& itab, unsigned i) } int -Set::delrow(Par par, unsigned i) +Set::delrow(Par par, uint i) { assert(m_row[i] != 0); Row& row = *m_row[i]; @@ -2823,7 +2929,7 @@ Set::delrow(Par par, unsigned i) } int -Set::delrow(Par par, const ITab& itab, unsigned i) +Set::delrow(Par par, const ITab& itab, uint i) { assert(m_row[i] != 0); Row& row = *m_row[i]; @@ -2836,8 +2942,8 @@ Set::selrow(Par par, const Row& keyrow) { Con& con = par.con(); const Tab& tab = par.tab(); - setkey(par, keyrow); - LL5("selrow " << tab.m_name << ": keyrow: " << keyrow); + LL5("selrow " << tab.m_name << " keyrow " << keyrow); + m_keyrow->copyval(keyrow, tab.m_pkmask); CHK(m_keyrow->selrow(par) == 0); CHK(getval(par) == 0); return 0; @@ -2847,45 +2953,15 @@ int Set::selrow(Par par, const ITab& itab, const Row& keyrow) { Con& con = par.con(); - setkey(par, itab, keyrow); - LL5("selrow " << itab.m_name << ": keyrow: " << keyrow); + LL5("selrow " << itab.m_name << " keyrow " << keyrow); + m_keyrow->copyval(keyrow, itab.m_keymask); CHK(m_keyrow->selrow(par, itab) == 0); CHK(getval(par) == 0); return 0; } -// set and get - -void -Set::setkey(Par par, const Row& keyrow) -{ - const Tab& tab = m_tab; - for (unsigned k = 0; k < tab.m_cols; k++) { - const Col& col = *tab.m_col[k]; - if (col.m_pk) { - Val& val1 = *m_keyrow->m_val[k]; - const Val& val2 = *keyrow.dbrow().m_val[k]; - val1.copy(val2); - } - } -} - -void -Set::setkey(Par par, const ITab& itab, const Row& keyrow) -{ - const Tab& tab = m_tab; - for (unsigned k = 0; k < itab.m_icols; k++) { - const ICol& icol = *itab.m_icol[k]; - const Col& col = icol.m_col; - unsigned m = col.m_num; - Val& val1 = *m_keyrow->m_val[m]; - const Val& val2 = *keyrow.dbrow().m_val[m]; - val1.copy(val2); - } -} - int -Set::setrow(Par par, unsigned i) +Set::setrow(Par par, uint i) { Con& con = par.con(); assert(m_row[i] != 0); @@ -2899,18 +2975,18 @@ Set::getval(Par par) Con& con = par.con(); const Tab& tab = m_tab; Rsq rsq1(tab.m_cols); - for (unsigned k = 0; k < tab.m_cols; k++) { - unsigned k2 = rsq1.next(); + for (uint k = 0; k < tab.m_cols; k++) { + uint k2 = rsq1.next(); CHK(con.getValue(k2, m_rec[k2]) == 0); } return 0; } int -Set::getkey(Par par, unsigned* i) +Set::getkey(Par par, uint* i) { const Tab& tab = m_tab; - unsigned k = tab.m_keycol; + uint k = tab.m_keycol; assert(m_rec[k] != 0); const char* aRef = m_rec[k]->aRef(); Uint32 key = *(const Uint32*)aRef; @@ -2921,14 +2997,18 @@ Set::getkey(Par par, unsigned* i) } int -Set::putval(unsigned i, bool force, unsigned n) +Set::putval(uint i, bool force, uint n) { const Tab& tab = m_tab; - if (m_row[i] == 0) - m_row[i] = new Row(tab); + LL4("putval key=" << i << " row=" << n << " old=" << m_row[i]); + if (m_row[i] != 0) { + assert(force); + delete m_row[i]; + m_row[i] = 0; + } + m_row[i] = new Row(tab); Row& row = *m_row[i]; - CHK(! row.m_exist || force); - for (unsigned k = 0; k < tab.m_cols; k++) { + for (uint k = 0; k < tab.m_cols; k++) { Val& val = *row.m_val[k]; NdbRecAttr* rec = m_rec[k]; assert(rec != 0); @@ -2940,13 +3020,13 @@ Set::putval(unsigned i, bool force, unsigned n) val.copy(aRef); val.m_null = false; } - if (! row.m_exist) - row.m_exist = true; if (n != ~0) m_rowkey[n] = i; return 0; } +// compare + void Set::sort(Par par, const ITab& itab) { @@ -2955,12 +3035,12 @@ Set::sort(Par par, const ITab& itab) } void -Set::sort(Par par, const ITab& itab, unsigned lo, unsigned hi) +Set::sort(Par par, const ITab& itab, uint lo, uint hi) { assert(lo < m_rows && hi < m_rows && lo <= hi); Row* const p = m_row[lo]; - unsigned i = lo; - unsigned j = hi; + uint i = lo; + uint j = hi; while (i < j) { while (i < j && m_row[j]->cmp(par, *p, itab) >= 0) j--; @@ -2982,22 +3062,48 @@ Set::sort(Par par, const ITab& itab, unsigned lo, unsigned hi) sort(par, itab, i + 1, hi); } +/* + * set1 (self) is from dml and can contain un-committed operations. + * set2 is from read and contains no operations. "dirty" applies + * to set1: false = use latest row, true = use committed row. + */ int -Set::verify(Par par, const Set& set2, bool pkonly) const -{ - assert(&m_tab == &set2.m_tab && m_rows == set2.m_rows); - LL4("verify set1 count=" << count() << " vs set2 count=" << set2.count()); - for (unsigned i = 0; i < m_rows; i++) { +Set::verify(Par par, const Set& set2, bool pkonly, bool dirty) const +{ + const Set& set1 = *this; + assert(&set1.m_tab == &set2.m_tab && set1.m_rows == set2.m_rows); + LL3("verify dirty:" << dirty); + for (uint i = 0; i < set1.m_rows; i++) { + // the row versions we actually compare + const Row* row1p = set1.getrow(i, dirty); + const Row* row2p = set2.getrow(i); bool ok = true; - if (exist(i) != set2.exist(i)) { - ok = false; - } else if (exist(i)) { - if (dbrow(i).verify(par, set2.dbrow(i), pkonly) != 0) + int place = 0; + if (row1p == 0) { + if (row2p != 0) { + ok = false; + place = 1; + } + } else { + Row::Op op1 = row1p->m_op; + if (op1 != Row::OpDel) { + if (row2p == 0) { + ok = false; + place = 2; + } else if (row1p->verify(par, *row2p, pkonly) == -1) { + ok = false; + place = 3; + } + } else if (row2p != 0) { ok = false; + place = 4; + } } - if (! ok) { - LL1("verify failed: key=" << i << " row1=" << m_row[i] << " row2=" << set2.m_row[i]); - CHK(0 == 1); + if (!ok) { + LL1("verify " << i << " failed at " << place); + LL1("row1 " << row1p); + LL1("row2 " << row2p); + CHK(false); } } return 0; @@ -3007,18 +3113,17 @@ int Set::verifyorder(Par par, const ITab& itab, bool descending) const { const Tab& tab = m_tab; - for (unsigned n = 0; n < m_rows; n++) { - unsigned i2 = m_rowkey[n]; + for (uint n = 0; n < m_rows; n++) { + uint i2 = m_rowkey[n]; if (i2 == ~0) break; if (n == 0) continue; - unsigned i1 = m_rowkey[n - 1]; - assert(i1 < m_rows && i2 < m_rows); + uint i1 = m_rowkey[n - 1]; + assert(m_row[i1] != 0 && m_row[i2] != 0); const Row& row1 = *m_row[i1]; const Row& row2 = *m_row[i2]; - assert(row1.m_exist && row2.m_exist); - if (! descending) + if (!descending) CHK(row1.cmp(par, row2, itab) <= 0); else CHK(row1.cmp(par, row2, itab) >= 0); @@ -3026,10 +3131,12 @@ Set::verifyorder(Par par, const ITab& itab, bool descending) const return 0; } +// print + static NdbOut& operator<<(NdbOut& out, const Set& set) { - for (unsigned i = 0; i < set.m_rows; i++) { + for (uint i = 0; i < set.m_rows; i++) { const Row& row = *set.m_row[i]; if (i > 0) out << endl; @@ -3058,8 +3165,8 @@ int BVal::setbnd(Par par) const { Con& con = par.con(); - assert(g_compare_null || ! m_null); - const char* addr = ! m_null ? (const char*)dataaddr() : 0; + assert(g_compare_null || !m_null); + const char* addr = !m_null ? (const char*)dataaddr() : 0; const ICol& icol = m_icol; CHK(con.setBound(icol.m_num, m_type, addr) == 0); return 0; @@ -3068,7 +3175,7 @@ BVal::setbnd(Par par) const int BVal::setflt(Par par) const { - static unsigned index_bound_to_filter_bound[5] = { + static uint index_bound_to_filter_bound[5] = { NdbScanFilter::COND_GE, NdbScanFilter::COND_GT, NdbScanFilter::COND_LE, @@ -3076,12 +3183,12 @@ BVal::setflt(Par par) const NdbScanFilter::COND_EQ }; Con& con = par.con(); - assert(g_compare_null || ! m_null); - const char* addr = ! m_null ? (const char*)dataaddr() : 0; + assert(g_compare_null || !m_null); + const char* addr = !m_null ? (const char*)dataaddr() : 0; const ICol& icol = m_icol; const Col& col = icol.m_col; - unsigned length = col.m_bytesize; - unsigned cond = index_bound_to_filter_bound[m_type]; + uint length = col.m_bytesize; + uint cond = index_bound_to_filter_bound[m_type]; CHK(con.setFilter(col.m_num, cond, addr, length) == 0); return 0; } @@ -3104,27 +3211,27 @@ operator<<(NdbOut& out, const BVal& bval) struct BSet { const Tab& m_tab; const ITab& m_itab; - unsigned m_alloc; - unsigned m_bvals; + uint m_alloc; + uint m_bvals; BVal** m_bval; - BSet(const Tab& tab, const ITab& itab, unsigned rows); + BSet(const Tab& tab, const ITab& itab); ~BSet(); void reset(); void calc(Par par); - void calcpk(Par par, unsigned i); + void calcpk(Par par, uint i); int setbnd(Par par) const; int setflt(Par par) const; void filter(Par par, const Set& set, Set& set2) const; }; -BSet::BSet(const Tab& tab, const ITab& itab, unsigned rows) : +BSet::BSet(const Tab& tab, const ITab& itab) : m_tab(tab), m_itab(itab), m_alloc(2 * itab.m_icols), m_bvals(0) { m_bval = new BVal* [m_alloc]; - for (unsigned i = 0; i < m_alloc; i++) { + for (uint i = 0; i < m_alloc; i++) { m_bval[i] = 0; } } @@ -3138,7 +3245,7 @@ void BSet::reset() { while (m_bvals > 0) { - unsigned i = --m_bvals; + uint i = --m_bvals; delete m_bval[i]; m_bval[i] = 0; } @@ -3150,10 +3257,10 @@ BSet::calc(Par par) const ITab& itab = m_itab; par.m_pctrange = par.m_pctbrange; reset(); - for (unsigned k = 0; k < itab.m_icols; k++) { + for (uint k = 0; k < itab.m_icols; k++) { const ICol& icol = *itab.m_icol[k]; const Col& col = icol.m_col; - for (unsigned i = 0; i <= 1; i++) { + for (uint i = 0; i <= 1; i++) { if (m_bvals == 0 && urandom(100) == 0) return; if (m_bvals != 0 && urandom(3) == 0) @@ -3162,7 +3269,7 @@ BSet::calc(Par par) BVal& bval = *new BVal(icol); m_bval[m_bvals++] = &bval; bval.m_null = false; - unsigned sel; + uint sel; do { // equality bound only on i==0 sel = urandom(5 - i); @@ -3175,7 +3282,7 @@ BSet::calc(Par par) bval.m_type = 4; if (k + 1 < itab.m_icols) bval.m_type = 4; - if (! g_compare_null) + if (!g_compare_null) par.m_pctnull = 0; if (bval.m_type == 0 || bval.m_type == 1) par.m_bdir = -1; @@ -3199,11 +3306,11 @@ BSet::calc(Par par) } void -BSet::calcpk(Par par, unsigned i) +BSet::calcpk(Par par, uint i) { const ITab& itab = m_itab; reset(); - for (unsigned k = 0; k < itab.m_icols; k++) { + for (uint k = 0; k < itab.m_icols; k++) { const ICol& icol = *itab.m_icol[k]; const Col& col = icol.m_col; assert(col.m_pk); @@ -3220,14 +3327,14 @@ BSet::setbnd(Par par) const { if (m_bvals != 0) { Rsq rsq1(m_bvals); - for (unsigned j = 0; j < m_bvals; j++) { - unsigned j2 = rsq1.next(); + for (uint j = 0; j < m_bvals; j++) { + uint j2 = rsq1.next(); const BVal& bval = *m_bval[j2]; CHK(bval.setbnd(par) == 0); } // duplicate if (urandom(5) == 0) { - unsigned j3 = urandom(m_bvals); + uint j3 = urandom(m_bvals); const BVal& bval = *m_bval[j3]; CHK(bval.setbnd(par) == 0); } @@ -3243,14 +3350,14 @@ BSet::setflt(Par par) const CHK(con.beginFilter(NdbScanFilter::AND) == 0); if (m_bvals != 0) { Rsq rsq1(m_bvals); - for (unsigned j = 0; j < m_bvals; j++) { - unsigned j2 = rsq1.next(); + for (uint j = 0; j < m_bvals; j++) { + uint j2 = rsq1.next(); const BVal& bval = *m_bval[j2]; CHK(bval.setflt(par) == 0); } // duplicate if (urandom(5) == 0) { - unsigned j3 = urandom(m_bvals); + uint j3 = urandom(m_bvals); const BVal& bval = *m_bval[j3]; CHK(bval.setflt(par) == 0); } @@ -3266,57 +3373,59 @@ BSet::filter(Par par, const Set& set, Set& set2) const const ITab& itab = m_itab; assert(&tab == &set2.m_tab && set.m_rows == set2.m_rows); assert(set2.count() == 0); - for (unsigned i = 0; i < set.m_rows; i++) { - if (! set.exist(i)) - continue; + for (uint i = 0; i < set.m_rows; i++) { set.lock(); - const Row& row = set.dbrow(i); - set.unlock(); - if (! g_store_null_key) { - bool ok1 = false; - for (unsigned k = 0; k < itab.m_icols; k++) { - const ICol& icol = *itab.m_icol[k]; + do { + if (set.m_row[i] == 0) { + break; + } + const Row& row = *set.m_row[i]; + if (!g_store_null_key) { + bool ok1 = false; + for (uint k = 0; k < itab.m_icols; k++) { + const ICol& icol = *itab.m_icol[k]; + const Col& col = icol.m_col; + const Val& val = *row.m_val[col.m_num]; + if (!val.m_null) { + ok1 = true; + break; + } + } + if (!ok1) + break; + } + bool ok2 = true; + for (uint j = 0; j < m_bvals; j++) { + const BVal& bval = *m_bval[j]; + const ICol& icol = bval.m_icol; const Col& col = icol.m_col; const Val& val = *row.m_val[col.m_num]; - if (! val.m_null) { - ok1 = true; - break; + int ret = bval.cmp(par, val); + LL5("cmp: ret=" << ret << " " << bval << " vs " << val); + if (bval.m_type == 0) + ok2 = (ret <= 0); + else if (bval.m_type == 1) + ok2 = (ret < 0); + else if (bval.m_type == 2) + ok2 = (ret >= 0); + else if (bval.m_type == 3) + ok2 = (ret > 0); + else if (bval.m_type == 4) + ok2 = (ret == 0); + else { + assert(false); } + if (!ok2) + break; } - if (! ok1) - continue; - } - bool ok2 = true; - for (unsigned j = 0; j < m_bvals; j++) { - const BVal& bval = *m_bval[j]; - const ICol& icol = bval.m_icol; - const Col& col = icol.m_col; - const Val& val = *row.m_val[col.m_num]; - int ret = bval.cmp(par, val); - LL5("cmp: ret=" << ret << " " << bval << " vs " << val); - if (bval.m_type == 0) - ok2 = (ret <= 0); - else if (bval.m_type == 1) - ok2 = (ret < 0); - else if (bval.m_type == 2) - ok2 = (ret >= 0); - else if (bval.m_type == 3) - ok2 = (ret > 0); - else if (bval.m_type == 4) - ok2 = (ret == 0); - else { - assert(false); - } - if (! ok2) + if (!ok2) break; - } - if (! ok2) - continue; - if (set2.m_row[i] == 0) + assert(set2.m_row[i] == 0); set2.m_row[i] = new Row(tab); - Row& row2 = *set2.m_row[i]; - assert(! row2.m_exist); - row2.copy(row); + Row& row2 = *set2.m_row[i]; + row2.copy(row, true); + } while (0); + set.unlock(); } } @@ -3324,7 +3433,7 @@ static NdbOut& operator<<(NdbOut& out, const BSet& bset) { out << "bounds=" << bset.m_bvals; - for (unsigned j = 0; j < bset.m_bvals; j++) { + for (uint j = 0; j < bset.m_bvals; j++) { const BVal& bval = *bset.m_bval[j]; out << " [bound " << j << ": " << bval << "]"; } @@ -3341,59 +3450,40 @@ pkinsert(Par par) Set& set = par.set(); LL3("pkinsert " << tab.m_name); CHK(con.startTransaction() == 0); - Lst lst; - for (unsigned j = 0; j < par.m_rows; j++) { - unsigned j2 = ! par.m_randomkey ? j : urandom(par.m_rows); - unsigned i = thrrow(par, j2); + uint batch = 0; + for (uint j = 0; j < par.m_rows; j++) { + uint j2 = !par.m_randomkey ? j : urandom(par.m_rows); + uint i = thrrow(par, j2); set.lock(); - if (set.exist(i) || set.pending(i, Row::AnyOp)) { + if (!set.compat(par, i, Row::OpIns)) { + LL3("pkinsert SKIP " << i << " " << set.getrow(i)); set.unlock(); - continue; - } - set.calc(par, i); - CHK(set.insrow(par, i) == 0); - set.unlock(); - LL4("pkinsert " << i << ": " << *set.m_row[i]); - lst.push(i); - if (lst.cnt() == par.m_batch) { - bool deadlock = par.m_deadlock; - bool nospace = true; - ExecType et = randompct(par.m_abortpct) ? Rollback : Commit; - CHK(con.execute(et, deadlock, nospace) == 0); - con.closeTransaction(); - if (deadlock) { - LL1("pkinsert: stop on deadlock [at 1]"); - return 0; - } - if (nospace) { - LL1("pkinsert: cnt=" << j << " stop on nospace"); - return 0; - } + } else { + set.push(i); + set.calc(par, i); + CHK(set.insrow(par, i) == 0); + set.unlock(); + LL4("pkinsert key=" << i << " " << set.getrow(i)); + batch++; + } + bool lastbatch = (batch != 0 && j + 1 == par.m_rows); + if (batch == par.m_batch || lastbatch) { + uint err = par.m_catcherr; + ExecType et = !randompct(par.m_abortpct) ? Commit : Rollback; + CHK(con.execute(et, err) == 0); set.lock(); - set.notpending(lst, et); + set.post(par, !err ? et : Rollback); set.unlock(); - lst.reset(); - CHK(con.startTransaction() == 0); - } - } - if (lst.cnt() != 0) { - bool deadlock = par.m_deadlock; - bool nospace = true; - ExecType et = randompct(par.m_abortpct) ? Rollback : Commit; - CHK(con.execute(et, deadlock, nospace) == 0); - con.closeTransaction(); - if (deadlock) { - LL1("pkinsert: stop on deadlock [at 2]"); - return 0; - } - if (nospace) { - LL1("pkinsert: end: stop on nospace"); - return 0; + if (err) { + LL1("pkinsert key=" << i << " stop on " << con.errname(err)); + break; + } + batch = 0; + if (!lastbatch) { + con.closeTransaction(); + CHK(con.startTransaction() == 0); + } } - set.lock(); - set.notpending(lst, et); - set.unlock(); - return 0; } con.closeTransaction(); return 0; @@ -3407,59 +3497,40 @@ pkupdate(Par par) Set& set = par.set(); LL3("pkupdate " << tab.m_name); CHK(con.startTransaction() == 0); - Lst lst; - bool deadlock = false; - bool nospace = false; - for (unsigned j = 0; j < par.m_rows; j++) { - unsigned j2 = ! par.m_randomkey ? j : urandom(par.m_rows); - unsigned i = thrrow(par, j2); + uint batch = 0; + for (uint j = 0; j < par.m_rows; j++) { + uint j2 = !par.m_randomkey ? j : urandom(par.m_rows); + uint i = thrrow(par, j2); set.lock(); - if (! set.exist(i) || set.pending(i, Row::AnyOp)) { - set.unlock(); - continue; - } - set.dbsave(i); - set.calc(par, i); - CHK(set.updrow(par, i) == 0); - set.unlock(); - LL4("pkupdate " << i << ": " << *set.m_row[i]); - lst.push(i); - if (lst.cnt() == par.m_batch) { - deadlock = par.m_deadlock; - nospace = true; - ExecType et = randompct(par.m_abortpct) ? Rollback : Commit; - CHK(con.execute(et, deadlock, nospace) == 0); - if (deadlock) { - LL1("pkupdate: stop on deadlock [at 1]"); - break; - } - if (nospace) { - LL1("pkupdate: cnt=" << j << " stop on nospace [at 1]"); - break; - } - con.closeTransaction(); - set.lock(); - set.notpending(lst, et); - set.dbdiscard(lst); + if (!set.compat(par, i, Row::OpUpd)) { + LL3("pkupdate SKIP " << i << " " << set.getrow(i)); set.unlock(); - lst.reset(); - CHK(con.startTransaction() == 0); - } - } - if (! deadlock && ! nospace && lst.cnt() != 0) { - deadlock = par.m_deadlock; - nospace = true; - ExecType et = randompct(par.m_abortpct) ? Rollback : Commit; - CHK(con.execute(et, deadlock, nospace) == 0); - if (deadlock) { - LL1("pkupdate: stop on deadlock [at 2]"); - } else if (nospace) { - LL1("pkupdate: end: stop on nospace [at 2]"); } else { + set.push(i); + set.copyval(i, tab.m_pkmask); + set.calc(par, i, ~tab.m_pkmask); + CHK(set.updrow(par, i) == 0); + set.unlock(); + LL4("pkupdate key=" << i << " " << set.getrow(i)); + batch++; + } + bool lastbatch = (batch != 0 && j + 1 == par.m_rows); + if (batch == par.m_batch || lastbatch) { + uint err = par.m_catcherr; + ExecType et = !randompct(par.m_abortpct) ? Commit : Rollback; + CHK(con.execute(et, err) == 0); set.lock(); - set.notpending(lst, et); - set.dbdiscard(lst); + set.post(par, !err ? et : Rollback); set.unlock(); + if (err) { + LL1("pkupdate key=" << i << ": stop on " << con.errname(err)); + break; + } + batch = 0; + if (!lastbatch) { + con.closeTransaction(); + CHK(con.startTransaction() == 0); + } } } con.closeTransaction(); @@ -3474,49 +3545,39 @@ pkdelete(Par par) Set& set = par.set(); LL3("pkdelete " << tab.m_name); CHK(con.startTransaction() == 0); - Lst lst; - bool deadlock = false; - bool nospace = false; - for (unsigned j = 0; j < par.m_rows; j++) { - unsigned j2 = ! par.m_randomkey ? j : urandom(par.m_rows); - unsigned i = thrrow(par, j2); + uint batch = 0; + for (uint j = 0; j < par.m_rows; j++) { + uint j2 = !par.m_randomkey ? j : urandom(par.m_rows); + uint i = thrrow(par, j2); set.lock(); - if (! set.exist(i) || set.pending(i, Row::AnyOp)) { + if (!set.compat(par, i, Row::OpDel)) { + LL3("pkdelete SKIP " << i << " " << set.getrow(i)); set.unlock(); - continue; - } - CHK(set.delrow(par, i) == 0); - set.unlock(); - LL4("pkdelete " << i << ": " << *set.m_row[i]); - lst.push(i); - if (lst.cnt() == par.m_batch) { - deadlock = par.m_deadlock; - nospace = true; - ExecType et = randompct(par.m_abortpct) ? Rollback : Commit; - CHK(con.execute(et, deadlock, nospace) == 0); - if (deadlock) { - LL1("pkdelete: stop on deadlock [at 1]"); - break; - } - con.closeTransaction(); - set.lock(); - set.notpending(lst, et); - set.unlock(); - lst.reset(); - CHK(con.startTransaction() == 0); - } - } - if (! deadlock && ! nospace && lst.cnt() != 0) { - deadlock = par.m_deadlock; - nospace = true; - ExecType et = randompct(par.m_abortpct) ? Rollback : Commit; - CHK(con.execute(et, deadlock, nospace) == 0); - if (deadlock) { - LL1("pkdelete: stop on deadlock [at 2]"); } else { + set.push(i); + set.copyval(i, tab.m_pkmask); + CHK(set.delrow(par, i) == 0); + set.unlock(); + LL4("pkdelete key=" << i << " " << set.getrow(i)); + batch++; + } + bool lastbatch = (batch != 0 && j + 1 == par.m_rows); + if (batch == par.m_batch || lastbatch) { + uint err = par.m_catcherr; + ExecType et = !randompct(par.m_abortpct) ? Commit : Rollback; + CHK(con.execute(et, err) == 0); set.lock(); - set.notpending(lst, et); + set.post(par, !err ? et : Rollback); set.unlock(); + if (err) { + LL1("pkdelete key=" << i << " stop on " << con.errname(err)); + break; + } + batch = 0; + if (!lastbatch) { + con.closeTransaction(); + CHK(con.startTransaction() == 0); + } } } con.closeTransaction(); @@ -3533,9 +3594,11 @@ pkread(Par par) // expected const Set& set1 = set; Set set2(tab, set.m_rows); - for (unsigned i = 0; i < set.m_rows; i++) { + for (uint i = 0; i < set.m_rows; i++) { set.lock(); - if (! set.exist(i)) { + // TODO lock mode + if (!set.compat(par, i, Row::OpREAD)) { + LL3("pkread SKIP " << i << " " << set.getrow(i)); set.unlock(); continue; } @@ -3543,10 +3606,10 @@ pkread(Par par) CHK(con.startTransaction() == 0); CHK(set2.selrow(par, *set1.m_row[i]) == 0); CHK(con.execute(Commit) == 0); - unsigned i2 = (unsigned)-1; + uint i2 = (uint)-1; CHK(set2.getkey(par, &i2) == 0 && i == i2); CHK(set2.putval(i, false) == 0); - LL4("row " << set2.count() << ": " << *set2.m_row[i]); + LL4("row " << set2.count() << " " << set2.getrow(i)); con.closeTransaction(); } if (par.m_verify) @@ -3555,7 +3618,7 @@ pkread(Par par) } static int -pkreadfast(Par par, unsigned count) +pkreadfast(Par par, uint count) { Con& con = par.con(); const Tab& tab = par.tab(); @@ -3563,9 +3626,9 @@ pkreadfast(Par par, unsigned count) LL3("pkfast " << tab.m_name); Row keyrow(tab); // not batched on purpose - for (unsigned j = 0; j < count; j++) { - unsigned i = urandom(set.m_rows); - assert(set.exist(i)); + for (uint j = 0; j < count; j++) { + uint i = urandom(set.m_rows); + assert(set.compat(par, i, Row::OpREAD)); CHK(con.startTransaction() == 0); // define key keyrow.calc(par, i); @@ -3585,53 +3648,46 @@ static int hashindexupdate(Par par, const ITab& itab) { Con& con = par.con(); + const Tab& tab = par.tab(); Set& set = par.set(); LL3("hashindexupdate " << itab.m_name); CHK(con.startTransaction() == 0); - Lst lst; - bool deadlock = false; - bool nospace = false; - for (unsigned j = 0; j < par.m_rows; j++) { - unsigned j2 = ! par.m_randomkey ? j : urandom(par.m_rows); - unsigned i = thrrow(par, j2); + uint batch = 0; + for (uint j = 0; j < par.m_rows; j++) { + uint j2 = !par.m_randomkey ? j : urandom(par.m_rows); + uint i = thrrow(par, j2); set.lock(); - if (! set.exist(i) || set.pending(i, Row::AnyOp)) { + if (!set.compat(par, i, Row::OpUpd)) { + LL3("hashindexupdate SKIP " << i << " " << set.getrow(i)); set.unlock(); - continue; - } - set.dbsave(i); - // index key columns are not re-calculated - set.calc(par, i, itab.m_colmask); - CHK(set.updrow(par, itab, i) == 0); - set.unlock(); - LL4("hashindexupdate " << i << ": " << *set.m_row[i]); - lst.push(i); - if (lst.cnt() == par.m_batch) { - deadlock = par.m_deadlock; - CHK(con.execute(Commit, deadlock, nospace) == 0); - if (deadlock) { - LL1("hashindexupdate: stop on deadlock [at 1]"); - break; - } - con.closeTransaction(); - set.lock(); - set.notpending(lst); - set.dbdiscard(lst); - set.unlock(); - lst.reset(); - CHK(con.startTransaction() == 0); - } - } - if (! deadlock && lst.cnt() != 0) { - deadlock = par.m_deadlock; - CHK(con.execute(Commit, deadlock, nospace) == 0); - if (deadlock) { - LL1("hashindexupdate: stop on deadlock [at 2]"); } else { + // table pk and index key are not updated + set.push(i); + uint keymask = tab.m_pkmask | itab.m_keymask; + set.copyval(i, keymask); + set.calc(par, i, ~keymask); + CHK(set.updrow(par, itab, i) == 0); + set.unlock(); + LL4("hashindexupdate " << i << " " << set.getrow(i)); + batch++; + } + bool lastbatch = (batch != 0 && j + 1 == par.m_rows); + if (batch == par.m_batch || lastbatch) { + uint err = par.m_catcherr; + ExecType et = !randompct(par.m_abortpct) ? Commit : Rollback; + CHK(con.execute(et, err) == 0); set.lock(); - set.notpending(lst); - set.dbdiscard(lst); + set.post(par, !err ? et : Rollback); set.unlock(); + if (err) { + LL1("hashindexupdate " << i << " stop on " << con.errname(err)); + break; + } + batch = 0; + if (!lastbatch) { + con.closeTransaction(); + CHK(con.startTransaction() == 0); + } } } con.closeTransaction(); @@ -3645,45 +3701,39 @@ hashindexdelete(Par par, const ITab& itab) Set& set = par.set(); LL3("hashindexdelete " << itab.m_name); CHK(con.startTransaction() == 0); - Lst lst; - bool deadlock = false; - bool nospace = false; - for (unsigned j = 0; j < par.m_rows; j++) { - unsigned j2 = ! par.m_randomkey ? j : urandom(par.m_rows); - unsigned i = thrrow(par, j2); + uint batch = 0; + for (uint j = 0; j < par.m_rows; j++) { + uint j2 = !par.m_randomkey ? j : urandom(par.m_rows); + uint i = thrrow(par, j2); set.lock(); - if (! set.exist(i) || set.pending(i, Row::AnyOp)) { - set.unlock(); - continue; - } - CHK(set.delrow(par, itab, i) == 0); - set.unlock(); - LL4("hashindexdelete " << i << ": " << *set.m_row[i]); - lst.push(i); - if (lst.cnt() == par.m_batch) { - deadlock = par.m_deadlock; - CHK(con.execute(Commit, deadlock, nospace) == 0); - if (deadlock) { - LL1("hashindexdelete: stop on deadlock [at 1]"); - break; - } - con.closeTransaction(); - set.lock(); - set.notpending(lst); + if (!set.compat(par, i, Row::OpDel)) { + LL3("hashindexdelete SKIP " << i << " " << set.getrow(i)); set.unlock(); - lst.reset(); - CHK(con.startTransaction() == 0); - } - } - if (! deadlock && lst.cnt() != 0) { - deadlock = par.m_deadlock; - CHK(con.execute(Commit, deadlock, nospace) == 0); - if (deadlock) { - LL1("hashindexdelete: stop on deadlock [at 2]"); } else { + set.push(i); + set.copyval(i, itab.m_keymask); + CHK(set.delrow(par, itab, i) == 0); + set.unlock(); + LL4("hashindexdelete " << i << " " << set.getrow(i)); + batch++; + } + bool lastbatch = (batch != 0 && j + 1 == par.m_rows); + if (batch == par.m_batch || lastbatch) { + uint err = par.m_catcherr; + ExecType et = !randompct(par.m_abortpct) ? Commit : Rollback; + CHK(con.execute(et, err) == 0); set.lock(); - set.notpending(lst); + set.post(par, !err ? et : Rollback); set.unlock(); + if (err) { + LL1("hashindexdelete " << i << " stop on " << con.errname(err)); + break; + } + batch = 0; + if (!lastbatch) { + con.closeTransaction(); + CHK(con.startTransaction() == 0); + } } } con.closeTransaction(); @@ -3700,9 +3750,11 @@ hashindexread(Par par, const ITab& itab) // expected const Set& set1 = set; Set set2(tab, set.m_rows); - for (unsigned i = 0; i < set.m_rows; i++) { + for (uint i = 0; i < set.m_rows; i++) { set.lock(); - if (! set.exist(i)) { + // TODO lock mode + if (!set.compat(par, i, Row::OpREAD)) { + LL3("hashindexread SKIP " << i << " " << set.getrow(i)); set.unlock(); continue; } @@ -3710,10 +3762,10 @@ hashindexread(Par par, const ITab& itab) CHK(con.startTransaction() == 0); CHK(set2.selrow(par, itab, *set1.m_row[i]) == 0); CHK(con.execute(Commit) == 0); - unsigned i2 = (unsigned)-1; + uint i2 = (uint)-1; CHK(set2.getkey(par, &i2) == 0 && i == i2); CHK(set2.putval(i, false) == 0); - LL4("row " << set2.count() << ": " << *set2.m_row[i]); + LL4("row " << set2.count() << " " << *set2.m_row[i]); con.closeTransaction(); } if (par.m_verify) @@ -3731,40 +3783,39 @@ scanreadtable(Par par) const Set& set = par.set(); // expected const Set& set1 = set; - LL3("scanread " << tab.m_name << " lockmode=" << par.m_lockmode << " tupscan=" << par.m_tupscan << " expect=" << set1.count() << " verify=" << par.m_verify); + LL3("scanreadtable " << tab.m_name << " lockmode=" << par.m_lockmode << " tupscan=" << par.m_tupscan << " expect=" << set1.count() << " verify=" << par.m_verify); Set set2(tab, set.m_rows); CHK(con.startTransaction() == 0); CHK(con.getNdbScanOperation(tab) == 0); CHK(con.readTuples(par) == 0); set2.getval(par); CHK(con.executeScan() == 0); - unsigned n = 0; - bool deadlock = false; + uint n = 0; while (1) { int ret; - deadlock = par.m_deadlock; - CHK((ret = con.nextScanResult(true, deadlock)) == 0 || ret == 1); + uint err = par.m_catcherr; + CHK((ret = con.nextScanResult(true, err)) == 0 || ret == 1); if (ret == 1) break; - if (deadlock) { - LL1("scanreadtable: stop on deadlock"); + if (err) { + LL1("scanreadtable stop on " << con.errname(err)); break; } - unsigned i = (unsigned)-1; + uint i = (uint)-1; CHK(set2.getkey(par, &i) == 0); CHK(set2.putval(i, false, n) == 0); - LL4("row " << n << ": " << *set2.m_row[i]); + LL4("row " << n << " " << *set2.m_row[i]); n++; } con.closeTransaction(); if (par.m_verify) CHK(set1.verify(par, set2, false) == 0); - LL3("scanread " << tab.m_name << " done rows=" << n); + LL3("scanreadtable " << tab.m_name << " done rows=" << n); return 0; } static int -scanreadtablefast(Par par, unsigned countcheck) +scanreadtablefast(Par par, uint countcheck) { Con& con = par.con(); const Tab& tab = par.tab(); @@ -3777,7 +3828,7 @@ scanreadtablefast(Par par, unsigned countcheck) NdbRecAttr* rec; CHK(con.getValue((Uint32)0, rec) == 0); CHK(con.executeScan() == 0); - unsigned count = 0; + uint count = 0; while (1) { int ret; CHK((ret = con.nextScanResult(true)) == 0 || ret == 1); @@ -3797,7 +3848,7 @@ calcscanbounds(Par par, const ITab& itab, BSet& bset, const Set& set, Set& set1) while (true) { bset.calc(par); bset.filter(par, set, set1); - unsigned n = set1.count(); + uint n = set1.count(); // prefer proper subset if (0 < n && n < set.m_rows) break; @@ -3819,7 +3870,7 @@ scanreadindex(Par par, const ITab& itab, BSet& bset, bool calc) } else { bset.filter(par, set, set1); } - LL3("scanread " << itab.m_name << " " << bset << " lockmode=" << par.m_lockmode << " expect=" << set1.count() << " ordered=" << par.m_ordered << " descending=" << par.m_descending << " verify=" << par.m_verify); + LL3("scanreadindex " << itab.m_name << " " << bset << " lockmode=" << par.m_lockmode << " expect=" << set1.count() << " ordered=" << par.m_ordered << " descending=" << par.m_descending << " verify=" << par.m_verify); Set set2(tab, set.m_rows); CHK(con.startTransaction() == 0); CHK(con.getNdbIndexScanOperation(itab, tab) == 0); @@ -3827,22 +3878,21 @@ scanreadindex(Par par, const ITab& itab, BSet& bset, bool calc) CHK(bset.setbnd(par) == 0); set2.getval(par); CHK(con.executeScan() == 0); - unsigned n = 0; - bool deadlock = false; + uint n = 0; while (1) { int ret; - deadlock = par.m_deadlock; - CHK((ret = con.nextScanResult(true, deadlock)) == 0 || ret == 1); + uint err = par.m_catcherr; + CHK((ret = con.nextScanResult(true, err)) == 0 || ret == 1); if (ret == 1) break; - if (deadlock) { - LL1("scanreadindex: stop on deadlock"); + if (err) { + LL1("scanreadindex stop on " << con.errname(err)); break; } - unsigned i = (unsigned)-1; + uint i = (uint)-1; CHK(set2.getkey(par, &i) == 0); CHK(set2.putval(i, par.m_dups, n) == 0); - LL4("key " << i << " row " << n << ": " << *set2.m_row[i]); + LL4("key " << i << " row " << n << " " << *set2.m_row[i]); n++; } con.closeTransaction(); @@ -3851,12 +3901,12 @@ scanreadindex(Par par, const ITab& itab, BSet& bset, bool calc) if (par.m_ordered) CHK(set2.verifyorder(par, itab, par.m_descending) == 0); } - LL3("scanread " << itab.m_name << " done rows=" << n); + LL3("scanreadindex " << itab.m_name << " done rows=" << n); return 0; } static int -scanreadindexfast(Par par, const ITab& itab, const BSet& bset, unsigned countcheck) +scanreadindexfast(Par par, const ITab& itab, const BSet& bset, uint countcheck) { Con& con = par.con(); const Tab& tab = par.tab(); @@ -3871,7 +3921,7 @@ scanreadindexfast(Par par, const ITab& itab, const BSet& bset, unsigned countche NdbRecAttr* rec; CHK(con.getValue((Uint32)0, rec) == 0); CHK(con.executeScan() == 0); - unsigned count = 0; + uint count = 0; while (1) { int ret; CHK((ret = con.nextScanResult(true)) == 0 || ret == 1); @@ -3904,22 +3954,21 @@ scanreadfilter(Par par, const ITab& itab, BSet& bset, bool calc) CHK(bset.setflt(par) == 0); set2.getval(par); CHK(con.executeScan() == 0); - unsigned n = 0; - bool deadlock = false; + uint n = 0; while (1) { int ret; - deadlock = par.m_deadlock; - CHK((ret = con.nextScanResult(true, deadlock)) == 0 || ret == 1); + uint err = par.m_catcherr; + CHK((ret = con.nextScanResult(true, err)) == 0 || ret == 1); if (ret == 1) break; - if (deadlock) { - LL1("scanfilter: stop on deadlock"); + if (err) { + LL1("scanfilter stop on " << con.errname(err)); break; } - unsigned i = (unsigned)-1; + uint i = (uint)-1; CHK(set2.getkey(par, &i) == 0); CHK(set2.putval(i, par.m_dups, n) == 0); - LL4("key " << i << " row " << n << ": " << *set2.m_row[i]); + LL4("key " << i << " row " << n << " " << *set2.m_row[i]); n++; } con.closeTransaction(); @@ -3934,9 +3983,9 @@ static int scanreadindex(Par par, const ITab& itab) { const Tab& tab = par.tab(); - for (unsigned i = 0; i < par.m_subloop; i++) { + for (uint i = 0; i < par.m_ssloop; i++) { if (itab.m_type == ITab::OrderedIndex) { - BSet bset(tab, itab, par.m_rows); + BSet bset(tab, itab); CHK(scanreadfilter(par, itab, bset, true) == 0); CHK(scanreadindex(par, itab, bset, true) == 0); } @@ -3948,7 +3997,7 @@ static int scanreadindex(Par par) { const Tab& tab = par.tab(); - for (unsigned i = 0; i < tab.m_itabs; i++) { + for (uint i = 0; i < tab.m_itabs; i++) { if (tab.m_itab[i] == 0) continue; const ITab& itab = *tab.m_itab[i]; @@ -3985,7 +4034,7 @@ timescanpkindex(Par par) { const Tab& tab = par.tab(); const ITab& itab = *tab.m_itab[0]; // 1st index is on PK - BSet bset(tab, itab, par.m_rows); + BSet bset(tab, itab); par.tmr().on(); CHK(scanreadindexfast(par, itab, bset, par.m_totrows) == 0); par.tmr().off(par.set().m_rows); @@ -3996,7 +4045,7 @@ static int timepkreadtable(Par par) { par.tmr().on(); - unsigned count = par.m_samples; + uint count = par.m_samples; if (count == 0) count = par.m_totrows; CHK(pkreadfast(par, count) == 0); @@ -4009,13 +4058,13 @@ timepkreadindex(Par par) { const Tab& tab = par.tab(); const ITab& itab = *tab.m_itab[0]; // 1st index is on PK - BSet bset(tab, itab, par.m_rows); - unsigned count = par.m_samples; + BSet bset(tab, itab); + uint count = par.m_samples; if (count == 0) count = par.m_totrows; par.tmr().on(); - for (unsigned j = 0; j < count; j++) { - unsigned i = urandom(par.m_totrows); + for (uint j = 0; j < count; j++) { + uint i = urandom(par.m_totrows); bset.calcpk(par, i); CHK(scanreadindexfast(par, itab, bset, 1) == 0); } @@ -4031,7 +4080,7 @@ scanupdatetable(Par par) Con& con = par.con(); const Tab& tab = par.tab(); Set& set = par.set(); - LL3("scan update " << tab.m_name); + LL3("scanupdatetable " << tab.m_name); Set set2(tab, set.m_rows); par.m_lockmode = NdbOperation::LM_Exclusive; CHK(con.startTransaction() == 0); @@ -4039,87 +4088,70 @@ scanupdatetable(Par par) CHK(con.readTuples(par) == 0); set2.getval(par); CHK(con.executeScan() == 0); - unsigned count = 0; + uint count = 0; // updating trans Con con2; con2.connect(con); CHK(con2.startTransaction() == 0); - Lst lst; - bool deadlock = false; - bool nospace = false; + uint batch = 0; while (1) { int ret; - deadlock = par.m_deadlock; - CHK((ret = con.nextScanResult(true, deadlock)) == 0 || ret == 1); - if (ret == 1) + uint32 err = par.m_catcherr; + CHK((ret = con.nextScanResult(true, err)) != -1); + if (ret != 0) break; - if (deadlock) { - LL1("scanupdatetable: stop on deadlock [at 1]"); + if (err) { + LL1("scanupdatetable [scan] stop on " << con.errname(err)); break; } if (par.m_scanstop != 0 && urandom(par.m_scanstop) == 0) { con.closeScan(); break; } - do { - unsigned i = (unsigned)-1; + while (1) { + uint i = (uint)-1; CHK(set2.getkey(par, &i) == 0); - const Row& row = *set.m_row[i]; set.lock(); - if (! set.exist(i) || set.pending(i, Row::AnyOp)) { - LL4("scan update " << tab.m_name << ": skip: " << row); + if (!set.compat(par, i, Row::OpUpd)) { + LL3("scanupdatetable SKIP " << i << " " << set.getrow(i)); } else { CHKTRY(set2.putval(i, false) == 0, set.unlock()); CHKTRY(con.updateScanTuple(con2) == 0, set.unlock()); Par par2 = par; par2.m_con = &con2; - set.dbsave(i); - set.calc(par, i); + set.push(i); + set.calc(par, i, ~tab.m_pkmask); CHKTRY(set.setrow(par2, i) == 0, set.unlock()); - LL4("scan update " << tab.m_name << ": " << row); - lst.push(i); + LL4("scanupdatetable " << i << " " << set.getrow(i)); + batch++; } set.unlock(); - if (lst.cnt() == par.m_batch) { - deadlock = par.m_deadlock; - CHK(con2.execute(Commit, deadlock, nospace) == 0); - if (deadlock) { - LL1("scanupdatetable: stop on deadlock [at 2]"); - goto out; - } - con2.closeTransaction(); + CHK((ret = con.nextScanResult(false)) != -1); + bool lastbatch = (batch != 0 && ret != 0); + if (batch == par.m_batch || lastbatch) { + uint err = par.m_catcherr; + ExecType et = Commit; + CHK(con2.execute(et, err) == 0); set.lock(); - set.notpending(lst); - set.dbdiscard(lst); + set.post(par, !err ? et : Rollback); set.unlock(); - count += lst.cnt(); - lst.reset(); - CHK(con2.startTransaction() == 0); - } - CHK((ret = con.nextScanResult(false)) == 0 || ret == 1 || ret == 2); - if (ret == 2 && lst.cnt() != 0) { - deadlock = par.m_deadlock; - CHK(con2.execute(Commit, deadlock, nospace) == 0); - if (deadlock) { - LL1("scanupdatetable: stop on deadlock [at 3]"); + if (err) { + LL1("scanupdatetable [update] stop on " << con2.errname(err)); goto out; } + LL4("scanupdatetable committed batch"); + count += batch; + batch = 0; con2.closeTransaction(); - set.lock(); - set.notpending(lst); - set.dbdiscard(lst); - set.unlock(); - count += lst.cnt(); - lst.reset(); CHK(con2.startTransaction() == 0); } - } while (ret == 0); - if (ret == 1) - break; + if (ret != 0) + break; + } } out: con2.closeTransaction(); - LL3("scan update " << tab.m_name << " rows updated=" << count); + LL3("scanupdatetable " << tab.m_name << " rows updated=" << count); con.closeTransaction(); return 0; } @@ -4137,7 +4169,7 @@ scanupdateindex(Par par, const ITab& itab, BSet& bset, bool calc) } else { bset.filter(par, set, set1); } - LL3("scan update " << itab.m_name << " " << bset << " expect=" << set1.count() << " ordered=" << par.m_ordered << " descending=" << par.m_descending << " verify=" << par.m_verify); + LL3("scanupdateindex " << itab.m_name << " " << bset << " expect=" << set1.count() << " ordered=" << par.m_ordered << " descending=" << par.m_descending << " verify=" << par.m_verify); Set set2(tab, set.m_rows); par.m_lockmode = NdbOperation::LM_Exclusive; CHK(con.startTransaction() == 0); @@ -4146,83 +4178,67 @@ scanupdateindex(Par par, const ITab& itab, BSet& bset, bool calc) CHK(bset.setbnd(par) == 0); set2.getval(par); CHK(con.executeScan() == 0); - unsigned count = 0; + uint count = 0; // updating trans Con con2; con2.connect(con); CHK(con2.startTransaction() == 0); - Lst lst; - bool deadlock = false; - bool nospace = false; + uint batch = 0; while (1) { int ret; - deadlock = par.m_deadlock; - CHK((ret = con.nextScanResult(true, deadlock)) == 0 || ret == 1); - if (ret == 1) + uint err = par.m_catcherr; + CHK((ret = con.nextScanResult(true, err)) != -1); + if (ret != 0) break; - if (deadlock) { - LL1("scanupdateindex: stop on deadlock [at 1]"); + if (err) { + LL1("scanupdateindex [scan] stop on " << con.errname(err)); break; } if (par.m_scanstop != 0 && urandom(par.m_scanstop) == 0) { con.closeScan(); break; } - do { - unsigned i = (unsigned)-1; + while (1) { + uint i = (uint)-1; CHK(set2.getkey(par, &i) == 0); - const Row& row = *set.m_row[i]; set.lock(); - if (! set.exist(i) || set.pending(i, Row::AnyOp)) { - LL4("scan update " << itab.m_name << ": skip: " << row); + if (!set.compat(par, i, Row::OpUpd)) { + LL4("scanupdateindex SKIP " << set.getrow(i)); } else { CHKTRY(set2.putval(i, par.m_dups) == 0, set.unlock()); CHKTRY(con.updateScanTuple(con2) == 0, set.unlock()); Par par2 = par; par2.m_con = &con2; - set.dbsave(i); - set.calc(par, i, ! par.m_noindexkeyupdate ? 0 : itab.m_colmask); + set.push(i); + uint colmask = !par.m_noindexkeyupdate ? ~0 : ~itab.m_keymask; + set.calc(par, i, colmask); CHKTRY(set.setrow(par2, i) == 0, set.unlock()); - LL4("scan update " << itab.m_name << ": " << row); - lst.push(i); + LL4("scanupdateindex " << i << " " << set.getrow(i)); + batch++; } set.unlock(); - if (lst.cnt() == par.m_batch) { - deadlock = par.m_deadlock; - CHK(con2.execute(Commit, deadlock, nospace) == 0); - if (deadlock) { - LL1("scanupdateindex: stop on deadlock [at 2]"); - goto out; - } - con2.closeTransaction(); - LL4("scanupdateindex: committed batch [at 1]"); + CHK((ret = con.nextScanResult(false)) != -1); + bool lastbatch = (batch != 0 && ret != 0); + if (batch == par.m_batch || lastbatch) { + uint err = par.m_catcherr; + ExecType et = Commit; + CHK(con2.execute(et, err) == 0); set.lock(); - set.notpending(lst); - set.dbdiscard(lst); + set.post(par, !err ? et : Rollback); set.unlock(); - count += lst.cnt(); - lst.reset(); - CHK(con2.startTransaction() == 0); - } - CHK((ret = con.nextScanResult(false)) == 0 || ret == 1 || ret == 2); - if (ret == 2 && lst.cnt() != 0) { - deadlock = par.m_deadlock; - CHK(con2.execute(Commit, deadlock, nospace) == 0); - if (deadlock) { - LL1("scanupdateindex: stop on deadlock [at 3]"); + if (err) { + LL1("scanupdateindex [update] stop on " << con2.errname(err)); goto out; } + LL4("scanupdateindex committed batch"); + count += batch; + batch = 0; con2.closeTransaction(); - LL4("scanupdateindex: committed batch [at 2]"); - set.lock(); - set.notpending(lst); - set.dbdiscard(lst); - set.unlock(); - count += lst.cnt(); - lst.reset(); CHK(con2.startTransaction() == 0); } - } while (ret == 0); + if (ret != 0) + break; + } } out: con2.closeTransaction(); @@ -4231,7 +4247,7 @@ out: if (par.m_ordered) CHK(set2.verifyorder(par, itab, par.m_descending) == 0); } - LL3("scan update " << itab.m_name << " rows updated=" << count); + LL3("scanupdateindex " << itab.m_name << " rows updated=" << count); con.closeTransaction(); return 0; } @@ -4240,9 +4256,9 @@ static int scanupdateindex(Par par, const ITab& itab) { const Tab& tab = par.tab(); - for (unsigned i = 0; i < par.m_subloop; i++) { + for (uint i = 0; i < par.m_ssloop; i++) { if (itab.m_type == ITab::OrderedIndex) { - BSet bset(tab, itab, par.m_rows); + BSet bset(tab, itab); CHK(scanupdateindex(par, itab, bset, true) == 0); } else { CHK(hashindexupdate(par, itab) == 0); @@ -4255,7 +4271,7 @@ static int scanupdateindex(Par par) { const Tab& tab = par.tab(); - for (unsigned i = 0; i < tab.m_itabs; i++) { + for (uint i = 0; i < tab.m_itabs; i++) { if (tab.m_itab[i] == 0) continue; const ITab& itab = *tab.m_itab[i]; @@ -4294,14 +4310,14 @@ readverifyfull(Par par) CHK(scanreadtable(par) == 0); } // each thread scans different indexes - for (unsigned i = 0; i < tab.m_itabs; i++) { - if (i % par.m_threads != par.m_no) + for (uint i = 0; i < tab.m_itabs; i++) { + if (i % par.m_usedthreads != par.m_no) continue; if (tab.m_itab[i] == 0) continue; const ITab& itab = *tab.m_itab[i]; if (itab.m_type == ITab::OrderedIndex) { - BSet bset(tab, itab, par.m_rows); + BSet bset(tab, itab); CHK(scanreadindex(par, itab, bset, false) == 0); } else { CHK(hashindexread(par, itab) == 0); @@ -4317,7 +4333,7 @@ readverifyindex(Par par) return 0; par.m_verify = true; par.m_lockmode = NdbOperation::LM_CommittedRead; - unsigned sel = urandom(10); + uint sel = urandom(10); if (sel < 9) { par.m_ordered = true; par.m_descending = (sel < 5); @@ -4331,8 +4347,8 @@ pkops(Par par) { const Tab& tab = par.tab(); par.m_randomkey = true; - for (unsigned i = 0; i < par.m_subloop; i++) { - unsigned j = 0; + for (uint i = 0; i < par.m_ssloop; i++) { + uint j = 0; while (j < tab.m_itabs) { if (tab.m_itab[j] != 0) { const ITab& itab = *tab.m_itab[j]; @@ -4341,7 +4357,7 @@ pkops(Par par) } j++; } - unsigned sel = urandom(10); + uint sel = urandom(10); if (par.m_slno % 2 == 0) { // favor insert if (sel < 8) { @@ -4389,8 +4405,8 @@ static int pkupdatescanread(Par par) { par.m_dups = true; - par.m_deadlock = true; - unsigned sel = urandom(10); + par.m_catcherr |= Con::ErrDeadlock; + uint sel = urandom(10); if (sel < 5) { CHK(pkupdate(par) == 0); } else if (sel < 6) { @@ -4411,9 +4427,9 @@ static int mixedoperations(Par par) { par.m_dups = true; - par.m_deadlock = true; + par.m_catcherr |= Con::ErrDeadlock; par.m_scanstop = par.m_totrows; // randomly close scans - unsigned sel = urandom(10); + uint sel = urandom(10); if (sel < 2) { CHK(pkdelete(par) == 0); } else if (sel < 4) { @@ -4434,8 +4450,8 @@ static int parallelorderedupdate(Par par) { const Tab& tab = par.tab(); - unsigned k = 0; - for (unsigned i = 0; i < tab.m_itabs; i++) { + uint k = 0; + for (uint i = 0; i < tab.m_itabs; i++) { if (tab.m_itab[i] == 0) continue; const ITab& itab = *tab.m_itab[i]; @@ -4447,10 +4463,11 @@ parallelorderedupdate(Par par) par.m_noindexkeyupdate = true; par.m_ordered = true; par.m_descending = (par.m_slno != 0); + par.m_dups = false; par.m_verify = true; - BSet bset(tab, itab, par.m_rows); // empty bounds + BSet bset(tab, itab); // empty bounds // prefer empty bounds - unsigned sel = urandom(10); + uint sel = urandom(10); CHK(scanupdateindex(par, itab, bset, sel < 2) == 0); } } @@ -4469,6 +4486,418 @@ pkupdateindexbuild(Par par) return 0; } +// savepoint tests (single thread for now) + +struct Spt { + enum Res { Committed, Latest, Deadlock }; + bool m_same; // same transaction + NdbOperation::LockMode m_lm; + Res m_res; +}; + +static Spt sptlist[] = { + { 1, NdbOperation::LM_Read, Spt::Latest }, + { 1, NdbOperation::LM_Exclusive, Spt::Latest }, + { 1, NdbOperation::LM_CommittedRead, Spt::Latest }, + { 0, NdbOperation::LM_Read, Spt::Deadlock }, + { 0, NdbOperation::LM_Exclusive, Spt::Deadlock }, + { 0, NdbOperation::LM_CommittedRead, Spt::Committed } +}; +static uint sptcount = sizeof(sptlist)/sizeof(sptlist[0]); + +static int +savepointreadpk(Par par, Spt spt) +{ + LL3("savepointreadpk"); + Con& con = par.con(); + const Tab& tab = par.tab(); + Set& set = par.set(); + const Set& set1 = set; + Set set2(tab, set.m_rows); + uint n = 0; + for (uint i = 0; i < set.m_rows; i++) { + set.lock(); + if (!set.compat(par, i, Row::OpREAD)) { + LL4("savepointreadpk SKIP " << i << " " << set.getrow(i)); + set.unlock(); + continue; + } + set.unlock(); + CHK(set2.selrow(par, *set1.m_row[i]) == 0); + uint err = par.m_catcherr | Con::ErrDeadlock; + ExecType et = NoCommit; + CHK(con.execute(et, err) == 0); + if (err) { + if (err & Con::ErrDeadlock) { + CHK(spt.m_res == Spt::Deadlock); + // all rows have same behaviour + CHK(n == 0); + } + LL1("savepointreadpk stop on " << con.errname(err)); + break; + } + uint i2 = (uint)-1; + CHK(set2.getkey(par, &i2) == 0 && i == i2); + CHK(set2.putval(i, false) == 0); + LL4("row " << set2.count() << " " << set2.getrow(i)); + n++; + } + bool dirty = (!spt.m_same && spt.m_lm == NdbOperation::LM_CommittedRead); + if (spt.m_res != Spt::Deadlock) + CHK(set1.verify(par, set2, false, dirty) == 0); + return 0; +} + +static int +savepointreadhashindex(Par par, Spt spt) +{ + if (spt.m_lm == NdbOperation::LM_CommittedRead && !spt.m_same) { + LL1("skip hash index dirty read"); + return 0; + } + LL3("savepointreadhashindex"); + Con& con = par.con(); + const Tab& tab = par.tab(); + const ITab& itab = par.itab(); + Set& set = par.set(); + const Set& set1 = set; + Set set2(tab, set.m_rows); + uint n = 0; + for (uint i = 0; i < set.m_rows; i++) { + set.lock(); + if (!set.compat(par, i, Row::OpREAD)) { + LL3("savepointreadhashindex SKIP " << i << " " << set.getrow(i)); + set.unlock(); + continue; + } + set.unlock(); + CHK(set2.selrow(par, itab, *set1.m_row[i]) == 0); + uint err = par.m_catcherr | Con::ErrDeadlock; + ExecType et = NoCommit; + CHK(con.execute(et, err) == 0); + if (err) { + if (err & Con::ErrDeadlock) { + CHK(spt.m_res == Spt::Deadlock); + // all rows have same behaviour + CHK(n == 0); + } + LL1("savepointreadhashindex stop on " << con.errname(err)); + break; + } + uint i2 = (uint)-1; + CHK(set2.getkey(par, &i2) == 0 && i == i2); + CHK(set2.putval(i, false) == 0); + LL4("row " << set2.count() << " " << *set2.m_row[i]); + n++; + } + bool dirty = (!spt.m_same && spt.m_lm == NdbOperation::LM_CommittedRead); + if (spt.m_res != Spt::Deadlock) + CHK(set1.verify(par, set2, false, dirty) == 0); + return 0; +} + +static int +savepointscantable(Par par, Spt spt) +{ + LL3("savepointscantable"); + Con& con = par.con(); + const Tab& tab = par.tab(); + const Set& set = par.set(); + const Set& set1 = set; // not modifying current set + Set set2(tab, set.m_rows); // scan result + CHK(con.getNdbScanOperation(tab) == 0); + CHK(con.readTuples(par) == 0); + set2.getval(par); // getValue all columns + CHK(con.executeScan() == 0); + bool deadlock = false; + uint n = 0; + while (1) { + int ret; + uint err = par.m_catcherr | Con::ErrDeadlock; + CHK((ret = con.nextScanResult(true, err)) == 0 || ret == 1); + if (ret == 1) + break; + if (err) { + if (err & Con::ErrDeadlock) { + CHK(spt.m_res == Spt::Deadlock); + // all rows have same behaviour + CHK(n == 0); + deadlock = true; + } + LL1("savepointscantable stop on " << con.errname(err)); + break; + } + CHK(spt.m_res != Spt::Deadlock); + uint i = (uint)-1; + CHK(set2.getkey(par, &i) == 0); + CHK(set2.putval(i, false, n) == 0); + LL4("row " << n << " key " << i << " " << set2.getrow(i)); + n++; + } + if (set1.m_rows > 0) { + if (!deadlock) + CHK(spt.m_res != Spt::Deadlock); + else + CHK(spt.m_res == Spt::Deadlock); + } + LL2("savepointscantable " << n << " rows"); + bool dirty = (!spt.m_same && spt.m_lm == NdbOperation::LM_CommittedRead); + if (spt.m_res != Spt::Deadlock) + CHK(set1.verify(par, set2, false, dirty) == 0); + return 0; +} + +static int +savepointscanindex(Par par, Spt spt) +{ + LL3("savepointscanindex"); + Con& con = par.con(); + const Tab& tab = par.tab(); + const ITab& itab = par.itab(); + const Set& set = par.set(); + const Set& set1 = set; + Set set2(tab, set.m_rows); + CHK(con.getNdbIndexScanOperation(itab, tab) == 0); + CHK(con.readIndexTuples(par) == 0); + set2.getval(par); + CHK(con.executeScan() == 0); + bool deadlock = false; + uint n = 0; + while (1) { + int ret; + uint err = par.m_catcherr | Con::ErrDeadlock; + CHK((ret = con.nextScanResult(true, err)) == 0 || ret == 1); + if (ret == 1) + break; + if (err) { + if (err & Con::ErrDeadlock) { + CHK(spt.m_res == Spt::Deadlock); + // all rows have same behaviour + CHK(n == 0); + deadlock = true; + } + LL1("savepointscanindex stop on " << con.errname(err)); + break; + } + CHK(spt.m_res != Spt::Deadlock); + uint i = (uint)-1; + CHK(set2.getkey(par, &i) == 0); + CHK(set2.putval(i, par.m_dups, n) == 0); + LL4("row " << n << " key " << i << " " << set2.getrow(i)); + n++; + } + if (set1.m_rows > 0) { + if (!deadlock) + CHK(spt.m_res != Spt::Deadlock); + else + CHK(spt.m_res == Spt::Deadlock); + } + LL2("savepointscanindex " << n << " rows"); + bool dirty = (!spt.m_same && spt.m_lm == NdbOperation::LM_CommittedRead); + if (spt.m_res != Spt::Deadlock) + CHK(set1.verify(par, set2, false, dirty) == 0); + return 0; +} + +typedef int (*SptFun)(Par, Spt); + +static int +savepointtest(Par par, Spt spt, SptFun fun) +{ + Con& con = par.con(); + Par par2 = par; + Con con2; + if (!spt.m_same) { + con2.connect(con); // copy ndb reference + par2.m_con = &con2; + CHK(con2.startTransaction() == 0); + } + par2.m_lockmode = spt.m_lm; + CHK((*fun)(par2, spt) == 0); + if (!spt.m_same) { + con2.closeTransaction(); + } + return 0; +} + +static int +savepointtest(Par par, const char* op) +{ + Con& con = par.con(); + const Tab& tab = par.tab(); + Set& set = par.set(); + LL2("savepointtest op=\"" << op << "\""); + CHK(con.startTransaction() == 0); + const char* p = op; + char c; + while ((c = *p++) != 0) { + uint j; + for (j = 0; j < par.m_rows; j++) { + uint i = thrrow(par, j); + if (c == 'c') { + ExecType et = Commit; + CHK(con.execute(et) == 0); + set.lock(); + set.post(par, et); + set.unlock(); + CHK(con.startTransaction() == 0); + } else { + set.lock(); + set.push(i); + if (c == 'i') { + set.calc(par, i); + CHK(set.insrow(par, i) == 0); + } else if (c == 'u') { + set.copyval(i, tab.m_pkmask); + set.calc(par, i, ~tab.m_pkmask); + CHK(set.updrow(par, i) == 0); + } else if (c == 'd') { + set.copyval(i, tab.m_pkmask); + CHK(set.delrow(par, i) == 0); + } else { + assert(false); + } + set.unlock(); + } + } + } + { + ExecType et = NoCommit; + CHK(con.execute(et) == 0); + set.lock(); + set.post(par, et); + set.unlock(); + } + for (uint k = 0; k < sptcount; k++) { + Spt spt = sptlist[k]; + LL2("spt lm=" << spt.m_lm << " same=" << spt.m_same); + CHK(savepointtest(par, spt, &savepointreadpk) == 0); + CHK(savepointtest(par, spt, &savepointscantable) == 0); + for (uint i = 0; i < tab.m_itabs; i++) { + if (tab.m_itab[i] == 0) + continue; + const ITab& itab = *tab.m_itab[i]; + par.m_itab = &itab; + if (itab.m_type == ITab::OrderedIndex) + CHK(savepointtest(par, spt, &savepointscanindex) == 0); + else + CHK(savepointtest(par, spt, &savepointreadhashindex) == 0); + par.m_itab = 0; + } + } + { + ExecType et = Rollback; + CHK(con.execute(et) == 0); + set.lock(); + set.post(par, et); + set.unlock(); + } + con.closeTransaction(); + return 0; +} + +static int +savepointtest(Par par) +{ + assert(par.m_usedthreads == 1); + const char* oplist[] = { + // each based on previous and "c" not last + "i", + "icu", + "uuuuu", + "d", + "dciuuuuud", + 0 + }; + int i; + for (i = 0; oplist[i] != 0; i++) { + CHK(savepointtest(par, oplist[i]) == 0); + } + return 0; +} + +static int +halloweentest(Par par, const ITab& itab) +{ + LL2("halloweentest " << itab.m_name); + Con& con = par.con(); + const Tab& tab = par.tab(); + Set& set = par.set(); + CHK(con.startTransaction() == 0); + // insert 1 row + uint i = 0; + set.push(i); + set.calc(par, i); + CHK(set.insrow(par, i) == 0); + CHK(con.execute(NoCommit) == 0); + // scan via index until Set m_rows reached + uint scancount = 0; + bool stop = false; + while (!stop) { + par.m_lockmode = // makes no difference + scancount % 2 == 0 ? NdbOperation::LM_CommittedRead : + NdbOperation::LM_Read; + Set set1(tab, set.m_rows); // expected scan result + Set set2(tab, set.m_rows); // actual scan result + BSet bset(tab, itab); + calcscanbounds(par, itab, bset, set, set1); + CHK(con.getNdbIndexScanOperation(itab, tab) == 0); + CHK(con.readIndexTuples(par) == 0); + CHK(bset.setbnd(par) == 0); + set2.getval(par); + CHK(con.executeScan() == 0); + const uint savepoint = i; + LL3("scancount=" << scancount << " savepoint=" << savepoint); + uint n = 0; + while (1) { + int ret; + CHK((ret = con.nextScanResult(true)) == 0 || ret == 1); + if (ret == 1) + break; + uint k = (uint)-1; + CHK(set2.getkey(par, &k) == 0); + CHK(set2.putval(k, false, n) == 0); + LL3("row=" << n << " key=" << k); + CHK(k <= savepoint); + if (++i == set.m_rows) { + stop = true; + break; + } + set.push(i); + set.calc(par, i); + CHK(set.insrow(par, i) == 0); + CHK(con.execute(NoCommit) == 0); + n++; + } + con.closeScan(); + LL3("scanrows=" << n); + if (!stop) { + CHK(set1.verify(par, set2, false) == 0); + } + scancount++; + } + CHK(con.execute(Commit) == 0); + set.post(par, Commit); + assert(set.count() == set.m_rows); + CHK(pkdelete(par) == 0); + return 0; +} + +static int +halloweentest(Par par) +{ + assert(par.m_usedthreads == 1); + const Tab& tab = par.tab(); + for (uint i = 0; i < tab.m_itabs; i++) { + if (tab.m_itab[i] == 0) + continue; + const ITab& itab = *tab.m_itab[i]; + if (itab.m_type == ITab::OrderedIndex) + CHK(halloweentest(par, itab) == 0); + } + return 0; +} + // threads typedef int (*TFunc)(Par par); @@ -4477,22 +4906,22 @@ enum TMode { ST = 1, MT = 2 }; extern "C" { static void* runthread(void* arg); } struct Thr { - enum State { Wait, Start, Stop, Stopped, Exit }; + enum State { Wait, Start, Stop, Exit }; State m_state; Par m_par; - Uint64 m_id; + pthread_t m_id; NdbThread* m_thread; NdbMutex* m_mutex; NdbCondition* m_cond; TFunc m_func; int m_ret; void* m_status; - Thr(Par par, unsigned n); + char m_tmp[20]; // used for debug msg prefix + Thr(Par par, uint n); ~Thr(); int run(); void start(); void stop(); - void stopped(); void exit(); // void lock() { @@ -4513,10 +4942,9 @@ struct Thr { } }; -Thr::Thr(Par par, unsigned n) : +Thr::Thr(Par par, uint n) : m_state(Wait), m_par(par), - m_id(0), m_thread(0), m_mutex(0), m_cond(0), @@ -4533,7 +4961,7 @@ Thr::Thr(Par par, unsigned n) : m_cond = NdbCondition_Create(); assert(m_mutex != 0 && m_cond != 0); // run - const unsigned stacksize = 256 * 1024; + const uint stacksize = 256 * 1024; const NDB_THREAD_PRIO prio = NDB_THREAD_PRIO_LOW; m_thread = NdbThread_Create(runthread, (void**)this, stacksize, name, prio); } @@ -4558,7 +4986,7 @@ static void* runthread(void* arg) { Thr& thr = *(Thr*)arg; - thr.m_id = (Uint64)pthread_self(); + thr.m_id = pthread_self(); if (thr.run() < 0) { LL1("exit on error"); } else { @@ -4589,11 +5017,16 @@ Thr::run() LL4("start"); assert(m_state == Start); m_ret = (*m_func)(m_par); - m_state = Stopped; + m_state = Stop; LL4("stop"); signal(); unlock(); - CHK(m_ret == 0); + if (m_ret == -1) { + if (m_par.m_cont) + LL1("continue running due to -cont"); + else + return -1; + } } con.disconnect(); return 0; @@ -4612,16 +5045,7 @@ void Thr::stop() { lock(); - m_state = Stop; - signal(); - unlock(); -} - -void -Thr::stopped() -{ - lock(); - while (m_state != Stopped) + while (m_state != Stop) wait(); m_state = Wait; unlock(); @@ -4640,27 +5064,44 @@ Thr::exit() static Thr** g_thrlist = 0; -static unsigned -getthrno() +static Thr* +getthr() { if (g_thrlist != 0) { - Uint64 id = (Uint64)pthread_self(); - for (unsigned n = 0; n < g_opt.m_threads; n++) { + pthread_t id = pthread_self(); + for (uint n = 0; n < g_opt.m_threads; n++) { if (g_thrlist[n] != 0) { - const Thr& thr = *g_thrlist[n]; - if (thr.m_id == id) - return thr.m_par.m_no; + Thr& thr = *g_thrlist[n]; + if (pthread_equal(thr.m_id, id)) + return &thr; } } } - return (unsigned)-1; + return 0; +} + +// for debug messages (par.m_no not available) +static const char* +getthrprefix() +{ + Thr* thrp = getthr(); + if (thrp != 0) { + Thr& thr = *thrp; + uint n = thr.m_par.m_no; + uint m = + g_opt.m_threads < 10 ? 1 : + g_opt.m_threads < 100 ? 2 : 3; + sprintf(thr.m_tmp, "[%0*u] ", m, n); + return thr.m_tmp; + } + return ""; } static int -runstep(Par par, const char* fname, TFunc func, unsigned mode) +runstep(Par par, const char* fname, TFunc func, uint mode) { LL2("step: " << fname); - const int threads = (mode & ST ? 1 : par.m_threads); + const int threads = (mode & ST ? 1 : par.m_usedthreads); int n; for (n = 0; n < threads; n++) { LL4("start " << n); @@ -4673,11 +5114,11 @@ runstep(Par par, const char* fname, TFunc func, unsigned mode) thr.m_func = func; thr.start(); } - unsigned errs = 0; + uint errs = 0; for (n = threads - 1; n >= 0; n--) { LL4("stop " << n); Thr& thr = *g_thrlist[n]; - thr.stopped(); + thr.stop(); if (thr.m_ret != 0) errs++; } @@ -4689,7 +5130,7 @@ runstep(Par par, const char* fname, TFunc func, unsigned mode) CHK(runstep(par, #func, func, mode) == 0) #define SUBLOOP(par) \ - "subloop: " << par.m_lno << "/" << par.m_currcase << "/" << \ + "sloop: " << par.m_lno << "/" << par.m_currcase << "/" << \ par.m_tab->m_name << "/" << par.m_slno static int @@ -4698,7 +5139,7 @@ tbuild(Par par) RUNSTEP(par, droptable, ST); RUNSTEP(par, createtable, ST); RUNSTEP(par, invalidatetable, MT); - for (par.m_slno = 0; par.m_slno < par.m_subloop; par.m_slno++) { + for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) { LL1(SUBLOOP(par)); if (par.m_slno % 3 == 0) { RUNSTEP(par, createindex, ST); @@ -4718,7 +5159,7 @@ tbuild(Par par) } RUNSTEP(par, readverifyfull, MT); // leave last one - if (par.m_slno + 1 < par.m_subloop) { + if (par.m_slno + 1 < par.m_sloop) { RUNSTEP(par, pkdelete, MT); RUNSTEP(par, readverifyfull, MT); RUNSTEP(par, dropindex, ST); @@ -4737,7 +5178,7 @@ tindexscan(Par par) RUNSTEP(par, invalidateindex, MT); RUNSTEP(par, pkinsert, MT); RUNSTEP(par, readverifyfull, MT); - for (par.m_slno = 0; par.m_slno < par.m_subloop; par.m_slno++) { + for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) { LL1(SUBLOOP(par)); RUNSTEP(par, readverifyindex, MT); } @@ -4753,7 +5194,7 @@ tpkops(Par par) RUNSTEP(par, invalidatetable, MT); RUNSTEP(par, createindex, ST); RUNSTEP(par, invalidateindex, MT); - for (par.m_slno = 0; par.m_slno < par.m_subloop; par.m_slno++) { + for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) { LL1(SUBLOOP(par)); RUNSTEP(par, pkops, MT); LL2("rows=" << par.set().count()); @@ -4772,7 +5213,7 @@ tpkopsread(Par par) RUNSTEP(par, createindex, ST); RUNSTEP(par, invalidateindex, MT); RUNSTEP(par, readverifyfull, MT); - for (par.m_slno = 0; par.m_slno < par.m_subloop; par.m_slno++) { + for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) { LL1(SUBLOOP(par)); RUNSTEP(par, pkupdatescanread, MT); RUNSTEP(par, readverifyfull, MT); @@ -4792,7 +5233,7 @@ tmixedops(Par par) RUNSTEP(par, createindex, ST); RUNSTEP(par, invalidateindex, MT); RUNSTEP(par, readverifyfull, MT); - for (par.m_slno = 0; par.m_slno < par.m_subloop; par.m_slno++) { + for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) { LL1(SUBLOOP(par)); RUNSTEP(par, mixedoperations, MT); RUNSTEP(par, readverifyfull, MT); @@ -4807,7 +5248,7 @@ tbusybuild(Par par) RUNSTEP(par, createtable, ST); RUNSTEP(par, invalidatetable, MT); RUNSTEP(par, pkinsert, MT); - for (par.m_slno = 0; par.m_slno < par.m_subloop; par.m_slno++) { + for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) { LL1(SUBLOOP(par)); RUNSTEP(par, pkupdateindexbuild, MT); RUNSTEP(par, invalidateindex, MT); @@ -4828,7 +5269,7 @@ trollback(Par par) RUNSTEP(par, createindex, ST); RUNSTEP(par, invalidateindex, MT); RUNSTEP(par, readverifyfull, MT); - for (par.m_slno = 0; par.m_slno < par.m_subloop; par.m_slno++) { + for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) { LL1(SUBLOOP(par)); RUNSTEP(par, mixedoperations, MT); RUNSTEP(par, readverifyfull, MT); @@ -4846,7 +5287,7 @@ tparupdate(Par par) RUNSTEP(par, createindex, ST); RUNSTEP(par, invalidateindex, MT); RUNSTEP(par, readverifyfull, MT); - for (par.m_slno = 0; par.m_slno < par.m_subloop; par.m_slno++) { + for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) { LL1(SUBLOOP(par)); RUNSTEP(par, parallelorderedupdate, MT); RUNSTEP(par, readverifyfull, MT); @@ -4855,13 +5296,44 @@ tparupdate(Par par) } static int +tsavepoint(Par par) +{ + RUNSTEP(par, droptable, ST); + RUNSTEP(par, createtable, ST); + RUNSTEP(par, invalidatetable, MT); + RUNSTEP(par, createindex, ST); + RUNSTEP(par, invalidateindex, MT); + for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) { + LL1(SUBLOOP(par)); + RUNSTEP(par, savepointtest, MT); + RUNSTEP(par, readverifyfull, MT); + } + return 0; +} + +static int +thalloween(Par par) +{ + RUNSTEP(par, droptable, ST); + RUNSTEP(par, createtable, ST); + RUNSTEP(par, invalidatetable, MT); + RUNSTEP(par, createindex, ST); + RUNSTEP(par, invalidateindex, MT); + for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) { + LL1(SUBLOOP(par)); + RUNSTEP(par, halloweentest, MT); + } + return 0; +} + +static int ttimebuild(Par par) { Tmr t1; RUNSTEP(par, droptable, ST); RUNSTEP(par, createtable, ST); RUNSTEP(par, invalidatetable, MT); - for (par.m_slno = 0; par.m_slno < par.m_subloop; par.m_slno++) { + for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) { LL1(SUBLOOP(par)); RUNSTEP(par, pkinsert, MT); t1.on(); @@ -4881,7 +5353,7 @@ ttimemaint(Par par) RUNSTEP(par, droptable, ST); RUNSTEP(par, createtable, ST); RUNSTEP(par, invalidatetable, MT); - for (par.m_slno = 0; par.m_slno < par.m_subloop; par.m_slno++) { + for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) { LL1(SUBLOOP(par)); RUNSTEP(par, pkinsert, MT); t1.on(); @@ -4911,7 +5383,7 @@ ttimescan(Par par) RUNSTEP(par, droptable, ST); RUNSTEP(par, createtable, ST); RUNSTEP(par, invalidatetable, MT); - for (par.m_slno = 0; par.m_slno < par.m_subloop; par.m_slno++) { + for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) { LL1(SUBLOOP(par)); RUNSTEP(par, pkinsert, MT); RUNSTEP(par, createindex, ST); @@ -4938,7 +5410,7 @@ ttimepkread(Par par) RUNSTEP(par, droptable, ST); RUNSTEP(par, createtable, ST); RUNSTEP(par, invalidatetable, MT); - for (par.m_slno = 0; par.m_slno < par.m_subloop; par.m_slno++) { + for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) { LL1(SUBLOOP(par)); RUNSTEP(par, pkinsert, MT); RUNSTEP(par, createindex, ST); @@ -4981,7 +5453,9 @@ tcaselist[] = { TCase("e", tmixedops, "pk operations and scan operations"), TCase("f", tbusybuild, "pk operations and index build"), TCase("g", trollback, "operations with random rollbacks"), - TCase("h", tparupdate, "parallel ordered update (bug20446)"), + TCase("h", tparupdate, "parallel ordered update bug#20446"), + TCase("i", tsavepoint, "savepoint test locking bug#31477"), + TCase("j", thalloween, "savepoint test halloween problem"), TCase("t", ttimebuild, "time index build"), TCase("u", ttimemaint, "time index maintenance"), TCase("v", ttimescan, "time full scan table vs index on pk"), @@ -4989,14 +5463,14 @@ tcaselist[] = { TCase("z", tdrop, "drop test tables") }; -static const unsigned +static const uint tcasecount = sizeof(tcaselist) / sizeof(tcaselist[0]); static void printcases() { ndbout << "test cases:" << endl; - for (unsigned i = 0; i < tcasecount; i++) { + for (uint i = 0; i < tcasecount; i++) { const TCase& tcase = tcaselist[i]; ndbout << " " << tcase.m_name << " - " << tcase.m_desc << endl; } @@ -5008,13 +5482,13 @@ printtables() Par par(g_opt); makebuiltintables(par); ndbout << "tables and indexes (x=ordered z=hash x0=on pk):" << endl; - for (unsigned j = 0; j < tabcount; j++) { + for (uint j = 0; j < tabcount; j++) { if (tablist[j] == 0) continue; const Tab& tab = *tablist[j]; const char* tname = tab.m_name; ndbout << " " << tname; - for (unsigned i = 0; i < tab.m_itabs; i++) { + for (uint i = 0; i < tab.m_itabs; i++) { if (tab.m_itab[i] == 0) continue; const ITab& itab = *tab.m_itab[i]; @@ -5023,7 +5497,7 @@ printtables() iname += strlen(tname); ndbout << " " << iname; ndbout << "("; - for (unsigned k = 0; k < itab.m_icols; k++) { + for (uint k = 0; k < itab.m_icols; k++) { if (k != 0) ndbout << ","; const ICol& icol = *itab.m_icol[k]; @@ -5036,14 +5510,48 @@ printtables() } } +static bool +setcasepar(Par& par) +{ + Opt d; + const char* c = par.m_currcase; + switch (c[0]) { + case 'i': + { + if (par.m_usedthreads > 1) { + par.m_usedthreads = 1; + LL1("case " << c << " reduce threads to " << par.m_usedthreads); + } + const uint rows = 100; + if (par.m_rows > rows) { + par.m_rows = rows; + LL1("case " << c << " reduce rows to " << rows); + } + } + break; + case 'j': + { + if (par.m_usedthreads > 1) { + par.m_usedthreads = 1; + LL1("case " << c << " reduce threads to " << par.m_usedthreads); + } + } + break; + default: + break; + } + return true; +} + static int runtest(Par par) { + int totret = 0; if (par.m_seed == -1) { // good enough for daily run - unsigned short seed = (unsigned short)getpid(); + ushort seed = (ushort)getpid(); LL0("random seed: " << seed); - srandom((unsigned)seed); + srandom((uint)seed); } else if (par.m_seed != 0) { LL0("random seed: " << par.m_seed); srandom(par.m_seed); @@ -5061,9 +5569,10 @@ runtest(Par par) Con con; CHK(con.connect() == 0); par.m_con = &con; + par.m_catcherr |= Con::ErrNospace; // threads g_thrlist = new Thr* [par.m_threads]; - unsigned n; + uint n; for (n = 0; n < par.m_threads; n++) { g_thrlist[n] = 0; } @@ -5078,23 +5587,38 @@ runtest(Par par) LL1("random seed: " << par.m_lno); srandom(par.m_lno); } - for (unsigned i = 0; i < tcasecount; i++) { + for (uint i = 0; i < tcasecount; i++) { const TCase& tcase = tcaselist[i]; - if (par.m_case != 0 && strchr(par.m_case, tcase.m_name[0]) == 0) + if (par.m_case != 0 && strchr(par.m_case, tcase.m_name[0]) == 0 || + par.m_skip != 0 && strchr(par.m_skip, tcase.m_name[0]) != 0) { continue; + } sprintf(par.m_currcase, "%c", tcase.m_name[0]); + par.m_usedthreads = par.m_threads; + if (!setcasepar(par)) { + LL1("case " << tcase.m_name << " cannot run with given options"); + continue; + } + par.m_totrows = par.m_usedthreads * par.m_rows; makebuiltintables(par); LL1("case: " << par.m_lno << "/" << tcase.m_name << " - " << tcase.m_desc); - for (unsigned j = 0; j < tabcount; j++) { + for (uint j = 0; j < tabcount; j++) { if (tablist[j] == 0) continue; const Tab& tab = *tablist[j]; par.m_tab = &tab; par.m_set = new Set(tab, par.m_totrows); LL1("table: " << par.m_lno << "/" << tcase.m_name << "/" << tab.m_name); - CHK(tcase.m_func(par) == 0); + int ret = tcase.m_func(par); delete par.m_set; par.m_set = 0; + if (ret == -1) { + if (!par.m_cont) + return -1; + totret = -1; + LL1("continue to next case due to -cont"); + break; + } } } } @@ -5110,7 +5634,7 @@ runtest(Par par) delete [] g_thrlist; g_thrlist = 0; con.disconnect(); - return 0; + return totret; } static const char* g_progname = "testOIBasic"; @@ -5119,7 +5643,7 @@ int main(int argc, char** argv) { ndb_init(); - unsigned i; + uint i; ndbout << g_progname; for (i = 1; i < argc; i++) ndbout << " " << argv[i]; @@ -5156,6 +5680,10 @@ main(int argc, char** argv) g_opt.m_collsp = true; continue; } + if (strcmp(arg, "-cont") == 0) { + g_opt.m_cont = true; + continue; + } if (strcmp(arg, "-core") == 0) { g_opt.m_core = true; continue; @@ -5252,9 +5780,21 @@ main(int argc, char** argv) continue; } } - if (strcmp(arg, "-subloop") == 0) { + if (strcmp(arg, "-skip") == 0) { + if (++argv, --argc > 0) { + g_opt.m_skip = strdup(argv[0]); + continue; + } + } + if (strcmp(arg, "-sloop") == 0) { + if (++argv, --argc > 0) { + g_opt.m_sloop = atoi(argv[0]); + continue; + } + } + if (strcmp(arg, "-ssloop") == 0) { if (++argv, --argc > 0) { - g_opt.m_subloop = atoi(argv[0]); + g_opt.m_ssloop = atoi(argv[0]); continue; } } diff --git a/ndb/test/run-test/daily-basic-tests.txt b/ndb/test/run-test/daily-basic-tests.txt index 7b4a4ca0e2d..a27b94193e5 100644 --- a/ndb/test/run-test/daily-basic-tests.txt +++ b/ndb/test/run-test/daily-basic-tests.txt @@ -649,10 +649,10 @@ max-time: 1000 cmd: testNdbApi args: -n Bug28443 -#max-time: 500 -#cmd: testInterpreter -#args: T1 -# +max-time: 500 +cmd: testInterpreter +args: T1 + max-time: 150000 cmd: testOperations args: diff --git a/ndb/tools/waiter.cpp b/ndb/tools/waiter.cpp index e221a26182e..8226de87b49 100644 --- a/ndb/tools/waiter.cpp +++ b/ndb/tools/waiter.cpp @@ -21,13 +21,11 @@ #include <NdbMain.h> #include <NdbOut.hpp> #include <NdbSleep.h> -#include <kernel/ndb_limits.h> #include <NDBT.hpp> -int -waitClusterStatus(const char* _addr, ndb_mgm_node_status _status, - unsigned int _timeout); +static int +waitClusterStatus(const char* _addr, ndb_mgm_node_status _status); enum ndb_waiter_options { OPT_WAIT_STATUS_NOT_STARTED = NDB_STD_OPTIONS_LAST, @@ -55,12 +53,13 @@ static struct my_option my_long_options[] = "Wait for cluster to enter single user mode", (gptr*) &_single_user, (gptr*) &_single_user, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, - { "timeout", 't', "Timeout to wait", + { "timeout", 't', "Timeout to wait in seconds", (gptr*) &_timeout, (gptr*) &_timeout, 0, GET_INT, REQUIRED_ARG, 120, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; + static void usage() { ndb_std_print_version(); @@ -70,16 +69,18 @@ static void usage() my_print_variables(my_long_options); } + int main(int argc, char** argv){ NDB_INIT(argv[0]); load_defaults("my",load_default_groups,&argc,&argv); const char* _hostName = NULL; - int ho_error; + #ifndef DBUG_OFF opt_debug= "d:t:O,/tmp/ndb_waiter.trace"; #endif - if ((ho_error=handle_options(&argc, &argv, my_long_options, - ndb_std_get_one_option))) + + if (handle_options(&argc, &argv, my_long_options, + ndb_std_get_one_option)) return NDBT_ProgramExit(NDBT_WRONGARGS); _hostName = argv[0]; @@ -105,7 +106,7 @@ int main(int argc, char** argv){ wait_status= NDB_MGM_NODE_STATUS_STARTED; } - if (waitClusterStatus(_hostName, wait_status, _timeout) != 0) + if (waitClusterStatus(_hostName, wait_status) != 0) return NDBT_ProgramExit(NDBT_FAILED); return NDBT_ProgramExit(NDBT_OK); } @@ -118,8 +119,6 @@ int main(int argc, char** argv){ NdbMgmHandle handle= NULL; Vector<ndb_mgm_node_state> ndbNodes; -Vector<ndb_mgm_node_state> mgmNodes; -Vector<ndb_mgm_node_state> apiNodes; int getStatus(){ @@ -128,8 +127,6 @@ getStatus(){ struct ndb_mgm_node_state * node; ndbNodes.clear(); - mgmNodes.clear(); - apiNodes.clear(); while(retries < 10){ status = ndb_mgm_get_status(handle); @@ -153,18 +150,16 @@ getStatus(){ ndbNodes.push_back(*node); break; case NDB_MGM_NODE_TYPE_MGM: - mgmNodes.push_back(*node); + /* Don't care about MGM nodes */ break; case NDB_MGM_NODE_TYPE_API: - apiNodes.push_back(*node); + /* Don't care about API nodes */ break; default: if(node->node_status == NDB_MGM_NODE_STATUS_UNKNOWN || node->node_status == NDB_MGM_NODE_STATUS_NO_CONTACT){ retries++; ndbNodes.clear(); - mgmNodes.clear(); - apiNodes.clear(); free(status); status = NULL; count = 0; @@ -183,24 +178,22 @@ getStatus(){ free(status); return 0; } - - g_err << "getStatus failed" << endl; + return -1; } -int +static int waitClusterStatus(const char* _addr, - ndb_mgm_node_status _status, - unsigned int _timeout) + ndb_mgm_node_status _status) { int _startphase = -1; - int _nodes[MAX_NDB_NODES]; - int _num_nodes = 0; + /* Ignore SIGPIPE */ + signal(SIGPIPE, SIG_IGN); handle = ndb_mgm_create_handle(); if (handle == NULL){ - g_err << "handle == NULL" << endl; + g_err << "Could not create ndb_mgm handle" << endl; return -1; } g_info << "Connecting to mgmsrv at " << _addr << endl; @@ -216,19 +209,11 @@ waitClusterStatus(const char* _addr, return -1; } - if (getStatus() != 0) - return -1; - - // Collect all nodes into nodes - for (size_t i = 0; i < ndbNodes.size(); i++){ - _nodes[i] = ndbNodes[i].node_id; - _num_nodes++; - } - - unsigned int attempts = 0; - unsigned int resetAttempts = 0; - const unsigned int MAX_RESET_ATTEMPTS = 10; - bool allInState = false; + int attempts = 0; + int resetAttempts = 0; + const int MAX_RESET_ATTEMPTS = 10; + bool allInState = false; + int timeout_ms= _timeout * 10; /* In number of 100 milliseconds */ while (allInState == false){ if (_timeout > 0 && attempts > _timeout){ /** @@ -236,8 +221,8 @@ waitClusterStatus(const char* _addr, * the state we want */ bool waitMore = false; - /** - * Make special check if we are waiting for + /** + * Make special check if we are waiting for * cluster to become started */ if(_status == NDB_MGM_NODE_STATUS_STARTED){ @@ -252,7 +237,7 @@ waitClusterStatus(const char* _addr, waitMore = false; } - } + } if (!waitMore || resetAttempts > MAX_RESET_ATTEMPTS){ g_err << "waitNodeState(" @@ -260,7 +245,7 @@ waitClusterStatus(const char* _addr, <<", "<<_startphase<<")" << " timeout after " << attempts <<" attemps" << endl; return -1; - } + } g_err << "waitNodeState(" << ndb_mgm_get_node_status_string(_status) @@ -269,62 +254,34 @@ waitClusterStatus(const char* _addr, << resetAttempts << endl; attempts = 0; resetAttempts++; - } - allInState = true; if (getStatus() != 0){ - g_err << "getStatus != 0" << endl; return -1; } - // ndbout << "waitNodeState; _num_nodes = " << _num_nodes << endl; - // for (int i = 0; i < _num_nodes; i++) - // ndbout << " node["<<i<<"] =" <<_nodes[i] << endl; + /* Assume all nodes are in state(if there is any) */ + allInState = (ndbNodes.size() > 0); - for (int i = 0; i < _num_nodes; i++){ - ndb_mgm_node_state* ndbNode = NULL; - for (size_t n = 0; n < ndbNodes.size(); n++){ - if (ndbNodes[n].node_id == _nodes[i]) - ndbNode = &ndbNodes[n]; - } + /* Loop through all nodes and check their state */ + for (size_t n = 0; n < ndbNodes.size(); n++) { + ndb_mgm_node_state* ndbNode = &ndbNodes[n]; - if(ndbNode == NULL){ - allInState = false; - continue; - } + assert(ndbNode != NULL); - g_info << "State node " << ndbNode->node_id << " " + g_info << "Node " << ndbNode->node_id << ": " << ndb_mgm_get_node_status_string(ndbNode->node_status)<< endl; - assert(ndbNode != NULL); - - if(_status == NDB_MGM_NODE_STATUS_STARTING && - ((ndbNode->node_status == NDB_MGM_NODE_STATUS_STARTING && - ndbNode->start_phase >= _startphase) || - (ndbNode->node_status == NDB_MGM_NODE_STATUS_STARTED))) - continue; - - if (_status == NDB_MGM_NODE_STATUS_STARTING){ - g_info << "status = " - << ndb_mgm_get_node_status_string(ndbNode->node_status) - <<", start_phase="<<ndbNode->start_phase<<endl; - if (ndbNode->node_status != _status) { - if (ndbNode->node_status < _status) - allInState = false; - else - g_info << "node_status(" << (unsigned)ndbNode->node_status - << ") != _status("<< (unsigned)_status << ")" <<endl; - } else if (ndbNode->start_phase < _startphase) - allInState = false; - } else { - if (ndbNode->node_status != _status) + if (ndbNode->node_status != _status) allInState = false; - } } - g_info << "Waiting for cluster enter state " - << ndb_mgm_get_node_status_string(_status)<< endl; - NdbSleep_SecSleep(1); + + if (!allInState) { + g_info << "Waiting for cluster enter state " + << ndb_mgm_get_node_status_string(_status)<< endl; + NdbSleep_MilliSleep(100); + } + attempts++; } return 0; diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt index 6fbfcab72d4..d7bcb8fd4e7 100755 --- a/scripts/CMakeLists.txt +++ b/scripts/CMakeLists.txt @@ -40,3 +40,44 @@ ADD_CUSTOM_COMMAND(OUTPUT ${PROJECT_SOURCE_DIR}/scripts/mysql_fix_privilege_tabl ADD_CUSTOM_TARGET(GenFixPrivs ALL DEPENDS ${PROJECT_SOURCE_DIR}/scripts/mysql_fix_privilege_tables_sql.c) + +# ---------------------------------------------------------------------- +# Replace some variables @foo@ in the .in/.sh file, and write the new script +# ---------------------------------------------------------------------- + +SET(CFLAGS "-D_WINDOWS ${CMAKE_C_FLAGS_RELWITHDEBINFO}") +SET(prefix "${CMAKE_INSTALL_PREFIX}/MySQL Server ${MYSQL_BASE_VERSION}") +SET(sysconfdir ${prefix}) +SET(bindir ${prefix}/bin) +SET(libexecdir ${prefix}/bin) +SET(scriptdir ${prefix}/bin) +SET(datadir ${prefix}/share) +SET(pkgdatadir ${prefix}/share) +SET(localstatedir ${prefix}/data) + +CONFIGURE_FILE(mysql_config.pl.in + scripts/mysql_config.pl ESCAPE_QUOTES @ONLY) + +CONFIGURE_FILE(mysql_convert_table_format.sh + scripts/mysql_convert_table_format.pl ESCAPE_QUOTES @ONLY) + +CONFIGURE_FILE(mysql_explain_log.sh + scripts/mysql_explain_log.pl ESCAPE_QUOTES @ONLY) + +CONFIGURE_FILE(mysql_install_db.pl.in + scripts/mysql_install_db.pl ESCAPE_QUOTES @ONLY) + +CONFIGURE_FILE(mysql_secure_installation.pl.in + scripts/mysql_secure_installation.pl ESCAPE_QUOTES @ONLY) + +CONFIGURE_FILE(mysql_tableinfo.sh + scripts/mysql_tableinfo.pl ESCAPE_QUOTES @ONLY) + +CONFIGURE_FILE(mysqld_multi.sh + scripts/mysqld_multi.pl ESCAPE_QUOTES @ONLY) + +CONFIGURE_FILE(mysqldumpslow.sh + scripts/mysqldumpslow.pl ESCAPE_QUOTES @ONLY) + +CONFIGURE_FILE(mysqlhotcopy.sh + scripts/mysqlhotcopy.pl ESCAPE_QUOTES @ONLY) diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 5db5fdd550f..87170b46675 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -48,11 +48,14 @@ EXTRA_SCRIPTS = make_binary_distribution.sh \ make_win_src_distribution_old.sh \ msql2mysql.sh \ mysql_config.sh \ + mysql_config.pl.in \ mysql_fix_privilege_tables.sh \ mysql_fix_extensions.sh \ mysql_install_db.sh \ + mysql_install_db.pl.in \ mysql_setpermission.sh \ mysql_secure_installation.sh \ + mysql_secure_installation.pl.in \ mysql_zap.sh \ mysqlaccess.sh \ mysqlbug.sh \ diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh index a87bb03526d..8598a022669 100644 --- a/scripts/make_binary_distribution.sh +++ b/scripts/make_binary_distribution.sh @@ -400,11 +400,13 @@ BASE=$BASE2 # if [ x"@GXX@" = x"yes" ] ; then - gcclib=`@CC@ @CFLAGS@ --print-libgcc-file` - if [ $? -ne 0 ] ; then - echo "Warning: Couldn't find libgcc.a!" - else + gcclib=`@CC@ @CFLAGS@ --print-libgcc-file 2>/dev/null` || true + if [ -z "$gcclib" ] ; then + echo "Warning: Compiler doesn't tell libgcc.a!" + elif [ -f "$gcclib" ] ; then $CP $gcclib $BASE/lib/libmygcc.a + else + echo "Warning: Compiler result '$gcclib' not found / no file!" fi fi diff --git a/scripts/make_win_bin_dist b/scripts/make_win_bin_dist index d065e171bb0..56510dc857b 100755 --- a/scripts/make_win_bin_dist +++ b/scripts/make_win_bin_dist @@ -327,35 +327,34 @@ if [ -d mysql-test/extra ] ; then fi # ---------------------------------------------------------------------- -# Copy what could be usable in the "scripts" directory. Currently -# only SQL files, others are Bourne shell scripts or Perl scripts -# not really usable on Windows. -# -# But to be nice to the few Cygwin users we might have in 5.0 we -# continue to copy the stuff, but don't include it in the WiX install. +# Copy what could be usable in the "scripts" directory # ---------------------------------------------------------------------- +mysql_scripts="\ +mysql_config.pl \ +mysql_convert_table_format.pl \ +mysql_explain_log.pl \ +mysql_install_db.pl \ +mysql_secure_installation.pl \ +mysql_tableinfo.pl \ +mysqld_multi.pl \ +mysqldumpslow.pl \ +mysqlhotcopy.pl \ +" + mkdir -p $DESTDIR/scripts -# Uncomment and remove the for loop in 5.1 -#cp scripts/*.sql $DESTDIR/scripts/ - -for i in `cd scripts && ls`; do \ - if echo $i | grep -q '\.sh'; then \ - cp scripts/$i $DESTDIR/scripts/`echo $i | sed -e 's/\.sh$//'`; \ - elif [ -d scripts/$i -o $i = Makefile.am -o $i = Makefile.in -o -e scripts/$i.sh ] ; then \ - : ; \ - else \ - cp scripts/$i $DESTDIR/scripts/$i; \ - fi; \ +for i in $mysql_scripts +do + cp scripts/$i $DESTDIR/scripts/$i done cp -pR sql/share $DESTDIR/ cp -pR sql-bench $DESTDIR/ rm -f $DESTDIR/sql-bench/*.sh $DESTDIR/sql-bench/Makefile* -# The SQL initialisation code is really expected to be in "share" -mv $DESTDIR/scripts/*.sql $DESTDIR/share/ || true +# The SQL initialisation code is to be in "share" +cp scripts/*.sql $DESTDIR/share/ # ---------------------------------------------------------------------- # Clean up from possibly copied SCCS directories diff --git a/scripts/mysql_config.pl.in b/scripts/mysql_config.pl.in new file mode 100644 index 00000000000..3ae8baf7db0 --- /dev/null +++ b/scripts/mysql_config.pl.in @@ -0,0 +1,285 @@ +#!/usr/bin/perl +# -*- cperl -*- +# +# Copyright (C) 2007 MySQL AB +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +############################################################################## +# +# This script reports various configuration settings that may be needed +# when using the MySQL client library. +# +# This script try to match the shell script version as close as possible, +# but in addition being compatible with ActiveState Perl on Windows. +# +# All unrecognized arguments to this script are passed to mysqld. +# +# NOTE: This script will only be used on Windows until solved how to +# handle @LIBS@ and other strings inserted that might contain +# several arguments, possibly with spaces in them. +# +# NOTE: This script was deliberately written to be as close to the shell +# script as possible, to make the maintenance of both in parallel +# easier. +# +############################################################################## + +use File::Basename; +use Getopt::Long; +use Cwd; +use strict; + +my @exclude_cflags = + qw/DDBUG_OFF DSAFEMALLOC USAFEMALLOC DSAFE_MUTEX + DPEDANTIC_SAFEMALLOC DUNIV_MUST_NOT_INLINE DFORCE_INIT_OF_VARS + DEXTRA_DEBUG DHAVE_purify O O[0-9] xO[0-9] W[-A-Za-z]* + Xa xstrconst xc99=none + unroll2 ip mp restrict/; + +my @exclude_libs = qw/lmtmalloc static-libcxa i-static static-intel/; + +my $cwd = cwd(); +my $basedir; + +my $socket = '@MYSQL_UNIX_ADDR@'; +my $version = '@VERSION@'; + +sub which +{ + my $file = shift; + + my $IFS = $^O eq "MSWin32" ? ";" : ":"; + + foreach my $dir ( split($IFS, $ENV{PATH}) ) + { + if ( -f "$dir/$file" or -f "$dir/$file.exe" ) + { + return "$dir/$file"; + } + } + print STDERR "which: no $file in ($ENV{PATH})\n"; + exit 1; +} + +# ---------------------------------------------------------------------- +# If we can find the given directory relatively to where mysql_config is +# we should use this instead of the incompiled one. +# This is to ensure that this script also works with the binary MySQL +# version +# ---------------------------------------------------------------------- + +sub fix_path +{ + my $default = shift; + my @dirs = @_; + + foreach my $dirname ( @dirs ) + { + my $path = "$basedir/$dirname"; + if ( -d $path ) + { + return $path; + } + } + return $default; +} + +sub get_full_path +{ + my $file = shift; + + # if the file is a symlink, try to resolve it + if ( $^O ne "MSWin32" and -l $file ) + { + $file = readlink($file); + } + + if ( $file =~ m,^/, ) + { + # Do nothing, absolute path + } + elsif ( $file =~ m,/, ) + { + # Make absolute, and remove "/./" in path + $file = "$cwd/$file"; + $file =~ s,/\./,/,g; + } + else + { + # Find in PATH + $file = which($file); + } + + return $file; +} + +############################################################################## +# +# Form a command line that can handle spaces in paths and arguments +# +############################################################################## + +sub quote_options { + my @cmd; + foreach my $opt ( @_ ) + { + next unless $opt; # If undefined or empty, just skip + push(@cmd, "\"$opt\""); # Quote argument + } + return join(" ", @cmd); +} + +############################################################################## +# +# Main program +# +############################################################################## + +my $me = get_full_path($0); +$basedir = dirname(dirname($me)); # Remove "/bin/mysql_config" part + +my $ldata = '@localstatedir@'; +my $execdir = '@libexecdir@'; +my $bindir = '@bindir@'; + +# ---------------------------------------------------------------------- +# If installed, search for the compiled in directory first (might be "lib64") +# ---------------------------------------------------------------------- + +my $pkglibdir = fix_path('@pkglibdir@',"libmysql/relwithdebinfo", + "libmysql/release","libmysql/debug","lib/mysql","lib"); + +my $pkgincludedir = fix_path('@pkgincludedir@', "include/mysql", "include"); + +# Assume no argument with space in it +my @ldflags = split(" ",'@LDFLAGS@'); + +my $port; +if ( '@MYSQL_TCP_PORT_DEFAULT@' == 0 ) { + $port = 0; +} else { + $port = '@MYSQL_TCP_PORT@'; +} + +# ---------------------------------------------------------------------- +# Create options +# We intentionally add a space to the beginning and end of lib strings, simplifies replace later +# ---------------------------------------------------------------------- + +my (@lib_opts,@lib_r_opts,@lib_e_opts); +if ( $^O eq "MSWin32" ) +{ + my $linkpath = "$pkglibdir"; + # user32 is only needed for debug or embedded + my @winlibs = ("wsock32.lib","advapi32.lib","user32.lib"); + @lib_opts = ("$linkpath/mysqlclient.lib",@winlibs); + @lib_r_opts = @lib_opts; + @lib_e_opts = ("$linkpath/mysqlserver.lib",@winlibs); +} +else +{ + my $linkpath = "-L$pkglibdir"; + @lib_opts = ($linkpath,"-lmysqlclient"); + @lib_r_opts = ($linkpath,"-lmysqlclient_r"); + @lib_e_opts = ($linkpath,"-lmysqld"); +} + +my $flags; +$flags->{libs} = + [@ldflags,@lib_opts,'@ZLIB_DEPS@','@NON_THREADED_LIBS@','@openssl_libs@','@STATIC_NSS_FLAGS@']; +$flags->{libs_r} = + [@ldflags,@lib_r_opts,'@ZLIB_DEPS@','@LIBS@','@openssl_libs@']; +$flags->{embedded_libs} = + [@ldflags,@lib_e_opts,'@ZLIB_DEPS@','@LIBS@','@WRAPLIBS@','@innodb_system_libs@','@openssl_libs@']; + +$flags->{include} = ["-I$pkgincludedir"]; +$flags->{cflags} = [@{$flags->{include}},split(" ",'@CFLAGS@')]; + +# ---------------------------------------------------------------------- +# Remove some options that a client doesn't have to care about +# FIXME until we have a --cxxflags, we need to remove -Xa +# and -xstrconst to make --cflags usable for Sun Forte C++ +# ---------------------------------------------------------------------- + +my $filter = join("|", @exclude_cflags); +my @tmp = @{$flags->{cflags}}; # Copy the flag list +$flags->{cflags} = []; # Clear it +foreach my $cflag ( @tmp ) +{ + push(@{$flags->{cflags}}, $cflag) unless $cflag =~ m/^($filter)$/o; +} + +# Same for --libs(_r) +$filter = join("|", @exclude_libs); +foreach my $lib_type ( "libs","libs_r","embedded_libs" ) +{ + my @tmp = @{$flags->{$lib_type}}; # Copy the flag list + $flags->{$lib_type} = []; # Clear it + foreach my $lib ( @tmp ) + { + push(@{$flags->{$lib_type}}, $lib) unless $lib =~ m/^($filter)$/o; + } +} + +my $include = quote_options(@{$flags->{include}}); +my $cflags = quote_options(@{$flags->{cflags}}); +my $libs = quote_options(@{$flags->{libs}}); +my $libs_r = quote_options(@{$flags->{libs_r}}); +my $embedded_libs = quote_options(@{$flags->{embedded_libs}}); + +############################################################################## +# +# Usage information, output if no option is given +# +############################################################################## + +sub usage +{ + print <<EOF; +Usage: $0 [OPTIONS] +Options: + --cflags [$cflags] + --include [$include] + --libs [$libs] + --libs_r [$libs_r] + --socket [$socket] + --port [$port] + --version [$version] + --libmysqld-libs [$embedded_libs] +EOF + exit 1; +} + +@ARGV or usage(); + +############################################################################## +# +# Get options and output the values +# +############################################################################## + +GetOptions( + "cflags" => sub { print "$cflags\n" }, + "include" => sub { print "$include\n" }, + "libs" => sub { print "$libs\n" }, + "libs_r" => sub { print "$libs_r\n" }, + "socket" => sub { print "$socket\n" }, + "port" => sub { print "$port\n" }, + "version" => sub { print "$version\n" }, + "embedded-libs|embedded|libmysqld-libs" => + sub { print "$embedded_libs\n" }, + ) or usage(); + +exit 0 diff --git a/scripts/mysql_config.sh b/scripts/mysql_config.sh index ae58655ed0f..915f623578d 100644 --- a/scripts/mysql_config.sh +++ b/scripts/mysql_config.sh @@ -107,16 +107,29 @@ libs="$libs @openssl_libs@ @STATIC_NSS_FLAGS@ " libs_r=" $ldflags -L$pkglibdir -lmysqlclient_r @ZLIB_DEPS@ @LIBS@ @openssl_libs@ " embedded_libs=" $ldflags -L$pkglibdir -lmysqld @ZLIB_DEPS@ @LIBS@ @WRAPLIBS@ @innodb_system_libs@ @openssl_libs@ " +if [ -r "$pkglibdir/libmygcc.a" ]; then + # When linking against the static library with a different version of GCC + # from what was used to compile the library, some symbols may not be defined + # automatically. We package the libmygcc.a from the build host, to provide + # definitions for those. Bugs 4921, 19561, 19817, 21158, etc. + libs="$libs -lmygcc " + libs_r="$libs_r -lmygcc " + embedded_libs="$embedded_libs -lmygcc " +fi + cflags="-I$pkgincludedir @CFLAGS@ " #note: end space! include="-I$pkgincludedir" # Remove some options that a client doesn't have to care about # FIXME until we have a --cxxflags, we need to remove -Xa # and -xstrconst to make --cflags usable for Sun Forte C++ +# FIXME until we have a --cxxflags, we need to remove -AC99 +# to make --cflags usable for HP C++ (aCC) for remove in DDBUG_OFF DSAFEMALLOC USAFEMALLOC DSAFE_MUTEX \ DPEDANTIC_SAFEMALLOC DUNIV_MUST_NOT_INLINE DFORCE_INIT_OF_VARS \ DEXTRA_DEBUG DHAVE_purify O 'O[0-9]' 'xO[0-9]' 'W[-A-Za-z]*' \ - Xa xstrconst "xc99=none" \ + 'mtune=[-A-Za-z0-9]*' 'mcpu=[-A-Za-z0-9]*' 'march=[-A-Za-z0-9]*' \ + Xa xstrconst "xc99=none" AC99 \ unroll2 ip mp restrict do # The first option we might strip will always have a space before it because diff --git a/scripts/mysql_convert_table_format.sh b/scripts/mysql_convert_table_format.sh index 0c9ce3a67e0..833b5bf5f11 100644 --- a/scripts/mysql_convert_table_format.sh +++ b/scripts/mysql_convert_table_format.sh @@ -1,4 +1,4 @@ -#!@PERL@ +#!/usr/bin/perl # Copyright (C) 2000-2002 MySQL AB # # This program is free software; you can redistribute it and/or modify diff --git a/scripts/mysql_explain_log.sh b/scripts/mysql_explain_log.sh index a549817db5a..30bee722873 100644 --- a/scripts/mysql_explain_log.sh +++ b/scripts/mysql_explain_log.sh @@ -1,4 +1,4 @@ -#!@PERL@ +#!/usr/bin/perl # Copyright (C) 2001-2003, 2006 MySQL AB # # This program is free software; you can redistribute it and/or modify @@ -196,9 +196,10 @@ if (defined ($help)) { elsif (m/^\s+(.+)$/ ) { # command could be some lines ... #print "multi-lined ($1)\n"; my ($A)=$1; - chomp $A; - $Param->{Query} .= " $1"; - #print "multi-lined ($1)<<$Param->{Query}>>\n"; + $A =~ s/\-\-.*//; + + $Param->{Query} .= " $A"; + #print "multi-lined ($A)<<$Param->{Query}>>\n"; } diff --git a/scripts/mysql_install_db.pl.in b/scripts/mysql_install_db.pl.in new file mode 100644 index 00000000000..18bd713c041 --- /dev/null +++ b/scripts/mysql_install_db.pl.in @@ -0,0 +1,612 @@ +#!/usr/bin/perl +# -*- cperl -*- +# +# Copyright (C) 2007 MySQL AB +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +############################################################################## +# +# This scripts creates the MySQL Server system tables. +# +# This script try to match the shell script version as close as possible, +# but in addition being compatible with ActiveState Perl on Windows. +# +# All unrecognized arguments to this script are passed to mysqld. +# +# NOTE: This script in 5.0 doesn't really match the shell script +# version 100%, it is more close to the 5.1 version. +# +# NOTE: This script was deliberately written to be as close to the shell +# script as possible, to make the maintenance of both in parallel +# easier. +# +############################################################################## + +use File::Basename; +use Getopt::Long; +use Sys::Hostname; +use Data::Dumper; +use strict; + +Getopt::Long::Configure("pass_through"); + +my @args; # Argument list filled in + +############################################################################## +# +# Usage information +# +############################################################################## + +sub usage +{ + print <<EOF; +Usage: $0 [OPTIONS] + --basedir=path The path to the MySQL installation directory. + --builddir=path If using --srcdir with out-of-directory builds, you + will need to set this to the location of the build + directory where built files reside. + --cross-bootstrap For internal use. Used when building the MySQL system + tables on a different host than the target. + --datadir=path The path to the MySQL data directory. + --force Causes mysql_install_db to run even if DNS does not + work. In that case, grant table entries that normally + use hostnames will use IP addresses. + --ldata=path The path to the MySQL data directory. Same as --datadir. + --rpm For internal use. This option is used by RPM files + during the MySQL installation process. + --skip-name-resolve Use IP addresses rather than hostnames when creating + grant table entries. This option can be useful if + your DNS does not work. + --srcdir=path The path to the MySQL source directory. This option + uses the compiled binaries and support files within the + source tree, useful for if you don't want to install + MySQL yet and just want to create the system tables. + --user=user_name The login username to use for running mysqld. Files + and directories created by mysqld will be owned by this + user. You must be root to use this option. By default + mysqld runs using your current login name and files and + directories that it creates will be owned by you. + +All other options are passed to the mysqld program + +EOF + exit 1; +} + +############################################################################## +# +# Parse an argument list +# +# We only need to pass arguments through to the server if we don't +# handle them here. So, we collect unrecognized options (passed on +# the command line) into the args variable. +# +############################################################################## + +sub parse_arguments +{ + my $opt = shift; + + my @saved_ARGV = @ARGV; + @ARGV = @_; # Set ARGV so GetOptions works + + my $pick_args; + if (@ARGV and $ARGV[0] eq 'PICK-ARGS-FROM-ARGV') + { + $pick_args = 1; + shift @ARGV; + } + + GetOptions( + $opt, + "force", + "basedir=s", + "builddir=s", # FIXME not documented + "srcdir=s", + "ldata|datadir=s", + + # Note that the user will be passed to mysqld so that it runs + # as 'user' (crucial e.g. if log-bin=/some_other_path/ + # where a chown of datadir won't help) + "user=s", + + "skip-name-resolve", + "verbose", + "rpm", + "help", + "defaults-file|defaults-extra-file|no-defaults:s", + + # Used when building the MySQL system tables on a different host than + # the target. The platform-independent files that are created in + # --datadir on the host can be copied to the target system. + # + # The most common use for this feature is in the Windows installer + # which will take the files from datadir and include them as part of + # the install package. See top-level 'dist-hook' make target. + # + # --windows is a deprecated alias + "cross-bootstrap|windows", # FIXME undocumented, even needed? + ) or usage(); + + usage() if $opt->{help}; + + @args = @ARGV if $pick_args; + + @ARGV = @saved_ARGV; # Set back ARGV +} + +############################################################################## +# +# Try to find a specific file within --basedir which can either be a binary +# release or installed source directory and return the path. +# +############################################################################## + +sub find_in_basedir +{ + my $opt = shift; + my $mode = shift; # "dir" or "file" + my $files = shift; + + foreach my $file ( @{ref($files) ? $files : [$files]} ) + { + foreach my $dir ( @_ ) + { + foreach my $part ( "$file","$file.exe","release/$file.exe", + "debug/$file.exe","relwithdebinfo/$file.exe" ) + { + my $path = "$opt->{basedir}/$dir/$part"; + if ( -f $path ) + { + return $mode eq "dir" ? dirname($path) : $path; + } + } + } + } +} + +############################################################################## +# +# Just a function to write out an error report +# +############################################################################## + +sub cannot_find_file +{ + my $file = shift; + + print "FATAL ERROR: Could not find $file\n"; + print "\n"; + print "If you compiled from source, you need to run 'make install' to\n"; + print "copy the software into the correct location ready for operation.\n"; + print "\n"; + print "If you are using a binary release, you must either be at the top\n"; + print "level of the extracted archive, or pass the --basedir option\n"; + print "pointing to that location.\n"; + print "\n"; + + exit 1; +} + +############################################################################## +# +# Form a command line that can handle spaces in paths and arguments +# +############################################################################## + +# FIXME this backslash escaping needed if using '"..."' ? +# This regexp makes sure that any special chars are quoted, +# so the arg gets passed exactly to the server. +# XXX: This is broken; true fix requires using eval and proper +# quoting of every single arg ($opt->{basedir}, $opt->{ldata}, etc.) +# join(" ", map {s/([^\w\_\.\-])/\\$1/g} + +sub quote_options { + my @cmd; + foreach my $opt ( @_ ) + { + next unless $opt; # If undefined or empty, just skip + push(@cmd, "\"$opt\""); # Quote argument + } + return join(" ", @cmd); +} + +############################################################################## +# +# Ok, let's go. We first need to parse arguments which are required by +# my_print_defaults so that we can execute it first, then later re-parse +# the command line to add any extra bits that we need. +# +############################################################################## + +my $opt = {}; +parse_arguments($opt, 'PICK-ARGS-FROM-ARGV', @ARGV); + +# ---------------------------------------------------------------------- +# We can now find my_print_defaults. This script supports: +# +# --srcdir=path pointing to compiled source tree +# --basedir=path pointing to installed binary location +# +# or default to compiled-in locations. +# ---------------------------------------------------------------------- + +my $print_defaults; + +if ( $opt->{srcdir} and $opt->{basedir} ) +{ + error("Specify either --basedir or --srcdir, not both"); +} +if ( $opt->{srcdir} ) +{ + $opt->{builddir} = $opt->{srcdir} unless $opt->{builddir}; + $print_defaults = "$opt->{builddir}/extra/my_print_defaults"; +} +elsif ( $opt->{basedir} ) +{ + $print_defaults = find_in_basedir($opt,"file","my_print_defaults","bin","extra"); +} +else +{ + $print_defaults='@bindir@/my_print_defaults'; +} + +-x $print_defaults or -f "$print_defaults.exe" + or cannot_find_file($print_defaults); + +# ---------------------------------------------------------------------- +# Now we can get arguments from the groups [mysqld] and [mysql_install_db] +# in the my.cfg file, then re-run to merge with command line arguments. +# ---------------------------------------------------------------------- + +my @default_options; +my $cmd = quote_options($print_defaults,$opt->{'defaults-file'}, + "mysqld","mysql_install_db"); +open(PIPE, "$cmd |") or error($opt,"can't run $cmd: $!"); +while ( <PIPE> ) +{ + chomp; + next unless /\S/; + push(@default_options, $_); +} +close PIPE; +$opt = {}; # Reset the arguments FIXME ? +parse_arguments($opt, @default_options); +parse_arguments($opt, 'PICK-ARGS-FROM-ARGV', @ARGV); + +# ---------------------------------------------------------------------- +# Configure paths to support files +# ---------------------------------------------------------------------- + +# FIXME $extra_bindir is not used +my ($bindir,$extra_bindir,$mysqld,$pkgdatadir,$mysqld_opt,$scriptdir); + +if ( $opt->{srcdir} ) +{ + $opt->{basedir} = $opt->{builddir}; + $bindir = "$opt->{basedir}/client"; + $extra_bindir = "$opt->{basedir}/extra"; + $mysqld = "$opt->{basedir}/sql/mysqld"; + $mysqld_opt = "--language=$opt->{srcdir}/sql/share/english"; + $pkgdatadir = "$opt->{srcdir}/scripts"; + $scriptdir = "$opt->{srcdir}/scripts"; +} +elsif ( $opt->{basedir} ) +{ + $bindir = "$opt->{basedir}/bin"; + $extra_bindir = $bindir; + $mysqld = find_in_basedir($opt,"file",["mysqld-nt","mysqld"], + "libexec","sbin","bin") || # ,"sql" + find_in_basedir($opt,"file","mysqld-nt", + "bin"); # ,"sql" + $pkgdatadir = find_in_basedir($opt,"dir","fill_help_tables.sql", + "share","share/mysql"); # ,"scripts" + $scriptdir = "$opt->{basedir}/scripts"; +} +else +{ + $opt->{basedir} = '@prefix@'; + $bindir = '@bindir@'; + $extra_bindir = $bindir; + $mysqld = '@libexecdir@/mysqld'; + $pkgdatadir = '@pkgdatadir@'; + $scriptdir = '@scriptdir@'; +} + +unless ( $opt->{ldata} ) +{ + $opt->{ldata} = '@localstatedir@'; +} + +if ( $opt->{srcdir} ) +{ + $pkgdatadir = "$opt->{srcdir}/scripts"; +} + +# ---------------------------------------------------------------------- +# Set up paths to SQL scripts required for bootstrap +# ---------------------------------------------------------------------- + +my $fill_help_tables = "$pkgdatadir/fill_help_tables.sql"; +my $create_system_tables = "$pkgdatadir/mysql_system_tables.sql"; +my $fill_system_tables = "$pkgdatadir/mysql_system_tables_data.sql"; + +foreach my $f ( $fill_help_tables,$create_system_tables,$fill_system_tables ) +{ + -f $f or cannot_find_file($f); +} + +-x $mysqld or -f "$mysqld.exe" or cannot_find_file($mysqld); +# Try to determine the hostname +my $hostname = hostname(); + +# ---------------------------------------------------------------------- +# Check if hostname is valid +# ---------------------------------------------------------------------- + +my $resolved; +if ( !$opt->{'cross-bootstrap'} and !$opt->{rpm} and !$opt->{force} ) +{ + my $resolveip; + + $resolved = `$resolveip $hostname 2>&1`; + if ( $? != 0 ) + { + $resolved=`$resolveip localhost 2>&1`; + if ( $? != 0 ) + { + error($opt, + "Neither host '$hostname' nor 'localhost' could be looked up with", + "$bindir/resolveip", + "Please configure the 'hostname' command to return a correct", + "hostname.", + "If you want to solve this at a later stage, restart this script", + "with the --force option"); + } + warning($opt, + "The host '$hostname' could not be looked up with resolveip.", + "This probably means that your libc libraries are not 100 % compatible", + "with this binary MySQL version. The MySQL daemon, mysqld, should work", + "normally with the exception that host name resolving will not work.", + "This means that you should use IP addresses instead of hostnames", + "when specifying MySQL privileges !"); + } +} + +# FIXME what does this really mean.... +if ( $opt->{'skip-name-resolve'} and $resolved and $resolved =~ /\s/ ) +{ + $hostname = (split(' ', $resolved))[5]; +} + +# ---------------------------------------------------------------------- +# Create database directories mysql & test +# ---------------------------------------------------------------------- + +foreach my $dir ( $opt->{ldata}, "$opt->{ldata}/mysql", "$opt->{ldata}/test" ) +{ + # FIXME not really the same as original "mkdir -p", but ok? + mkdir($dir, 0700) unless -d $dir; + chown($opt->{user}, $dir) if -w "/" and !$opt->{user}; +} + +push(@args, "--user=$opt->{user}") if $opt->{user}; + +# ---------------------------------------------------------------------- +# Configure mysqld command line +# ---------------------------------------------------------------------- + +# FIXME use --init-file instead of --bootstrap ?! + +my $mysqld_bootstrap = $ENV{MYSQLD_BOOTSTRAP} || $mysqld; +my $mysqld_install_cmd_line = quote_options($mysqld_bootstrap, + $opt->{'defaults-file'}, + $mysqld_opt, + "--bootstrap", + "--basedir=$opt->{basedir}", + "--datadir=$opt->{ldata}", + "--skip-innodb", + "--skip-bdb", + "--skip-ndbcluster", + "--max_allowed_packet=8M", + "--net_buffer_length=16K", + @args, + ); + +# ---------------------------------------------------------------------- +# Create the system and help tables by passing them to "mysqld --bootstrap" +# ---------------------------------------------------------------------- + +report_verbose_wait($opt,"Installing MySQL system tables..."); + +open(SQL, $create_system_tables) + or error($opt,"can't open $create_system_tables for reading: $!"); +# FIXME > /dev/null ? +if ( open(PIPE, "| $mysqld_install_cmd_line") ) +{ + print PIPE "use mysql;\n"; + while ( <SQL> ) + { + # When doing a "cross bootstrap" install, no reference to the current + # host should be added to the system tables. So we filter out any + # lines which contain the current host name. + next if $opt->{'cross-bootstrap'} and /\@current_hostname/; + + print PIPE $_; + } + close PIPE; + close SQL; + + report_verbose($opt,"OK"); + + # ---------------------------------------------------------------------- + # Pipe fill_help_tables.sql to "mysqld --bootstrap" + # ---------------------------------------------------------------------- + + report_verbose_wait($opt,"Filling help tables..."); + open(SQL, $fill_help_tables) + or error($opt,"can't open $fill_help_tables for reading: $!"); + # FIXME > /dev/null ? + if ( open(PIPE, "| $mysqld_install_cmd_line") ) + { + print PIPE "use mysql;\n"; + while ( <SQL> ) + { + print PIPE $_; + } + close PIPE; + close SQL; + + report_verbose($opt,"OK"); + } + else + { + warning($opt,"HELP FILES ARE NOT COMPLETELY INSTALLED!", + "The \"HELP\" command might not work properly"); + } + + report_verbose($opt,"To start mysqld at boot time you have to copy", + "support-files/mysql.server to the right place " . + "for your system"); + + if ( !$opt->{'cross-bootstrap'} ) + { + # This is not a true installation on a running system. The end user must + # set a password after installing the data files on the real host system. + # At this point, there is no end user, so it does not make sense to print + # this reminder. + report($opt, + "PLEASE REMEMBER TO SET A PASSWORD FOR THE MySQL root USER !", + "To do so, start the server, then issue the following commands:", + "", + " $bindir/mysqladmin -u root password 'new-password'", + " $bindir/mysqladmin -u root -h $hostname password 'new-password'", + "", + "Alternatively you can run:", + "", + " $bindir/mysql_secure_installation", + "", + "which will also give you the option of removing the test", + "databases and anonymous user created by default. This is", + "strongly recommended for production servers.", + "", + "See the manual for more instructions."); + + if ( !$opt->{rpm} ) + { + report($opt, + "You can start the MySQL daemon with:", + "", + " cd " . '@prefix@' . " ; $bindir/mysqld_safe &", + "", + "You can test the MySQL daemon with mysql-test-run.pl", + "", + " cd mysql-test ; perl mysql-test-run.pl"); + } + report($opt, + "Please report any problems with the " . '@scriptdir@' . "/mysqlbug script!", + "", + "The latest information about MySQL is available on the web at", + "", + " http://www.mysql.com", + "", + "Support MySQL by buying support/licenses at http://shop.mysql.com"); + } + exit 0 +} +else +{ + error($opt, + "Installation of system tables failed!", + "", + "Examine the logs in $opt->{ldata} for more information.", + "You can try to start the mysqld daemon with:", + "$mysqld --skip-grant &", + "and use the command line tool", + "$bindir/mysql to connect to the mysql", + "database and look at the grant tables:", + "", + "shell> $bindir/mysql -u root mysql", + "mysql> show tables", + "", + "Try 'mysqld --help' if you have problems with paths. Using --log", + "gives you a log in $opt->{ldata} that may be helpful.", + "", + "The latest information about MySQL is available on the web at", + "http://www.mysql.com", + "Please consult the MySQL manual section: 'Problems running mysql_install_db',", + "and the manual section that describes problems on your OS.", + "Another information source is the MySQL email archive.", + "Please check all of the above before mailing us!", + "And if you do mail us, you MUST use the " . '@scriptdir@' . "/mysqlbug script!") +} + +############################################################################## +# +# Misc +# +############################################################################## + +sub report_verbose +{ + my $opt = shift; + my $text = shift; + + report_verbose_wait($opt, $text, @_); + print "\n\n"; +} + +sub report_verbose_wait +{ + my $opt = shift; + my $text = shift; + + if ( $opt->{verbose} or (!$opt->{rpm} and !$opt->{'cross-bootstrap'}) ) + { + print "$text"; + map {print "\n$_"} @_; + } +} + +sub report +{ + my $opt = shift; + my $text = shift; + + print "$text\n"; + map {print "$_\n"} @_; + print "\n"; +} + +sub error +{ + my $opt = shift; + my $text = shift; + + print "FATAL ERROR: $text\n"; + map {print "$_\n"} @_; + exit 1; +} + +sub warning +{ + my $opt = shift; + my $text = shift; + + print "WARNING: $text\n"; + map {print "$_\n"} @_; + print "\n"; +} diff --git a/scripts/mysql_secure_installation.pl.in b/scripts/mysql_secure_installation.pl.in new file mode 100755 index 00000000000..4eeb50e6d2f --- /dev/null +++ b/scripts/mysql_secure_installation.pl.in @@ -0,0 +1,352 @@ +#!/usr/bin/perl +# -*- cperl -*- +# +# Copyright (C) 2002 MySQL AB and Jeremy Cole +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +use Fcntl; +use strict; + +my $config = ".my.cnf.$$"; +my $command = ".mysql.$$"; +my $hadpass = 0; + +# FIXME +# trap "interrupt" 2 + +my $rootpass = ""; + +sub echo_on { + if ($^O eq 'MSWin32') { + ReadMode('normal'); + } else { + system("stty echo"); + } +} + +sub echo_off { + if ($^O eq 'MSWin32') { + ReadMode('noecho'); + } else { + system("stty -echo"); + } +} + +sub write_file { + my $file = shift; + -f $file or die "ERROR: file is missing \"$file\": $!"; + open(FILE, ">$file") or die "ERROR: can't write to file \"$file\": $!"; + foreach my $line ( @_ ) { + print FILE $line, "\n"; # Add EOL char + } + close FILE; +} + +sub prepare { + foreach my $file ( $config, $command ) { + next if -f $file; # Already exists + local *FILE; + sysopen(FILE, $file, O_CREAT, 0600) + or die "ERROR: can't create $file: $!"; + close FILE; + } +} + +sub do_query { + my $query = shift; + write_file($command, $query); + system("mysql --defaults-file=$config < $command"); + return $?; +} + +sub make_config { + my $password = shift; + + write_file($config, + "# mysql_secure_installation config file", + "[mysql]", + "user=root", + "password=$rootpass"); +} + +sub get_root_password { + my $status = 1; + while ( $status == 1 ) { + echo_off(); + print "Enter current password for root (enter for none): "; + my $password = <STDIN>; + echo_on(); + if ( $password ) { + $hadpass = 1; + } else { + $hadpass = 0; + } + $rootpass = $password; + make_config($rootpass); + do_query(""); + $status = $?; + } + print "OK, successfully used password, moving on...\n\n"; +} + +sub set_root_password { + echo_off(); + print "New password: "; + my $password1 = <STDIN>; + print "\nRe-enter new password: "; + my $password2 = <STDIN>; + print "\n"; + echo_on(); + + if ( $password1 eq $password2 ) { + print "Sorry, passwords do not match.\n\n"; + return 1; + } + + if ( !$password1 ) { + print "Sorry, you can't use an empty password here.\n\n"; + return 1; + } + + do_query("UPDATE mysql.user SET Password=PASSWORD('$password1') WHERE User='root';"); + if ( $? == 0 ) { + print "Password updated successfully!\n"; + print "Reloading privilege tables..\n"; + if ( !reload_privilege_tables() ) { + exit 1; + } + print "\n"; + $rootpass = $password1; + make_config($rootpass); + } else { + print "Password update failed!\n"; + exit 1; + } + + return 0; +} + +sub remove_anonymous_users { + do_query("DELETE FROM mysql.user WHERE User='';"); + if ( $? == 0 ) { + print " ... Success!\n"; + } else { + print " ... Failed!\n"; + exit 1; + } + + return 0; +} + +sub remove_remote_root { + do_query("DELETE FROM mysql.user WHERE User='root' AND Host!='localhost';"); + if ( $? == 0 ) { + print " ... Success!\n"; + } else { + print " ... Failed!\n"; + } +} + +sub remove_test_database { + print " - Dropping test database...\n"; + do_query("DROP DATABASE test;"); + if ( $? == 0 ) { + print " ... Success!\n"; + } else { + print " ... Failed! Not critical, keep moving...\n"; + } + + print " - Removing privileges on test database...\n"; + do_query("DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%'"); + if ( $? == 0 ) { + print " ... Success!\n"; + } else { + print " ... Failed! Not critical, keep moving...\n"; + } + + return 0; +} + +sub reload_privilege_tables { + do_query("FLUSH PRIVILEGES;"); + if ( $? == 0 ) { + print " ... Success!\n"; + return 0; + } else { + print " ... Failed!\n"; + return 1; + } +} + +sub interrupt { + print "\nAborting!\n\n"; + cleanup(); + echo_on(); + exit 1; +} + +sub cleanup { + print "Cleaning up...\n"; + unlink($config,$command); +} + + +# The actual script starts here + +prepare(); + +print <<HERE; + + + +NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MySQL + SERVERS IN PRODUCTION USE! PLEASE READ EACH STEP CAREFULLY! + +In order to log into MySQL to secure it, we'll need the current +password for the root user. If you've just installed MySQL, and +you haven't set the root password yet, the password will be blank, +so you should just press enter here. + +HERE + +get_root_password(); + + +# +# Set the root password +# + +print "Setting the root password ensures that nobody can log into the MySQL\n"; +print "root user without the proper authorisation.\n\n"; + +if ( $hadpass == 0 ) { + print "Set root password? [Y/n] "; +} else { + print "You already have a root password set, so you can safely answer 'n'.\n\n"; + print "Change the root password? [Y/n] "; +} + +my $reply = <STDIN>; +if ( $reply =~ /n/i ) { + print " ... skipping.\n"; +} else { + my $status = 1; + while ( $status == 1 ) { + set_root_password(); + $status = $?; + } +} +print "\n"; + + +# +# Remove anonymous users +# + +print <<HERE; +By default, a MySQL installation has an anonymous user, allowing anyone +to log into MySQL without having to have a user account created for +them. This is intended only for testing, and to make the installation +go a bit smoother. You should remove them before moving into a +production environment. + +HERE + +print "Remove anonymous users? [Y/n] "; +$reply = <STDIN>; +if ( $reply =~ /n/i ) { + print " ... skipping.\n"; +} else { + remove_anonymous_users(); +} +print "\n"; + + +# +# Disallow remote root login +# + +print <<HERE; +Normally, root should only be allowed to connect from 'localhost'. This +ensures that someone cannot guess at the root password from the network. + +HERE + +print "Disallow root login remotely? [Y/n] "; +$reply = <STDIN>; +if ( $reply =~ /n/i ) { + print " ... skipping.\n"; +} else { + remove_remote_root(); +} +print "\n"; + + +# +# Remove test database +# + +print <<HERE; +By default, MySQL comes with a database named 'test' that anyone can +access. This is also intended only for testing, and should be removed +before moving into a production environment. + +HERE + +print "Remove test database and access to it? [Y/n] "; +$reply = <STDIN>; +if ( $reply =~ /n/i ) { + print " ... skipping.\n"; +} else { + remove_test_database(); +} +print "\n"; + + +# +# Reload privilege tables +# + +print <<HERE; +Reloading the privilege tables will ensure that all changes made so far +will take effect immediately. + +HERE + +print "Reload privilege tables now? [Y/n] "; +$reply = <STDIN>; +if ( $reply =~ /n/i ) { + print " ... skipping.\n"; +} else { + reload_privilege_tables(); +} +print "\n"; + +cleanup(); + +print <<HERE; + + + +All done! If you've completed all of the above steps, your MySQL +installation should now be secure. + +Thanks for using MySQL! + + +HERE + + + diff --git a/scripts/mysql_tableinfo.sh b/scripts/mysql_tableinfo.sh index 2ed7e381fa3..c90c410ca78 100644 --- a/scripts/mysql_tableinfo.sh +++ b/scripts/mysql_tableinfo.sh @@ -1,4 +1,4 @@ -#!@PERL@ -w +#!/usr/bin/perl use strict; use Getopt::Long; diff --git a/scripts/mysqld_multi.sh b/scripts/mysqld_multi.sh index 92cfbe3ef22..3cb4665eb1c 100644 --- a/scripts/mysqld_multi.sh +++ b/scripts/mysqld_multi.sh @@ -1,4 +1,4 @@ -#!@PERL@ +#!/usr/bin/perl use Getopt::Long; use POSIX qw(strftime); diff --git a/scripts/mysqldumpslow.sh b/scripts/mysqldumpslow.sh index ff82a35ec3f..f05761bb837 100644 --- a/scripts/mysqldumpslow.sh +++ b/scripts/mysqldumpslow.sh @@ -1,4 +1,4 @@ -#!@PERL@ +#!/usr/bin/perl # mysqldumpslow - parse and summarize the MySQL slow query log # Original version by Tim Bunce, sometime in 2000. diff --git a/scripts/mysqlhotcopy.sh b/scripts/mysqlhotcopy.sh index 6ad5c77b954..8814e36b2fa 100644 --- a/scripts/mysqlhotcopy.sh +++ b/scripts/mysqlhotcopy.sh @@ -1,4 +1,4 @@ -#!@PERL@ -w +#!/usr/bin/perl use strict; use Getopt::Long; @@ -39,7 +39,7 @@ WARNING: THIS PROGRAM IS STILL IN BETA. Comments/patches welcome. # Documentation continued at end of file -my $VERSION = "1.22"; +my $VERSION = "1.23"; my $opt_tmpdir = $ENV{TMPDIR} || "/tmp"; @@ -132,7 +132,6 @@ GetOptions( \%opt, # 'target' - destination directory of the copy # 'tables' - array-ref to list of tables in the db # 'files' - array-ref to list of files to be copied -# (RAID files look like 'nn/name.MYD') # 'index' - array-ref to list of indexes to be copied # @@ -263,7 +262,6 @@ my $hc_locks = ""; my $hc_tables = ""; my $num_tables = 0; my $num_files = 0; -my $raid_dir_regex = '[A-Za-z0-9]{2}'; foreach my $rdb ( @db_desc ) { my $db = $rdb->{src}; @@ -292,20 +290,12 @@ foreach my $rdb ( @db_desc ) { or die "Cannot open dir '$db_dir': $!"; my %db_files; - my @raid_dir = (); while ( defined( my $name = readdir DBDIR ) ) { - if ( $name =~ /^$raid_dir_regex$/ && -d "$db_dir/$name" ) { - push @raid_dir, $name; - } - else { - $db_files{$name} = $1 if ( $name =~ /(.+)\.\w+$/ ); - } + $db_files{$name} = $1 if ( $name =~ /(.+)\.\w+$/ ); } closedir( DBDIR ); - scan_raid_dir( \%db_files, $db_dir, @raid_dir ); - unless( keys %db_files ) { warn "'$db' is an empty database\n"; } @@ -336,8 +326,6 @@ foreach my $rdb ( @db_desc ) { my @hc_tables = map { quote_names("$db.$_") } @dbh_tables; $rdb->{tables} = [ @hc_tables ]; - $rdb->{raid_dirs} = [ get_raid_dirs( $rdb->{files} ) ]; - $hc_locks .= ", " if ( length $hc_locks && @hc_tables ); $hc_locks .= join ", ", map { "$_ READ" } @hc_tables; $hc_tables .= ", " if ( length $hc_tables && @hc_tables ); @@ -411,27 +399,24 @@ if ($opt{method} =~ /^cp\b/) retire_directory( @existing ) if @existing && !$opt{addtodest}; foreach my $rdb ( @db_desc ) { - foreach my $td ( '', @{$rdb->{raid_dirs}} ) { - - my $tgt_dirpath = "$rdb->{target}/$td"; - # Remove trailing slashes (needed for Mac OS X) - substr($tgt_dirpath, 1) =~ s|/+$||; - if ( $opt{dryrun} ) { - print "mkdir $tgt_dirpath, 0750\n"; - } - elsif ($opt{method} =~ /^scp\b/) { - ## assume it's there? - ## ... - } - else { - mkdir($tgt_dirpath, 0750) or die "Can't create '$tgt_dirpath': $!\n" - unless -d $tgt_dirpath; - if ($^O !~ m/^(NetWare)$/) - { - my @f_info= stat "$datadir/$rdb->{src}"; - chown $f_info[4], $f_info[5], $tgt_dirpath; - } - } + my $tgt_dirpath = "$rdb->{target}"; + # Remove trailing slashes (needed for Mac OS X) + substr($tgt_dirpath, 1) =~ s|/+$||; + if ( $opt{dryrun} ) { + print "mkdir $tgt_dirpath, 0750\n"; + } + elsif ($opt{method} =~ /^scp\b/) { + ## assume it's there? + ## ... + } + else { + mkdir($tgt_dirpath, 0750) or die "Can't create '$tgt_dirpath': $!\n" + unless -d $tgt_dirpath; + if ($^O !~ m/^(NetWare)$/) + { + my @f_info= stat "$datadir/$rdb->{src}"; + chown $f_info[4], $f_info[5], $tgt_dirpath; + } } } @@ -489,7 +474,7 @@ foreach my $rdb ( @db_desc ) my @files = map { "$datadir/$rdb->{src}/$_" } @{$rdb->{files}}; next unless @files; - eval { copy_files($opt{method}, \@files, $rdb->{target}, $rdb->{raid_dirs} ); }; + eval { copy_files($opt{method}, \@files, $rdb->{target}); }; push @failed, "$rdb->{src} -> $rdb->{target} failed: $@" if ( $@ ); @@ -582,7 +567,7 @@ exit 0; # --- sub copy_files { - my ($method, $files, $target, $raid_dirs) = @_; + my ($method, $files, $target) = @_; my @cmd; print "Copying ".@$files." files...\n" unless $opt{quiet}; @@ -603,15 +588,8 @@ sub copy_files { # add recursive option for scp $cp.= " -r" if $^O =~ /m^(solaris|linux|freebsd|darwin)$/ && $method =~ /^scp\b/; - my @non_raid = map { "'$_'" } grep { ! m:/$raid_dir_regex/[^/]+$: } @$files; - - # add files to copy and the destination directory - safe_system( $cp, @non_raid, "'$target'" ) if (@non_raid); - - foreach my $rd ( @$raid_dirs ) { - my @raid = map { "'$_'" } grep { m:$rd/: } @$files; - safe_system( $cp, @raid, "'$target'/$rd" ) if ( @raid ); - } + # perform the actual copy + safe_system( $cp, (map { "'$_'" } @$files), "'$target'" ); } else { @@ -789,35 +767,6 @@ sub get_row_hash { return $sth->fetchrow_hashref(); } -sub scan_raid_dir { - my ( $r_db_files, $data_dir, @raid_dir ) = @_; - - local(*RAID_DIR); - - foreach my $rd ( @raid_dir ) { - - opendir(RAID_DIR, "$data_dir/$rd" ) - or die "Cannot open dir '$data_dir/$rd': $!"; - - while ( defined( my $name = readdir RAID_DIR ) ) { - $r_db_files->{"$rd/$name"} = $1 if ( $name =~ /(.+)\.\w+$/ ); - } - closedir( RAID_DIR ); - } -} - -sub get_raid_dirs { - my ( $r_files ) = @_; - - my %dirs = (); - foreach my $f ( @$r_files ) { - if ( $f =~ m:^($raid_dir_regex)/: ) { - $dirs{$1} = 1; - } - } - return sort keys %dirs; -} - sub get_list_of_tables { my ( $db ) = @_; diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 84b042a91b1..9ea9874c1b1 100755 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -48,7 +48,7 @@ ENDIF(DISABLE_GRANT_OPTIONS) ADD_EXECUTABLE(mysqld${MYSQLD_EXE_SUFFIX} ../sql-common/client.c derror.cc des_key_file.cc - discover.cc ../libmysql/errmsg.c field.cc field_conv.cc + discover.cc ../libmysql/errmsg.c field.cc stacktrace.c stacktrace.h field_conv.cc filesort.cc gstream.cc ha_blackhole.cc ha_archive.cc ha_heap.cc ha_myisam.cc ha_myisammrg.cc ha_innodb.cc ha_federated.cc ha_berkeley.cc diff --git a/sql/field.cc b/sql/field.cc index f1e2b6a4f27..53eafcaf2cc 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -5861,26 +5861,41 @@ check_string_copy_error(Field_str *field, } - /* - Send a truncation warning or a truncation error - after storing a too long character string info a field. + Check if we lost any important data and send a truncation error/warning SYNOPSIS - report_data_too_long() - field - Field + Field_longstr::report_if_important_data() + ptr - Truncated rest of string + end - End of truncated string - RETURN - N/A + RETURN VALUES + 0 - None was truncated (or we don't count cut fields) + 2 - Some bytes was truncated + + NOTE + Check if we lost any important data (anything in a binary string, + or any non-space in others). If only trailing spaces was lost, + send a truncation note, otherwise send a truncation error. */ -inline void -report_data_too_long(Field_str *field) +int +Field_longstr::report_if_important_data(const char *ptr, const char *end) { - if (field->table->in_use->abort_on_warning) - field->set_warning(MYSQL_ERROR::WARN_LEVEL_ERROR, ER_DATA_TOO_LONG, 1); - else - field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1); + if ((ptr < end) && table->in_use->count_cuted_fields) + { + if (test_if_important_data(field_charset, ptr, end)) + { + if (table->in_use->abort_on_warning) + set_warning(MYSQL_ERROR::WARN_LEVEL_ERROR, ER_DATA_TOO_LONG, 1); + else + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1); + } + else /* If we lost only spaces then produce a NOTE, not a WARNING */ + set_warning(MYSQL_ERROR::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1); + return 2; + } + return 0; } @@ -5914,19 +5929,7 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) cannot_convert_error_pos, from + length)) return 2; - /* - Check if we lost any important data (anything in a binary string, - or any non-space in others). - */ - if ((from_end_pos < from + length) && table->in_use->count_cuted_fields) - { - if (test_if_important_data(field_charset, from_end_pos, from + length)) - { - report_data_too_long(this); - return 2; - } - } - return 0; + return report_if_important_data(from_end_pos, from + length); } @@ -6385,16 +6388,7 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs) cannot_convert_error_pos, from + length)) return 2; - // Check if we lost something other than just trailing spaces - if ((from_end_pos < from + length) && table->in_use->count_cuted_fields) - { - if (test_if_important_data(field_charset, from_end_pos, from + length)) - report_data_too_long(this); - else /* If we lost only spaces then produce a NOTE, not a WARNING */ - set_warning(MYSQL_ERROR::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1); - return 2; - } - return 0; + return report_if_important_data(from_end_pos, from + length); } @@ -7030,13 +7024,7 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) cannot_convert_error_pos, from + length)) return 2; - if (from_end_pos < from + length) - { - report_data_too_long(this); - return 2; - } - - return 0; + return report_if_important_data(from_end_pos, from + length); oom_error: /* Fatal OOM error */ @@ -7883,10 +7871,10 @@ int Field_set::store(const char *from,uint length,CHARSET_INFO *cs) int Field_set::store(longlong nr, bool unsigned_val) { int error= 0; - if ((ulonglong) nr > (ulonglong) (((longlong) 1 << typelib->count) - - (longlong) 1)) + ulonglong max_nr= set_bits(ulonglong, typelib->count); + if ((ulonglong) nr > max_nr) { - nr&= (longlong) (((longlong) 1 << typelib->count) - (longlong) 1); + nr&= max_nr; set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1); error=1; } diff --git a/sql/field.h b/sql/field.h index d681229a9fd..c82d65147ac 100644 --- a/sql/field.h +++ b/sql/field.h @@ -454,6 +454,8 @@ public: class Field_longstr :public Field_str { +protected: + int report_if_important_data(const char *ptr, const char *end); public: Field_longstr(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, diff --git a/sql/filesort.cc b/sql/filesort.cc index 43b079e83d5..70fc6937b59 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -112,6 +112,13 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, FILESORT_INFO table_sort; TABLE_LIST *tab= table->pos_in_table_list; Item_subselect *subselect= tab ? tab->containing_subselect() : 0; + + /* + Release InnoDB's adaptive hash index latch (if holding) before + running a sort. + */ + ha_release_temporary_latches(thd); + /* Don't use table->sort in filesort as it is also used by QUICK_INDEX_MERGE_SELECT. Work with a copy and put it back at the end @@ -215,8 +222,7 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, sort_keys= table_sort.sort_keys; if (memavl < min_sort_memory) { - my_error(ER_OUTOFMEMORY,MYF(ME_ERROR+ME_WAITTANG), - thd->variables.sortbuff_size); + my_error(ER_OUT_OF_SORTMEMORY,MYF(ME_ERROR+ME_WAITTANG)); goto err; } if (open_cached_file(&buffpek_pointers,mysql_tmpdir,TEMP_PREFIX, diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index fa68da87661..2d2007c8fdd 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -6339,7 +6339,9 @@ void innodb_export_status(void) /*======================*/ { - srv_export_innodb_status(); + if (innodb_inited) { + srv_export_innodb_status(); + } } /**************************************************************************** diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index c93091e36d2..e3ab2b67e26 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -439,7 +439,8 @@ void ha_ndbcluster::no_uncommitted_rows_reset(THD *thd) void ha_ndbcluster::invalidate_dictionary_cache(bool global) { - NDBDICT *dict= get_ndb()->getDictionary(); + Ndb * ndb= get_ndb(); + NDBDICT *dict= ndb->getDictionary(); DBUG_ENTER("invalidate_dictionary_cache"); DBUG_PRINT("info", ("invalidating %s", m_tabname)); @@ -459,6 +460,7 @@ void ha_ndbcluster::invalidate_dictionary_cache(bool global) } else dict->removeCachedTable(m_tabname); + build_index_list(ndb, table, ILBP_OPEN); table->s->version=0L; /* Free when thread is ready */ /* Invalidate indexes */ for (uint i= 0; i < table->s->keys; i++) @@ -470,17 +472,23 @@ void ha_ndbcluster::invalidate_dictionary_cache(bool global) switch (idx_type) { case PRIMARY_KEY_ORDERED_INDEX: case ORDERED_INDEX: + if (!index) + break; if (global) dict->invalidateIndex(index->getName(), m_tabname); else dict->removeCachedIndex(index->getName(), m_tabname); break; case UNIQUE_ORDERED_INDEX: + if (!index) + break; if (global) dict->invalidateIndex(index->getName(), m_tabname); else dict->removeCachedIndex(index->getName(), m_tabname); case UNIQUE_INDEX: + if (!unique_index) + break; if (global) dict->invalidateIndex(unique_index->getName(), m_tabname); else diff --git a/sql/ha_ndbcluster_cond.cc b/sql/ha_ndbcluster_cond.cc index c7b185a92f0..f5b41959b40 100644 --- a/sql/ha_ndbcluster_cond.cc +++ b/sql/ha_ndbcluster_cond.cc @@ -117,7 +117,8 @@ void ndb_serialize_cond(const Item *item, void *arg) if (item->type() == Item::FUNC_ITEM) { Item_func *func_item= (Item_func *) item; - if (func_item->functype() == Item_func::UNKNOWN_FUNC && + if ((func_item->functype() == Item_func::UNKNOWN_FUNC || + func_item->functype() == Item_func::NEG_FUNC) && func_item->const_item()) { // Skip any arguments since we will evaluate function instead @@ -369,8 +370,9 @@ void ndb_serialize_cond(const Item *item, void *arg) { Item_func *func_item= (Item_func *) item; // Check that we expect a function or functional expression here - if (context->expecting(Item::FUNC_ITEM) || - func_item->functype() == Item_func::UNKNOWN_FUNC) + if (context->expecting(Item::FUNC_ITEM) || + func_item->functype() == Item_func::UNKNOWN_FUNC || + func_item->functype() == Item_func::NEG_FUNC) context->expect_nothing(); else { @@ -584,6 +586,7 @@ void ndb_serialize_cond(const Item *item, void *arg) context->expect(Item::FUNC_ITEM); break; } + case Item_func::NEG_FUNC: case Item_func::UNKNOWN_FUNC: { DBUG_PRINT("info", ("UNKNOWN_FUNC %s", diff --git a/sql/ha_ndbcluster_cond.h b/sql/ha_ndbcluster_cond.h index 6baf6945b58..6504df8d9d4 100644 --- a/sql/ha_ndbcluster_cond.h +++ b/sql/ha_ndbcluster_cond.h @@ -228,6 +228,7 @@ public: case (Item_func::ISNOTNULL_FUNC): { return NDB_ISNOTNULL_FUNC; } case (Item_func::LIKE_FUNC): { return NDB_LIKE_FUNC; } case (Item_func::NOT_FUNC): { return NDB_NOT_FUNC; } + case (Item_func::NEG_FUNC): { return NDB_UNKNOWN_FUNC; } case (Item_func::UNKNOWN_FUNC): { return NDB_UNKNOWN_FUNC; } case (Item_func::COND_AND_FUNC): { return NDB_COND_AND_FUNC; } case (Item_func::COND_OR_FUNC): { return NDB_COND_OR_FUNC; } diff --git a/sql/handler.cc b/sql/handler.cc index 27204ae725b..bfad10f986f 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1381,6 +1381,13 @@ int ha_delete_table(THD *thd, enum db_type table_type, const char *path, handler *handler::clone(MEM_ROOT *mem_root) { handler *new_handler= get_new_handler(table, mem_root, table->s->db_type); + /* + Allocate handler->ref here because otherwise ha_open will allocate it + on this->table->mem_root and we will not be able to reclaim that memory + when the clone handler object is destroyed. + */ + if (!(new_handler->ref= (byte*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2))) + return NULL; if (new_handler && !new_handler->ha_open(table->s->path, table->db_stat, HA_OPEN_IGNORE_IF_LOCKED)) return new_handler; @@ -1420,8 +1427,9 @@ int handler::ha_open(const char *name, int mode, int test_if_locked) (void) extra(HA_EXTRA_NO_READCHECK); // Not needed in SQL DBUG_ASSERT(alloc_root_inited(&table->mem_root)); - - if (!(ref= (byte*) alloc_root(&table->mem_root, ALIGN_SIZE(ref_length)*2))) + /* ref is already allocated for us if we're called from handler::clone() */ + if (!ref && !(ref= (byte*) alloc_root(&table->mem_root, + ALIGN_SIZE(ref_length)*2))) { close(); error=HA_ERR_OUT_OF_MEM; diff --git a/sql/item.cc b/sql/item.cc index 713e7709bcb..11e9acb1e55 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1207,6 +1207,22 @@ bool Item_name_const::is_null() return value_item->is_null(); } + +Item_name_const::Item_name_const(Item *name_arg, Item *val): + value_item(val), name_item(name_arg) +{ + if (!(valid_args= name_item->basic_const_item() && + (value_item->basic_const_item() || + ((value_item->type() == FUNC_ITEM) && + (((Item_func *) value_item)->functype() == + Item_func::NEG_FUNC) && + (((Item_func *) value_item)->key_item()->type() != + FUNC_ITEM))))) + my_error(ER_WRONG_ARGUMENTS, MYF(0), "NAME_CONST"); + Item::maybe_null= TRUE; +} + + Item::Type Item_name_const::type() const { /* @@ -1218,8 +1234,17 @@ Item::Type Item_name_const::type() const if (item->type() == FIELD_ITEM) ((Item_field *) item)->... we return NULL_ITEM in the case to avoid wrong casting. + + valid_args guarantees value_item->basic_const_item(); if type is + FUNC_ITEM, then we have a fudged item_func_neg() on our hands + and return the underlying type. */ - return valid_args ? value_item->type() : NULL_ITEM; + return valid_args ? + (((value_item->type() == FUNC_ITEM) && + (((Item_func *) value_item)->functype() == Item_func::NEG_FUNC)) ? + ((Item_func *) value_item)->key_item()->type() : + value_item->type()) : + NULL_ITEM; } @@ -2385,14 +2410,14 @@ default_set_param_func(Item_param *param, Item_param::Item_param(unsigned pos_in_query_arg) : - strict_type(FALSE), state(NO_VALUE), item_result_type(STRING_RESULT), /* Don't pretend to be a literal unless value for this item is set. */ item_type(PARAM_ITEM), param_type(MYSQL_TYPE_VARCHAR), pos_in_query(pos_in_query_arg), - set_param_func(default_set_param_func) + set_param_func(default_set_param_func), + limit_clause_param(FALSE) { name= (char*) "?"; /* @@ -2580,8 +2605,14 @@ bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry) if (entry && entry->value) { item_result_type= entry->type; - if (strict_type && required_result_type != item_result_type) - DBUG_RETURN(1); + unsigned_flag= entry->unsigned_flag; + if (limit_clause_param) + { + my_bool unused; + set_int(entry->val_int(&unused), MY_INT64_NUM_DECIMAL_DIGITS); + item_type= Item::INT_ITEM; + DBUG_RETURN(!unsigned_flag && value.integer < 0 ? 1 : 0); + } switch (item_result_type) { case REAL_RESULT: set_double(*(double*)entry->value); @@ -2875,7 +2906,10 @@ const String *Item_param::query_val_str(String* str) const { switch (state) { case INT_VALUE: - str->set(value.integer, &my_charset_bin); + if (unsigned_flag) + str->set((ulonglong) value.integer, &my_charset_bin); + else + str->set(value.integer, &my_charset_bin); break; case REAL_VALUE: str->set(value.real, NOT_FIXED_DEC, &my_charset_bin); @@ -3903,6 +3937,18 @@ bool Item_field::fix_fields(THD *thd, Item **reference) else if (!from_field) goto error; + if (!outer_fixed && cached_table && cached_table->select_lex && + context->select_lex && + cached_table->select_lex != context->select_lex) + { + int ret; + if ((ret= fix_outer_field(thd, &from_field, reference)) < 0) + goto error; + else if (!ret) + return FALSE; + outer_fixed= 1; + } + /* if it is not expression from merged VIEW we will set this field. @@ -3918,18 +3964,6 @@ bool Item_field::fix_fields(THD *thd, Item **reference) if (from_field == view_ref_found) return FALSE; - if (!outer_fixed && cached_table && cached_table->select_lex && - context->select_lex && - cached_table->select_lex != context->select_lex) - { - int ret; - if ((ret= fix_outer_field(thd, &from_field, reference)) < 0) - goto error; - else if (!ret) - return FALSE; - outer_fixed= 1; - } - set_field(from_field); if (thd->lex->in_sum_func && thd->lex->in_sum_func->nest_level == @@ -4083,6 +4117,30 @@ bool Item_field::subst_argument_checker(byte **arg) } +/** + Convert a numeric value to a zero-filled string + + @param[in,out] item the item to operate on + @param field The field that this value is equated to + + This function converts a numeric value to a string. In this conversion + the zero-fill flag of the field is taken into account. + This is required so the resulting string value can be used instead of + the field reference when propagating equalities. +*/ + +static void convert_zerofill_number_to_string(Item **item, Field_num *field) +{ + char buff[MAX_FIELD_WIDTH],*pos; + String tmp(buff,sizeof(buff), field->charset()), *res; + + res= (*item)->val_str(&tmp); + field->prepend_zeros(res); + pos= (char *) sql_strmake (res->ptr(), res->length()); + *item= new Item_string(pos, res->length(), field->charset()); +} + + /* Set a pointer to the multiple equality the field reference belongs to (if any) @@ -4131,6 +4189,13 @@ Item *Item_field::equal_fields_propagator(byte *arg) if (!item || (cmp_context != (Item_result)-1 && item->cmp_context != cmp_context)) item= this; + else if (field && (field->flags & ZEROFILL_FLAG) && IS_NUM(field->type())) + { + if (item && cmp_context != INT_RESULT) + convert_zerofill_number_to_string(&item, (Field_num *)field); + else + item= this; + } return item; } @@ -4302,6 +4367,49 @@ String *Item::check_well_formed_result(String *str, bool send_error) return str; } +/* + Compare two items using a given collation + + SYNOPSIS + eq_by_collation() + item item to compare with + binary_cmp TRUE <-> compare as binaries + cs collation to use when comparing strings + + DESCRIPTION + This method works exactly as Item::eq if the collation cs coincides with + the collation of the compared objects. Otherwise, first the collations that + differ from cs are replaced for cs and then the items are compared by + Item::eq. After the comparison the original collations of items are + restored. + + RETURN + 1 compared items has been detected as equal + 0 otherwise +*/ + +bool Item::eq_by_collation(Item *item, bool binary_cmp, CHARSET_INFO *cs) +{ + CHARSET_INFO *save_cs= 0; + CHARSET_INFO *save_item_cs= 0; + if (collation.collation != cs) + { + save_cs= collation.collation; + collation.collation= cs; + } + if (item->collation.collation != cs) + { + save_item_cs= item->collation.collation; + item->collation.collation= cs; + } + bool res= eq(item, binary_cmp); + if (save_cs) + collation.collation= save_cs; + if (save_item_cs) + item->collation.collation= save_item_cs; + return res; +} + /* Create a field to hold a string value from an item diff --git a/sql/item.h b/sql/item.h index 5f511557f47..a948c5a45f7 100644 --- a/sql/item.h +++ b/sql/item.h @@ -873,12 +873,30 @@ public: virtual Field::geometry_type get_geometry_type() const { return Field::GEOM_GEOMETRY; }; String *check_well_formed_result(String *str, bool send_error= 0); + bool eq_by_collation(Item *item, bool binary_cmp, CHARSET_INFO *cs); }; class sp_head; +class Item_basic_constant :public Item +{ +public: + /* to prevent drop fixed flag (no need parent cleanup call) */ + void cleanup() + { + /* + Restore the original field name as it might not have been allocated + in the statement memory. If the name is auto generated, it must be + done again between subsequent executions of a prepared statement. + */ + if (orig_name) + name= orig_name; + } +}; + + /***************************************************************************** The class is a base class for representation of stored routine variables in the Item-hierarchy. There are the following kinds of SP-vars: @@ -1113,14 +1131,7 @@ class Item_name_const : public Item Item *name_item; bool valid_args; public: - Item_name_const(Item *name_arg, Item *val): - value_item(val), name_item(name_arg) - { - if (!(valid_args= name_item->basic_const_item() & - value_item->basic_const_item())) - my_error(ER_WRONG_ARGUMENTS, MYF(0), "NAME_CONST"); - Item::maybe_null= TRUE; - } + Item_name_const(Item *name_arg, Item *val); bool fix_fields(THD *, Item **); @@ -1161,7 +1172,7 @@ bool agg_item_charsets(DTCollation &c, const char *name, Item **items, uint nitems, uint flags, int item_sep); -class Item_num: public Item +class Item_num: public Item_basic_constant { public: Item_num() {} /* Remove gcc warning */ @@ -1352,7 +1363,7 @@ public: friend class st_select_lex_unit; }; -class Item_null :public Item +class Item_null :public Item_basic_constant { public: Item_null(char *name_par=0) @@ -1374,8 +1385,6 @@ public: bool send(Protocol *protocol, String *str); enum Item_result result_type () const { return STRING_RESULT; } enum_field_types field_type() const { return MYSQL_TYPE_NULL; } - /* to prevent drop fixed flag (no need parent cleanup call) */ - void cleanup() {} bool basic_const_item() const { return 1; } Item *clone_item() { return new Item_null(name); } bool is_null() { return 1; } @@ -1402,8 +1411,6 @@ class Item_param :public Item char cnvbuf[MAX_FIELD_WIDTH]; String cnvstr; Item *cnvitem; - bool strict_type; - enum Item_result required_result_type; public: enum enum_item_param_state @@ -1533,11 +1540,8 @@ public: Otherwise return FALSE. */ bool eq(const Item *item, bool binary_cmp) const; - void set_strict_type(enum Item_result result_type_arg) - { - strict_type= TRUE; - required_result_type= result_type_arg; - } + /** Item is a argument to a limit clause. */ + bool limit_clause_param; }; @@ -1567,8 +1571,6 @@ public: int save_in_field(Field *field, bool no_conversions); bool basic_const_item() const { return 1; } Item *clone_item() { return new Item_int(name,value,max_length); } - // to prevent drop fixed flag (no need parent cleanup call) - void cleanup() {} void print(String *str); Item_num *neg() { value= -value; return this; } uint decimal_precision() const @@ -1621,8 +1623,6 @@ public: { return new Item_decimal(name, &decimal_value, decimals, max_length); } - // to prevent drop fixed flag (no need parent cleanup call) - void cleanup() {} void print(String *str); Item_num *neg() { @@ -1673,8 +1673,6 @@ public: String *val_str(String*); my_decimal *val_decimal(my_decimal *); bool basic_const_item() const { return 1; } - // to prevent drop fixed flag (no need parent cleanup call) - void cleanup() {} Item *clone_item() { return new Item_float(name, value, decimals, max_length); } Item_num *neg() { value= -value; return this; } @@ -1696,7 +1694,7 @@ public: }; -class Item_string :public Item +class Item_string :public Item_basic_constant { public: Item_string(const char *str,uint length, @@ -1780,8 +1778,6 @@ public: max_length= str_value.numchars() * collation.collation->mbmaxlen; } void print(String *str); - // to prevent drop fixed flag (no need parent cleanup call) - void cleanup() {} }; @@ -1839,10 +1835,10 @@ public: }; -class Item_hex_string: public Item +class Item_hex_string: public Item_basic_constant { public: - Item_hex_string(): Item() {} + Item_hex_string() {} Item_hex_string(const char *str,uint str_length); enum Type type() const { return VARBIN_ITEM; } double val_real() @@ -1858,8 +1854,6 @@ public: enum Item_result result_type () const { return STRING_RESULT; } enum Item_result cast_to_int_type() const { return INT_RESULT; } enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; } - // to prevent drop fixed flag (no need parent cleanup call) - void cleanup() {} void print(String *str); bool eq(const Item *item, bool binary_cmp) const; virtual Item *safe_charset_converter(CHARSET_INFO *tocs); @@ -1989,6 +1983,35 @@ public: Item_field *filed_for_view_update() { return (*ref)->filed_for_view_update(); } virtual Ref_Type ref_type() { return REF; } + + // Row emulation: forwarding of ROW-related calls to ref + uint cols() + { + return ref && result_type() == ROW_RESULT ? (*ref)->cols() : 1; + } + Item* element_index(uint i) + { + return ref && result_type() == ROW_RESULT ? (*ref)->element_index(i) : this; + } + Item** addr(uint i) + { + return ref && result_type() == ROW_RESULT ? (*ref)->addr(i) : 0; + } + bool check_cols(uint c) + { + return ref && result_type() == ROW_RESULT ? (*ref)->check_cols(c) + : Item::check_cols(c); + } + bool null_inside() + { + return ref && result_type() == ROW_RESULT ? (*ref)->null_inside() : 0; + } + void bring_value() + { + if (ref && result_type() == ROW_RESULT) + (*ref)->bring_value(); + } + }; @@ -2449,7 +2472,7 @@ private: }; -class Item_cache: public Item +class Item_cache: public Item_basic_constant { protected: Item *example; @@ -2486,8 +2509,6 @@ public: static Item_cache* get_cache(const Item *item); table_map used_tables() const { return used_table_map; } virtual void keep_array() {} - // to prevent drop fixed flag (no need parent cleanup call) - void cleanup() {} void print(String *str); bool eq_def(Field *field) { diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 98bcb256138..17345e76bba 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -2995,7 +2995,10 @@ void in_string::set(uint pos,Item *item) { if (res->uses_buffer_owned_by(str)) res->copy(); - *str= *res; + if (item->type() == Item::FUNC_ITEM) + str->copy(*res); + else + *str= *res; } if (!str->charset()) { diff --git a/sql/item_func.cc b/sql/item_func.cc index 639e069d24e..44b8ed998fe 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -3985,7 +3985,7 @@ double user_var_entry::val_real(my_bool *null_value) /* Get the value of a variable as an integer */ -longlong user_var_entry::val_int(my_bool *null_value) +longlong user_var_entry::val_int(my_bool *null_value) const { if ((*null_value= (value == 0))) return LL(0); @@ -5515,6 +5515,8 @@ Item_func_sp::make_field(Send_field *tmp_field) DBUG_ENTER("Item_func_sp::make_field"); DBUG_ASSERT(sp_result_field); sp_result_field->make_field(tmp_field); + if (name) + tmp_field->col_name= name; DBUG_VOID_RETURN; } diff --git a/sql/item_func.h b/sql/item_func.h index 940586fce01..6dcf32cba07 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -54,7 +54,8 @@ public: NOT_FUNC, NOT_ALL_FUNC, NOW_FUNC, TRIG_COND_FUNC, SUSERVAR_FUNC, GUSERVAR_FUNC, COLLATE_FUNC, - EXTRACT_FUNC, CHAR_TYPECAST_FUNC, FUNC_SP, UDF_FUNC }; + EXTRACT_FUNC, CHAR_TYPECAST_FUNC, FUNC_SP, UDF_FUNC, + NEG_FUNC }; enum optimize_type { OPTIMIZE_NONE,OPTIMIZE_KEY,OPTIMIZE_OP, OPTIMIZE_NULL, OPTIMIZE_EQUAL }; enum Type type() const { return FUNC_ITEM; } @@ -466,7 +467,7 @@ public: longlong int_op(); my_decimal *decimal_op(my_decimal *); const char *func_name() const { return "-"; } - virtual bool basic_const_item() const { return args[0]->basic_const_item(); } + enum Functype functype() const { return NEG_FUNC; } void fix_length_and_dec(); void fix_num_length_and_dec(); uint decimal_precision() const { return args[0]->decimal_precision(); } diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 3d261dc2c36..3d6d46ab3f4 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -597,6 +597,7 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref) result_field=0; null_value=1; fix_length_and_dec(); + item= item->real_item(); if (item->type() == Item::FIELD_ITEM) hybrid_field_type= ((Item_field*) item)->field->type(); else @@ -3459,6 +3460,6 @@ void Item_func_group_concat::print(String *str) Item_func_group_concat::~Item_func_group_concat() { - if (unique_filter) + if (!original && unique_filter) delete unique_filter; } diff --git a/sql/log.cc b/sql/log.cc index d1da900e1b5..15e8679171c 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -122,6 +122,20 @@ static int binlog_prepare(THD *thd, bool all) return 0; } +/** + This function is called once after each statement. + + It has the responsibility to flush the transaction cache to the + binlog file on commits. + + @param thd The client thread that executes the transaction. + @param all true if this is the last statement before a COMMIT + statement; false if either this is a statement in a + transaction but not the last, or if this is a statement + not inside a BEGIN block and autocommit is on. + + @see handlerton::commit +*/ static int binlog_commit(THD *thd, bool all) { IO_CACHE *trans_log= (IO_CACHE*)thd->ha_data[binlog_hton.slot]; @@ -134,7 +148,15 @@ static int binlog_commit(THD *thd, bool all) // we're here because trans_log was flushed in MYSQL_LOG::log_xid() DBUG_RETURN(0); } - if (all) + /* + Write commit event if at least one of the following holds: + - the user sends an explicit COMMIT; or + - the autocommit flag is on, and we are not inside a BEGIN. + However, if the user has not sent an explicit COMMIT, and we are + either inside a BEGIN or run with autocommit off, then this is not + the end of a transaction and we should not write a commit event. + */ + if (all || !(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), TRUE, FALSE); qev.error_code= 0; // see comment in MYSQL_LOG::write(THD, IO_CACHE) @@ -144,6 +166,22 @@ static int binlog_commit(THD *thd, bool all) DBUG_RETURN(binlog_end_trans(thd, trans_log, &invisible_commit)); } +/** + This function is called when a transaction involving a transactional + table is rolled back. + + It has the responsibility to flush the transaction cache to the + binlog file. However, if the transaction does not involve + non-transactional tables, nothing needs to be logged. + + @param thd The client thread that executes the transaction. + @param all true if this is the last statement before a COMMIT + statement; false if either this is a statement in a + transaction but not the last, or if this is a statement + not inside a BEGIN block and autocommit is on. + + @see handlerton::rollback +*/ static int binlog_rollback(THD *thd, bool all) { int error=0; @@ -1817,9 +1855,11 @@ uint MYSQL_LOG::next_file_id() IMPLEMENTATION - To support transaction over replication, we wrap the transaction with BEGIN/COMMIT or BEGIN/ROLLBACK in the binary log. - We want to write a BEGIN/ROLLBACK block when a non-transactional table - was updated in a transaction which was rolled back. This is to ensure - that the same updates are run on the slave. + If a transaction that only involves transactional tables is + rolled back, we do not binlog it. However, we write a + BEGIN/ROLLBACK block when a non-transactional table was updated + in a transaction which was rolled back. This is to ensure that + the same updates are run on the slave. */ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event) @@ -1837,32 +1877,34 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event) byte header[LOG_EVENT_HEADER_LEN]; /* - Log "BEGIN" at the beginning of the transaction. - which may contain more than 1 SQL statement. + Log "BEGIN" at the beginning of every transaction. Here, a + transaction is either a BEGIN..COMMIT block or a single + statement in autocommit mode. */ - if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) - { - Query_log_event qinfo(thd, STRING_WITH_LEN("BEGIN"), TRUE, FALSE); - /* - Imagine this is rollback due to net timeout, after all statements of - the transaction succeeded. Then we want a zero-error code in BEGIN. - In other words, if there was a really serious error code it's already - in the statement's events, there is no need to put it also in this - internally generated event, and as this event is generated late it - would lead to false alarms. - This is safer than thd->clear_error() against kills at shutdown. - */ - qinfo.error_code= 0; - /* - Now this Query_log_event has artificial log_pos 0. It must be adjusted - to reflect the real position in the log. Not doing it would confuse the - slave: it would prevent this one from knowing where he is in the - master's binlog, which would result in wrong positions being shown to - the user, MASTER_POS_WAIT undue waiting etc. - */ - if (qinfo.write(&log_file)) - goto err; - } + Query_log_event qinfo(thd, STRING_WITH_LEN("BEGIN"), TRUE, FALSE); + /* + Imagine this is rollback due to net timeout, after all + statements of the transaction succeeded. Then we want a + zero-error code in BEGIN. In other words, if there was a + really serious error code it's already in the statement's + events, there is no need to put it also in this internally + generated event, and as this event is generated late it would + lead to false alarms. + + This is safer than thd->clear_error() against kills at shutdown. + */ + qinfo.error_code= 0; + /* + Now this Query_log_event has artificial log_pos 0. It must be + adjusted to reflect the real position in the log. Not doing it + would confuse the slave: it would prevent this one from + knowing where he is in the master's binlog, which would result + in wrong positions being shown to the user, MASTER_POS_WAIT + undue waiting etc. + */ + if (qinfo.write(&log_file)) + goto err; + /* Read from the file used to cache the queries .*/ if (reinit_io_cache(cache, READ_CACHE, 0, 0, 0)) goto err; diff --git a/sql/log_event.cc b/sql/log_event.cc index d22973d12a3..a950094a018 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1862,7 +1862,7 @@ void Query_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) { print_query_header(file, print_event_info); my_fwrite(file, (byte*) query, q_len, MYF(MY_NABP | MY_WME)); - fprintf(file, "%s\n", print_event_info->delimiter); + fprintf(file, "\n%s\n", print_event_info->delimiter); } #endif /* MYSQL_CLIENT */ @@ -3793,6 +3793,7 @@ Xid_log_event(const char* buf, #ifndef MYSQL_CLIENT bool Xid_log_event::write(IO_CACHE* file) { + DBUG_EXECUTE_IF("do_not_write_xid", return 0;); return write_header(file, sizeof(xid)) || my_b_safe_write(file, (byte*) &xid, sizeof(xid)); } @@ -5180,12 +5181,12 @@ void Execute_load_query_log_event::print(FILE* file, fprintf(file, " INTO"); my_fwrite(file, (byte*) query + fn_pos_end, q_len-fn_pos_end, MYF(MY_NABP | MY_WME)); - fprintf(file, "%s\n", print_event_info->delimiter); + fprintf(file, "\n%s\n", print_event_info->delimiter); } else { my_fwrite(file, (byte*) query, q_len, MYF(MY_NABP | MY_WME)); - fprintf(file, "%s\n", print_event_info->delimiter); + fprintf(file, "\n%s\n", print_event_info->delimiter); } if (!print_event_info->short_form) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 4334dedfe4e..59ec18e1a3d 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -73,6 +73,7 @@ extern const char *primary_key_name; #include "mysql_com.h" #include <violite.h> #include "unireg.h" +#define IS_NUM(t) ((t) <= FIELD_TYPE_INT24 || (t) == FIELD_TYPE_YEAR || (t) == FIELD_TYPE_NEWDECIMAL) void init_sql_alloc(MEM_ROOT *root, uint block_size, uint pre_alloc_size); gptr sql_alloc(unsigned size); @@ -1254,6 +1255,7 @@ void my_dbopt_free(void); extern time_t server_start_time; extern char *mysql_data_home,server_version[SERVER_VERSION_LENGTH], mysql_real_data_home[], *opt_mysql_tmpdir, mysql_charsets_dir[], + mysql_unpacked_real_data_home[], def_ft_boolean_syntax[sizeof(ft_boolean_syntax)]; #define mysql_tmpdir (my_tmpdir(&mysql_tmpdir_list)) extern MY_TMPDIR mysql_tmpdir_list; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 693b72f5c98..b8df51e9e58 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -138,6 +138,13 @@ extern "C" { // Because of SCO 3.2V4.2 #include <sys/mman.h> #endif +#ifdef __WIN__ +#include <crtdbg.h> +#define SIGNAL_FMT "exception 0x%x" +#else +#define SIGNAL_FMT "signal %d" +#endif + #ifdef __NETWARE__ #define zVOLSTATE_ACTIVE 6 #define zVOLSTATE_DEACTIVE 2 @@ -227,6 +234,7 @@ inline void set_proper_floating_point_mode() extern "C" int gethostname(char *name, int namelen); #endif +extern "C" sig_handler handle_segfault(int sig); /* Constants */ @@ -467,14 +475,13 @@ char log_error_file[FN_REFLEN], glob_hostname[FN_REFLEN]; char mysql_real_data_home[FN_REFLEN], language[FN_REFLEN], reg_ext[FN_EXTLEN], mysql_charsets_dir[FN_REFLEN], *opt_init_file, *opt_tc_log_file, + mysql_unpacked_real_data_home[FN_REFLEN], def_ft_boolean_syntax[sizeof(ft_boolean_syntax)]; - +char *mysql_data_home= mysql_real_data_home; const key_map key_map_empty(0); key_map key_map_full(0); // Will be initialized later const char *opt_date_time_formats[3]; - -char *mysql_data_home= mysql_real_data_home; char server_version[SERVER_VERSION_LENGTH]; char *mysqld_unix_port, *opt_mysql_tmpdir; const char **errmesg; /* Error messages */ @@ -1031,9 +1038,6 @@ static void __cdecl kill_server(int sig_ptr) #endif close_connections(); if (sig != MYSQL_KILL_SIGNAL && -#ifdef __WIN__ - sig != SIGINT && /* Bug#18235 */ -#endif sig != 0) unireg_abort(1); /* purecov: inspected */ else @@ -1592,8 +1596,7 @@ static void network_init(void) FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL ); - MessageBox(NULL, (LPTSTR) lpMsgBuf, "Error from CreateNamedPipe", - MB_OK|MB_ICONINFORMATION); + sql_perror((char *)lpMsgBuf); LocalFree(lpMsgBuf); unireg_abort(1); } @@ -1796,17 +1799,163 @@ extern "C" sig_handler abort_thread(int sig __attribute__((unused))) ******************************************************************************/ -#if defined(__WIN__) || defined(OS2) +#if defined(__WIN__) + + +/* + On Windows, we use native SetConsoleCtrlHandler for handle events like Ctrl-C + with graceful shutdown. + Also, we do not use signal(), but SetUnhandledExceptionFilter instead - as it + provides possibility to pass the exception to just-in-time debugger, collect + dumps and potentially also the exception and thread context used to output + callstack. +*/ + +static BOOL WINAPI console_event_handler( DWORD type ) +{ + DBUG_ENTER("console_event_handler"); + if(type == CTRL_C_EVENT) + { + /* + Do not shutdown before startup is finished and shutdown + thread is initialized. Otherwise there is a race condition + between main thread doing initialization and CTRL-C thread doing + cleanup, which can result into crash. + */ + if(hEventShutdown) + kill_mysql(); + else + sql_print_warning("CTRL-C ignored during startup"); + DBUG_RETURN(TRUE); + } + DBUG_RETURN(FALSE); +} + + +/* + In Visual Studio 2005 and later, default SIGABRT handler will overwrite + any unhandled exception filter set by the application and will try to + call JIT debugger. This is not what we want, this we calling __debugbreak + to stop in debugger, if process is being debugged or to generate + EXCEPTION_BREAKPOINT and then handle_segfault will do its magic. +*/ + +#if (_MSC_VER >= 1400) +static void my_sigabrt_handler(int sig) +{ + __debugbreak(); +} +#endif /*_MSC_VER >=1400 */ + +void win_install_sigabrt_handler(void) +{ +#if (_MSC_VER >=1400) + /*abort() should not override our exception filter*/ + _set_abort_behavior(0,_CALL_REPORTFAULT); + signal(SIGABRT,my_sigabrt_handler); +#endif /* _MSC_VER >=1400 */ +} + +#ifdef DEBUG_UNHANDLED_EXCEPTION_FILTER +#define DEBUGGER_ATTACH_TIMEOUT 120 +/* + Wait for debugger to attach and break into debugger. If debugger is not attached, + resume after timeout. +*/ +static void wait_for_debugger(int timeout_sec) +{ + if(!IsDebuggerPresent()) + { + int i; + printf("Waiting for debugger to attach, pid=%u\n",GetCurrentProcessId()); + fflush(stdout); + for(i= 0; i < timeout_sec; i++) + { + Sleep(1000); + if(IsDebuggerPresent()) + { + /* Break into debugger */ + __debugbreak(); + return; + } + } + printf("pid=%u, debugger not attached after %d seconds, resuming\n",GetCurrentProcessId(), + timeout_sec); + fflush(stdout); + } +} +#endif /* DEBUG_UNHANDLED_EXCEPTION_FILTER */ + +LONG WINAPI my_unhandler_exception_filter(EXCEPTION_POINTERS *ex_pointers) +{ + static BOOL first_time= TRUE; + if(!first_time) + { + /* + This routine can be called twice, typically + when detaching in JIT debugger. + Return EXCEPTION_EXECUTE_HANDLER to terminate process. + */ + return EXCEPTION_EXECUTE_HANDLER; + } + first_time= FALSE; +#ifdef DEBUG_UNHANDLED_EXCEPTION_FILTER + /* + Unfortunately there is no clean way to debug unhandled exception filters, + as debugger does not stop there(also documented in MSDN) + To overcome, one could put a MessageBox, but this will not work in service. + Better solution is to print error message and sleep some minutes + until debugger is attached + */ + wait_for_debugger(DEBUGGER_ATTACH_TIMEOUT); +#endif /* DEBUG_UNHANDLED_EXCEPTION_FILTER */ + __try + { + set_exception_pointers(ex_pointers); + handle_segfault(ex_pointers->ExceptionRecord->ExceptionCode); + } + __except(EXCEPTION_EXECUTE_HANDLER) + { + DWORD written; + const char msg[] = "Got exception in exception handler!\n"; + WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),msg, sizeof(msg)-1, + &written,NULL); + } + /* + Return EXCEPTION_CONTINUE_SEARCH to give JIT debugger + (drwtsn32 or vsjitdebugger) possibility to attach, + if JIT debugger is configured. + Windows Error reporting might generate a dump here. + */ + return EXCEPTION_CONTINUE_SEARCH; +} + + static void init_signals(void) { - int signals[] = {SIGINT,SIGILL,SIGFPE,SIGSEGV,SIGTERM,SIGABRT } ; - for (uint i=0 ; i < sizeof(signals)/sizeof(int) ; i++) - signal(signals[i], kill_server) ; -#if defined(__WIN__) - signal(SIGBREAK,SIG_IGN); //ignore SIGBREAK for NT -#else - signal(SIGBREAK, kill_server); -#endif + win_install_sigabrt_handler(); + if(opt_console) + SetConsoleCtrlHandler(console_event_handler,TRUE); + else + { + /* Avoid MessageBox()es*/ + _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); + _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); + _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + + /* + Do not use SEM_NOGPFAULTERRORBOX in the following SetErrorMode (), + because it would prevent JIT debugger and Windows error reporting + from working. We need WER or JIT-debugging, since our own unhandled + exception filter is not guaranteed to work in all situation + (like heap corruption or stack overflow) + */ + SetErrorMode(SetErrorMode(0)|SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX); + } + SetUnhandledExceptionFilter(my_unhandler_exception_filter); } static void start_signal_handler(void) @@ -2094,8 +2243,8 @@ static void start_signal_handler(void) static void check_data_home(const char *path) {} +#endif /*__WIN__ || __NETWARE || __EMX__*/ -#else /* if ! __WIN__ && ! __EMX__ */ #ifdef HAVE_LINUXTHREADS #define UNSAFE_DEFAULT_LINUX_THREADS 200 @@ -2115,7 +2264,7 @@ extern "C" sig_handler handle_segfault(int sig) */ if (segfaulted) { - fprintf(stderr, "Fatal signal %d while backtracing\n", sig); + fprintf(stderr, "Fatal " SIGNAL_FMT " while backtracing\n", sig); exit(1); } @@ -2125,7 +2274,7 @@ extern "C" sig_handler handle_segfault(int sig) localtime_r(&curr_time, &tm); fprintf(stderr,"\ -%02d%02d%02d %2d:%02d:%02d - mysqld got signal %d;\n\ +%02d%02d%02d %2d:%02d:%02d - mysqld got " SIGNAL_FMT " ;\n\ This could be because you hit a bug. It is also possible that this binary\n\ or one of the libraries it was linked against is corrupt, improperly built,\n\ or misconfigured. This error can also be caused by malfunctioning hardware.\n", @@ -2166,6 +2315,10 @@ the thread stack. Please read http://dev.mysql.com/doc/mysql/en/linux.html\n\n", if (!(test_flags & TEST_NO_STACKTRACE)) { fprintf(stderr,"thd=%p\n",thd); + fprintf(stderr,"\ +Attempting backtrace. You can use the following information to find out\n\ +where mysqld died. If you see no messages after this, something went\n\ +terribly wrong...\n"); print_stacktrace(thd ? (gptr) thd->thread_stack : (gptr) 0, thread_stack); } @@ -2214,15 +2367,22 @@ of those buggy OS calls. You should consider whether you really need the\n\ bugs.\n"); } +#ifdef HAVE_WRITE_CORE if (test_flags & TEST_CORE_ON_SIGNAL) { fprintf(stderr, "Writing a core file\n"); fflush(stderr); write_core(sig); } +#endif + +#ifndef __WIN__ + /* On Windows, do not terminate, but pass control to exception filter */ exit(1); +#endif } +#if !defined(__WIN__) && !defined(__NETWARE__) && !defined(__EMX__) #ifndef SA_RESETHAND #define SA_RESETHAND 0 #endif @@ -2238,10 +2398,6 @@ static void init_signals(void) struct sigaction sa; DBUG_ENTER("init_signals"); - if (test_flags & TEST_SIGINT) - { - my_sigset(thr_kill_signal, end_thread_signal); - } my_sigset(THR_SERVER_ALARM,print_signal_warning); // Should never be called! if (!(test_flags & TEST_NO_STACKTRACE) || (test_flags & TEST_CORE_ON_SIGNAL)) @@ -2278,7 +2434,6 @@ static void init_signals(void) (void) sigemptyset(&set); my_sigset(SIGPIPE,SIG_IGN); sigaddset(&set,SIGPIPE); - sigaddset(&set,SIGINT); #ifndef IGNORE_SIGHUP_SIGQUIT sigaddset(&set,SIGQUIT); sigaddset(&set,SIGHUP); @@ -2300,9 +2455,12 @@ static void init_signals(void) sigaddset(&set,THR_SERVER_ALARM); if (test_flags & TEST_SIGINT) { + my_sigset(thr_kill_signal, end_thread_signal); // May be SIGINT sigdelset(&set, thr_kill_signal); } + else + sigaddset(&set,SIGINT); sigprocmask(SIG_SETMASK,&set,NULL); pthread_sigmask(SIG_SETMASK,&set,NULL); DBUG_VOID_RETURN; @@ -2567,19 +2725,6 @@ static void my_str_free_mysqld(void *ptr) #ifdef __WIN__ - -struct utsname -{ - char nodename[FN_REFLEN]; -}; - - -int uname(struct utsname *a) -{ - return -1; -} - - pthread_handler_t handle_shutdown(void *arg) { MSG msg; @@ -2593,18 +2738,6 @@ pthread_handler_t handle_shutdown(void *arg) kill_server(MYSQL_KILL_SIGNAL); return 0; } - - -int STDCALL handle_kill(ulong ctrl_type) -{ - if (ctrl_type == CTRL_CLOSE_EVENT || - ctrl_type == CTRL_SHUTDOWN_EVENT) - { - kill_server(MYSQL_KILL_SIGNAL); - return TRUE; - } - return FALSE; -} #endif @@ -3633,11 +3766,6 @@ we force server id to 2, but this MySQL server will not act as a slave."); freopen(log_error_file,"a+",stderr); FreeConsole(); // Remove window } - else - { - /* Don't show error dialog box when on foreground: it stops the server */ - SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS); - } #endif /* @@ -5798,7 +5926,7 @@ log and this option does nothing anymore.", "Data file autoextend increment in megabytes", (gptr*) &srv_auto_extend_increment, (gptr*) &srv_auto_extend_increment, - 0, GET_LONG, REQUIRED_ARG, 8L, 1L, 1000L, 0, 1L, 0}, + 0, GET_ULONG, REQUIRED_ARG, 8L, 1L, 1000L, 0, 1L, 0}, {"innodb_buffer_pool_awe_mem_mb", OPT_INNODB_BUFFER_POOL_AWE_MEM_MB, "If Windows AWE is used, the size of InnoDB buffer pool allocated from the AWE memory.", (gptr*) &innobase_buffer_pool_awe_mem_mb, (gptr*) &innobase_buffer_pool_awe_mem_mb, 0, @@ -5811,7 +5939,7 @@ log and this option does nothing anymore.", {"innodb_commit_concurrency", OPT_INNODB_COMMIT_CONCURRENCY, "Helps in performance tuning in heavily concurrent environments.", (gptr*) &srv_commit_concurrency, (gptr*) &srv_commit_concurrency, - 0, GET_LONG, REQUIRED_ARG, 0, 0, 1000, 0, 1, 0}, + 0, GET_ULONG, REQUIRED_ARG, 0, 0, 1000, 0, 1, 0}, {"innodb_concurrency_tickets", OPT_INNODB_CONCURRENCY_TICKETS, "Number of times a thread is allowed to enter InnoDB within the same \ SQL query after it has once got the ticket", @@ -7611,6 +7739,9 @@ static void fix_paths(void) pos[1]= 0; } convert_dirname(mysql_real_data_home,mysql_real_data_home,NullS); + (void) fn_format(buff, mysql_real_data_home, "", "", + (MY_RETURN_REAL_PATH|MY_RESOLVE_SYMLINKS)); + (void) unpack_dirname(mysql_unpacked_real_data_home, buff); convert_dirname(language,language,NullS); (void) my_load_path(mysql_home,mysql_home,""); // Resolve current dir (void) my_load_path(mysql_real_data_home,mysql_real_data_home,mysql_home); diff --git a/sql/set_var.cc b/sql/set_var.cc index d0362edaa29..a99b063a97e 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -113,8 +113,7 @@ static int check_max_delayed_threads(THD *thd, set_var *var); static void fix_thd_mem_root(THD *thd, enum_var_type type); static void fix_trans_mem_root(THD *thd, enum_var_type type); static void fix_server_id(THD *thd, enum_var_type type); -static ulonglong fix_unsigned(THD *thd, ulonglong num, - const struct my_option *option_limits); +static ulonglong fix_unsigned(THD *, ulonglong, const struct my_option *); static bool get_unsigned(THD *thd, set_var *var); static void throw_bounds_warning(THD *thd, const char *name, ulonglong num); static KEY_CACHE *create_key_cache(const char *name, uint length); @@ -1449,6 +1448,7 @@ static void fix_trans_mem_root(THD *thd, enum_var_type type) static void fix_server_id(THD *thd, enum_var_type type) { server_id_supplied = 1; + thd->server_id= server_id; } @@ -1524,8 +1524,10 @@ bool sys_var_long_ptr_global::update(THD *thd, set_var *var) void sys_var_long_ptr_global::set_default(THD *thd, enum_var_type type) { + bool not_used; pthread_mutex_lock(guard); - *value= (ulong) option_limits->def_value; + *value= (ulong) getopt_ull_limit_value((ulong) option_limits->def_value, + option_limits, ¬_used); pthread_mutex_unlock(guard); } @@ -1545,8 +1547,10 @@ bool sys_var_ulonglong_ptr::update(THD *thd, set_var *var) void sys_var_ulonglong_ptr::set_default(THD *thd, enum_var_type type) { + bool not_used; pthread_mutex_lock(&LOCK_global_system_variables); - *value= (ulonglong) option_limits->def_value; + *value= getopt_ull_limit_value((ulonglong) option_limits->def_value, + option_limits, ¬_used); pthread_mutex_unlock(&LOCK_global_system_variables); } @@ -1616,8 +1620,11 @@ void sys_var_thd_ulong::set_default(THD *thd, enum_var_type type) { if (type == OPT_GLOBAL) { + bool not_used; /* We will not come here if option_limits is not set */ - global_system_variables.*offset= (ulong) option_limits->def_value; + global_system_variables.*offset= + (ulong) getopt_ull_limit_value((ulong) option_limits->def_value, + option_limits, ¬_used); } else thd->variables.*offset= global_system_variables.*offset; @@ -1660,9 +1667,12 @@ void sys_var_thd_ha_rows::set_default(THD *thd, enum_var_type type) { if (type == OPT_GLOBAL) { + bool not_used; /* We will not come here if option_limits is not set */ pthread_mutex_lock(&LOCK_global_system_variables); - global_system_variables.*offset= (ha_rows) option_limits->def_value; + global_system_variables.*offset= + (ha_rows) getopt_ull_limit_value((ha_rows) option_limits->def_value, + option_limits, ¬_used); pthread_mutex_unlock(&LOCK_global_system_variables); } else @@ -1709,8 +1719,11 @@ void sys_var_thd_ulonglong::set_default(THD *thd, enum_var_type type) { if (type == OPT_GLOBAL) { + bool not_used; pthread_mutex_lock(&LOCK_global_system_variables); - global_system_variables.*offset= (ulonglong) option_limits->def_value; + global_system_variables.*offset= + getopt_ull_limit_value((ulonglong) option_limits->def_value, + option_limits, ¬_used); pthread_mutex_unlock(&LOCK_global_system_variables); } else diff --git a/sql/slave.cc b/sql/slave.cc index 1509916fe91..8a3620080f2 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2447,14 +2447,15 @@ bool show_master_info(THD* thd, MASTER_INFO* mi) protocol->prepare_for_resend(); /* - TODO: we read slave_running without run_lock, whereas these variables - are updated under run_lock and not data_lock. In 5.0 we should lock - run_lock on top of data_lock (with good order). + slave_running can be accessed without run_lock but not other + non-volotile members like mi->io_thd, which is guarded by the mutex. */ + pthread_mutex_lock(&mi->run_lock); + protocol->store(mi->io_thd ? mi->io_thd->proc_info : "", &my_charset_bin); + pthread_mutex_unlock(&mi->run_lock); + pthread_mutex_lock(&mi->data_lock); pthread_mutex_lock(&mi->rli.data_lock); - - protocol->store(mi->io_thd ? mi->io_thd->proc_info : "", &my_charset_bin); protocol->store(mi->host, &my_charset_bin); protocol->store(mi->user, &my_charset_bin); protocol->store((uint32) mi->port); @@ -3348,7 +3349,10 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) if (rli->slave_skip_counter && !((type_code == INTVAR_EVENT || type_code == RAND_EVENT || - type_code == USER_VAR_EVENT) && + type_code == USER_VAR_EVENT || + type_code == BEGIN_LOAD_QUERY_EVENT || + type_code == APPEND_BLOCK_EVENT || + type_code == CREATE_FILE_EVENT) && rli->slave_skip_counter == 1) && #if MYSQL_VERSION_ID < 50100 /* diff --git a/sql/slave.h b/sql/slave.h index e7d4456ccd9..c61787cdf3b 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -65,8 +65,8 @@ mi->rli does not either. In MASTER_INFO: run_lock, data_lock - run_lock protects all information about the run state: slave_running, and the - existence of the I/O thread (to stop/start it, you need this mutex). + run_lock protects all information about the run state: slave_running, thd + and the existence of the I/O thread to stop/start it, you need this mutex). data_lock protects some moving members of the struct: counters (log name, position) and relay log (MYSQL_LOG object). diff --git a/sql/sp.cc b/sql/sp.cc index f8b039626f9..7224d3c4f0e 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -261,6 +261,7 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp) char buff[65]; String str(buff, sizeof(buff), &my_charset_bin); ulong sql_mode; + bool saved_time_zone_used= thd->time_zone_used; Open_tables_state open_tables_state_backup; DBUG_ENTER("db_find_routine"); DBUG_PRINT("enter", ("type: %d name: %.*s", @@ -370,6 +371,11 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp) definer, created, modified); done: + /* + Restore the time zone flag as the timezone usage in proc table + does not affect replication. + */ + thd->time_zone_used= saved_time_zone_used; if (table) close_proc_table(thd, &open_tables_state_backup); DBUG_RETURN(ret); diff --git a/sql/sp_head.cc b/sql/sp_head.cc index e8ddacb820e..46f3d25c441 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1933,11 +1933,17 @@ sp_head::backpatch(sp_label_t *lab) uint dest= instructions(); List_iterator_fast<bp_t> li(m_backpatch); + DBUG_ENTER("sp_head::backpatch"); while ((bp= li++)) { if (bp->lab == lab) + { + DBUG_PRINT("info", ("backpatch: (m_ip %d, label 0x%lx <%s>) to dest %d", + bp->instr->m_ip, (ulong) lab, lab->name, dest)); bp->instr->backpatch(dest, lab->ctx); + } } + DBUG_VOID_RETURN; } /* diff --git a/sql/sp_head.h b/sql/sp_head.h index a46ec9433d7..0e710196603 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -779,8 +779,9 @@ public: virtual void backpatch(uint dest, sp_pcontext *dst_ctx) { - if (m_dest == 0) // Don't reset - m_dest= dest; + /* Calling backpatch twice is a logic flaw in jump resolution. */ + DBUG_ASSERT(m_dest == 0); + m_dest= dest; } /* diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc index 54e016f6099..129aaa46de6 100644 --- a/sql/sp_rcontext.cc +++ b/sql/sp_rcontext.cc @@ -334,17 +334,91 @@ sp_rcontext::handle_error(uint sql_errno, void sp_rcontext::push_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i) { + DBUG_ENTER("sp_rcontext::push_cursor"); + DBUG_ASSERT(m_ccount < m_root_parsing_ctx->max_cursor_index()); m_cstack[m_ccount++]= new sp_cursor(lex_keeper, i); + DBUG_PRINT("info", ("m_ccount: %d", m_ccount)); + DBUG_VOID_RETURN; } - void sp_rcontext::pop_cursors(uint count) { + DBUG_ENTER("sp_rcontext::pop_cursors"); + DBUG_ASSERT(m_ccount >= count); while (count--) { delete m_cstack[--m_ccount]; } + DBUG_PRINT("info", ("m_ccount: %d", m_ccount)); + DBUG_VOID_RETURN; +} + +void +sp_rcontext::push_handler(struct sp_cond_type *cond, uint h, int type, uint f) +{ + DBUG_ENTER("sp_rcontext::push_handler"); + DBUG_ASSERT(m_hcount < m_root_parsing_ctx->max_handler_index()); + + m_handler[m_hcount].cond= cond; + m_handler[m_hcount].handler= h; + m_handler[m_hcount].type= type; + m_handler[m_hcount].foffset= f; + m_hcount+= 1; + + DBUG_PRINT("info", ("m_hcount: %d", m_hcount)); + DBUG_VOID_RETURN; +} + +void +sp_rcontext::pop_handlers(uint count) +{ + DBUG_ENTER("sp_rcontext::pop_handlers"); + DBUG_ASSERT(m_hcount >= count); + m_hcount-= count; + DBUG_PRINT("info", ("m_hcount: %d", m_hcount)); + DBUG_VOID_RETURN; +} + +void +sp_rcontext::push_hstack(uint h) +{ + DBUG_ENTER("sp_rcontext::push_hstack"); + DBUG_ASSERT(m_hsp < m_root_parsing_ctx->max_handler_index()); + m_hstack[m_hsp++]= h; + DBUG_PRINT("info", ("m_hsp: %d", m_hsp)); + DBUG_VOID_RETURN; +} + +uint +sp_rcontext::pop_hstack() +{ + uint handler; + DBUG_ENTER("sp_rcontext::pop_hstack"); + DBUG_ASSERT(m_hsp); + handler= m_hstack[--m_hsp]; + DBUG_PRINT("info", ("m_hsp: %d", m_hsp)); + DBUG_RETURN(handler); +} + +void +sp_rcontext::enter_handler(int hid) +{ + DBUG_ENTER("sp_rcontext::enter_handler"); + DBUG_ASSERT(m_ihsp < m_root_parsing_ctx->max_handler_index()); + m_in_handler[m_ihsp++]= hid; + DBUG_PRINT("info", ("m_ihsp: %d", m_ihsp)); + DBUG_VOID_RETURN; +} + +void +sp_rcontext::exit_handler() +{ + DBUG_ENTER("sp_rcontext::exit_handler"); + DBUG_ASSERT(m_ihsp); + m_ihsp-= 1; + DBUG_PRINT("info", ("m_ihsp: %d", m_ihsp)); + DBUG_VOID_RETURN; } diff --git a/sql/sp_rcontext.h b/sql/sp_rcontext.h index 43102cfeeb2..368a017da21 100644 --- a/sql/sp_rcontext.h +++ b/sql/sp_rcontext.h @@ -107,21 +107,9 @@ class sp_rcontext : public Sql_alloc return m_return_value_set; } - inline void - push_handler(struct sp_cond_type *cond, uint h, int type, uint f) - { - m_handler[m_hcount].cond= cond; - m_handler[m_hcount].handler= h; - m_handler[m_hcount].type= type; - m_handler[m_hcount].foffset= f; - m_hcount+= 1; - } + void push_handler(struct sp_cond_type *cond, uint h, int type, uint f); - inline void - pop_handlers(uint count) - { - m_hcount-= count; - } + void pop_handlers(uint count); // Returns 1 if a handler was found, 0 otherwise. bool @@ -158,29 +146,13 @@ class sp_rcontext : public Sql_alloc m_hfound= -1; } - inline void - push_hstack(uint h) - { - m_hstack[m_hsp++]= h; - } + void push_hstack(uint h); - inline uint - pop_hstack() - { - return m_hstack[--m_hsp]; - } + uint pop_hstack(); - inline void - enter_handler(int hid) - { - m_in_handler[m_ihsp++]= hid; - } + void enter_handler(int hid); - inline void - exit_handler() - { - m_ihsp-= 1; - } + void exit_handler(); void push_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 134541368e9..e9504f423ad 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -668,7 +668,9 @@ static ulong get_sort(uint count,...) { for (; *str ; str++) { - if (*str == wild_many || *str == wild_one || *str == wild_prefix) + if (*str == wild_prefix && str[1]) + str++; + else if (*str == wild_many || *str == wild_one) { wild_pos= (uint) (str - start) + 1; break; @@ -5333,6 +5335,7 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list) LEX_USER *user_name, *tmp_user_name; List_iterator <LEX_USER> user_list(list); TABLE_LIST tables[GRANT_TABLES]; + bool some_users_created= FALSE; DBUG_ENTER("mysql_create_user"); /* CREATE USER may be skipped on replication client. */ @@ -5361,6 +5364,7 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list) continue; } + some_users_created= TRUE; sql_mode= thd->variables.sql_mode; if (replace_user_table(thd, tables[0].table, *user_name, 0, 0, 1, 0)) { @@ -5371,7 +5375,10 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list) VOID(pthread_mutex_unlock(&acl_cache->lock)); - if (mysql_bin_log.is_open()) + if (result) + my_error(ER_CANNOT_USER, MYF(0), "CREATE USER", wrong_users.c_ptr_safe()); + + if (some_users_created && mysql_bin_log.is_open()) { Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); mysql_bin_log.write(&qinfo); @@ -5379,8 +5386,6 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list) rw_unlock(&LOCK_grant); close_thread_tables(thd); - if (result) - my_error(ER_CANNOT_USER, MYF(0), "CREATE USER", wrong_users.c_ptr_safe()); DBUG_RETURN(result); } @@ -5405,6 +5410,7 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list) LEX_USER *user_name, *tmp_user_name; List_iterator <LEX_USER> user_list(list); TABLE_LIST tables[GRANT_TABLES]; + bool some_users_deleted= FALSE; DBUG_ENTER("mysql_drop_user"); /* DROP USER may be skipped on replication client. */ @@ -5426,7 +5432,9 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list) { append_user(&wrong_users, user_name); result= TRUE; + continue; } + some_users_deleted= TRUE; } /* Rebuild 'acl_check_hosts' since 'acl_users' has been modified */ @@ -5440,7 +5448,7 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list) DBUG_PRINT("info", ("thd->net.last_errno: %d", thd->net.last_errno)); DBUG_PRINT("info", ("thd->net.last_error: %s", thd->net.last_error)); - if (mysql_bin_log.is_open()) + if (some_users_deleted && mysql_bin_log.is_open()) { Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); mysql_bin_log.write(&qinfo); @@ -5473,6 +5481,7 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list) LEX_USER *user_to, *tmp_user_to; List_iterator <LEX_USER> user_list(list); TABLE_LIST tables[GRANT_TABLES]; + bool some_users_renamed= FALSE; DBUG_ENTER("mysql_rename_user"); /* RENAME USER may be skipped on replication client. */ @@ -5506,7 +5515,9 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list) { append_user(&wrong_users, user_from); result= TRUE; + continue; } + some_users_renamed= TRUE; } /* Rebuild 'acl_check_hosts' since 'acl_users' has been modified */ @@ -5514,7 +5525,10 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list) VOID(pthread_mutex_unlock(&acl_cache->lock)); - if (mysql_bin_log.is_open()) + if (result) + my_error(ER_CANNOT_USER, MYF(0), "RENAME USER", wrong_users.c_ptr_safe()); + + if (some_users_renamed && mysql_bin_log.is_open()) { Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); mysql_bin_log.write(&qinfo); @@ -5522,8 +5536,6 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list) rw_unlock(&LOCK_grant); close_thread_tables(thd); - if (result) - my_error(ER_CANNOT_USER, MYF(0), "RENAME USER", wrong_users.c_ptr_safe()); DBUG_RETURN(result); } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 8190b3eeacd..c9f20b3d71b 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2852,8 +2852,12 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags) } if (tables->lock_type != TL_UNLOCK && ! thd->locked_tables) - tables->table->reginfo.lock_type= tables->lock_type == TL_WRITE_DEFAULT ? - thd->update_lock_default : tables->lock_type; + { + if (tables->lock_type == TL_WRITE_DEFAULT) + tables->table->reginfo.lock_type= thd->update_lock_default; + else if (tables->table->s->tmp_table == NO_TMP_TABLE) + tables->table->reginfo.lock_type= tables->lock_type; + } tables->table->grant= tables->grant; process_view_routines: diff --git a/sql/sql_class.h b/sql/sql_class.h index 97f2d07b1d3..4ca8947de30 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2329,7 +2329,7 @@ class user_var_entry bool unsigned_flag; double val_real(my_bool *null_value); - longlong val_int(my_bool *null_value); + longlong val_int(my_bool *null_value) const; String *val_str(my_bool *null_value, String *str, uint decimals); my_decimal *val_decimal(my_bool *null_value, my_decimal *result); DTCollation collation; diff --git a/sql/sql_cursor.cc b/sql/sql_cursor.cc index 2e98da42be1..c2345f1f2cd 100644 --- a/sql/sql_cursor.cc +++ b/sql/sql_cursor.cc @@ -88,6 +88,7 @@ class Materialized_cursor: public Server_side_cursor public: Materialized_cursor(select_result *result, TABLE *table); + int fill_item_list(THD *thd, List<Item> &send_fields); virtual bool is_open() const { return table != 0; } virtual int open(JOIN *join __attribute__((unused))); virtual void fetch(ulong num_rows); @@ -109,6 +110,7 @@ class Select_materialize: public select_union { select_result *result; /* the result object of the caller (PS or SP) */ public: + Materialized_cursor *materialized_cursor; Select_materialize(select_result *result_arg) :result(result_arg) {} virtual bool send_fields(List<Item> &list, uint flags); }; @@ -152,7 +154,7 @@ int mysql_open_cursor(THD *thd, uint flags, select_result *result, if (! (sensitive_cursor= new (thd->mem_root) Sensitive_cursor(thd, result))) { - delete result; + delete result_materialize; return 1; } @@ -174,13 +176,13 @@ int mysql_open_cursor(THD *thd, uint flags, select_result *result, /* Possible options here: - a sensitive cursor is open. In this case rc is 0 and - result_materialize->table is NULL, or + result_materialize->materialized_cursor is NULL, or - a materialized cursor is open. In this case rc is 0 and - result_materialize->table is not NULL - - an error occured during materializaton. - result_materialize->table is not NULL, but rc != 0 + result_materialize->materialized is not NULL + - an error occurred during materialization. + result_materialize->materialized_cursor is not NULL, but rc != 0 - successful completion of mysql_execute_command without - a cursor: rc is 0, result_materialize->table is NULL, + a cursor: rc is 0, result_materialize->materialized_cursor is NULL, sensitive_cursor is not open. This is possible if some command writes directly to the network, bypassing select_result mechanism. An example of @@ -191,7 +193,7 @@ int mysql_open_cursor(THD *thd, uint flags, select_result *result, if (sensitive_cursor->is_open()) { - DBUG_ASSERT(!result_materialize->table); + DBUG_ASSERT(!result_materialize->materialized_cursor); /* It's safer if we grab THD state after mysql_execute_command is finished and not in Sensitive_cursor::open(), because @@ -202,18 +204,10 @@ int mysql_open_cursor(THD *thd, uint flags, select_result *result, *pcursor= sensitive_cursor; goto end; } - else if (result_materialize->table) + else if (result_materialize->materialized_cursor) { - Materialized_cursor *materialized_cursor; - TABLE *table= result_materialize->table; - MEM_ROOT *mem_root= &table->mem_root; - - if (!(materialized_cursor= new (mem_root) - Materialized_cursor(result, table))) - { - rc= 1; - goto err_open; - } + Materialized_cursor *materialized_cursor= + result_materialize->materialized_cursor; if ((rc= materialized_cursor->open(0))) { @@ -229,8 +223,6 @@ int mysql_open_cursor(THD *thd, uint flags, select_result *result, err_open: DBUG_ASSERT(! (sensitive_cursor && sensitive_cursor->is_open())); delete sensitive_cursor; - if (result_materialize->table) - free_tmp_table(thd, result_materialize->table); end: delete result_materialize; return rc; @@ -544,6 +536,51 @@ Materialized_cursor::Materialized_cursor(select_result *result_arg, } +/** + Preserve the original metadata that would be sent to the client. + + @param thd Thread identifier. + @param send_fields List of fields that would be sent. +*/ + +int Materialized_cursor::fill_item_list(THD *thd, List<Item> &send_fields) +{ + Query_arena backup_arena; + int rc; + List_iterator_fast<Item> it_org(send_fields); + List_iterator_fast<Item> it_dst(item_list); + Item *item_org; + Item *item_dst; + + thd->set_n_backup_active_arena(this, &backup_arena); + + if ((rc= table->fill_item_list(&item_list))) + goto end; + + DBUG_ASSERT(send_fields.elements == item_list.elements); + + /* + Unless we preserve the original metadata, it will be lost, + since new fields describe columns of the temporary table. + Allocate a copy of the name for safety only. Currently + items with original names are always kept in memory, + but in case this changes a memory leak may be hard to notice. + */ + while ((item_dst= it_dst++, item_org= it_org++)) + { + Send_field send_field; + Item_ident *ident= static_cast<Item_ident *>(item_dst); + item_org->make_field(&send_field); + + ident->db_name= thd->strdup(send_field.db_name); + ident->table_name= thd->strdup(send_field.table_name); + } +end: + thd->restore_active_arena(this, &backup_arena); + /* Check for thd->is_error() in case of OOM */ + return rc || thd->net.report_error; +} + int Materialized_cursor::open(JOIN *join __attribute__((unused))) { THD *thd= fake_unit.thd; @@ -552,8 +589,7 @@ int Materialized_cursor::open(JOIN *join __attribute__((unused))) thd->set_n_backup_active_arena(this, &backup_arena); /* Create a list of fields and start sequential scan */ - rc= (table->fill_item_list(&item_list) || - result->prepare(item_list, &fake_unit) || + rc= (result->prepare(item_list, &fake_unit) || table->file->ha_rnd_init(TRUE)); thd->restore_active_arena(this, &backup_arena); if (rc == 0) @@ -664,6 +700,24 @@ bool Select_materialize::send_fields(List<Item> &list, uint flags) if (create_result_table(unit->thd, unit->get_unit_column_types(), FALSE, thd->options | TMP_TABLE_ALL_COLUMNS, "")) return TRUE; + + materialized_cursor= new (&table->mem_root) + Materialized_cursor(result, table); + + if (! materialized_cursor) + { + free_tmp_table(table->in_use, table); + table= 0; + return TRUE; + } + if (materialized_cursor->fill_item_list(unit->thd, list)) + { + delete materialized_cursor; + table= 0; + materialized_cursor= 0; + return TRUE; + } + return FALSE; } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 14292f1cd9d..1d324872409 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -3006,7 +3006,8 @@ bool select_insert::send_eof() ((thd->client_capabilities & CLIENT_FOUND_ROWS) ? info.touched : info.updated); id= autoinc_value_of_first_inserted_row > 0 ? - autoinc_value_of_first_inserted_row : thd->last_insert_id; + autoinc_value_of_first_inserted_row : thd->insert_id_used ? + thd->last_insert_id : 0; ::send_ok(thd, (ulong) thd->row_count_func, id, buff); DBUG_RETURN(0); } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 8af79d77fa1..8bdbd812529 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -76,6 +76,7 @@ static void remove_escape(char *name); static bool append_file_to_dir(THD *thd, const char **filename_ptr, const char *table_name); static bool check_show_create_table_access(THD *thd, TABLE_LIST *table); +static bool test_if_data_home_dir(const char *dir); const char *any_db="*any*"; // Special symbol for check_access @@ -98,22 +99,7 @@ static bool do_command(THD *thd); #endif // EMBEDDED_LIBRARY #ifdef __WIN__ -static void test_signal(int sig_ptr) -{ -#if !defined( DBUG_OFF) - MessageBox(NULL,"Test signal","DBUG",MB_OK); -#endif -#if defined(OS2) - fprintf(stderr, "Test signal %d\n", sig_ptr); - fflush(stderr); -#endif -} -static void init_signals(void) -{ - int signals[7] = {SIGINT,SIGILL,SIGFPE,SIGSEGV,SIGTERM,SIGBREAK,SIGABRT } ; - for (int i=0 ; i < 7 ; i++) - signal( signals[i], test_signal) ; -} +extern void win_install_sigabrt_handler(void); #endif static void unlock_locked_tables(THD *thd) @@ -1124,7 +1110,7 @@ pthread_handler_t handle_one_connection(void *arg) /* now that we've called my_thread_init(), it is safe to call DBUG_* */ #if defined(__WIN__) - init_signals(); + win_install_sigabrt_handler(); #elif !defined(OS2) && !defined(__NETWARE__) sigset_t set; VOID(sigemptyset(&set)); // Get mask in use @@ -2067,7 +2053,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd, unregister_slave(thd,1,1); /* fake COM_QUIT -- if we get here, the thread needs to terminate */ error = TRUE; - net->error = 0; break; } #endif @@ -3056,6 +3041,20 @@ mysql_execute_command(THD *thd) "INDEX DIRECTORY option ignored"); create_info.data_file_name= create_info.index_file_name= NULL; #else + + if (test_if_data_home_dir(lex->create_info.data_file_name)) + { + my_error(ER_WRONG_ARGUMENTS,MYF(0),"DATA DIRECORY"); + res= -1; + break; + } + if (test_if_data_home_dir(lex->create_info.index_file_name)) + { + my_error(ER_WRONG_ARGUMENTS,MYF(0),"INDEX DIRECORY"); + res= -1; + break; + } + /* Fix names if symlinked tables */ if (append_file_to_dir(thd, &create_info.data_file_name, create_table->table_name) || @@ -7899,3 +7898,48 @@ bool check_string_length(LEX_STRING *str, const char *err_msg, return TRUE; } + + +/* + Check if path does not contain mysql data home directory + + SYNOPSIS + test_if_data_home_dir() + dir directory + conv_home_dir converted data home directory + home_dir_len converted data home directory length + + RETURN VALUES + 0 ok + 1 error +*/ + +static bool test_if_data_home_dir(const char *dir) +{ + char path[FN_REFLEN], conv_path[FN_REFLEN]; + uint dir_len, home_dir_len= strlen(mysql_unpacked_real_data_home); + DBUG_ENTER("test_if_data_home_dir"); + + if (!dir) + DBUG_RETURN(0); + + (void) fn_format(path, dir, "", "", + (MY_RETURN_REAL_PATH|MY_RESOLVE_SYMLINKS)); + dir_len= unpack_dirname(conv_path, dir); + + if (home_dir_len <= dir_len) + { + if (lower_case_file_system) + { + if (!my_strnncoll(default_charset_info, (const uchar*) conv_path, + home_dir_len, + (const uchar*) mysql_unpacked_real_data_home, + home_dir_len)) + DBUG_RETURN(1); + } + else if (!memcmp(conv_path, mysql_unpacked_real_data_home, home_dir_len)) + DBUG_RETURN(1); + } + DBUG_RETURN(0); +} + diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 74cbd2c5505..18cfd8d7dfc 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1512,6 +1512,44 @@ static bool mysql_test_create_table(Prepared_statement *stmt) } +/** + @brief Validate and prepare for execution CREATE VIEW statement + + @param stmt prepared statement + + @note This function handles create view commands. + + @retval FALSE Operation was a success. + @retval TRUE An error occured. +*/ + +static bool mysql_test_create_view(Prepared_statement *stmt) +{ + DBUG_ENTER("mysql_test_create_view"); + THD *thd= stmt->thd; + LEX *lex= stmt->lex; + bool res= TRUE; + /* Skip first table, which is the view we are creating */ + bool link_to_local; + TABLE_LIST *view= lex->unlink_first_table(&link_to_local); + TABLE_LIST *tables= lex->query_tables; + + if (create_view_precheck(thd, tables, view, lex->create_view_mode)) + goto err; + + if (open_normal_and_derived_tables(thd, tables, 0)) + goto err; + + lex->view_prepare_mode= 1; + res= select_like_stmt_test(stmt, 0, 0); + +err: + /* put view back for PS rexecuting */ + lex->link_first_table_back(view, link_to_local); + DBUG_RETURN(res); +} + + /* Validate and prepare for execution a multi update statement. @@ -1730,6 +1768,7 @@ static bool check_prepared_statement(Prepared_statement *stmt, my_message(ER_UNSUPPORTED_PS, ER(ER_UNSUPPORTED_PS), MYF(0)); goto error; } + res= mysql_test_create_view(stmt); break; case SQLCOM_DO: res= mysql_test_do_fields(stmt, tables, lex->insert_list); diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 903d254db8f..5bbff69f197 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -1229,9 +1229,6 @@ bool change_master(THD* thd, MASTER_INFO* mi) DBUG_RETURN(TRUE); } } - mi->rli.group_master_log_pos = mi->master_log_pos; - DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->master_log_pos)); - /* Coordinates in rli were spoilt by the 'if (need_relay_log_purge)' block, so restore them to good values. If we left them to ''/0, that would work; @@ -1243,6 +1240,7 @@ bool change_master(THD* thd, MASTER_INFO* mi) That's why we always save good coords in rli. */ mi->rli.group_master_log_pos= mi->master_log_pos; + DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->master_log_pos)); strmake(mi->rli.group_master_log_name,mi->master_log_name, sizeof(mi->rli.group_master_log_name)-1); @@ -1355,6 +1353,11 @@ bool mysql_show_binlog_events(THD* thd) if ((file=open_binlog(&log, linfo.log_file_name, &errmsg)) < 0) goto err; + /* + to account binlog event header size + */ + thd->variables.max_allowed_packet += MAX_LOG_EVENT_HEADER; + pthread_mutex_lock(log_lock); /* @@ -1365,7 +1368,6 @@ bool mysql_show_binlog_events(THD* thd) This code will fail on a mixed relay log (one which has Format_desc then Rotate then Format_desc). */ - ev = Log_event::read_log_event(&log,(pthread_mutex_t*)0,description_event); if (ev) { @@ -1556,37 +1558,52 @@ err: DBUG_RETURN(TRUE); } - +/** + Load data's io cache specific hook to be executed + before a chunk of data is being read into the cache's buffer + The fuction instantianates and writes into the binlog + replication events along LOAD DATA processing. + + @param file pointer to io-cache + @return 0 +*/ int log_loaded_block(IO_CACHE* file) { + DBUG_ENTER("log_loaded_block"); LOAD_FILE_INFO *lf_info; - uint block_len ; - - /* file->request_pos contains position where we started last read */ - char* buffer = (char*) file->request_pos; - if (!(block_len = (char*) file->read_end - (char*) buffer)) - return 0; - lf_info = (LOAD_FILE_INFO*) file->arg; + uint block_len; + /* buffer contains position where we started last read */ + char* buffer= (char*) my_b_get_buffer_start(file); + uint max_event_size= current_thd->variables.max_allowed_packet; + lf_info= (LOAD_FILE_INFO*) file->arg; if (lf_info->last_pos_in_file != HA_POS_ERROR && - lf_info->last_pos_in_file >= file->pos_in_file) - return 0; - lf_info->last_pos_in_file = file->pos_in_file; - if (lf_info->wrote_create_file) - { - Append_block_log_event a(lf_info->thd, lf_info->thd->db, buffer, - block_len, lf_info->log_delayed); - mysql_bin_log.write(&a); - } - else + lf_info->last_pos_in_file >= my_b_get_pos_in_file(file)) + DBUG_RETURN(0); + + for (block_len= my_b_get_bytes_in_buffer(file); block_len > 0; + buffer += min(block_len, max_event_size), + block_len -= min(block_len, max_event_size)) { - Begin_load_query_log_event b(lf_info->thd, lf_info->thd->db, - buffer, block_len, - lf_info->log_delayed); - mysql_bin_log.write(&b); - lf_info->wrote_create_file = 1; - DBUG_SYNC_POINT("debug_lock.created_file_event",10); + lf_info->last_pos_in_file= my_b_get_pos_in_file(file); + if (lf_info->wrote_create_file) + { + Append_block_log_event a(lf_info->thd, lf_info->thd->db, buffer, + min(block_len, max_event_size), + lf_info->log_delayed); + mysql_bin_log.write(&a); + } + else + { + Begin_load_query_log_event b(lf_info->thd, lf_info->thd->db, + buffer, + min(block_len, max_event_size), + lf_info->log_delayed); + mysql_bin_log.write(&b); + lf_info->wrote_create_file= 1; + DBUG_SYNC_POINT("debug_lock.created_file_event",10); + } } - return 0; + DBUG_RETURN(0); } #endif /* HAVE_REPLICATION */ diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 87935b5548f..6392f7c4299 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -360,10 +360,10 @@ fix_inner_refs(THD *thd, List<Item> &all_fields, SELECT_LEX *select, } } new_ref= direct_ref ? - new Item_direct_ref(ref->context, item_ref, ref->field_name, - ref->table_name, ref->alias_name_used) : - new Item_ref(ref->context, item_ref, ref->field_name, - ref->table_name, ref->alias_name_used); + new Item_direct_ref(ref->context, item_ref, ref->table_name, + ref->field_name, ref->alias_name_used) : + new Item_ref(ref->context, item_ref, ref->table_name, + ref->field_name, ref->alias_name_used); if (!new_ref) return TRUE; ref->outer_ref= new_ref; @@ -2887,7 +2887,9 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end, } } else if (old->eq_func && new_fields->eq_func && - old->val->eq(new_fields->val, old->field->binary())) + old->val->eq_by_collation(new_fields->val, + old->field->binary(), + old->field->charset())) { old->level= and_level; @@ -10794,7 +10796,7 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab, we found a row, as no new rows can be added to the result. */ if (not_used_in_distinct && found_records != join->found_records) - return NESTED_LOOP_OK; + return NESTED_LOOP_NO_MORE_ROWS; } else join_tab->read_record.file->unlock_row(); @@ -11171,19 +11173,42 @@ join_read_key(JOIN_TAB *tab) } +/* + ref access method implementation: "read_first" function + + SYNOPSIS + join_read_always_key() + tab JOIN_TAB of the accessed table + + DESCRIPTION + This is "read_fist" function for the "ref" access method. + + The functon must leave the index initialized when it returns. + ref_or_null access implementation depends on that. + + RETURN + 0 - Ok + -1 - Row not found + 1 - Error +*/ + static int join_read_always_key(JOIN_TAB *tab) { int error; TABLE *table= tab->table; + /* Initialize the index first */ + if (!table->file->inited) + table->file->ha_index_init(tab->ref.key); + + /* Perform "Late NULLs Filtering" (see internals manual for explanations) */ for (uint i= 0 ; i < tab->ref.key_parts ; i++) { if ((tab->ref.null_rejecting & 1 << i) && tab->ref.items[i]->is_null()) return -1; - } - if (!table->file->inited) - table->file->ha_index_init(tab->ref.key); + } + if (cp_buffer_from_ref(tab->join->thd, &tab->ref)) return -1; if ((error=table->file->index_read(table->record[0], diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 606a9ddb26d..75e47dd0c8e 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -307,8 +307,8 @@ bool String::copy_aligned(const char *str,uint32 arg_length, uint32 offset, return TRUE; /* - Note, this is only safe for little-endian UCS-2. - If we add big-endian UCS-2 sometimes, this code + Note, this is only safe for big-endian UCS-2. + If we add little-endian UCS-2 sometimes, this code will be more complicated. But it's OK for now. */ bzero((char*) Ptr, offset); diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 297edd0d90d..4c8e6e80c41 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -182,10 +182,33 @@ fill_defined_view_parts (THD *thd, TABLE_LIST *view) TABLE_LIST decoy; memcpy (&decoy, view, sizeof (TABLE_LIST)); - if (!open_table(thd, &decoy, thd->mem_root, ¬_used, OPEN_VIEW_NO_PARSE) && - !decoy.view) + + /* + Let's reset decoy.view before calling open_table(): when we start + supporting ALTER VIEW in PS/SP that may save us from a crash. + */ + + decoy.view= NULL; + + /* + open_table() will return NULL if 'decoy' is idenitifying a view *and* + there is no TABLE object for that view in the table cache. However, + decoy.view will be set to 1. + + If there is a TABLE-instance for the oject identified by 'decoy', + open_table() will return that instance no matter if it is a table or + a view. + + Thus, there is no need to check for the return value of open_table(), + since the return value itself does not mean anything. + */ + + open_table(thd, &decoy, thd->mem_root, ¬_used, OPEN_VIEW_NO_PARSE); + + if (!decoy.view) { - /* It's a table */ + /* It's a table. */ + my_error(ER_WRONG_OBJECT, MYF(0), view->db, view->table_name, "VIEW"); return TRUE; } @@ -204,104 +227,31 @@ fill_defined_view_parts (THD *thd, TABLE_LIST *view) return FALSE; } +#ifndef NO_EMBEDDED_ACCESS_CHECKS /** - @brief Creating/altering VIEW procedure + @brief CREATE VIEW privileges pre-check. @param thd thread handler + @param tables tables used in the view @param views views to create @param mode VIEW_CREATE_NEW, VIEW_ALTER, VIEW_CREATE_OR_REPLACE - @note This function handles both create and alter view commands. - @retval FALSE Operation was a success. @retval TRUE An error occured. */ -bool mysql_create_view(THD *thd, TABLE_LIST *views, - enum_view_create_mode mode) +bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view, + enum_view_create_mode mode) { LEX *lex= thd->lex; - bool link_to_local; /* first table in list is target VIEW name => cut off it */ - TABLE_LIST *view= lex->unlink_first_table(&link_to_local); - TABLE_LIST *tables= lex->query_tables; TABLE_LIST *tbl; SELECT_LEX *select_lex= &lex->select_lex; -#ifndef NO_EMBEDDED_ACCESS_CHECKS SELECT_LEX *sl; -#endif - SELECT_LEX_UNIT *unit= &lex->unit; - bool res= FALSE; - DBUG_ENTER("mysql_create_view"); + bool res= TRUE; + DBUG_ENTER("create_view_precheck"); - /* This is ensured in the parser. */ - DBUG_ASSERT(!lex->proc_list.first && !lex->result && - !lex->param_list.elements && !lex->derived_tables); - - if (mode != VIEW_CREATE_NEW) - { - if (mode == VIEW_ALTER && - fill_defined_view_parts(thd, view)) - { - res= TRUE; - goto err; - } - sp_cache_invalidate(); - } - - if (!lex->definer) - { - /* - DEFINER-clause is missing; we have to create default definer in - persistent arena to be PS/SP friendly. - If this is an ALTER VIEW then the current user should be set as - the definer. - */ - Query_arena original_arena; - Query_arena *ps_arena = thd->activate_stmt_arena_if_needed(&original_arena); - - if (!(lex->definer= create_default_definer(thd))) - res= TRUE; - - if (ps_arena) - thd->restore_active_arena(ps_arena, &original_arena); - - if (res) - goto err; - } - -#ifndef NO_EMBEDDED_ACCESS_CHECKS - /* - check definer of view: - - same as current user - - current user has SUPER_ACL - */ - if (lex->definer && - (strcmp(lex->definer->user.str, thd->security_ctx->priv_user) != 0 || - my_strcasecmp(system_charset_info, - lex->definer->host.str, - thd->security_ctx->priv_host) != 0)) - { - if (!(thd->security_ctx->master_access & SUPER_ACL)) - { - my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER"); - res= TRUE; - goto err; - } - else - { - if (!is_acl_user(lex->definer->host.str, - lex->definer->user.str)) - { - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, - ER_NO_SUCH_USER, - ER(ER_NO_SUCH_USER), - lex->definer->user.str, - lex->definer->host.str); - } - } - } /* Privilege check for view creation: - user has CREATE VIEW privilege on view table @@ -323,10 +273,8 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, (check_access(thd, DROP_ACL, view->db, &view->grant.privilege, 0, 0, is_schema_db(view->db)) || grant_option && check_grant(thd, DROP_ACL, view, 0, 1, 0)))) - { - res= TRUE; goto err; - } + for (sl= select_lex; sl; sl= sl->next_select()) { for (tbl= sl->get_table_list(); tbl; tbl= tbl->next_local) @@ -340,7 +288,6 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), "ANY", thd->security_ctx->priv_user, thd->security_ctx->priv_host, tbl->table_name); - res= TRUE; goto err; } /* @@ -376,10 +323,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, if (check_access(thd, SELECT_ACL, tbl->db, &tbl->grant.privilege, 0, 0, test(tbl->schema_table)) || grant_option && check_grant(thd, SELECT_ACL, tbl, 0, 1, 0)) - { - res= TRUE; goto err; - } } } } @@ -403,8 +347,126 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, } } } + + res= FALSE; + +err: + DBUG_RETURN(res || thd->net.report_error); +} + +#else + +bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view, + enum_view_create_mode mode) +{ + return FALSE; +} + +#endif + + +/** + @brief Creating/altering VIEW procedure + + @param thd thread handler + @param views views to create + @param mode VIEW_CREATE_NEW, VIEW_ALTER, VIEW_CREATE_OR_REPLACE + + @note This function handles both create and alter view commands. + + @retval FALSE Operation was a success. + @retval TRUE An error occured. +*/ + +bool mysql_create_view(THD *thd, TABLE_LIST *views, + enum_view_create_mode mode) +{ + LEX *lex= thd->lex; + bool link_to_local; + /* first table in list is target VIEW name => cut off it */ + TABLE_LIST *view= lex->unlink_first_table(&link_to_local); + TABLE_LIST *tables= lex->query_tables; + TABLE_LIST *tbl; + SELECT_LEX *select_lex= &lex->select_lex; +#ifndef NO_EMBEDDED_ACCESS_CHECKS + SELECT_LEX *sl; +#endif + SELECT_LEX_UNIT *unit= &lex->unit; + bool res= FALSE; + DBUG_ENTER("mysql_create_view"); + + /* This is ensured in the parser. */ + DBUG_ASSERT(!lex->proc_list.first && !lex->result && + !lex->param_list.elements && !lex->derived_tables); + + if (mode != VIEW_CREATE_NEW) + { + if (mode == VIEW_ALTER && + fill_defined_view_parts(thd, view)) + { + res= TRUE; + goto err; + } + sp_cache_invalidate(); + } + + if (!lex->definer) + { + /* + DEFINER-clause is missing; we have to create default definer in + persistent arena to be PS/SP friendly. + If this is an ALTER VIEW then the current user should be set as + the definer. + */ + Query_arena original_arena; + Query_arena *ps_arena = thd->activate_stmt_arena_if_needed(&original_arena); + + if (!(lex->definer= create_default_definer(thd))) + res= TRUE; + + if (ps_arena) + thd->restore_active_arena(ps_arena, &original_arena); + + if (res) + goto err; + } + +#ifndef NO_EMBEDDED_ACCESS_CHECKS + /* + check definer of view: + - same as current user + - current user has SUPER_ACL + */ + if (lex->definer && + (strcmp(lex->definer->user.str, thd->security_ctx->priv_user) != 0 || + my_strcasecmp(system_charset_info, + lex->definer->host.str, + thd->security_ctx->priv_host) != 0)) + { + if (!(thd->security_ctx->master_access & SUPER_ACL)) + { + my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER"); + res= TRUE; + goto err; + } + else + { + if (!is_acl_user(lex->definer->host.str, + lex->definer->user.str)) + { + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, + ER_NO_SUCH_USER, + ER(ER_NO_SUCH_USER), + lex->definer->user.str, + lex->definer->host.str); + } + } + } #endif + if ((res= create_view_precheck(thd, tables, view, mode))) + goto err; + if (open_and_lock_tables(thd, tables)) { res= TRUE; @@ -1424,6 +1486,8 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) String non_existant_views; char *wrong_object_db= NULL, *wrong_object_name= NULL; bool error= FALSE; + bool some_views_deleted= FALSE; + bool something_wrong= FALSE; VOID(pthread_mutex_lock(&LOCK_open)); for (view= views; view; view= view->next_local) @@ -1462,33 +1526,37 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) } if (my_delete(path, MYF(MY_WME))) error= TRUE; + some_views_deleted= TRUE; query_cache_invalidate3(thd, view, 0); sp_cache_invalidate(); } - if (mysql_bin_log.is_open()) - { - thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); - mysql_bin_log.write(&qinfo); - } - VOID(pthread_mutex_unlock(&LOCK_open)); - - if (error) - { - DBUG_RETURN(TRUE); - } if (wrong_object_name) { my_error(ER_WRONG_OBJECT, MYF(0), wrong_object_db, wrong_object_name, "VIEW"); - DBUG_RETURN(TRUE); } if (non_existant_views.length()) { my_error(ER_BAD_TABLE_ERROR, MYF(0), non_existant_views.c_ptr()); + } + + something_wrong= error || wrong_object_name || non_existant_views.length(); + if (some_views_deleted || !something_wrong) + { + if (!something_wrong) + thd->clear_error(); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + mysql_bin_log.write(&qinfo); + } + + VOID(pthread_mutex_unlock(&LOCK_open)); + + if (something_wrong) + { DBUG_RETURN(TRUE); } + send_ok(thd); DBUG_RETURN(FALSE); } diff --git a/sql/sql_view.h b/sql/sql_view.h index ab0920e0bf2..1d45283352b 100644 --- a/sql/sql_view.h +++ b/sql/sql_view.h @@ -15,6 +15,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view, + enum_view_create_mode mode); + bool mysql_create_view(THD *thd, TABLE_LIST *view, enum_view_create_mode mode); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index af57fbdb108..80fa037b964 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -458,10 +458,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %pure_parser /* We have threads */ /* - Currently there are 245 shift/reduce conflicts. + Currently there are 240 shift/reduce conflicts. We should not introduce new conflicts any more. */ -%expect 245 +%expect 240 %token END_OF_INPUT @@ -1111,6 +1111,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %type <interval_time_st> interval_time_st +%type <interval_time_st> interval_time_stamp + %type <db_type> storage_engines %type <row_type> row_types @@ -2214,6 +2216,10 @@ sp_proc_stmt: lex->sphead->backpatch(lex->spcont->pop_label()); } + | sp_labeled_block + {} + | sp_unlabeled_block + {} | LEAVE_SYM label_ident { LEX *lex= Lex; @@ -2231,9 +2237,17 @@ sp_proc_stmt: sp_instr_jump *i; uint ip= sp->instructions(); uint n; + /* + When jumping to a BEGIN-END block end, the target jump + points to the block hpop/cpop cleanup instructions, + so we should exclude the block context here. + When jumping to something else (i.e., SP_LAB_ITER), + there are no hpop/cpop at the jump destination, + so we should include the block context here for cleanup. + */ + bool exclusive= (lab->type == SP_LAB_BEGIN); - n= ctx->diff_handlers(lab->ctx, TRUE); /* Exclusive the dest. */ - + n= ctx->diff_handlers(lab->ctx, exclusive); if (n) { sp_instr_hpop *hpop= new sp_instr_hpop(ip++, ctx, n); @@ -2241,10 +2255,12 @@ sp_proc_stmt: MYSQL_YYABORT; sp->add_instr(hpop); } - n= ctx->diff_cursors(lab->ctx, TRUE); /* Exclusive the dest. */ + n= ctx->diff_cursors(lab->ctx, exclusive); if (n) { sp_instr_cpop *cpop= new sp_instr_cpop(ip++, ctx, n); + if (cpop == NULL) + MYSQL_YYABORT; sp->add_instr(cpop); } i= new sp_instr_jump(ip, ctx); @@ -2276,12 +2292,16 @@ sp_proc_stmt: if (n) { sp_instr_hpop *hpop= new sp_instr_hpop(ip++, ctx, n); + if (hpop == NULL) + MYSQL_YYABORT; sp->add_instr(hpop); } n= ctx->diff_cursors(lab->ctx, FALSE); /* Inclusive the dest. */ if (n) { sp_instr_cpop *cpop= new sp_instr_cpop(ip++, ctx, n); + if (cpop == NULL) + MYSQL_YYABORT; sp->add_instr(cpop); } i= new sp_instr_jump(ip, ctx, lab->ip); /* Jump back */ @@ -2577,19 +2597,17 @@ sp_labeled_control: sp_unlabeled_control sp_opt_label { LEX *lex= Lex; + sp_label_t *lab= lex->spcont->pop_label(); if ($5.str) { - sp_label_t *lab= lex->spcont->find_label($5.str); - - if (!lab || - my_strcasecmp(system_charset_info, $5.str, lab->name) != 0) + if (my_strcasecmp(system_charset_info, $5.str, lab->name) != 0) { my_error(ER_SP_LABEL_MISMATCH, MYF(0), $5.str); MYSQL_YYABORT; } } - lex->sphead->backpatch(lex->spcont->pop_label()); + lex->sphead->backpatch(lab); } ; @@ -2598,15 +2616,59 @@ sp_opt_label: | label_ident { $$= $1; } ; -sp_unlabeled_control: +sp_labeled_block: + label_ident ':' + { + LEX *lex= Lex; + sp_pcontext *ctx= lex->spcont; + sp_label_t *lab= ctx->find_label($1.str); + + if (lab) + { + my_error(ER_SP_LABEL_REDEFINE, MYF(0), $1.str); + MYSQL_YYABORT; + } + + lab= lex->spcont->push_label($1.str, + lex->sphead->instructions()); + lab->type= SP_LAB_BEGIN; + } + sp_block_content sp_opt_label + { + LEX *lex= Lex; + sp_label_t *lab= lex->spcont->pop_label(); + + if ($5.str) + { + if (my_strcasecmp(system_charset_info, $5.str, lab->name) != 0) + { + my_error(ER_SP_LABEL_MISMATCH, MYF(0), $5.str); + MYSQL_YYABORT; + } + } + } + ; + +sp_unlabeled_block: + { /* Unlabeled blocks get a secret label. */ + LEX *lex= Lex; + uint ip= lex->sphead->instructions(); + sp_label_t *lab= lex->spcont->push_label((char *)"", ip); + lab->type= SP_LAB_BEGIN; + } + sp_block_content + { + LEX *lex= Lex; + lex->spcont->pop_label(); + } + ; + +sp_block_content: BEGIN_SYM { /* QQ This is just a dummy for grouping declarations and statements together. No [[NOT] ATOMIC] yet, and we need to figure out how make it coexist with the existing BEGIN COMMIT/ROLLBACK. */ LEX *lex= Lex; - sp_label_t *lab= lex->spcont->last_label(); - - lab->type= SP_LAB_BEGIN; lex->spcont= lex->spcont->push_context(LABEL_DEFAULT_SCOPE); } sp_decls @@ -2636,7 +2698,10 @@ sp_unlabeled_control: } lex->spcont= ctx->pop_context(); } - | LOOP_SYM + ; + +sp_unlabeled_control: + LOOP_SYM sp_proc_stmts1 END LOOP_SYM { LEX *lex= Lex; @@ -5027,9 +5092,9 @@ simple_expr: { $$= new Item_datetime_typecast($3); } | TIMESTAMP '(' expr ',' expr ')' { $$= new Item_func_add_time($3, $5, 1, 0); } - | TIMESTAMP_ADD '(' interval_time_st ',' expr ',' expr ')' + | TIMESTAMP_ADD '(' interval_time_stamp ',' expr ',' expr ')' { $$= new Item_date_add_interval($7,$5,$3,0); } - | TIMESTAMP_DIFF '(' interval_time_st ',' expr ',' expr ')' + | TIMESTAMP_DIFF '(' interval_time_stamp ',' expr ',' expr ')' { $$= new Item_func_timestamp_diff($5,$7,$3); } | TRIM '(' expr ')' { $$= new Item_func_trim($3); } @@ -6005,21 +6070,40 @@ interval: | HOUR_MICROSECOND_SYM { $$=INTERVAL_HOUR_MICROSECOND; } | HOUR_MINUTE_SYM { $$=INTERVAL_HOUR_MINUTE; } | HOUR_SECOND_SYM { $$=INTERVAL_HOUR_SECOND; } - | MICROSECOND_SYM { $$=INTERVAL_MICROSECOND; } | MINUTE_MICROSECOND_SYM { $$=INTERVAL_MINUTE_MICROSECOND; } | MINUTE_SECOND_SYM { $$=INTERVAL_MINUTE_SECOND; } | SECOND_MICROSECOND_SYM { $$=INTERVAL_SECOND_MICROSECOND; } | YEAR_MONTH_SYM { $$=INTERVAL_YEAR_MONTH; }; +interval_time_stamp: + interval_time_st {} + | FRAC_SECOND_SYM { + $$=INTERVAL_MICROSECOND; + /* + FRAC_SECOND was mistakenly implemented with + a wrong resolution. According to the ODBC + standard it should be nanoseconds, not + microseconds. Changing it to nanoseconds + in MySQL would mean making TIMESTAMPDIFF + and TIMESTAMPADD to return DECIMAL, since + the return value would be too big for BIGINT + Hence we just deprecate the incorrect + implementation without changing its + resolution. + */ + WARN_DEPRECATED("FRAC_SECOND", "MICROSECOND"); // Will be removed in 6.2 + } + ; + interval_time_st: DAY_SYM { $$=INTERVAL_DAY; } | WEEK_SYM { $$=INTERVAL_WEEK; } | HOUR_SYM { $$=INTERVAL_HOUR; } - | FRAC_SECOND_SYM { $$=INTERVAL_MICROSECOND; } | MINUTE_SYM { $$=INTERVAL_MINUTE; } | MONTH_SYM { $$=INTERVAL_MONTH; } | QUARTER_SYM { $$=INTERVAL_QUARTER; } | SECOND_SYM { $$=INTERVAL_SECOND; } + | MICROSECOND_SYM { $$=INTERVAL_MICROSECOND; } | YEAR_SYM { $$=INTERVAL_YEAR; } ; @@ -6257,7 +6341,7 @@ limit_options: limit_option: param_marker { - ((Item_param *) $1)->set_strict_type(INT_RESULT); + ((Item_param *) $1)->limit_clause_param= TRUE; } | ULONGLONG_NUM { $$= new Item_uint($1.str, $1.length); } | LONG_NUM { $$= new Item_uint($1.str, $1.length); } diff --git a/sql/stacktrace.c b/sql/stacktrace.c index c947beafac3..ce91d63d3f7 100644 --- a/sql/stacktrace.c +++ b/sql/stacktrace.c @@ -13,11 +13,15 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/* Workaround for Bug#32082: VOID redefinition on Win results in compile errors*/ +#define DONT_DEFINE_VOID 1 + #include <my_global.h> #include "stacktrace.h" + +#ifndef __WIN__ #include <signal.h> #include <my_pthread.h> - #ifdef HAVE_STACKTRACE #include <unistd.h> #include <strings.h> @@ -118,10 +122,7 @@ void print_stacktrace(gptr stack_bottom, ulong thread_stack) #endif LINT_INIT(fp); - fprintf(stderr,"\ -Attempting backtrace. You can use the following information to find out\n\ -where mysqld died. If you see no messages after this, something went\n\ -terribly wrong...\n"); + #ifdef __i386__ __asm __volatile__ ("movl %%ebp,%0" :"=r"(fp) @@ -257,3 +258,267 @@ void write_core(int sig) #endif } #endif +#else /* __WIN__*/ + +#include <dbghelp.h> + +/* + Stack tracing on Windows is implemented using Debug Helper library(dbghelp.dll) + We do not redistribute dbghelp and the one comes with older OS (up to Windows 2000) + is missing some important functions like functions StackWalk64 or MinidumpWriteDump. + Hence, we have to load functions at runtime using LoadLibrary/GetProcAddress. +*/ + +typedef DWORD (WINAPI *SymSetOptions_FctType)(DWORD dwOptions); +typedef BOOL (WINAPI *SymGetModuleInfo64_FctType) + (HANDLE,DWORD64,PIMAGEHLP_MODULE64) ; +typedef BOOL (WINAPI *SymGetSymFromAddr64_FctType) + (HANDLE,DWORD64,PDWORD64,PIMAGEHLP_SYMBOL64) ; +typedef BOOL (WINAPI *SymGetLineFromAddr64_FctType) + (HANDLE,DWORD64,PDWORD,PIMAGEHLP_LINE64); +typedef BOOL (WINAPI *SymInitialize_FctType) + (HANDLE,PSTR,BOOL); +typedef BOOL (WINAPI *StackWalk64_FctType) + (DWORD,HANDLE,HANDLE,LPSTACKFRAME64,PVOID,PREAD_PROCESS_MEMORY_ROUTINE64, + PFUNCTION_TABLE_ACCESS_ROUTINE64,PGET_MODULE_BASE_ROUTINE64 , + PTRANSLATE_ADDRESS_ROUTINE64); +typedef BOOL (WINAPI *MiniDumpWriteDump_FctType)( + IN HANDLE hProcess, + IN DWORD ProcessId, + IN HANDLE hFile, + IN MINIDUMP_TYPE DumpType, + IN CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, OPTIONAL + IN CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, OPTIONAL + IN CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam OPTIONAL + ); + +static SymSetOptions_FctType pSymSetOptions; +static SymGetModuleInfo64_FctType pSymGetModuleInfo64; +static SymGetSymFromAddr64_FctType pSymGetSymFromAddr64; +static SymInitialize_FctType pSymInitialize; +static StackWalk64_FctType pStackWalk64; +static SymGetLineFromAddr64_FctType pSymGetLineFromAddr64; +static MiniDumpWriteDump_FctType pMiniDumpWriteDump; + +static EXCEPTION_POINTERS *exception_ptrs; + +#define MODULE64_SIZE_WINXP 576 +#define STACKWALK_MAX_FRAMES 64 + +/* + Dynamically load dbghelp functions +*/ +BOOL init_dbghelp_functions() +{ + static BOOL first_time= TRUE; + static BOOL rc; + HMODULE hDbghlp; + + if(first_time) + { + first_time= FALSE; + hDbghlp= LoadLibrary("dbghelp"); + if(!hDbghlp) + { + rc= FALSE; + return rc; + } + pSymSetOptions= (SymSetOptions_FctType) + GetProcAddress(hDbghlp,"SymSetOptions"); + pSymInitialize= (SymInitialize_FctType) + GetProcAddress(hDbghlp,"SymInitialize"); + pSymGetModuleInfo64= (SymGetModuleInfo64_FctType) + GetProcAddress(hDbghlp,"SymGetModuleInfo64"); + pSymGetLineFromAddr64= (SymGetLineFromAddr64_FctType) + GetProcAddress(hDbghlp,"SymGetLineFromAddr64"); + pSymGetSymFromAddr64=(SymGetSymFromAddr64_FctType) + GetProcAddress(hDbghlp,"SymGetSymFromAddr64"); + pStackWalk64= (StackWalk64_FctType) + GetProcAddress(hDbghlp,"StackWalk64"); + pMiniDumpWriteDump = (MiniDumpWriteDump_FctType) + GetProcAddress(hDbghlp,"MiniDumpWriteDump"); + + rc = (BOOL)(pSymSetOptions && pSymInitialize && pSymGetModuleInfo64 + && pSymGetLineFromAddr64 && pSymGetSymFromAddr64 && pStackWalk64); + } + return rc; +} + +void set_exception_pointers(EXCEPTION_POINTERS *ep) +{ + exception_ptrs = ep; +} + +/* Platform SDK in VS2003 does not have definition for SYMOPT_NO_PROMPTS*/ +#ifndef SYMOPT_NO_PROMPTS +#define SYMOPT_NO_PROMPTS 0 +#endif + +void print_stacktrace(gptr unused1, ulong unused2) +{ + HANDLE hProcess= GetCurrentProcess(); + HANDLE hThread= GetCurrentThread(); + static IMAGEHLP_MODULE64 module= {sizeof(module)}; + static IMAGEHLP_SYMBOL64_PACKAGE package; + DWORD64 addr; + DWORD machine; + int i; + CONTEXT context; + STACKFRAME64 frame={0}; + + if(!exception_ptrs || !init_dbghelp_functions()) + return; + + /* Copy context, as stackwalking on original will unwind the stack */ + context = *(exception_ptrs->ContextRecord); + /*Initialize symbols.*/ + pSymSetOptions(SYMOPT_LOAD_LINES|SYMOPT_NO_PROMPTS|SYMOPT_DEFERRED_LOADS|SYMOPT_DEBUG); + pSymInitialize(hProcess,NULL,TRUE); + + /*Prepare stackframe for the first StackWalk64 call*/ + frame.AddrFrame.Mode= frame.AddrPC.Mode= frame.AddrStack.Mode= AddrModeFlat; +#if (defined _M_IX86) + machine= IMAGE_FILE_MACHINE_I386; + frame.AddrFrame.Offset= context.Ebp; + frame.AddrPC.Offset= context.Eip; + frame.AddrStack.Offset= context.Esp; +#elif (defined _M_X64) + machine = IMAGE_FILE_MACHINE_AMD64; + frame.AddrFrame.Offset= context.Rbp; + frame.AddrPC.Offset= context.Rip; + frame.AddrStack.Offset= context.Rsp; +#else + /*There is currently no need to support IA64*/ +#pragma error ("unsupported architecture") +#endif + + package.sym.SizeOfStruct= sizeof(package.sym); + package.sym.MaxNameLength= sizeof(package.name); + + /*Walk the stack, output useful information*/ + for(i= 0; i< STACKWALK_MAX_FRAMES;i++) + { + DWORD64 function_offset= 0; + DWORD line_offset= 0; + IMAGEHLP_LINE64 line= {sizeof(line)}; + BOOL have_module= FALSE; + BOOL have_symbol= FALSE; + BOOL have_source= FALSE; + + if(!pStackWalk64(machine, hProcess, hThread, &frame, &context, 0, 0, 0 ,0)) + break; + addr= frame.AddrPC.Offset; + + have_module= pSymGetModuleInfo64(hProcess,addr,&module); +#ifdef _M_IX86 + if(!have_module) + { + /* + ModuleInfo structure has been "compatibly" extended in releases after XP, + and its size was increased. To make XP dbghelp.dll function + happy, pretend passing the old structure. + */ + module.SizeOfStruct= MODULE64_SIZE_WINXP; + have_module= pSymGetModuleInfo64(hProcess, addr, &module); + } +#endif + + have_symbol= pSymGetSymFromAddr64(hProcess, addr, &function_offset, + &(package.sym)); + have_source= pSymGetLineFromAddr64(hProcess, addr, &line_offset, &line); + + fprintf(stderr, "%p ", addr); + if(have_module) + { + char *base_image_name= strrchr(module.ImageName, '\\'); + if(base_image_name) + base_image_name++; + else + base_image_name= module.ImageName; + fprintf(stderr, "%s!", base_image_name); + } + if(have_symbol) + fprintf(stderr, "%s()", package.sym.Name); + else if(have_module) + fprintf(stderr, "???"); + + if(have_source) + { + char *base_file_name= strrchr(line.FileName, '\\'); + if(base_file_name) + base_file_name++; + else + base_file_name= line.FileName; + fprintf(stderr,"[%s:%u]", base_file_name, line.LineNumber); + } + fprintf(stderr, "\n"); + } + fflush(stderr); +} + + +/* + Write dump. The dump is created in current directory, + file name is constructed from executable name plus + ".dmp" extension +*/ +void write_core(int unused) +{ + char path[MAX_PATH]; + char dump_fname[MAX_PATH]= "core.dmp"; + MINIDUMP_EXCEPTION_INFORMATION info; + HANDLE hFile; + + if(!exception_ptrs || !init_dbghelp_functions() || !pMiniDumpWriteDump) + return; + + info.ExceptionPointers= exception_ptrs; + info.ClientPointers= FALSE; + info.ThreadId= GetCurrentThreadId(); + + if(GetModuleFileName(NULL, path, sizeof(path))) + { + _splitpath(path, NULL, NULL,dump_fname,NULL); + strncat(dump_fname, ".dmp", sizeof(dump_fname)); + } + + hFile= CreateFile(dump_fname, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, 0); + if(hFile) + { + /* Create minidump */ + if(pMiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), + hFile, MiniDumpNormal, &info, 0, 0)) + { + fprintf(stderr, "Minidump written to %s\n", + _fullpath(path, dump_fname, sizeof(path)) ? path : dump_fname); + } + else + { + fprintf(stderr,"MiniDumpWriteDump() failed, last error %u\n", + GetLastError()); + } + CloseHandle(hFile); + } + else + { + fprintf(stderr, "CreateFile(%s) failed, last error %u\n", dump_fname, + GetLastError()); + } + fflush(stderr); +} + + +void safe_print_str(const char *name, const char *val, int len) +{ + fprintf(stderr,"%s at %p", name, val); + __try + { + fprintf(stderr,"=%.*s\n", len, val); + } + __except(EXCEPTION_EXECUTE_HANDLER) + { + fprintf(stderr,"is an invalid string pointer\n"); + } +} +#endif /*__WIN__*/ diff --git a/sql/stacktrace.h b/sql/stacktrace.h index f5c92e54e1c..e5e17cc5b9b 100644 --- a/sql/stacktrace.h +++ b/sql/stacktrace.h @@ -29,20 +29,33 @@ extern char* heap_start; heap_start = (char*) &__bss_start; \ check_thread_lib(); \ } while(0); +void check_thread_lib(void); +#endif /* defined (__i386__) || (defined(__alpha__) && defined(__GNUC__))) */ +#elif defined (__WIN__) +#define HAVE_STACKTRACE +extern void set_exception_pointers(EXCEPTION_POINTERS *ep); +#define init_stacktrace() {} +#endif + +#ifdef HAVE_STACKTRACE void print_stacktrace(gptr stack_bottom, ulong thread_stack); void safe_print_str(const char* name, const char* val, int max_len); -void check_thread_lib(void); -#endif /* (defined (__i386__) || (defined(__alpha__) && defined(__GNUC__))) */ -#endif /* TARGET_OS_LINUX */ - +#else /* Define empty prototypes for functions that are not implemented */ -#ifndef HAVE_STACKTRACE #define init_stacktrace() {} #define print_stacktrace(A,B) {} #define safe_print_str(A,B,C) {} #endif /* HAVE_STACKTRACE */ + +#if !defined(__NETWARE__) +#define HAVE_WRITE_CORE +#endif + +#ifdef HAVE_WRITE_CORE void write_core(int sig); +#endif + #ifdef __cplusplus } diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 8c4909fc8d5..acf7d571710 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -15,6 +15,7 @@ # MA 02110-1301 USA. %define mysql_version @VERSION@ +%define mysql_vendor MySQL AB # use "rpmbuild --with static" or "rpm --define '_with_static 1'" (for RPM 3.x) # to enable static linking (off by default) @@ -69,7 +70,7 @@ License: %{license} Source: http://www.mysql.com/Downloads/MySQL-@MYSQL_BASE_VERSION@/mysql-%{mysql_version}.tar.gz URL: http://www.mysql.com/ Packager: MySQL Production Engineering Team <build@mysql.com> -Vendor: MySQL AB +Vendor: %{mysql_vendor} Provides: msqlormysql MySQL-server mysql BuildRequires: ncurses-devel Obsoletes: mysql @@ -420,6 +421,72 @@ touch $RBR%{_sysconfdir}/my.cnf touch $RBR%{_sysconfdir}/mysqlmanager.passwd %pre server +# Check if we can safely upgrade. An upgrade is only safe if it's from one +# of our RPMs in the same version family. + +installed=`rpm -q --whatprovides mysql-server 2> /dev/null` +if [ $? -eq 0 -a -n "$installed" ]; then + vendor=`rpm -q --queryformat='%{VENDOR}' "$installed" 2>&1` + version=`rpm -q --queryformat='%{VERSION}' "$installed" 2>&1` + myvendor='%{mysql_vendor}' + myversion='%{mysql_version}' + + old_family=`echo $version | sed -n -e 's,^\([1-9][0-9]*\.[0-9][0-9]*\)\..*$,\1,p'` + new_family=`echo $myversion | sed -n -e 's,^\([1-9][0-9]*\.[0-9][0-9]*\)\..*$,\1,p'` + + [ -z "$vendor" ] && vendor='<unknown>' + [ -z "$old_family" ] && old_family="<unrecognized version $version>" + [ -z "$new_family" ] && new_family="<bad package specification: version $myversion>" + + error_text= + if [ "$vendor" != "$myvendor" ]; then + error_text="$error_text +The current MySQL server package is provided by a different +vendor ($vendor) than $myvendor. Some files may be installed +to different locations, including log files and the service +startup script in %{_sysconfdir}/init.d/. +" + fi + + if [ "$old_family" != "$new_family" ]; then + error_text="$error_text +Upgrading directly from MySQL $old_family to MySQL $new_family may not +be safe in all cases. A manual dump and restore using mysqldump is +recommended. It is important to review the MySQL manual's Upgrading +section for version-specific incompatibilities. +" + fi + + if [ -n "$error_text" ]; then + cat <<HERE >&2 + +****************************************************************** +A MySQL server package ($installed) is installed. +$error_text +A manual upgrade is required. + +- Ensure that you have a complete, working backup of your data and my.cnf + files +- Shut down the MySQL server cleanly +- Remove the existing MySQL packages. Usually this command will + list the packages you should remove: + rpm -qa | grep -i '^mysql-' + + You may choose to use 'rpm --nodeps -ev <package-name>' to remove + the package which contains the mysqlclient shared library. The + library will be reinstalled by the MySQL-shared-compat package. +- Install the new MySQL packages supplied by $myvendor +- Ensure that the MySQL server is started +- Run the 'mysql_upgrade' program + +This is a brief description of the upgrade process. Important details +can be found in the MySQL manual, in the Upgrading section. +****************************************************************** +HERE + exit 1 + fi +fi + # Shut down a previously installed server first if test -x %{_sysconfdir}/init.d/mysql then @@ -715,6 +782,11 @@ fi # itself - note that they must be ordered by date (important when # merging BK trees) %changelog +* Mon Feb 18 2008 Timothy Smith <tim@mysql.com> + +- Require a manual upgrade if the alread-installed mysql-server is + from another vendor, or is of a different major version. + * Fri Nov 16 2007 Joerg Bruehe <joerg@mysql.com> - When testing the debug server, use "make test-bt-debug". diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 9cc2af25529..dbe22f2a9e4 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -8702,8 +8702,8 @@ static void test_sqlmode() strmov(c1, "My"); strmov(c2, "SQL"); rc= mysql_stmt_execute(stmt); check_execute(stmt, rc); - mysql_stmt_close(stmt); + verify_col_data("test_piping", "name", "MySQL"); rc= mysql_query(mysql, "DELETE FROM test_piping"); @@ -12993,7 +12993,7 @@ from t2);"); static void test_bug8378() { #if defined(HAVE_CHARSET_gbk) && !defined(EMBEDDED_LIBRARY) - MYSQL *old_mysql=mysql; + MYSQL *lmysql; char out[9]; /* strlen(TEST_BUG8378)*2+1 */ char buf[256]; int len, rc; @@ -13002,17 +13002,17 @@ static void test_bug8378() if (!opt_silent) fprintf(stdout, "\n Establishing a test connection ..."); - if (!(mysql= mysql_init(NULL))) + if (!(lmysql= mysql_init(NULL))) { myerror("mysql_init() failed"); exit(1); } - if (mysql_options(mysql, MYSQL_SET_CHARSET_NAME, "gbk")) + if (mysql_options(lmysql, MYSQL_SET_CHARSET_NAME, "gbk")) { myerror("mysql_options() failed"); exit(1); } - if (!(mysql_real_connect(mysql, opt_host, opt_user, + if (!(mysql_real_connect(lmysql, opt_host, opt_user, opt_password, current_db, opt_port, opt_unix_socket, 0))) { @@ -13022,19 +13022,17 @@ static void test_bug8378() if (!opt_silent) fprintf(stdout, " OK"); - len= mysql_real_escape_string(mysql, out, TEST_BUG8378_IN, 4); + len= mysql_real_escape_string(lmysql, out, TEST_BUG8378_IN, 4); /* No escaping should have actually happened. */ DIE_UNLESS(memcmp(out, TEST_BUG8378_OUT, len) == 0); sprintf(buf, "SELECT '%s'", out); - rc=mysql_real_query(mysql, buf, strlen(buf)); + rc=mysql_real_query(lmysql, buf, strlen(buf)); myquery(rc); - mysql_close(mysql); - - mysql=old_mysql; + mysql_close(lmysql); #endif } @@ -14869,7 +14867,7 @@ static void test_opt_reconnect() if (mysql_options(lmysql, MYSQL_OPT_RECONNECT, &my_true)) { myerror("mysql_options failed: unknown option MYSQL_OPT_RECONNECT\n"); - exit(1); + DIE_UNLESS(0); } /* reconnect should be 1 */ @@ -14882,7 +14880,7 @@ static void test_opt_reconnect() opt_unix_socket, 0))) { myerror("connection failed"); - exit(1); + DIE_UNLESS(0); } /* reconnect should still be 1 */ @@ -14896,7 +14894,7 @@ static void test_opt_reconnect() if (!(lmysql= mysql_init(NULL))) { myerror("mysql_init() failed"); - exit(1); + DIE_UNLESS(0); } if (!opt_silent) @@ -14908,7 +14906,7 @@ static void test_opt_reconnect() opt_unix_socket, 0))) { myerror("connection failed"); - exit(1); + DIE_UNLESS(0); } /* reconnect should still be 0 */ @@ -14926,32 +14924,32 @@ static void test_opt_reconnect() static void test_bug12744() { MYSQL_STMT *prep_stmt = NULL; + MYSQL *lmysql; int rc; myheader("test_bug12744"); - prep_stmt= mysql_stmt_init(mysql); - rc= mysql_stmt_prepare(prep_stmt, "SELECT 1", 8); - DIE_UNLESS(rc==0); - - mysql_close(mysql); + lmysql= mysql_init(NULL); + DIE_UNLESS(lmysql); - if ((rc= mysql_stmt_execute(prep_stmt))) + if (!mysql_real_connect(lmysql, opt_host, opt_user, opt_password, + current_db, opt_port, opt_unix_socket, 0)) { - if ((rc= mysql_stmt_reset(prep_stmt))) - printf("OK!\n"); - else - { - printf("Error!"); - DIE_UNLESS(1==0); - } - } - else - { - fprintf(stderr, "expected error but no error occured\n"); - DIE_UNLESS(1==0); + fprintf(stderr, "Failed to connect to the database\n"); + DIE_UNLESS(0); } + + prep_stmt= mysql_stmt_init(lmysql); + rc= mysql_stmt_prepare(prep_stmt, "SELECT 1", 8); + DIE_UNLESS(rc == 0); + + mysql_close(lmysql); + + rc= mysql_stmt_execute(prep_stmt); + DIE_UNLESS(rc); + rc= mysql_stmt_reset(prep_stmt); + DIE_UNLESS(rc); rc= mysql_stmt_close(prep_stmt); - client_connect(0); + DIE_UNLESS(rc == 0); } #endif /* EMBEDDED_LIBRARY */ @@ -15216,7 +15214,6 @@ static void test_bug14169() /* Test that mysql_insert_id() behaves as documented in our manual */ - static void test_mysql_insert_id() { my_ulonglong res; @@ -15241,6 +15238,22 @@ static void test_mysql_insert_id() myquery(rc); res= mysql_insert_id(mysql); DIE_UNLESS(res == 0); + + /* + Test for bug #34889: mysql_client_test::test_mysql_insert_id test fails + sporadically + */ + rc= mysql_query(mysql, "create table t2 (f1 int not null primary key auto_increment, f2 varchar(255))"); + myquery(rc); + rc= mysql_query(mysql, "insert into t2 values (null,'b')"); + myquery(rc); + rc= mysql_query(mysql, "insert into t1 select 5,'c'"); + myquery(rc); + res= mysql_insert_id(mysql); + DIE_UNLESS(res == 0); + rc= mysql_query(mysql, "drop table t2"); + myquery(rc); + rc= mysql_query(mysql, "insert into t1 select null,'d'"); myquery(rc); res= mysql_insert_id(mysql); @@ -15759,6 +15772,7 @@ static void test_bug24179() mysql_stmt_error(stmt)); } DIE_UNLESS(mysql_stmt_errno(stmt) == 1323); + mysql_stmt_close(stmt); DBUG_VOID_RETURN; } @@ -15801,6 +15815,7 @@ static void test_bug27876() myquery(rc); result= mysql_store_result(mysql); mytest(result); + mysql_free_result(result); sprintf(query, "DROP FUNCTION IF EXISTS %s", utf8_func); rc= mysql_query(mysql, query); @@ -15817,6 +15832,7 @@ static void test_bug27876() myquery(rc); result= mysql_store_result(mysql); mytest(result); + mysql_free_result(result); sprintf(query, "DROP FUNCTION %s", utf8_func); rc= mysql_query(mysql, query); @@ -15936,6 +15952,7 @@ static void test_bug27592() DBUG_VOID_RETURN; } +#if 0 static void test_bug29948() { @@ -15965,6 +15982,7 @@ static void test_bug29948() exit(1); } + bzero(&bind, sizeof(bind)); bind.buffer_type= MYSQL_TYPE_LONG; bind.buffer= (char *)&buf; bind.is_null= &is_null; @@ -16010,6 +16028,8 @@ static void test_bug29948() mysql_close(dbc); } +#endif + /** Bug#29306 Truncated data in MS Access with decimal (3,1) columns in a VIEW */ @@ -16152,6 +16172,99 @@ static void test_bug31669() DBUG_VOID_RETURN; } + +/** + Bug#32265 Server returns different metadata if prepared statement is used +*/ + +static void test_bug32265() +{ + int rc; + MYSQL_STMT *stmt; + MYSQL_FIELD *field; + MYSQL_RES *metadata; + + DBUG_ENTER("test_bug32265"); + myheader("test_bug32265"); + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + myquery(rc); + rc= mysql_query(mysql, "CREATE TABLE t1 (a INTEGER)"); + myquery(rc); + rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1)"); + myquery(rc); + rc= mysql_query(mysql, "CREATE VIEW v1 AS SELECT * FROM t1"); + myquery(rc); + + stmt= open_cursor("SELECT * FROM t1"); + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + + metadata= mysql_stmt_result_metadata(stmt); + field= mysql_fetch_field(metadata); + DIE_UNLESS(field); + DIE_UNLESS(strcmp(field->table, "t1") == 0); + DIE_UNLESS(strcmp(field->org_table, "t1") == 0); + DIE_UNLESS(strcmp(field->db, "client_test_db") == 0); + mysql_free_result(metadata); + mysql_stmt_close(stmt); + + stmt= open_cursor("SELECT a '' FROM t1 ``"); + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + + metadata= mysql_stmt_result_metadata(stmt); + field= mysql_fetch_field(metadata); + DIE_UNLESS(strcmp(field->table, "") == 0); + DIE_UNLESS(strcmp(field->org_table, "t1") == 0); + DIE_UNLESS(strcmp(field->db, "client_test_db") == 0); + mysql_free_result(metadata); + mysql_stmt_close(stmt); + + stmt= open_cursor("SELECT a '' FROM t1 ``"); + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + + metadata= mysql_stmt_result_metadata(stmt); + field= mysql_fetch_field(metadata); + DIE_UNLESS(strcmp(field->table, "") == 0); + DIE_UNLESS(strcmp(field->org_table, "t1") == 0); + DIE_UNLESS(strcmp(field->db, "client_test_db") == 0); + mysql_free_result(metadata); + mysql_stmt_close(stmt); + + stmt= open_cursor("SELECT * FROM v1"); + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + + metadata= mysql_stmt_result_metadata(stmt); + field= mysql_fetch_field(metadata); + DIE_UNLESS(strcmp(field->table, "v1") == 0); + DIE_UNLESS(strcmp(field->org_table, "t1") == 0); + DIE_UNLESS(strcmp(field->db, "client_test_db") == 0); + mysql_free_result(metadata); + mysql_stmt_close(stmt); + + stmt= open_cursor("SELECT * FROM v1 /* SIC */ GROUP BY 1"); + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + + metadata= mysql_stmt_result_metadata(stmt); + field= mysql_fetch_field(metadata); + DIE_UNLESS(strcmp(field->table, "v1") == 0); + DIE_UNLESS(strcmp(field->org_table, "t1") == 0); + DIE_UNLESS(strcmp(field->db, "client_test_db") == 0); + mysql_free_result(metadata); + mysql_stmt_close(stmt); + + rc= mysql_query(mysql, "DROP VIEW v1"); + myquery(rc); + rc= mysql_query(mysql, "DROP TABLE t1"); + myquery(rc); + + DBUG_VOID_RETURN; +} + /* Read and parse arguments and MySQL options from my.cnf */ @@ -16443,9 +16556,10 @@ static struct my_tests_st my_tests[]= { { "test_bug28505", test_bug28505 }, { "test_bug28934", test_bug28934 }, { "test_bug27592", test_bug27592 }, - { "test_bug29948", test_bug29948 }, + /* { "test_bug29948", test_bug29948 }, Bug#35103 */ { "test_bug29306", test_bug29306 }, { "test_bug31669", test_bug31669 }, + { "test_bug32265", test_bug32265 }, { 0, 0 } }; diff --git a/vio/viossl.c b/vio/viossl.c index c178d9e9d1b..eea274cf92d 100644 --- a/vio/viossl.c +++ b/vio/viossl.c @@ -172,20 +172,15 @@ void vio_ssl_delete(Vio *vio) vio_delete(vio); } -int sslaccept(struct st_VioSSLFd *ptr, Vio *vio, long timeout) -{ - DBUG_ENTER("sslaccept"); - DBUG_RETURN(sslconnect(ptr, vio, timeout)); -} - -int sslconnect(struct st_VioSSLFd *ptr, Vio *vio, long timeout) +static int ssl_do(struct st_VioSSLFd *ptr, Vio *vio, long timeout, + int (*connect_accept_func)(SSL*)) { SSL *ssl; my_bool unused; my_bool was_blocking; - DBUG_ENTER("sslconnect"); + DBUG_ENTER("ssl_do"); DBUG_PRINT("enter", ("ptr: 0x%lx, sd: %d ctx: 0x%lx", (long) ptr, vio->sd, (long) ptr->ssl_context)); @@ -204,13 +199,9 @@ int sslconnect(struct st_VioSSLFd *ptr, Vio *vio, long timeout) SSL_SESSION_set_timeout(SSL_get_session(ssl), timeout); SSL_set_fd(ssl, vio->sd); - /* - SSL_do_handshake will select between SSL_connect - or SSL_accept depending on server or client side - */ - if (SSL_do_handshake(ssl) < 1) + if (connect_accept_func(ssl) < 1) { - DBUG_PRINT("error", ("SSL_do_handshake failure")); + DBUG_PRINT("error", ("SSL_connect/accept failure")); report_errors(ssl); SSL_free(ssl); vio_blocking(vio, was_blocking, &unused); @@ -259,6 +250,20 @@ int sslconnect(struct st_VioSSLFd *ptr, Vio *vio, long timeout) } +int sslaccept(struct st_VioSSLFd *ptr, Vio *vio, long timeout) +{ + DBUG_ENTER("sslaccept"); + DBUG_RETURN(ssl_do(ptr, vio, timeout, SSL_accept)); +} + + +int sslconnect(struct st_VioSSLFd *ptr, Vio *vio, long timeout) +{ + DBUG_ENTER("sslconnect"); + DBUG_RETURN(ssl_do(ptr, vio, timeout, SSL_connect)); +} + + int vio_ssl_blocking(Vio *vio __attribute__((unused)), my_bool set_blocking_mode, my_bool *old_mode) @@ -269,4 +274,6 @@ int vio_ssl_blocking(Vio *vio __attribute__((unused)), return (set_blocking_mode ? 0 : 1); } + + #endif /* HAVE_OPENSSL */ |