diff options
199 files changed, 2986 insertions, 1068 deletions
diff --git a/.bzrignore b/.bzrignore index a7c02ee341b..8583b7ef437 100644 --- a/.bzrignore +++ b/.bzrignore @@ -544,3 +544,4 @@ vio/test-sslclient vio/test-sslserver vio/viotest-ssl scripts/make_win_binary_distribution +EXCEPTIONS-CLIENT diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 7a3063c3884..698f7655b6e 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -5,6 +5,7 @@ Administrator@fred. Greg@greg-laptop. Miguel@light.local Sinisa@sinisa.nasamreza.org +acurtis@pcgem.rdg.cyberkinetica.com ahlentz@co3064164-a.rochd1.qld.optusnet.com.au akishkin@work.mysql.com antony@ltantony.dsl-verizon.net @@ -15,11 +16,13 @@ arjen@george.bitbike.com bar@bar.intranet.mysql.r18.ru bar@bar.mysql.r18.ru bar@bar.udmsearch.izhnet.ru +bar@mysql.com bell@laptop.sanja.is.com.ua bell@sanja.is.com.ua bk@admin.bk carsten@tsort.bitbybit.dk davida@isil.mysql.com +dlenev@brandersnatch.localdomain dlenev@build.mysql.com dlenev@mysql.com gerberb@ou800.zenez.com @@ -55,6 +58,7 @@ jcole@main.burghcom.com jcole@mugatu.spaceapes.com jcole@sarvik.tfr.cafe.ee jcole@tetra.spaceapes.com +joerg@mysql.com jorge@linux.jorge.mysql.com kaj@work.mysql.com konstantin@mysql.com @@ -66,6 +70,7 @@ miguel@hegel.(none) miguel@hegel.br miguel@hegel.local miguel@hegel.txg +miguel@hegel.txg.br miguel@light. miguel@light.local miguel@sartre.local @@ -107,6 +112,7 @@ ram@gw.mysql.r18.ru ram@mysql.r18.ru ram@ram.(none) ranger@regul.home.lan +rburnett@build.mysql.com root@x3.internalnet salle@geopard.(none) salle@geopard.online.bg diff --git a/Build-tools/Bootstrap b/Build-tools/Bootstrap index a46d83ca91c..8cad093bc5f 100755 --- a/Build-tools/Bootstrap +++ b/Build-tools/Bootstrap @@ -28,8 +28,8 @@ else # Some predefined settings $build_command= "BUILD/compile-pentium-max"; $PWD= cwd(); -$LOGFILE= $PWD . "/Bootstrap.log"; $opt_docdir= $PWD . "/mysqldoc"; +$opt_archive_log= undef; $opt_build_command= undef; $opt_changelog= undef; $opt_delete= undef; @@ -46,10 +46,12 @@ $opt_test= undef; $opt_skip_check= undef; $opt_skip_manual= undef; $opt_win_dist= undef; +$opt_quiet= undef; $version= "unknown"; $major=$minor=$release=0; GetOptions( + "archive-log|a", "build-command|b=s", "changelog|c:s", "directory|d=s", @@ -67,10 +69,22 @@ GetOptions( "suffix=s", "test|t", "verbose|v", - "win-dist|w" + "win-dist|w", + "quiet|q", ) || print_help(""); # +# Override predefined build command +# +if (defined $opt_build_command) +{ + $build_command= $opt_build_command; +} + +print_help("") if ($opt_help); +defined($REPO=$ARGV[0]) || print_help("Please enter the BK repository to be used!"); + +# # Override predefined Log file name # if (defined $opt_log) @@ -88,18 +102,7 @@ if (defined $opt_log) } } -# -# Override predefined build command -# -if (defined $opt_build_command) -{ - $build_command= $opt_build_command; -} - -print_help("") if ($opt_help); -defined($REPO=$ARGV[0]) || print_help("Please enter the BK repository to be used!"); - -$subject= "Bootstrap of $REPO failed" if $opt_mail; +$LOGFILE= $PWD . "/Bootstrap-" . $REPO . ".log" unless ($LOGFILE); &logger("Starting build"); &abort("The directory \"$REPO\" could not be found!") if (!-d $REPO); @@ -120,14 +123,16 @@ if (($opt_directory ne $PWD) && (!-d $opt_directory && !$opt_dry_run)) if ($opt_pull) { &logger("Updating BK tree $REPO to latest ChangeSet first"); - $command= "cd $REPO; bk pull; cd .."; - &run_command($command, "Could not update $REPO!"); + chdir ($REPO) or &abort("Could not chdir to $REPO!"); + &run_command("bk pull", "Could not update $REPO!"); + chdir ($PWD) or &abort("Could not chdir to $PWD!"); unless ($opt_skip_manual) { &logger("Updating manual tree in $opt_docdir"); - $command= "cd $opt_docdir; bk pull; cd .."; - &run_command($command, "Could not update $opt_docdir!"); + chdir ($opt_docdir) or &abort("Could not chdir to $opt_docdir!"); + &run_command("bk pull", "Could not update $opt_docdir!"); + chdir ($PWD) or &abort("Could not chdir to $PWD!"); } } @@ -306,7 +311,7 @@ if (!$opt_dry_run) # # Now build the source distribution # -&logger("Compiling"); +&logger("Compiling..."); $command= $build_command; &run_command($command, "Compilation failed!"); @@ -351,6 +356,21 @@ if (!$opt_skip_check) # All done when we came down here # &logger("SUCCESS: Build finished successfully.") if (!$opt_dry_run); + +# +# Move the log file into the Log dir of the target dir +# +if ($opt_archive_log) +{ + my $logdir= $target_dir . "/Logs"; + &logger("Moving $LOGFILE to $logdir"); + mkdir "$logdir" if (! -d $logdir); + $command= "mv "; + $command.= "-v " if ($opt_verbose || defined $opt_log); + $command.= "$LOGFILE $logdir"; + &run_command($command, "Could not move $LOGFILE to $logdir!"); +} + exit 0; # @@ -378,6 +398,8 @@ distribution check can be run before the source archive is being created. Options: +-a, --archive-log Move the log file into the Logs directory of + the exported tree after a successful build -b, --build-command=<cmd> Use <cmd> to compile the sources before packing the distribution. (default is "$build_command") @@ -398,11 +420,12 @@ Options: do not build or test the source distribution -h, --help Print this help message -l, --log[=<filename>] Write a log file [to <filename>] - (default is "$LOGFILE") + (default is "./Bootstrap-<bk repository>.log") -m, --mail=<address> Mail a failure report to the given address (and include a log file snippet, if logging is enabled) Note that the \@-Sign needs to be quoted! Example: --mail=user\\\@domain.com +-q, --quiet Be quiet -p, --pull Update the source BK trees before building -r, --revision=<rev> Export the tree as of revision <rev> (default is up to the latest revision) diff --git a/Build-tools/Do-compile b/Build-tools/Do-compile index d79fd1f0b65..f92af463a0a 100755 --- a/Build-tools/Do-compile +++ b/Build-tools/Do-compile @@ -169,6 +169,17 @@ info("PATH is $ENV{PATH}"); log_timestamp(); +$md5_result= safe_system("perl $ENV{HOME}/my_md5sum -c ${opt_distribution}.md5"); + +if ($md5_result != 0) +{ + abort("MD5 check failed for $opt_distribution!"); +} +else +{ + info("SUCCESS: MD5 checks for $opt_distribution"); +} + if (-x "$host/bin/mysqladmin") { log_system("$host/bin/mysqladmin $mysqladmin_args -S $mysql_unix_port -s shutdown"); @@ -320,6 +331,11 @@ if ($opt_stage <= 3) $tar_file=<$pwd/$host/mysql*.t*gz>; abort ("Could not find tarball!") unless ($tar_file); +# Generate the MD5 for the binary distribution +$tar_file=~ /(mysql[^\/]*)\.(tar\.gz|tgz)/; +$tar_file_lite= "$1.$2"; +system("cd $pwd/$host; perl $ENV{HOME}/my_md5sum $tar_file_lite > ${tar_file_lite}.md5"); + # # Unpack the binary distribution # @@ -345,7 +361,7 @@ if ($opt_stage <= 5 && !$opt_no_test && !$opt_no_mysqltest) log_timestamp(); system("mkdir $bench_tmpdir") if (! -d $bench_tmpdir); safe_cd("${test_dir}/mysql-test"); - check_system("./mysql-test-run --warnings --tmpdir=$bench_tmpdir --master_port=$mysql_tcp_port --slave_port=$slave_port --manager-port=$manager_port --no-manager --sleep=10", "tests were successful"); + check_system("./mysql-test-run --tmpdir=$bench_tmpdir --master_port=$mysql_tcp_port --slave_port=$slave_port --manager-port=$manager_port --no-manager --sleep=10", "tests were successful"); } # @@ -633,7 +649,10 @@ sub safe_system my($com,$res)=@_; print LOG "$com\n"; print "$host: $com\n" if ($opt_debug); - system("$com >> $log 2>&1") && abort("error: Couldn't execute command, error: " . ($? / 256)); + my $result= system("$com >> $log 2>&1"); + abort("error: Couldn't execute command, error: " . ($? / 256)) unless $result == 0; + + return $result; } sub check_system diff --git a/Build-tools/logger.pm b/Build-tools/logger.pm index 835d8014aa0..d3fb4c9db2f 100644 --- a/Build-tools/logger.pm +++ b/Build-tools/logger.pm @@ -5,7 +5,10 @@ # sub logger { - my $message=$_[0]; + my $message= $_[0]; + my $cmnd= $_[1]; + + print $message . "\n" if !$opt_quiet && !$opt_verbose && !$cmnd; print timestamp() . " " . $message . "\n" if $opt_verbose; if (defined $opt_log && !$opt_dry_run) { @@ -30,9 +33,12 @@ sub run_command } else { - &logger($command); - $command.= " >> $LOGFILE 2>&1" if defined $opt_log; - $command.= " > /dev/null" if (!$opt_verbose && !$opt_log); + &logger($command, 1); + + $command.= ';' unless ($command =~ m/^.*;$/); + + $command =~ s/;/ >> $LOGFILE 2>&1;/g if defined $opt_log; + $command =~ s/;/ > \/dev\/null;/g if (!$opt_verbose && !$opt_log); system($command) == 0 or &abort("$errormsg\n"); } } @@ -47,6 +53,7 @@ sub abort { my $message= $_[0]; my $messagefile; + my $subject= "Bootstrap of $REPO failed" if $opt_mail; $message= "ERROR: " . $message; &logger($message); diff --git a/Build-tools/my_md5sum b/Build-tools/my_md5sum index 20742ee2ed0..f4ac2f7d674 100755 --- a/Build-tools/my_md5sum +++ b/Build-tools/my_md5sum @@ -10,10 +10,22 @@ # Written by Matt Wagner <matt@mysql.com> # use strict; + +# +# Use local perl libraries first. 'unshift' adds to the front of @INC +# The local perl library dir hidden is $HOME/.perllibs on each build host +# +BEGIN +{ + my $homedir= $ENV{HOME}; + unshift (@INC, "$homedir/.perllibs"); +} + use Digest::MD5; use Getopt::Long; -my $VER= "1.1"; +my $VER= "1.3"; +my $EXIT= 0; # # Strip the leading path info off the program name ($0). We want 'my_md5sum' @@ -67,6 +79,9 @@ if ($opt_check) # Print an error message if they don't match, else print OK print "$checkfile: FAILED\n" if $digest ne $checksum; print "$checkfile: OK\n" if $digest eq $checksum; + + # Set the exit() status to non-zero if FAILED + $EXIT= 1 if $digest ne $checksum; } } # Else generate the MD5 digest to STDOUT @@ -80,6 +95,8 @@ else } } +exit($EXIT); + # # This routine generates the MD5 digest of a file diff --git a/Build-tools/mysql-copyright b/Build-tools/mysql-copyright index f3a2a2960ea..ad4547b493c 100755 --- a/Build-tools/mysql-copyright +++ b/Build-tools/mysql-copyright @@ -101,6 +101,7 @@ sub main # on the toplevel of the directory instead. file 'PUBLIC' shouldn't # exist in the new mysql distributions, but let's be sure.. unlink("$destdir/PUBLIC", "$destdir/README"); + unlink("$destdir/COPYING", "$destdir/EXCEPTIONS-CLIENT"); copy("$WD/Docs/MySQLEULA.txt", "$destdir"); # remove readline subdir and update configure accordingly @@ -119,7 +120,7 @@ sub main open(CONFIGURE,">configure.in") or die "$! Unable to open configure.in to write to!\n"; print CONFIGURE $configure; close(CONFIGURE); - `autoconf`; + `aclocal && autoheader && aclocal && automake && autoconf`; if (! -f "configure") { print "\"./configure\" was not produced, exiting!\n"; exit(0); diff --git a/Docs/Makefile.am b/Docs/Makefile.am index 9a77202a91b..a4e8e14a38d 100644 --- a/Docs/Makefile.am +++ b/Docs/Makefile.am @@ -26,7 +26,7 @@ EXTRA_DIST = $(noinst_SCRIPTS) $(BUILT_SOURCES) mysqld_error.txt \ all: $(targets) txt_files -txt_files: ../INSTALL-SOURCE ../COPYING \ +txt_files: ../INSTALL-SOURCE ../COPYING ../EXCEPTIONS-CLIENT \ INSTALL-BINARY ../support-files/MacOSX/ReadMe.txt CLEAN_FILES: $(BUILD_SOURCES) @@ -202,7 +202,10 @@ INSTALL-BINARY: mysql.info $(GT) perl -w $(GT) mysql.info "Installing binary" "Installing source" > $@ ../COPYING: mysql.info $(GT) - perl -w $(GT) mysql.info "GPL license" "Function Index" > $@ + perl -w $(GT) mysql.info "GPL license" "MySQL FLOSS License Exception" > $@ + +../EXCEPTIONS-CLIENT: mysql.info $(GT) + perl -w $(GT) mysql.info "MySQL FLOSS License Exception" "Function Index" > $@ ../support-files/MacOSX/ReadMe.txt: mysql.info $(GT) perl -w $(GT) mysql.info "Mac OS X installation" "NetWare installation" > $@ diff --git a/Makefile.am b/Makefile.am index 8a5df17c2cb..fb0735b562c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -19,7 +19,7 @@ AUTOMAKE_OPTIONS = foreign # These are built from source in the Docs directory -EXTRA_DIST = INSTALL-SOURCE README COPYING +EXTRA_DIST = INSTALL-SOURCE README COPYING EXCEPTIONS-CLIENT SUBDIRS = . include @docs_dirs@ @readline_dir@ \ @thread_dirs@ pstack @sql_client_dirs@ \ @sql_server_dirs@ scripts man tests \ diff --git a/VC++Files/innobase/innobase.dsp b/VC++Files/innobase/innobase.dsp index ea0aaeb3b83..25e9d5d75b8 100644 --- a/VC++Files/innobase/innobase.dsp +++ b/VC++Files/innobase/innobase.dsp @@ -368,6 +368,10 @@ SOURCE=.\row\row0vers.c # End Source File # Begin Source File +SOURCE=.\srv\srv0que.c +# End Source File +# Begin Source File + SOURCE=.\srv\srv0srv.c # End Source File # Begin Source File diff --git a/VC++Files/sql/message.mc b/VC++Files/sql/message.mc new file mode 100644 index 00000000000..a1a7c8cff7e --- /dev/null +++ b/VC++Files/sql/message.mc @@ -0,0 +1,8 @@ +MessageId = 100 +Severity = Error +Facility = Application +SymbolicName = MSG_DEFAULT +Language = English +%1For more information, see Help and Support Center at http://www.mysql.com. + + diff --git a/VC++Files/sql/mysqld.dsp b/VC++Files/sql/mysqld.dsp index 454b79abe43..3198c918a5e 100644 --- a/VC++Files/sql/mysqld.dsp +++ b/VC++Files/sql/mysqld.dsp @@ -187,7 +187,7 @@ LINK32=xilink6.exe # PROP Target_Dir "" # ADD BASE CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /D "DBUG_OFF" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "USE_SYMDIR" /D "HAVE_DLOPEN" /D "NDEBUG" /FD /c # SUBTRACT BASE CPP /YX -# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /D LICENSE=Commercial /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "HAVE_DLOPEN" /D "DBUG_OFF" /D "_MBCS" /D "NDEBUG" /FD /c +# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /D LICENSE=Commercial /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "HAVE_DLOPEN" /D "DBUG_OFF" /D "_MBCS" /D "NDEBUG" /FD /D MYSQL_SERVER_SUFFIX=-classic /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe @@ -243,7 +243,7 @@ LINK32=xilink6.exe # PROP Target_Dir "" # ADD BASE CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /D "DBUG_OFF" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "USE_SYMDIR" /D "HAVE_DLOPEN" /D "NDEBUG" /FD /c # SUBTRACT BASE CPP /YX -# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /D "__NT__" /D "DBUG_OFF" /D "NDEBUG" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /FD /D LICENSE=Commercial /D MYSQL_SERVER_SUFFIX=-nt /c +# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /D "__NT__" /D "DBUG_OFF" /D "NDEBUG" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /FD /D LICENSE=Commercial /D MYSQL_SERVER_SUFFIX=-classic-nt /c # SUBTRACT CPP /YX # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" @@ -900,6 +900,89 @@ SOURCE=.\log_event.cpp # End Source File # Begin Source File +SOURCE=.\message.mc + +!IF "$(CFG)" == "mysqld - Win32 Release" + +!ELSEIF "$(CFG)" == "mysqld - Win32 Debug" + +!ELSEIF "$(CFG)" == "mysqld - Win32 nt" + +# Begin Custom Build - Compiling messages +InputDir=. +InputPath=.\message.mc +InputName=message + +BuildCmds= \ + mc.exe "$(InputDir)\$(InputName).mc" + +"$(InputDir)\$(InputName).rc" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)\$(InputName).h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ELSEIF "$(CFG)" == "mysqld - Win32 Max nt" +# Begin Custom Build - Compiling messages +InputDir=. +InputPath=.\message.mc +InputName=message + +BuildCmds= \ + mc.exe "$(InputDir)\$(InputName).mc" + +"$(InputDir)\$(InputName).rc" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)\$(InputName).h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build +!ELSEIF "$(CFG)" == "mysqld - Win32 Max" + +!ELSEIF "$(CFG)" == "mysqld - Win32 classic" + +!ELSEIF "$(CFG)" == "mysqld - Win32 pro" + +!ELSEIF "$(CFG)" == "mysqld - Win32 classic nt" +# Begin Custom Build - Compiling messages +InputDir=. +InputPath=.\message.mc +InputName=message + +BuildCmds= \ + mc.exe "$(InputDir)\$(InputName).mc" + +"$(InputDir)\$(InputName).rc" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)\$(InputName).h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build +!ELSEIF "$(CFG)" == "mysqld - Win32 pro nt" +# Begin Custom Build - Compiling messages +InputDir=. +InputPath=.\message.mc +InputName=message + +BuildCmds= \ + mc.exe "$(InputDir)\$(InputName).mc" + +"$(InputDir)\$(InputName).rc" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)\$(InputName).h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\message.rc +# End Source File +# Begin Source File + SOURCE=.\mf_iocache.cpp !IF "$(CFG)" == "mysqld - Win32 Release" diff --git a/acconfig.h b/acconfig.h index 825842d256a..71dea4825f6 100644 --- a/acconfig.h +++ b/acconfig.h @@ -281,6 +281,9 @@ /* READLINE: */ #undef VOID_SIGHANDLER +/* Define this if you want extra character set conversion table*/ +#undef DEFINE_ALL_CHARACTER_SETS + /* Leave that blank line there!! Autoheader needs it. If you're adding to this file, keep in mind: diff --git a/client/mysql.cc b/client/mysql.cc index 66a99bbdf75..154695aa9e5 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -279,7 +279,8 @@ static void initialize_readline (char *name); #endif static COMMANDS *find_command (char *name,char cmd_name); -static bool add_line(String &buffer,char *line,char *in_string); +static bool add_line(String &buffer, char *line, char *in_string, + my_bool *in_comment); static void remove_cntrl(String &buffer); static void print_table_data(MYSQL_RES *result); static void print_table_data_html(MYSQL_RES *result); @@ -800,6 +801,7 @@ static int read_lines(bool execute_commands) #endif char *line; char in_string=0; + my_bool in_comment= 0; ulong line_number=0; COMMANDS *com; status.exit_status=1; @@ -879,7 +881,7 @@ static int read_lines(bool execute_commands) #endif continue; } - if (add_line(glob_buffer,line,&in_string)) + if (add_line(glob_buffer, line, &in_string, &in_comment)) break; } /* if in batch mode, send last query even if it doesn't end with \g or go */ @@ -939,12 +941,12 @@ static COMMANDS *find_command (char *name,char cmd_char) } -static bool add_line(String &buffer,char *line,char *in_string) +static bool add_line(String &buffer,char *line,char *in_string, + my_bool *in_comment) { uchar inchar; char buff[80],*pos,*out; COMMANDS *com; - my_bool in_comment= 0; if (!line[0] && buffer.is_empty()) return 0; @@ -1004,7 +1006,7 @@ static bool add_line(String &buffer,char *line,char *in_string) continue; } } - else if (inchar == ';' && !*in_string && !in_comment) + else if (inchar == ';' && !*in_string && !*in_comment) { // ';' is end of command if (out != line) buffer.append(line,(uint) (out-line)); // Add this line @@ -1032,15 +1034,15 @@ static bool add_line(String &buffer,char *line,char *in_string) { // Add found char to buffer if (inchar == *in_string) *in_string=0; - else if (!in_comment && !*in_string && (inchar == '\'' || inchar == '"' || inchar == '`')) + else if (!*in_comment && !*in_string && (inchar == '\'' || inchar == '"' || inchar == '`')) *in_string=(char) inchar; *out++ = (char) inchar; if (inchar == '*' && !*in_string) { if (pos != line && pos[-1] == '/') - in_comment= 1; + *in_comment= 1; else if (in_comment && pos[1] == '/') - in_comment= 0; + *in_comment= 0; } } } @@ -2351,13 +2353,16 @@ com_status(String *buffer __attribute__((unused)), MYSQL_RES *result; LINT_INIT(result); tee_fprintf(stdout, "\nConnection id:\t\t%lu\n",mysql_thread_id(&mysql)); - if (!mysql_query(&mysql,"select DATABASE(),USER()") && + if (!mysql_query(&mysql,"select DATABASE(), USER() limit 1") && (result=mysql_use_result(&mysql))) { MYSQL_ROW cur=mysql_fetch_row(result); - tee_fprintf(stdout, "Current database:\t%s\n", cur[0] ? cur[0] : ""); - tee_fprintf(stdout, "Current user:\t\t%s\n",cur[1]); - (void) mysql_fetch_row(result); // Read eof + if (cur) + { + tee_fprintf(stdout, "Current database:\t%s\n", cur[0] ? cur[0] : ""); + tee_fprintf(stdout, "Current user:\t\t%s\n", cur[1]); + } + mysql_free_result(result); } #ifdef HAVE_OPENSSL if (mysql.net.vio && mysql.net.vio->ssl_arg && diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 7bceedea4fe..7c3d22c4900 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -723,8 +723,8 @@ static int dump_remote_log_entries(const char* logname) */ if (old_off) old_off+= len-1; - else - old_off= BIN_LOG_HEADER_SIZE; + else // first event, so it's a fake Rotate event + old_off= position; } return 0; } diff --git a/client/mysqltest.c b/client/mysqltest.c index 68b9dd505b2..2ec07692a4d 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -1817,13 +1817,6 @@ int read_query(struct st_query** q_ptr) q->record_file[0] = 0; q->require_file=0; q->first_word_len = 0; - memcpy((gptr) q->expected_errno, (gptr) global_expected_errno, - sizeof(global_expected_errno)); - q->expected_errors=global_expected_errors; - q->abort_on_error = global_expected_errno[0] == 0; - bzero((gptr) global_expected_errno,sizeof(global_expected_errno)); - global_expected_errors=0; - q->type = Q_UNKNOWN; q->query_buf=q->query=0; if (read_line(read_query_buf, sizeof(read_query_buf))) @@ -1832,8 +1825,16 @@ int read_query(struct st_query** q_ptr) if (*p == '#') { q->type = Q_COMMENT; + /* This goto is to avoid losing the "expected error" info. */ + goto end; } - else if (p[0] == '-' && p[1] == '-') + memcpy((gptr) q->expected_errno, (gptr) global_expected_errno, + sizeof(global_expected_errno)); + q->expected_errors=global_expected_errors; + q->abort_on_error = global_expected_errno[0] == 0; + bzero((gptr) global_expected_errno,sizeof(global_expected_errno)); + global_expected_errors=0; + if (p[0] == '-' && p[1] == '-') { q->type = Q_COMMENT_WITH_COMMAND; p+=2; /* To calculate first word */ @@ -1868,6 +1869,8 @@ int read_query(struct st_query** q_ptr) *p1 = 0; } } + +end: while (*p && my_isspace(charset_info,*p)) p++; if (!(q->query_buf=q->query=my_strdup(p,MYF(MY_WME)))) diff --git a/configure.in b/configure.in index e346ebfa15e..7853b615ae0 100644 --- a/configure.in +++ b/configure.in @@ -768,7 +768,7 @@ AC_CHECK_FUNC(sem_init, , AC_CHECK_LIB(posix4, sem_init)) # For compress in zlib case $SYSTEM_TYPE in - *netware*) + *netware* | *modesto*) AC_DEFINE(HAVE_COMPRESS) ;; *) @@ -936,6 +936,16 @@ esac MAX_C_OPTIMIZE="-O3" MAX_CXX_OPTIMIZE="-O3" +# workaround for Sun Forte/x86 see BUG#4681 +case $SYSTEM_TYPE-$MACHINE_TYPE-$ac_cv_prog_gcc in + *solaris*-i?86-no) + CFLAGS="$CFLAGS -DBIG_FILES" + CXXFLAGS="$CXXFLAGS -DBIG_FILES" + ;; + *) ;; +esac + + case $SYSTEM_TYPE in *solaris2.7*) # Solaris 2.7 has a broken /usr/include/widec.h @@ -1037,10 +1047,11 @@ case $SYSTEM_TYPE in MAX_C_OPTIMIZE="-O" fi ;; - *darwin7*) + *darwin[[7-8]]*) + # don't forget to escape [] like above if test "$ac_cv_prog_gcc" = "yes" then - FLAGS="-DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ" + FLAGS="-DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DIGNORE_SIGHUP_SIGQUIT" CFLAGS="$CFLAGS $FLAGS" CXXFLAGS="$CXXFLAGS $FLAGS" MAX_C_OPTIMIZE="-O" @@ -1280,6 +1291,7 @@ then with_named_thread="-lgthreads -lsocket -lgthreads" # sched.h conflicts with fsu-threads touch ./include/sched.h + touch ./include/semaphore.h # We must have gcc if expr "$CC" : ".*gcc.*" @@ -2250,9 +2262,11 @@ elif test "$extra_charsets" = complex; then CHARSETS=`/bin/ls -1 $srcdir/strings/ctype-*.c | \ sed -e 's;^.*/ctype-;;' -e 's;.c$;;'` CHARSETS=`echo $CHARSETS` # get rid of line breaks + AC_DEFINE([DEFINE_ALL_CHARACTER_SETS]) else if test "$extra_charsets" = all; then CHARSETS="$CHARSETS_AVAILABLE $CHARSETS_DEPRECATED" + AC_DEFINE([DEFINE_ALL_CHARACTER_SETS]) else CHARSETS=`echo $extra_charsets | sed -e 's/,/ /g'` fi diff --git a/extra/mysql_waitpid.c b/extra/mysql_waitpid.c index bff1752ec21..c228cc52c8b 100644 --- a/extra/mysql_waitpid.c +++ b/extra/mysql_waitpid.c @@ -20,6 +20,7 @@ #include <my_global.h> #include <m_string.h> +#include <my_sys.h> #include <my_getopt.h> #include <signal.h> #include <errno.h> diff --git a/include/m_string.h b/include/m_string.h index eb2758ec506..419e70d93bf 100644 --- a/include/m_string.h +++ b/include/m_string.h @@ -238,6 +238,9 @@ extern char *str2int(const char *src,int radix,long lower,long upper, #ifndef HAVE_STRTOULL #define HAVE_STRTOULL #endif +#ifndef HAVE_STRTOLL +#define HAVE_STRTOLL +#endif #else #ifdef HAVE_LONG_LONG extern char *longlong2str(longlong val,char *dst,int radix); diff --git a/include/my_getopt.h b/include/my_getopt.h index 3b4551b445e..e602773e181 100644 --- a/include/my_getopt.h +++ b/include/my_getopt.h @@ -14,10 +14,22 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#ifndef _my_getopt_h +#define _my_getopt_h + C_MODE_START -enum get_opt_var_type { GET_NO_ARG, GET_BOOL, GET_INT, GET_UINT, GET_LONG, - GET_ULONG, GET_LL, GET_ULL, GET_STR, GET_STR_ALLOC }; +#define GET_NO_ARG 1 +#define GET_BOOL 2 +#define GET_INT 3 +#define GET_UINT 4 +#define GET_LONG 5 +#define GET_ULONG 6 +#define GET_LL 7 +#define GET_ULL 8 +#define GET_STR 9 +#define GET_STR_ALLOC 10 + enum get_opt_arg_type { NO_ARG, OPT_ARG, REQUIRED_ARG }; struct my_option @@ -28,7 +40,7 @@ struct my_option gptr *value; /* The variable value */ gptr *u_max_value; /* The user def. max variable value */ const char **str_values; /* Pointer to possible values */ - enum get_opt_var_type var_type; + ulong var_type; enum get_opt_arg_type arg_type; longlong def_value; /* Default value */ longlong min_value; /* Min allowed value */ @@ -38,17 +50,22 @@ struct my_option int app_type; /* To be used by an application */ }; +typedef my_bool (* my_get_one_option) (int, const struct my_option *, char * ); +typedef void (* my_error_reporter) (enum loglevel level, const char *format, ... ); + extern char *disabled_my_option; extern my_bool my_getopt_print_errors; +extern my_error_reporter my_getopt_error_reporter; extern int handle_options (int *argc, char ***argv, - const struct my_option *longopts, - my_bool (*get_one_option)(int, - const struct my_option *, - char *)); + const struct my_option *longopts, my_get_one_option); extern void my_print_help(const struct my_option *options); extern void my_print_variables(const struct my_option *options); ulonglong getopt_ull_limit_value(ulonglong num, const struct my_option *optp); my_bool getopt_compare_strings(const char *s, const char *t, uint length); + C_MODE_END + +#endif /* _my_getopt_h */ + diff --git a/include/my_global.h b/include/my_global.h index 284cfdc1f97..f24fc05471e 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -641,23 +641,17 @@ extern double my_atof(const char*); #endif #endif /* defined (HAVE_LONG_LONG) && !defined(ULONGLONG_MAX)*/ -#if SIZEOF_LONG == 4 -#define INT_MIN32 (long) 0x80000000L -#define INT_MAX32 (long) 0x7FFFFFFFL -#define INT_MIN24 ((long) 0xff800000L) -#define INT_MAX24 0x007fffffL -#define INT_MIN16 ((short int) 0x8000) -#define INT_MAX16 0x7FFF -#define INT_MIN8 ((char) 0x80) -#define INT_MAX8 ((char) 0x7F) -#else /* Probably Alpha */ -#define INT_MIN32 ((long) (int) 0x80000000) -#define INT_MAX32 ((long) (int) 0x7FFFFFFF) -#define INT_MIN24 ((long) (int) 0xff800000) -#define INT_MAX24 ((long) (int) 0x007fffff) -#define INT_MIN16 ((short int) 0xffff8000) -#define INT_MAX16 ((short int) 0x00007FFF) -#endif +#define INT_MIN32 (~0x7FFFFFFFL) +#define INT_MAX32 0x7FFFFFFFL +#define UINT_MAX32 0xFFFFFFFFL +#define INT_MIN24 (~0x007FFFFF) +#define INT_MAX24 0x007FFFFF +#define UINT_MAX24 0x00FFFFFF +#define INT_MIN16 (~0x7FFF) +#define INT_MAX16 0x7FFF +#define UINT_MAX16 0xFFFF +#define INT_MIN8 (~0x7F) +#define INT_MAX8 0x7F /* From limits.h instead */ #ifndef DBL_MIN diff --git a/include/my_sys.h b/include/my_sys.h index 4934df3c4e5..9e43889d0e0 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -261,6 +261,12 @@ typedef struct st_typelib { /* Different types saved here */ const char **type_names; } TYPELIB; +enum loglevel { + ERROR_LEVEL, + WARNING_LEVEL, + INFORMATION_LEVEL +}; + enum cache_type { READ_CACHE,WRITE_CACHE, diff --git a/innobase/btr/btr0cur.c b/innobase/btr/btr0cur.c index 8974200efe8..b07b06765e6 100644 --- a/innobase/btr/btr0cur.c +++ b/innobase/btr/btr0cur.c @@ -2707,8 +2707,11 @@ btr_estimate_number_of_different_key_vals( rec = page_rec_get_next(rec); } + if (n_cols == dict_index_get_n_unique_in_tree(index)) { - /* We add one because we know that the first record + + /* If there is more than one leaf page in the tree, + we add one because we know that the first record on the page certainly had a different prefix than the last record on the previous index page in the alphabetical order. Before this fix, if there was @@ -2716,7 +2719,11 @@ btr_estimate_number_of_different_key_vals( algorithm grossly underestimated the number of rows in the table. */ - n_diff[n_cols]++; + if (btr_page_get_prev(page, &mtr) != FIL_NULL + || btr_page_get_next(page, &mtr) != FIL_NULL) { + + n_diff[n_cols]++; + } } total_external_size += diff --git a/innobase/buf/buf0flu.c b/innobase/buf/buf0flu.c index 7456e5d6f61..9eb8076732d 100644 --- a/innobase/buf/buf0flu.c +++ b/innobase/buf/buf0flu.c @@ -213,7 +213,9 @@ buf_flush_buffered_writes(void) /*===========================*/ { buf_block_t* block; + byte* write_buf; ulint len; + ulint len2; ulint i; if (trx_doublewrite == NULL) { @@ -240,6 +242,16 @@ buf_flush_buffered_writes(void) block = trx_doublewrite->buf_block_arr[i]; ut_a(block->state == BUF_BLOCK_FILE_PAGE); + if (mach_read_from_4(block->frame + FIL_PAGE_LSN + 4) + != mach_read_from_4(block->frame + UNIV_PAGE_SIZE + - FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) { + ut_print_timestamp(stderr); + fprintf(stderr, +" InnoDB: ERROR: The page to be written seems corrupt!\n" +"InnoDB: The lsn fields do not match! Noticed in the buffer pool\n" +"InnoDB: before posting to the doublewrite buffer.\n"); + } + if (block->check_index_page_at_flush && !page_simple_validate(block->frame)) { @@ -268,6 +280,19 @@ buf_flush_buffered_writes(void) trx_doublewrite->block1, 0, len, (void*)trx_doublewrite->write_buf, NULL); + write_buf = trx_doublewrite->write_buf; + + for (len2 = 0; len2 + UNIV_PAGE_SIZE <= len; len2 += UNIV_PAGE_SIZE) { + if (mach_read_from_4(write_buf + len2 + FIL_PAGE_LSN + 4) + != mach_read_from_4(write_buf + len2 + UNIV_PAGE_SIZE + - FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) { + ut_print_timestamp(stderr); + fprintf(stderr, +" InnoDB: ERROR: The page to be written seems corrupt!\n" +"InnoDB: The lsn fields do not match! Noticed in the doublewrite block1.\n"); + } + } + if (trx_doublewrite->first_free > TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) { len = (trx_doublewrite->first_free - TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) * UNIV_PAGE_SIZE; @@ -278,6 +303,22 @@ buf_flush_buffered_writes(void) (void*)(trx_doublewrite->write_buf + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * UNIV_PAGE_SIZE), NULL); + + write_buf = trx_doublewrite->write_buf + + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * UNIV_PAGE_SIZE; + for (len2 = 0; len2 + UNIV_PAGE_SIZE <= len; + len2 += UNIV_PAGE_SIZE) { + if (mach_read_from_4(write_buf + len2 + + FIL_PAGE_LSN + 4) + != mach_read_from_4(write_buf + len2 + + UNIV_PAGE_SIZE + - FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) { + ut_print_timestamp(stderr); + fprintf(stderr, +" InnoDB: ERROR: The page to be written seems corrupt!\n" +"InnoDB: The lsn fields do not match! Noticed in the doublewrite block2.\n"); + } + } } /* Now flush the doublewrite buffer data to disk */ @@ -291,6 +332,19 @@ buf_flush_buffered_writes(void) for (i = 0; i < trx_doublewrite->first_free; i++) { block = trx_doublewrite->buf_block_arr[i]; + if (mach_read_from_4(block->frame + FIL_PAGE_LSN + 4) + != mach_read_from_4(block->frame + UNIV_PAGE_SIZE + - FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) { + ut_print_timestamp(stderr); + fprintf(stderr, +" InnoDB: ERROR: The page to be written seems corrupt!\n" +"InnoDB: The lsn fields do not match! Noticed in the buffer pool\n" +"InnoDB: after posting and flushing the doublewrite buffer.\n" +"InnoDB: Page buf fix count %lu, io fix %lu, state %lu\n", + (ulong)block->buf_fix_count, (ulong)block->io_fix, + (ulong)block->state); + } + fil_io(OS_FILE_WRITE | OS_AIO_SIMULATED_WAKE_LATER, FALSE, block->space, block->offset, 0, UNIV_PAGE_SIZE, (void*)block->frame, (void*)block); diff --git a/innobase/buf/buf0rea.c b/innobase/buf/buf0rea.c index 83397c9c7fa..a808c282934 100644 --- a/innobase/buf/buf0rea.c +++ b/innobase/buf/buf0rea.c @@ -546,6 +546,8 @@ buf_read_ibuf_merge_pages( } } + os_aio_simulated_wake_handler_threads(); + /* Flush pages from the end of the LRU list if necessary */ buf_flush_free_margin(); diff --git a/innobase/dict/dict0crea.c b/innobase/dict/dict0crea.c index 6ebefc98a24..31a601e68b0 100644 --- a/innobase/dict/dict0crea.c +++ b/innobase/dict/dict0crea.c @@ -32,6 +32,7 @@ static dtuple_t* dict_create_sys_tables_tuple( /*=========================*/ + /* out: the tuple which should be inserted */ dict_table_t* table, /* in: table */ mem_heap_t* heap) /* in: memory heap from which the memory for the built tuple is allocated */ diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c index e2c2043db74..ccaa5720c20 100644 --- a/innobase/dict/dict0dict.c +++ b/innobase/dict/dict0dict.c @@ -643,6 +643,7 @@ dict_init(void) rw_lock_set_level(&dict_operation_lock, SYNC_DICT_OPERATION); dict_foreign_err_file = os_file_create_tmpfile(); + ut_a(dict_foreign_err_file); mutex_create(&dict_foreign_err_mutex); mutex_set_level(&dict_foreign_err_mutex, SYNC_ANY_LATCH); } diff --git a/innobase/include/dyn0dyn.h b/innobase/include/dyn0dyn.h index 501fde05e90..abee62300e3 100644 --- a/innobase/include/dyn0dyn.h +++ b/innobase/include/dyn0dyn.h @@ -47,7 +47,8 @@ dyn_array_open( /*===========*/ /* out: pointer to the buffer */ dyn_array_t* arr, /* in: dynamic array */ - ulint size); /* in: size in bytes of the buffer */ + ulint size); /* in: size in bytes of the buffer; MUST be + smaller than DYN_ARRAY_DATA_SIZE! */ /************************************************************************* Closes the buffer returned by dyn_array_open. */ UNIV_INLINE diff --git a/innobase/include/lock0lock.h b/innobase/include/lock0lock.h index 9c5f35c6674..9f525042dcc 100644 --- a/innobase/include/lock0lock.h +++ b/innobase/include/lock0lock.h @@ -418,7 +418,8 @@ lock_release_off_kernel( /*====================*/ trx_t* trx); /* in: transaction */ /************************************************************************* -Releases table locks, and releases possible other transactions waiting +Releases table locks explicitly requested with LOCK TABLES (indicated by +lock type LOCK_TABLE_EXP), and releases possible other transactions waiting because of these locks. */ void @@ -548,7 +549,7 @@ extern lock_sys_t* lock_sys; /* Lock types */ #define LOCK_TABLE 16 /* these type values should be so high that */ #define LOCK_REC 32 /* they can be ORed to the lock mode */ -#define LOCK_TABLE_EXP 80 /* explicit table lock */ +#define LOCK_TABLE_EXP 80 /* explicit table lock (80 = 16 + 64) */ #define LOCK_TYPE_MASK 0xF0UL /* mask used to extract lock type from the type_mode field in a lock */ /* Waiting lock flag */ diff --git a/innobase/include/mtr0log.h b/innobase/include/mtr0log.h index 785985dea16..be671e119e3 100644 --- a/innobase/include/mtr0log.h +++ b/innobase/include/mtr0log.h @@ -98,7 +98,8 @@ mlog_open( /*======*/ /* out: buffer, NULL if log mode MTR_LOG_NONE */ mtr_t* mtr, /* in: mtr */ - ulint size); /* in: buffer size in bytes */ + ulint size); /* in: buffer size in bytes; MUST be + smaller than DYN_ARRAY_DATA_SIZE! */ /************************************************************ Closes a buffer opened to mlog. */ UNIV_INLINE diff --git a/innobase/include/mtr0log.ic b/innobase/include/mtr0log.ic index b0392e214f1..e544a38330f 100644 --- a/innobase/include/mtr0log.ic +++ b/innobase/include/mtr0log.ic @@ -18,7 +18,8 @@ mlog_open( /*======*/ /* out: buffer, NULL if log mode MTR_LOG_NONE */ mtr_t* mtr, /* in: mtr */ - ulint size) /* in: buffer size in bytes */ + ulint size) /* in: buffer size in bytes; MUST be + smaller than DYN_ARRAY_DATA_SIZE! */ { dyn_array_t* mlog; diff --git a/innobase/include/os0file.h b/innobase/include/os0file.h index 43741f79855..9727c2b8243 100644 --- a/innobase/include/os0file.h +++ b/innobase/include/os0file.h @@ -134,12 +134,12 @@ void os_io_init_simple(void); /*===================*/ /*************************************************************************** -Creates a temporary file. In case of error, causes abnormal termination. */ +Creates a temporary file. */ FILE* os_file_create_tmpfile(void); /*========================*/ - /* out: temporary file handle (never NULL) */ + /* out: temporary file handle, or NULL on error */ /******************************************************************** A simple function to open or create a file. */ diff --git a/innobase/include/page0page.ic b/innobase/include/page0page.ic index e7c0f8ee07c..3d2bf3b090e 100644 --- a/innobase/include/page0page.ic +++ b/innobase/include/page0page.ic @@ -479,7 +479,20 @@ page_rec_get_next( offs = rec_get_next_offs(rec); - ut_a(offs < UNIV_PAGE_SIZE); + if (offs >= UNIV_PAGE_SIZE) { + fprintf(stderr, +"InnoDB: Next record offset is nonsensical %lu in record at offset %lu\n", + (ulong)offs, (ulong)(rec - page)); + fprintf(stderr, +"\nInnoDB: rec address %lx, first buffer frame %lx\n" +"InnoDB: buffer pool high end %lx, buf fix count %lu\n", + (ulong)rec, (ulong)buf_pool->frame_zero, + (ulong)buf_pool->high_end, + (ulong)buf_block_align(rec)->buf_fix_count); + buf_page_print(page); + + ut_a(0); + } if (offs == 0) { diff --git a/innobase/include/row0mysql.h b/innobase/include/row0mysql.h index e088071a1c4..0ab70db2dea 100644 --- a/innobase/include/row0mysql.h +++ b/innobase/include/row0mysql.h @@ -153,11 +153,12 @@ row_lock_table_autoinc_for_mysql( row_prebuilt_t* prebuilt); /* in: prebuilt struct in the MySQL table handle */ /************************************************************************* -Unlocks a table lock possibly reserved by trx. */ +Unlocks all table locks explicitly requested by trx (with LOCK TABLES, +lock type LOCK_TABLE_EXP). */ void -row_unlock_table_for_mysql( -/*=======================*/ +row_unlock_tables_for_mysql( +/*========================*/ trx_t* trx); /* in: transaction */ /************************************************************************* Sets a table lock on the table mentioned in prebuilt. */ diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h index 40a96e79973..57ca1f84f26 100644 --- a/innobase/include/srv0srv.h +++ b/innobase/include/srv0srv.h @@ -92,6 +92,8 @@ extern lint srv_conc_n_threads; extern ibool srv_fast_shutdown; +extern ibool srv_innodb_status; + extern ibool srv_use_doublewrite_buf; extern ibool srv_set_thread_priorities; @@ -149,6 +151,7 @@ extern ulint srv_test_n_mutexes; extern ulint srv_test_array_size; extern ulint srv_activity_count; +extern ulint srv_fatal_semaphore_wait_threshold; extern mutex_t* kernel_mutex_temp;/* mutex protecting the server, trx structs, query threads, and lock table: we allocate diff --git a/innobase/include/srv0start.h b/innobase/include/srv0start.h index c4c8dac5d7a..539ccb32744 100644 --- a/innobase/include/srv0start.h +++ b/innobase/include/srv0start.h @@ -63,11 +63,13 @@ innobase_start_or_create_for_mysql(void); /* out: DB_SUCCESS or error code */ /******************************************************************** Shuts down the Innobase database. */ - int innobase_shutdown_for_mysql(void); /*=============================*/ /* out: DB_SUCCESS or error code */ +#ifdef __NETWARE__ +void set_panic_flag_for_netware(void); +#endif extern ulint srv_sizeof_trx_t_in_ha_innodb_cc; diff --git a/innobase/include/sync0arr.h b/innobase/include/sync0arr.h index 383d0c69fb2..4324f2d3f2c 100644 --- a/innobase/include/sync0arr.h +++ b/innobase/include/sync0arr.h @@ -95,7 +95,7 @@ void sync_arr_wake_threads_if_sema_free(void); /*====================================*/ /************************************************************************** -Prints warnings of long semaphore waits to stderr. Currently > 120 sec. */ +Prints warnings of long semaphore waits to stderr. */ void sync_array_print_long_waits(void); diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h index 07d5e5a8215..3be16e8f46d 100644 --- a/innobase/include/trx0trx.h +++ b/innobase/include/trx0trx.h @@ -423,8 +423,9 @@ struct trx_struct{ lock_t* auto_inc_lock; /* possible auto-inc lock reserved by the transaction; note that it is also in the lock list trx_locks */ - ulint n_tables_locked;/* number of table locks reserved by - the transaction, stored in trx_locks */ + ulint n_lock_table_exp;/* number of explicit table locks + (LOCK TABLES) reserved by the + transaction, stored in trx_locks */ UT_LIST_NODE_T(trx_t) trx_list; /* list of transactions */ UT_LIST_NODE_T(trx_t) diff --git a/innobase/include/ut0dbg.h b/innobase/include/ut0dbg.h index bec9cdd42b5..fe6aba2cccb 100644 --- a/innobase/include/ut0dbg.h +++ b/innobase/include/ut0dbg.h @@ -22,7 +22,38 @@ extern ulint* ut_dbg_null_ptr; extern const char* ut_dbg_msg_assert_fail; extern const char* ut_dbg_msg_trap; extern const char* ut_dbg_msg_stop; - +/* Have a graceful exit on NetWare rather than a segfault to avoid abends */ +#ifdef __NETWARE__ +extern ibool panic_shutdown; +#define ut_a(EXPR) do {\ + if (!((ulint)(EXPR) + ut_dbg_zero)) {\ + ut_print_timestamp(stderr);\ + fprintf(stderr, ut_dbg_msg_assert_fail,\ + os_thread_pf(os_thread_get_curr_id()), __FILE__,\ + (ulint)__LINE__);\ + fputs("InnoDB: Failing assertion: " #EXPR "\n", stderr);\ + fputs(ut_dbg_msg_trap, stderr);\ + ut_dbg_stop_threads = TRUE;\ + if (ut_dbg_stop_threads) {\ + fprintf(stderr, ut_dbg_msg_stop,\ + os_thread_pf(os_thread_get_curr_id()), __FILE__, (ulint)__LINE__);\ + }\ + if(!panic_shutdown){\ + panic_shutdown = TRUE;\ + innobase_shutdown_for_mysql();}\ + exit(1);\ + }\ +} while (0) +#define ut_error do {\ + ut_print_timestamp(stderr);\ + fprintf(stderr, ut_dbg_msg_assert_fail,\ + os_thread_pf(os_thread_get_curr_id()), __FILE__, (ulint)__LINE__);\ + fprintf(stderr, ut_dbg_msg_trap);\ + ut_dbg_stop_threads = TRUE;\ + if(!panic_shutdown){panic_shutdown = TRUE;\ + innobase_shutdown_for_mysql();}\ +} while (0) +#else #define ut_a(EXPR) do {\ if (!((ulint)(EXPR) + ut_dbg_zero)) {\ ut_print_timestamp(stderr);\ @@ -49,6 +80,7 @@ extern const char* ut_dbg_msg_stop; ut_dbg_stop_threads = TRUE;\ if (*(ut_dbg_null_ptr)) ut_dbg_null_ptr = NULL;\ } while (0) +#endif #ifdef UNIV_DEBUG # define ut_ad(EXPR) ut_a(EXPR) diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c index 11bd1f93808..1c9b1263130 100644 --- a/innobase/lock/lock0lock.c +++ b/innobase/lock/lock0lock.c @@ -509,6 +509,7 @@ lock_sys_create( /* hash_create_mutexes(lock_sys->rec_hash, 2, SYNC_REC_LOCK); */ lock_latest_err_file = os_file_create_tmpfile(); + ut_a(lock_latest_err_file); } /************************************************************************* @@ -2023,9 +2024,8 @@ lock_grant( lock->trx->auto_inc_lock = lock; } else if (lock_get_type(lock) == LOCK_TABLE_EXP) { - ut_ad(lock_get_mode(lock) == LOCK_S + ut_a(lock_get_mode(lock) == LOCK_S || lock_get_mode(lock) == LOCK_X); - lock->trx->n_tables_locked++; } if (lock_print_waits) { @@ -3203,6 +3203,10 @@ lock_table_create( lock->type_mode = type_mode | LOCK_TABLE; lock->trx = trx; + if (lock_get_type(lock) == LOCK_TABLE_EXP) { + lock->trx->n_lock_table_exp++; + } + lock->un_member.tab_lock.table = table; UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock); @@ -3238,7 +3242,11 @@ lock_table_remove_low( if (lock == trx->auto_inc_lock) { trx->auto_inc_lock = NULL; } - + + if (lock_get_type(lock) == LOCK_TABLE_EXP) { + lock->trx->n_lock_table_exp--; + } + UT_LIST_REMOVE(trx_locks, trx->trx_locks, lock); UT_LIST_REMOVE(un_member.tab_lock.locks, table->locks, lock); } @@ -3386,7 +3394,7 @@ lock_table( return(DB_SUCCESS); } - ut_ad(flags == 0 || flags == LOCK_TABLE_EXP); + ut_a(flags == 0 || flags == LOCK_TABLE_EXP); trx = thr_get_trx(thr); @@ -3418,10 +3426,7 @@ lock_table( lock_table_create(table, mode | flags, trx); - if (flags) { - ut_ad(mode == LOCK_S || mode == LOCK_X); - trx->n_tables_locked++; - } + ut_a(!flags || mode == LOCK_S || mode == LOCK_X); lock_mutex_exit_kernel(); @@ -3502,13 +3507,13 @@ lock_table_dequeue( #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ - ut_ad(lock_get_type(in_lock) == LOCK_TABLE || + ut_a(lock_get_type(in_lock) == LOCK_TABLE || lock_get_type(in_lock) == LOCK_TABLE_EXP); lock = UT_LIST_GET_NEXT(un_member.tab_lock.locks, in_lock); lock_table_remove_low(in_lock); - + /* Check if waiting locks in the queue can now be granted: grant locks if there are no conflicting locks ahead. */ @@ -3607,9 +3612,8 @@ lock_release_off_kernel( lock_table_dequeue(lock); if (lock_get_type(lock) == LOCK_TABLE_EXP) { - ut_ad(lock_get_mode(lock) == LOCK_S + ut_a(lock_get_mode(lock) == LOCK_S || lock_get_mode(lock) == LOCK_X); - trx->n_tables_locked--; } } @@ -3630,11 +3634,12 @@ lock_release_off_kernel( mem_heap_empty(trx->lock_heap); ut_a(trx->auto_inc_lock == NULL); - ut_a(trx->n_tables_locked == 0); + ut_a(trx->n_lock_table_exp == 0); } /************************************************************************* -Releases table locks, and releases possible other transactions waiting +Releases table locks explicitly requested with LOCK TABLES (indicated by +lock type LOCK_TABLE_EXP), and releases possible other transactions waiting because of these locks. */ void @@ -3659,7 +3664,7 @@ lock_release_tables_off_kernel( count++; if (lock_get_type(lock) == LOCK_TABLE_EXP) { - ut_ad(lock_get_mode(lock) == LOCK_S + ut_a(lock_get_mode(lock) == LOCK_S || lock_get_mode(lock) == LOCK_X); if (trx->insert_undo || trx->update_undo) { @@ -3675,7 +3680,7 @@ lock_release_tables_off_kernel( } lock_table_dequeue(lock); - trx->n_tables_locked--; + lock = UT_LIST_GET_LAST(trx->trx_locks); continue; } @@ -3694,9 +3699,7 @@ lock_release_tables_off_kernel( lock = UT_LIST_GET_PREV(trx_locks, lock); } - mem_heap_empty(trx->lock_heap); - - ut_a(trx->n_tables_locked == 0); + ut_a(trx->n_lock_table_exp == 0); } /************************************************************************* diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index 8cb2b171328..56f01568ead 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -371,22 +371,72 @@ os_io_init_simple(void) } } +#ifndef UNIV_HOTBACKUP +/************************************************************************* +Creates a temporary file. This function is defined in ha_innodb.cc. */ + +int +innobase_mysql_tmpfile(void); +/*========================*/ + /* out: temporary file descriptor, or < 0 on error */ +#endif /* !UNIV_HOTBACKUP */ + /*************************************************************************** -Creates a temporary file. In case of error, causes abnormal termination. */ +Creates a temporary file. */ FILE* os_file_create_tmpfile(void) /*========================*/ - /* out: temporary file handle (never NULL) */ + /* out: temporary file handle, or NULL on error */ { - FILE* file = tmpfile(); - if (file == NULL) { + FILE* file = NULL; + int fd = -1; +#ifdef UNIV_HOTBACKUP + int tries; + for (tries = 10; tries--; ) { + char* name = tempnam(fil_path_to_mysql_datadir, "ib"); + if (!name) { + break; + } + + fd = open(name, +# ifdef __WIN__ + O_SEQUENTIAL | O_SHORT_LIVED | O_TEMPORARY | +# endif /* __WIN__ */ + O_CREAT | O_EXCL | O_RDWR, + S_IREAD | S_IWRITE); + if (fd >= 0) { +# ifndef __WIN__ + unlink(name); +# endif /* !__WIN__ */ + free(name); + break; + } + ut_print_timestamp(stderr); - fputs(" InnoDB: Error: unable to create temporary file\n", - stderr); - os_file_handle_error(NULL, "tmpfile"); - ut_error; + fprintf(stderr, " InnoDB: Warning: " + "unable to create temporary file %s, retrying\n", + name); + free(name); } +#else /* UNIV_HOTBACKUP */ + fd = innobase_mysql_tmpfile(); +#endif /* UNIV_HOTBACKUP */ + + if (fd >= 0) { + file = fdopen(fd, "w+b"); + } + + if (!file) { + ut_print_timestamp(stderr); + fprintf(stderr, + " InnoDB: Error: unable to create temporary file;" + " errno: %d\n", errno); + if (fd >= 0) { + close(fd); + } + } + return(file); } @@ -2736,6 +2786,9 @@ consecutive_loop: ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: ERROR: The page to be written seems corrupt!\n"); + fprintf(stderr, +"InnoDB: Writing a block of %lu bytes, currently writing at offset %lu\n", + (ulong)total_len, (ulong)len2); buf_page_print(combined_buf + len2); fprintf(stderr, "InnoDB: ERROR: The page to be written seems corrupt!\n"); diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c index 93d360eaaeb..458970da4e2 100644 --- a/innobase/row/row0ins.c +++ b/innobase/row/row0ins.c @@ -370,6 +370,32 @@ row_ins_cascade_ancestor_updates_table( return(FALSE); } +/************************************************************************* +Returns the number of ancestor UPDATE or DELETE nodes of a +cascaded update/delete node. */ +static +ulint +row_ins_cascade_n_ancestors( +/*========================*/ + /* out: number of ancestors */ + que_node_t* node) /* in: node in a query graph */ +{ + que_node_t* parent; + ulint n_ancestors = 0; + + parent = que_node_get_parent(node); + + while (que_node_get_type(parent) == QUE_NODE_UPDATE) { + n_ancestors++; + + parent = que_node_get_parent(parent); + + ut_a(parent); + } + + return(n_ancestors); +} + /********************************************************************** Calculates the update vector node->cascade->update for a child table in a cascaded update. */ @@ -616,6 +642,34 @@ row_ins_foreign_report_add_err( } /************************************************************************* +Invalidate the query cache for the given table. */ +static +void +row_ins_invalidate_query_cache( +/*===========================*/ + que_thr_t* thr, /* in: query thread whose run_node + is an update node */ + const char* name) /* in: table name prefixed with + database name and a '/' character */ +{ + char* buf; + char* ptr; + ulint len = strlen(name) + 1; + + buf = mem_strdupl(name, len); + + ptr = strchr(buf, '/'); + ut_a(ptr); + *ptr = '\0'; + + /* We call a function in ha_innodb.cc */ +#ifndef UNIV_HOTBACKUP + innobase_invalidate_query_cache(thr_get_trx(thr), buf, len); +#endif + mem_free(buf); +} + +/************************************************************************* Perform referential actions or checks when a parent row is deleted or updated and the constraint had an ON DELETE or ON UPDATE condition which was not RESTRICT. */ @@ -650,26 +704,14 @@ row_ins_foreign_check_on_constraint( ulint n_to_update; ulint err; ulint i; - char* ptr; - char table_name_buf[1000]; ut_a(thr && foreign && pcur && mtr); /* Since we are going to delete or update a row, we have to invalidate the MySQL query cache for table */ - ut_a(ut_strlen(table->name) < 998); - strcpy(table_name_buf, table->name); + row_ins_invalidate_query_cache(thr, table->name); - ptr = strchr(table_name_buf, '/'); - ut_a(ptr); - *ptr = '\0'; - - /* We call a function in ha_innodb.cc */ -#ifndef UNIV_HOTBACKUP - innobase_invalidate_query_cache(thr_get_trx(thr), table_name_buf, - ut_strlen(table->name) + 1); -#endif node = thr->run_node; if (node->is_delete && 0 == (foreign->type & @@ -756,6 +798,16 @@ row_ins_foreign_check_on_constraint( goto nonstandard_exit_func; } + if (row_ins_cascade_n_ancestors(cascade) >= 15) { + err = DB_ROW_IS_REFERENCED; + + row_ins_foreign_report_err( +(char*)"Trying a too deep cascaded delete or update\n", + thr, foreign, btr_pcur_get_rec(pcur), entry); + + goto nonstandard_exit_func; + } + index = btr_pcur_get_btr_cur(pcur)->index; ut_a(index == foreign->foreign_index); diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index b7779e5b7a3..70743e3a753 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -723,14 +723,15 @@ run_again: } /************************************************************************* -Unlocks a table lock possibly reserved by trx. */ +Unlocks all table locks explicitly requested by trx (with LOCK TABLES, +lock type LOCK_TABLE_EXP). */ void -row_unlock_table_for_mysql( -/*=======================*/ +row_unlock_tables_for_mysql( +/*========================*/ trx_t* trx) /* in: transaction */ { - if (!trx->n_tables_locked) { + if (!trx->n_lock_table_exp) { return; } @@ -2640,6 +2641,30 @@ row_rename_table_for_mysql( NULL); trx->error_state = DB_SUCCESS; } + } else { + err = dict_load_foreigns(new_name); + + if (err != DB_SUCCESS) { + + ut_print_timestamp(stderr); + + fputs( + " InnoDB: Error: in RENAME TABLE table ", + stderr); + ut_print_name(stderr, new_name); + fputs("\n" + "InnoDB: is referenced in foreign key constraints\n" + "InnoDB: which are not compatible with the new table definition.\n", + stderr); + + ut_a(dict_table_rename_in_cache(table, + old_name, FALSE)); + + trx->error_state = DB_SUCCESS; + trx_general_rollback_for_mysql(trx, FALSE, + NULL); + trx->error_state = DB_SUCCESS; + } } } funct_exit: @@ -2805,7 +2830,12 @@ row_check_table_for_mysql( REPEATABLE READ here */ prebuilt->trx->isolation_level = TRX_ISO_REPEATABLE_READ; - + + /* Enlarge the fatal lock wait timeout during CHECK TABLE. */ + mutex_enter(&kernel_mutex); + srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */ + mutex_exit(&kernel_mutex); + index = dict_table_get_first_index(table); while (index != NULL) { @@ -2853,6 +2883,11 @@ row_check_table_for_mysql( ret = DB_ERROR; } + /* Restore the fatal lock wait timeout after CHECK TABLE. */ + mutex_enter(&kernel_mutex); + srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */ + mutex_exit(&kernel_mutex); + prebuilt->trx->op_info = (char *) ""; return(ret); diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c index e0bf4684214..6c62fed974c 100644 --- a/innobase/row/row0sel.c +++ b/innobase/row/row0sel.c @@ -3088,8 +3088,15 @@ rec_loop: if (srv_force_recovery == 0 || moves_up == FALSE) { ut_print_timestamp(stderr); + buf_page_print(buf_frame_align(rec)); fprintf(stderr, -" InnoDB: Index corruption: rec offs %lu next offs %lu, page no %lu,\n" +"\nInnoDB: rec address %lx, first buffer frame %lx\n" +"InnoDB: buffer pool high end %lx, buf block fix count %lu\n", + (ulong)rec, (ulong)buf_pool->frame_zero, + (ulong)buf_pool->high_end, + (ulong)buf_block_align(rec)->buf_fix_count); + fprintf(stderr, +"InnoDB: Index corruption: rec offs %lu next offs %lu, page no %lu,\n" "InnoDB: ", (ulint)(rec - buf_frame_align(rec)), next_offs, buf_frame_get_page_no(rec)); diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index a78bd0d864c..d799ada1e20 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -55,6 +55,9 @@ ibool srv_lower_case_table_names = FALSE; in the server */ ulint srv_activity_count = 0; +/* The following is the maximum allowed duration of a lock wait. */ +ulint srv_fatal_semaphore_wait_threshold = 600; + ibool srv_lock_timeout_and_monitor_active = FALSE; ibool srv_error_monitor_active = FALSE; @@ -220,6 +223,9 @@ merge to completion before shutdown */ ibool srv_fast_shutdown = FALSE; +/* Generate a innodb_status.<pid> file */ +ibool srv_innodb_status = FALSE; + ibool srv_use_doublewrite_buf = TRUE; ibool srv_set_thread_priorities = TRUE; diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c index 0fb8da9fe3a..9baa86234a0 100644 --- a/innobase/srv/srv0start.c +++ b/innobase/srv/srv0start.c @@ -1023,16 +1023,24 @@ NetWare. */ mutex_create(&srv_monitor_file_mutex); mutex_set_level(&srv_monitor_file_mutex, SYNC_NO_ORDER_CHECK); - srv_monitor_file_name = mem_alloc( - strlen(fil_path_to_mysql_datadir) + - 20 + sizeof "/innodb_status."); - sprintf(srv_monitor_file_name, "%s/innodb.status.%lu", - fil_path_to_mysql_datadir, os_proc_get_number()); - srv_monitor_file = fopen(srv_monitor_file_name, "w+"); - if (!srv_monitor_file) { - fprintf(stderr, "InnoDB: unable to create %s: %s\n", - srv_monitor_file_name, strerror(errno)); - return(DB_ERROR); + if (srv_innodb_status) { + srv_monitor_file_name = mem_alloc( + strlen(fil_path_to_mysql_datadir) + + 20 + sizeof "/innodb_status."); + sprintf(srv_monitor_file_name, "%s/innodb_status.%lu", + fil_path_to_mysql_datadir, os_proc_get_number()); + srv_monitor_file = fopen(srv_monitor_file_name, "w+"); + if (!srv_monitor_file) { + fprintf(stderr, "InnoDB: unable to create %s: %s\n", + srv_monitor_file_name, strerror(errno)); + return(DB_ERROR); + } + } else { + srv_monitor_file_name = NULL; + srv_monitor_file = os_file_create_tmpfile(); + if (!srv_monitor_file) { + return(DB_ERROR); + } } /* Restrict the maximum number of file i/o threads */ @@ -1071,6 +1079,7 @@ NetWare. */ for (i = 0; i < srv_n_file_io_threads; i++) { n[i] = i; + os_thread_create(io_handler_thread, n + i, thread_ids + i); } @@ -1432,7 +1441,6 @@ NetWare. */ } fflush(stderr); - return((int) DB_SUCCESS); } @@ -1445,7 +1453,9 @@ innobase_shutdown_for_mysql(void) /* out: DB_SUCCESS or error code */ { ulint i; - +#ifdef __NETWARE__ + extern ibool panic_shutdown; +#endif if (!srv_was_started) { if (srv_is_being_started) { ut_print_timestamp(stderr); @@ -1463,8 +1473,11 @@ innobase_shutdown_for_mysql(void) The step 1 is the real InnoDB shutdown. The remaining steps just free data structures after the shutdown. */ +#ifdef __NETWARE__ + if(!panic_shutdown) +#endif logs_empty_and_mark_files_at_shutdown(); - + if (srv_conc_n_threads != 0) { fprintf(stderr, "InnoDB: Warning: query counter shows %ld queries still\n" @@ -1527,15 +1540,16 @@ innobase_shutdown_for_mysql(void) if (srv_monitor_file) { fclose(srv_monitor_file); srv_monitor_file = 0; - unlink(srv_monitor_file_name); - mem_free(srv_monitor_file_name); + if (srv_monitor_file_name) { + unlink(srv_monitor_file_name); + mem_free(srv_monitor_file_name); + } } - + mutex_free(&srv_monitor_file_mutex); /* 3. Free all InnoDB's own mutexes and the os_fast_mutexes inside them */ - sync_close(); /* 4. Free the os_conc_mutex and all os_events and os_mutexes */ @@ -1546,7 +1560,7 @@ innobase_shutdown_for_mysql(void) /* 5. Free all allocated memory and the os_fast_mutex created in ut0mem.c */ - ut_free_all_mem(); + ut_free_all_mem(); if (os_thread_count != 0 || os_event_count != 0 @@ -1573,3 +1587,11 @@ innobase_shutdown_for_mysql(void) return((int) DB_SUCCESS); } + +#ifdef __NETWARE__ +void set_panic_flag_for_netware() +{ + extern ibool panic_shutdown; + panic_shutdown = TRUE; +} +#endif diff --git a/innobase/sync/sync0arr.c b/innobase/sync/sync0arr.c index 944503aa0e2..176aedb6ae3 100644 --- a/innobase/sync/sync0arr.c +++ b/innobase/sync/sync0arr.c @@ -890,7 +890,7 @@ sync_arr_wake_threads_if_sema_free(void) } /************************************************************************** -Prints warnings of long semaphore waits to stderr. Currently > 120 sec. */ +Prints warnings of long semaphore waits to stderr. */ void sync_array_print_long_waits(void) @@ -900,6 +900,7 @@ sync_array_print_long_waits(void) ibool old_val; ibool noticed = FALSE; ulint i; + ulint fatal_timeout = srv_fatal_semaphore_wait_threshold; for (i = 0; i < sync_primary_wait_array->n_cells; i++) { @@ -914,12 +915,13 @@ sync_array_print_long_waits(void) } if (cell->wait_object != NULL - && difftime(time(NULL), cell->reservation_time) > 600) { + && difftime(time(NULL), cell->reservation_time) + > fatal_timeout) { - fputs( -"InnoDB: Error: semaphore wait has lasted > 600 seconds\n" + fprintf(stderr, +"InnoDB: Error: semaphore wait has lasted > %lu seconds\n" "InnoDB: We intentionally crash the server, because it appears to be hung.\n", - stderr); + fatal_timeout); ut_error; } diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c index 335e1f69228..576827966ab 100644 --- a/innobase/trx/trx0trx.c +++ b/innobase/trx/trx0trx.c @@ -151,7 +151,7 @@ trx_create( trx->n_tickets_to_enter_innodb = 0; trx->auto_inc_lock = NULL; - trx->n_tables_locked = 0; + trx->n_lock_table_exp = 0; trx->read_view_heap = mem_heap_create(256); trx->read_view = NULL; @@ -279,7 +279,7 @@ trx_free( ut_a(!trx->has_search_latch); ut_a(!trx->auto_inc_lock); - ut_a(!trx->n_tables_locked); + ut_a(!trx->n_lock_table_exp); ut_a(trx->dict_operation_lock_mode == 0); diff --git a/innobase/ut/ut0dbg.c b/innobase/ut/ut0dbg.c index 65703ec1c86..2a0cfe1f13a 100644 --- a/innobase/ut/ut0dbg.c +++ b/innobase/ut/ut0dbg.c @@ -14,7 +14,12 @@ ulint ut_dbg_zero = 0; /* If this is set to TRUE all threads will stop into the next assertion and assert */ ibool ut_dbg_stop_threads = FALSE; - +#ifdef __NETWARE__ +ibool panic_shutdown = FALSE; /* This is set to TRUE when on NetWare there + happens an InnoDB assertion failure or other + fatal error condition that requires an + immediate shutdown. */ +#endif /* Null pointer used to generate memory trap */ ulint* ut_dbg_null_ptr = NULL; diff --git a/innobase/ut/ut0mem.c b/innobase/ut/ut0mem.c index 2cab36a9580..9b08b1e79aa 100644 --- a/innobase/ut/ut0mem.c +++ b/innobase/ut/ut0mem.c @@ -106,7 +106,13 @@ ut_malloc_low( /* Make an intentional seg fault so that we get a stack trace */ + /* Intentional segfault on NetWare causes an abend. Avoid this + by graceful exit handling in ut_a(). */ +#if (!defined __NETWARE__) if (*ut_mem_null_ptr) ut_mem_null_ptr = 0; +#else + ut_a(0); +#endif } if (set_to_zero) { diff --git a/install-sh b/install-sh index e9de23842dc..c1666c37407 100755 --- a/install-sh +++ b/install-sh @@ -43,7 +43,7 @@ mkdirprog="${MKDIRPROG-mkdir}" transformbasename="" transform_arg="" -instcmd="$mvprog" +instcmd="$cpprog" chmodcmd="$chmodprog 0755" chowncmd="" chgrpcmd="" diff --git a/libmysql/Makefile.am b/libmysql/Makefile.am index 686f7807949..fefed7f079c 100644 --- a/libmysql/Makefile.am +++ b/libmysql/Makefile.am @@ -1,9 +1,12 @@ -# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB +# Copyright (C) 2000-2004 MySQL AB # -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Library General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. +# This program is free software; you can redistribute it and/or modify +# it under the terms of version 2 GNU General Public License as +# published by the Free Software Foundation. +# +# There are special exceptions to the terms and conditions of the GPL as it +# is applied to this software. View the full text of the exception in file +# EXCEPTIONS-CLIENT in the directory of this software distribution. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -14,7 +17,7 @@ # License along with this library; if not, write to the Free # Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, # MA 02111-1307, USA - +# # This file is public domain and comes with NO WARRANTY of any kind target = libmysqlclient.la diff --git a/libmysql/Makefile.shared b/libmysql/Makefile.shared index 764983506d1..06d5c14f602 100644 --- a/libmysql/Makefile.shared +++ b/libmysql/Makefile.shared @@ -1,21 +1,24 @@ -## Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB -## -## This library is free software; you can redistribute it and/or -## modify it under the terms of the GNU Library General Public -## License as published by the Free Software Foundation; either -## version 2 of the License, or (at your option) any later version. -## -## This library 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 -## Library General Public License for more details. -## -## You should have received a copy of the GNU Library General Public -## License along with this library; if not, write to the Free -## Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, -## MA 02111-1307, USA -## -## This file is public domain and comes with NO WARRANTY of any kind +# Copyright (C) 2000-2004 MySQL AB +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of version 2 GNU General Public License as +# published by the Free Software Foundation. +# +# There are special exceptions to the terms and conditions of the GPL as it +# is applied to this software. View the full text of the exception in file +# EXCEPTIONS-CLIENT in the directory of this software distribution. +# +# This library 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 +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this library; if not, write to the Free +# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +# MA 02111-1307, USA +# +# This file is public domain and comes with NO WARRANTY of any kind MYSQLDATAdir = $(localstatedir) MYSQLSHAREdir = $(pkgdatadir) diff --git a/libmysql/conf_to_src.c b/libmysql/conf_to_src.c index 95ffcf1cb2b..e9084afae41 100644 --- a/libmysql/conf_to_src.c +++ b/libmysql/conf_to_src.c @@ -1,9 +1,12 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000-2004 MySQL AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + the Free Software Foundation. + + There are special exceptions to the terms and conditions of the GPL as it + is applied to this software. View the full text of the exception in file + EXCEPTIONS-CLIENT in the directory of this software distribution. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/libmysql/dll.c b/libmysql/dll.c index 92aa611000b..90731ee209e 100644 --- a/libmysql/dll.c +++ b/libmysql/dll.c @@ -1,9 +1,12 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000-2004 MySQL AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + the Free Software Foundation. + + There are special exceptions to the terms and conditions of the GPL as it + is applied to this software. View the full text of the exception in file + EXCEPTIONS-CLIENT in the directory of this software distribution. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/libmysql/errmsg.c b/libmysql/errmsg.c index 06d21cf36c3..e43864bfd33 100644 --- a/libmysql/errmsg.c +++ b/libmysql/errmsg.c @@ -1,9 +1,12 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000-2004 MySQL AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + the Free Software Foundation. + + There are special exceptions to the terms and conditions of the GPL as it + is applied to this software. View the full text of the exception in file + EXCEPTIONS-CLIENT in the directory of this software distribution. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/libmysql/get_password.c b/libmysql/get_password.c index 0e3b2dcb0ae..e55e77320f0 100644 --- a/libmysql/get_password.c +++ b/libmysql/get_password.c @@ -1,9 +1,12 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright (C) 2000-2004 MySQL AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + the Free Software Foundation. + + There are special exceptions to the terms and conditions of the GPL as it + is applied to this software. View the full text of the exception in file + EXCEPTIONS-CLIENT in the directory of this software distribution. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index bac72064e1b..a591ad9317d 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -1,9 +1,12 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright (C) 2000-2004 MySQL AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + the Free Software Foundation. + + There are special exceptions to the terms and conditions of the GPL as it + is applied to this software. View the full text of the exception in file + EXCEPTIONS-CLIENT in the directory of this software distribution. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -941,7 +944,7 @@ static void mysql_read_default_options(struct st_mysql_options *options, options->client_flag&= ~CLIENT_LOCAL_FILES; break; case 22: - options->client_flag&= CLIENT_LOCAL_FILES; + options->client_flag&= ~CLIENT_LOCAL_FILES; break; case 23: /* replication probe */ options->rpl_probe= 1; diff --git a/libmysql/manager.c b/libmysql/manager.c index 5d432848f7b..8e0f56326ac 100644 --- a/libmysql/manager.c +++ b/libmysql/manager.c @@ -1,9 +1,12 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000-2004 MySQL AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + the Free Software Foundation. + + There are special exceptions to the terms and conditions of the GPL as it + is applied to this software. View the full text of the exception in file + EXCEPTIONS-CLIENT in the directory of this software distribution. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/libmysql_r/Makefile.am b/libmysql_r/Makefile.am index 04b6f3b6c6c..8ed4a64d309 100644 --- a/libmysql_r/Makefile.am +++ b/libmysql_r/Makefile.am @@ -1,9 +1,12 @@ -# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB +# Copyright (C) 2000-2004 MySQL AB # -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Library General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. +# This program is free software; you can redistribute it and/or modify +# it under the terms of version 2 GNU General Public License as +# published by the Free Software Foundation. +# +# There are special exceptions to the terms and conditions of the GPL as it +# is applied to this software. View the full text of the exception in file +# EXCEPTIONS-CLIENT in the directory of this software distribution. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -14,8 +17,8 @@ # License along with this library; if not, write to the Free # Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, # MA 02111-1307, USA - - +# +# This file is public domain and comes with NO WARRANTY of any kind target = libmysqlclient_r.la target_defs = -DDONT_USE_RAID -DMYSQL_CLIENT @LIB_EXTRA_CCFLAGS@ diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am index 54c7ada4a85..ef0f61b4234 100644 --- a/libmysqld/Makefile.am +++ b/libmysqld/Makefile.am @@ -89,9 +89,9 @@ libmysqld.a: libmysqld_int.a $(INC_LIB) cd tmp ; \ for file in *.a ; do \ bfile=`basename $$file .a` ; \ - ar x $$file; \ + $(AR) x $$file; \ for obj in *.o ; do mv $$obj $${bfile}_$$obj ; done ; \ - ar q ../libmysqld_int2.a *.o ; \ + $(AR) q ../libmysqld_int2.a *.o ; \ rm -f *.o ; \ done ; \ cd .. ; \ diff --git a/libmysqld/libmysqld.c b/libmysqld/libmysqld.c index 6f60e4c4fbc..9c79536b2e0 100644 --- a/libmysqld/libmysqld.c +++ b/libmysqld/libmysqld.c @@ -412,8 +412,8 @@ mysql_free_result(MYSQL_RES *result) DBUG_PRINT("warning",("Not all rows in set were read; Ignoring rows")); for (;;) { - uint pkt_len; - if ((pkt_len=(uint) net_safe_read(result->handle)) == packet_error) + ulong pkt_len; + if ((pkt_len=net_safe_read(result->handle)) == packet_error) break; if (pkt_len == 1 && result->handle->net.read_pos[0] == 254) break; /* End of data */ @@ -611,7 +611,8 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields, static MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, uint fields) { - uint field,pkt_len; + uint field; + ulong pkt_len; ulong len; uchar *cp; char *to; @@ -620,7 +621,7 @@ static MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, NET *net = &mysql->net; DBUG_ENTER("read_rows"); - if ((pkt_len=(uint) net_safe_read(mysql)) == packet_error) + if ((pkt_len= net_safe_read(mysql)) == packet_error) DBUG_RETURN(0); if (!(result=(MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA), MYF(MY_WME | MY_ZEROFILL)))) @@ -805,7 +806,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, uint port, const char *unix_socket,uint client_flag) { char buff[100],charset_name_buff[16],*end,*host_info, *charset_name; - uint pkt_length; + ulong pkt_length; ulong max_allowed_packet; NET *net= &mysql->net; DBUG_ENTER("mysql_real_connect"); @@ -1153,7 +1154,7 @@ mysql_read_query_result(MYSQL *mysql) uchar *pos; ulong field_count; MYSQL_DATA *fields; - uint length; + ulong length; DBUG_ENTER("mysql_read_query_result"); if ((length=net_safe_read(mysql)) == packet_error) diff --git a/libmysqld/libmysqld.rc b/libmysqld/libmysqld.rc new file mode 100755 index 00000000000..5b6142faddf --- /dev/null +++ b/libmysqld/libmysqld.rc @@ -0,0 +1,125 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 4,0,20,0 + PRODUCTVERSION 4,0,20,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x9L +#else + FILEFLAGS 0x8L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN +#ifdef _DEBUG + VALUE "Comments", "Embedded Server\0" + VALUE "CompanyName", "MySQL AB\0" + VALUE "FileDescription", "Embedded Server\0" + VALUE "FileVersion", "4.0.20\0" + VALUE "InternalName", "Embedded Server\0" + VALUE "LegalCopyright", "Copyright ╘ 2004\0" + VALUE "LegalTrademarks", "MySQL and MySQL AB\0" + VALUE "OriginalFilename", "libmysqld.dll debug\0" + VALUE "PrivateBuild", "libmysqld.dll debug \0" + VALUE "ProductName", "libmysqld.dll debug\0" + VALUE "ProductVersion", "4.0.20\0" + VALUE "SpecialBuild", "\0" +#else + VALUE "Comments", "Embedded Server\0" + VALUE "CompanyName", "MySQL AB\0" + VALUE "FileDescription", "Embedded Server\0" + VALUE "FileVersion", "4.0.20\0" + VALUE "InternalName", "Embedded Server\0" + VALUE "LegalCopyright", "Copyright ╘ 2004\0" + VALUE "LegalTrademarks", "MySQL and MySQL AB\0" + VALUE "OriginalFilename", "libmysqld.dll release\0" + VALUE "PrivateBuild", "libmysqld.dll release \0" + VALUE "ProductName", "libmysqld.dll release\0" + VALUE "ProductVersion", "4.0.20\0" + VALUE "SpecialBuild", "\0" +#endif + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // !_MAC + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/libmysqld/resource.h b/libmysqld/resource.h new file mode 100755 index 00000000000..f770fe490a6 --- /dev/null +++ b/libmysqld/resource.h @@ -0,0 +1,15 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by libmysqld.rc +// + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/man/Makefile.am b/man/Makefile.am index 37eb8a13f4e..539c43dfed6 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -23,7 +23,7 @@ man_MANS = mysql.1 isamchk.1 isamlog.1 mysql_zap.1 mysqlaccess.1 \ EXTRA_DIST = mysql.1.in isamchk.1.in isamlog.1.in mysql_zap.1.in \ mysqlaccess.1.in mysqladmin.1.in mysqld.1.in mysqld_multi.1.in \ - mysqldump.1.in mysqlshow.1.in perror.1.in replace.1.in \ + mysqldump.1.in mysqlshow.1.in perror.1.in replace.1.in mysqlman.1.in \ mysqld_safe.1.in mysql_fix_privilege_tables.1.in CLEANFILES = $(man_MANS) diff --git a/man/mysqlman.1.in b/man/mysqlman.1.in new file mode 100644 index 00000000000..610a64da198 --- /dev/null +++ b/man/mysqlman.1.in @@ -0,0 +1,15 @@ +.TH mysqlman 1 "20 July 2004" "MySQL @MYSQL_BASE_VERSION@" "MySQL database" +.SH NAME +mysqlman \- default man page for mysql +.SH "DESCRIPTION" +Certain executables distributed with the MySQL database management system do +not have specific man pages. +.SH "SEE ALSO" +In most cases, you can run the executable from the command line with a "--help" +argument to display a brief summary of the executable's arguments and function. +For more information about MySQL, please refer to the MySQL reference manual, +which may already be installed locally and which is also available online at +http://dev.mysql.com/doc/ +.SH BUGS +Please refer to http://bugs.mysql.com/ to report bugs. +.\" end of man page diff --git a/myisam/mi_key.c b/myisam/mi_key.c index 766ecf334b6..1688ab74823 100644 --- a/myisam/mi_key.c +++ b/myisam/mi_key.c @@ -177,6 +177,8 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old, if (!(*key++= (char) 1-*old++)) /* Copy null marker */ { k_length-=length; + if (keyseg->flag & (HA_VAR_LENGTH | HA_BLOB_PART)) + k_length-=2; /* Skip length */ continue; /* Found NULL */ } } diff --git a/myisam/mi_search.c b/myisam/mi_search.c index b98ee351195..cfc1c5cc3c0 100644 --- a/myisam/mi_search.c +++ b/myisam/mi_search.c @@ -63,8 +63,8 @@ int _mi_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *keypos,*maxpos; uchar lastkey[MI_MAX_KEY_BUFF],*buff; DBUG_ENTER("_mi_search"); - DBUG_PRINT("enter",("pos: %ld nextflag: %d lastpos: %ld", - pos,nextflag,info->lastpos)); + DBUG_PRINT("enter",("pos: %lu nextflag: %u lastpos: %lu", + (ulong) pos, nextflag, (ulong) info->lastpos)); DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE,keyinfo->seg,key,key_len);); if (pos == HA_OFFSET_ERROR) @@ -235,15 +235,15 @@ int _mi_seq_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, if (length == 0 || page > end) { my_errno=HA_ERR_CRASHED; - DBUG_PRINT("error",("Found wrong key: length: %d page: %lx end: %lx", - length,page,end)); + DBUG_PRINT("error",("Found wrong key: length: %u page: %p end: %p", + length, page, end)); DBUG_RETURN(MI_FOUND_WRONG_KEY); } if ((flag=_mi_key_cmp(keyinfo->seg,t_buff,key,key_len,comp_flag, ¬_used)) >= 0) break; #ifdef EXTRA_DEBUG - DBUG_PRINT("loop",("page: %lx key: '%s' flag: %d",page,t_buff,flag)); + DBUG_PRINT("loop",("page: %p key: '%s' flag: %d", page, t_buff, flag)); #endif memcpy(buff,t_buff,length); *ret_pos=page; @@ -251,7 +251,7 @@ int _mi_seq_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, if (flag == 0) memcpy(buff,t_buff,length); /* Result is first key */ *last_key= page == end; - DBUG_PRINT("exit",("flag: %d ret_pos: %lx",flag,*ret_pos)); + DBUG_PRINT("exit",("flag: %d ret_pos: %p", flag, *ret_pos)); DBUG_RETURN(flag); } /* _mi_seq_search */ @@ -350,7 +350,8 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, saved_vseg=vseg; saved_prefix_len=prefix_len; - DBUG_PRINT("loop",("page: '%.*s%.*s'",prefix_len,t_buff+seg_len_pack,suffix_len,vseg)); + DBUG_PRINT("loop",("page: '%.*s%.*s'", prefix_len, t_buff + seg_len_pack, + suffix_len, vseg)); { uchar *from=vseg+suffix_len; MI_KEYSEG *keyseg; @@ -381,8 +382,8 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, if (page > end) { my_errno=HA_ERR_CRASHED; - DBUG_PRINT("error",("Found wrong key: length: %d page: %lx end: %lx", - length,page,end)); + DBUG_PRINT("error",("Found wrong key: length: %u page: %p end: %p", + length, page, end)); DBUG_RETURN(MI_FOUND_WRONG_KEY); } @@ -463,7 +464,7 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, *last_key= page == end; - DBUG_PRINT("exit",("flag: %d ret_pos: %lx",flag,*ret_pos)); + DBUG_PRINT("exit",("flag: %d ret_pos: %p", flag, *ret_pos)); DBUG_RETURN(flag); } /* _mi_prefix_search */ @@ -540,7 +541,7 @@ my_off_t _mi_dpos(MI_INFO *info, uint nod_flag, uchar *after_key) after_key-=(nod_flag + info->s->rec_reflength); switch (info->s->rec_reflength) { #if SIZEOF_OFF_T > 4 - case 8: pos= (my_off_t) mi_uint5korr(after_key); break; + case 8: pos= (my_off_t) mi_uint8korr(after_key); break; case 7: pos= (my_off_t) mi_uint7korr(after_key); break; case 6: pos= (my_off_t) mi_uint6korr(after_key); break; case 5: pos= (my_off_t) mi_uint5korr(after_key); break; @@ -1134,8 +1135,9 @@ uint _mi_get_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag, key+= length; /* Same diff_key as prev */ if (length > keyseg->length) { - DBUG_PRINT("error",("Found too long null packed key: %d of %d at %lx", - length, keyseg->length, *page_pos)); + DBUG_PRINT("error", + ("Found too long null packed key: %u of %u at %p", + length, keyseg->length, *page_pos)); DBUG_DUMP("key",(char*) *page_pos,16); my_errno=HA_ERR_CRASHED; return 0; @@ -1190,7 +1192,7 @@ uint _mi_get_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag, } if (length > (uint) keyseg->length) { - DBUG_PRINT("error",("Found too long packed key: %d of %d at %lx", + DBUG_PRINT("error",("Found too long packed key: %u of %u at %p", length, keyseg->length, *page_pos)); DBUG_DUMP("key",(char*) *page_pos,16); my_errno=HA_ERR_CRASHED; @@ -1245,7 +1247,7 @@ uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag, { if (length > keyinfo->maxlength) { - DBUG_PRINT("error",("Found too long binary packed key: %d of %d at %lx", + DBUG_PRINT("error",("Found too long binary packed key: %u of %u at %p", length, keyinfo->maxlength, *page_pos)); DBUG_DUMP("key",(char*) *page_pos,16); my_errno=HA_ERR_CRASHED; @@ -1292,7 +1294,7 @@ uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag, length-=tmp; from=page; from_end=page_end; } - DBUG_PRINT("info",("key: %lx from: %lx length: %u", + DBUG_PRINT("info",("key: %p from: %p length: %u", key, from, length)); memcpy_overlap((byte*) key, (byte*) from, (size_t) length); key+=length; @@ -1348,7 +1350,7 @@ uchar *_mi_get_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page, } } } - DBUG_PRINT("exit",("page: %lx length: %d",page,*return_key_length)); + DBUG_PRINT("exit",("page: %p length: %u", page, *return_key_length)); DBUG_RETURN(page); } /* _mi_get_key */ @@ -1399,7 +1401,7 @@ uchar *_mi_get_last_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page, uint nod_flag; uchar *lastpos; DBUG_ENTER("_mi_get_last_key"); - DBUG_PRINT("enter",("page: %lx endpos: %lx",page,endpos)); + DBUG_PRINT("enter",("page: %p endpos: %p", page, endpos)); nod_flag=mi_test_if_nod(page); if (! (keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY))) @@ -1419,13 +1421,13 @@ uchar *_mi_get_last_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page, *return_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,lastkey); if (*return_key_length == 0) { - DBUG_PRINT("error",("Couldn't find last key: page: %lx",page)); + DBUG_PRINT("error",("Couldn't find last key: page: %p", page)); my_errno=HA_ERR_CRASHED; DBUG_RETURN(0); } } } - DBUG_PRINT("exit",("lastpos: %lx length: %d",lastpos,*return_key_length)); + DBUG_PRINT("exit",("lastpos: %p length: %u", lastpos, *return_key_length)); DBUG_RETURN(lastpos); } /* _mi_get_last_key */ @@ -1510,8 +1512,9 @@ int _mi_search_next(register MI_INFO *info, register MI_KEYDEF *keyinfo, uint nod_flag; uchar lastkey[MI_MAX_KEY_BUFF]; DBUG_ENTER("_mi_search_next"); - DBUG_PRINT("enter",("nextflag: %d lastpos: %ld int_keypos: %lx", - nextflag,(long) info->lastpos,info->int_keypos)); + DBUG_PRINT("enter",("nextflag: %u lastpos: %lu int_keypos: %lu", + nextflag, (ulong) info->lastpos, + (ulong) info->int_keypos)); DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE,keyinfo->seg,key,key_length);); /* Force full read if we are at last key or if we are not on a leaf @@ -1618,7 +1621,7 @@ int _mi_search_first(register MI_INFO *info, register MI_KEYDEF *keyinfo, info->page_changed=info->buff_used=0; info->lastpos=_mi_dpos(info,0,info->lastkey+info->lastkey_length); - DBUG_PRINT("exit",("found key at %ld",(ulong) info->lastpos)); + DBUG_PRINT("exit",("found key at %lu", (ulong) info->lastpos)); DBUG_RETURN(0); } /* _mi_search_first */ @@ -1852,8 +1855,8 @@ _mi_calc_var_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key, } s_temp->totlength=(uint) length; s_temp->prev_length=0; - DBUG_PRINT("test",("tot_length: %d length: %d uniq_key_length: %d", - key_length,length,s_temp->key_length)); + DBUG_PRINT("test",("tot_length: %u length: %d uniq_key_length: %u", + key_length, length, s_temp->key_length)); /* If something after that hasn't length=0, test if we can combine */ if ((s_temp->next_key_pos=next_key)) @@ -1959,7 +1962,7 @@ _mi_calc_var_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key, ref_length=0; next_length_pack=0; } - DBUG_PRINT("test",("length: %d next_key: %lx",length,next_key)); + DBUG_PRINT("test",("length: %d next_key: %p", length, next_key)); { uint tmp_length; diff --git a/myisammrg/myrg_open.c b/myisammrg/myrg_open.c index 5188669cad1..4c6ffb98ad5 100644 --- a/myisammrg/myrg_open.c +++ b/myisammrg/myrg_open.c @@ -32,30 +32,35 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking) { - int save_errno,i,errpos; - uint files,dir_length,length,key_parts; + int save_errno,errpos=0; + uint files=0,i,dir_length,length,key_parts; ulonglong file_offset; char name_buff[FN_REFLEN*2],buff[FN_REFLEN],*end; - MYRG_INFO info,*m_info; + MYRG_INFO *m_info=0; File fd; IO_CACHE file; - MI_INFO *isam,*last_isam; + MI_INFO *isam=0; DBUG_ENTER("myrg_open"); - LINT_INIT(last_isam); - LINT_INIT(m_info); - isam=0; - errpos=files=0; - bzero((gptr) &info,sizeof(info)); bzero((char*) &file,sizeof(file)); if ((fd=my_open(fn_format(name_buff,name,"",MYRG_NAME_EXT,4), - O_RDONLY | O_SHARE,MYF(0))) < 0 || - init_io_cache(&file, fd, IO_SIZE, READ_CACHE, 0, 0, + O_RDONLY | O_SHARE,MYF(0))) < 0) + goto err; + errpos=1; + if (init_io_cache(&file, fd, 4*IO_SIZE, READ_CACHE, 0, 0, MYF(MY_WME | MY_NABP))) - goto err; - errpos=1; + goto err; + errpos=2; dir_length=dirname_part(name_buff,name); - info.reclength=0; + while ((length=my_b_gets(&file,buff,FN_REFLEN-1))) + { + if ((end=buff+length)[-1] == '\n') + end[-1]='\0'; + if (buff[0] && buff[0] != '#') + files++; + } + + my_b_seek(&file, 0); while ((length=my_b_gets(&file,buff,FN_REFLEN-1))) { if ((end=buff+length)[-1] == '\n') @@ -67,7 +72,7 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking) if( !strncmp(buff+1,"INSERT_METHOD=",14)) { /* Lookup insert method */ int tmp=find_type(buff+15,&merge_insert_method,2); - info.merge_insert_method = (uint) (tmp >= 0 ? tmp : 0); + m_info->merge_insert_method = (uint) (tmp >= 0 ? tmp : 0); } continue; /* Skip comments */ } @@ -80,65 +85,58 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking) } if (!(isam=mi_open(buff,mode,(handle_locking?HA_OPEN_WAIT_IF_LOCKED:0)))) goto err; + if (!m_info) + { + key_parts=isam->s->base.key_parts; + if (!(m_info= (MYRG_INFO*) my_malloc(sizeof(MYRG_INFO) + + files*sizeof(MYRG_TABLE) + + key_parts*sizeof(long), + MYF(MY_WME|MY_ZEROFILL)))) + goto err; + if (files) + { + m_info->open_tables=(MYRG_TABLE *) (m_info+1); + m_info->rec_per_key_part=(ulong *) (m_info->open_tables+files); + } + else + { + m_info->open_tables=0; + m_info->rec_per_key_part=0; + } + m_info->tables=files; + m_info->reclength=isam->s->base.reclength; + file_offset=files=0; + errpos=3; + } + m_info->open_tables[files].table= isam; + m_info->open_tables[files].file_offset=(my_off_t) file_offset; + file_offset+=isam->state->data_file_length; files++; - last_isam=isam; - if (info.reclength && info.reclength != isam->s->base.reclength) + if (m_info->reclength != isam->s->base.reclength) { my_errno=HA_ERR_WRONG_MRG_TABLE_DEF; goto err; } - info.reclength=isam->s->base.reclength; - } - key_parts=(isam ? isam->s->base.key_parts : 0); - if (!(m_info= (MYRG_INFO*) my_malloc(sizeof(MYRG_INFO)+ - files*sizeof(MYRG_TABLE)+ - sizeof(long)*key_parts, - MYF(MY_WME)))) - goto err; - *m_info=info; - m_info->tables=files; - if (files) - { - m_info->open_tables=(MYRG_TABLE *) (m_info+1); - m_info->rec_per_key_part=(ulong *) (m_info->open_tables+files); - bzero((char*) m_info->rec_per_key_part,sizeof(long)*key_parts); + m_info->options|= isam->s->options; + m_info->records+= isam->state->records; + m_info->del+= isam->state->del; + m_info->data_file_length+= isam->state->data_file_length; + for (i=0; i < key_parts; i++) + m_info->rec_per_key_part[i]+=isam->s->state.rec_per_key_part[i] / m_info->tables; } - else - { - m_info->open_tables=0; - m_info->rec_per_key_part=0; - } - errpos=2; - for (i=files ; i-- > 0 ; ) - { - uint j; - m_info->open_tables[i].table=isam; - m_info->options|=isam->s->options; - m_info->records+=isam->state->records; - m_info->del+=isam->state->del; - m_info->data_file_length+=isam->state->data_file_length; - for (j=0; j < key_parts; j++) - m_info->rec_per_key_part[j]+=isam->s->state.rec_per_key_part[j] / files; - if (i) - isam=(MI_INFO*) (isam->open_list.next->data); - } + if (!m_info && !(m_info= (MYRG_INFO*) my_malloc(sizeof(MYRG_INFO), + MYF(MY_WME|MY_ZEROFILL)))) + goto err; /* Don't mark table readonly, for ALTER TABLE ... UNION=(...) to work */ m_info->options&= ~(HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA); - /* Fix fileinfo for easyer debugging (actually set by rrnd) */ - file_offset=0; - for (i=0 ; (uint) i < files ; i++) - { - m_info->open_tables[i].file_offset=(my_off_t) file_offset; - file_offset+=m_info->open_tables[i].table->state->data_file_length; - } if (sizeof(my_off_t) == 4 && file_offset > (ulonglong) (ulong) ~0L) { my_errno=HA_ERR_RECORD_FILE_FULL; goto err; } - m_info->keys=(files) ? m_info->open_tables->table->s->base.keys : 0; + m_info->keys= files ? isam->s->base.keys : 0; bzero((char*) &m_info->by_key,sizeof(m_info->by_key)); /* this works ok if the table list is empty */ @@ -156,19 +154,16 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking) err: save_errno=my_errno; switch (errpos) { - case 2: + case 3: + while (files) + mi_close(m_info->open_tables[--files].table); my_free((char*) m_info,MYF(0)); /* Fall through */ + case 2: + end_io_cache(&file); + /* Fall through */ case 1: VOID(my_close(fd,MYF(0))); - end_io_cache(&file); - for (i=files ; i-- > 0 ; ) - { - isam=last_isam; - if (i) - last_isam=(MI_INFO*) (isam->open_list.next->data); - mi_close(isam); - } } my_errno=save_errno; DBUG_RETURN (NULL); diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am index 66f931133e3..ba96c5947ba 100644 --- a/mysql-test/Makefile.am +++ b/mysql-test/Makefile.am @@ -48,6 +48,7 @@ install-data-local: $(INSTALL_DATA) $(srcdir)/r/*.require $(DESTDIR)$(testdir)/r $(INSTALL_DATA) $(srcdir)/include/*.inc $(DESTDIR)$(testdir)/include $(INSTALL_DATA) $(srcdir)/std_data/*.dat $(DESTDIR)$(testdir)/std_data + $(INSTALL_DATA) $(srcdir)/std_data/*.*001 $(DESTDIR)$(testdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/des_key_file $(DESTDIR)$(testdir)/std_data SUFFIXES = .sh diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index 449b7015188..d47560fe7a6 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -349,9 +349,11 @@ while test $# -gt 0; do VALGRIND=`which valgrind` # this will print an error if not found # Give good warning to the user and stop if [ -z "$VALGRIND" ] ; then - $ECHO "You need to have the 'valgrind' program in your PATH to run mysql-test-run with option --valgrind. Valgrind's home page is http://developer.kde.org/~sewardj ." + $ECHO "You need to have the 'valgrind' program in your PATH to run mysql-test-run with option --valgrind. Valgrind's home page is http://valgrind.kde.org ." exit 1 fi + # >=2.1.2 requires the --tool option, some versions write to stdout, some to stderr + valgrind --help 2>&1 | grep "\-\-tool" > /dev/null && VALGRIND="$VALGRIND --tool=memcheck" VALGRIND="$VALGRIND --alignment=8 --leak-check=yes --num-callers=16" EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT --skip-safemalloc --skip-bdb" EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT --skip-safemalloc --skip-bdb" @@ -589,6 +591,8 @@ show_failed_diff () echo "Please follow the instructions outlined at" echo "http://www.mysql.com/doc/en/Reporting_mysqltest_bugs.html" echo "to find the reason to this problem and how to report this." + echo "" + echo "Test $1 failed!" fi } diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index c2fd5161353..e7a8d2c7cdf 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -380,3 +380,9 @@ t1 0 PRIMARY 1 Host A NULL NULL NULL BTREE t1 0 PRIMARY 2 User A 0 NULL NULL BTREE t1 1 Host 1 Host A NULL NULL NULL BTREE disabled DROP TABLE t1; +create table t1 (a int); +alter table t1 rename to `t1\\`; +Incorrect table name 't1\\' +rename table t1 to `t1\\`; +Incorrect table name 't1\\' +drop table t1; diff --git a/mysql-test/r/binary.result b/mysql-test/r/binary.result index 2de8b01bc3a..054918e8df3 100644 --- a/mysql-test/r/binary.result +++ b/mysql-test/r/binary.result @@ -80,3 +80,21 @@ NULL select b from t1 having binary b like ''; b drop table t1; +create table t1( firstname char(20), lastname char(20)); +insert into t1 values ("john","doe"),("John","Doe"); +select * from t1 where firstname='john' and firstname like binary 'john'; +firstname lastname +john doe +select * from t1 where firstname='john' and binary 'john' = firstname; +firstname lastname +john doe +select * from t1 where firstname='john' and firstname = binary 'john'; +firstname lastname +john doe +select * from t1 where firstname='John' and firstname like binary 'john'; +firstname lastname +john doe +select * from t1 where firstname='john' and firstname like binary 'John'; +firstname lastname +John Doe +drop table t1; diff --git a/mysql-test/r/create_select_tmp.result b/mysql-test/r/create_select_tmp.result new file mode 100644 index 00000000000..610ee70b3e3 --- /dev/null +++ b/mysql-test/r/create_select_tmp.result @@ -0,0 +1,19 @@ +drop table if exists t1, t2; +CREATE TABLE t1 ( a int ); +INSERT INTO t1 VALUES (1),(2),(1); +CREATE TABLE t2 ( PRIMARY KEY (a) ) TYPE=INNODB SELECT a FROM t1; +Duplicate entry '1' for key 1 +select * from t2; +Table 'test.t2' doesn't exist +CREATE TEMPORARY TABLE t2 ( PRIMARY KEY (a) ) TYPE=INNODB SELECT a FROM t1; +Duplicate entry '1' for key 1 +select * from t2; +Table 'test.t2' doesn't exist +CREATE TABLE t2 ( PRIMARY KEY (a) ) TYPE=MYISAM SELECT a FROM t1; +Duplicate entry '1' for key 1 +select * from t2; +Table 'test.t2' doesn't exist +CREATE TEMPORARY TABLE t2 ( PRIMARY KEY (a) ) TYPE=MYISAM SELECT a FROM t1; +Duplicate entry '1' for key 1 +select * from t2; +Table 'test.t2' doesn't exist diff --git a/mysql-test/r/flush_block_commit.result b/mysql-test/r/flush_block_commit.result new file mode 100644 index 00000000000..3205dd9dad9 --- /dev/null +++ b/mysql-test/r/flush_block_commit.result @@ -0,0 +1,23 @@ +drop table if exists t1; +create table t1 (a int) type=innodb; +begin; +insert into t1 values(1); +flush tables with read lock; +select * from t1; +a + commit; +select * from t1; +a +unlock tables; +begin; +select * from t1 for update; +a +1 +begin; + select * from t1 for update; + flush tables with read lock; +commit; +a +1 +unlock tables; +drop table t1; diff --git a/mysql-test/r/func_math.result b/mysql-test/r/func_math.result index 46ad7a14e25..4688adc61d8 100644 --- a/mysql-test/r/func_math.result +++ b/mysql-test/r/func_math.result @@ -18,44 +18,44 @@ abs(-10) sign(-5) sign(5) sign(0) 10 -1 1 0 select log(exp(10)),exp(log(sqrt(10))*2),log(-1),log(NULL),log(1,1),log(3,9),log(-1,2),log(NULL,2); log(exp(10)) exp(log(sqrt(10))*2) log(-1) log(NULL) log(1,1) log(3,9) log(-1,2) log(NULL,2) -10.000000 10.000000 NULL NULL NULL 2.000000 NULL NULL +10 10 NULL NULL NULL 2 NULL NULL select ln(exp(10)),exp(ln(sqrt(10))*2),ln(-1),ln(0),ln(NULL); ln(exp(10)) exp(ln(sqrt(10))*2) ln(-1) ln(0) ln(NULL) -10.000000 10.000000 NULL NULL NULL +10 10 NULL NULL NULL select log2(8),log2(15),log2(-2),log2(0),log2(NULL); log2(8) log2(15) log2(-2) log2(0) log2(NULL) -3.000000 3.906891 NULL NULL NULL +3 3.9068905956085 NULL NULL NULL select log10(100),log10(18),log10(-4),log10(0),log10(NULL); log10(100) log10(18) log10(-4) log10(0) log10(NULL) -2.000000 1.255273 NULL NULL NULL +2 1.2552725051033 NULL NULL NULL select pow(10,log10(10)),power(2,4); pow(10,log10(10)) power(2,4) -10.000000 16.000000 +10 16 set @@rand_seed1=10000000,@@rand_seed2=1000000; select rand(999999),rand(); rand(999999) rand() 0.014231365187309 0.028870999839968 -select pi(),sin(pi()/2),cos(pi()/2),abs(tan(pi())),cot(1),asin(1),acos(0),atan(1); -pi() sin(pi()/2) cos(pi()/2) abs(tan(pi())) cot(1) asin(1) acos(0) atan(1) -3.141593 1.000000 0.000000 0.000000 0.64209262 1.570796 1.570796 0.785398 +select pi(),format(sin(pi()/2),6),format(cos(pi()/2),6),format(abs(tan(pi())),6),format(cot(1),6),format(asin(1),6),format(acos(0),6),format(atan(1),6); +pi() format(sin(pi()/2),6) format(cos(pi()/2),6) format(abs(tan(pi())),6) format(cot(1),6) format(asin(1),6) format(acos(0),6) format(atan(1),6) +3.141593 1.000000 0.000000 0.000000 0.642093 1.570796 1.570796 0.785398 select degrees(pi()),radians(360); degrees(pi()) radians(360) 180 6.2831853071796 SELECT ACOS(1.0); ACOS(1.0) -0.000000 +0 SELECT ASIN(1.0); ASIN(1.0) -1.570796 +1.5707963267949 SELECT ACOS(0.2*5.0); ACOS(0.2*5.0) -0.000000 +0 SELECT ACOS(0.5*2.0); ACOS(0.5*2.0) -0.000000 +0 SELECT ASIN(0.8+0.2); ASIN(0.8+0.2) -1.570796 +1.5707963267949 SELECT ASIN(1.2-0.2); ASIN(1.2-0.2) -1.570796 +1.5707963267949 diff --git a/mysql-test/r/func_set.result b/mysql-test/r/func_set.result index eeeb216d142..9181fe9e54d 100644 --- a/mysql-test/r/func_set.result +++ b/mysql-test/r/func_set.result @@ -28,3 +28,12 @@ find_in_set("abc","abc") find_in_set("ab","abc") find_in_set("abcd","abc") select interval(null, 1, 10, 100); interval(null, 1, 10, 100) -1 +select find_in_set(binary 'a',binary 'A,B,C'); +find_in_set(binary 'a',binary 'A,B,C') +0 +select find_in_set('a',binary 'A,B,C'); +find_in_set('a',binary 'A,B,C') +0 +select find_in_set(binary 'a', 'A,B,C'); +find_in_set(binary 'a', 'A,B,C') +0 diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index 1a968fa4f2f..d4d8dd1f026 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -131,3 +131,22 @@ Wrong usage of DB GRANT and GLOBAL PRIVILEGES select 1; 1 1 +insert into mysql.user (host, user) values ('localhost', 'test11'); +insert into mysql.db (host, db, user, select_priv) values +('localhost', 'a%', 'test11', 'Y'), ('localhost', 'ab%', 'test11', 'Y'); +alter table mysql.db order by db asc; +flush privileges; +show grants for test11@localhost; +Grants for test11@localhost +GRANT USAGE ON *.* TO 'test11'@'localhost' +GRANT SELECT ON `ab%`.* TO 'test11'@'localhost' +GRANT SELECT ON `a%`.* TO 'test11'@'localhost' +alter table mysql.db order by db desc; +flush privileges; +show grants for test11@localhost; +Grants for test11@localhost +GRANT USAGE ON *.* TO 'test11'@'localhost' +GRANT SELECT ON `ab%`.* TO 'test11'@'localhost' +GRANT SELECT ON `a%`.* TO 'test11'@'localhost' +delete from mysql.user where user='test11'; +delete from mysql.db where user='test11'; diff --git a/mysql-test/r/having.result b/mysql-test/r/having.result index d643070f7f9..f0e9172991c 100644 --- a/mysql-test/r/having.result +++ b/mysql-test/r/having.result @@ -78,3 +78,43 @@ sqty 5 9 drop table t1; +CREATE TABLE t1 ( +`id` bigint(20) NOT NULL default '0', +`description` text +) TYPE=MyISAM; +CREATE TABLE t2 ( +`id` bigint(20) NOT NULL default '0', +`description` varchar(20) +) TYPE=MyISAM; +INSERT INTO t1 VALUES (1, 'test'); +INSERT INTO t2 VALUES (1, 'test'); +CREATE TABLE t3 ( +`id` bigint(20) NOT NULL default '0', +`order_id` bigint(20) NOT NULL default '0' +) TYPE=MyISAM; +select +a.id, a.description, +count(b.id) as c +from t1 a left join t3 b on a.id=b.order_id +group by a.id, a.description +having (a.description is not null) and (c=0); +id description c +1 test 0 +select +a.*, +count(b.id) as c +from t2 a left join t3 b on a.id=b.order_id +group by a.id, a.description +having (a.description is not null) and (c=0); +id description c +1 test 0 +INSERT INTO t1 VALUES (2, 'test2'); +select +a.id, a.description, +count(b.id) as c +from t1 a left join t3 b on a.id=b.order_id +group by a.id, a.description +having (a.description is not null) and (c=0); +id description c +1 test 0 +2 test2 0 diff --git a/mysql-test/r/heap.result b/mysql-test/r/heap.result index bdf7dc225f3..11958f0a619 100644 --- a/mysql-test/r/heap.result +++ b/mysql-test/r/heap.result @@ -217,3 +217,13 @@ DELETE from t1 where a < 100; SELECT * from t1; a DROP TABLE t1; +CREATE TABLE `job_titles` ( +`job_title_id` int(6) unsigned NOT NULL default '0', +`job_title` char(18) NOT NULL default '', +PRIMARY KEY (`job_title_id`), +UNIQUE KEY `job_title_id` (`job_title_id`,`job_title`) +) TYPE=HEAP; +SELECT MAX(job_title_id) FROM job_titles; +MAX(job_title_id) +NULL +DROP TABLE job_titles; diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 6a67bbc6f8b..c282ec68c78 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -1259,3 +1259,15 @@ Cannot delete or update a parent row: a foreign key constraint fails update t3 set t3.id=7 where t1.id =1 and t2.id = t1.id and t3.id = t2.id; Unknown table 't1' in where clause drop table t3,t2,t1; +create table t1( +id int primary key, +pid int, +index(pid), +foreign key(pid) references t1(id) on delete cascade) type=innodb; +insert into t1 values(0,0),(1,0),(2,1),(3,2),(4,3),(5,4),(6,5),(7,6), +(8,7),(9,8),(10,9),(11,10),(12,11),(13,12),(14,13),(15,14); +delete from t1 where id=0; +Cannot delete or update a parent row: a foreign key constraint fails +delete from t1 where id=15; +delete from t1 where id=0; +drop table t1; diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result index ae4d99e6241..5778b2f9b72 100644 --- a/mysql-test/r/join_outer.result +++ b/mysql-test/r/join_outer.result @@ -91,7 +91,7 @@ grp a c id a c d NULL NULL NULL NULL NULL NULL explain select t1.*,t2.* from t1,t2 where t1.a=t2.a and isnull(t2.a)=1; Comment -Impossible WHERE noticed after reading const tables +Impossible WHERE explain select t1.*,t2.* from t1 left join t2 on t1.a=t2.a where isnull(t2.a)=1; table type possible_keys key key_len ref rows Extra t1 ALL NULL NULL NULL NULL 7 diff --git a/mysql-test/r/lowercase_table.result b/mysql-test/r/lowercase_table.result index 16bc92cb711..43d24b1ab17 100644 --- a/mysql-test/r/lowercase_table.result +++ b/mysql-test/r/lowercase_table.result @@ -1,4 +1,5 @@ drop table if exists t1,t2,t3,t4,T1; +drop database if exists mysqltest; create table T1 (id int primary key, Word varchar(40) not null, Index(Word)); create table t4 (id int primary key, Word varchar(40) not null); INSERT INTO T1 VALUES (1, 'a'), (2, 'b'), (3, 'c'); @@ -39,3 +40,22 @@ Unknown table 'T1' in field list select count(bags.a) from t1 as Bags; Unknown table 'bags' in field list drop table t1; +create database mysqltest; +use MYSQLTEST; +create table t1 (a int); +select T1.a from MYSQLTEST.T1; +a +select t1.a from MYSQLTEST.T1; +Unknown table 't1' in field list +select mysqltest.t1.* from MYSQLTEST.t1; +a +select MYSQLTEST.t1.* from MYSQLTEST.t1; +a +select MYSQLTEST.T1.* from MYSQLTEST.T1; +a +select MYSQLTEST.T1.* from T1; +a +alter table t1 rename to T1; +select MYSQLTEST.t1.* from MYSQLTEST.t1; +a +drop database mysqltest; diff --git a/mysql-test/r/lowercase_table2.result b/mysql-test/r/lowercase_table2.result index d2283927789..929cedb2ee3 100644 --- a/mysql-test/r/lowercase_table2.result +++ b/mysql-test/r/lowercase_table2.result @@ -32,7 +32,7 @@ T1 ALTER TABLE T1 add b int; SHOW TABLES LIKE "T1"; Tables_in_test (T1) -t1 +T1 ALTER TABLE T1 RENAME T2; SHOW TABLES LIKE "T2"; Tables_in_test (T2) @@ -41,7 +41,7 @@ LOCK TABLE T2 WRITE; ALTER TABLE T2 drop b; SHOW TABLES LIKE "T2"; Tables_in_test (T2) -t2 +T2 UNLOCK TABLES; RENAME TABLE T2 TO T1; SHOW TABLES LIKE "T1"; diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index 1fd64377f12..c55bacdd371 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -453,3 +453,12 @@ table type possible_keys key key_len ref rows Extra t1 system NULL NULL NULL NULL 1 Using temporary t2 index NULL PRIMARY 4 NULL 2 Using index; Distinct drop table t1,t2; +create table t1 ( a tinytext, b char(1), index idx (a(1),b) ); +insert into t1 values (null,''), (null,''); +explain select count(*) from t1 where a is null; +table type possible_keys key key_len ref rows Extra +t1 ref idx idx 4 const 1 Using where +select count(*) from t1 where a is null; +count(*) +2 +drop table t1; diff --git a/mysql-test/r/null.result b/mysql-test/r/null.result index ba2161d3147..41a1a06aebe 100644 --- a/mysql-test/r/null.result +++ b/mysql-test/r/null.result @@ -109,3 +109,22 @@ a b c d 0 0000-00-00 00:00:00 0 0 0000-00-00 00:00:00 0 drop table t1; +CREATE TABLE t1(i int, KEY(i)); +INSERT INTO t1 VALUES(1); +INSERT INTO t1 SELECT i*2 FROM t1; +INSERT INTO t1 SELECT i*2 FROM t1; +INSERT INTO t1 SELECT i*2 FROM t1; +INSERT INTO t1 SELECT i*2 FROM t1; +INSERT INTO t1 SELECT i*2 FROM t1; +INSERT INTO t1 SELECT i*2 FROM t1; +INSERT INTO t1 SELECT i*2 FROM t1; +INSERT INTO t1 SELECT i*2 FROM t1; +INSERT INTO t1 SELECT i*2 FROM t1; +EXPLAIN SELECT * FROM t1 WHERE i=2 OR i IS NULL; +table type possible_keys key key_len ref rows Extra +t1 range i i 5 NULL 10 Using where; Using index +ALTER TABLE t1 CHANGE i i int NOT NULL; +EXPLAIN SELECT * FROM t1 WHERE i=2 OR i IS NULL; +table type possible_keys key key_len ref rows Extra +t1 range i i 4 NULL 7 Using where; Using index +DROP TABLE t1; diff --git a/mysql-test/r/rpl_drop.result b/mysql-test/r/rpl_drop.result new file mode 100644 index 00000000000..ce1f5b6ee81 --- /dev/null +++ b/mysql-test/r/rpl_drop.result @@ -0,0 +1,10 @@ +slave stop; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +slave start; +drop table if exists t1, t2; +create table t1 (a int); +drop table t1, t2; +Unknown table 't2' diff --git a/mysql-test/r/rpl_heap.result b/mysql-test/r/rpl_heap.result index 1556bcd5f25..1facbcb7676 100644 --- a/mysql-test/r/rpl_heap.result +++ b/mysql-test/r/rpl_heap.result @@ -1,22 +1,22 @@ reset master; drop table if exists t1; -create table t1 (a int) type=HEAP; -insert into t1 values(10); +create table t1 type=HEAP select 10 as a; +insert into t1 values(11); show binlog events from 79; Log_name Pos Event_type Server_id Orig_log_pos Info -master-bin.001 79 Query 1 79 use `test`; create table t1 (a int) type=HEAP -master-bin.001 147 Query 1 147 use `test`; DELETE FROM `test`.`t1` -master-bin.001 205 Query 1 205 use `test`; insert into t1 values(10) +master-bin.001 79 Query 1 79 use `test`; create table t1 type=HEAP select 10 as a +master-bin.001 154 Query 1 154 use `test`; insert into t1 values(11) reset slave; start slave; show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` int(11) default NULL + `a` bigint(2) NOT NULL default '0' ) TYPE=HEAP select * from t1; a 10 +11 select * from t1; a select * from t1 limit 10; diff --git a/mysql-test/r/system_mysql_db_refs.result b/mysql-test/r/system_mysql_db_refs.result index e15934b03ac..ac072505bc9 100644 --- a/mysql-test/r/system_mysql_db_refs.result +++ b/mysql-test/r/system_mysql_db_refs.result @@ -18,44 +18,44 @@ create table test_columns_priv select * from mysql.columns_priv; delete from test_columns_priv; insert into test_columns_priv (Host,Db,User,Table_name,Column_name) values (@name,@name,@name,@name,@name); select -if(isnull(test_db.Host),'WRONG!!!','ok') as test_db_Host,
-if(isnull(test_host.Host),'WRONG!!!','ok') as test_host_Host,
-if(isnull(test_user.Host),'WRONG!!!','ok') as test_user_Host,
-if(isnull(test_tables_priv.Host),'WRONG!!!','ok') as test_tables_priv_Host,
-if(isnull(test_columns_priv.Host),'WRONG!!!','ok') as test_columns_priv_Host
-from test_db
-left join test_host on test_db.Host=test_host.Host
-left join test_user on test_db.Host=test_user.Host
-left join test_tables_priv on test_db.Host=test_tables_priv.Host
+if(isnull(test_db.Host),'WRONG!!!','ok') as test_db_Host, +if(isnull(test_host.Host),'WRONG!!!','ok') as test_host_Host, +if(isnull(test_user.Host),'WRONG!!!','ok') as test_user_Host, +if(isnull(test_tables_priv.Host),'WRONG!!!','ok') as test_tables_priv_Host, +if(isnull(test_columns_priv.Host),'WRONG!!!','ok') as test_columns_priv_Host +from test_db +left join test_host on test_db.Host=test_host.Host +left join test_user on test_db.Host=test_user.Host +left join test_tables_priv on test_db.Host=test_tables_priv.Host left join test_columns_priv on test_db.Host=test_columns_priv.Host; test_db_Host test_host_Host test_user_Host test_tables_priv_Host test_columns_priv_Host ok ok ok ok ok select -if(isnull(test_db.Db),'WRONG!!!','ok') as test_db_Db,
-if(isnull(test_host.Db),'WRONG!!!','ok') as test_host_Db,
-if(isnull(test_tables_priv.Db),'WRONG!!!','ok') as test_tables_priv_Db,
-if(isnull(test_columns_priv.Db),'WRONG!!!','ok') as est_columns_priv_Db
-from test_db
-left join test_host on test_db.Db=test_host.Db
-left join test_tables_priv on test_db.Db=test_tables_priv.Db
+if(isnull(test_db.Db),'WRONG!!!','ok') as test_db_Db, +if(isnull(test_host.Db),'WRONG!!!','ok') as test_host_Db, +if(isnull(test_tables_priv.Db),'WRONG!!!','ok') as test_tables_priv_Db, +if(isnull(test_columns_priv.Db),'WRONG!!!','ok') as est_columns_priv_Db +from test_db +left join test_host on test_db.Db=test_host.Db +left join test_tables_priv on test_db.Db=test_tables_priv.Db left join test_columns_priv on test_db.Db=test_columns_priv.Db; test_db_Db test_host_Db test_tables_priv_Db est_columns_priv_Db ok ok ok ok -select
-if(isnull(test_db.User),'WRONG!!!','ok') as test_db_User,
-if(isnull(test_user.User),'WRONG!!!','ok') as test_user_User,
-if(isnull(test_tables_priv.User),'WRONG!!!','ok') as test_tables_priv_User,
-if(isnull(test_columns_priv.User),'WRONG!!!','ok') as test_columns_priv_User
-from test_db
-left join test_user on test_db.User=test_user.User
-left join test_tables_priv on test_db.User=test_tables_priv.User
+select +if(isnull(test_db.User),'WRONG!!!','ok') as test_db_User, +if(isnull(test_user.User),'WRONG!!!','ok') as test_user_User, +if(isnull(test_tables_priv.User),'WRONG!!!','ok') as test_tables_priv_User, +if(isnull(test_columns_priv.User),'WRONG!!!','ok') as test_columns_priv_User +from test_db +left join test_user on test_db.User=test_user.User +left join test_tables_priv on test_db.User=test_tables_priv.User left join test_columns_priv on test_db.User=test_columns_priv.User; test_db_User test_user_User test_tables_priv_User test_columns_priv_User ok ok ok ok -select
-if(isnull(test_tables_priv.User),'WRONG!!!','ok') as test_tables_priv_User,
-if(isnull(test_columns_priv.User),'WRONG!!!','ok') as test_columns_priv_User
-from test_tables_priv
+select +if(isnull(test_tables_priv.User),'WRONG!!!','ok') as test_tables_priv_User, +if(isnull(test_columns_priv.User),'WRONG!!!','ok') as test_columns_priv_User +from test_tables_priv left join test_columns_priv on test_tables_priv.Table_name=test_columns_priv.Table_name; test_tables_priv_User test_columns_priv_User ok ok diff --git a/mysql-test/r/truncate.result b/mysql-test/r/truncate.result index 1b387214292..fef15533738 100644 --- a/mysql-test/r/truncate.result +++ b/mysql-test/r/truncate.result @@ -31,4 +31,25 @@ SELECT * from t1; a 1 2 +delete from t1; +insert into t1 (a) values (NULL),(NULL); +SELECT * from t1; +a +3 +4 +drop table t1; +create temporary table t1 (a integer auto_increment primary key); +insert into t1 (a) values (NULL),(NULL); +truncate table t1; +insert into t1 (a) values (NULL),(NULL); +SELECT * from t1; +a +1 +2 +delete from t1; +insert into t1 (a) values (NULL),(NULL); +SELECT * from t1; +a +3 +4 drop table t1; diff --git a/mysql-test/r/type_date.result b/mysql-test/r/type_date.result index 3b08f7dcbf2..5ec2c9e0434 100644 --- a/mysql-test/r/type_date.result +++ b/mysql-test/r/type_date.result @@ -79,3 +79,20 @@ SELECT DATE_FORMAT(f1, "%l.%i %p") , DATE_FORMAT(f2, "%l.%i %p") FROM t1; DATE_FORMAT(f1, "%l.%i %p") DATE_FORMAT(f2, "%l.%i %p") 9.00 AM 12.00 PM DROP TABLE t1; +CREATE TABLE t1 (f1 DATE); +CREATE TABLE t2 (f2 VARCHAR(8)); +CREATE TABLE t3 (f2 CHAR(8)); +INSERT INTO t1 VALUES ('1978-11-26'); +INSERT INTO t2 SELECT f1+0 FROM t1; +INSERT INTO t2 SELECT f1+0 FROM t1 UNION SELECT f1+0 FROM t1; +INSERT INTO t3 SELECT f1+0 FROM t1; +INSERT INTO t3 SELECT f1+0 FROM t1 UNION SELECT f1+0 FROM t1; +SELECT * FROM t2; +f2 +19781126 +19781126 +SELECT * FROM t3; +f2 +19781126 +19781126 +DROP TABLE t1, t2, t3; diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result index c9996e9c9f3..f4c5df353a3 100644 --- a/mysql-test/r/type_float.result +++ b/mysql-test/r/type_float.result @@ -72,14 +72,17 @@ insert t1 values (121,"16"); select c1 + c1 * (c2 / 100) as col from t1; col 140.36 -create table t2 select c1 + c1 * (c2 / 100) as col from t1; +create table t2 select c1 + c1 * (c2 / 100) as col1, round(c1, 5) as col2, round(c1, 35) as col3, sqrt(c1*1e-15) col4 from t1; select * from t2; -col -140.36 +col1 col2 col3 col4 +140.36 121.00000 121 3.47850542618522e-07 show create table t2; Table Create Table t2 CREATE TABLE `t2` ( - `col` double default NULL + `col1` double default NULL, + `col2` double(22,5) default NULL, + `col3` double default NULL, + `col4` double default NULL ) TYPE=MyISAM drop table t1,t2; create table t1 (f float, f2 float(24), f3 float(6,2), d double, d2 float(53), d3 double(10,3), de decimal, de2 decimal(6), de3 decimal(5,2), n numeric, n2 numeric(8), n3 numeric(5,6)); @@ -111,6 +114,9 @@ select min(a) from t1; min(a) -0.010 drop table t1; +create table t1 (c20 char); +insert into t1 (c20) values (5000.0); +drop table t1; create table t1 (f float(54)); Incorrect column specifier for column 'f' drop table if exists t1; diff --git a/mysql-test/r/type_timestamp.result b/mysql-test/r/type_timestamp.result index cd45bcf911d..752a5045eb0 100644 --- a/mysql-test/r/type_timestamp.result +++ b/mysql-test/r/type_timestamp.result @@ -167,3 +167,15 @@ ts1 ts2 2001-09-09 04:46:40 0000-00-00 00:00:00 2001-09-09 04:46:40 0000-00-00 00:00:00 drop table t1; +create table t1 (ts timestamp(19)); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `ts` timestamp(19) NOT NULL +) TYPE=MyISAM +set TIMESTAMP=1000000000; +insert into t1 values (); +select * from t1; +ts +2001-09-09 04:46:40 +drop table t1; diff --git a/mysql-test/r/type_uint.result b/mysql-test/r/type_uint.result index 1acfc700d3a..0b7452b566b 100644 --- a/mysql-test/r/type_uint.result +++ b/mysql-test/r/type_uint.result @@ -2,8 +2,10 @@ drop table if exists t1; create table t1 (this int unsigned); insert into t1 values (1); insert into t1 values (-1); +insert into t1 values ('5000000000'); select * from t1; this 1 0 +4294967295 drop table t1; diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index e36f4165f46..13d09e09783 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -381,3 +381,19 @@ set global myisam_max_sort_file_size=4294967296; show global variables like 'myisam_max_sort_file_size'; Variable_name Value myisam_max_sort_file_size MAX_FILE_SIZE +set @tstlw = @@log_warnings; +show global variables like 'log_warnings'; +Variable_name Value +log_warnings 1 +set global log_warnings = 0; +show global variables like 'log_warnings'; +Variable_name Value +log_warnings 0 +set global log_warnings = 42; +show global variables like 'log_warnings'; +Variable_name Value +log_warnings 42 +set global log_warnings = @tstlw; +show global variables like 'log_warnings'; +Variable_name Value +log_warnings 1 diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test index 9a29ab3c2d7..11290134a71 100644 --- a/mysql-test/t/alter_table.test +++ b/mysql-test/t/alter_table.test @@ -243,3 +243,14 @@ LOCK TABLES t1 WRITE; ALTER TABLE t1 DISABLE KEYS; SHOW INDEX FROM t1; DROP TABLE t1; + +# +# BUG#4717 - check for valid table names +# +create table t1 (a int); +--error 1103 +alter table t1 rename to `t1\\`; +--error 1103 +rename table t1 to `t1\\`; +drop table t1; + diff --git a/mysql-test/t/binary.test b/mysql-test/t/binary.test index 95815cda60f..a8c724bf33b 100644 --- a/mysql-test/t/binary.test +++ b/mysql-test/t/binary.test @@ -49,3 +49,16 @@ select b from t1 where binary b like ''; select b from t1 group by binary b like ''; select b from t1 having binary b like ''; drop table t1; + +# +# Bug5134: WHERE x = 'bar' AND x LIKE BINARY 'bar' returns wrong results +# + +create table t1( firstname char(20), lastname char(20)); +insert into t1 values ("john","doe"),("John","Doe"); +select * from t1 where firstname='john' and firstname like binary 'john'; +select * from t1 where firstname='john' and binary 'john' = firstname; +select * from t1 where firstname='john' and firstname = binary 'john'; +select * from t1 where firstname='John' and firstname like binary 'john'; +select * from t1 where firstname='john' and firstname like binary 'John'; +drop table t1; diff --git a/mysql-test/t/create_select_tmp.test b/mysql-test/t/create_select_tmp.test new file mode 100644 index 00000000000..36292abd899 --- /dev/null +++ b/mysql-test/t/create_select_tmp.test @@ -0,0 +1,27 @@ +# Testcase for BUG#4551 +# The bug was that when the table was TEMPORARY, it was not deleted if +# the CREATE SELECT failed (the code intended too, but it actually +# didn't). And as the CREATE TEMPORARY TABLE was not written to the +# binlog if it was a transactional table, it resulted in an +# inconsistency between binlog and the internal list of temp tables. + +-- source include/have_innodb.inc +drop table if exists t1, t2; +CREATE TABLE t1 ( a int ); +INSERT INTO t1 VALUES (1),(2),(1); +--error 1062; +CREATE TABLE t2 ( PRIMARY KEY (a) ) TYPE=INNODB SELECT a FROM t1; +--error 1146; +select * from t2; +--error 1062; +CREATE TEMPORARY TABLE t2 ( PRIMARY KEY (a) ) TYPE=INNODB SELECT a FROM t1; +--error 1146; +select * from t2; +--error 1062; +CREATE TABLE t2 ( PRIMARY KEY (a) ) TYPE=MYISAM SELECT a FROM t1; +--error 1146; +select * from t2; +--error 1062; +CREATE TEMPORARY TABLE t2 ( PRIMARY KEY (a) ) TYPE=MYISAM SELECT a FROM t1; +--error 1146; +select * from t2; diff --git a/mysql-test/t/flush_block_commit.test b/mysql-test/t/flush_block_commit.test new file mode 100644 index 00000000000..20ecec1361c --- /dev/null +++ b/mysql-test/t/flush_block_commit.test @@ -0,0 +1,49 @@ +# Let's see if FLUSH TABLES WITH READ LOCK blocks COMMIT of existing +# transactions. +# We verify that we did not introduce a deadlock. + +-- source include/have_innodb.inc + +connect (con1,localhost,root,,); +connect (con2,localhost,root,,); +connect (con3,localhost,root,,); +connection con1; +drop table if exists t1; +create table t1 (a int) type=innodb; + +# blocks COMMIT ? + +begin; +insert into t1 values(1); +connection con2; +flush tables with read lock; +select * from t1; +connection con1; +send commit; # blocked by con2 +sleep 1; +connection con2; +select * from t1; # verify con1 was blocked and data did not move +unlock tables; +connection con1; +reap; + +# No deadlock ? + +connection con1; +begin; +select * from t1 for update; +connection con2; +begin; +send select * from t1 for update; # blocked by con1 +sleep 1; +connection con3; +send flush tables with read lock; # blocked by con2 +connection con1; +commit; # should not be blocked by con3 +connection con2; +reap; +connection con3; +reap; +unlock tables; +connection con1; +drop table t1; diff --git a/mysql-test/t/func_math.test b/mysql-test/t/func_math.test index ca958253d14..e745c7738ac 100644 --- a/mysql-test/t/func_math.test +++ b/mysql-test/t/func_math.test @@ -15,7 +15,7 @@ select log10(100),log10(18),log10(-4),log10(0),log10(NULL); select pow(10,log10(10)),power(2,4); set @@rand_seed1=10000000,@@rand_seed2=1000000; select rand(999999),rand(); -select pi(),sin(pi()/2),cos(pi()/2),abs(tan(pi())),cot(1),asin(1),acos(0),atan(1); +select pi(),format(sin(pi()/2),6),format(cos(pi()/2),6),format(abs(tan(pi())),6),format(cot(1),6),format(asin(1),6),format(acos(0),6),format(atan(1),6); select degrees(pi()),radians(360); # diff --git a/mysql-test/t/func_set.test b/mysql-test/t/func_set.test index 81f561989d5..a1ee293ae05 100644 --- a/mysql-test/t/func_set.test +++ b/mysql-test/t/func_set.test @@ -16,3 +16,11 @@ select elt(2,1),field(NULL,"a","b","c"); select find_in_set("","a,b,c"),find_in_set("","a,b,c,"),find_in_set("",",a,b,c"); select find_in_set("abc","abc"),find_in_set("ab","abc"),find_in_set("abcd","abc"); select interval(null, 1, 10, 100); + +# +# Bug4340: find_in_set is case insensitive even on binary operators +# + +select find_in_set(binary 'a',binary 'A,B,C'); +select find_in_set('a',binary 'A,B,C'); +select find_in_set(binary 'a', 'A,B,C'); diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test index 598a7186a6e..a278b9d5928 100644 --- a/mysql-test/t/grant.test +++ b/mysql-test/t/grant.test @@ -89,3 +89,19 @@ drop table t1; --error 1221 GRANT FILE on mysqltest.* to mysqltest_1@localhost; select 1; -- To test that the previous command didn't cause problems + + +# +# Bug #4898: User privileges depending on ORDER BY Settings of table db +# +insert into mysql.user (host, user) values ('localhost', 'test11'); +insert into mysql.db (host, db, user, select_priv) values +('localhost', 'a%', 'test11', 'Y'), ('localhost', 'ab%', 'test11', 'Y'); +alter table mysql.db order by db asc; +flush privileges; +show grants for test11@localhost; +alter table mysql.db order by db desc; +flush privileges; +show grants for test11@localhost; +delete from mysql.user where user='test11'; +delete from mysql.db where user='test11'; diff --git a/mysql-test/t/having.test b/mysql-test/t/having.test index cb6fa85ffde..c8835bf1613 100644 --- a/mysql-test/t/having.test +++ b/mysql-test/t/having.test @@ -66,3 +66,49 @@ select id, sum(qty) as sqty from t1 group by id having sqty>2; select sum(qty) as sqty from t1 group by id having count(id) > 0; select sum(qty) as sqty from t1 group by id having count(distinct id) > 0; drop table t1; + +# +# Test case for Bug #4358 Problem with HAVING clause that uses alias from the +# select list and TEXT field +# + +CREATE TABLE t1 ( + `id` bigint(20) NOT NULL default '0', + `description` text +) TYPE=MyISAM; + +CREATE TABLE t2 ( + `id` bigint(20) NOT NULL default '0', + `description` varchar(20) +) TYPE=MyISAM; + +INSERT INTO t1 VALUES (1, 'test'); +INSERT INTO t2 VALUES (1, 'test'); + +CREATE TABLE t3 ( + `id` bigint(20) NOT NULL default '0', + `order_id` bigint(20) NOT NULL default '0' +) TYPE=MyISAM; + +select + a.id, a.description, + count(b.id) as c +from t1 a left join t3 b on a.id=b.order_id +group by a.id, a.description +having (a.description is not null) and (c=0); + +select + a.*, + count(b.id) as c +from t2 a left join t3 b on a.id=b.order_id +group by a.id, a.description +having (a.description is not null) and (c=0); + +INSERT INTO t1 VALUES (2, 'test2'); + +select + a.id, a.description, + count(b.id) as c +from t1 a left join t3 b on a.id=b.order_id +group by a.id, a.description +having (a.description is not null) and (c=0); diff --git a/mysql-test/t/heap.test b/mysql-test/t/heap.test index b2de58ca083..87518798a36 100644 --- a/mysql-test/t/heap.test +++ b/mysql-test/t/heap.test @@ -147,3 +147,17 @@ INSERT into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11); DELETE from t1 where a < 100; SELECT * from t1; DROP TABLE t1; + +# +# Bug#4411 Server hangs when trying to SELECT MAX(id) from an empty HEAP table +# +CREATE TABLE `job_titles` ( + `job_title_id` int(6) unsigned NOT NULL default '0', + `job_title` char(18) NOT NULL default '', + PRIMARY KEY (`job_title_id`), + UNIQUE KEY `job_title_id` (`job_title_id`,`job_title`) +) TYPE=HEAP; + +SELECT MAX(job_title_id) FROM job_titles; + +DROP TABLE job_titles; diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index 04642ddd619..34eabcc22df 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -896,3 +896,17 @@ update t1,t2,t3 set t3.id=5, t2.id=6, t1.id=7 where t1.id =1 and t2.id = t1.id --error 1109 update t3 set t3.id=7 where t1.id =1 and t2.id = t1.id and t3.id = t2.id; drop table t3,t2,t1; + +create table t1( + id int primary key, + pid int, + index(pid), + foreign key(pid) references t1(id) on delete cascade) type=innodb; +insert into t1 values(0,0),(1,0),(2,1),(3,2),(4,3),(5,4),(6,5),(7,6), + (8,7),(9,8),(10,9),(11,10),(12,11),(13,12),(14,13),(15,14); +-- error 1217 +delete from t1 where id=0; +delete from t1 where id=15; +delete from t1 where id=0; + +drop table t1; diff --git a/mysql-test/t/lowercase_table.test b/mysql-test/t/lowercase_table.test index 5bc19f26c0e..1b431a9d920 100644 --- a/mysql-test/t/lowercase_table.test +++ b/mysql-test/t/lowercase_table.test @@ -3,6 +3,7 @@ # drop table if exists t1,t2,t3,t4,T1; +drop database if exists mysqltest; create table T1 (id int primary key, Word varchar(40) not null, Index(Word)); create table t4 (id int primary key, Word varchar(40) not null); INSERT INTO T1 VALUES (1, 'a'), (2, 'b'), (3, 'c'); @@ -30,3 +31,20 @@ select count(T1.a) from t1; --error 1109 select count(bags.a) from t1 as Bags; drop table t1; + +# +# Test all caps database name +# +create database mysqltest; +use MYSQLTEST; +create table t1 (a int); +select T1.a from MYSQLTEST.T1; +--error 1109 +select t1.a from MYSQLTEST.T1; +select mysqltest.t1.* from MYSQLTEST.t1; +select MYSQLTEST.t1.* from MYSQLTEST.t1; +select MYSQLTEST.T1.* from MYSQLTEST.T1; +select MYSQLTEST.T1.* from T1; +alter table t1 rename to T1; +select MYSQLTEST.t1.* from MYSQLTEST.t1; +drop database mysqltest; diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index 59b86309d77..57b64e30bac 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -436,3 +436,13 @@ select sql_big_result distinct t1.a from t1,t2; explain select sql_big_result distinct t1.a from t1,t2 order by t2.a; explain select distinct t1.a from t1,t2 order by t2.a; drop table t1,t2; + +# +# index search for NULL in blob. Bug #4816 +# +create table t1 ( a tinytext, b char(1), index idx (a(1),b) ); +insert into t1 values (null,''), (null,''); +explain select count(*) from t1 where a is null; +select count(*) from t1 where a is null; +drop table t1; + diff --git a/mysql-test/t/null.test b/mysql-test/t/null.test index 6fea7f0d10d..fc9b0a8aff2 100644 --- a/mysql-test/t/null.test +++ b/mysql-test/t/null.test @@ -79,3 +79,26 @@ INSERT INTO t1 (d) values (null),(null); select * from t1; drop table t1; +# Test case for bug #4256 + +CREATE TABLE t1(i int, KEY(i)); + +INSERT INTO t1 VALUES(1); + +INSERT INTO t1 SELECT i*2 FROM t1; +INSERT INTO t1 SELECT i*2 FROM t1; +INSERT INTO t1 SELECT i*2 FROM t1; +INSERT INTO t1 SELECT i*2 FROM t1; +INSERT INTO t1 SELECT i*2 FROM t1; +INSERT INTO t1 SELECT i*2 FROM t1; +INSERT INTO t1 SELECT i*2 FROM t1; +INSERT INTO t1 SELECT i*2 FROM t1; +INSERT INTO t1 SELECT i*2 FROM t1; + +EXPLAIN SELECT * FROM t1 WHERE i=2 OR i IS NULL; + +ALTER TABLE t1 CHANGE i i int NOT NULL; + +EXPLAIN SELECT * FROM t1 WHERE i=2 OR i IS NULL; + +DROP TABLE t1; diff --git a/mysql-test/t/rpl_drop.test b/mysql-test/t/rpl_drop.test new file mode 100644 index 00000000000..6fc2500fc97 --- /dev/null +++ b/mysql-test/t/rpl_drop.test @@ -0,0 +1,10 @@ +# Testcase for BUG#4552 (DROP on two tables, one of which does not +# exist, must be binlogged with a non-zero error code) +source include/master-slave.inc; +drop table if exists t1, t2; +create table t1 (a int); +--error 1051; +drop table t1, t2; +save_master_pos; +connection slave; +sync_with_master; diff --git a/mysql-test/t/rpl_heap.test b/mysql-test/t/rpl_heap.test index 15f61918034..0bc71eaf30c 100644 --- a/mysql-test/t/rpl_heap.test +++ b/mysql-test/t/rpl_heap.test @@ -13,8 +13,10 @@ connect (slave,localhost,root,,test,0,slave.sock); connection master; reset master; drop table if exists t1; -create table t1 (a int) type=HEAP; -insert into t1 values(10); +# we use CREATE SELECT to verify that DELETE does not get into binlog +# before CREATE SELECT +create table t1 type=HEAP select 10 as a; +insert into t1 values(11); save_master_pos; show binlog events from 79; connection slave; diff --git a/mysql-test/t/system_mysql_db.test b/mysql-test/t/system_mysql_db.test index bd69297b739..85a2f7f9bae 100644 --- a/mysql-test/t/system_mysql_db.test +++ b/mysql-test/t/system_mysql_db.test @@ -1,8 +1,8 @@ -#
-# This test must examine integrity of system database "mysql"
-#
-
--- disable_query_log
-use mysql;
--- enable_query_log
--- source include/system_db_struct.inc
+# +# This test must examine integrity of system database "mysql" +# + +-- disable_query_log +use mysql; +-- enable_query_log +-- source include/system_db_struct.inc diff --git a/mysql-test/t/system_mysql_db_fix.test b/mysql-test/t/system_mysql_db_fix.test index 6f3979bf66e..0acc7ea073d 100644 --- a/mysql-test/t/system_mysql_db_fix.test +++ b/mysql-test/t/system_mysql_db_fix.test @@ -1,78 +1,78 @@ -#
+# # This is the test for mysql_fix_privilege_tables -#
+# --- disable_result_log
--- disable_query_log
-
-use test;
-
-# create system tables as in mysql-3.20
-
-CREATE TABLE db (
- Host char(60) binary DEFAULT '' NOT NULL,
- Db char(32) binary DEFAULT '' NOT NULL,
- User char(16) binary DEFAULT '' NOT NULL,
- Select_priv enum('N','Y') DEFAULT 'N' NOT NULL,
- Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL,
- Update_priv enum('N','Y') DEFAULT 'N' NOT NULL,
- Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL,
- Create_priv enum('N','Y') DEFAULT 'N' NOT NULL,
- Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL,
- PRIMARY KEY Host (Host,Db,User),
- KEY User (User)
-)
-type=ISAM;
+-- disable_result_log +-- disable_query_log -INSERT INTO db VALUES ('%','test', '','Y','Y','Y','Y','Y','Y');
-INSERT INTO db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y');
+use test; -CREATE TABLE host (
- Host char(60) binary DEFAULT '' NOT NULL,
- Db char(32) binary DEFAULT '' NOT NULL,
- Select_priv enum('N','Y') DEFAULT 'N' NOT NULL,
- Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL,
- Update_priv enum('N','Y') DEFAULT 'N' NOT NULL,
- Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL,
- Create_priv enum('N','Y') DEFAULT 'N' NOT NULL,
- Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL,
- PRIMARY KEY Host (Host,Db)
-)
-type=ISAM;
+# create system tables as in mysql-3.20 -CREATE TABLE user (
- Host char(60) binary DEFAULT '' NOT NULL,
- User char(16) binary DEFAULT '' NOT NULL,
- Password char(16),
- Select_priv enum('N','Y') DEFAULT 'N' NOT NULL,
- Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL,
- Update_priv enum('N','Y') DEFAULT 'N' NOT NULL,
- Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL,
- Create_priv enum('N','Y') DEFAULT 'N' NOT NULL,
- Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL,
- Reload_priv enum('N','Y') DEFAULT 'N' NOT NULL,
- Shutdown_priv enum('N','Y') DEFAULT 'N' NOT NULL,
- Process_priv enum('N','Y') DEFAULT 'N' NOT NULL,
- PRIMARY KEY Host (Host,User)
-)
-type=ISAM;
+CREATE TABLE db ( + Host char(60) binary DEFAULT '' NOT NULL, + Db char(32) binary DEFAULT '' NOT NULL, + User char(16) binary DEFAULT '' NOT NULL, + Select_priv enum('N','Y') DEFAULT 'N' NOT NULL, + Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL, + Update_priv enum('N','Y') DEFAULT 'N' NOT NULL, + Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL, + Create_priv enum('N','Y') DEFAULT 'N' NOT NULL, + Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL, + PRIMARY KEY Host (Host,Db,User), + KEY User (User) +) +type=ISAM; + +INSERT INTO db VALUES ('%','test', '','Y','Y','Y','Y','Y','Y'); +INSERT INTO db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y'); + +CREATE TABLE host ( + Host char(60) binary DEFAULT '' NOT NULL, + Db char(32) binary DEFAULT '' NOT NULL, + Select_priv enum('N','Y') DEFAULT 'N' NOT NULL, + Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL, + Update_priv enum('N','Y') DEFAULT 'N' NOT NULL, + Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL, + Create_priv enum('N','Y') DEFAULT 'N' NOT NULL, + Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL, + PRIMARY KEY Host (Host,Db) +) +type=ISAM; + +CREATE TABLE user ( + Host char(60) binary DEFAULT '' NOT NULL, + User char(16) binary DEFAULT '' NOT NULL, + Password char(16), + Select_priv enum('N','Y') DEFAULT 'N' NOT NULL, + Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL, + Update_priv enum('N','Y') DEFAULT 'N' NOT NULL, + Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL, + Create_priv enum('N','Y') DEFAULT 'N' NOT NULL, + Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL, + Reload_priv enum('N','Y') DEFAULT 'N' NOT NULL, + Shutdown_priv enum('N','Y') DEFAULT 'N' NOT NULL, + Process_priv enum('N','Y') DEFAULT 'N' NOT NULL, + PRIMARY KEY Host (Host,User) +) +type=ISAM; + +INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y'); +INSERT INTO user VALUES ('localhost','', '','N','N','N','N','N','N','N','N','N'); -INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y');
-INSERT INTO user VALUES ('localhost','', '','N','N','N','N','N','N','N','N','N');
-
-- exec $MYSQL_FIX_SYSTEM_TABLES --database=test --- enable_query_log
--- enable_result_log
-
--- source include/system_db_struct.inc
-
--- disable_query_log
-
-DROP TABLE db;
-DROP TABLE host;
-DROP TABLE user;
-DROP TABLE func;
-DROP TABLE tables_priv;
-DROP TABLE columns_priv;
-
--- enable_query_log
+-- enable_query_log +-- enable_result_log + +-- source include/system_db_struct.inc + +-- disable_query_log + +DROP TABLE db; +DROP TABLE host; +DROP TABLE user; +DROP TABLE func; +DROP TABLE tables_priv; +DROP TABLE columns_priv; + +-- enable_query_log diff --git a/mysql-test/t/system_mysql_db_refs.test b/mysql-test/t/system_mysql_db_refs.test index 49d6f198b32..b68503a6aa5 100644 --- a/mysql-test/t/system_mysql_db_refs.test +++ b/mysql-test/t/system_mysql_db_refs.test @@ -1,89 +1,89 @@ -#
-# This test must examine integrity of current system database
-#
-
-set @name="This is a very long string, that mustn't find room in a system field like Table_name. Thus it should be cut by the actual size of the field. So we can use this string to find out the actual length of the field and to use it in any compare queries";
-
-#
-# If this part is wrong, most likely you've done wrong modification of system database "mysql"
-#
-
-create table test_db select * from mysql.db;
-delete from test_db;
-insert into test_db (Host,Db,User) values (@name,@name,@name);
-
-create table test_host select * from mysql.host;
-delete from test_host;
-insert into test_host (Host,Db) values (@name,@name);
-
-create table test_user select * from mysql.user;
-delete from test_user;
-insert into test_user (Host,User) values (@name,@name);
-
-create table test_func select * from mysql.func;
-delete from test_func;
-insert into test_func (name) values (@name);
-
-create table test_tables_priv select * from mysql.tables_priv;
-delete from test_tables_priv;
-insert into test_tables_priv (Host,Db,User,Table_name) values (@name,@name,@name,@name);
-
-create table test_columns_priv select * from mysql.columns_priv;
-delete from test_columns_priv;
-insert into test_columns_priv (Host,Db,User,Table_name,Column_name) values (@name,@name,@name,@name,@name);
-
-# 'Host' field must be the same for all the tables:
-
+# +# This test must examine integrity of current system database +# + +set @name="This is a very long string, that mustn't find room in a system field like Table_name. Thus it should be cut by the actual size of the field. So we can use this string to find out the actual length of the field and to use it in any compare queries"; + +# +# If this part is wrong, most likely you've done wrong modification of system database "mysql" +# + +create table test_db select * from mysql.db; +delete from test_db; +insert into test_db (Host,Db,User) values (@name,@name,@name); + +create table test_host select * from mysql.host; +delete from test_host; +insert into test_host (Host,Db) values (@name,@name); + +create table test_user select * from mysql.user; +delete from test_user; +insert into test_user (Host,User) values (@name,@name); + +create table test_func select * from mysql.func; +delete from test_func; +insert into test_func (name) values (@name); + +create table test_tables_priv select * from mysql.tables_priv; +delete from test_tables_priv; +insert into test_tables_priv (Host,Db,User,Table_name) values (@name,@name,@name,@name); + +create table test_columns_priv select * from mysql.columns_priv; +delete from test_columns_priv; +insert into test_columns_priv (Host,Db,User,Table_name,Column_name) values (@name,@name,@name,@name,@name); + +# 'Host' field must be the same for all the tables: + +select + if(isnull(test_db.Host),'WRONG!!!','ok') as test_db_Host, + if(isnull(test_host.Host),'WRONG!!!','ok') as test_host_Host, + if(isnull(test_user.Host),'WRONG!!!','ok') as test_user_Host, + if(isnull(test_tables_priv.Host),'WRONG!!!','ok') as test_tables_priv_Host, + if(isnull(test_columns_priv.Host),'WRONG!!!','ok') as test_columns_priv_Host + +from test_db +left join test_host on test_db.Host=test_host.Host +left join test_user on test_db.Host=test_user.Host +left join test_tables_priv on test_db.Host=test_tables_priv.Host +left join test_columns_priv on test_db.Host=test_columns_priv.Host; + +# 'Db' field must be the same for all the tables: + select - if(isnull(test_db.Host),'WRONG!!!','ok') as test_db_Host,
- if(isnull(test_host.Host),'WRONG!!!','ok') as test_host_Host,
- if(isnull(test_user.Host),'WRONG!!!','ok') as test_user_Host,
- if(isnull(test_tables_priv.Host),'WRONG!!!','ok') as test_tables_priv_Host,
- if(isnull(test_columns_priv.Host),'WRONG!!!','ok') as test_columns_priv_Host
- -from test_db
-left join test_host on test_db.Host=test_host.Host
-left join test_user on test_db.Host=test_user.Host
-left join test_tables_priv on test_db.Host=test_tables_priv.Host
-left join test_columns_priv on test_db.Host=test_columns_priv.Host;
-
-# 'Db' field must be the same for all the tables:
-
+ if(isnull(test_db.Db),'WRONG!!!','ok') as test_db_Db, + if(isnull(test_host.Db),'WRONG!!!','ok') as test_host_Db, + if(isnull(test_tables_priv.Db),'WRONG!!!','ok') as test_tables_priv_Db, + if(isnull(test_columns_priv.Db),'WRONG!!!','ok') as est_columns_priv_Db + +from test_db +left join test_host on test_db.Db=test_host.Db +left join test_tables_priv on test_db.Db=test_tables_priv.Db +left join test_columns_priv on test_db.Db=test_columns_priv.Db; + +# 'User' field must be the same for all the tables: + select - if(isnull(test_db.Db),'WRONG!!!','ok') as test_db_Db,
- if(isnull(test_host.Db),'WRONG!!!','ok') as test_host_Db,
- if(isnull(test_tables_priv.Db),'WRONG!!!','ok') as test_tables_priv_Db,
- if(isnull(test_columns_priv.Db),'WRONG!!!','ok') as est_columns_priv_Db
- -from test_db
-left join test_host on test_db.Db=test_host.Db
-left join test_tables_priv on test_db.Db=test_tables_priv.Db
-left join test_columns_priv on test_db.Db=test_columns_priv.Db;
-
-# 'User' field must be the same for all the tables:
-
-select
- if(isnull(test_db.User),'WRONG!!!','ok') as test_db_User,
- if(isnull(test_user.User),'WRONG!!!','ok') as test_user_User,
- if(isnull(test_tables_priv.User),'WRONG!!!','ok') as test_tables_priv_User,
- if(isnull(test_columns_priv.User),'WRONG!!!','ok') as test_columns_priv_User
- -from test_db
-left join test_user on test_db.User=test_user.User
-left join test_tables_priv on test_db.User=test_tables_priv.User
-left join test_columns_priv on test_db.User=test_columns_priv.User;
-
-# 'Table_name' field must be the same for all the tables:
-
-select
- if(isnull(test_tables_priv.User),'WRONG!!!','ok') as test_tables_priv_User,
- if(isnull(test_columns_priv.User),'WRONG!!!','ok') as test_columns_priv_User
-from test_tables_priv
-left join test_columns_priv on test_tables_priv.Table_name=test_columns_priv.Table_name;
-
-drop table test_columns_priv;
-drop table test_tables_priv;
-drop table test_func;
-drop table test_host;
-drop table test_user;
-drop table test_db;
+ if(isnull(test_db.User),'WRONG!!!','ok') as test_db_User, + if(isnull(test_user.User),'WRONG!!!','ok') as test_user_User, + if(isnull(test_tables_priv.User),'WRONG!!!','ok') as test_tables_priv_User, + if(isnull(test_columns_priv.User),'WRONG!!!','ok') as test_columns_priv_User + +from test_db +left join test_user on test_db.User=test_user.User +left join test_tables_priv on test_db.User=test_tables_priv.User +left join test_columns_priv on test_db.User=test_columns_priv.User; + +# 'Table_name' field must be the same for all the tables: + +select + if(isnull(test_tables_priv.User),'WRONG!!!','ok') as test_tables_priv_User, + if(isnull(test_columns_priv.User),'WRONG!!!','ok') as test_columns_priv_User +from test_tables_priv +left join test_columns_priv on test_tables_priv.Table_name=test_columns_priv.Table_name; + +drop table test_columns_priv; +drop table test_tables_priv; +drop table test_func; +drop table test_host; +drop table test_user; +drop table test_db; diff --git a/mysql-test/t/truncate.test b/mysql-test/t/truncate.test index 3acab9f56de..f92e92fbc97 100644 --- a/mysql-test/t/truncate.test +++ b/mysql-test/t/truncate.test @@ -23,7 +23,7 @@ drop table t1; truncate non_existing_table; # -# test autoincrement with TRUNCATE +# test autoincrement with TRUNCATE; verifying difference with DELETE # create table t1 (a integer auto_increment primary key); @@ -31,5 +31,19 @@ insert into t1 (a) values (NULL),(NULL); truncate table t1; insert into t1 (a) values (NULL),(NULL); SELECT * from t1; +delete from t1; +insert into t1 (a) values (NULL),(NULL); +SELECT * from t1; drop table t1; +# Verifying that temp tables are handled the same way + +create temporary table t1 (a integer auto_increment primary key); +insert into t1 (a) values (NULL),(NULL); +truncate table t1; +insert into t1 (a) values (NULL),(NULL); +SELECT * from t1; +delete from t1; +insert into t1 (a) values (NULL),(NULL); +SELECT * from t1; +drop table t1; diff --git a/mysql-test/t/type_date.test b/mysql-test/t/type_date.test index fe706e9bf57..0f949e3a10a 100644 --- a/mysql-test/t/type_date.test +++ b/mysql-test/t/type_date.test @@ -84,3 +84,22 @@ CREATE TABLE t1 (f1 time default NULL, f2 time default NULL) TYPE=MyISAM; INSERT INTO t1 (f1, f2) VALUES ('09:00', '12:00'); SELECT DATE_FORMAT(f1, "%l.%i %p") , DATE_FORMAT(f2, "%l.%i %p") FROM t1; DROP TABLE t1; + +# +# Bug 4937: different date -> string conversion when using SELECT ... UNION +# and INSERT ... SELECT ... UNION +# + +CREATE TABLE t1 (f1 DATE); +CREATE TABLE t2 (f2 VARCHAR(8)); +CREATE TABLE t3 (f2 CHAR(8)); + +INSERT INTO t1 VALUES ('1978-11-26'); +INSERT INTO t2 SELECT f1+0 FROM t1; +INSERT INTO t2 SELECT f1+0 FROM t1 UNION SELECT f1+0 FROM t1; +INSERT INTO t3 SELECT f1+0 FROM t1; +INSERT INTO t3 SELECT f1+0 FROM t1 UNION SELECT f1+0 FROM t1; +SELECT * FROM t2; +SELECT * FROM t3; + +DROP TABLE t1, t2, t3; diff --git a/mysql-test/t/type_float.test b/mysql-test/t/type_float.test index 65d594387b9..084d4b815e5 100644 --- a/mysql-test/t/type_float.test +++ b/mysql-test/t/type_float.test @@ -28,10 +28,14 @@ select a from t1 order by a; select min(a) from t1; drop table t1; +# +# BUG#3612, BUG#4393, BUG#4356, BUG#4394 +# + create table t1 (c1 double, c2 varchar(20)); insert t1 values (121,"16"); select c1 + c1 * (c2 / 100) as col from t1; -create table t2 select c1 + c1 * (c2 / 100) as col from t1; +create table t2 select c1 + c1 * (c2 / 100) as col1, round(c1, 5) as col2, round(c1, 35) as col3, sqrt(c1*1e-15) col4 from t1; select * from t2; show create table t2; drop table t1,t2; @@ -50,8 +54,16 @@ select a from t1 order by a; select min(a) from t1; drop table t1; +# +# float in a char(1) field +# +create table t1 (c20 char); +insert into t1 (c20) values (5000.0); +drop table t1; + # Errors -!$1063 create table t1 (f float(54)); # Should give an error +--error 1063 +create table t1 (f float(54)); # Should give an error drop table if exists t1; diff --git a/mysql-test/t/type_timestamp.test b/mysql-test/t/type_timestamp.test index 3483227376e..92bd20e846e 100644 --- a/mysql-test/t/type_timestamp.test +++ b/mysql-test/t/type_timestamp.test @@ -105,3 +105,14 @@ insert into t1 values (); insert into t1 values (DEFAULT, DEFAULT); select * from t1; drop table t1; + +# +# Test for bug #4491, TIMESTAMP(19) should be possible to create and not +# only read in 4.0 +# +create table t1 (ts timestamp(19)); +show create table t1; +set TIMESTAMP=1000000000; +insert into t1 values (); +select * from t1; +drop table t1; diff --git a/mysql-test/t/type_uint.test b/mysql-test/t/type_uint.test index 32bcd61ecdb..7eb48ae21ac 100644 --- a/mysql-test/t/type_uint.test +++ b/mysql-test/t/type_uint.test @@ -6,5 +6,6 @@ drop table if exists t1; create table t1 (this int unsigned); insert into t1 values (1); insert into t1 values (-1); +insert into t1 values ('5000000000'); select * from t1; drop table t1; diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index b9aa52ec627..03e4778d9d6 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -276,3 +276,13 @@ select @@session.key_buffer_size; set global myisam_max_sort_file_size=4294967296; --replace_result 4294967296 MAX_FILE_SIZE 2146435072 MAX_FILE_SIZE show global variables like 'myisam_max_sort_file_size'; + +# BUG#5135: cannot turn on log_warnings with SET in 4.1 (and 4.0) +set @tstlw = @@log_warnings; +show global variables like 'log_warnings'; +set global log_warnings = 0; +show global variables like 'log_warnings'; +set global log_warnings = 42; +show global variables like 'log_warnings'; +set global log_warnings = @tstlw; +show global variables like 'log_warnings'; diff --git a/mysys/mf_tempfile.c b/mysys/mf_tempfile.c index ea2bec076d4..ca9912d9210 100644 --- a/mysys/mf_tempfile.c +++ b/mysys/mf_tempfile.c @@ -98,7 +98,7 @@ File create_temp_file(char *to, const char *dir, const char *prefix, if (strlen(dir)+ pfx_len > FN_REFLEN-2) { errno=my_errno= ENAMETOOLONG; - return 1; + DBUG_RETURN(file); } strmov(convert_dirname(to,dir,NullS),prefix_buff); org_file=mkstemp(to); @@ -124,7 +124,7 @@ File create_temp_file(char *to, const char *dir, const char *prefix, #ifdef OS2 /* changing environ variable doesn't work with VACPP */ char buffer[256], *end; - buffer[sizeof[buffer)-1]= 0; + buffer[sizeof(buffer)-1]= 0; end= strxnmov(buffer, sizeof(buffer)-1, (char*) "TMP=", dir, NullS); /* remove ending backslash */ if (end[-1] == '\\') diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index 694c4685667..71f8819756a 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -17,10 +17,13 @@ #include <my_global.h> #include <m_string.h> #include <stdlib.h> -#include <my_getopt.h> #include <assert.h> #include <my_sys.h> #include <mysys_err.h> +#include <my_getopt.h> + +static void default_reporter(enum loglevel level, const char *format, ...); +my_error_reporter my_getopt_error_reporter= &default_reporter; static int findopt(char *optpat, uint length, const struct my_option **opt_res, @@ -56,6 +59,14 @@ char *disabled_my_option= (char*) "0"; my_bool my_getopt_print_errors= 1; +static void default_reporter(enum loglevel level __attribute__((unused)), + const char *format, ...) +{ + va_list args; + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); +} /* function: handle_options @@ -68,10 +79,8 @@ my_bool my_getopt_print_errors= 1; */ int handle_options(int *argc, char ***argv, - const struct my_option *longopts, - my_bool (*get_one_option)(int, - const struct my_option *, - char *)) + const struct my_option *longopts, + my_get_one_option get_one_option) { uint opt_found, argvpos= 0, length, i; my_bool end_of_options= 0, must_be_var, set_maximum_value, special_used, @@ -109,8 +118,9 @@ int handle_options(int *argc, char ***argv, if (!*++pos) { if (my_getopt_print_errors) - fprintf(stderr, "%s: Option '-O' requires an argument\n", - progname); + my_getopt_error_reporter(ERROR_LEVEL, + "%s: Option '-O' requires an argument\n", + progname); return EXIT_ARGUMENT_REQUIRED; } cur_arg= *pos; @@ -126,9 +136,9 @@ int handle_options(int *argc, char ***argv, if (!*cur_arg) { if (my_getopt_print_errors) - fprintf(stderr, - "%s: Option '--set-variable' requires an argument\n", - progname); + my_getopt_error_reporter(ERROR_LEVEL, + "%s: Option '--set-variable' requires an argument\n", + progname); return EXIT_ARGUMENT_REQUIRED; } } @@ -140,9 +150,9 @@ int handle_options(int *argc, char ***argv, if (!*++pos) { if (my_getopt_print_errors) - fprintf(stderr, - "%s: Option '--set-variable' requires an argument\n", - progname); + my_getopt_error_reporter(ERROR_LEVEL, + "%s: Option '--set-variable' requires an argument\n", + progname); return EXIT_ARGUMENT_REQUIRED; } cur_arg= *pos; @@ -201,10 +211,11 @@ int handle_options(int *argc, char ***argv, if (opt_found > 1) { if (my_getopt_print_errors) - fprintf(stderr, - "%s: ambiguous option '--%s-%s' (--%s-%s)\n", - progname, special_opt_prefix[i], cur_arg, - special_opt_prefix[i], prev_found); + my_getopt_error_reporter(ERROR_LEVEL, + "%s: ambiguous option '--%s-%s' (--%s-%s)\n", + progname, special_opt_prefix[i], + cur_arg, special_opt_prefix[i], + prev_found); return EXIT_AMBIGUOUS_OPTION; } switch (i) { @@ -236,18 +247,20 @@ int handle_options(int *argc, char ***argv, if (must_be_var) { if (my_getopt_print_errors) - fprintf(stderr, - "%s: %s: unknown variable '%s'\n", progname, - option_is_loose ? "WARNING" : "ERROR", cur_arg); + my_getopt_error_reporter(option_is_loose ? + WARNING_LEVEL : ERROR_LEVEL, + "%s: unknown variable '%s'\n", + progname, cur_arg); if (!option_is_loose) return EXIT_UNKNOWN_VARIABLE; } else { if (my_getopt_print_errors) - fprintf(stderr, - "%s: %s: unknown option '--%s'\n", progname, - option_is_loose ? "WARNING" : "ERROR", cur_arg); + my_getopt_error_reporter(option_is_loose ? + WARNING_LEVEL : ERROR_LEVEL, + "%s: unknown option '--%s'\n", + progname, cur_arg); if (!option_is_loose) return EXIT_UNKNOWN_OPTION; } @@ -263,23 +276,27 @@ int handle_options(int *argc, char ***argv, if (must_be_var) { if (my_getopt_print_errors) - fprintf(stderr, "%s: variable prefix '%s' is not unique\n", - progname, cur_arg); + my_getopt_error_reporter(ERROR_LEVEL, + "%s: variable prefix '%s' is not unique\n", + progname, cur_arg); return EXIT_VAR_PREFIX_NOT_UNIQUE; } else { if (my_getopt_print_errors) - fprintf(stderr, "%s: ambiguous option '--%s' (%s, %s)\n", - progname, cur_arg, prev_found, optp->name); + my_getopt_error_reporter(ERROR_LEVEL, + "%s: ambiguous option '--%s' (%s, %s)\n", + progname, cur_arg, prev_found, + optp->name); return EXIT_AMBIGUOUS_OPTION; } } if (must_be_var && optp->var_type == GET_NO_ARG) { if (my_getopt_print_errors) - fprintf(stderr, "%s: option '%s' cannot take an argument\n", - progname, optp->name); + my_getopt_error_reporter(ERROR_LEVEL, + "%s: option '%s' cannot take an argument\n", + progname, optp->name); return EXIT_NO_ARGUMENT_ALLOWED; } if (optp->arg_type == NO_ARG) @@ -287,8 +304,9 @@ int handle_options(int *argc, char ***argv, if (optend && optp->var_type != GET_BOOL) { if (my_getopt_print_errors) - fprintf(stderr, "%s: option '--%s' cannot take an argument\n", - progname, optp->name); + my_getopt_error_reporter(ERROR_LEVEL, + "%s: option '--%s' cannot take an argument\n", + progname, optp->name); return EXIT_NO_ARGUMENT_ALLOWED; } if (optp->var_type == GET_BOOL) @@ -325,8 +343,9 @@ int handle_options(int *argc, char ***argv, if (!*++pos) { if (my_getopt_print_errors) - fprintf(stderr, "%s: option '--%s' requires an argument\n", - progname, optp->name); + my_getopt_error_reporter(ERROR_LEVEL, + "%s: option '--%s' requires an argument\n", + progname, optp->name); return EXIT_ARGUMENT_REQUIRED; } argument= *pos; @@ -375,9 +394,9 @@ int handle_options(int *argc, char ***argv, if (!pos[1]) { if (my_getopt_print_errors) - fprintf(stderr, - "%s: option '-%c' requires an argument\n", - progname, optp->id); + my_getopt_error_reporter(ERROR_LEVEL, + "%s: option '-%c' requires an argument\n", + progname, optp->id); return EXIT_ARGUMENT_REQUIRED; } argument= *++pos; @@ -387,9 +406,9 @@ int handle_options(int *argc, char ***argv, } if ((error= setval(optp, argument, set_maximum_value))) { - fprintf(stderr, - "%s: Error while setting value '%s' to '%s'\n", - progname, argument, optp->name); + my_getopt_error_reporter(ERROR_LEVEL, + "%s: Error while setting value '%s' to '%s'\n", + progname, argument, optp->name); return error; } get_one_option(optp->id, optp, argument); @@ -399,8 +418,9 @@ int handle_options(int *argc, char ***argv, if (!opt_found) { if (my_getopt_print_errors) - fprintf(stderr, - "%s: unknown option '-%c'\n", progname, *optend); + my_getopt_error_reporter(ERROR_LEVEL, + "%s: unknown option '-%c'\n", + progname, *optend); return EXIT_UNKNOWN_OPTION; } } @@ -409,9 +429,9 @@ int handle_options(int *argc, char ***argv, } if ((error= setval(optp, argument, set_maximum_value))) { - fprintf(stderr, - "%s: Error while setting value '%s' to '%s'\n", - progname, argument, optp->name); + my_getopt_error_reporter(ERROR_LEVEL, + "%s: Error while setting value '%s' to '%s'\n", + progname, argument, optp->name); return error; } get_one_option(optp->id, optp, argument); diff --git a/mysys/my_lock.c b/mysys/my_lock.c index 5058c301adb..add274bdcec 100644 --- a/mysys/my_lock.c +++ b/mysys/my_lock.c @@ -117,10 +117,10 @@ int my_lock(File fd, int locktype, my_off_t start, my_off_t length, #if defined(HAVE_FCNTL) { struct flock lock; - lock.l_type= (short) locktype; - lock.l_whence=0L; - lock.l_start=(long) start; - lock.l_len=(long) length; + lock.l_type= (short) locktype; + lock.l_whence= SEEK_SET; + lock.l_start= (off_t) start; + lock.l_len= (off_t) length; if (MyFlags & MY_DONT_WAIT) { if (fcntl(fd,F_SETLK,&lock) != -1) /* Check if we can lock */ diff --git a/mysys/my_vsnprintf.c b/mysys/my_vsnprintf.c index e49b1d0e729..e7cc780060c 100644 --- a/mysys/my_vsnprintf.c +++ b/mysys/my_vsnprintf.c @@ -14,27 +14,30 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "mysys_priv.h" -#include "mysys_err.h" +#include <my_global.h> #include <m_string.h> #include <stdarg.h> #include <m_ctype.h> -#include <assert.h> -int my_snprintf(char* to, size_t n, const char* fmt, ...) -{ - int result; - va_list args; - va_start(args,fmt); - result= my_vsnprintf(to, n, fmt, args); - va_end(args); - return result; -} +/* + Limited snprintf() implementations + IMPLEMENTION: + Supports following formats: + %#[l]d + %#[l]u + %#[l]x + %#.#s Note first # is ignored + + RETURN + length of result string +*/ int my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap) { char *start=to, *end=to+n-1; + uint length, width, pre_zero, have_long; + for (; *fmt ; fmt++) { if (fmt[0] != '%') @@ -44,33 +47,77 @@ int my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap) *to++= *fmt; /* Copy ordinary char */ continue; } - /* Skip if max size is used (to be compatible with printf) */ - fmt++; - while (isdigit(*fmt) || *fmt == '.' || *fmt == '-') + fmt++; /* skip '%' */ + /* Read max fill size (only used with %d and %u) */ + if (*fmt == '-') fmt++; + length= width= pre_zero= have_long= 0; + for (;isdigit(*fmt); fmt++) + { + length=length*10+ (uint) (*fmt-'0'); + if (!length) + pre_zero= 1; /* first digit was 0 */ + } + if (*fmt == '.') + for (fmt++;isdigit(*fmt); fmt++) + width=width*10+ (uint) (*fmt-'0'); + else + width= ~0; if (*fmt == 'l') + { fmt++; + have_long= 1; + } if (*fmt == 's') /* String parameter */ { reg2 char *par = va_arg(ap, char *); - uint plen,left_len = (uint)(end-to); + uint plen,left_len = (uint)(end-to)+1; if (!par) par = (char*)"(null)"; plen = (uint) strlen(par); + set_if_smaller(plen,width); if (left_len <= plen) plen = left_len - 1; to=strnmov(to,par,plen); continue; } - else if (*fmt == 'd' || *fmt == 'u') /* Integer parameter */ + else if (*fmt == 'd' || *fmt == 'u'|| *fmt== 'x') /* Integer parameter */ { - register int iarg; - if ((uint) (end-to) < 16) - break; - iarg = va_arg(ap, int); + register long larg; + uint res_length, to_length; + char *store_start= to, *store_end; + char buff[32]; + + if ((to_length= (uint) (end-to)) < 16 || length) + store_start= buff; + if (have_long) + larg = va_arg(ap, long); + else + if (*fmt == 'd') + larg = va_arg(ap, int); + else + larg= (long) (uint) va_arg(ap, int); if (*fmt == 'd') - to=int10_to_str((long) iarg,to, -10); + store_end= int10_to_str(larg, store_start, -10); else - to=int10_to_str((long) (uint) iarg,to,10); + if (*fmt== 'u') + store_end= int10_to_str(larg, store_start, 10); + else + store_end= int2str(larg, store_start, 16); + if ((res_length= (uint) (store_end - store_start)) > to_length) + break; /* num doesn't fit in output */ + /* If %#d syntax was used, we have to pre-zero/pre-space the string */ + if (store_start == buff) + { + length= min(length, to_length); + if (res_length < length) + { + uint diff= (length- res_length); + bfill(to, diff, pre_zero ? '0' : ' '); + to+= diff; + } + bmove(to, store_start, res_length); + } + to+= res_length; continue; } /* We come here on '%%', unknown code or too long parameter */ @@ -78,11 +125,19 @@ int my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap) break; *to++='%'; /* % used as % or unknown code */ } - DBUG_ASSERT(to <= end); *to='\0'; /* End of errmessage */ return (uint) (to - start); } +int my_snprintf(char* to, size_t n, const char* fmt, ...) +{ + int result; + va_list args; + va_start(args,fmt); + result= my_vsnprintf(to, n, fmt, args); + va_end(args); + return result; +} #ifdef MAIN #define OVERRUN_SENTRY 250 @@ -96,7 +151,7 @@ static void my_printf(const char * fmt, ...) n = my_vsnprintf(buf, sizeof(buf)-1,fmt, ar); printf(buf); printf("n=%d, strlen=%d\n", n, strlen(buf)); - if (buf[sizeof(buf)-1] != OVERRUN_SENTRY) + if ((uchar) buf[sizeof(buf)-1] != OVERRUN_SENTRY) { fprintf(stderr, "Buffer overrun\n"); abort(); @@ -117,6 +172,7 @@ int main() my_printf("Hello '%s' hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh\n", "hack"); my_printf("Hello hhhhhhhhhhhhhh %d sssssssssssssss\n", 1); my_printf("Hello %u\n", 1); + my_printf("Hex: %lx '%6lx'\n", 32, 65); my_printf("conn %ld to: '%-.64s' user: '%-.32s' host:\ `%-.64s' (%-.64s)", 1, 0,0,0,0); return 0; diff --git a/mytest-old.c b/mytest-old.c deleted file mode 100644 index 8b4029f5e1e..00000000000 --- a/mytest-old.c +++ /dev/null @@ -1,169 +0,0 @@ -/*C4*/ -/****************************************************************/ -/* Author: Jethro Wright, III TS : 3/ 4/1998 9:15 */ -/* Date: 02/18/1998 */ -/* mytest.c : do some testing of the libmySQL.DLL.... */ -/* */ -/* History: */ -/* 02/18/1998 jw3 also sprach zarathustra.... */ -/****************************************************************/ - - -#include <windows.h> -#include <stdio.h> -#include <string.h> - -#include <mysql.h> - -#define DEFALT_SQL_STMT "SELECT * FROM db" -#ifndef offsetof -#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) -#endif - - -/******************************************************** -** -** main :- -** -********************************************************/ - -int -main( int argc, char * argv[] ) -{ - - char szSQL[ 200 ], aszFlds[ 25 ][ 25 ], * pszT, szDB[ 50 ] ; - int i, j, k, l, x ; - MYSQL * myData ; - MYSQL_RES * res ; - MYSQL_FIELD * fd ; - MYSQL_ROW row ; - - //....just curious.... - printf( "sizeof( MYSQL ) == %d\n", sizeof( MYSQL ) ) ; - if ( argc == 2 ) - { - strcpy( szDB, argv[ 1 ] ) ; - strcpy( szSQL, DEFALT_SQL_STMT ) ; - if (!strcmp(szDB,"--debug")) - { - strcpy( szDB, "mysql" ) ; - printf("Some mysql struct information (size and offset):\n"); - printf("net:\t%3d %3d\n",sizeof(myData->net),offsetof(MYSQL,net)); - printf("host:\t%3d %3d\n",sizeof(myData->host),offsetof(MYSQL,host)); - printf("port:\t%3d %3d\n",sizeof(myData->port),offsetof(MYSQL,port)); - printf("protocol_version:\t%3d %3d\n",sizeof(myData->protocol_version), - offsetof(MYSQL,protocol_version)); - printf("thread_id:\t%3d %3d\n",sizeof(myData->thread_id), - offsetof(MYSQL,thread_id)); - printf("affected_rows:\t%3d %3d\n",sizeof(myData->affected_rows), - offsetof(MYSQL,affected_rows)); - printf("packet_length:\t%3d %3d\n",sizeof(myData->packet_length), - offsetof(MYSQL,packet_length)); - printf("status:\t%3d %3d\n",sizeof(myData->status), - offsetof(MYSQL,status)); - printf("fields:\t%3d %3d\n",sizeof(myData->fields), - offsetof(MYSQL,fields)); - printf("field_alloc:\t%3d %3d\n",sizeof(myData->field_alloc), - offsetof(MYSQL,field_alloc)); - printf("free_me:\t%3d %3d\n",sizeof(myData->free_me), - offsetof(MYSQL,free_me)); - printf("options:\t%3d %3d\n",sizeof(myData->options), - offsetof(MYSQL,options)); - puts(""); - } - } - else if ( argc > 2 ) { - strcpy( szDB, argv[ 1 ] ) ; - strcpy( szSQL, argv[ 2 ] ) ; - } - else { - strcpy( szDB, "mysql" ) ; - strcpy( szSQL, DEFALT_SQL_STMT ) ; - } - //.... - - if ( (myData = mysql_init((MYSQL*) 0)) && - mysql_real_connect( myData, NULL, NULL, NULL, NULL, MYSQL_PORT, - NULL, 0 ) ) - { - if ( mysql_select_db( myData, szDB ) < 0 ) { - printf( "Can't select the %s database !\n", szDB ) ; - mysql_close( myData ) ; - return 2 ; - } - } - else { - printf( "Can't connect to the mysql server on port %d !\n", - MYSQL_PORT ) ; - mysql_close( myData ) ; - return 1 ; - } - //.... - if ( ! mysql_query( myData, szSQL ) ) { - res = mysql_store_result( myData ) ; - i = (int) mysql_num_rows( res ) ; l = 1 ; - printf( "Query: %s\nNumber of records found: %ld\n", szSQL, i ) ; - //....we can get the field-specific characteristics here.... - for ( x = 0 ; fd = mysql_fetch_field( res ) ; x++ ) - strcpy( aszFlds[ x ], fd->name ) ; - //.... - while ( row = mysql_fetch_row( res ) ) { - j = mysql_num_fields( res ) ; - printf( "Record #%ld:-\n", l++ ) ; - for ( k = 0 ; k < j ; k++ ) - printf( " Fld #%d (%s): %s\n", k + 1, aszFlds[ k ], - (((row[k]==NULL)||(!strlen(row[k])))?"NULL":row[k])) ; - puts( "==============================\n" ) ; - } - mysql_free_result( res ) ; - } - else printf( "Couldn't execute %s on the server !\n", szSQL ) ; - //.... - puts( "==== Diagnostic info ====" ) ; - pszT = mysql_get_client_info() ; - printf( "Client info: %s\n", pszT ) ; - //.... - pszT = mysql_get_host_info( myData ) ; - printf( "Host info: %s\n", pszT ) ; - //.... - pszT = mysql_get_server_info( myData ) ; - printf( "Server info: %s\n", pszT ) ; - //.... - res = mysql_list_processes( myData ) ; l = 1 ; - if (res) - { - for ( x = 0 ; fd = mysql_fetch_field( res ) ; x++ ) - strcpy( aszFlds[ x ], fd->name ) ; - while ( row = mysql_fetch_row( res ) ) { - j = mysql_num_fields( res ) ; - printf( "Process #%ld:-\n", l++ ) ; - for ( k = 0 ; k < j ; k++ ) - printf( " Fld #%d (%s): %s\n", k + 1, aszFlds[ k ], - (((row[k]==NULL)||(!strlen(row[k])))?"NULL":row[k])) ; - puts( "==============================\n" ) ; - } - } - else - { - printf("Got error %s when retreiving processlist\n",mysql_error(myData)); - } - //.... - res = mysql_list_tables( myData, "%" ) ; l = 1 ; - for ( x = 0 ; fd = mysql_fetch_field( res ) ; x++ ) - strcpy( aszFlds[ x ], fd->name ) ; - while ( row = mysql_fetch_row( res ) ) { - j = mysql_num_fields( res ) ; - printf( "Table #%ld:-\n", l++ ) ; - for ( k = 0 ; k < j ; k++ ) - printf( " Fld #%d (%s): %s\n", k + 1, aszFlds[ k ], - (((row[k]==NULL)||(!strlen(row[k])))?"NULL":row[k])) ; - puts( "==============================\n" ) ; - } - //.... - pszT = mysql_stat( myData ) ; - puts( pszT ) ; - //.... - mysql_close( myData ) ; - return 0 ; - -} diff --git a/netware/mysql_test_run.c b/netware/mysql_test_run.c index 5e5f49da73f..0b86e67fc68 100644 --- a/netware/mysql_test_run.c +++ b/netware/mysql_test_run.c @@ -143,7 +143,7 @@ int read_option(char *, char *); void run_test(char *); void setup(char *); void vlog(char *, va_list); -void log(char *, ...); +void mtr_log(char *, ...); void log_info(char *, ...); void log_error(char *, ...); void log_errno(char *, ...); @@ -160,21 +160,21 @@ void report_stats() { if (total_fail == 0) { - log("\nAll %d test(s) were successful.\n", total_test); + mtr_log("\nAll %d test(s) were successful.\n", total_test); } else { double percent = ((double)total_pass / total_test) * 100; - log("\nFailed %u/%u test(s), %.02f%% successful.\n", + mtr_log("\nFailed %u/%u test(s), %.02f%% successful.\n", total_fail, total_test, percent); - log("\nThe .out and .err files in %s may give you some\n", result_dir); - log("hint of what when wrong.\n"); - log("\nIf you want to report this error, please first read the documentation\n"); - log("at: http://www.mysql.com/doc/M/y/MySQL_test_suite.html\n"); + mtr_log("\nThe .out and .err files in %s may give you some\n", result_dir); + mtr_log("hint of what when wrong.\n"); + mtr_log("\nIf you want to report this error, please first read the documentation\n"); + mtr_log("at: http://www.mysql.com/doc/M/y/MySQL_test_suite.html\n"); } - log("\n%.02f total minutes elapsed in the test cases\n\n", total_time / 60); + mtr_log("\n%.02f total minutes elapsed in the test cases\n\n", total_time / 60); } /****************************************************************************** @@ -794,7 +794,7 @@ void run_test(char *test) if(ignore) { // show test - log("%-46s ", test); + mtr_log("%-46s ", test); // ignore rstr = TEST_IGNORE; @@ -876,7 +876,7 @@ void run_test(char *test) sleep(1); // show test - log("%-46s ", test); + mtr_log("%-46s ", test); // args init_args(&al); @@ -948,7 +948,7 @@ void run_test(char *test) else // early skips { // show test - log("%-46s ", test); + mtr_log("%-46s ", test); // skip rstr = TEST_SKIP; @@ -956,7 +956,7 @@ void run_test(char *test) } // result - log("%10.06f %-14s\n", elapsed, rstr); + mtr_log("%10.06f %-14s\n", elapsed, rstr); } /****************************************************************************** @@ -985,7 +985,7 @@ void vlog(char *format, va_list ap) Log the message. ******************************************************************************/ -void log(char *format, ...) +void mtr_log(char *format, ...) { va_list ap; @@ -1009,9 +1009,9 @@ void log_info(char *format, ...) va_start(ap, format); - log("-- INFO : "); + mtr_log("-- INFO : "); vlog(format, ap); - log("\n"); + mtr_log("\n"); va_end(ap); } @@ -1029,9 +1029,9 @@ void log_error(char *format, ...) va_start(ap, format); - log("-- ERROR: "); + mtr_log("-- ERROR: "); vlog(format, ap); - log("\n"); + mtr_log("\n"); va_end(ap); } @@ -1049,9 +1049,9 @@ void log_errno(char *format, ...) va_start(ap, format); - log("-- ERROR: (%003u) ", errno); + mtr_log("-- ERROR: (%003u) ", errno); vlog(format, ap); - log("\n"); + mtr_log("\n"); va_end(ap); } @@ -1184,18 +1184,18 @@ int main(int argc, char **argv) is_ignore_list = 1; } // header - log("MySQL Server %s, for %s (%s)\n\n", VERSION, SYSTEM_TYPE, MACHINE_TYPE); + mtr_log("MySQL Server %s, for %s (%s)\n\n", VERSION, SYSTEM_TYPE, MACHINE_TYPE); - log("Initializing Tests...\n"); + mtr_log("Initializing Tests...\n"); // install test databases mysql_install_db(); - log("Starting Tests...\n"); + mtr_log("Starting Tests...\n"); - log("\n"); - log(HEADER); - log(DASH); + mtr_log("\n"); + mtr_log(HEADER); + mtr_log(DASH); if ( argc > 1 + is_ignore_list ) { @@ -1250,10 +1250,10 @@ int main(int argc, char **argv) // stop server mysql_stop(); - log(DASH); - log("\n"); + mtr_log(DASH); + mtr_log("\n"); - log("Ending Tests...\n"); + mtr_log("Ending Tests...\n"); // report stats report_stats(); diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh index ea64f5ccfbd..8ea9a16f56b 100644 --- a/scripts/make_binary_distribution.sh +++ b/scripts/make_binary_distribution.sh @@ -86,7 +86,7 @@ do done for i in COPYING COPYING.LIB README Docs/INSTALL-BINARY \ - MySQLEULA.txt LICENSE.doc README.NW + EXCEPTIONS-CLIENT MySQLEULA.txt LICENSE.doc README.NW do if [ -f $i ] then diff --git a/scripts/make_sharedlib_distribution.sh b/scripts/make_sharedlib_distribution.sh index 4104a315296..fbc945e445a 100644 --- a/scripts/make_sharedlib_distribution.sh +++ b/scripts/make_sharedlib_distribution.sh @@ -45,8 +45,10 @@ fi mkdir -p $BASE/lib for i in \ - libmysql/.libs/libmysqlclient.so* \ - libmysql_r/.libs/libmysqlclient_r.so* + libmysql/.libs/libmysqlclient.s{l,o}* \ + libmysql/.libs/libmysqlclient*.dylib \ + libmysql_r/.libs/libmysqlclient_r.s{l,o}* \ + libmysql_r/.libs/libmysqlclient_r*.dylib do if [ -f $i ] then diff --git a/scripts/make_win_binary_distribution.sh b/scripts/make_win_binary_distribution.sh index e5893c1eb1e..9b2cc2d7d22 100644 --- a/scripts/make_win_binary_distribution.sh +++ b/scripts/make_win_binary_distribution.sh @@ -110,6 +110,9 @@ print_debug "Copying sql-bench to $DIRNAME/bench" mkdir $DIRNAME/bench cp -fr sql-bench/* $DIRNAME/bench +print_debug "Copying support-files to $DIRNAME" +cp support-files/* $DIRNAME + # Files for bin for i in client_release/* client_debug/mysqld.exe lib_release/libmySQL.dll do @@ -124,7 +127,7 @@ do cp $i $DIRNAME/include done -# Windows users are used to having dbug.h +# Windows users are used to having dbug.h ? cp include/my_dbug.h $DIRNAME/include/dbug.h # Libraries found in lib_release and lib_debug diff --git a/scripts/make_win_src_distribution.sh b/scripts/make_win_src_distribution.sh index 54c25b49035..9aca62527e6 100755..100644 --- a/scripts/make_win_src_distribution.sh +++ b/scripts/make_win_src_distribution.sh @@ -178,18 +178,8 @@ rm -r -f "$BASE/share/Makefile" rm -r -f "$BASE/share/Makefile.in" rm -r -f "$BASE/share/Makefile.am" -# -# Clean up if we did this from a bk tree -# - -if [ -d $BASE/SCCS ] -then - find $BASE/ -type d -name SCCS -printf " \"%p\"" | xargs rm -r -f -fi - mkdir $BASE/Docs $BASE/extra $BASE/include - # # Copy directory files # @@ -282,12 +272,12 @@ touch $BASE/innobase/ib_config.h # cd $SOURCE -for i in COPYING ChangeLog README \ +for i in COPYING ChangeLog README EXCEPTIONS-CLIENT\ INSTALL-SOURCE INSTALL-WIN \ INSTALL-WIN-SOURCE \ Docs/manual_toc.html Docs/manual.html \ Docs/manual.txt Docs/mysqld_error.txt \ - Docs/INSTALL-BINARY + Docs/INSTALL-BINARY Docs/internals.texi do print_debug "Copying file '$i'" @@ -298,6 +288,12 @@ do done # +# support files +# +mkdir $BASE/support-files +cp support-files/*.cnf $BASE/support-files + +# # Raw dirs from source tree # @@ -312,7 +308,7 @@ do done # -# Fix some windows files +# Fix some windows files to avoid compiler warnings # ./extra/replace std:: "" -- $BASE/sql/sql_yacc.cpp @@ -321,6 +317,15 @@ unix_to_dos $BASE/README mv $BASE/README $BASE/README.txt # +# Clean up if we did this from a bk tree +# + +if [ -d $BASE/SSL/SCCS ] +then + find $BASE/ -type d -name SCCS -printf " \"%p\"" | xargs rm -r -f +fi + +# # Initialize the initial data directory # diff --git a/scripts/mysql_fix_privilege_tables.sql b/scripts/mysql_fix_privilege_tables.sql index bfff05151e5..6e1fd0d1be5 100644 --- a/scripts/mysql_fix_privilege_tables.sql +++ b/scripts/mysql_fix_privilege_tables.sql @@ -9,6 +9,8 @@ -- this sql script. -- On windows you should do 'mysql --force mysql < mysql_fix_privilege_tables.sql' +SET SQL_SAFE_UPDATES=0; + USE mysql; ALTER TABLE user type=MyISAM; ALTER TABLE db type=MyISAM; diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index 7ab312baa5c..f9f3160d220 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -143,7 +143,7 @@ then resolved=`$bindir/resolveip localhost 2>&1` if [ $? -ne 0 ] then - echo "Neither host '$hostname' and 'localhost' could not be looked up with" + echo "Neither host '$hostname' nor 'localhost' could not be looked up with" echo "$bindir/resolveip" echo "Please configure the 'hostname' command to return a correct hostname." echo "If you want to solve this at a later stage, restart this script with" diff --git a/scripts/mysqlhotcopy.sh b/scripts/mysqlhotcopy.sh index 6388855eaa6..af4e6084c59 100644 --- a/scripts/mysqlhotcopy.sh +++ b/scripts/mysqlhotcopy.sh @@ -8,6 +8,7 @@ use File::Path; use DBI; use Sys::Hostname; use File::Copy; +use File::Temp; =head1 NAME @@ -626,7 +627,6 @@ sub copy_files { sub copy_index { my ($method, $files, $source, $target) = @_; - my $tmpfile="$opt_tmpdir/mysqlhotcopy$$"; print "Copying indices for ".@$files." files...\n" unless $opt{quiet}; foreach my $file (@$files) @@ -652,23 +652,23 @@ sub copy_index } close OUTPUT || die "Error on close of $to: $!\n"; } - elsif ($opt{method} eq 'scp') + elsif ($opt{method} =~ /^scp\b/) { - my $tmp=$tmpfile; - open(OUTPUT,">$tmp") || die "Can\'t create file $tmp: $!\n"; - if (syswrite(OUTPUT,$buff) != length($buff)) + my ($fh, $tmp)=tempfile('mysqlhotcopy-XXXXXX', DIR => $opt_tmpdir); + die "Can\'t create/open file in $opt_tmpdir\n"; + if (syswrite($fh,$buff) != length($buff)) { die "Error when writing data to $tmp: $!\n"; } - close OUTPUT || die "Error on close of $tmp: $!\n"; - safe_system("scp $tmp $to"); + close $fh || die "Error on close of $tmp: $!\n"; + safe_system("$opt{method} $tmp $to"); + unlink $tmp; } else { die "Can't use unsupported method '$opt{method}'\n"; } } - unlink "$tmpfile" if ($opt{method} eq 'scp'); } diff --git a/sql/Makefile.am b/sql/Makefile.am index f3751eabd25..0a664a120a5 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -125,8 +125,8 @@ sql_lex.o: lex_hash.h udf_example.so: udf_example.cc $(CXXCOMPILE) -shared -o $@ $< -#distclean: -# rm -f lex_hash.h +distclean: + rm -f lex_hash.h # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/sql/convert.cc b/sql/convert.cc index e4ae13d1e07..f84c80a6121 100644 --- a/sql/convert.cc +++ b/sql/convert.cc @@ -20,6 +20,9 @@ ** Some of the tables are hidden behind IFDEF to reduce some space. ** One can enable them by removing the // characters from the next comment ** One must also give a name to each mapping that one wants to use... +** +** All tables are activated if --with-extra-charsets=all or +** --with-extra-charsets=complex was given to configure. */ /* #define DEFINE_ALL_CHARACTER_SETS */ diff --git a/sql/field.cc b/sql/field.cc index e3bdf78e718..394d53238c2 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -37,6 +37,7 @@ #include "sql_select.h" #include <m_ctype.h> #include <errno.h> +#include <assert.h> #ifdef HAVE_FCONVERT #include <floatingpoint.h> #endif @@ -58,6 +59,8 @@ template class List_iterator<create_field>; uchar Field_null::null[1]={1}; const char field_separator=','; +#define DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE 320 + /***************************************************************************** Static help functions *****************************************************************************/ @@ -739,7 +742,7 @@ void Field_decimal::store(double nr) reg4 uint i,length; char fyllchar,*to; - char buff[320]; + char buff[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE]; fyllchar = zerofill ? (char) '0' : (char) ' '; #ifdef HAVE_SNPRINTF @@ -1504,7 +1507,7 @@ void Field_long::store(const char *from,uint len) { len--; from++; } - long tmp; + long tmp, cuted_fields=0; String tmp_str(from,len); from= tmp_str.c_ptr(); // Add end null if needed errno=0; @@ -1520,9 +1523,34 @@ void Field_long::store(const char *from,uint len) } else tmp=strtol(from, &end, 10); - if (errno || + if (errno || (from+len != end && current_thd->count_cuted_fields && !test_if_int(from,len))) + cuted_fields=1; +#if SIZEOF_LONG > 4 + if (unsigned_flag) + { + if (tmp > UINT_MAX32) + { + tmp= UINT_MAX32; + cuted_fields=1; + } + } + else + { + if (tmp > INT_MAX32) + { + tmp= INT_MAX32; + cuted_fields=1; + } + else if (tmp < INT_MIN32) + { + tmp= INT_MIN32; + cuted_fields=1; + } + } +#endif + if (cuted_fields) current_thd->cuted_fields++; #ifdef WORDS_BIGENDIAN if (table->db_low_byte_first) @@ -2301,7 +2329,7 @@ String *Field_double::val_str(String *val_buffer, #endif doubleget(nr,ptr); - uint to_length=max(field_length,320); + uint to_length=max(field_length, DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE); val_buffer->alloc(to_length); char *to=(char*) val_buffer->ptr(); @@ -2313,7 +2341,8 @@ String *Field_double::val_str(String *val_buffer, else { #ifdef HAVE_FCONVERT - char buff[320],*pos=buff; + char buff[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE]; + char *pos= buff; int decpt,sign,tmp_dec=dec; VOID(fconvert(nr,tmp_dec,&decpt,&sign,buff)); @@ -3669,13 +3698,58 @@ void Field_string::store(const char *from,uint length) } +/* + Store double value in Field_string or Field_varstring. + + SYNOPSIS + store_double_in_string_field() + field field to store value in + field_length number of characters in the field + nr number + + DESCRIPTION + Pretty prints double number into field_length characters buffer. +*/ + +static void store_double_in_string_field(Field_str *field, uint32 field_length, + double nr) +{ + bool use_scientific_notation=TRUE; + char buff[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE]; + uint length; + if (field_length < 32 && nr > 1) + { + if (field->ceiling == 0) + { + static double e[]= {1e1, 1e2, 1e4, 1e8, 1e16 }; + double p= 1; + for (int i= sizeof(e)/sizeof(e[0]), j= 1<<i ; j; i--, j>>= 1 ) + { + if (field_length & j) + p*= e[i]; + } + field->ceiling= p-1; + } + use_scientific_notation= (field->ceiling < nr); + } + length= (uint)sprintf(buff, "%-.*g", + use_scientific_notation ? max(0,(int)field_length-5) : field_length, + nr); + /* + +1 below is because "precision" in %g above means the + max. number of significant digits, not the output width. + Thus the width can be larger than number of significant digits by 1 + (for decimal point) + the test for field_length < 5 is for extreme cases, + like inserting 500.0 in char(1) + */ + DBUG_ASSERT(field_length < 5 || length <= field_length+1); + field->store(buff, min(length, field_length)); +} + void Field_string::store(double nr) { - char buff[MAX_FIELD_WIDTH],*end; - int width=min(field_length,DBL_DIG+5); - sprintf(buff,"%-*.*g",width,max(width-5,0),nr); - end=strcend(buff,' '); - Field_string::store(buff,(uint) (end - buff)); + store_double_in_string_field(this, field_length, nr); } @@ -3875,11 +3949,7 @@ void Field_varstring::store(const char *from,uint length) void Field_varstring::store(double nr) { - char buff[MAX_FIELD_WIDTH],*end; - int width=min(field_length,DBL_DIG+5); - sprintf(buff,"%-*.*g",width,max(width-5,0),nr); - end=strcend(buff,' '); - Field_varstring::store(buff,(uint) (end - buff)); + store_double_in_string_field(this, field_length, nr); } diff --git a/sql/field.h b/sql/field.h index d93ed1db9b5..d25ce8d4774 100644 --- a/sql/field.h +++ b/sql/field.h @@ -255,12 +255,13 @@ public: class Field_str :public Field { public: + double ceiling; // for ::store(double nr) Field_str(char *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, const char *field_name_arg, struct st_table *table_arg) :Field(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, - unireg_check_arg, field_name_arg, table_arg) + unireg_check_arg, field_name_arg, table_arg), ceiling(0.0) {} Item_result result_type () const { return STRING_RESULT; } uint decimals() const { return NOT_FIXED_DEC; } diff --git a/sql/gen_lex_hash.cc b/sql/gen_lex_hash.cc index 1f604659272..1e78aa35195 100644 --- a/sql/gen_lex_hash.cc +++ b/sql/gen_lex_hash.cc @@ -384,7 +384,7 @@ static int get_options(int argc, char **argv) { int ho_error; - if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option))) + if ((ho_error= handle_options(&argc, &argv, my_long_options, get_one_option))) exit(ho_error); if (argc >= 1) diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc index eb4bf517374..5aa42fa1beb 100644 --- a/sql/ha_heap.cc +++ b/sql/ha_heap.cc @@ -264,7 +264,8 @@ THR_LOCK_DATA **ha_heap::store_lock(THD *thd, int ha_heap::delete_table(const char *name) { - int error=heap_delete_table(name); + char buff[FN_REFLEN]; + int error= heap_delete_table(fn_format(buff,name,"","",4+2)); return error == ENOENT ? 0 : error; } diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index df193bde947..3d3aca9cfd5 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -31,6 +31,7 @@ have disables the InnoDB inlining in this file. */ #include <assert.h> #include <hash.h> #include <myisampack.h> +#include <mysys_err.h> #define MAX_ULONG_BIT ((ulong) 1 << (sizeof(ulong)*8-1)) @@ -103,6 +104,7 @@ uint innobase_flush_log_at_trx_commit = 1; my_bool innobase_log_archive = FALSE; my_bool innobase_use_native_aio = FALSE; my_bool innobase_fast_shutdown = TRUE; +my_bool innobase_create_status_file = FALSE; static char *internal_innobase_data_file_path = NULL; @@ -120,6 +122,10 @@ char innodb_dummy_stmt_trx_handle = 'D'; static HASH innobase_open_tables; +#ifdef __NETWARE__ /* some special cleanup for NetWare */ +bool nw_panic = FALSE; +#endif + static mysql_byte* innobase_get_key(INNOBASE_SHARE *share,uint *length, my_bool not_used __attribute__((unused))); static INNOBASE_SHARE *get_share(const char *table_name); @@ -406,6 +412,50 @@ innobase_mysql_print_thd( } /************************************************************************* +Creates a temporary file. */ +extern "C" +int +innobase_mysql_tmpfile(void) +/*========================*/ + /* out: temporary file descriptor, or < 0 on error */ +{ + char filename[FN_REFLEN]; + int fd2 = -1; + File fd = create_temp_file(filename, NullS, "ib", +#ifdef __WIN__ + O_BINARY | O_TRUNC | O_SEQUENTIAL | + O_TEMPORARY | O_SHORT_LIVED | +#endif /* __WIN__ */ + O_CREAT | O_EXCL | O_RDWR, + MYF(MY_WME)); + if (fd >= 0) { +#ifndef __WIN__ + /* On Windows, open files cannot be removed, but files can be + created with the O_TEMPORARY flag to the same effect + ("delete on close"). */ + unlink(filename); +#endif /* !__WIN__ */ + /* Copy the file descriptor, so that the additional resources + allocated by create_temp_file() can be freed by invoking + my_close(). + + Because the file descriptor returned by this function + will be passed to fdopen(), it will be closed by invoking + fclose(), which in turn will invoke close() instead of + my_close(). */ + fd2 = dup(fd); + if (fd2 < 0) { + DBUG_PRINT("error",("Got error %d on dup",fd2)); + my_errno=errno; + my_error(EE_OUT_OF_FILERESOURCES, + MYF(ME_BELL+ME_WAITTANG), filename, my_errno); + } + my_close(fd, MYF(MY_WME)); + } + return(fd2); +} + +/************************************************************************* Gets the InnoDB transaction handle for a MySQL handler object, creates an InnoDB transaction struct if the corresponding MySQL thread struct still lacks one. */ @@ -861,6 +911,7 @@ innobase_init(void) srv_force_recovery = (ulint) innobase_force_recovery; srv_fast_shutdown = (ibool) innobase_fast_shutdown; + srv_innodb_status = (ibool) innobase_create_status_file; srv_print_verbose_log = mysql_embedded ? 0 : 1; @@ -924,6 +975,11 @@ innobase_end(void) DBUG_ENTER("innobase_end"); +#ifdef __NETWARE__ /* some special cleanup for NetWare */ + if (nw_panic) { + set_panic_flag_for_netware(); + } +#endif err = innobase_shutdown_for_mysql(); hash_free(&innobase_open_tables); my_free(internal_innobase_data_file_path,MYF(MY_ALLOW_ZERO_PTR)); @@ -4270,7 +4326,7 @@ ha_innobase::update_table_comment( trx_search_latch_release_if_reserved(prebuilt->trx); str = NULL; - if (FILE* file = tmpfile()) { + if (FILE* file = os_file_create_tmpfile()) { long flen; /* output the data to a temporary file */ @@ -4330,7 +4386,7 @@ ha_innobase::get_foreign_key_create_info(void) update_thd(current_thd); - if (FILE* file = tmpfile()) { + if (FILE* file = os_file_create_tmpfile()) { long flen; prebuilt->trx->op_info = (char*)"getting info on foreign keys"; @@ -4656,8 +4712,8 @@ ha_innobase::external_lock( trx->n_mysql_tables_in_use--; prebuilt->mysql_has_locked = FALSE; auto_inc_counter_for_this_stat = 0; - if (trx->n_tables_locked) { - row_unlock_table_for_mysql(trx); + if (trx->n_lock_table_exp) { + row_unlock_tables_for_mysql(trx); } /* If the MySQL lock count drops to zero we know that the current SQL diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h index 384b3dec949..5736f70c65c 100644 --- a/sql/ha_innodb.h +++ b/sql/ha_innodb.h @@ -203,7 +203,8 @@ extern char *innobase_log_group_home_dir, *innobase_log_arch_dir; extern char *innobase_unix_file_flush_method; /* The following variables have to be my_bool for SHOW VARIABLES to work */ extern my_bool innobase_log_archive, - innobase_use_native_aio, innobase_fast_shutdown; + innobase_use_native_aio, innobase_fast_shutdown, + innobase_create_status_file; extern "C" { extern ulong srv_max_buf_pool_modified_pct; } diff --git a/sql/handler.cc b/sql/handler.cc index a1e738583fd..9eb129fab45 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -342,17 +342,30 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans) #ifdef USING_TRANSACTIONS if (opt_using_transactions) { - bool operation_done= 0; + bool operation_done= 0, need_start_waiters= 0; bool transaction_commited= 0; - - /* Update the binary log if we have cached some queries */ - if (trans == &thd->transaction.all && mysql_bin_log.is_open() && + /* If transaction has done some updates to tables */ + if (trans == &thd->transaction.all && my_b_tell(&thd->transaction.trans_log)) { - mysql_bin_log.write(thd, &thd->transaction.trans_log, 1); - reinit_io_cache(&thd->transaction.trans_log, - WRITE_CACHE, (my_off_t) 0, 0, 1); - thd->transaction.trans_log.end_of_file= max_binlog_cache_size; + if (error= wait_if_global_read_lock(thd, 0, 0)) + { + /* + Note that ROLLBACK [TO SAVEPOINT] does not have this test; it's + because ROLLBACK never updates data, so needn't wait on the lock. + */ + my_error(ER_ERROR_DURING_COMMIT, MYF(0), error); + error= 1; + } + else + need_start_waiters= 1; + if (mysql_bin_log.is_open()) + { + mysql_bin_log.write(thd, &thd->transaction.trans_log, 1); + reinit_io_cache(&thd->transaction.trans_log, + WRITE_CACHE, (my_off_t) 0, 0, 1); + thd->transaction.trans_log.end_of_file= max_binlog_cache_size; + } } #ifdef HAVE_BERKELEY_DB if (trans->bdb_tid) @@ -393,6 +406,8 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans) statistic_increment(ha_commit_count,&LOCK_status); thd->transaction.cleanup(); } + if (need_start_waiters) + start_waiting_global_read_lock(thd); } #endif // using transactions DBUG_RETURN(error); diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index a0bcd864d4b..236ebb8d28b 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -469,6 +469,7 @@ public: if (!args[0]->maybe_null) { used_tables_cache= 0; /* is always false */ + const_item_cache= 1; cached_value= (longlong) 0; } else diff --git a/sql/item_func.cc b/sql/item_func.cc index 368c14cc8df..334be48dc9a 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -684,7 +684,7 @@ void Item_func_round::fix_length_and_dec() if (tmp < 0) decimals=0; else - decimals=tmp; + decimals=min(tmp,NOT_FIXED_DEC); } } @@ -1071,6 +1071,7 @@ static const char separator=','; longlong Item_func_find_in_set::val_int() { + bool binary_cmp= args[0]->binary || args[1]->binary; if (enum_value) { ulonglong tmp=(ulonglong) args[1]->val_int(); @@ -1103,12 +1104,25 @@ longlong Item_func_find_in_set::val_int() do { const char *pos= f_pos; - while (pos != f_end) + if (binary_cmp) { - if (toupper(*str) != toupper(*pos)) - goto not_found; - str++; - pos++; + while (pos != f_end) + { + if (*str != *pos) + goto not_found; + str++; + pos++; + } + } + else + { + while (pos != f_end) + { + if (toupper(*str) != toupper(*pos)) + goto not_found; + str++; + pos++; + } } if (str == real_end || str[0] == separator) return (longlong) position; @@ -1286,7 +1300,7 @@ udf_handler::fix_fields(THD *thd,TABLE_LIST *tables,Item_result_field *func, func->max_length=min(initid.max_length,MAX_BLOB_WIDTH); func->maybe_null=initid.maybe_null; const_item_cache=initid.const_item; - func->decimals=min(initid.decimals,31); + func->decimals=min(initid.decimals,NOT_FIXED_DEC); } initialized=1; if (error) diff --git a/sql/item_func.h b/sql/item_func.h index 4d171cda490..8a013f42c05 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -295,7 +295,7 @@ class Item_dec_func :public Item_real_func Item_dec_func(Item *a,Item *b) :Item_real_func(a,b) {} void fix_length_and_dec() { - decimals=6; max_length=float_length(decimals); + decimals=NOT_FIXED_DEC; max_length=float_length(decimals); maybe_null=1; } inline double fix_result(double value) diff --git a/sql/item_sum.h b/sql/item_sum.h index 6835b1e8fae..802e3f1ba45 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -234,7 +234,11 @@ public: class Item_sum_avg :public Item_sum_num { - void fix_length_and_dec() { decimals+=4; maybe_null=1; } + void fix_length_and_dec() + { + decimals=min(decimals+4, NOT_FIXED_DEC); + maybe_null=1; + } double sum; ulonglong count; @@ -276,7 +280,11 @@ class Item_sum_std :public Item_sum_num double sum; double sum_sqr; ulonglong count; - void fix_length_and_dec() { decimals+=4; maybe_null=1; } + void fix_length_and_dec() + { + decimals=min(decimals+4, NOT_FIXED_DEC); + maybe_null=1; + } public: Item_sum_std(Item *item_par) :Item_sum_num(item_par),count(0) {} diff --git a/sql/lock.cc b/sql/lock.cc index 5010d115a6c..dd2b61b65d2 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -96,7 +96,7 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd,TABLE **tables,uint count) Someone has issued LOCK ALL TABLES FOR READ and we want a write lock Wait until the lock is gone */ - if (wait_if_global_read_lock(thd, 1)) + if (wait_if_global_read_lock(thd, 1, 1)) { my_free((gptr) sql_lock,MYF(0)); sql_lock=0; @@ -453,7 +453,7 @@ int lock_and_wait_for_table_name(THD *thd, TABLE_LIST *table_list) int error= -1; DBUG_ENTER("lock_and_wait_for_table_name"); - if (wait_if_global_read_lock(thd,0)) + if (wait_if_global_read_lock(thd, 0, 1)) DBUG_RETURN(1); VOID(pthread_mutex_lock(&LOCK_open)); if ((lock_retcode = lock_table_name(thd, table_list)) < 0) @@ -667,14 +667,23 @@ static void print_lock_error(int error) The global locks are handled through the global variables: global_read_lock + global_read_lock_blocks_commit waiting_for_read_lock protect_against_global_read_lock + + Taking the global read lock is TWO steps (2nd step is optional; without + it, COMMIT of existing transactions will be allowed): + lock_global_read_lock() THEN make_global_read_lock_block_commit(). ****************************************************************************/ volatile uint global_read_lock=0; +volatile uint global_read_lock_blocks_commit=0; static volatile uint protect_against_global_read_lock=0; static volatile uint waiting_for_read_lock=0; +#define GOT_GLOBAL_READ_LOCK 1 +#define MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT 2 + bool lock_global_read_lock(THD *thd) { DBUG_ENTER("lock_global_read_lock"); @@ -692,40 +701,53 @@ bool lock_global_read_lock(THD *thd) while (protect_against_global_read_lock && !thd->killed) pthread_cond_wait(&COND_refresh, &LOCK_open); waiting_for_read_lock--; - thd->exit_cond(old_message); if (thd->killed) { - (void) pthread_mutex_unlock(&LOCK_open); + thd->exit_cond(old_message); DBUG_RETURN(1); } - thd->global_read_lock=1; + thd->global_read_lock= GOT_GLOBAL_READ_LOCK; global_read_lock++; - (void) pthread_mutex_unlock(&LOCK_open); + thd->exit_cond(old_message); } + /* + We DON'T set global_read_lock_blocks_commit now, it will be set after + tables are flushed (as the present function serves for FLUSH TABLES WITH + READ LOCK only). Doing things in this order is necessary to avoid + deadlocks (we must allow COMMIT until all tables are closed; we should not + forbid it before, or we can have a 3-thread deadlock if 2 do SELECT FOR + UPDATE and one does FLUSH TABLES WITH READ LOCK). + */ DBUG_RETURN(0); } void unlock_global_read_lock(THD *thd) { uint tmp; - thd->global_read_lock=0; pthread_mutex_lock(&LOCK_open); tmp= --global_read_lock; + if (thd->global_read_lock == MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT) + --global_read_lock_blocks_commit; pthread_mutex_unlock(&LOCK_open); /* Send the signal outside the mutex to avoid a context switch */ if (!tmp) pthread_cond_broadcast(&COND_refresh); + thd->global_read_lock= 0; } +#define must_wait (global_read_lock && \ + (is_not_commit || \ + global_read_lock_blocks_commit)) -bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh) +bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh, bool is_not_commit) { const char *old_message; - bool result=0; + bool result= 0, need_exit_cond; DBUG_ENTER("wait_if_global_read_lock"); + LINT_INIT(old_message); (void) pthread_mutex_lock(&LOCK_open); - if (global_read_lock) + if (need_exit_cond= must_wait) { if (thd->global_read_lock) // This thread had the read locks { @@ -735,16 +757,18 @@ bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh) } old_message=thd->enter_cond(&COND_refresh, &LOCK_open, "Waiting for release of readlock"); - while (global_read_lock && ! thd->killed && + while (must_wait && ! thd->killed && (!abort_on_refresh || thd->version == refresh_version)) (void) pthread_cond_wait(&COND_refresh,&LOCK_open); if (thd->killed) result=1; - thd->exit_cond(old_message); } if (!abort_on_refresh && !result) protect_against_global_read_lock++; - pthread_mutex_unlock(&LOCK_open); + if (unlikely(need_exit_cond)) // global read locks are rare + thd->exit_cond(old_message); + else + pthread_mutex_unlock(&LOCK_open); DBUG_RETURN(result); } @@ -760,3 +784,21 @@ void start_waiting_global_read_lock(THD *thd) pthread_cond_broadcast(&COND_refresh); DBUG_VOID_RETURN; } + + +void make_global_read_lock_block_commit(THD *thd) +{ + /* + If we didn't succeed lock_global_read_lock(), or if we already suceeded + make_global_read_lock_block_commit(), do nothing. + */ + if (thd->global_read_lock != GOT_GLOBAL_READ_LOCK) + return; + pthread_mutex_lock(&LOCK_open); + /* increment this BEFORE waiting on cond (otherwise race cond) */ + global_read_lock_blocks_commit++; + while (protect_against_global_read_lock) + pthread_cond_wait(&COND_refresh, &LOCK_open); + pthread_mutex_unlock(&LOCK_open); + thd->global_read_lock= MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT; +} diff --git a/sql/log.cc b/sql/log.cc index 559d30f28ba..55ef2e72960 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -31,12 +31,55 @@ #include <m_ctype.h> // For test_if_number #include <assert.h> +#ifdef __NT__ +#include "message.h" +#endif + MYSQL_LOG mysql_log,mysql_update_log,mysql_slow_log,mysql_bin_log; extern I_List<i_string> binlog_do_db, binlog_ignore_db; static bool test_if_number(const char *str, long *res, bool allow_wildcards); +#ifdef __NT__ +static int eventSource = 0; + +void setup_windows_event_source() +{ + HKEY hRegKey= NULL; + DWORD dwError= 0; + TCHAR szPath[MAX_PATH]; + DWORD dwTypes; + + if (eventSource) // Ensure that we are only called once + return; + eventSource= 1; + + // Create the event source registry key + dwError= RegCreateKey(HKEY_LOCAL_MACHINE, + "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\MySQL", + &hRegKey); + + /* Name of the PE module that contains the message resource */ + GetModuleFileName(NULL, szPath, MAX_PATH); + + /* Register EventMessageFile */ + dwError = RegSetValueEx(hRegKey, "EventMessageFile", 0, REG_EXPAND_SZ, + (PBYTE) szPath, strlen(szPath)+1); + + + /* Register supported event types */ + dwTypes= (EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | + EVENTLOG_INFORMATION_TYPE); + dwError= RegSetValueEx(hRegKey, "TypesSupported", 0, REG_DWORD, + (LPBYTE) &dwTypes, sizeof dwTypes); + + RegCloseKey(hRegKey); +} + +#endif /* __NT__ */ + + /**************************************************************************** ** Find a uniq filename for 'filename.#'. ** Set # to a number as low as possible @@ -1169,12 +1212,24 @@ bool MYSQL_LOG::write(Log_event* event_info) /* Write log events to reset the 'run environment' of the SQL command */ - if (thd && thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) + if (thd) { - Query_log_event e(thd, "SET FOREIGN_KEY_CHECKS=1", 24, 0); - e.set_log_pos(this); - if (e.write(file)) - goto err; + if (thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) + { + Query_log_event e(thd, "SET FOREIGN_KEY_CHECKS=1", 24, 0); + e.set_log_pos(this); + if (e.write(file)) + goto err; + } +#if MYSQL_VERSION_ID < 40100 + if (thd->variables.convert_set) + { + Query_log_event e(thd, "SET CHARACTER SET DEFAULT", 25, 0); + e.set_log_pos(this); + if (e.write(file)) + goto err; + } +#endif } /* @@ -1533,18 +1588,13 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length, NOTES One must have a lock on LOCK_log before calling this function. - This lock will be freed before return! - - The reason for the above is that for enter_cond() / exit_cond() to - work the mutex must be got before enter_cond() but releases before - exit_cond(). - If you don't do it this way, you will get a deadlock in THD::awake() + This lock will be freed before return! That's required by + THD::enter_cond() (see NOTES in sql_class.h). */ void MYSQL_LOG:: wait_for_update(THD* thd, bool master_or_slave) { - safe_mutex_assert_owner(&LOCK_log); const char* old_msg = thd->enter_cond(&update_cond, &LOCK_log, master_or_slave ? "Has read all relay log; waiting for \ @@ -1552,7 +1602,6 @@ the I/O slave thread to update it" : "Has sent all binlog to slave; \ waiting for binlog to be updated"); pthread_cond_wait(&update_cond, &LOCK_log); - pthread_mutex_unlock(&LOCK_log); // See NOTES thd->exit_cond(old_msg); } @@ -1633,6 +1682,22 @@ void MYSQL_LOG::set_max_size(ulong max_size_arg) } +Disable_binlog::Disable_binlog(THD *thd_arg) : + thd(thd_arg), + save_options(thd_arg->options), save_master_access(thd_arg->master_access) +{ + thd_arg->options&= ~OPTION_BIN_LOG; + thd_arg->master_access|= SUPER_ACL; // unneeded in 4.1 +}; + + +Disable_binlog::~Disable_binlog() +{ + thd->options= save_options; + thd->master_access= save_master_access; +} + + /* Check if a string is a valid number @@ -1683,39 +1748,31 @@ static bool test_if_number(register const char *str, } /* test_if_number */ -void sql_print_error(const char *format,...) +void print_buffer_to_file(enum loglevel level, const char *buffer) { - va_list args; time_t skr; struct tm tm_tmp; struct tm *start; - va_start(args,format); - DBUG_ENTER("sql_print_error"); + DBUG_ENTER("print_buffer_to_file"); + DBUG_PRINT("enter",("buffer: %s", buffer)); VOID(pthread_mutex_lock(&LOCK_error_log)); -#ifndef DBUG_OFF - { - char buff[1024]; - my_vsnprintf(buff,sizeof(buff)-1,format,args); - DBUG_PRINT("error",("%s",buff)); - va_end(args); - va_start(args,format); - } -#endif + skr=time(NULL); - localtime_r(&skr,&tm_tmp); + localtime_r(&skr, &tm_tmp); start=&tm_tmp; - fprintf(stderr,"%02d%02d%02d %2d:%02d:%02d ", - start->tm_year % 100, - start->tm_mon+1, + fprintf(stderr, "%02d%02d%02d %2d:%02d:%02d [%s] %s\n", + start->tm_year % 100, + start->tm_mon+1, start->tm_mday, start->tm_hour, start->tm_min, - start->tm_sec); - (void) vfprintf(stderr,format,args); - (void) fputc('\n',stderr); + start->tm_sec, + (level == ERROR_LEVEL ? "ERROR" : level == WARNING_LEVEL ? + "WARNING" : "INFORMATION"), + buffer); + fflush(stderr); - va_end(args); VOID(pthread_mutex_unlock(&LOCK_error_log)); DBUG_VOID_RETURN; @@ -1731,6 +1788,7 @@ void sql_perror(const char *message) #endif } + bool flush_error_log() { bool result=0; @@ -1776,3 +1834,127 @@ bool flush_error_log() } return result; } + + +#ifdef __NT__ +void print_buffer_to_nt_eventlog(enum loglevel level, char *buff, + uint length, int buffLen) +{ + HANDLE event; + char *buffptr; + LPCSTR *buffmsgptr; + DBUG_ENTER("print_buffer_to_nt_eventlog"); + + buffptr= buff; + if (length > (uint)(buffLen-4)) + { + char *newBuff= new char[length + 4]; + strcpy(newBuff, buff); + buffptr= newBuff; + } + strmov(buffptr+length, "\r\n\r\n"); + buffmsgptr= (LPCSTR*) &buffptr; // Keep windows happy + + setup_windows_event_source(); + if ((event= RegisterEventSource(NULL,"MySQL"))) + { + switch (level) { + case ERROR_LEVEL: + ReportEvent(event, EVENTLOG_ERROR_TYPE, 0, MSG_DEFAULT, NULL, 1, 0, + buffmsgptr, NULL); + break; + case WARNING_LEVEL: + ReportEvent(event, EVENTLOG_WARNING_TYPE, 0, MSG_DEFAULT, NULL, 1, 0, + buffmsgptr, NULL); + break; + case INFORMATION_LEVEL: + ReportEvent(event, EVENTLOG_INFORMATION_TYPE, 0, MSG_DEFAULT, NULL, 1, + 0, buffmsgptr, NULL); + break; + } + DeregisterEventSource(event); + } + + /* if we created a string buffer, then delete it */ + if (buffptr != buff) + delete[] buffptr; + + DBUG_VOID_RETURN; +} +#endif /* __NT__ */ + + +/* + Prints a printf style message to the error log and, under NT, to the + Windows event log. + + SYNOPSIS + vprint_msg_to_log() + event_type Type of event to write (Error, Warning, or Info) + format Printf style format of message + args va_list list of arguments for the message + + NOTE + + IMPLEMENTATION + This function prints the message into a buffer and then sends that buffer + to other functions to write that message to other logging sources. + + RETURN VALUES + void +*/ + +void vprint_msg_to_log(enum loglevel level, const char *format, va_list args) +{ + char buff[1024]; + uint length; + DBUG_ENTER("vprint_msg_to_log"); + + length= my_vsnprintf(buff, sizeof(buff)-5, format, args); + print_buffer_to_file(level, buff); + +#ifdef __NT__ + print_buffer_to_nt_eventlog(level, buff, length, sizeof(buff)); +#endif + + DBUG_VOID_RETURN; +} + + +void sql_print_error(const char *format, ...) +{ + va_list args; + DBUG_ENTER("sql_print_error"); + + va_start(args, format); + vprint_msg_to_log(ERROR_LEVEL, format, args); + va_end(args); + + DBUG_VOID_RETURN; +} + + +void sql_print_warning(const char *format, ...) +{ + va_list args; + DBUG_ENTER("sql_print_warning"); + + va_start(args, format); + vprint_msg_to_log(WARNING_LEVEL, format, args); + va_end(args); + + DBUG_VOID_RETURN; +} + + +void sql_print_information(const char *format, ...) +{ + va_list args; + DBUG_ENTER("sql_print_information"); + + va_start(args, format); + vprint_msg_to_log(INFORMATION_LEVEL, format, args); + va_end(args); + + DBUG_VOID_RETURN; +} diff --git a/sql/log_event.cc b/sql/log_event.cc index f94056694cc..5526795c9d1 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1932,8 +1932,6 @@ end: thd->query= 0; // just to be sure thd->query_length= 0; VOID(pthread_mutex_unlock(&LOCK_thread_count)); - // assume no convert for next query unless set explictly - thd->variables.convert_set = 0; close_thread_tables(thd); free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC)); return (thd->query_error ? thd->query_error : Log_event::exec_event(rli)); @@ -1968,10 +1966,10 @@ end: int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, bool use_rli_only_for_errors) { + char *load_data_query= 0; init_sql_alloc(&thd->mem_root, thd->variables.query_alloc_block_size, 0); thd->db= (char*) rewrite_db(db); DBUG_ASSERT(thd->query == 0); - thd->query = 0; // Should not be needed clear_all_errors(thd, rli); if (!use_rli_only_for_errors) @@ -2024,6 +2022,19 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, { char llbuff[22]; enum enum_duplicates handle_dup; + /* + Make a simplified LOAD DATA INFILE query, for the information of the + user in SHOW PROCESSLIST. Note that db is known in the 'db' column. + */ + if ((load_data_query= (char *) my_alloca(18 + strlen(fname) + 14 + + strlen(tables.real_name) + 8))) + { + thd->query_length= (uint)(strxmov(load_data_query, + "LOAD DATA INFILE '", fname, + "' INTO TABLE `", tables.real_name, + "` <...>", NullS) - load_data_query); + thd->query= load_data_query; + } if (sql_ex.opt_flags & REPLACE_FLAG) handle_dup= DUP_REPLACE; else if (sql_ex.opt_flags & IGNORE_FLAG) @@ -2103,8 +2114,14 @@ Slave: load data infile on table '%s' at log position %s in log \ } thd->net.vio = 0; - thd->db= 0; // prevent db from being freed + VOID(pthread_mutex_lock(&LOCK_thread_count)); + thd->db= 0; + thd->query= 0; + thd->query_length= 0; + VOID(pthread_mutex_unlock(&LOCK_thread_count)); close_thread_tables(thd); + if (load_data_query) + my_afree(load_data_query); if (thd->query_error) { /* this err/sql_errno code is copy-paste from send_error() */ @@ -2326,7 +2343,7 @@ int Slave_log_event::exec_event(struct st_relay_log_info* rli) int Create_file_log_event::exec_event(struct st_relay_log_info* rli) { - char fname_buf[FN_REFLEN+10]; + char proc_info[17+FN_REFLEN+10], *fname_buf= proc_info+17; char *p; int fd = -1; IO_CACHE file; @@ -2335,6 +2352,8 @@ int Create_file_log_event::exec_event(struct st_relay_log_info* rli) bzero((char*)&file, sizeof(file)); p = slave_load_file_stem(fname_buf, file_id, server_id); strmov(p, ".info"); // strmov takes less code than memcpy + strnmov(proc_info, "Making temp file ", 17); // no end 0 + thd->proc_info= proc_info; if ((fd = my_open(fname_buf, O_WRONLY|O_CREAT|O_BINARY|O_TRUNC, MYF(MY_WME))) < 0 || init_io_cache(&file, fd, IO_SIZE, WRITE_CACHE, (my_off_t)0, 0, @@ -2376,6 +2395,7 @@ err: end_io_cache(&file); if (fd >= 0) my_close(fd, MYF(0)); + thd->proc_info= 0; return error ? 1 : Log_event::exec_event(rli); } @@ -2392,12 +2412,14 @@ int Delete_file_log_event::exec_event(struct st_relay_log_info* rli) int Append_block_log_event::exec_event(struct st_relay_log_info* rli) { - char fname[FN_REFLEN+10]; + char proc_info[17+FN_REFLEN+10], *fname= proc_info+17; char *p= slave_load_file_stem(fname, file_id, server_id); int fd; int error = 1; memcpy(p, ".data", 6); + strnmov(proc_info, "Making temp file ", 17); // no end 0 + thd->proc_info= proc_info; if ((fd = my_open(fname, O_WRONLY|O_APPEND|O_BINARY, MYF(MY_WME))) < 0) { slave_print_error(rli,my_errno, "Error in Append_block event: could not open file '%s'", fname); @@ -2413,6 +2435,7 @@ int Append_block_log_event::exec_event(struct st_relay_log_info* rli) err: if (fd >= 0) my_close(fd, MYF(0)); + thd->proc_info= 0; return error ? error : Log_event::exec_event(rli); } diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 5c15ae9a714..acc07eb6188 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -24,6 +24,7 @@ #include <thr_lock.h> #include <my_base.h> /* Needed by field.h */ #include <my_bitmap.h> +#include <my_getopt.h> #ifdef __EMX__ #undef write /* remove pthread.h macro definition for EMX */ @@ -438,7 +439,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, int mysql_create_table(THD *thd,const char *db, const char *table_name, HA_CREATE_INFO *create_info, List<create_field> &fields, List<Key> &keys, - bool tmp_table, bool no_log); + bool tmp_table); TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, const char *db, const char *name, List<create_field> *extra_fields, @@ -477,7 +478,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table,List<Item> &fields, void kill_delayed_threads(void); int mysql_delete(THD *thd, TABLE_LIST *table, COND *conds, ORDER *order, ha_rows rows, ulong options); -int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok=0); +int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok); TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update); TABLE *open_table(THD *thd,const char *db,const char *table,const char *alias, bool *refresh); @@ -535,6 +536,8 @@ int mysqld_show_variables(THD *thd,const char *wild); int mysqld_show(THD *thd, const char *wild, show_var_st *variables, enum enum_var_type value_type, pthread_mutex_t *mutex); +int mysql_find_files(THD *thd,List<char> *files, const char *db, + const char *path, const char *wild, bool dir); /* sql_handler.cc */ int mysql_ha_open(THD *thd, TABLE_LIST *tables); @@ -638,8 +641,14 @@ bool check_if_key_used(TABLE *table, uint idx, List<Item> &fields); void init_errmessage(void); void sql_perror(const char *message); -void sql_print_error(const char *format,...) - __attribute__ ((format (printf, 1, 2))); + +void vprint_msg_to_log( enum loglevel level, const char *format, va_list args ); +void sql_print_error( const char *format, ... ); +void sql_print_warning( const char *format, ...); +void sql_print_information( const char *format, ...); + + + bool fn_format_relative_to_data_home(my_string to, const char *name, const char *dir, const char *extension); bool open_log(MYSQL_LOG *log, const char *hostname, @@ -760,8 +769,9 @@ void mysql_lock_abort_for_thread(THD *thd, TABLE *table); MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a,MYSQL_LOCK *b); bool lock_global_read_lock(THD *thd); void unlock_global_read_lock(THD *thd); -bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh); +bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh, bool is_not_commit); void start_waiting_global_read_lock(THD *thd); +void make_global_read_lock_block_commit(THD *thd); /* Lock based on name */ int lock_and_wait_for_table_name(THD *thd, TABLE_LIST *table_list); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 80e9292a873..1e682e16d1f 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1547,6 +1547,8 @@ void registerwithneb() ulong neb_event_callback(struct EventBlock *eblock) { EventChangeVolStateEnter_s *voldata; + extern bool nw_panic; + voldata= (EventChangeVolStateEnter_s *)eblock->EBEventData; /* Deactivation of a volume */ @@ -1559,6 +1561,7 @@ ulong neb_event_callback(struct EventBlock *eblock) if (!memcmp(&voldata->volID, &datavolid, sizeof(VolumeID_t))) { consoleprintf("MySQL data volume is deactivated, shutting down MySQL Server \n"); + nw_panic = TRUE; kill_server(0); } } @@ -1836,9 +1839,11 @@ static void init_signals(void) sigaddset(&set,SIGPIPE); #endif sigaddset(&set,SIGINT); +#ifndef IGNORE_SIGHUP_SIGQUIT sigaddset(&set,SIGQUIT); - sigaddset(&set,SIGTERM); sigaddset(&set,SIGHUP); +#endif + sigaddset(&set,SIGTERM); /* Fix signals if blocked by parents (can happen on Mac OS X) */ sigemptyset(&sa.sa_mask); @@ -1921,11 +1926,13 @@ extern "C" void *signal_hand(void *arg __attribute__((unused))) #ifdef USE_ONE_SIGNAL_HAND (void) sigaddset(&set,THR_SERVER_ALARM); // For alarms #endif +#ifndef IGNORE_SIGHUP_SIGQUIT (void) sigaddset(&set,SIGQUIT); - (void) sigaddset(&set,SIGTERM); #if THR_CLIENT_ALARM != SIGHUP (void) sigaddset(&set,SIGHUP); #endif +#endif + (void) sigaddset(&set,SIGTERM); (void) sigaddset(&set,SIGTSTP); /* Save pid to this process (or thread on Linux) */ @@ -2240,6 +2247,10 @@ int main(int argc, char **argv) if (!opt_mysql_tmpdir || !opt_mysql_tmpdir[0]) opt_mysql_tmpdir=(char*) P_tmpdir; /* purecov: inspected */ + /* needed by get_options */ + + (void) pthread_mutex_init(&LOCK_error_log,MY_MUTEX_INIT_FAST); + set_options(); get_options(argc,argv); set_server_version(); @@ -2256,7 +2267,6 @@ int main(int argc, char **argv) (void) pthread_mutex_init(&LOCK_thread_count,MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_mapped_file,MY_MUTEX_INIT_SLOW); (void) pthread_mutex_init(&LOCK_status,MY_MUTEX_INIT_FAST); - (void) pthread_mutex_init(&LOCK_error_log,MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_delayed_insert,MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_delayed_status,MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_delayed_create,MY_MUTEX_INIT_SLOW); @@ -2614,6 +2624,9 @@ server."); printf(ER(ER_READY),my_progname,server_version, ((unix_sock == INVALID_SOCKET) ? (char*) "" : mysql_unix_port), mysql_port); + if (MYSQL_COMPILATION_COMMENT[0] != '\0') + fputs(" " MYSQL_COMPILATION_COMMENT, stdout); + putchar('\n'); fflush(stdout); #ifdef __NT__ @@ -3455,6 +3468,7 @@ enum options_mysqld { OPT_INNODB_LOCK_WAIT_TIMEOUT, OPT_INNODB_THREAD_CONCURRENCY, OPT_INNODB_FORCE_RECOVERY, + OPT_INNODB_STATUS_FILE, OPT_INNODB_MAX_DIRTY_PAGES_PCT, OPT_BDB_CACHE_SIZE, OPT_BDB_LOG_BUFFER_SIZE, @@ -3622,6 +3636,10 @@ struct my_option my_long_options[] = {"innodb_fast_shutdown", OPT_INNODB_FAST_SHUTDOWN, "Speeds up server shutdown process", (gptr*) &innobase_fast_shutdown, (gptr*) &innobase_fast_shutdown, 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, + {"innodb_status_file", OPT_INNODB_STATUS_FILE, + "Enable SHOW INNODB STATUS output in the innodb_status.<pid> file", + (gptr*) &innobase_create_status_file, (gptr*) &innobase_create_status_file, + 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"innodb_max_dirty_pages_pct", OPT_INNODB_MAX_DIRTY_PAGES_PCT, "Percentage of dirty pages allowed in bufferpool", (gptr*) &srv_max_buf_pool_modified_pct, (gptr*) &srv_max_buf_pool_modified_pct, 0, GET_ULONG, REQUIRED_ARG, 90, 0, 100, 0, 0, 0}, @@ -3944,11 +3962,11 @@ replicating a LOAD DATA INFILE command", 0, 0, 0, 0}, {"log-warnings", 'W', "Log some not critical warnings to the log file", (gptr*) &global_system_variables.log_warnings, - (gptr*) &max_system_variables.log_warnings, 0, GET_ULONG, OPT_ARG, 1, 0, 0, + (gptr*) &max_system_variables.log_warnings, 0, GET_ULONG, OPT_ARG, 1, 0, ~0L, 0, 0, 0}, {"warnings", 'W', "Deprecated ; Use --log-warnings instead", (gptr*) &global_system_variables.log_warnings, - (gptr*) &max_system_variables.log_warnings, 0, GET_ULONG, OPT_ARG, 1, 0, 0, + (gptr*) &max_system_variables.log_warnings, 0, GET_ULONG, OPT_ARG, 1, 0, ~0L, 0, 0, 0}, { "back_log", OPT_BACK_LOG, "The number of outstanding connection requests MySQL can have. This comes into play when the main MySQL thread gets very many connection requests in a very short time.", @@ -5085,13 +5103,24 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), } return 0; } + + +void option_error_reporter(enum loglevel level, const char *format, ...) +{ + va_list args; + va_start(args, format); + vprint_msg_to_log(level, format, args); + va_end(args); +} + /* Initiates DEBUG - but no debugging here ! */ static void get_options(int argc,char **argv) { int ho_error; - if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option))) + my_getopt_error_reporter= option_error_reporter; + if ((ho_error= handle_options(&argc, &argv, my_long_options, get_one_option))) exit(ho_error); #if defined(HAVE_BROKEN_REALPATH) diff --git a/sql/net_pkg.cc b/sql/net_pkg.cc index 315cad5ca6d..cc9147fe90a 100644 --- a/sql/net_pkg.cc +++ b/sql/net_pkg.cc @@ -124,7 +124,9 @@ net_printf(NET *net, uint errcode, ...) } offset= net->return_errno ? 2 : 0; text_pos=(char*) net->buff+head_length+offset+1; - (void) vsprintf(my_const_cast(char*) (text_pos),format,args); + (void) my_vsnprintf(my_const_cast(char*) (text_pos), + (char*)net->buff_end-text_pos, + format,args); length=(uint) strlen((char*) text_pos); if (length >= sizeof(net->last_error)) length=sizeof(net->last_error)-1; /* purecov: inspected */ diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index b5eec2d5dd4..0831c375f7a 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -401,6 +401,7 @@ static bool find_range_key(TABLE_REF *ref, Field* field, COND *cond) /* Can't use this key, for looking up min() or max(), end if last one */ if (key == 1) return 0; + key>>=1; idx++; } ref->key_length=0; ref->key=idx; diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index 1edf452d5f6..604938a8ed0 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -584,6 +584,8 @@ pthread_handler_decl(handle_failsafe_rpl,arg) THD *thd = new THD; thd->thread_stack = (char*)&thd; MYSQL* recovery_captain = 0; + const char* msg; + pthread_detach_this_thread(); if (init_failsafe_rpl_thread(thd) || !(recovery_captain=mc_mysql_init(0))) { @@ -591,11 +593,11 @@ pthread_handler_decl(handle_failsafe_rpl,arg) goto err; } pthread_mutex_lock(&LOCK_rpl_status); + msg= thd->enter_cond(&COND_rpl_status, + &LOCK_rpl_status, "Waiting for request"); while (!thd->killed && !abort_loop) { bool break_req_chain = 0; - const char* msg = thd->enter_cond(&COND_rpl_status, - &LOCK_rpl_status, "Waiting for request"); pthread_cond_wait(&COND_rpl_status, &LOCK_rpl_status); thd->proc_info="Processing request"; while (!break_req_chain) @@ -613,9 +615,8 @@ pthread_handler_decl(handle_failsafe_rpl,arg) break; } } - thd->exit_cond(msg); } - pthread_mutex_unlock(&LOCK_rpl_status); + thd->exit_cond(msg); err: if (recovery_captain) mc_mysql_close(recovery_captain); diff --git a/sql/share/charsets/win1251.conf b/sql/share/charsets/win1251.conf index a5ccc3190ad..e05568323b4 100644 --- a/sql/share/charsets/win1251.conf +++ b/sql/share/charsets/win1251.conf @@ -41,7 +41,7 @@ A0 A1 A2 A3 A4 A5 A6 A7 B8 A9 AA AB AC AD AE AF B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF - F0 F1 F2 F3 F4 F5 F5 F7 F8 F9 FA FB FC FD FE FF + F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF @@ -59,7 +59,7 @@ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF B0 B1 B2 B3 B4 B5 B6 B7 A8 B9 BA BB BC BD BE BF C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF - D0 D1 D2 D3 D4 D5 D5 D7 D8 D9 DA DB DC DD DE DF + D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index e36475d7803..b6737df91e1 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -86,7 +86,7 @@ "Blob sloupec '%-.64s' nem-BЫ╬e bЩt pou╬it jako klМХ", "P-BЬМli╧ velkА dИlka sloupce '%-.64s' (nejvМce %d). Pou╬ijte BLOB", "M-BЫ╬ete mМt pouze jedno AUTO pole a to musМ bЩt definovАno jako klМХ", -"%s: p-BЬipraven na spojenМ\n", +"%s: p-BЬipraven na spojenМ", "%s: norm-BАlnМ ukonХenМ\n", "%s: p-BЬijat signal %d, konХМm\n", "%s: ukon-BХenМ prАce hotovo\n", diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index 4e612c599ec..ba50c78e92c 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -80,7 +80,7 @@ "BLOB feltet '%-.64s' kan ikke bruges ved specifikation af indeks", "For stor feltlФngde for kolonne '%-.64s' (maks = %d). Brug BLOB i stedet", "Der kan kun specificeres eet AUTO_INCREMENT-felt, og det skal vФre indekseret", -"%s: klar til tilslutninger\n", +"%s: klar til tilslutninger", "%s: Normal nedlukning\n", "%s: Fangede signal %d. Afslutter!!\n", "%s: Server lukket\n", diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index 4aafa51e856..1b9c1025e69 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -88,7 +88,7 @@ "BLOB kolom '%-.64s' kan niet gebruikt worden bij zoeksleutel specificatie", "Te grote kolomlengte voor '%-.64s' (max = %d). Maak hiervoor gebruik van het type BLOB", "Er kan slechts 1 autofield zijn en deze moet als zoeksleutel worden gedefinieerd.", -"%s: klaar voor verbindingen\n", +"%s: klaar voor verbindingen", "%s: Normaal afgesloten \n", "%s: Signaal %d. Systeem breekt af!\n", "%s: Afsluiten afgerond\n", diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index dca9311b277..edbf2357ff8 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -77,7 +77,7 @@ "BLOB column '%-.64s' can't be used in key specification with the used table type", "Too big column length for column '%-.64s' (max = %d). Use BLOB instead", "Incorrect table definition; There can only be one auto column and it must be defined as a key", -"%s: ready for connections.\nVersion: '%s' socket: '%s' port: %d\n", +"%s: ready for connections.\nVersion: '%s' socket: '%s' port: %d", "%s: Normal shutdown\n", "%s: Got signal %d. Aborting!\n", "%s: Shutdown Complete\n", diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index f583568193f..8ec5d4b29f0 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -82,7 +82,7 @@ "BLOB-tЭЭpi tulpa '%-.64s' ei saa kasutada vУtmena", "Tulba '%-.64s' pikkus on liiga pikk (maksimaalne pikkus: %d). Kasuta BLOB vДljatЭЭpi", "Vigane tabelikirjeldus; Tabelis tohib olla Эks auto_increment tЭЭpi tulp ning see peab olema defineeritud vУtmena", -"%s: ootab Эhendusi\n", +"%s: ootab Эhendusi", "%s: MySQL lУpetas\n", "%s: sain signaali %d. LУpetan!\n", "%s: LУpp\n", diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index cabb22a6494..3c5c827aa62 100644 --- a/sql/share/french/errmsg.txt +++ b/sql/share/french/errmsg.txt @@ -77,7 +77,7 @@ "Champ BLOB '%-.64s' ne peut Йtre utilisИ dans une clИ", "Champ '%-.64s' trop long (max = %d). Utilisez un BLOB", "Un seul champ automatique est permis et il doit Йtre indexИ", -"%s: PrЙt pour des connections\n", +"%s: PrЙt pour des connections", "%s: ArrЙt normal du serveur\n", "%s: ReГu le signal %d. Abandonne!\n", "%s: ArrЙt du serveur terminИ\n", diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt index 518cb507466..3960dcc2122 100644 --- a/sql/share/german/errmsg.txt +++ b/sql/share/german/errmsg.txt @@ -80,7 +80,7 @@ "BLOB-Feld '%-.64s' kann nicht als SchlЭssel verwendet werden.", "FeldlДnge fЭr Feld '%-.64s' zu groъ (max = %d). BLOB-Feld verwenden!", "Nur ein Auto-Feld mЖglich, welches als SchlЭssel definiert werden muъ.", -"%-.64s: Warten auf Verbindungen.\n", +"%-.64s: Warten auf Verbindungen", "%-.64s: Normal beendet.\n", "%-.64s: Signal %d erhalten. Abbruch!\n", "%-.64s: Shutdown ausgefЭhrt.\n", diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index d993d80dcc1..3e9a68f2b4b 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -77,7 +77,7 @@ "пЕДъО ТЩПОУ Blob '%-.64s' ДЕМ ЛПОЯЕъ МА ВЯГСИЛОПОИГХЕъ СТОМ ОЯИСЛЭ ЕМЭР ЙКЕИДИОЩ (key specification)", "пОКЩ ЛЕЦэКО ЛчЙОР ЦИА ТО ПЕДъО '%-.64s' (max = %d). пАЯАЙАКЧ ВЯГСИЛОПОИЕъСТЕ ТОМ ТЩПО BLOB", "лПОЯЕъ МА УПэЯВЕИ ЛЭМО щМА auto field ЙАИ ПЯщПЕИ МА щВЕИ ОЯИСХЕъ САМ key", -"%s: СЕ АМАЛОМч СУМДщСЕЫМ\n", +"%s: СЕ АМАЛОМч СУМДщСЕЫМ", "%s: жУСИОКОЦИЙч ДИАДИЙАСъА shutdown\n", "%s: еКчЖХГ ТО ЛчМУЛА %d. г ДИАДИЙАСъА ЕЦЙАТАКЕъПЕТАИ!\n", "%s: г ДИАДИЙАСъА Shutdown ОКОЙКГЯЧХГЙЕ\n", diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index 4a65e735ef9..9da878981b0 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -79,7 +79,7 @@ "Blob objektum '%-.64s' nem hasznalhato kulcskent", "A(z) '%-.64s' oszlop tul hosszu. (maximum = %d). Hasznaljon BLOB tipust inkabb.", "Csak egy auto mezo lehetseges, es azt kulcskent kell definialni.", -"%s: kapcsolatra kesz\n", +"%s: kapcsolatra kesz", "%s: Normal leallitas\n", "%s: %d jelzes. Megszakitva!\n", "%s: A leallitas kesz\n", diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index c384c4bded4..7e267261a2e 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -79,7 +79,7 @@ "BLOB column '%-.64s' can't be used in key specification with the used table type", "column '%-.64s' ╓о,Ёнйщ╓╧╓К column ╓нбГ╓╜╓╣╓╛б©╓╧╓╝╓ч╓╧. (╨гбГ %d ╓ч╓г). BLOB ╓Р╓╚╓О╓Й╓к╩хмя╓╥╓ф╓╞╓ю╓╣╓╓.", "╔ф║╪╔ж╔К╓ндЙ╣а╓╛╟Ц╓╓╓ч╓╧; There can only be one auto column and it must be defined as a key", -"%s: ╫ЮхВ╢╟н╩\n", +"%s: ╫ЮхВ╢╟н╩", "%s: Normal shutdown\n", "%s: Got signal %d. цФцг!\n", "%s: Shutdown ╢╟н╩\n", diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index b706069b495..1ad5432f4db 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -77,7 +77,7 @@ "BLOB д╝╥Ё '%-.64s'╢б е╟ а╓юг©║╪╜ ╩Г©К╣и ╪Ж ╬Ь╫ю╢о╢ы.", "д╝╥Ё '%-.64s'юг д╝╥Ё ╠Фюл╟║ Ёй╧╚ ╠И╢о╢ы (цж╢К = %d). ╢К╫е©║ BLOB╦╕ ╩Г©Кго╪╪©Д.", "╨на╓х╝гя евюл╨М а╓юг; евюл╨Мю╨ гоЁ╙юг auto д╝╥Ёюл а╦юГго╟М е╟╥н а╓юг╣г╬На╝╬ъ гу╢о╢ы.", -"%s: ©╛╟А аь╨Яаъют╢о╢ы.\n", +"%s: ©╛╟А аь╨Яаъют╢о╢ы", "%s: а╓╩СюШюн shutdown\n", "%s: %d ╫ехё╟║ ╣И╬Н©тю╫. аъаЖ!\n", "%s: Shutdown юл ©о╥А╣й!\n", diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index 2c1deead312..234a53b53fb 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -79,7 +79,7 @@ "Blob kolonne '%-.64s' kan ikkje brukast ved spesifikasjon av nyklar", "For stor nykkellengde for felt '%-.64s' (maks = %d). Bruk BLOB istadenfor", "Bare eitt auto felt kan vФre definert som nЬkkel.", -"%s: klar for tilkoblingar\n", +"%s: klar for tilkoblingar", "%s: Normal nedkopling\n", "%s: Oppdaga signal %d. Avsluttar!\n", "%s: Nedkopling komplett\n", diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index 42b35c18cfc..e582786dc6e 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -79,7 +79,7 @@ "Blob felt '%-.64s' kan ikke brukes ved spesifikasjon av nЬkler", "For stor nЬkkellengde for kolonne '%-.64s' (maks = %d). Bruk BLOB istedenfor", "Bare ett auto felt kan vФre definert som nЬkkel.", -"%s: klar for tilkoblinger\n", +"%s: klar for tilkoblinger", "%s: Normal avslutning\n", "%s: Oppdaget signal %d. Avslutter!\n", "%s: Avslutning komplett\n", diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt index d8e84b08a9a..a4d11046ea4 100644 --- a/sql/share/polish/errmsg.txt +++ b/sql/share/polish/errmsg.txt @@ -81,7 +81,7 @@ "Kolumna typu Blob '%-.64s' nie mo©e byФ u©yta w specyfikacji klucza", "Zbyt du©a dЁugo?Ф kolumny '%-.64s' (maks. = %d). W zamian u©yj typu BLOB", "W tabeli mo©e byФ tylko jedno pole auto i musi ono byФ zdefiniowane jako klucz", -"%s: gotowe do poЁ?czenia\n", +"%s: gotowe do poЁ?czenia", "%s: Standardowe zakoЯczenie dziaЁania\n", "%s: Otrzymano sygnaЁ %d. KoЯczenie dziaЁania!\n", "%s: ZakoЯczenie dziaЁania wykonane\n", diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt index a1b5e87a52d..14c14270dc0 100644 --- a/sql/share/portuguese/errmsg.txt +++ b/sql/share/portuguese/errmsg.txt @@ -77,7 +77,7 @@ "Coluna BLOB '%-.64s' nЦo pode ser utilizada na especificaГЦo de chave para o tipo de tabela usado", "Comprimento da coluna '%-.64s' grande demais (max = %d). Use BLOB em seu lugar", "DefiniГЦo incorreta de tabela. Somente И permitido um Зnico campo auto-incrementado e ele tem que ser definido como chave", -"%s: Pronto para conexУes\n", +"%s: Pronto para conexУes", "%s: 'Shutdown' normal\n", "%s: Obteve sinal %d. Abortando!\n", "%s: 'Shutdown' completo\n", diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index 44e8b9fa8de..8d2decdf23f 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -81,7 +81,7 @@ "Coloana de tip BLOB '%-.64s' nu poate fi folosita in specificarea cheii cu tipul de tabla folosit", "Lungimea coloanei '%-.64s' este prea lunga (maximum = %d). Foloseste BLOB mai bine", "Definitia tabelei este incorecta; Nu pot fi mai mult de o singura coloana de tip auto si aceasta trebuie definita ca cheie", -"%s: sint gata pentru conectii\n", +"%s: sint gata pentru conectii", "%s: Terminare normala\n", "%s: Semnal %d obtinut. Aborting!\n", "%s: Terminare completa\n", diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt index 472031c6300..42845b57d76 100644 --- a/sql/share/russian/errmsg.txt +++ b/sql/share/russian/errmsg.txt @@ -79,7 +79,7 @@ "Столбец типа BLOB '%-.64s' не может быть использован как значение ключа в таблице такого типа", "Слишком большая длина столбца '%-.64s' (максимум = %d). Используйте тип BLOB вместо текущего", "Некорректное определение таблицы: может существовать только один автоинкрементный столбец, и он должен быть определен как ключ", -"%s: Готов принимать соединения.\nВерсия: '%s' сокет: '%s' порт: %d\n", +"%s: Готов принимать соединения.\nВерсия: '%s' сокет: '%s' порт: %d", "%s: Корректная остановка\n", "%s: Получен сигнал %d. Прекращаем!\n", "%s: Остановка завершена\n", diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index 411f93b97da..52ed69a238d 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -85,7 +85,7 @@ "Blob pole '%-.64s' nemТ╬e by╩ pou╬itИ ako k╣ЗХ", "PrМli╧ ve╣kА dЕ╬ka pre pole '%-.64s' (maximum = %d). Pou╬ite BLOB", "MТ╬ete ma╩ iba jedno AUTO pole a to musМ by╩ definovanИ ako k╣ЗХ", -"%s: pripravenЩ na spojenie\n", +"%s: pripravenЩ na spojenie", "%s: normАlne ukonХenie\n", "%s: prijatЩ signАl %d, ukonХenie (Abort)!\n", "%s: prАca ukonХenА\n", diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index 0010769aa4f..2ed3c19b68e 100644 --- a/sql/share/spanish/errmsg.txt +++ b/sql/share/spanish/errmsg.txt @@ -78,7 +78,7 @@ "La columna Blob '%-.64s' no puede ser usada en una declaracion de clave", "Longitud de columna demasiado grande para la columna '%-.64s' (maximo = %d).Usar BLOB en su lugar", "Puede ser solamente un campo automatico y este debe ser definido como una clave", -"%s: preparado para conexiones\n", +"%s: preparado para conexiones", "%s: Apagado normal\n", "%s: Recibiendo signal %d. Abortando!\n", "%s: Apagado completado\n", diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index 508737dde2f..4fd05875b43 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -77,7 +77,7 @@ "En BLOB '%-.64s' kan inte vara nyckel med den anvДnda tabelltypen", "FЖr stor kolumnlДngd angiven fЖr '%-.64s' (max= %d). AnvДnd en BLOB instДllet", "Det fЕr finnas endast ett AUTO_INCREMENT-fДlt och detta mЕste vara en nyckel", -"%s: klar att ta emot klienter\n", +"%s: klar att ta emot klienter", "%s: Normal avslutning\n", "%s: Fick signal %d. Avslutar!\n", "%s: Avslutning klar\n", diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt index 372cfa78dff..6036f4be2d5 100644 --- a/sql/share/ukrainian/errmsg.txt +++ b/sql/share/ukrainian/errmsg.txt @@ -82,7 +82,7 @@ "BLOB стовбець '%-.64s' не може бути використаний у визначенн╕ ключа в цьому тип╕ таблиц╕", "Задовга довжина стовбця '%-.64s' (max = %d). Використайте тип BLOB", "Нев╕рне визначення таблиц╕; Може бути лише один автоматичний стовбець, що повинен бути визначений як ключ", -"%s: Готовий для з'╓днань!\n", +"%s: Готовий для з'╓днань!", "%s: Нормальне завершення\n", "%s: Отримано сигнал %d. Перериваюсь!\n", "%s: Роботу завершено\n", diff --git a/sql/slave.cc b/sql/slave.cc index 2269fc8d8cf..4416a2544ef 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -582,7 +582,7 @@ int start_slave_thread(pthread_handler h_func, pthread_mutex_t *start_lock, pthread_mutex_unlock(start_lock); DBUG_RETURN(ER_SLAVE_THREAD); } - if (start_cond && cond_lock) + if (start_cond && cond_lock) // caller has cond_lock { THD* thd = current_thd; while (start_id == *slave_run_id) @@ -592,11 +592,9 @@ int start_slave_thread(pthread_handler h_func, pthread_mutex_t *start_lock, "Waiting for slave thread to start"); pthread_cond_wait(start_cond,cond_lock); thd->exit_cond(old_msg); + pthread_mutex_lock(cond_lock); // re-acquire it as exit_cond() released if (thd->killed) - { - pthread_mutex_unlock(cond_lock); DBUG_RETURN(ER_SERVER_SHUTDOWN); - } } } if (start_lock) @@ -1561,7 +1559,6 @@ thread to free enough relay log space"); !rli->ignore_log_space_limit) pthread_cond_wait(&rli->log_space_cond, &rli->log_space_lock); thd->exit_cond(save_proc_info); - pthread_mutex_unlock(&rli->log_space_lock); DBUG_RETURN(slave_killed); } @@ -1965,6 +1962,9 @@ int st_relay_log_info::wait_for_pos(THD* thd, String* log_name, (long) timeout)); pthread_mutex_lock(&data_lock); + const char *msg= thd->enter_cond(&data_cond, &data_lock, + "Waiting for the SQL slave thread to " + "advance position"); /* This function will abort when it notices that some CHANGE MASTER or RESET MASTER has changed the master info. @@ -2063,9 +2063,6 @@ int st_relay_log_info::wait_for_pos(THD* thd, String* log_name, //wait for master update, with optional timeout. DBUG_PRINT("info",("Waiting for master update")); - const char* msg = thd->enter_cond(&data_cond, &data_lock, - "Waiting for the SQL slave thread to \ -advance position"); /* We are going to pthread_cond_(timed)wait(); if the SQL thread stops it will wake us up. @@ -2087,8 +2084,7 @@ advance position"); } else pthread_cond_wait(&data_cond, &data_lock); - DBUG_PRINT("info",("Got signal of master update")); - thd->exit_cond(msg); + DBUG_PRINT("info",("Got signal of master update or timed out")); if (error == ETIMEDOUT || error == ETIME) { error= -1; @@ -2100,7 +2096,7 @@ advance position"); } err: - pthread_mutex_unlock(&data_lock); + thd->exit_cond(msg); DBUG_PRINT("exit",("killed: %d abort: %d slave_running: %d \ improper_arguments: %d timed_out: %d", (int) thd->killed, diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 4af6f407b57..58d0fe9a7fa 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -460,22 +460,30 @@ static ulong get_sort(uint count,...) va_start(args,count); ulong sort=0; + /* Should not use this function with more than 4 arguments for compare. */ + DBUG_ASSERT(count <= 4); + while (count--) { - char *str=va_arg(args,char*); - uint chars=0,wild=0; + char *start, *str= va_arg(args,char*); + uint chars= 0; + uint wild_pos= 0; /* first wildcard position */ - if (str) + if (start= str) { for (; *str ; str++) { if (*str == wild_many || *str == wild_one || *str == wild_prefix) - wild++; + { + wild_pos= str - start + 1; + break; + } else chars++; } } - sort= (sort << 8) + (wild ? 1 : chars ? 2 : 0); + sort= (sort << 8) + (wild_pos ? (wild_pos > 127 ? 127 : wild_pos) : + (chars ? 128 : 0)); } va_end(args); return sort; diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc index bd8c0e5ba87..3847849d6a7 100644 --- a/sql/sql_analyse.cc +++ b/sql/sql_analyse.cc @@ -34,9 +34,6 @@ #define MAX_TREEMEM 8192 #define MAX_TREE_ELEMENTS 256 -#define UINT_MAX16 0xffff -#define UINT_MAX24 0xffffff -#define UINT_MAX32 0xffffffff int sortcmp2(void* cmp_arg __attribute__((unused)), const String *a,const String *b) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 7b1b3cc1b7a..8fd7273fd78 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2062,9 +2062,23 @@ bool insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name, const char *table_name, List_iterator<Item> *it) { + char name_buff[NAME_LEN+1]; uint found; DBUG_ENTER("insert_fields"); + if (db_name && lower_case_table_names) + { + /* + convert database to lower case for comparison + We can't do this in Item_field as this would change the + 'name' of the item which may be used in the select list + */ + strmake(name_buff, db_name, sizeof(name_buff)-1); + casedn_str(name_buff); + db_name= name_buff; + } + + found=0; for (; tables ; tables=tables->next) { diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 44faa3d6963..eb6e74a58c4 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -299,8 +299,18 @@ void THD::awake(bool prepare_to_die) exits the cond in the time between read and broadcast, but that is ok since all we want to do is to make the victim thread get out of waiting on current_cond. + If we see a non-zero current_cond: it cannot be an old value (because + then exit_cond() should have run and it can't because we have mutex); so + it is the true value but maybe current_mutex is not yet non-zero (we're + in the middle of enter_cond() and there is a "memory order + inversion"). So we test the mutex too to not lock 0. + Note that there is a small chance we fail to kill. If victim has locked + current_mutex, and hasn't entered enter_cond(), then we don't know it's + going to wait on cond. Then victim goes into its cond "forever" (until + we issue a second KILL). True we have set its thd->killed but it may not + see it immediately and so may have time to reach the cond_wait(). */ - if (mysys_var->current_cond) + if (mysys_var->current_cond && mysys_var->current_mutex) { pthread_mutex_lock(mysys_var->current_mutex); pthread_cond_broadcast(mysys_var->current_cond); diff --git a/sql/sql_class.h b/sql/sql_class.h index 484a442af20..30947041b7d 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -478,7 +478,7 @@ public: ulong rand_saved_seed1, rand_saved_seed2; long dbug_thread_id; pthread_t real_id; - uint current_tablenr,tmp_table,cond_count; + uint current_tablenr,tmp_table,cond_count,global_read_lock; uint server_status,open_options,system_thread; uint32 query_length; uint32 db_length; @@ -489,7 +489,7 @@ public: bool set_query_id,locked,count_cuted_fields,some_tables_deleted; bool no_errors, allow_sum_func, password, fatal_error; bool query_start_used,last_insert_id_used,insert_id_used,rand_used; - bool in_lock_tables,global_read_lock; + bool in_lock_tables; bool query_error, bootstrap, cleanup_done; bool safe_to_cache_query; bool volatile killed; @@ -535,6 +535,12 @@ public: void close_active_vio(); #endif void awake(bool prepare_to_die); + /* + For enter_cond() / exit_cond() to work the mutex must be got before + enter_cond() (in 4.1 an assertion will soon ensure this); this mutex is + then released by exit_cond(). Use must be: + lock mutex; enter_cond(); your code; exit_cond(). + */ inline const char* enter_cond(pthread_cond_t *cond, pthread_mutex_t* mutex, const char* msg) { @@ -546,6 +552,13 @@ public: } inline void exit_cond(const char* old_msg) { + /* + Putting the mutex unlock in exit_cond() ensures that + mysys_var->current_mutex is always unlocked _before_ mysys_var->mutex is + locked (if that would not be the case, you'll get a deadlock if someone + does a THD::awake() on you). + */ + pthread_mutex_unlock(mysys_var->current_mutex); pthread_mutex_lock(&mysys_var->mutex); mysys_var->current_mutex = 0; mysys_var->current_cond = 0; @@ -626,6 +639,27 @@ public: #define SYSTEM_THREAD_SLAVE_SQL 4 /* + Disables binary logging for one thread, and resets it back to what it was + before being disabled. + Some functions (like the internal mysql_create_table() when it's called by + mysql_alter_table()) must NOT write to the binlog (binlogging is done at the + at a later stage of the command already, and must be, for locking reasons); + so we internally disable it temporarily by creating the Disable_binlog + object and reset the state by destroying the object (don't forget that! or + write code so that the object gets automatically destroyed when leaving a + block, see example in sql_table.cc). +*/ +class Disable_binlog { +private: + THD *thd; + ulong save_options; + ulong save_master_access; +public: + Disable_binlog(THD *thd_arg); + ~Disable_binlog(); +}; + +/* Used to hold information about file and file structure in exchainge via non-DB file (...INTO OUTFILE..., ...LOAD DATA...) */ diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 2ee725e7432..3d877403813 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -42,7 +42,7 @@ int mysql_create_db(THD *thd, char *db, uint create_options, bool silent) VOID(pthread_mutex_lock(&LOCK_mysql_create_db)); // do not create database if another thread is holding read lock - if (wait_if_global_read_lock(thd,0)) + if (wait_if_global_read_lock(thd, 0, 1)) { error= -1; goto exit2; @@ -146,7 +146,7 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) VOID(pthread_mutex_lock(&LOCK_mysql_create_db)); // do not drop database if another thread is holding read lock - if (wait_if_global_read_lock(thd,0)) + if (wait_if_global_read_lock(thd, 0, 1)) { error= -1; goto exit2; diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index b568166a766..555e63b9e32 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -545,15 +545,13 @@ int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok) int error; DBUG_ENTER("mysql_truncate"); + bzero((char*) &create_info,sizeof(create_info)); /* If it is a temporary table, close and regenerate it */ if (!dont_send_ok && (table_ptr=find_temporary_table(thd,table_list->db, table_list->real_name))) { TABLE *table= *table_ptr; - HA_CREATE_INFO create_info; table->file->info(HA_STATUS_AUTO | HA_STATUS_NO_LOCK); - bzero((char*) &create_info,sizeof(create_info)); - create_info.auto_increment_value= table->file->auto_increment_value; db_type table_type=table->db_type; strmov(path,table->path); @@ -596,7 +594,6 @@ int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok) DBUG_RETURN(-1); } - bzero((char*) &create_info,sizeof(create_info)); *fn_ext(path)=0; // Remove the .frm extension error= ha_create_table(path,&create_info,1) ? -1 : 0; query_cache_invalidate3(thd, table_list, 0); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 94e2f8f8850..8912c1faf2a 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1545,9 +1545,13 @@ void select_create::abort() table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); enum db_type table_type=table->db_type; if (!table->tmp_table) + { hash_delete(&open_cache,(byte*) table); - if (!create_info->table_existed) - quick_rm_table(table_type,db,name); + if (!create_info->table_existed) + quick_rm_table(table_type, db, name); + } + else if (!create_info->table_existed) + close_temporary_table(thd, db, name); table=0; } VOID(pthread_mutex_unlock(&LOCK_open)); diff --git a/sql/sql_load.cc b/sql/sql_load.cc index a3ba14373b2..501852b5de8 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -291,6 +291,9 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, { if (transactional_table) ha_autocommit_or_rollback(thd,error); + if (read_file_from_client) + while (!read_info.next_line()) + ; if (mysql_bin_log.is_open()) { /* diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 4dd5d126cc9..14fc748c288 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1692,7 +1692,7 @@ mysql_execute_command(void) tables->real_name, &lex->create_info, lex->create_list, - lex->key_list,0, 0); // do logging + lex->key_list,0); if (!res) send_ok(&thd->net); } @@ -2046,7 +2046,7 @@ mysql_execute_command(void) send_error(&thd->net,ER_LOCK_OR_ACTIVE_TRANSACTION,NullS); goto error; } - res=mysql_truncate(thd,tables); + res=mysql_truncate(thd, tables, 0); break; case SQLCOM_DELETE: { @@ -2869,10 +2869,10 @@ bool check_stack_overrun(THD *thd,char *buf __attribute__((unused))) #define MY_YACC_INIT 1000 // Start with big alloc #define MY_YACC_MAX 32000 // Because of 'short' -bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, int *yystacksize) +bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, ulong *yystacksize) { LEX *lex=current_lex; - int old_info=0; + ulong old_info=0; if ((uint) *yystacksize >= MY_YACC_MAX) return 1; if (!lex->yacc_yyvs) @@ -3231,8 +3231,12 @@ bool add_field_to_list(char *field_name, enum_field_types type, case FIELD_TYPE_TIMESTAMP: if (!length) new_field->length= 14; // Full date YYYYMMDDHHMMSS - else + else if (new_field->length != 19) { + /* + We support only even TIMESTAMP lengths less or equal than 14 + and 19 as length of 4.1 compatible representation. + */ new_field->length=((new_field->length+1)/2)*2; /* purecov: inspected */ new_field->length= min(new_field->length,14); /* purecov: inspected */ } @@ -3704,8 +3708,12 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables) { if (lock_global_read_lock(thd)) return 1; + result=close_cached_tables(thd,(options & REFRESH_FAST) ? 0 : 1, + tables); + make_global_read_lock_block_commit(thd); } - result=close_cached_tables(thd,(options & REFRESH_FAST) ? 0 : 1, tables); + else + result=close_cached_tables(thd,(options & REFRESH_FAST) ? 0 : 1, tables); } if (options & REFRESH_HOSTS) hostname_cache_refresh(); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 096b73c482f..cf5e8a75f85 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3371,7 +3371,10 @@ change_cond_ref_to_const(I_List<COND_CMP> *save_list,Item *and_father, Item *right_item= func->arguments()[1]; Item_func::Functype functype= func->functype(); - if (right_item->eq(field,0) && left_item != value) + if (right_item->eq(field,0) && left_item != value && + (left_item->result_type() != STRING_RESULT || + value->result_type() != STRING_RESULT || + left_item->binary == value->binary)) { Item *tmp=value->new_item(); if (tmp) @@ -3390,7 +3393,10 @@ change_cond_ref_to_const(I_List<COND_CMP> *save_list,Item *and_father, func->arguments()[1]->result_type())); } } - else if (left_item->eq(field,0) && right_item != value) + else if (left_item->eq(field,0) && right_item != value && + (right_item->result_type() != STRING_RESULT || + value->result_type() != STRING_RESULT || + right_item->binary == value->binary)) { Item *tmp=value->new_item(); if (tmp) @@ -4533,6 +4539,20 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, new_table.no_rows=1; } +#ifdef TO_BE_DONE_LATER_IN_4_1 + /* + To use start_bulk_insert() (which is new in 4.1) we need to find + all places where a corresponding end_bulk_insert() should be put. + */ + table->file->info(HA_STATUS_VARIABLE); /* update table->file->records */ + new_table.file->start_bulk_insert(table->file->records); +#else + /* + HA_EXTRA_WRITE_CACHE can stay until close, no need to disable it explicitly. + */ + new_table.file->extra(HA_EXTRA_WRITE_CACHE); +#endif + /* copy all old rows */ while (!table->file->rnd_next(new_table.record[1])) { @@ -7158,7 +7178,16 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields) if (!(pos=new Item_copy_string(pos))) goto err; VOID(li.replace(pos)); - if (param->copy_funcs.push_back(pos)) + /* + Item_copy_string::copy for function can call + Item_copy_string::val_int for blob via Item_ref. + But if Item_copy_string::copy for blob isn't called before, + it's value will be wrong + so let's insert Item_copy_string for blobs in the beginning of + copy_funcs + (to see full test case look at having.test, BUG #4358) + */ + if (param->copy_funcs.push_front(pos)) goto err; continue; } diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 26163ed9bef..6784cd64465 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -35,9 +35,6 @@ static TYPELIB grant_types = { sizeof(grant_names)/sizeof(char **), "grant_types", grant_names}; -static int mysql_find_files(THD *thd,List<char> *files, const char *db, - const char *path, const char *wild, bool dir); - static int store_create_info(THD *thd, TABLE *table, String *packet); @@ -170,7 +167,7 @@ int mysqld_show_tables(THD *thd,const char *db,const char *wild) } -static int +int mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path, const char *wild, bool dir) { diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 1b956779832..96eebd98ac3 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -230,6 +230,17 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, wrong_tables.append(String(table->real_name)); } } + + error= 0; + if (wrong_tables.length()) + { + if (!foreign_key_error) + my_error(ER_BAD_TABLE_ERROR,MYF(0),wrong_tables.c_ptr()); + else + my_error(ER_ROW_IS_REFERENCED,MYF(0)); + error= 1; + } + if (some_tables_deleted || tmp_table_deleted) { query_cache_invalidate3(thd, tables, 0); @@ -238,7 +249,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, mysql_update_log.write(thd, thd->query,thd->query_length); if (mysql_bin_log.is_open()) { - thd->clear_error(); + if (!error) + thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, tmp_table_deleted && !some_tables_deleted); mysql_bin_log.write(&qinfo); @@ -247,15 +259,6 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, } unlock_table_names(thd, tables); - error= 0; - if (wrong_tables.length()) - { - if (!foreign_key_error) - my_error(ER_BAD_TABLE_ERROR,MYF(0),wrong_tables.c_ptr()); - else - my_error(ER_ROW_IS_REFERENCED,MYF(0)); - error= 1; - } DBUG_RETURN(error); } @@ -333,7 +336,6 @@ static int sort_keys(KEY *a, KEY *b) keys List of keys to create tmp_table Set to 1 if this is an internal temporary table (From ALTER TABLE) - no_log Don't log the query to binary log. DESCRIPTION If one creates a temporary table, this is automaticly opened @@ -351,7 +353,7 @@ static int sort_keys(KEY *a, KEY *b) int mysql_create_table(THD *thd,const char *db, const char *table_name, HA_CREATE_INFO *create_info, List<create_field> &fields, - List<Key> &keys,bool tmp_table,bool no_log) + List<Key> &keys,bool tmp_table) { char path[FN_REFLEN]; const char *key_name, *alias; @@ -776,7 +778,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, goto end; } } - if (!tmp_table && !no_log) + if (!tmp_table) { // Must be written before unlock mysql_update_log.write(thd,thd->query, thd->query_length); @@ -840,6 +842,7 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, TABLE tmp_table; // Used during 'create_field()' TABLE *table; tmp_table.table_name=0; + Disable_binlog disable_binlog(thd); DBUG_ENTER("create_table_from_items"); /* Add selected items to field list */ @@ -870,9 +873,17 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, } /* create and lock table */ /* QQ: This should be done atomic ! */ + /* We don't log the statement, it will be logged later */ if (mysql_create_table(thd,db,name,create_info,*extra_fields, - *keys,0,1)) // no logging + *keys,0)) DBUG_RETURN(0); + /* + If this is a HEAP table, the automatic DELETE FROM which is written to the + binlog when a HEAP table is opened for the first time since startup, must + not be written: 1) it would be wrong (imagine we're in CREATE SELECT: we + don't want to delete from it) 2) it would be written before the CREATE + TABLE, which is a wrong order. So we keep binary logging disabled. + */ if (!(table=open_table(thd,db,name,name,(bool*) 0))) { quick_rm_table(create_info->db_type,db,table_case_name(create_info,name)); @@ -889,6 +900,7 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, } table->file->extra(HA_EXTRA_WRITE_CACHE); DBUG_RETURN(table); + /* Note that leaving the function resets binlogging properties */ } @@ -1298,7 +1310,6 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables, dropping_tables--; } thd->exit_cond(old_message); - pthread_mutex_unlock(&LOCK_open); if (thd->killed) goto err; open_for_modify=0; @@ -1913,12 +1924,17 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, } else create_info->data_file_name=create_info->index_file_name=0; - - if ((error=mysql_create_table(thd, new_db, tmp_name, - create_info, - create_list,key_list,1,1))) // no logging - DBUG_RETURN(error); - + { + /* + We don't log the statement, it will be logged later. Using a block so + that disable_binlog is deleted when we leave it in either way. + */ + Disable_binlog disable_binlog(thd); + if ((error=mysql_create_table(thd, new_db, tmp_name, + create_info, + create_list,key_list,1))) + DBUG_RETURN(error); + } if (table->tmp_table) new_table=open_table(thd,new_db,tmp_name,tmp_name,0); else diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 2930c60310a..2199a0c8be5 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -32,7 +32,7 @@ extern void yyerror(const char*); int yylex(void *yylval); -#define yyoverflow(A,B,C,D,E,F) if (my_yyoverflow((B),(D),(int*) (F))) { yyerror((char*) (A)); return 2; } +#define yyoverflow(A,B,C,D,E,F) {ulong val= *(F); if(my_yyoverflow((B), (D), &val)) { yyerror((char*) (A)); return 2; } else { *(F)= (YYSIZE_T)val; }} inline Item *or_or_concat(Item* A, Item* B) { @@ -71,7 +71,7 @@ inline Item *or_or_concat(Item* A, Item* B) } %{ -bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); +bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %} %pure_parser /* We have threads */ @@ -1316,10 +1316,16 @@ alter_list_item: lex->simple_alter=0; } | RENAME opt_to table_ident - { + { LEX *lex=Lex; lex->select->db=$3->db.str; lex->name= $3->table.str; + if (check_table_name($3->table.str,$3->table.length) || + $3->db.str && check_db_name($3->db.str)) + { + net_printf(&lex->thd->net,ER_WRONG_TABLE_NAME,$3->table.str); + YYABORT; + } } | create_table_options { Lex->simple_alter=0; } | order_clause { Lex->simple_alter=0; }; diff --git a/sql/table.cc b/sql/table.cc index 7e6338a3f3f..573fa11a4c4 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -993,8 +993,23 @@ ulong next_io_size(register ulong pos) void append_unescaped(String *res,const char *pos) { - for (; *pos ; pos++) +#ifdef USE_MB + const char *end= pos + strlen(pos); +#endif + + for (; *pos ; ) { +#if defined(USE_MB) && MYSQL_VERSION_ID < 40100 + uint mblen; + if (use_mb(default_charset_info) && + (mblen= my_ismbchar(default_charset_info, pos, end))) + { + res->append(pos, mblen); + pos+= mblen; + continue; + } +#endif + switch (*pos) { case 0: /* Must be escaped for 'mysql' */ res->append('\\'); @@ -1020,6 +1035,7 @@ void append_unescaped(String *res,const char *pos) res->append(*pos); break; } + pos++; } } diff --git a/strings/strto.c b/strings/strto.c index c98b19a7e67..9ad4502faaf 100644 --- a/strings/strto.c +++ b/strings/strto.c @@ -35,8 +35,12 @@ it can be compiled with the UNSIGNED and/or LONGLONG flag set */ -#include <my_global.h> -#include "m_string.h" + +#if !defined(_global_h) || !defined(_m_string_h) +# error Calling file must include 'my_global.h' and 'm_string.h' + /* see 'strtoll.c' and 'strtoull.c' for the reasons */ +#endif + #include "m_ctype.h" #include "my_sys.h" /* defines errno */ #include <errno.h> diff --git a/strings/strtol.c b/strings/strtol.c index 10d7f8f9da6..ed4ca86c846 100644 --- a/strings/strtol.c +++ b/strings/strtol.c @@ -14,9 +14,16 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* This defines strtol() if neaded */ +/* This implements strtol() if needed */ +/* + These includes are mandatory because they check for type sizes and + functions, especially they handle tricks for Tru64 where 'long' is + 64 bit already and our 'longlong' is just a 'long'. + */ #include <my_global.h> +#include <m_string.h> + #if !defined(MSDOS) && !defined(HAVE_STRTOL) && !defined(__WIN__) #include "strto.c" #endif diff --git a/strings/strtoll.c b/strings/strtoll.c index b0b4ef328fc..45352ffd360 100644 --- a/strings/strtoll.c +++ b/strings/strtoll.c @@ -14,11 +14,20 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* This is defines strtoll() if neaded */ +/* This implements strtoll() if needed */ -#define strtoll glob_strtoll /* Fix for True64 */ +/* + These includes are mandatory because they check for type sizes and + functions, especially they handle tricks for Tru64 where 'long' is + 64 bit already and our 'longlong' is just a 'long'. + This solves a problem on Tru64 where the C99 compiler has a prototype + for 'strtoll()' but no implementation, see "6.1 New C99 library functions" + in file '/usr/share/doclib/cc.dtk/release_notes.txt'. + */ #include <my_global.h> +#include <m_string.h> + #if !defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG) #define USE_LONGLONG #include "strto.c" diff --git a/strings/strtoul.c b/strings/strtoul.c index 00e1f820942..77bc267d218 100644 --- a/strings/strtoul.c +++ b/strings/strtoul.c @@ -14,9 +14,16 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* This is defines strtoul() if neaded */ +/* This implements strtoul() if needed */ +/* + These includes are mandatory because they check for type sizes and + functions, especially they handle tricks for Tru64 where 'long' is + 64 bit already and our 'longlong' is just a 'long'. + */ #include <my_global.h> +#include <m_string.h> + #if !defined(MSDOS) && !defined(HAVE_STRTOUL) #define USE_UNSIGNED #include "strto.c" diff --git a/strings/strtoull.c b/strings/strtoull.c index f4f3ce19bf7..0c2788bc188 100644 --- a/strings/strtoull.c +++ b/strings/strtoull.c @@ -14,9 +14,20 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* This is defines strtoull() */ +/* This implements strtoull() if needed */ + +/* + These includes are mandatory because they check for type sizes and + functions, especially they handle tricks for Tru64 where 'long' is + 64 bit already and our 'longlong' is just a 'long'. + This solves a problem on Tru64 where the C99 compiler has a prototype + for 'strtoull()' but no implementation, see "6.1 New C99 library functions" + in file '/usr/share/doclib/cc.dtk/release_notes.txt'. + */ #include <my_global.h> +#include <m_string.h> + #if !defined(HAVE_STRTOULL) && defined(HAVE_LONG_LONG) #define USE_UNSIGNED #define USE_LONGLONG diff --git a/support-files/Makefile.am b/support-files/Makefile.am index 79ba6eec763..1f38b4c30c2 100644 --- a/support-files/Makefile.am +++ b/support-files/Makefile.am @@ -22,6 +22,7 @@ EXTRA_DIST = mysql.spec.sh \ my-medium.cnf.sh \ my-large.cnf.sh \ my-huge.cnf.sh \ + my-innodb-heavy-4G.cnf.sh \ mysql-log-rotate.sh \ mysql.server.sh \ binary-configure.sh \ @@ -34,6 +35,7 @@ pkgdata_DATA = my-small.cnf \ my-medium.cnf \ my-large.cnf \ my-huge.cnf \ + my-innodb-heavy-4G.cnf \ mysql-log-rotate \ mysql-@VERSION@.spec \ binary-configure \ @@ -45,6 +47,7 @@ CLEANFILES = my-small.cnf \ my-medium.cnf \ my-large.cnf \ my-huge.cnf \ + my-innodb-heavy-4G.cnf \ mysql.spec \ mysql-@VERSION@.spec \ mysql-log-rotate \ diff --git a/support-files/MySQL-shared-compat.spec.sh b/support-files/MySQL-shared-compat.spec.sh index 2a257a601a1..068daadab58 100644 --- a/support-files/MySQL-shared-compat.spec.sh +++ b/support-files/MySQL-shared-compat.spec.sh @@ -26,8 +26,8 @@ # # Change this to match the version of the shared libs you want to include # -%define version4 @VERSION@ -%define version3 3.23.56 +%define version4 @MYSQL_NO_DASH_VERSION@ +%define version3 3.23.58 Name: MySQL-shared-compat Packager: Lenz Grimmer <build@mysql.com> diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 5ddc19580f3..eb5b469c8da 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -153,7 +153,7 @@ Summary: MySQL - server with Berkeley BD, RAID and UDF support Group: Applications/Databases Provides: mysql-Max Obsoletes: mysql-Max -Requires: MySQL >= 4.0 +Requires: MySQL-server >= 4.0 %description Max Optional MySQL server binary that supports additional features like @@ -282,7 +282,18 @@ mv sql/mysqld sql/mysqld-max nm --numeric-sort sql/mysqld-max > sql/mysqld-max.sym # Install embedded server library in the build root -install -m 644 libmysqld/libmysqld.a $RBR%{_libdir}/mysql +install -m 644 libmysqld/libmysqld.a $RBR%{_libdir}/mysql/ + +# Include libgcc.a in the devel subpackage (BUG 4921) +if [ "$CC" = gcc ] +then + libgcc=`$CC --print-libgcc-file` + if [ -f $libgcc ] + then + %define have_libgcc 1 + install -m 644 $libgcc $RBR%{_libdir}/mysql/libmygcc.a + fi +fi # Save libraries (cd libmysql/.libs; tar cf $RBR/shared-libs.tar *.so*) @@ -446,7 +457,7 @@ fi %files server %defattr(-,root,root,0755) -%doc COPYING README +%doc COPYING README %doc Docs/manual.{html,ps,texi,txt} %doc Docs/manual_toc.html %doc support-files/my-*.cnf @@ -531,6 +542,7 @@ fi %files devel %defattr(-, root, root, 0755) +%doc EXCEPTIONS-CLIENT %attr(755, root, root) %{_bindir}/comp_err %attr(755, root, root) %{_bindir}/mysql_config %dir %attr(755, root, root) %{_includedir}/mysql @@ -539,6 +551,9 @@ fi %{_libdir}/mysql/libdbug.a %{_libdir}/mysql/libheap.a %{_libdir}/mysql/libmerge.a +%if %{have_libgcc} +%{_libdir}/mysql/libmygcc.a +%endif %{_libdir}/mysql/libmyisam.a %{_libdir}/mysql/libmyisammrg.a %{_libdir}/mysql/libmysqlclient.a @@ -573,8 +588,22 @@ fi %attr(644, root, root) %{_libdir}/mysql/libmysqld.a # The spec file changelog only includes changes made to the spec file -# itself +# itself - note that they must be ordered by date (important when +# merging BK trees) %changelog +* Thu Aug 26 2004 Lenz Grimmer <lenz@mysql.com> + +- MySQL-Max now requires MySQL-server instead of MySQL (BUG 3860) + +* Tue Aug 10 2004 Lenz Grimmer <lenz@mysql.com> + +- Added libmygcc.a to the devel subpackage (required to link applications + against the the embedded server libmysqld.a) (BUG 4921) + +* Mon Aug 09 2004 Lenz Grimmer <lenz@mysql.com> + +- Added EXCEPTIONS-CLIENT to the "devel" package + * Mon Apr 05 2004 Lenz Grimmer <lenz@mysql.com> - added ncurses-devel to the build prerequisites (BUG 3377) |