Merge paul@work.mysql.com:/home/bk/mysql-4.0

into teton.kitebird.com:/home/paul/mysql-4.0
This commit is contained in:
paul@teton.kitebird.com 2002-02-21 16:10:27 -06:00
commit 2645d5083f
64 changed files with 2625 additions and 1358 deletions

View file

@ -460,3 +460,4 @@ vio/test-sslserver
vio/viotest-ssl
Docs/mysql.xml
mysql-test/r/rpl000001.eval
Docs/safe-mysql.xml

View file

@ -8,6 +8,6 @@ c_warnings="$c_warnings $debug_extra_warnings"
cxx_warnings="$cxx_warnings $debug_extra_warnings"
extra_configs="$pentium_configs $debug_configs"
extra_configs="$extra_configs --with-berkeley-db --with-innodb --with-embedded-server --with-openssl"
extra_configs="$extra_configs --with-berkeley-db --with-innodb --with-embedded-server --with-openssl --enable-local-infile"
. "$path/FINISH.sh"

View file

@ -8,6 +8,7 @@ arjen@co3064164-a.bitbike.com
bell@sanja.is.com.ua
davida@isil.mysql.com
heikki@donna.mysql.fi
heikki@hundin.mysql.fi
jani@hynda.mysql.fi
jani@janikt.pp.saunalahti.fi
jani@rhols221.adsl.netsonic.fi
@ -15,6 +16,7 @@ jcole@abel.spaceapes.com
jcole@main.burghcom.com
jcole@sarvik.tfr.cafe.ee
jcole@tetra.spaceapes.com
jorge@linux.jorge.mysql.com
kaj@work.mysql.com
miguel@light.local
monty@bitch.mysql.fi
@ -43,3 +45,4 @@ tonu@volk.internalnet
tonu@x153.internalnet
tonu@x3.internalnet
venu@work.mysql.com
zak@linux.local

View file

@ -63,6 +63,7 @@ aclocal; autoheader; aclocal; automake; autoconf
--with-low-memory \
--with-mit-threads=yes $EXTRA_CONFIG \
--enable-thread-safe-client \
--enable-local-infile \
--with-berkeley-db \
--with-innodb \
--with-vio \

View file

@ -3,30 +3,30 @@
use Getopt::Long;
$opt_distribution=$opt_user=$opt_result=$opt_config_options=$opt_config_env="";
$opt_dbd_options=$opt_perl_options=$opt_suffix="";
$opt_tmp=$version_suffix="";
$opt_tmp=$opt_version_suffix="";
$opt_help=$opt_Information=$opt_delete=$opt_debug=$opt_stage=$opt_rsh_mail=$opt_no_test=$opt_no_perl=$opt_with_low_memory=$opt_fast_benchmark=$opt_static_client=$opt_static_server=$opt_static_perl=$opt_sur=$opt_with_small_disk=$opt_local_perl=$opt_tcpip=$opt_build_thread=$opt_no_mysqltest=$opt_use_old_distribution=$opt_enable_shared=$opt_no_crash_me=$opt_no_strip=0;
$opt_innodb=$opt_bdb=0;
GetOptions("Information","help","distribution=s","user=s","result=s","delete","no-test","no-mysqltest","perl-files=s","debug","config-options=s","config-env=s","stage=i","rsh-mail","with-low-memory","fast-benchmark","tmp=s","static-client","static-server","static-perl","no-perl","local-perl","perl-options=s","sur","with-small-disk","dbd-options=s","tcpip","suffix=s","build-thread=i","innodb","bdb","use-old-distribution","enable-shared","no-crash-me","no-strip") || usage();
GetOptions("Information","help","distribution=s","user=s","result=s","delete","no-test","no-mysqltest","perl-files=s","debug","config-options=s","config-env=s","stage=i","rsh-mail","with-low-memory","fast-benchmark","tmp=s","static-client","static-server","static-perl","no-perl","local-perl","perl-options=s","sur","with-small-disk","dbd-options=s","tcpip","suffix=s","build-thread=i","innodb","bdb","use-old-distribution","enable-shared","no-crash-me","no-strip","version-suffix=s") || usage();
usage() if ($opt_help || $opt_Information);
usage() if (!$opt_distribution);
if ($opt_innodb || $opt_bdb)
if (($opt_innodb || $opt_bdb) && $opt_version_suffix eq "")
{
$version_suffix="-max";
$opt_version_suffix="-max";
}
chomp($host=`hostname`);
$full_host_name=$host;
info("Compiling MySQL$version_suffix at $host$suffix, stage: $opt_stage\n");
info("Compiling MySQL$opt_version_suffix at $host$suffix, stage: $opt_stage\n");
$connect_option= ($opt_tcpip ? "--host=$host" : "");
$host =~ /^([^.-]*)/;
$host=$1 . $opt_suffix;
$email="$opt_user\@mysql.com";
$pwd = `pwd`; chomp($pwd);
$log="$pwd/Logs/$host$version_suffix.log";
$opt_distribution =~ /(mysql-[^\/]*)\.tar/;
$log="$pwd/Logs/$host$opt_version_suffix.log";
$opt_distribution =~ /(mysql[^\/]*)\.tar/;
$ver=$1;
$gcc_version=which("gcc");
if (defined($gcc_version) && ! $opt_config_env)
@ -108,7 +108,7 @@ $|=1;
select STDOUT;
$|=1;
safe_cd("$host");
safe_cd($host);
if ($opt_stage == 0 && ! $opt_use_old_distribution)
{
safe_system("gunzip < $opt_distribution | $tar xf -");
@ -118,6 +118,7 @@ if ($opt_stage == 0 && ! $opt_use_old_distribution)
system("touch timestamp; find . -newer timestamp -print | xargs touch; rm -f timestamp");
sleep(2);
# Ensure that files we don't want to rebuild are newer than other files
safe_cd($ver);
foreach $name ("configure",
"Docs/include.texi",
"Docs/*.html", "Docs/manual.txt", "Docs/mysql.info",
@ -125,9 +126,11 @@ if ($opt_stage == 0 && ! $opt_use_old_distribution)
{
system("touch $name");
}
# Fix some file modes in BDB tables that makes life harder.
system("chmod -R u+rw .");
}
safe_cd($ver);
safe_cd("$pwd/$host/$ver");
if ($opt_stage <= 1)
{
$opt_config_options.=" --with-low-memory" if ($opt_with_low_memory);
@ -156,7 +159,7 @@ if ($opt_stage <= 1)
{
$opt_config_options.= " --with-innodb"
}
check_system("$opt_config_env ./configure --prefix=/usr/local/mysql \"--with-comment=Official MySQL$version_suffix binary\" --with-extra-charsets=complex \"--with-server-suffix=$version_suffix\" --enable-thread-safe-client $opt_config_options","Thank you for choosing MySQL");
check_system("$opt_config_env ./configure --prefix=/usr/local/mysql \"--with-comment=Official MySQL$opt_version_suffix binary\" --with-extra-charsets=complex \"--with-server-suffix=$opt_version_suffix\" --enable-thread-safe-client --enable-local-infile $opt_config_options","Thank you for choosing MySQL");
if (-d "$pwd/$host/include-mysql")
{
safe_system("cp -r $pwd/$host/include-mysql/* $pwd/$host/$ver/include");
@ -209,7 +212,7 @@ if ($opt_stage <= 4 && !$opt_no_test)
safe_system("gunzip < $tar_file | $tar xf -");
}
$tar_file =~ /(mysql-[^\/]*)\.tar/;
$tar_file =~ /(mysql[^\/]*)\.tar/;
$ver=$1;
$test_dir="$pwd/$host/test/$ver";
$ENV{"LD_LIBRARY_PATH"}= "$test_dir/lib:" . $ENV{"LD_LIBRARY_PATH"};
@ -361,6 +364,9 @@ To set up the environment, like 'CC=cc CXX=gcc CXXFLAGS=-O3'
--dbd-options 'options'
Options for Makefile.PL when configuring msql-mysql-modules.
--version-suffix suffix
Can be used to set a suffix (normally 'com' or '-max') for a distribution
--with-low-memory
Use less memory when compiling.

View file

@ -96,7 +96,7 @@ sub main
# remove the 'PUBLIC' file from distribution and copy LICENSE
# on the toplevel of the directory instead. file 'PUBLIC' shouldn't
# exist in the new mysql distributions, but let's be sure..
`rm -f $destdir/PUBLIC`;
`rm -f $destdir/PUBLIC $destdir/README`;
`cp -p $WD/Docs/LICENSE $destdir/`;
# fix file copyrights
@ -129,7 +129,7 @@ sub fix_usage_copyright
foreach my $Cfile (@Cfiles)
{
chop $Cfile;
`replace \"This is free software,\\\\\\nand you are welcome to modify and redistribute it under the GPL license\" \"This is commercial software,\\\\nplease see the file LICENSE for details\" -- $Cfile`;
`replace "This is free software," "This is commercial software," "and you are welcome to modify and redistribute it under the GPL license" "please see the file LICENSE for details" -- $Cfile`;
}
}

View file

@ -1,4 +1,6 @@
#!/usr/bin/perl
#!/usr/bin/perl -w
# 2002-02-15 zak@mysql.com
# Use -w to make perl print useful warnings about the script being run
sub fix_underscore {
$str = shift;
@ -13,9 +15,39 @@ sub strip_emph {
return $str;
};
print STDERR "\n--Post-processing makeinfo output--\n";
# 2002-02-15 zak@mysql.com
print STDERR "Discard DTD - ORA can add the appropriate DTD for their flavour of DocBook\n";
<STDIN>;
print STDERR "Slurp! In comes the rest of the file. :)\n";
$data = join "", <STDIN>;
# 2002-02-15 zak@mysql.com
print STDERR "Add an XML processing instruction with the right character encoding\n";
$data = "<?xml version='1.0' encoding='ISO-8859-1'?>" . $data;
# 2002-02-15 zak@mysql.com
# Less than optimal - should be fixed in makeinfo
print STDERR "Put in missing <bookinfo> and <abstract>\n";
$data =~ s/<book lang="en">/<book lang="en"><bookinfo><abstract>/gs;
# 2002-02-15 zak@mysql.com
print STDERR "Convert existing ampersands to escape sequences \n";
$data =~ s/&(?!\w+;)/&amp;/gs;
# 2002-02-15 zak@mysql.com
# Need to talk to Arjen about what the <n> bits are for
print STDERR "Rework references of the notation '<n>'\n";
$data =~ s/<(\d)>/[$1]/gs;
# 2002-02-15 zak@mysql.com
# We might need to encode the high-bit characters to ensure proper representation
# print STDERR "Converting high-bit characters to entities\n";
# $data =~ s/([\200-\400])/&get_entity($1)>/gs;
# There is no get_entity function yet - no point writing it til we need it :)
print STDERR "Changing @@ to @...\n";
$data =~ s/@@/@/gs;
@ -45,6 +77,11 @@ print STDERR "Fixing spacing problem with titles...\n";
$data =~ s{</(\w+)>(\w{2,})}
{</$1> $2}gs;
# 2002-02-15 arjen@mysql.com
print STDERR "Adding closing / to XREF...\n";
$data =~ s{<xref (.+?)>}
{<xref $1 />}gs;
# 2002-01-30 arjen@mysql.com
print STDERR "Removing COLSPEC...\n";
$data =~ s{\n *<colspec colwidth=\"[0-9]+\*\">}
@ -65,10 +102,10 @@ print STDERR "Removing lf before /PARA in ENTRY...\n";
$data =~ s{(<entry><para>(.+?))\n(</para></entry>)}
{$1$3}gs;
# 2002-01-31 arjen@mysql.com
print STDERR "Removing whitespace before /PARA...\n";
$data =~ s{[ ]+</para>}
{</para>}gs;
# 2002-01-31 arjen@mysql.com (2002-02-15 added \n stuff)
print STDERR "Removing whitespace before /PARA if not on separate line...\n";
$data =~ s{([^\n ])[ ]+</para>}
{$1</para>}gs;
# 2002-01-31 arjen@mysql.com
print STDERR "Removing empty PARA in ENTRY...\n";

96
Docs/Support/docbook-split Executable file
View file

@ -0,0 +1,96 @@
#! /usr/local/bin/perl
# O'Reilly's Perl script to chop mysql.xml into separate ch/apps/index files.
# The indexes are actually not used, they're created straight from the xrefs.
use strict;
# Breaks the MySQL reference manual into chapters, appendices, and indexes.
my $input_file;
my $directory;
my $chap_num;
my $app_letter;
my $start_text;
my $line;
my $input_file;
my $output_name;
$input_file = "mysql.xml";
$directory="chaps_apps_index";
$chap_num=1; # Start chapter numbers at one (there is no preface)
$app_letter="a"; # Start appendix letters at "a"
$start_text="";
$line="";
open (INPUT_FILE, '<' . $input_file) or die "Cannot open $input_file";
if (-d $directory) {
my $unlinked = unlink <$directory/*>;
printf(Removed "%d files\n", $unlinked);
}
else {
mkdir $directory or die "Cannot make $directory subdirectory";
}
while (1) {
# Terminating statement for loop.
exit if not defined $line;
if ($line =~ /(?:.*)(<chapter.*)/i ) {
$start_text = $1;
$output_name = &make_chapter_name($chap_num);
$chap_num++;
&process_file("chapter");
}
elsif ($line =~ /(?:.*)(<appendix.*)/i ) {
$start_text = $1 ;
$output_name = &make_appendix_name($app_letter);
$app_letter++;
&process_file("appendix");
}
elsif ($line =~ /(?:.*)(<index\s+id=")(.*?)(">.*)/i ) {
$start_text = $1 . $2 . $3;
$output_name = lc($2) . ".xml";
&process_file("index");
}
else {
# Automatically skips junk in between chapters, appendices,
# and indexes.
$line = <INPUT_FILE>;
}
}
sub make_chapter_name {
my $num = shift;
my $name = "ch" . sprintf("%02d", $num) . ".xml";
return $name;
}
sub make_appendix_name {
my $letter = shift;
my $name = "app" . sprintf("%s", $letter) . ".xml";
return $name;
}
sub process_file {
my $marker=shift;
open (OUTPUT_FILE, '>' . $directory . "/" . $output_name) or
die "Cannot open $output_name";
# Print whatever happened to appear at the end of the previous chapter.
print OUTPUT_FILE $start_text . "\n" if $start_text;
while (1) {
$line = <INPUT_FILE>;
exit if not defined $line;
# Note: Anything after the terminating marker is lost, just like
# lines in between chapters.
if ($line =~ /(.*<\/\s*$marker\s*>)/i ) {
print OUTPUT_FILE $1 . "\n" if $1;
close OUTPUT_FILE;
return;
}
print OUTPUT_FILE $line;
}
}
exit 0;

View file

@ -13,7 +13,8 @@
sed -e 's;MYSQL_TCP_PORT_DEFAULT=;;' >> include.texi
# produce DocBook XML
makeinfo --force --no-ifinfo --docbook manual.texi
mv mysql.xml mysql-tmp.xml
Support/docbook-fixup.pl <mysql-tmp.xml >mysql.xml
rm -f mysql-tmp.xml
makeinfo --force --no-ifinfo --docbook -o - manual.texi |\
Support/docbook-fixup.pl > mysql.xml
# See if the XML output is well-formed
xmlwf mysql.xml

67
Docs/Support/xwf Executable file
View file

@ -0,0 +1,67 @@
#!/usr/bin/perl -w
#
# Parse document and report first syntax (well-formedness) error found.
#
use strict;
use XML::Parser;
use Getopt::Std;
my %opts;
getopts('e', \%opts);
my $ENTREFS = exists( $opts{'e'} ); # flag: check ent refs
my $parser = XML::Parser->new(
ErrorContext => 2, # output error context
);
# get input from files
if( @ARGV ) {
foreach( @ARGV ) {
my $file = $_;
unless( -r $file ) {
print STDERR "ERROR: Can't open '$file'.\n";
return;
}
my $input = '';
open( F, $file );
while( <F> ) { $input .= $_; }
close F;
# parse and report errors
if( &parse_string( $input )) {
print STDERR "ERROR in $file:\n$@\n";
} else {
print STDERR "'$file' is well-formed.\n";
}
}
print "All files checked.\n";
# get input from STDIN
} else {
my $input = "";
while( <STDIN> ) { $input .= $_; }
if( &parse_string( $input )) {
print STDERR "ERROR in stream:\n$@\n";
} else {
print STDERR "No syntax errors found in XML stream.\n";
}
}
# parse the string and return error message
#
# NOTE: By default, entity refs are not expanded. XML::Parser can be
# told not to expand entity refs, but will still try to find
# replacement text just in case, which we don't want. Therefore, we
# need to do a stupid regexp replacement, removing entities from input.
#
sub parse_string {
my $string = shift;
unless( $ENTREFS ) {
$string =~ s/\&[^\s;]+;//g; # remove entity references
}
eval { $parser->parse( $string ); };
$@ =~ s/at \/.*?$//s; # remove module line number
return $@;
}

File diff suppressed because it is too large Load diff

View file

@ -21,6 +21,9 @@
/* Version of .frm files */
#undef DOT_FRM_VERSION
/* If LOAD DATA LOCAL INFILE should be enabled by default */
#undef ENABLED_LOCAL_INFILE
/* READLINE: */
#undef FIONREAD_IN_SYS_IOCTL

View file

@ -31,4 +31,4 @@ enum options { OPT_CHARSETS_DIR=256, OPT_DEFAULT_CHARSET,
OPT_LOW_PRIORITY, OPT_AUTO_REPAIR, OPT_COMPRESS,
OPT_DROP, OPT_LOCKS, OPT_KEYWORDS, OPT_DELAYED, OPT_OPTIMIZE,
OPT_FTB, OPT_LTB, OPT_ENC, OPT_O_ENC, OPT_ESC, OPT_TABLES,
OPT_MASTER_DATA, OPT_AUTOCOMMIT};
OPT_MASTER_DATA, OPT_AUTOCOMMIT, OPT_LOCAL_INFILE};

View file

@ -38,7 +38,7 @@
#include <signal.h>
#include <violite.h>
const char *VER="11.19";
const char *VER="11.20";
/* Don't try to make a nice table if the data is too big */
#define MAX_COLUMN_LENGTH 1024
@ -116,10 +116,10 @@ static MYSQL mysql; /* The connection */
static bool info_flag=0,ignore_errors=0,wait_flag=0,quick=0,
connected=0,opt_raw_data=0,unbuffered=0,output_tables=0,
no_rehash=0,skip_updates=0,safe_updates=0,one_database=0,
opt_compress=0,
opt_compress=0, using_opt_local_infile=0,
vertical=0,skip_line_numbers=0,skip_column_names=0,opt_html=0,
opt_xml=0,opt_nopager=1, opt_outfile=0, no_named_cmds=1;
static uint verbose=0,opt_silent=0,opt_mysql_port=0;
static uint verbose=0,opt_silent=0,opt_mysql_port=0, opt_local_infile=0;
static my_string opt_mysql_unix_port=0;
static int connect_flag=CLIENT_INTERACTIVE;
static char *current_host,*current_db,*current_user=0,*opt_password=0,
@ -436,6 +436,7 @@ static struct option long_options[] =
{"xml", no_argument, 0, 'X'},
{"host", required_argument, 0, 'h'},
{"ignore-spaces", no_argument, 0, 'i'},
{"local-infile", optional_argument, 0, OPT_LOCAL_INFILE},
{"no-auto-rehash",no_argument, 0, 'A'},
{"no-named-commands", no_argument, 0, 'g'},
{"no-tee", no_argument, 0, OPT_NOTEE},
@ -738,6 +739,10 @@ static int get_options(int argc, char **argv)
case 'C':
opt_compress=1;
break;
case OPT_LOCAL_INFILE:
using_opt_local_infile=1;
opt_local_infile= test(!optarg || atoi(optarg)>0);
break;
case 'L':
skip_line_numbers=1;
break;
@ -2235,6 +2240,8 @@ sql_real_connect(char *host,char *database,char *user,char *password,
}
if (opt_compress)
mysql_options(&mysql,MYSQL_OPT_COMPRESS,NullS);
if (using_opt_local_infile)
mysql_options(&mysql,MYSQL_OPT_LOCAL_INFILE, (char*) &opt_local_infile);
#ifdef HAVE_OPENSSL
if (opt_use_ssl)
mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,

View file

@ -518,7 +518,7 @@ AC_ARG_ENABLE(thread-safe-client,
[ THREAD_SAFE_CLIENT=no ]
)
# Make thread safe client
# compile with strings functions in assembler
AC_ARG_ENABLE(assembler,
[ --enable-assembler Use assembler versions of some string
functions if available.],
@ -583,6 +583,14 @@ AC_ARG_WITH(mysqld-user,
)
AC_SUBST(MYSQLD_USER)
# compile with strings functions in assembler
AC_ARG_ENABLE(local-infile,
[ --enable-local-infile
If LOAD DATA LOCAL INFILE is enabled by default.],
[ ENABLED_LOCAL_INFILE=$enablewal ],
[ ENABLED_LOCAL_INFILE=no ]
)
# Use Paul Eggerts macros from GNU tar to check for large file support.
MYSQL_SYS_LARGEFILE
@ -610,9 +618,11 @@ AC_CHECK_HEADERS(fcntl.h float.h floatingpoint.h ieeefp.h limits.h \
#--------------------------------------------------------------------
AC_CHECK_LIB(m, floor, [], AC_CHECK_LIB(m, __infinity))
AC_CHECK_FUNC(gethostbyname_r, [], [
AC_CHECK_LIB(nsl_r, gethostbyname_r, [],
AC_CHECK_LIB(nsl, gethostbyname_r))])
AC_CHECK_LIB(nsl_r, gethostbyname_r, [],
AC_CHECK_LIB(nsl, gethostbyname_r))
AC_CHECK_FUNC(gethostbyname_r)
AC_CHECK_FUNC(setsockopt, , AC_CHECK_LIB(socket, setsockopt))
AC_CHECK_FUNC(yp_get_default_domain, ,
AC_CHECK_LIB(nsl, yp_get_default_domain))
@ -921,7 +931,7 @@ then
AC_TRY_COMPILE([#include <sched.h>], [int a = sched_get_priority_min(1);], ,
AC_MSG_ERROR([Syntax error in sched.h. Change _P to __P in the /usr/include/sched.h file. See the Installation chapter in the Reference Manual]))
# RedHat 5.0 does not work with dynamic linking of this. -static also
# gives a spped increase in linux so it does not hurt on other systems.
# gives a speed increase in linux so it does not hurt on other systems.
with_named_thread="-lpthread"
else
AC_MSG_RESULT("Not found")

View file

@ -62,9 +62,6 @@ extern const char *compiled_charset_name(uint charset_number);
#define MY_CHARSET_UNDEFINED 0
#define MY_CHARSET_CURRENT (default_charset_info->number)
#ifdef __WIN__
#include <ctype.h>
#endif
/* Don't include std ctype.h when this is included */
#define _CTYPE_H
#define _CTYPE_H_
@ -72,6 +69,26 @@ extern const char *compiled_charset_name(uint charset_number);
#define __CTYPE_INCLUDED
#define _CTYPE_USING /* Don't put names in global namespace. */
/* Fix things, if ctype.h would have been included before */
#undef toupper
#undef _toupper
#undef _tolower
#undef toupper
#undef tolower
#undef isalpha
#undef isupper
#undef islower
#undef isdigit
#undef isxdigit
#undef isalnum
#undef isspace
#undef ispunct
#undef isprint
#undef isgraph
#undef iscntrl
#undef isascii
#undef toascii
#define _U 01 /* Upper case */
#define _L 02 /* Lower case */
#define _N 04 /* Numeral (digit) */
@ -86,7 +103,6 @@ extern const char *compiled_charset_name(uint charset_number);
#define my_to_lower (default_charset_info->to_lower)
#define my_sort_order (default_charset_info->sort_order)
#ifndef __WIN__
#define _toupper(c) (char) my_to_upper[(uchar) (c)]
#define _tolower(c) (char) my_to_lower[(uchar) (c)]
#define toupper(c) (char) my_to_upper[(uchar) (c)]
@ -110,8 +126,6 @@ extern const char *compiled_charset_name(uint charset_number);
#undef ctype
#endif /* ctype */
#endif /* __WIN__ */
#define my_isalpha(s, c) (((s)->ctype+1)[(uchar) (c)] & (_U | _L))
#define my_isupper(s, c) (((s)->ctype+1)[(uchar) (c)] & _U)
#define my_islower(s, c) (((s)->ctype+1)[(uchar) (c)] & _L)

View file

@ -157,7 +157,8 @@ struct st_mysql_options {
enum mysql_option { MYSQL_OPT_CONNECT_TIMEOUT, MYSQL_OPT_COMPRESS,
MYSQL_OPT_NAMED_PIPE, MYSQL_INIT_COMMAND,
MYSQL_READ_DEFAULT_FILE, MYSQL_READ_DEFAULT_GROUP,
MYSQL_SET_CHARSET_DIR, MYSQL_SET_CHARSET_NAME};
MYSQL_SET_CHARSET_DIR, MYSQL_SET_CHARSET_NAME,
MYSQL_OPT_LOCAL_INFILE};
enum mysql_status { MYSQL_STATUS_READY,MYSQL_STATUS_GET_RESULT,
MYSQL_STATUS_USE_RESULT};

View file

@ -2552,6 +2552,7 @@ btr_estimate_number_of_different_key_vals(
ulint total_external_size = 0;
ulint i;
ulint j;
ulint add_on;
mtr_t mtr;
n_cols = dict_index_get_n_unique(index);
@ -2624,8 +2625,25 @@ btr_estimate_number_of_different_key_vals(
+ not_empty_flag)
/ (BTR_KEY_VAL_ESTIMATE_N_PAGES
+ total_external_size);
}
/* If the tree is small, smaller than <
10 * BTR_KEY_VAL_ESTIMATE_N_PAGES + total_external_size, then
the above estimate is ok. For bigger trees it is common that we
do not see any borders between key values in the few pages
we pick. But still there may be BTR_KEY_VAL_ESTIMATE_N_PAGES
different key values, or even more. Let us try to approximate
that: */
add_on = index->stat_n_leaf_pages /
(10 * (BTR_KEY_VAL_ESTIMATE_N_PAGES + total_external_size));
if (add_on > BTR_KEY_VAL_ESTIMATE_N_PAGES) {
add_on = BTR_KEY_VAL_ESTIMATE_N_PAGES;
}
index->stat_n_diff_key_vals[j] += add_on;
}
mem_free(n_diff);
}

View file

@ -243,7 +243,6 @@ loop:
if (n_iterations > 30) {
ut_print_timestamp(stderr);
fprintf(stderr,
" ***********************************************\n"
"InnoDB: Warning: difficult to find free blocks from\n"
"InnoDB: the buffer pool (%lu search iterations)! Consider\n"
"InnoDB: increasing the buffer pool size.\n",

View file

@ -1235,16 +1235,23 @@ loop:
if (error != DB_SUCCESS) {
fprintf(stderr,
"InnoDB: foreign constraint creation failed;\n"
"InnoDB: Foreign key constraint creation failed:\n"
"InnoDB: internal error number %lu\n", error);
ut_a(error == DB_OUT_OF_FILE_SPACE);
if (error == DB_DUPLICATE_KEY) {
fprintf(stderr,
"InnoDB: Duplicate key error in system table %s index %s\n",
((dict_index_t*)trx->error_info)->table_name,
((dict_index_t*)trx->error_info)->name);
fprintf(stderr, "InnoDB: tablespace is full\n");
trx_general_rollback_for_mysql(trx, FALSE, NULL);
error = DB_MUST_GET_MORE_FILE_SPACE;
fprintf(stderr, "%s\n", buf);
fprintf(stderr,
"InnoDB: Maybe the internal data dictionary of InnoDB is\n"
"InnoDB: out-of-sync from the .frm files of your tables.\n"
"InnoDB: See section 15.1 Troubleshooting data dictionary operations\n"
"InnoDB: at http://www.innodb.com/ibman.html\n");
}
return(error);
}

View file

@ -195,21 +195,6 @@ dict_mutex_exit_for_mysql(void)
mutex_exit(&(dict_sys->mutex));
}
/************************************************************************
Increments the count of open MySQL handles to a table. */
void
dict_table_increment_handle_count(
/*==============================*/
dict_table_t* table) /* in: table */
{
mutex_enter(&(dict_sys->mutex));
table->n_mysql_handles_opened++;
mutex_exit(&(dict_sys->mutex));
}
/************************************************************************
Decrements the count of open MySQL handles to a table. */
@ -495,6 +480,41 @@ dict_table_get(
return(table);
}
/**************************************************************************
Returns a table object and increments MySQL open handle count on the table.
*/
dict_table_t*
dict_table_get_and_increment_handle_count(
/*======================================*/
/* out: table, NULL if does not exist */
char* table_name, /* in: table name */
trx_t* trx) /* in: transaction handle or NULL */
{
dict_table_t* table;
UT_NOT_USED(trx);
mutex_enter(&(dict_sys->mutex));
table = dict_table_get_low(table_name);
if (table != NULL) {
table->n_mysql_handles_opened++;
}
mutex_exit(&(dict_sys->mutex));
if (table != NULL) {
if (!table->stat_initialized) {
dict_update_statistics(table);
}
}
return(table);
}
/**************************************************************************
Adds a table object to the dictionary cache. */

View file

@ -1088,7 +1088,15 @@ loop:
node = UT_LIST_GET_FIRST(space->chain);
for (;;) {
ut_a(node);
if (node == NULL) {
fprintf(stderr,
"InnoDB: Error: trying to access page number %lu in space %lu\n"
"InnoDB: which is outside the tablespace bounds.\n"
"InnoDB: Byte offset %lu, len %lu, i/o type %lu\n",
block_offset, space_id, byte_offset, len, type);
ut_a(0);
}
if (node->size > block_offset) {
/* Found! */

View file

@ -26,13 +26,6 @@ Created 1/8/1996 Heikki Tuuri
#include "ut0byte.h"
#include "trx0types.h"
/************************************************************************
Increments the count of open MySQL handles to a table. */
void
dict_table_increment_handle_count(
/*==============================*/
dict_table_t* table); /* in: table */
/************************************************************************
Decrements the count of open MySQL handles to a table. */
@ -195,6 +188,16 @@ dict_table_get(
char* table_name, /* in: table name */
trx_t* trx); /* in: transaction handle */
/**************************************************************************
Returns a table object and increments MySQL open handle count on the table.
*/
dict_table_t*
dict_table_get_and_increment_handle_count(
/*======================================*/
/* out: table, NULL if does not exist */
char* table_name, /* in: table name */
trx_t* trx); /* in: transaction handle or NULL */
/**************************************************************************
Returns a table object, based on table id, and memoryfixes it. */
dict_table_t*

View file

@ -258,6 +258,7 @@ struct recv_sys_struct{
extern recv_sys_t* recv_sys;
extern ibool recv_recovery_on;
extern ibool recv_no_ibuf_operations;
extern ibool recv_needed_recovery;
/* States of recv_addr_struct */
#define RECV_NOT_PROCESSED 71

View file

@ -269,13 +269,24 @@ mem_realloc(
ulint n, /* in: desired number of bytes */
char* file_name,/* in: file name where called */
ulint line); /* in: line where called */
#ifdef MEM_PERIODIC_CHECK
/**********************************************************************
Goes through the list of all allocated mem blocks, checks their magic
numbers, and reports possible corruption. */
void
mem_validate_all_blocks(void);
/*=========================*/
#endif
/*#######################################################################*/
/* The info header of a block in a memory heap */
struct mem_block_info_struct {
ulint magic_n;/* magic number for debugging */
char file_name[8];/* file name where the mem heap was created */
ulint line; /* line number where the mem heap was created */
UT_LIST_BASE_NODE_T(mem_block_t) base; /* In the first block in the
the list this is the base node of the list of blocks;
in subsequent blocks this is undefined */
@ -299,9 +310,11 @@ struct mem_block_info_struct {
allocated buffer frame, which can be appended as a
free block to the heap, if we need more space;
otherwise, this is NULL */
ulint magic_n;/* magic number for debugging */
char file_name[8];/* file name where the mem heap was created */
ulint line; /* line number where the mem heap was created */
#ifdef MEM_PERIODIC_CHECK
UT_LIST_NODE_T(mem_block_t) mem_block_list;
/* List of all mem blocks allocated; protected
by the mem_comm_pool mutex */
#endif
};
#define MEM_BLOCK_MAGIC_N 764741555

View file

@ -72,6 +72,18 @@ mem_pool_get_reserved(
/* out: reserved mmeory in bytes */
mem_pool_t* pool); /* in: memory pool */
/************************************************************************
Reserves the mem pool mutex. */
void
mem_pool_mutex_enter(void);
/*======================*/
/************************************************************************
Releases the mem pool mutex. */
void
mem_pool_mutex_exit(void);
/*=====================*/
/************************************************************************
Validates a memory pool. */
ibool

View file

@ -251,6 +251,24 @@ row_table_add_foreign_constraints(
char* name); /* in: table full name in the normalized form
database_name/table_name */
/*************************************************************************
The master thread in srv0srv.c calls this regularly to drop tables which
we must drop in background after queries to them have ended. Such lazy
dropping of tables is needed in ALTER TABLE on Unix. */
ulint
row_drop_tables_for_mysql_in_background(void);
/*=========================================*/
/* out: how many tables dropped
+ remaining tables in list */
/*************************************************************************
Get the background drop list length. NOTE: the caller must own the kernel
mutex! */
ulint
row_get_background_drop_list_len_low(void);
/*======================================*/
/* out: how many tables in list */
/*************************************************************************
Drops a table for MySQL. If the name of the dropped table ends to
characters INNODB_MONITOR, then this also stops printing of monitor
output by the master thread. */
@ -426,7 +444,7 @@ struct row_prebuilt_struct {
fetched row in fetch_cache */
ulint n_fetch_cached; /* number of not yet fetched rows
in fetch_cache */
mem_heap_t* blob_heap; /* in SELECTS BLOB fields are copied
mem_heap_t* blob_heap; /* in SELECTS BLOB fie lds are copied
to this heap */
mem_heap_t* old_vers_heap; /* memory heap where a previous
version is built in consistent read */

View file

@ -250,6 +250,12 @@ mutex, for performace reasons). */
void
srv_active_wake_master_thread(void);
/*===============================*/
/***********************************************************************
Wakes up the master thread if it is suspended or being suspended. */
void
srv_wake_master_thread(void);
/*========================*/
/*************************************************************************
Puts an OS thread to wait if there are too many concurrent threads
(>= srv_thread_concurrency) inside InnoDB. The threads wait in a FIFO queue. */

View file

@ -50,6 +50,13 @@ trx_allocate_for_mysql(void);
/*========================*/
/* out, own: transaction object */
/************************************************************************
Creates a transaction object for background operations by the master thread. */
trx_t*
trx_allocate_for_background(void);
/*=============================*/
/* out, own: transaction object */
/************************************************************************
Frees a transaction object. */
void
@ -63,6 +70,13 @@ void
trx_free_for_mysql(
/*===============*/
trx_t* trx); /* in, own: trx object */
/************************************************************************
Frees a transaction object of a background operation of the master thread. */
void
trx_free_for_background(
/*====================*/
trx_t* trx); /* in, own: trx object */
/********************************************************************
Creates trx objects for transactions and initializes the trx list of
trx_sys at database start. Rollback segment and undo log lists must
@ -266,11 +280,14 @@ struct trx_sig_struct{
transaction is waiting a reply */
};
#define TRX_MAGIC_N 91118598
/* The transaction handle; every session has a trx object which is freed only
when the session is freed; in addition there may be session-less transactions
rolling back after a database recovery */
struct trx_struct{
ulint magic_n;
/* All the next fields are protected by the kernel mutex, except the
undo logs which are protected by undo_mutex */
char* op_info; /* English text describing the

View file

@ -1020,8 +1020,9 @@ loop:
if (recv_addr->state == RECV_NOT_PROCESSED) {
if (!has_printed) {
ut_print_timestamp(stderr);
fprintf(stderr,
"InnoDB: Starting an apply batch of log records to the database...\n"
" InnoDB: Starting an apply batch of log records to the database...\n"
"InnoDB: Progress in percents: ");
has_printed = TRUE;
}

View file

@ -75,6 +75,14 @@ After freeing, all the blocks in the heap are set to random bytes
to help us discover errors which result from the use of
buffers in an already freed heap. */
#ifdef MEM_PERIODIC_CHECK
ibool mem_block_list_inited;
/* List of all mem blocks allocated; protected by the mem_comm_pool mutex */
UT_LIST_BASE_NODE_T(mem_block_t) mem_block_list;
#endif
/*******************************************************************
NOTE: Use the corresponding macro instead of this function.
Allocates a single buffer of memory from the dynamic memory of
@ -169,7 +177,19 @@ mem_heap_create_block(
7);
block->file_name[7]='\0';
block->line = line;
#ifdef MEM_PERIODIC_CHECK
mem_pool_mutex_enter();
if (!mem_block_list_inited) {
mem_block_list_inited = TRUE;
UT_LIST_INIT(mem_block_list);
}
UT_LIST_ADD_LAST(mem_block_list, mem_block_list, block);
mem_pool_mutex_exit();
#endif
mem_block_set_len(block, len);
mem_block_set_type(block, type);
mem_block_set_free(block, MEM_BLOCK_HEADER_SIZE);
@ -261,6 +281,13 @@ mem_heap_block_free(
UT_LIST_REMOVE(list, heap->base, block);
#ifdef MEM_PERIODIC_CHECK
mem_pool_mutex_enter();
UT_LIST_REMOVE(mem_block_list, mem_block_list, block);
mem_pool_mutex_exit();
#endif
type = heap->type;
len = block->len;
init_block = block->init_block;
@ -306,3 +333,30 @@ mem_heap_free_block_free(
heap->free_block = NULL;
}
}
#ifdef MEM_PERIODIC_CHECK
/**********************************************************************
Goes through the list of all allocated mem blocks, checks their magic
numbers, and reports possible corruption. */
void
mem_validate_all_blocks(void)
/*=========================*/
{
mem_block_t* block;
mem_pool_mutex_enter();
block = UT_LIST_GET_FIRST(mem_block_list);
while (block) {
if (block->magic_n != MEM_BLOCK_MAGIC_N) {
mem_analyze_corruption((byte*)block);
}
block = UT_LIST_GET_NEXT(mem_block_list, block);
}
mem_pool_mutex_exit();
}
#endif

View file

@ -78,9 +78,9 @@ pool, and after that its locks will grow into the buffer pool. */
/* The smallest memory area total size */
#define MEM_AREA_MIN_SIZE (2 * MEM_AREA_EXTRA_SIZE)
/* Data structure for a memory pool. The space is allocated using the buddy
algorithm, where free list i contains areas of size 2 to power i. */
struct mem_pool_struct{
byte* buf; /* memory pool */
ulint size; /* memory common pool size */
@ -98,6 +98,26 @@ mem_pool_t* mem_comm_pool = NULL;
ulint mem_out_of_mem_err_msg_count = 0;
/************************************************************************
Reserves the mem pool mutex. */
void
mem_pool_mutex_enter(void)
/*======================*/
{
mutex_enter(&(mem_comm_pool->mutex));
}
/************************************************************************
Releases the mem pool mutex. */
void
mem_pool_mutex_exit(void)
/*=====================*/
{
mutex_exit(&(mem_comm_pool->mutex));
}
/************************************************************************
Returns memory area size. */
UNIV_INLINE
@ -240,15 +260,15 @@ mem_pool_fill_free_list(
if (mem_out_of_mem_err_msg_count % 1000000000 == 0) {
/* We do not print the message every time: */
ut_print_timestamp(stderr);
fprintf(stderr,
"Innobase: Warning: out of memory in additional memory pool.\n");
fprintf(stderr,
"Innobase: Innobase will start allocating memory from the OS.\n");
fprintf(stderr,
"Innobase: You should restart the database with a bigger value in\n");
fprintf(stderr,
"Innobase: the MySQL .cnf file for innobase_additional_mem_pool_size.\n");
" InnoDB: Out of memory in additional memory pool.\n"
"InnoDB: InnoDB will start allocating memory from the OS.\n"
"InnoDB: You may get better performance if you configure a bigger\n"
"InnoDB: value in the MySQL my.cnf file for\n"
"InnoDB: innodb_additional_mem_pool_size.\n");
}
mem_out_of_mem_err_msg_count++;

View file

@ -113,6 +113,16 @@ cmp_types_are_equal(
return(FALSE);
}
if (type1->mtype == DATA_INT
&& (type1->prtype & DATA_UNSIGNED)
!= (type2->prtype & DATA_UNSIGNED)) {
/* The storage format of an unsigned integer is different
from a signed integer: in a signed integer we OR
0x8000... to the value of positive integers. */
return(FALSE);
}
if (type1->mtype == DATA_MYSQL
|| type1->mtype == DATA_VARMYSQL) {

View file

@ -26,6 +26,19 @@ Created 9/17/2000 Heikki Tuuri
#include "trx0purge.h"
#include "lock0lock.h"
#include "rem0cmp.h"
#include "log0log.h"
/* List of tables we should drop in background. ALTER TABLE in MySQL requires
that the table handler can drop the table in background when there are no
queries to it any more. Protected by the kernel mutex. */
typedef struct row_mysql_drop_struct row_mysql_drop_t;
struct row_mysql_drop_struct{
char* table_name;
UT_LIST_NODE_T(row_mysql_drop_t) row_mysql_drop_list;
};
UT_LIST_BASE_NODE_T(row_mysql_drop_t) row_mysql_drop_list;
ibool row_mysql_drop_list_inited = FALSE;
/***********************************************************************
Reads a MySQL format variable-length field (like VARCHAR) length and
@ -172,10 +185,22 @@ handle_new_error:
trx_general_rollback_for_mysql(trx, TRUE, savept);
}
} else if (err == DB_TOO_BIG_RECORD) {
if (savept) {
/* Roll back the latest, possibly incomplete
insertion or update */
trx_general_rollback_for_mysql(trx, TRUE, savept);
}
/* MySQL will roll back the latest SQL statement */
} else if (err == DB_ROW_IS_REFERENCED
|| err == DB_NO_REFERENCED_ROW
|| err == DB_CANNOT_ADD_CONSTRAINT) {
if (savept) {
/* Roll back the latest, possibly incomplete
insertion or update */
trx_general_rollback_for_mysql(trx, TRUE, savept);
}
/* MySQL will roll back the latest SQL statement */
} else if (err == DB_LOCK_WAIT) {
@ -200,6 +225,12 @@ handle_new_error:
trx_general_rollback_for_mysql(trx, FALSE, NULL);
} else if (err == DB_OUT_OF_FILE_SPACE) {
if (savept) {
/* Roll back the latest, possibly incomplete
insertion or update */
trx_general_rollback_for_mysql(trx, TRUE, savept);
}
/* MySQL will roll back the latest SQL statement */
} else if (err == DB_MUST_GET_MORE_FILE_SPACE) {
@ -242,8 +273,6 @@ row_create_prebuilt(
ulint ref_len;
ulint i;
dict_table_increment_handle_count(table);
heap = mem_heap_create(128);
prebuilt = mem_heap_alloc(heap, sizeof(row_prebuilt_t));
@ -375,13 +404,13 @@ row_update_prebuilt_trx(
handle */
trx_t* trx) /* in: transaction handle */
{
if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED) {
if (trx->magic_n != TRX_MAGIC_N) {
fprintf(stderr,
"InnoDB: Error: trying to free a corrupt\n"
"InnoDB: table handle. Magic n %lu, table name %s\n",
prebuilt->magic_n, prebuilt->table->name);
"InnoDB: Error: trying to use a corrupt\n"
"InnoDB: trx handle. Magic n %lu\n",
trx->magic_n);
mem_analyze_corruption((byte*)prebuilt);
mem_analyze_corruption((byte*)trx);
ut_a(0);
}
@ -1172,8 +1201,11 @@ row_create_table_for_mysql(
row_drop_table_for_mysql(table->name, trx, TRUE);
} else {
ut_a(err == DB_DUPLICATE_KEY);
ut_print_timestamp(stderr);
fprintf(stderr,
"InnoDB: Error: table %s already exists in InnoDB internal\n"
" InnoDB: Error: table %s already exists in InnoDB internal\n"
"InnoDB: data dictionary. Have you deleted the .frm file\n"
"InnoDB: and not used DROP TABLE? Have you used DROP DATABASE\n"
"InnoDB: for InnoDB tables in MySQL version <= 3.23.43?\n"
@ -1351,6 +1383,177 @@ row_table_add_foreign_constraints(
return((int) err);
}
/*************************************************************************
Drops a table for MySQL as a background operation. MySQL relies on Unix
in ALTER TABLE to the fact that the table handler does not remove the
table before all handles to it has been removed. Furhermore, the MySQL's
call to drop table must be non-blocking. Therefore we do the drop table
as a background operation, which is taken care of by the master thread
in srv0srv.c. */
static
int
row_drop_table_for_mysql_in_background(
/*===================================*/
/* out: error code or DB_SUCCESS */
char* name) /* in: table name */
{
ulint error;
trx_t* trx;
trx = trx_allocate_for_background();
/* fprintf(stderr, "InnoDB: Dropping table %s in background drop list\n",
name); */
/* Drop the table in InnoDB */
error = row_drop_table_for_mysql(name, trx, FALSE);
if (error != DB_SUCCESS) {
fprintf(stderr,
"InnoDB: Error: Dropping table %s in background drop list failed\n",
name);
}
/* Flush the log to reduce probability that the .frm files and
the InnoDB data dictionary get out-of-sync if the user runs
with innodb_flush_log_at_trx_commit = 0 */
log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
trx_commit_for_mysql(trx);
trx_free_for_background(trx);
return(DB_SUCCESS);
}
/*************************************************************************
The master thread in srv0srv.c calls this regularly to drop tables which
we must drop in background after queries to them have ended. Such lazy
dropping of tables is needed in ALTER TABLE on Unix. */
ulint
row_drop_tables_for_mysql_in_background(void)
/*=========================================*/
/* out: how many tables dropped
+ remaining tables in list */
{
row_mysql_drop_t* drop;
dict_table_t* table;
ulint n_tables;
ulint n_tables_dropped = 0;
loop:
mutex_enter(&kernel_mutex);
if (!row_mysql_drop_list_inited) {
UT_LIST_INIT(row_mysql_drop_list);
row_mysql_drop_list_inited = TRUE;
}
drop = UT_LIST_GET_FIRST(row_mysql_drop_list);
n_tables = UT_LIST_GET_LEN(row_mysql_drop_list);
mutex_exit(&kernel_mutex);
if (drop == NULL) {
return(n_tables + n_tables_dropped);
}
mutex_enter(&(dict_sys->mutex));
table = dict_table_get_low(drop->table_name);
mutex_exit(&(dict_sys->mutex));
if (table == NULL) {
/* If for some reason the table has already been dropped
through some other mechanism, do not try to drop it */
goto already_dropped;
}
if (table->n_mysql_handles_opened > 0) {
return(n_tables + n_tables_dropped);
}
n_tables_dropped++;
row_drop_table_for_mysql_in_background(drop->table_name);
already_dropped:
mutex_enter(&kernel_mutex);
UT_LIST_REMOVE(row_mysql_drop_list, row_mysql_drop_list, drop);
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Dropped table %s in background drop queue.\n",
drop->table_name);
mem_free(drop->table_name);
mem_free(drop);
mutex_exit(&kernel_mutex);
goto loop;
}
/*************************************************************************
Get the background drop list length. NOTE: the caller must own the kernel
mutex! */
ulint
row_get_background_drop_list_len_low(void)
/*======================================*/
/* out: how many tables in list */
{
ut_ad(mutex_own(&kernel_mutex));
if (!row_mysql_drop_list_inited) {
UT_LIST_INIT(row_mysql_drop_list);
row_mysql_drop_list_inited = TRUE;
}
return(UT_LIST_GET_LEN(row_mysql_drop_list));
}
/*************************************************************************
Adds a table to the list of tables which the master thread drops in
background. We need this on Unix because in ALTER TABLE MySQL may call
drop table even if the table has running queries on it. */
static
void
row_add_table_to_background_drop_list(
/*==================================*/
dict_table_t* table) /* in: table */
{
row_mysql_drop_t* drop;
drop = mem_alloc(sizeof(row_mysql_drop_t));
drop->table_name = mem_alloc(1 + ut_strlen(table->name));
ut_memcpy(drop->table_name, table->name, 1 + ut_strlen(table->name));
mutex_enter(&kernel_mutex);
if (!row_mysql_drop_list_inited) {
UT_LIST_INIT(row_mysql_drop_list);
row_mysql_drop_list_inited = TRUE;
}
UT_LIST_ADD_LAST(row_mysql_drop_list, row_mysql_drop_list, drop);
/* fprintf(stderr, "InnoDB: Adding table %s to background drop list\n",
drop->table_name); */
mutex_exit(&kernel_mutex);
}
/*************************************************************************
Drops a table for MySQL. If the name of the dropped table ends to
characters INNODB_MONITOR, then this also stops printing of monitor
@ -1541,9 +1744,10 @@ row_drop_table_for_mysql(
if (!table) {
err = DB_TABLE_NOT_FOUND;
ut_print_timestamp(stderr);
fprintf(stderr,
"InnoDB: Error: table %s does not exist in the InnoDB internal\n"
" InnoDB: Error: table %s does not exist in the InnoDB internal\n"
"InnoDB: data dictionary though MySQL is trying to drop it.\n"
"InnoDB: Have you copied the .frm file of the table to the\n"
"InnoDB: MySQL database directory from another database?\n",
@ -1551,41 +1755,25 @@ row_drop_table_for_mysql(
goto funct_exit;
}
if (table->n_mysql_handles_opened > 0) {
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Warning: MySQL is trying to drop table %s\n"
"InnoDB: though there are still open handles to it.\n"
"InnoDB: Adding the table to the background drop queue.\n",
table->name);
row_add_table_to_background_drop_list(table);
err = DB_SUCCESS;
goto funct_exit;
}
/* Remove any locks there are on the table or its records */
lock_reset_all_on_table(table);
loop:
if (table->n_mysql_handles_opened > 0) {
rw_lock_s_unlock(&(purge_sys->purge_is_running));
rw_lock_x_unlock(&(dict_foreign_key_check_lock));
mutex_exit(&(dict_sys->mutex));
if (rounds > 60) {
fprintf(stderr,
"InnoDB: waiting for queries to table %s to end before dropping it\n",
name);
}
os_thread_sleep(1000000);
mutex_enter(&(dict_sys->mutex));
rw_lock_x_lock(&(dict_foreign_key_check_lock));
rw_lock_s_lock(&(purge_sys->purge_is_running));
rounds++;
if (rounds > 120) {
fprintf(stderr,
"InnoDB: Warning: queries to table %s have not ended but we continue anyway\n",
name);
} else {
goto loop;
}
}
trx->dict_operation = TRUE;
trx->table_id = table->id;
@ -1622,6 +1810,8 @@ funct_exit:
trx->op_info = (char *) "";
srv_wake_master_thread();
return((int) err);
}
@ -1635,6 +1825,7 @@ row_drop_database_for_mysql(
char* name, /* in: database name which ends to '/' */
trx_t* trx) /* in: transaction handle */
{
dict_table_t* table;
char* table_name;
int err = DB_SUCCESS;
@ -1645,12 +1836,35 @@ row_drop_database_for_mysql(
trx->op_info = (char *) "dropping database";
trx_start_if_not_started(trx);
loop:
mutex_enter(&(dict_sys->mutex));
while ((table_name = dict_get_first_table_name_in_db(name))) {
ut_a(memcmp(table_name, name, strlen(name)) == 0);
table = dict_table_get_low(table_name);
ut_a(table);
/* Wait until MySQL does not have any queries running on
the table */
if (table->n_mysql_handles_opened > 0) {
mutex_exit(&(dict_sys->mutex));
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Warning: MySQL is trying to drop database %s\n"
"InnoDB: though there are still open handles to table %s.\n",
name, table_name);
os_thread_sleep(1000000);
mem_free(table_name);
goto loop;
}
err = row_drop_table_for_mysql(table_name, trx, TRUE);
mem_free(table_name);
@ -1793,7 +2007,31 @@ row_rename_table_for_mysql(
err = trx->error_state;
if (err != DB_SUCCESS) {
row_mysql_handle_errors(&err, trx, thr, NULL);
if (err == DB_DUPLICATE_KEY) {
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Error: table %s exists in the InnoDB internal data\n"
"InnoDB: dictionary though MySQL is trying rename table %s to it.\n"
"InnoDB: Have you deleted the .frm file and not used DROP TABLE?\n",
new_name, old_name);
fprintf(stderr,
"InnoDB: If table %s is a temporary table #sql..., then it can be that\n"
"InnoDB: there are still queries running on the table, and it will be\n"
"InnoDB: dropped automatically when the queries end.\n", new_name);
fprintf(stderr,
"InnoDB: You can drop the orphaned table inside InnoDB by\n"
"InnoDB: creating an InnoDB table with the same name in another\n"
"InnoDB: database and moving the .frm file to the current database.\n"
"InnoDB: Then MySQL thinks the table exists, and DROP TABLE will\n"
"InnoDB: succeed.\n");
}
trx->error_state = DB_SUCCESS;
trx_general_rollback_for_mysql(trx, FALSE, NULL);
trx->error_state = DB_SUCCESS;
} else {
ut_a(dict_table_rename_in_cache(table, new_name));
}
@ -1950,7 +2188,7 @@ row_check_table_for_mysql(
ulint ret = DB_SUCCESS;
prebuilt->trx->op_info = (char *) "checking table";
index = dict_table_get_first_index(table);
while (index != NULL) {

View file

@ -20,7 +20,7 @@ Windows 2000 will have something called thread pooling
Another possibility could be to use some very fast user space
thread library. This might confuse NT though.
(c) 1995 InnoDB Oy
(c) 1995 Innobase Oy
Created 10/8/1995 Heikki Tuuri
*******************************************************/
@ -49,6 +49,7 @@ Created 10/8/1995 Heikki Tuuri
#include "btr0sea.h"
#include "dict0load.h"
#include "srv0start.h"
#include "row0mysql.h"
/* Buffer which can be used in printing fatal error messages */
char srv_fatal_errbuf[5000];
@ -91,8 +92,43 @@ ibool srv_log_archive_on = TRUE;
ulint srv_log_buffer_size = ULINT_MAX; /* size in database pages */
ibool srv_flush_log_at_trx_commit = TRUE;
byte srv_latin1_ordering[256]; /* The sort order table of the latin1
character set */
byte srv_latin1_ordering[256] /* The sort order table of the latin1
character set. The following table is
the MySQL order as of Feb 10th, 2002 */
= {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17
, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F
, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27
, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F
, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37
, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F
, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47
, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F
, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57
, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F
, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47
, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F
, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57
, 0x58, 0x59, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F
, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87
, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F
, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97
, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F
, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7
, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF
, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7
, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF
, 0x41, 0x41, 0x41, 0x41, 0x5C, 0x5B, 0x5C, 0x43
, 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49
, 0x44, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0x5D, 0xD7
, 0xD8, 0x55, 0x55, 0x55, 0x59, 0x59, 0xDE, 0xDF
, 0x41, 0x41, 0x41, 0x41, 0x5C, 0x5B, 0x5C, 0x43
, 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49
, 0x44, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0x5D, 0xF7
, 0xD8, 0x55, 0x55, 0x55, 0x59, 0x59, 0xDE, 0xFF
};
ibool srv_use_native_aio = FALSE;
@ -1920,17 +1956,12 @@ srv_boot(void)
srv_init();
/* Reserve the first slot for the current thread, i.e., the master
thread */
srv_table_reserve_slot(SRV_MASTER);
return(DB_SUCCESS);
}
/*************************************************************************
Reserves a slot in the thread table for the current MySQL OS thread.
NOTE! The server mutex has to be reserved by the caller! */
NOTE! The kernel mutex has to be reserved by the caller! */
static
srv_slot_t*
srv_table_reserve_slot_for_mysql(void)
@ -1940,6 +1971,8 @@ srv_table_reserve_slot_for_mysql(void)
srv_slot_t* slot;
ulint i;
ut_ad(mutex_own(&kernel_mutex));
i = 0;
slot = srv_mysql_table + i;
@ -2361,6 +2394,22 @@ srv_active_wake_master_thread(void)
}
}
/***********************************************************************
Wakes up the master thread if it is suspended or being suspended. */
void
srv_wake_master_thread(void)
/*========================*/
{
srv_activity_count++;
mutex_enter(&kernel_mutex);
srv_release_threads(SRV_MASTER, 1);
mutex_exit(&kernel_mutex);
}
/*************************************************************************
The master thread controlling the server. */
@ -2383,6 +2432,7 @@ srv_master_thread(
ulint n_bytes_merged;
ulint n_pages_flushed;
ulint n_bytes_archived;
ulint n_tables_to_drop;
ulint n_ios;
ulint n_ios_old;
ulint n_ios_very_old;
@ -2424,7 +2474,11 @@ loop:
can drop tables lazily after there no longer are SELECT
queries to them. */
/* row_drop_tables_for_mysql_in_background(); */
srv_main_thread_op_info = "doing background drop tables";
row_drop_tables_for_mysql_in_background();
srv_main_thread_op_info = "";
if (srv_force_recovery >= SRV_FORCE_NO_BACKGROUND) {
@ -2475,6 +2529,11 @@ loop:
printf("Master thread wakes up!\n");
}
#ifdef MEM_PERIODIC_CHECK
/* Check magic numbers of every allocated mem block once in 10
seconds */
mem_validate_all_blocks();
#endif
/* If there were less than 200 i/os during the 10 second period,
we assume that there is free disk i/o capacity available, and it
makes sense to do a buffer pool flush. */
@ -2531,6 +2590,12 @@ background_loop:
/* In this loop we run background operations when the server
is quiet and we also come here about once in 10 seconds */
srv_main_thread_op_info = "doing background drop tables";
n_tables_to_drop = row_drop_tables_for_mysql_in_background();
srv_main_thread_op_info = "";
srv_main_thread_op_info = "flushing buffer pool pages";
/* Flush a few oldest pages to make the checkpoint younger */
@ -2616,11 +2681,13 @@ background_loop:
log_archive_do(FALSE, &n_bytes_archived);
if (srv_fast_shutdown && srv_shutdown_state > 0) {
if (n_pages_flushed + n_bytes_archived != 0) {
if (n_tables_to_drop + n_pages_flushed
+ n_bytes_archived != 0) {
goto background_loop;
}
} else if (n_pages_purged + n_bytes_merged + n_pages_flushed
} else if (n_tables_to_drop +
n_pages_purged + n_bytes_merged + n_pages_flushed
+ n_bytes_archived != 0) {
goto background_loop;
}
@ -2639,6 +2706,12 @@ suspend_thread:
mutex_enter(&kernel_mutex);
if (row_get_background_drop_list_len_low() > 0) {
mutex_exit(&kernel_mutex);
goto loop;
}
event = srv_suspend_thread();
mutex_exit(&kernel_mutex);

View file

@ -271,13 +271,18 @@ open_or_create_log_file(
} else {
*log_file_created = TRUE;
ut_print_timestamp(stderr);
fprintf(stderr,
"InnoDB: Log file %s did not exist: new to be created\n",
" InnoDB: Log file %s did not exist: new to be created\n",
name);
fprintf(stderr, "InnoDB: Setting log file %s size to %lu MB\n",
name, srv_log_file_size
>> (20 - UNIV_PAGE_SIZE_SHIFT));
fprintf(stderr,
"InnoDB: Database physically writes the file full: wait...\n");
ret = os_file_set_size(name, files[i],
srv_calc_low32(srv_log_file_size),
srv_calc_high32(srv_log_file_size));
@ -456,8 +461,9 @@ open_or_create_data_files(
one_created = TRUE;
if (i > 0) {
ut_print_timestamp(stderr);
fprintf(stderr,
"InnoDB: Data file %s did not exist: new to be created\n",
" InnoDB: Data file %s did not exist: new to be created\n",
name);
} else {
fprintf(stderr,
@ -466,8 +472,9 @@ open_or_create_data_files(
*create_new_db = TRUE;
}
ut_print_timestamp(stderr);
fprintf(stderr,
"InnoDB: Setting file %s size to %lu MB\n",
" InnoDB: Setting file %s size to %lu MB\n",
name, (srv_data_file_sizes[i]
>> (20 - UNIV_PAGE_SIZE_SHIFT)));
@ -911,6 +918,12 @@ innobase_start_or_create_for_mysql(void)
mtr_commit(&mtr);
}
if (recv_needed_recovery) {
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Flushing modified pages from the buffer pool...\n");
}
log_make_checkpoint_at(ut_dulint_max, TRUE);
if (!srv_log_archive_on) {
@ -991,9 +1004,8 @@ innobase_shutdown_for_mysql(void)
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Warning: shutting down a not properly started\n");
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: or created database!\n");
" InnoDB: or created database!\n");
}
return(DB_SUCCESS);

View file

@ -226,9 +226,9 @@ trx_purge_sys_create(void)
value */
purge_sys->sess = sess_open(com_endpoint, (byte*)"purge_system", 13);
purge_sys->trx = (purge_sys->sess)->trx;
purge_sys->trx = purge_sys->sess->trx;
(purge_sys->trx)->type = TRX_PURGE;
purge_sys->trx->type = TRX_PURGE;
ut_a(trx_start_low(purge_sys->trx, ULINT_UNDEFINED));

View file

@ -26,9 +26,9 @@ Created 3/26/1996 Heikki Tuuri
/* Copy of the prototype for innobase_mysql_print_thd: this
copy must be equal to the one in mysql/sql/ha_innobase.cc ! */
void innobase_mysql_print_thd(void* thd);
copy must be equal to the one in mysql/sql/ha_innobase.cc ! */
void innobase_mysql_print_thd(void* thd);
/* Dummy session used currently in MySQL interface */
sess_t* trx_dummy_sess = NULL;
@ -64,6 +64,8 @@ trx_create(
trx = mem_alloc(sizeof(trx_t));
trx->magic_n = TRX_MAGIC_N;
trx->op_info = (char *) "";
trx->type = TRX_USER;
@ -157,6 +159,32 @@ trx_allocate_for_mysql(void)
return(trx);
}
/************************************************************************
Creates a transaction object for background operations by the master thread. */
trx_t*
trx_allocate_for_background(void)
/*=============================*/
/* out, own: transaction object */
{
trx_t* trx;
mutex_enter(&kernel_mutex);
/* Open a dummy session */
if (!trx_dummy_sess) {
trx_dummy_sess = sess_open(NULL, (byte*)"Dummy sess",
ut_strlen("Dummy sess"));
}
trx = trx_create(trx_dummy_sess);
mutex_exit(&kernel_mutex);
return(trx);
}
/************************************************************************
Releases the search latch if trx has reserved it. */
@ -181,6 +209,11 @@ trx_free(
trx_t* trx) /* in, own: trx object */
{
ut_ad(mutex_own(&kernel_mutex));
ut_a(trx->magic_n == TRX_MAGIC_N);
trx->magic_n = 11112222;
ut_a(trx->conc_state == TRX_NOT_STARTED);
mutex_free(&(trx->undo_mutex));
@ -242,6 +275,21 @@ trx_free_for_mysql(
mutex_exit(&kernel_mutex);
}
/************************************************************************
Frees a transaction object of a background operation of the master thread. */
void
trx_free_for_background(
/*====================*/
trx_t* trx) /* in, own: trx object */
{
mutex_enter(&kernel_mutex);
trx_free(trx);
mutex_exit(&kernel_mutex);
}
/********************************************************************
Inserts the trx handle in the trx system trx list in the right position.
The list is sorted on the trx id so that the biggest id is at the list

View file

@ -60,7 +60,7 @@ static my_bool mysql_client_init=0;
uint mysql_port=0;
my_string mysql_unix_port=0;
#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_LOCAL_FILES | CLIENT_TRANSACTIONS)
#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_TRANSACTIONS)
#ifdef __WIN__
#define CONNECT_TIMEOUT 20
@ -694,12 +694,14 @@ mysql_free_result(MYSQL_RES *result)
****************************************************************************/
static const char *default_options[]=
{"port","socket","compress","password","pipe", "timeout", "user",
"init-command", "host", "database", "debug", "return-found-rows",
"ssl-key" ,"ssl-cert" ,"ssl-ca" ,"ssl-capath", "ssl-cipher"
"character-set-dir", "default-character-set", "interactive-timeout",
"connect_timeout", "replication-probe", "enable-reads-from-master",
"repl-parse-query",
{
"port","socket","compress","password","pipe", "timeout", "user",
"init-command", "host", "database", "debug", "return-found-rows",
"ssl-key" ,"ssl-cert" ,"ssl-ca" ,"ssl-capath",
"character-set-dir", "default-character-set", "interactive-timeout",
"connect-timeout", "local-infile", "disable-local-infile",
"replication-probe", "enable-reads-from-master", "repl-parse-query",
"ssl-chiper",
NullS
};
@ -734,6 +736,9 @@ static void mysql_read_default_options(struct st_mysql_options *options,
opt_arg=end+1;
*end=0; /* Remove '=' */
}
/* Change all '_' in variable name to '-' */
for (end= *option ; (end= strcend(end,'_')) ; )
*end= '-';
switch (find_type(*option+2,&option_types,2)) {
case 1: /* port */
if (opt_arg)
@ -831,15 +836,24 @@ static void mysql_read_default_options(struct st_mysql_options *options,
options->charset_name = my_strdup(opt_arg, MYF(MY_WME));
break;
case 19: /* Interactive-timeout */
options->client_flag|=CLIENT_INTERACTIVE;
options->client_flag|= CLIENT_INTERACTIVE;
break;
case 21: /* replication probe */
case 21:
if (!opt_arg || atoi(opt_arg) != 0)
options->client_flag|= CLIENT_LOCAL_FILES;
else
options->client_flag&= ~CLIENT_LOCAL_FILES;
break;
case 22:
options->client_flag&= CLIENT_LOCAL_FILES;
break;
case 23: /* replication probe */
options->rpl_probe = 1;
break;
case 22: /* enable-reads-from-master */
case 24: /* enable-reads-from-master */
options->rpl_parse = 1;
break;
case 23: /* repl-parse-query */
case 25: /* repl-parse-query */
options->no_master_reads = 0;
break;
default:
@ -1321,6 +1335,14 @@ mysql_init(MYSQL *mysql)
if (!((mysql)->client_flag & CLIENT_IGNORE_SIGPIPE))
(void) signal(SIGPIPE,pipe_sig_handler);
#endif
/*
Only enable LOAD DATA INFILE by default if configured with
--with-enabled-local-inflile
*/
#ifdef ENABLED_LOCAL_INFILE
mysql->options.client_flag|= CLIENT_LOCAL_FILES;
#endif
return mysql;
}
@ -1770,7 +1792,6 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
if (mysql->options.use_ssl)
client_flag|=CLIENT_SSL;
#endif /* HAVE_OPENSSL */
if (db)
client_flag|=CLIENT_CONNECT_WITH_DB;
#ifdef HAVE_COMPRESS
@ -2714,11 +2735,17 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const char *arg)
mysql->options.connect_timeout= *(uint*) arg;
break;
case MYSQL_OPT_COMPRESS:
mysql->options.compress=1; /* Remember for connect */
mysql->options.compress= 1; /* Remember for connect */
break;
case MYSQL_OPT_NAMED_PIPE:
mysql->options.named_pipe=1; /* Force named pipe */
break;
case MYSQL_OPT_LOCAL_INFILE: /* Allow LOAD DATA LOCAL ?*/
if (!arg || test(*(uint*) arg))
mysql->options.client_flag|= CLIENT_LOCAL_FILES;
else
mysql->options.client_flag&= ~CLIENT_LOCAL_FILES;
break;
case MYSQL_INIT_COMMAND:
my_free(mysql->options.init_command,MYF(MY_ALLOW_ZERO_PTR));
mysql->options.init_command=my_strdup(arg,MYF(MY_WME));

View file

@ -121,8 +121,6 @@ void start_embedded_conn1(NET * net)
if (thd->max_join_size == HA_POS_ERROR)
thd->options |= OPTION_BIG_SELECTS;
if (thd->options & OPTION_ANSI_MODE)
thd->client_capabilities|=CLIENT_IGNORE_SPACE;
thd->proc_info=0; // Remove 'login'
thd->command=COM_SLEEP;

View file

@ -5,7 +5,7 @@ select 1 /* long
multi line comment */;
1
1
/* empty query */;
;
Query was empty
select 1 /*!32301 +1 */;
1 /*!32301 +1
@ -25,3 +25,4 @@ select 1 # The rest of the row will be ignored
;
1
1
/* line with only comment */;

View file

@ -168,9 +168,9 @@ Table Op Msg_type Msg_text
test.t1 optimize error The handler for the table doesn't support check/repair
show keys from t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
t1 0 PRIMARY 1 id A NULL NULL NULL BTREE
t1 1 parent_id 1 parent_id A NULL NULL NULL BTREE
t1 1 level 1 level A NULL NULL NULL BTREE
t1 0 PRIMARY 1 id A 87 NULL NULL BTREE
t1 1 parent_id 1 parent_id A 43 NULL NULL BTREE
t1 1 level 1 level A 8 NULL NULL BTREE
drop table t1;
CREATE TABLE t1 (
gesuchnr int(11) DEFAULT '0' NOT NULL,
@ -211,7 +211,7 @@ Table Op Msg_type Msg_text
test.t1 analyze error The handler for the table doesn't support check/repair
show keys from t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
t1 1 skr 1 a A NULL NULL NULL YES BTREE
t1 1 skr 1 a A 3 NULL NULL YES BTREE
drop table t1;
create table t1 (a int,b varchar(20),key(a)) type=innodb;
insert into t1 values (1,""), (2,"testing");
@ -727,7 +727,7 @@ Table Op Msg_type Msg_text
test.t1 optimize error The handler for the table doesn't support check/repair
show keys from t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
t1 0 PRIMARY 1 a A NULL NULL NULL BTREE
t1 0 PRIMARY 1 a A 2 NULL NULL BTREE
drop table t1;
create table t1 (i int, j int ) TYPE=innodb;
insert into t1 values (1,2);

View file

@ -186,3 +186,25 @@ t3.CanRead='1' AND t3.Active='1';
COUNT(t1.Title)
1
drop table t1,t2,t3;
CREATE TABLE t1 (
t1_id int(11) default NULL,
t2_id int(11) default NULL,
type enum('Cost','Percent') default NULL,
cost_unit enum('Cost','Unit') default NULL,
min_value double default NULL,
max_value double default NULL,
t3_id int(11) default NULL,
item_id int(11) default NULL
) TYPE=MyISAM;
INSERT INTO t1 VALUES (12,5,'Percent','Cost',-1,0,-1,-1),(14,4,'Percent','Cost',-1,0,-1,-1),(18,5,'Percent','Cost',-1,0,-1,-1),(19,4,'Percent','Cost',-1,0,-1,-1),(20,5,'Percent','Cost',100,-1,22,291),(21,5,'Percent','Cost',100,-1,18,291),(22,1,'Percent','Cost',100,-1,6,291),(23,1,'Percent','Cost',100,-1,21,291),(24,1,'Percent','Cost',100,-1,9,291),(25,1,'Percent','Cost',100,-1,4,291),(26,1,'Percent','Cost',100,-1,20,291),(27,4,'Percent','Cost',100,-1,7,202),(28,1,'Percent','Cost',50,-1,-1,137),(29,2,'Percent','Cost',100,-1,4,354),(30,2,'Percent','Cost',100,-1,9,137),(93,2,'Cost','Cost',-1,10000000,-1,-1);
CREATE TABLE t2 (
id int(10) unsigned NOT NULL auto_increment,
name varchar(255) default NULL,
PRIMARY KEY (id)
) TYPE=MyISAM;
INSERT INTO t2 VALUES (1,'s1'),(2,'s2'),(3,'s3'),(4,'s4'),(5,'s5');
select t1.*, t2.* from t1, t2 where t2.id=t1.t2_id limit 2;
t1_id t2_id type cost_unit min_value max_value t3_id item_id id name
22 1 Percent Cost 100 -1 6 291 1 s1
23 1 Percent Cost 100 -1 21 291 1 s1
drop table t1,t2;

View file

@ -5,7 +5,7 @@
select 1+2/*hello*/+3;
select 1 /* long
multi line comment */;
!$1065 /* empty query */;
!$1065 ;
select 1 /*!32301 +1 */;
select 1 /*!52301 +1 */;
select 1--1;
@ -15,3 +15,4 @@ select 1 --2
+1;
select 1 # The rest of the row will be ignored
;
/* line with only comment */;

View file

@ -194,3 +194,27 @@ t3.Contractor_ID = '999999' OR
t3.Contractor_ID = '1') AND
t3.CanRead='1' AND t3.Active='1';
drop table t1,t2,t3;
#
# Bug when doing full join and NULL fields.
#
CREATE TABLE t1 (
t1_id int(11) default NULL,
t2_id int(11) default NULL,
type enum('Cost','Percent') default NULL,
cost_unit enum('Cost','Unit') default NULL,
min_value double default NULL,
max_value double default NULL,
t3_id int(11) default NULL,
item_id int(11) default NULL
) TYPE=MyISAM;
INSERT INTO t1 VALUES (12,5,'Percent','Cost',-1,0,-1,-1),(14,4,'Percent','Cost',-1,0,-1,-1),(18,5,'Percent','Cost',-1,0,-1,-1),(19,4,'Percent','Cost',-1,0,-1,-1),(20,5,'Percent','Cost',100,-1,22,291),(21,5,'Percent','Cost',100,-1,18,291),(22,1,'Percent','Cost',100,-1,6,291),(23,1,'Percent','Cost',100,-1,21,291),(24,1,'Percent','Cost',100,-1,9,291),(25,1,'Percent','Cost',100,-1,4,291),(26,1,'Percent','Cost',100,-1,20,291),(27,4,'Percent','Cost',100,-1,7,202),(28,1,'Percent','Cost',50,-1,-1,137),(29,2,'Percent','Cost',100,-1,4,354),(30,2,'Percent','Cost',100,-1,9,137),(93,2,'Cost','Cost',-1,10000000,-1,-1);
CREATE TABLE t2 (
id int(10) unsigned NOT NULL auto_increment,
name varchar(255) default NULL,
PRIMARY KEY (id)
) TYPE=MyISAM;
INSERT INTO t2 VALUES (1,'s1'),(2,'s2'),(3,'s3'),(4,'s4'),(5,'s5');
select t1.*, t2.* from t1, t2 where t2.id=t1.t2_id limit 2;
drop table t1,t2;

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & InnoDB Oy
/* Copyright (C) 2000 MySQL AB & InnoDB Oy
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
@ -85,8 +85,8 @@ long innobase_mirrored_log_groups, innobase_log_files_in_group,
char *innobase_data_home_dir;
char *innobase_log_group_home_dir, *innobase_log_arch_dir;
char *innobase_unix_file_flush_method;
bool innobase_flush_log_at_trx_commit, innobase_log_archive,
innobase_use_native_aio, innobase_fast_shutdown;
my_bool innobase_flush_log_at_trx_commit, innobase_log_archive,
innobase_use_native_aio, innobase_fast_shutdown;
/*
Set default InnoDB size to 64M, to let users use InnoDB without having
@ -235,7 +235,7 @@ convert_error_code_to_mysql(
extern "C" {
/*****************************************************************
Prints info of a THD object (== user session thread) to the
standatd output. NOTE that mysql/innobase/trx/trx0trx.c must contain
standard output. NOTE that mysql/innobase/trx/trx0trx.c must contain
the prototype for this function! */
void
@ -304,6 +304,8 @@ check_trx_exists(
thd->transaction.stmt.innobase_tid =
(void*)&innodb_dummy_stmt_trx_handle;
} else {
ut_a(trx->magic_n == TRX_MAGIC_N);
}
return(trx);
@ -841,6 +843,7 @@ innobase_close_connection(
whose transaction should be rolled back */
{
if (NULL != thd->transaction.all.innobase_tid) {
trx_rollback_for_mysql((trx_t*)
(thd->transaction.all.innobase_tid));
trx_free_for_mysql((trx_t*)
@ -984,7 +987,10 @@ ha_innobase::open(
/* Get pointer to a table object in InnoDB dictionary cache */
if (NULL == (ib_table = dict_table_get(norm_name, NULL))) {
ib_table = dict_table_get_and_increment_handle_count(
norm_name, NULL);
if (NULL == ib_table) {
sql_print_error("InnoDB error:\n\
Cannot find table %s from the internal data dictionary\n\
@ -2465,44 +2471,6 @@ ha_innobase::position(
ref_stored_len = len;
}
/***********************************************************************
Tells something additional to the handler about how to do things. */
int
ha_innobase::extra(
/*===============*/
/* out: 0 or error number */
enum ha_extra_function operation)
/* in: HA_EXTRA_DONT_USE_CURSOR_TO_UPDATE */
{
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
switch (operation) {
case HA_EXTRA_RESET:
case HA_EXTRA_RESET_STATE:
prebuilt->read_just_key = 0;
break;
case HA_EXTRA_NO_KEYREAD:
prebuilt->read_just_key = 0;
break;
case HA_EXTRA_DONT_USE_CURSOR_TO_UPDATE:
prebuilt->in_update_remember_pos = FALSE;
break;
case HA_EXTRA_KEYREAD:
prebuilt->read_just_key = 1;
break;
default:/* Do nothing */
;
}
return(0);
}
int ha_innobase::reset(void)
{
return(0);
}
/*********************************************************************
Creates a table definition to an InnoDB database. */
@ -2866,7 +2834,9 @@ innobase_drop_database(
memcpy(namebuf, ptr, len);
namebuf[len] = '/';
namebuf[len + 1] = '\0';
#ifdef __WIN__
casedn_str(namebuf);
#endif
trx = trx_allocate_for_mysql();
error = row_drop_database_for_mysql(namebuf, trx);
@ -2981,9 +2951,9 @@ ha_innobase::records_in_range(
DBUG_ENTER("records_in_range");
if (prebuilt->trx) {
prebuilt->trx->op_info = (char*) "estimating range size";
}
/* Warning: since it is not sure that MySQL calls external_lock
before calling this function, the trx field in prebuilt can be
obsolete! */
active_index = keynr;
@ -3017,10 +2987,6 @@ ha_innobase::records_in_range(
my_free((char*) key_val_buff2, MYF(0));
if (prebuilt->trx) {
prebuilt->trx->op_info = (char*) "";
}
DBUG_RETURN((ha_rows) n_rows);
}
@ -3041,10 +3007,9 @@ ha_innobase::estimate_number_of_rows(void)
ulonglong estimate;
ulonglong data_file_length;
if (prebuilt->trx) {
prebuilt->trx->op_info =
(char*) "estimating upper bound of table size";
}
/* Warning: since it is not sure that MySQL calls external_lock
before calling this function, the trx field in prebuilt can be
obsolete! */
DBUG_ENTER("info");
@ -3061,10 +3026,6 @@ ha_innobase::estimate_number_of_rows(void)
estimate = 2 * data_file_length / dict_index_calc_min_rec_len(index);
if (prebuilt->trx) {
prebuilt->trx->op_info = (char*) "";
}
DBUG_RETURN((ha_rows) estimate);
}
@ -3080,10 +3041,12 @@ ha_innobase::scan_time()
{
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
/* In the following formula we assume that scanning 10 pages
takes the same time as a disk seek: */
return((double) (prebuilt->table->stat_clustered_index_size / 10));
/* Since MySQL seems to favor table scans too much over index
searches, we pretend that a sequential read takes the same time
as a random disk read, that is, we do not divide the following
by 10, which would be physically realistic. */
return((double) (prebuilt->table->stat_clustered_index_size));
}
/*************************************************************************
@ -3104,9 +3067,9 @@ ha_innobase::info(
DBUG_ENTER("info");
if (prebuilt->trx) {
prebuilt->trx->op_info = (char*) "calculating table stats";
}
/* Warning: since it is not sure that MySQL calls external_lock
before calling this function, the trx field in prebuilt can be
obsolete! */
ib_table = prebuilt->table;
@ -3154,25 +3117,17 @@ ha_innobase::info(
index->stat_n_diff_key_vals[j + 1]);
}
/* Since MySQL seems to favor table scans
too much over index searches, we pretend
index selectivity is 2 times better than
our estimate: */
rec_per_key = rec_per_key / 2;
if (rec_per_key == 0) {
rec_per_key = 1;
}
/* Since the MySQL optimizer is often too
pessimistic in the assumption that a table
does not fit in the buffer pool, we
increase the attractiveness of indexes
by assuming the selectivity of any prefix
of an index is 1 / 100 or better.
(Actually, we should look at the table
size, and if the table is smaller than
the buffer pool, we should uniformly
increase the attractiveness of indexes,
regardless of the estimated selectivity.) */
if (rec_per_key > records / 100) {
rec_per_key = records / 100;
}
table->key_info[i].rec_per_key[j]
= rec_per_key;
}
@ -3188,15 +3143,13 @@ ha_innobase::info(
pointer and cause a seg fault. */
if (flag & HA_STATUS_ERRKEY) {
ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N);
errkey = (unsigned int) row_get_mysql_key_number_for_index(
(dict_index_t*)
trx_get_error_info(prebuilt->trx));
}
if (prebuilt->trx) {
prebuilt->trx->op_info = (char*) "";
}
DBUG_VOID_RETURN;
}
@ -3217,6 +3170,8 @@ ha_innobase::check(
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
ulint ret;
ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N);
if (prebuilt->mysql_template == NULL) {
/* Build the template; we will use a dummy template
in index scans done in checking */
@ -3250,6 +3205,10 @@ ha_innobase::update_table_comment(
char* str = my_malloc(length + 550, MYF(0));
char* pos;
/* Warning: since it is not sure that MySQL calls external_lock
before calling this function, the trx field in prebuilt can be
obsolete! */
if (!str) {
return((char*)comment);
}
@ -3271,6 +3230,53 @@ ha_innobase::update_table_comment(
return(str);
}
/***********************************************************************
Tells something additional to the handler about how to do things. */
int
ha_innobase::extra(
/*===============*/
/* out: 0 or error number */
enum ha_extra_function operation)
/* in: HA_EXTRA_DONT_USE_CURSOR_TO_UPDATE */
{
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
/* Warning: since it is not sure that MySQL calls external_lock
before calling this function, the trx field in prebuilt can be
obsolete! */
switch (operation) {
case HA_EXTRA_RESET:
case HA_EXTRA_RESET_STATE:
prebuilt->read_just_key = 0;
break;
case HA_EXTRA_NO_KEYREAD:
prebuilt->read_just_key = 0;
break;
case HA_EXTRA_DONT_USE_CURSOR_TO_UPDATE:
prebuilt->in_update_remember_pos = FALSE;
break;
case HA_EXTRA_KEYREAD:
prebuilt->read_just_key = 1;
break;
default:/* Do nothing */
;
}
return(0);
}
/**********************************************************************
????????????? */
int
ha_innobase::reset(void)
/*====================*/
{
return(0);
}
/**********************************************************************
As MySQL will execute an external lock for every new table it uses when it
starts to process an SQL statement, we can use this function to store the
@ -3496,5 +3502,4 @@ ha_innobase::get_auto_increment()
return(nr);
}
#endif /* HAVE_INNOBASE_DB */

View file

@ -178,8 +178,9 @@ extern long innobase_force_recovery, innobase_thread_concurrency;
extern char *innobase_data_home_dir, *innobase_data_file_path;
extern char *innobase_log_group_home_dir, *innobase_log_arch_dir;
extern char *innobase_unix_file_flush_method;
extern bool innobase_flush_log_at_trx_commit, innobase_log_archive,
innobase_use_native_aio, innobase_fast_shutdown;
/* The following variables have to be my_bool for SHOW VARIABLES to work */
extern my_bool innobase_flush_log_at_trx_commit, innobase_log_archive,
innobase_use_native_aio, innobase_fast_shutdown;
extern TYPELIB innobase_lock_typelib;

View file

@ -222,28 +222,31 @@ int ha_autocommit_or_rollback(THD *thd, int error)
DBUG_RETURN(error);
}
/* This function is called when MySQL writes the log segment of a transaction
to the binlog. It is called when the LOCK_log mutex is reserved. Here we
communicate to transactional table handlers whta binlog position corresponds
to the current transaction. The handler can store it and in recovery print
to the user, so that the user knows from what position in the binlog to
start possible roll-forward, for example, if the crashed server was a slave
in replication. This function also calls the commit of the table handler,
because the order of trasnactions in the log of the table handler must be
the same as in the binlog. */
/*
This function is called when MySQL writes the log segment of a
transaction to the binlog. It is called when the LOCK_log mutex is
reserved. Here we communicate to transactional table handlers whta
binlog position corresponds to the current transaction. The handler
can store it and in recovery print to the user, so that the user
knows from what position in the binlog to start possible
roll-forward, for example, if the crashed server was a slave in
replication. This function also calls the commit of the table
handler, because the order of trasnactions in the log of the table
handler must be the same as in the binlog.
int ha_report_binlog_offset_and_commit(
THD *thd, /* in: user thread */
char *log_file_name, /* in: latest binlog file name */
my_off_t end_offset) /* in: the offset in the binlog file
up to which we wrote */
arguments:
log_file_name: latest binlog file name
end_offset: the offset in the binlog file up to which we wrote
*/
int ha_report_binlog_offset_and_commit(THD *thd,
char *log_file_name,
my_off_t end_offset)
{
THD_TRANS *trans;
int error = 0;
trans = &thd->transaction.all;
int error= 0;
#ifdef HAVE_INNOBASE_DB
THD_TRANS *trans;
trans = &thd->transaction.all;
if (trans->innobase_tid)
{
if ((error=innobase_report_binlog_offset_and_commit(thd,
@ -257,10 +260,10 @@ int ha_report_binlog_offset_and_commit(
trans->innodb_active_trans=0;
}
#endif
return error;
}
int ha_commit_trans(THD *thd, THD_TRANS* trans)
{
int error=0;

View file

@ -26,10 +26,6 @@
#include <thr_alarm.h>
#include <errno.h>
#ifdef HAVE_FCNTL
static struct flock lock; /* Must be static for sun-sparc */
#endif
/* Lock a part of a file */
int my_lock(File fd,int locktype,my_off_t start,my_off_t length,myf MyFlags)
@ -37,24 +33,25 @@ int my_lock(File fd,int locktype,my_off_t start,my_off_t length,myf MyFlags)
thr_alarm_t alarmed;
ALARM alarm_buff;
uint wait_for_alarm;
struct flock m_lock;
DBUG_ENTER("my_lock");
DBUG_PRINT("my",("Fd: %d Op: %d start: %ld Length: %ld MyFlags: %d",
fd,locktype,(ulong) start,(ulong) length,MyFlags));
if (my_disable_locking)
DBUG_RETURN(0); /* purecov: inspected */
lock.l_type=(short) locktype;
lock.l_whence=0L;
lock.l_start=(long) start;
lock.l_len=(long) length;
m_lock.l_type=(short) locktype;
m_lock.l_whence=0L;
m_lock.l_start=(long) start;
m_lock.l_len=(long) length;
wait_for_alarm=(MyFlags & MY_DONT_WAIT ? MY_HOW_OFTEN_TO_ALARM :
(uint) 12*60*60);
if (fcntl(fd,F_SETLK,&lock) != -1) /* Check if we can lock */
if (fcntl(fd,F_SETLK,&m_lock) != -1) /* Check if we can lock */
DBUG_RETURN(0); /* Ok, file locked */
DBUG_PRINT("info",("Was locked, trying with alarm"));
if (!thr_alarm(&alarmed,wait_for_alarm,&alarm_buff))
{
int value;
while ((value=fcntl(fd,F_SETLKW,&lock)) && !thr_got_alarm(&alarmed) &&
while ((value=fcntl(fd,F_SETLKW,&m_lock)) && !thr_got_alarm(&alarmed) &&
errno == EINTR) ;
thr_end_alarm(&alarmed);
if (value != -1)

View file

@ -160,8 +160,8 @@ char* query_table_status(THD *thd,const char *db,const char *table_name);
#define OPTION_LOW_PRIORITY_UPDATES 8192
#define OPTION_WARNINGS 16384
#define OPTION_AUTO_IS_NULL 32768
#define OPTION_ANSI_MODE 65536L
#define OPTION_SAFE_UPDATES OPTION_ANSI_MODE*2
#define OPTION_FOUND_COMMENT 65536L
#define OPTION_SAFE_UPDATES OPTION_FOUND_COMMENT*2
#define OPTION_BUFFER_RESULT OPTION_SAFE_UPDATES*2
#define OPTION_BIN_LOG OPTION_BUFFER_RESULT*2
#define OPTION_NOT_AUTO_COMMIT OPTION_BIN_LOG*2
@ -181,7 +181,7 @@ char* query_table_status(THD *thd,const char *db,const char *table_name);
#define SELECT_NO_UNLOCK (QUERY_NO_GOOD_INDEX_USED*2)
#define TMP_TABLE_ALL_COLUMNS (SELECT_NO_UNLOCK*2)
/* Bits for different SQL modes modes (including ANSI mode) */
#define MODE_REAL_AS_FLOAT 1
#define MODE_PIPES_AS_CONCAT 2
#define MODE_ANSI_QUOTES 4
@ -583,6 +583,7 @@ extern pthread_cond_t COND_refresh,COND_thread_count;
extern pthread_attr_t connection_attrib;
extern bool opt_endinfo, using_udf_functions, locked_in_memory,
opt_using_transactions, use_temp_pool, mysql_embedded;
extern bool opt_local_infile;
extern char f_fyllchar;
extern ulong ha_read_count, ha_write_count, ha_delete_count, ha_update_count,
ha_read_key_count, ha_read_next_count, ha_read_prev_count,

View file

@ -297,6 +297,7 @@ ulong bytes_sent = 0L, bytes_received = 0L;
bool opt_endinfo,using_udf_functions,low_priority_updates, locked_in_memory;
bool opt_using_transactions, using_update_log, opt_warnings=0;
bool opt_local_infile=1;
bool volatile abort_loop,select_thread_in_use,grant_option;
bool volatile ready_to_exit,shutdown_in_progress;
ulong refresh_version=1L,flush_version=1L; /* Increments on each reload */
@ -708,8 +709,9 @@ static pthread_handler_decl(kill_server_thread,arg __attribute__((unused)))
static sig_handler print_signal_warning(int sig)
{
sql_print_error("Warning: Got signal %d from thread %d",
sig,my_thread_id());
if (opt_warnings)
sql_print_error("Warning: Got signal %d from thread %d",
sig,my_thread_id());
#ifdef DONT_REMEMBER_SIGNAL
sigset(sig,print_signal_warning); /* int. thread system calls */
#endif
@ -856,20 +858,33 @@ static void set_user(const char *user)
if (!strcmp(user,"root"))
return; // Avoid problem with dynamic libraries
uid_t uid;
if (!(ent = getpwnam(user)))
{
fprintf(stderr,"Fatal error: Can't change to run as user '%s' ; Please check that the user exists!\n",user);
unireg_abort(1);
// allow a numeric uid to be used
const char *pos;
for (pos=user; isdigit(*pos); pos++) ;
if (*pos) // Not numeric id
{
fprintf(stderr,"Fatal error: Can't change to run as user '%s' ; Please check that the user exists!\n",user);
unireg_abort(1);
}
uid=atoi(user); // Use numberic uid
}
#ifdef HAVE_INITGROUPS
initgroups((char*) user,ent->pw_gid);
#endif
if (setgid(ent->pw_gid) == -1)
else
{
sql_perror("setgid");
unireg_abort(1);
#ifdef HAVE_INITGROUPS
initgroups((char*) user,ent->pw_gid);
#endif
if (setgid(ent->pw_gid) == -1)
{
sql_perror("setgid");
unireg_abort(1);
}
uid=ent->pw_uid;
}
if (setuid(ent->pw_uid) == -1)
if (setuid(uid) == -1)
{
sql_perror("setuid");
unireg_abort(1);
@ -2673,7 +2688,7 @@ enum options {
OPT_SLAVE_LOAD_TMPDIR, OPT_NO_MIX_TYPE,
OPT_RPL_RECOVERY_RANK,OPT_INIT_RPL_ROLE,
OPT_RELAY_LOG, OPT_RELAY_LOG_INDEX, OPT_RELAY_LOG_INFO_FILE,
OPT_SLAVE_SKIP_ERRORS, OPT_DES_KEY_FILE
OPT_SLAVE_SKIP_ERRORS, OPT_DES_KEY_FILE, OPT_LOCAL_INFILE
};
static struct option long_options[] = {
@ -2735,6 +2750,7 @@ static struct option long_options[] = {
{"init-file", required_argument, 0, (int) OPT_INIT_FILE},
{"log", optional_argument, 0, 'l'},
{"language", required_argument, 0, 'L'},
{"local-infile", optional_argument, 0, (int) OPT_LOCAL_INFILE},
{"log-bin", optional_argument, 0, (int) OPT_BIN_LOG},
{"log-bin-index", required_argument, 0, (int) OPT_BIN_LOG_INDEX},
{"log-isam", optional_argument, 0, (int) OPT_ISAM_LOG},
@ -3309,10 +3325,11 @@ static void use_help(void)
static void usage(void)
{
print_version();
puts("Copyright (C) 2000 MySQL AB & MySQL Finland AB, by Monty and others");
puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,");
puts("and you are welcome to modify and redistribute it under the GPL license\n");
puts("Starts the MySQL server\n");
puts("\
Copyright (C) 2000 MySQL AB, by Monty and others\n\
This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n\
and you are welcome to modify and redistribute it under the GPL license\n\
Starts the MySQL server\n");
printf("Usage: %s [OPTIONS]\n", my_progname);
puts("\n\
@ -3601,6 +3618,9 @@ static void get_options(int argc,char **argv)
case 'P':
mysql_port= (unsigned int) atoi(optarg);
break;
case OPT_LOCAL_INFILE:
opt_local_infile= test(!optarg || atoi(optarg) != 0);
break;
case OPT_SLAVE_SKIP_ERRORS:
init_slave_skip_errors(optarg);
break;

View file

@ -768,6 +768,7 @@ int yylex(void *arg)
return(TEXT_STRING);
case STATE_COMMENT: // Comment
lex->select_lex.options|= OPTION_FOUND_COMMENT;
while ((c = yyGet()) != '\n' && c) ;
yyUnget(); // Safety against eof
state = STATE_START; // Try again
@ -779,6 +780,7 @@ int yylex(void *arg)
break;
}
yySkip(); // Skip '*'
lex->select_lex.options|= OPTION_FOUND_COMMENT;
if (yyPeek() == '!') // MySQL command in comment
{
ulong version=MYSQL_VERSION_ID;

View file

@ -57,6 +57,7 @@ enum enum_sql_command {
SQLCOM_HA_OPEN, SQLCOM_HA_CLOSE, SQLCOM_HA_READ,
SQLCOM_SHOW_SLAVE_HOSTS, SQLCOM_DELETE_MULTI, SQLCOM_MULTI_UPDATE,
SQLCOM_SHOW_BINLOG_EVENTS, SQLCOM_SHOW_NEW_MASTER, SQLCOM_DO,
SQLCOM_EMPTY_QUERY,
SQLCOM_END
};

View file

@ -145,7 +145,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
if (read_file_from_client && handle_duplicates == DUP_ERROR)
handle_duplicates=DUP_IGNORE;
if (read_file_from_client && (thd->client_capabilities & CLIENT_LOCAL_FILES))
if (read_file_from_client)
{
(void)net_request_file(&thd->net,ex->file_name);
file = -1;

View file

@ -120,8 +120,9 @@ inline bool end_active_trans(THD *thd)
static HASH hash_user_connections;
extern pthread_mutex_t LOCK_user_conn;
static int get_or_create_user_conn(THD *thd, const char *user, const char *host,
uint max_questions)
static int get_or_create_user_conn(THD *thd, const char *user,
const char *host,
uint max_questions)
{
int return_val=0;
uint temp_len;
@ -134,19 +135,18 @@ static int get_or_create_user_conn(THD *thd, const char *user, const char *host,
temp_len= (uint) (strxnmov(temp_user, sizeof(temp_user)-1, user, "@", host,
NullS) - temp_user);
(void) pthread_mutex_lock(&LOCK_user_conn);
uc = (struct user_conn *) hash_search(&hash_user_connections,
(byte*) temp_user, temp_len);
if (!uc)
if (!(uc = (struct user_conn *) hash_search(&hash_user_connections,
(byte*) temp_user, temp_len)))
{
uc= ((struct user_conn*)
my_malloc(sizeof(struct user_conn) + temp_len+1,
MYF(MY_WME)));
if (!uc)
/* First connection for user; Create a user connection object */
if (!(uc= ((struct user_conn*)
my_malloc(sizeof(struct user_conn) + temp_len+1,
MYF(MY_WME)))))
{
send_error(&current_thd->net, 0, NullS); // Out of memory
return_val=1;
goto end;
}
}
uc->user=(char*) (uc+1);
memcpy(uc->user,temp_user,temp_len+1);
uc->len = temp_len;
@ -279,9 +279,6 @@ static int check_for_max_user_connections(UC *uc)
{
int error=0;
DBUG_ENTER("check_for_max_user_connections");
// DBUG_PRINT("enter",("user: '%s' host: '%s'", user, host));
DBUG_ASSERT(uc != 0);
if (max_user_connections <= (uint) uc->connections)
{
@ -302,8 +299,6 @@ static void decrease_user_connections(UC *uc)
return;
DBUG_ENTER("decrease_user_connections");
DBUG_ASSERT(uc != 0);
// DBUG_PRINT("enter",("user: '%s' host: '%s'", user, host));
if (!--uc->connections && !mqh_used)
{
@ -325,6 +320,10 @@ void free_max_user_conn(void)
/*
Check if maximum queries per hour limit has been reached
returns 0 if OK.
In theory we would need a mutex in the UC structure for this to be 100 %
safe, but as the worst scenario is that we would miss counting a couple of
queries, this isn't critical.
*/
static bool check_mqh(THD *thd)
@ -334,15 +333,14 @@ static bool check_mqh(THD *thd)
UC *uc=thd->user_connect;
DBUG_ASSERT(uc != 0);
/* TODO: Add username + host to THD for faster execution */
bool my_start = thd->start_time != 0;
time_t check_time = (my_start) ? thd->start_time : time(NULL);
if (check_time - uc->intime >= 3600)
{
// (void) pthread_mutex_lock(&LOCK_user_conn);
uc->questions=(uint) my_start;
(void) pthread_mutex_lock(&LOCK_user_conn);
uc->questions=1;
uc->intime=check_time;
// (void) pthread_mutex_unlock(&LOCK_user_conn);
(void) pthread_mutex_unlock(&LOCK_user_conn);
}
else if (uc->max_questions && ++(uc->questions) > uc->max_questions)
{
@ -356,27 +354,22 @@ end:
DBUG_RETURN(error);
}
static void reset_mqh(THD *thd,LEX_USER *lu, uint mq)
{
char user[USERNAME_LENGTH+1];
char host[USERNAME_LENGTH+1];
char *where;
static void reset_mqh(THD *thd, LEX_USER *lu, uint mq)
{
(void) pthread_mutex_lock(&LOCK_user_conn);
if (lu) // for GRANT
{
UC *uc;
uint temp_len;
uint temp_len=lu->user.length+lu->host.length+2;
char temp_user[USERNAME_LENGTH+HOSTNAME_LENGTH+2];
memcpy(user,lu->user.str,lu->user.length);
user[lu->user.length]='\0';
memcpy(host,lu->host.str,lu->host.length);
host[lu->host.length]='\0';
temp_len= (uint) (strxnmov(temp_user, sizeof(temp_user)-1, user, "@", host,
NullS) - temp_user);
uc = (struct user_conn *) hash_search(&hash_user_connections,
(byte*) temp_user, temp_len);
if (uc)
memcpy(temp_user,lu->user.str,lu->user.length);
memcpy(temp_user+lu->user.length+1,lu->host.str,lu->host.length);
temp_user[lu->user.length]=temp_user[temp_len-1]=0;
if ((uc = (struct user_conn *) hash_search(&hash_user_connections,
(byte*) temp_user, temp_len)))
{
uc->questions=0;
uc->max_questions=mq;
@ -384,21 +377,20 @@ static void reset_mqh(THD *thd,LEX_USER *lu, uint mq)
}
else // for FLUSH PRIVILEGES
{
(void) pthread_mutex_lock(&LOCK_user_conn);
for (uint idx=0;idx<hash_user_connections.records;idx++)
for (uint idx=0;idx < hash_user_connections.records; idx++)
{
HASH_LINK *data=dynamic_element(&hash_user_connections.array,idx,HASH_LINK*);
UC *uc=(struct user_conn *)data->data;
char user[USERNAME_LENGTH+1];
char *where;
UC *uc=(struct user_conn *) hash_element(&hash_user_connections, idx);
where=strchr(uc->user,'@');
memcpy(user,uc->user,where - uc->user);
user[where-uc->user]='\0'; where++;
strcpy(host,where);
uc->max_questions=get_mqh(user,host);
strmake(user,uc->user,where - uc->user);
uc->max_questions=get_mqh(user,where+1);
}
(void) pthread_mutex_unlock(&LOCK_user_conn);
}
(void) pthread_mutex_unlock(&LOCK_user_conn);
}
/*
Check connnetion and get priviliges
Returns 0 on ok, -1 < if error is given > 0 on error.
@ -833,8 +825,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
{
NET *net= &thd->net;
bool error=0;
// commands which will always take a long time should be marked with
// this so that they will not get logged to the slow query log
/*
Commands which will always take a long time should be marked with
this so that they will not get logged to the slow query log
*/
bool slow_command=FALSE;
DBUG_ENTER("dispatch_command");
@ -912,7 +906,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break;
}
if (max_connections && save_uc)
decrease_user_connections (save_uc);
decrease_user_connections(save_uc);
x_free((gptr) save_db);
x_free((gptr) save_user);
thd->password=test(passwd[0]);
@ -947,8 +941,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
DBUG_PRINT("query",("%s",thd->query));
if (thd->user_connect && check_mqh(thd))
{
error = TRUE;
net->error = 0;
error = TRUE; // Abort client
net->error = 0; // Don't give abort message
break;
}
/* thd->query_length is set by mysql_parse() */
@ -1071,11 +1065,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
else
send_eof(net);
if (mqh_used)
{
if (hash_user_connections.array.buffer == 0)
init_max_user_conn();
reset_mqh(thd,(LEX_USER *)NULL,0);
}
reset_mqh(thd,(LEX_USER *) NULL, 0);
break;
}
case COM_SHUTDOWN:
@ -1321,6 +1311,10 @@ mysql_execute_command(void)
res=mysql_do(thd, *lex->insert_list);
break;
case SQLCOM_EMPTY_QUERY:
send_ok(&thd->net);
break;
case SQLCOM_PURGE:
{
if (check_process_priv(thd))
@ -2103,13 +2097,20 @@ mysql_execute_command(void)
{
uint privilege= (lex->duplicates == DUP_REPLACE ?
INSERT_ACL | UPDATE_ACL | DELETE_ACL : INSERT_ACL);
if (!(lex->local_file && (thd->client_capabilities & CLIENT_LOCAL_FILES)))
if (!lex->local_file)
{
if (check_access(thd,privilege | FILE_ACL,tables->db))
goto error;
}
else
{
if (!(thd->client_capabilities & CLIENT_LOCAL_FILES) ||
! opt_local_infile)
{
send_error(&thd->net,ER_NOT_ALLOWED_COMMAND);
goto error;
}
if (check_access(thd,privilege,tables->db,&tables->grant.privilege) ||
grant_option && check_grant(thd,privilege,tables))
goto error;
@ -2305,17 +2306,12 @@ mysql_execute_command(void)
Query_log_event qinfo(thd, thd->query);
mysql_bin_log.write(&qinfo);
}
if (mqh_used)
if (mqh_used && lex->mqh)
{
if (hash_user_connections.array.buffer == 0)
init_max_user_conn();
if (lex->mqh)
{
List_iterator <LEX_USER> str_list (lex->users_list);
LEX_USER *Str;
str_list.rewind();
reset_mqh(thd,str_list++,lex->mqh);
}
List_iterator <LEX_USER> str_list(lex->users_list);
LEX_USER *user;
while ((user=str_list++))
reset_mqh(thd,user,lex->mqh);
}
}
}

View file

@ -144,7 +144,7 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab);
static void init_sum_functions(Item_sum **func);
static bool update_sum_func(Item_sum **func);
static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
bool distinct);
bool distinct, const char *message=NullS);
static void describe_info(THD *thd, const char *info);
/*
@ -195,6 +195,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
Procedure *procedure;
List<Item> all_fields(fields);
bool select_distinct;
SELECT_LEX *select_lex = &(thd->lex.select_lex);
DBUG_ENTER("mysql_select");
/* Check that all tables, fields, conds and order are ok */
@ -350,10 +351,13 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
}
if (cond_value == Item::COND_FALSE || !thd->select_limit)
{ /* Impossible cond */
error=return_zero_rows(result, tables, fields,
join.tmp_table_param.sum_func_count != 0 && !group,
select_options,"Impossible WHERE",having,
procedure);
if (select_options & SELECT_DESCRIBE && select_lex->next)
select_describe(&join,false,false,false,"Impossible WHERE");
else
error=return_zero_rows(result, tables, fields,
join.tmp_table_param.sum_func_count != 0 && !group,
select_options,"Impossible WHERE",having,
procedure);
delete procedure;
DBUG_RETURN(error);
}
@ -366,17 +370,23 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
{
if (res < 0)
{
error=return_zero_rows(result, tables, fields, !group,
select_options,"No matching min/max row",
having,procedure);
if (select_options & SELECT_DESCRIBE && select_lex->next)
select_describe(&join,false,false,false,"No matching min/max row");
else
error=return_zero_rows(result, tables, fields, !group,
select_options,"No matching min/max row",
having,procedure);
delete procedure;
DBUG_RETURN(error);
}
if (select_options & SELECT_DESCRIBE)
{
describe_info(thd,"Select tables optimized away");
if (select_lex->next)
select_describe(&join,false,false,false,"Select tables optimized away");
else
describe_info(thd,"Select tables optimized away");
delete procedure;
DBUG_RETURN(0);
DBUG_RETURN(error);
}
tables=0; // All tables resolved
}
@ -385,7 +395,12 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
{ // Only test of functions
error=0;
if (select_options & SELECT_DESCRIBE)
describe_info(thd,"No tables used");
{
if (select_lex->next)
select_describe(&join,false,false,false,"No tables used");
else
describe_info(thd,"No tables used");
}
else
{
result->send_fields(fields,1);
@ -463,11 +478,14 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
}
if (make_join_select(&join,select,conds))
{
error=return_zero_rows(result,tables,fields,
join.tmp_table_param.sum_func_count != 0 && !group,
select_options,
"Impossible WHERE noticed after reading const tables",
having,procedure);
if (select_options & SELECT_DESCRIBE && select_lex->next)
select_describe(&join,false,false,false,"Impossible WHERE noticed after reading const tables");
else
error=return_zero_rows(result,tables,fields,
join.tmp_table_param.sum_func_count != 0 && !group,
select_options,
"Impossible WHERE noticed after reading const tables",
having,procedure);
goto err;
}
@ -535,7 +553,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
make_join_readinfo(&join,
(select_options & (SELECT_DESCRIBE |
SELECT_NO_JOIN_CACHE)) |
(thd->lex.select_lex.ftfunc_list.elements ? SELECT_NO_JOIN_CACHE : 0));
(select_lex->ftfunc_list.elements ? SELECT_NO_JOIN_CACHE : 0));
/* Need to tell Innobase that to play it safe, it should fetch all
columns of the tables: this is because MySQL
@ -2516,6 +2534,7 @@ static void
make_join_readinfo(JOIN *join,uint options)
{
uint i;
SELECT_LEX *select_lex = &(join->thd->lex.select_lex);
DBUG_ENTER("make_join_readinfo");
for (i=join->const_tables ; i < join->tables ; i++)
@ -2598,7 +2617,7 @@ make_join_readinfo(JOIN *join,uint options)
/* These init changes read_record */
if (tab->use_quick == 2)
{
join->thd->lex.select_lex.options|=QUERY_NO_GOOD_INDEX_USED;
select_lex->options|=QUERY_NO_GOOD_INDEX_USED;
tab->read_first_record= join_init_quick_read_record;
statistic_increment(select_range_check_count, &LOCK_status);
}
@ -2613,7 +2632,7 @@ make_join_readinfo(JOIN *join,uint options)
}
else
{
join->thd->lex.select_lex.options|=QUERY_NO_INDEX_USED;
select_lex->options|=QUERY_NO_INDEX_USED;
statistic_increment(select_scan_count, &LOCK_status);
}
}
@ -2625,7 +2644,7 @@ make_join_readinfo(JOIN *join,uint options)
}
else
{
join->thd->lex.select_lex.options|=QUERY_NO_INDEX_USED;
select_lex->options|=QUERY_NO_INDEX_USED;
statistic_increment(select_full_join_count, &LOCK_status);
}
}
@ -2913,7 +2932,7 @@ return_zero_rows(select_result *result,TABLE_LIST *tables,List<Item> &fields,
DBUG_ENTER("return_zero_rows");
if (select_options & SELECT_DESCRIBE)
{
{
describe_info(current_thd, info);
DBUG_RETURN(0);
}
@ -5962,10 +5981,10 @@ SORT_FIELD *make_unireg_sortorder(ORDER *order, uint *length)
/*****************************************************************************
** Fill join cache with packed records
** Records are stored in tab->cache.buffer and last record in
** last record is stored with pointers to blobs to support very big
** records
Fill join cache with packed records
Records are stored in tab->cache.buffer and last record in
last record is stored with pointers to blobs to support very big
records
******************************************************************************/
static int
@ -6027,7 +6046,7 @@ join_init_cache(THD *thd,JOIN_TAB *tables,uint table_count)
if (null_fields && tables[i].table->null_fields)
{ /* must copy null bits */
copy->str=(char*) tables[i].table->null_flags;
copy->length=(tables[i].table->null_fields+7)/8;
copy->length=tables[i].table->null_bytes;
copy->strip=0;
copy->blob_field=0;
length+=copy->length;
@ -6940,16 +6959,17 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab)
****************************************************************************/
static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
bool distinct)
bool distinct,const char *message)
{
List<Item> field_list;
Item *item;
THD *thd=join->thd;
SELECT_LEX *select_lex = &(join->thd->lex.select_lex);
DBUG_ENTER("select_describe");
/* Don't log this into the slow query log */
join->thd->lex.select_lex.options&= ~(QUERY_NO_INDEX_USED | QUERY_NO_GOOD_INDEX_USED);
if (join->thd->lex.select == &join->thd->lex.select_lex)
select_lex->options&= ~(QUERY_NO_INDEX_USED | QUERY_NO_GOOD_INDEX_USED);
if (join->thd->lex.select == select_lex)
{
field_list.push_back(new Item_empty_string("table",NAME_LEN));
field_list.push_back(new Item_empty_string("type",10));
@ -6970,133 +6990,150 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
}
char buff[512],*buff_ptr;
String tmp(buff,sizeof(buff)),*packet= &thd->packet;
table_map used_tables=0;
for (uint i=0 ; i < join->tables ; i++)
if (message)
{
JOIN_TAB *tab=join->join_tab+i;
TABLE *table=tab->table;
if (tab->type == JT_ALL && tab->select && tab->select->quick)
tab->type= JT_RANGE;
packet->length(0);
net_store_data(packet,table->table_name);
net_store_data(packet,join_type_str[tab->type]);
tmp.length(0);
key_map bits;
uint j;
for (j=0,bits=tab->keys ; bits ; j++,bits>>=1)
net_store_null(packet);
net_store_null(packet);
net_store_null(packet);
net_store_null(packet);
net_store_null(packet);
net_store_null(packet);
net_store_null(packet);
net_store_data(packet,message,strlen(message));
if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length()))
DBUG_VOID_RETURN;
}
else
{
table_map used_tables=0;
for (uint i=0 ; i < join->tables ; i++)
{
if (bits & 1)
{
if (tmp.length())
tmp.append(',');
tmp.append(table->key_info[j].name);
}
}
if (tmp.length())
net_store_data(packet,tmp.ptr(),tmp.length());
else
net_store_null(packet);
if (tab->ref.key_parts)
{
net_store_data(packet,table->key_info[tab->ref.key].name);
net_store_data(packet,(uint32) tab->ref.key_length);
JOIN_TAB *tab=join->join_tab+i;
TABLE *table=tab->table;
if (tab->type == JT_ALL && tab->select && tab->select->quick)
tab->type= JT_RANGE;
packet->length(0);
net_store_data(packet,table->table_name);
net_store_data(packet,join_type_str[tab->type]);
tmp.length(0);
for (store_key **ref=tab->ref.key_copy ; *ref ; ref++)
key_map bits;
uint j;
for (j=0,bits=tab->keys ; bits ; j++,bits>>=1)
{
if (tmp.length())
tmp.append(',');
tmp.append((*ref)->name());
if (bits & 1)
{
if (tmp.length())
tmp.append(',');
tmp.append(table->key_info[j].name);
}
}
net_store_data(packet,tmp.ptr(),tmp.length());
}
else if (tab->type == JT_NEXT)
{
net_store_data(packet,table->key_info[tab->index].name);
net_store_data(packet,(uint32) table->key_info[tab->index].key_length);
net_store_null(packet);
}
else if (tab->select && tab->select->quick)
{
net_store_data(packet,table->key_info[tab->select->quick->index].name);;
net_store_data(packet,(uint32) tab->select->quick->max_used_key_length);
net_store_null(packet);
}
else
{
net_store_null(packet);
net_store_null(packet);
net_store_null(packet);
}
sprintf(buff,"%.0f",join->best_positions[i].records_read);
net_store_data(packet,buff);
my_bool key_read=table->key_read;
if (tab->type == JT_NEXT &&
((table->used_keys & ((key_map) 1 << tab->index))))
key_read=1;
buff_ptr=buff;
if (tab->info)
net_store_data(packet,tab->info);
else if (tab->select)
{
if (tab->use_quick == 2)
if (tmp.length())
net_store_data(packet,tmp.ptr(),tmp.length());
else
net_store_null(packet);
if (tab->ref.key_parts)
{
sprintf(buff_ptr,"range checked for each record (index map: %u)",
tab->keys);
buff_ptr=strend(buff_ptr);
net_store_data(packet,table->key_info[tab->ref.key].name);
net_store_data(packet,(uint32) tab->ref.key_length);
tmp.length(0);
for (store_key **ref=tab->ref.key_copy ; *ref ; ref++)
{
if (tmp.length())
tmp.append(',');
tmp.append((*ref)->name());
}
net_store_data(packet,tmp.ptr(),tmp.length());
}
else if (tab->type == JT_NEXT)
{
net_store_data(packet,table->key_info[tab->index].name);
net_store_data(packet,(uint32) table->key_info[tab->index].key_length);
net_store_null(packet);
}
else if (tab->select && tab->select->quick)
{
net_store_data(packet,table->key_info[tab->select->quick->index].name);;
net_store_data(packet,(uint32) tab->select->quick->max_used_key_length);
net_store_null(packet);
}
else
buff_ptr=strmov(buff_ptr,"where used");
}
if (key_read)
{
if (buff != buff_ptr)
{
buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2;
net_store_null(packet);
net_store_null(packet);
net_store_null(packet);
}
buff_ptr=strmov(buff_ptr,"Using index");
}
if (table->reginfo.not_exists_optimize)
{
if (buff != buff_ptr)
sprintf(buff,"%.0f",join->best_positions[i].records_read);
net_store_data(packet,buff);
my_bool key_read=table->key_read;
if (tab->type == JT_NEXT &&
((table->used_keys & ((key_map) 1 << tab->index))))
key_read=1;
buff_ptr=buff;
if (tab->info)
net_store_data(packet,tab->info);
else if (tab->select)
{
buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2;
if (tab->use_quick == 2)
{
sprintf(buff_ptr,"range checked for each record (index map: %u)",
tab->keys);
buff_ptr=strend(buff_ptr);
}
else
buff_ptr=strmov(buff_ptr,"where used");
}
buff_ptr=strmov(buff_ptr,"Not exists");
}
if (need_tmp_table)
{
need_tmp_table=0;
if (buff != buff_ptr)
if (key_read)
{
buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2;
if (buff != buff_ptr)
{
buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2;
}
buff_ptr=strmov(buff_ptr,"Using index");
}
buff_ptr=strmov(buff_ptr,"Using temporary");
}
if (need_order)
{
need_order=0;
if (buff != buff_ptr)
if (table->reginfo.not_exists_optimize)
{
buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2;
if (buff != buff_ptr)
{
buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2;
}
buff_ptr=strmov(buff_ptr,"Not exists");
}
buff_ptr=strmov(buff_ptr,"Using filesort");
}
if (distinct & test_all_bits(used_tables,thd->used_tables))
{
if (buff != buff_ptr)
if (need_tmp_table)
{
buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2;
need_tmp_table=0;
if (buff != buff_ptr)
{
buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2;
}
buff_ptr=strmov(buff_ptr,"Using temporary");
}
buff_ptr=strmov(buff_ptr,"Distinct");
}
net_store_data(packet,buff,(uint) (buff_ptr - buff));
if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length()))
DBUG_VOID_RETURN; /* purecov: inspected */
if (need_order)
{
need_order=0;
if (buff != buff_ptr)
{
buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2;
}
buff_ptr=strmov(buff_ptr,"Using filesort");
}
if (distinct & test_all_bits(used_tables,thd->used_tables))
{
if (buff != buff_ptr)
{
buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2;
}
buff_ptr=strmov(buff_ptr,"Distinct");
}
net_store_data(packet,buff,(uint) (buff_ptr - buff));
if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length()))
DBUG_VOID_RETURN; /* Purecov: Inspected */
// For next iteration
used_tables|=table->map;
// For next iteration
used_tables|=table->map;
}
}
if (!join->thd->lex.select->next)
send_eof(&thd->net);

View file

@ -825,7 +825,7 @@ bool close_cached_table(THD *thd,TABLE *table)
/* Mark all tables that are in use as 'old' */
mysql_lock_abort(thd,table); // end threads waiting on lock
#ifdef REMOVE_LOCKS
#if defined(USING_TRANSACTIONS) || defined( __WIN__) || defined( __EMX__) || !defined(OS2)
/* Wait until all there are no other threads that has this table open */
while (remove_table_from_cache(thd,table->table_cache_key,
table->table_name))
@ -1674,19 +1674,28 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
}
}
#if defined( __WIN__) || defined( __EMX__) || defined( OS2)
// Win32 can't rename an open table, so we must close the org table!
table_name=thd->strdup(table_name); // must be saved
if (close_cached_table(thd,table))
{ // Aborted
VOID(quick_rm_table(new_db_type,new_db,tmp_name));
VOID(pthread_mutex_unlock(&LOCK_open));
goto err;
}
table=0; // Marker for win32 version
#else
table->file->extra(HA_EXTRA_FORCE_REOPEN); // Don't use this file anymore
#if (!defined( __WIN__) && !defined( __EMX__) && !defined( OS2))
if (table->file->has_transactions())
#endif
{
/*
Win32 and InnoDB can't drop a table that is in use, so we must
close all the original table at before doing the rename
*/
table_name=thd->strdup(table_name); // must be saved
if (close_cached_table(thd,table))
{ // Aborted
VOID(quick_rm_table(new_db_type,new_db,tmp_name));
VOID(pthread_mutex_unlock(&LOCK_open));
goto err;
}
table=0; // Marker that table is closed
}
#if (!defined( __WIN__) && !defined( __EMX__) && !defined( OS2))
else
table->file->extra(HA_EXTRA_FORCE_REOPEN); // Don't use this file anymore
#endif
error=0;
if (mysql_rename_table(old_db_type,db,table_name,db,old_name))

View file

@ -76,6 +76,12 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
for (sl= &lex->select_lex; sl; sl=sl->next)
{
lex->select=sl;
thd->offset_limit=sl->offset_limit;
thd->select_limit=sl->select_limit+sl->offset_limit;
if (thd->select_limit < sl->select_limit)
thd->select_limit= HA_POS_ERROR; // no limit
if (thd->select_limit == HA_POS_ERROR)
sl->options&= ~OPTION_FOUND_ROWS;
res=mysql_select(thd, (TABLE_LIST*) sl->table_list.first,
sl->item_list,
sl->where,

View file

@ -596,9 +596,17 @@ END_OF_INPUT
query:
END_OF_INPUT
{
if (!current_thd->bootstrap)
THD *thd=current_thd;
if (!thd->bootstrap &&
(!(thd->lex.select_lex.options & OPTION_FOUND_COMMENT)))
{
send_error(&current_thd->net,ER_EMPTY_QUERY);
YYABORT;
YYABORT;
}
else
{
thd->lex.sql_command = SQLCOM_EMPTY_QUERY;
}
}
| verb_clause END_OF_INPUT {}
@ -776,7 +784,7 @@ opt_table_options:
table_options:
table_option { $$=$1; }
| table_option table_options { $$= $1 | $2 }
| table_option table_options { $$= $1 | $2; }
table_option:
TEMPORARY { $$=HA_LEX_CREATE_TMP_TABLE; }
@ -2828,7 +2836,7 @@ literal:
| FLOAT_NUM { $$ = new Item_float($1.str, $1.length); }
| NULL_SYM { $$ = new Item_null();
Lex->next_state=STATE_OPERATOR_OR_IDENT;}
| HEX_NUM { $$ = new Item_varbinary($1.str,$1.length)};
| HEX_NUM { $$ = new Item_varbinary($1.str,$1.length);}
| DATE_SYM text_literal { $$ = $2; }
| TIME_SYM text_literal { $$ = $2; }
| TIMESTAMP text_literal { $$ = $2; }

View file

@ -486,11 +486,11 @@ static bool pack_fields(File file,List<create_field> &create_fields)
if (field->interval_id > int_count)
{
int_count=field->interval_id;
tmp.append('\377');
tmp.append(NAMES_SEP_CHAR);
for (const char **pos=field->interval->type_names ; *pos ; pos++)
{
tmp.append(*pos);
tmp.append('\377');
tmp.append(NAMES_SEP_CHAR);
}
tmp.append('\0'); // End of intervall
}

View file

@ -70,11 +70,6 @@
#define FERR -1 /* Error from my_functions */
#define CREATE_MODE 0 /* Default mode on new files */
#define NAMES_SEP_CHAR '\377' /* Char to sep. names */
#ifdef MSDOS
#define EXTRA_FIELD_CHAR (char) '\234' /* Interchangebly with '#' */
#else
#define EXTRA_FIELD_CHAR '#' /* Interchangebly with '#' */
#endif
#define READ_RECORD_BUFFER (uint) (IO_SIZE*8) /* Pointer_buffer_size */
#define DISK_BUFFER_SIZE (uint) (IO_SIZE*16) /* Size of diskbuffer */

View file

@ -174,6 +174,7 @@ sh -c "PATH=\"${MYSQL_BUILD_PATH:-/bin:/usr/bin}\" \
./configure \
$* \
--enable-assembler \
--enable-local-infile \
--with-mysqld-user=%{mysqld_user} \
--with-unix-socket-path=/var/lib/mysql/mysql.sock \
--prefix=/ \