Commit b1d08ba2 authored by monty@mysql.com's avatar monty@mysql.com

Merge with 4.0 to get the latest bug patches to 4.1

parents f6765146 c3eb9360
...@@ -790,3 +790,4 @@ sql/mysql_tzinfo_to_sql_tztime.cc ...@@ -790,3 +790,4 @@ sql/mysql_tzinfo_to_sql_tztime.cc
sql/my_time.c sql/my_time.c
libmysql/my_time.c libmysql/my_time.c
libmysqld/my_time.c libmysqld/my_time.c
sql/mysql_tzinfo_to_sql
...@@ -90,6 +90,7 @@ marko@hundin.mysql.fi ...@@ -90,6 +90,7 @@ marko@hundin.mysql.fi
miguel@hegel.(none) miguel@hegel.(none)
miguel@hegel.br miguel@hegel.br
miguel@hegel.local miguel@hegel.local
miguel@hegel.txg
miguel@light. miguel@light.
miguel@light.local miguel@light.local
miguel@sartre.local miguel@sartre.local
......
...@@ -22,6 +22,7 @@ use Getopt::Long; ...@@ -22,6 +22,7 @@ use Getopt::Long;
Getopt::Long::Configure ("bundling"); Getopt::Long::Configure ("bundling");
use Sys::Hostname; use Sys::Hostname;
$opt_nobuild = undef;
$opt_cc= undef; $opt_cc= undef;
$opt_cflags= undef; $opt_cflags= undef;
$opt_clean= undef; $opt_clean= undef;
...@@ -48,6 +49,7 @@ GetOptions( ...@@ -48,6 +49,7 @@ GetOptions(
"help|h", "help|h",
"log|l:s", "log|l:s",
"mail|m=s", "mail|m=s",
"nobuild",
"verbose|v", "verbose|v",
) || &print_help; ) || &print_help;
...@@ -79,7 +81,10 @@ foreach (@spec) ...@@ -79,7 +81,10 @@ foreach (@spec)
if (m/^%define\s*mysql_version\s*(.*)/) if (m/^%define\s*mysql_version\s*(.*)/)
{ {
$VERSION= $1; $VERSION= $1;
$VERSION_SRPM=$VERSION;
($MAJOR, $MINOR, $RELEASE)= split(/\./,$VERSION); ($MAJOR, $MINOR, $RELEASE)= split(/\./,$VERSION);
$VERSION_SRPM= $MAJOR . '.' . $MINOR . '.' . $RELEASE;
$VERSION_SRPM =~ s/\-\w+$//;
($RELEASE, $SUFFIX)= split(/\-/,$RELEASE); ($RELEASE, $SUFFIX)= split(/\-/,$RELEASE);
$SUFFIX= "-" . $SUFFIX if ($SUFFIX); $SUFFIX= "-" . $SUFFIX if ($SUFFIX);
} }
...@@ -143,60 +148,64 @@ chomp($SRCRPMDIR= `$RPM --eval "%{_srcrpmdir}" 2> /dev/null`); ...@@ -143,60 +148,64 @@ chomp($SRCRPMDIR= `$RPM --eval "%{_srcrpmdir}" 2> /dev/null`);
$SOURCEFILE= glob "mysql*-$VERSION.tar.gz"; $SOURCEFILE= glob "mysql*-$VERSION.tar.gz";
&logger("Starting RPM build of MySQL-$VERSION on $HOST"); unless($opt_nobuild) {
foreach $file ($SOURCEFILE, $SPECFILE) &logger("Starting RPM build of MySQL-$VERSION on $HOST");
{
&abort("Unable to find $file!") unless (-f "$file"); foreach $file ($SOURCEFILE, $SPECFILE)
} {
&abort("Unable to find $file!") unless (-f "$file");
}
# #
# Install source and spec file # Install source and spec file
# #
&logger("Copying SOURCE and SPEC file to build directories."); &logger("Copying SOURCE and SPEC file to build directories.");
unless ($opt_dry_run) unless ($opt_dry_run)
{ {
copy($SOURCEFILE, $SOURCEDIR) copy($SOURCEFILE, $SOURCEDIR)
or &abort("Unable to copy $SOURCEFILE to $SOURCEDIR!"); or &abort("Unable to copy $SOURCEFILE to $SOURCEDIR!");
copy($SPECFILE, $SPECDIR) copy($SPECFILE, $SPECDIR)
or &abort("Unable to copy $SPECFILE to $SPECDIR!"); or &abort("Unable to copy $SPECFILE to $SPECDIR!");
} }
# #
# Set environment variables - these are being used in the # Set environment variables - these are being used in the
# official MySQL RPM spec file # official MySQL RPM spec file
# #
&logger("Setting special build environment variables") &logger("Setting special build environment variables")
if ($opt_cc) or ($opt_cflags) or ($opt_cxxflags) or ($opt_cxx); if ($opt_cc) or ($opt_cflags) or ($opt_cxxflags) or ($opt_cxx);
$ENV{MYSQL_BUILD_CC}=$opt_cc if ($opt_cc); $ENV{MYSQL_BUILD_CC}=$opt_cc if ($opt_cc);
$ENV{MYSQL_BUILD_CFLAGS}=$opt_cflags if ($opt_cflags); $ENV{MYSQL_BUILD_CFLAGS}=$opt_cflags if ($opt_cflags);
$ENV{MYSQL_BUILD_CXXFLAGS}=$opt_cxxflags if ($opt_cxxflags); $ENV{MYSQL_BUILD_CXXFLAGS}=$opt_cxxflags if ($opt_cxxflags);
$ENV{MYSQL_BUILD_CXX}=$opt_cxx if ($opt_cxx); $ENV{MYSQL_BUILD_CXX}=$opt_cxx if ($opt_cxx);
# #
# Build the RPMs # Build the RPMs
# #
$command= "$RPM"; $command= "$RPM";
$command.= " -v" if ($opt_verbose); $command.= " -v" if ($opt_verbose);
$command.= " -ba"; $command.= " -ba";
$command.= " --clean $RMSOURCE" if $opt_clean; $command.= " --clean $RMSOURCE" if $opt_clean;
$command.= " $SPECDIR/"; $command.= " $SPECDIR/";
$command.= basename($SPECFILE); $command.= basename($SPECFILE);
&logger("Building RPM."); &logger("Building RPM.");
&run_command($command, "Error while building the RPMs!"); &run_command($command, "Error while building the RPMs!");
}
# #
# Move the resulting RPMs into the pwd # Move the resulting RPMs into the pwd
# #
$command= "mv"; $command= "mv";
$command.= " -v " if ($opt_verbose); $command.= " -v " if ($opt_verbose);
$command.= " $SRCRPMDIR/MySQL*$VERSION*.src.rpm $PWD"; $command.= " $SRCRPMDIR/MySQL*$VERSION_SRPM*.src.rpm $PWD";
&logger("Moving source RPM to current dir."); &logger("Moving source RPM to current dir.");
&run_command($command, "Error moving source RPM!"); &run_command($command, "Error moving source RPM!");
$command= "mv"; $command= "mv";
$command.= " -v " if ($opt_verbose); $command.= " -v " if ($opt_verbose);
$command.= " $RPMDIR/$RPMARCH/MySQL*$VERSION*.$RPMARCH.rpm $PWD"; # $command.= " $RPMDIR/$RPMARCH/MySQL*$VERSION*.$RPMARCH.rpm $PWD";
$command.= " $RPMDIR/$RPMARCH/MySQL*$VERSION_SRPM*.$RPMARCH.rpm $PWD";
&logger("Moving binary RPMs to current dir."); &logger("Moving binary RPMs to current dir.");
&run_command($command, "Error moving binary RPMs!"); &run_command($command, "Error moving binary RPMs!");
......
#!/usr/bin/perl
#
# my_md5sum
#
# Script to clone the 'md5sum' command found on modern systems, since that
# command is not always found on all systems.
#
# Use the "--help" option for more info!
#
# Written by Matt Wagner <matt@mysql.com>
#
use strict;
use Digest::MD5;
use Getopt::Long;
my $VER= "1.1";
#
# Strip the leading path info off the program name ($0). We want 'my_md5sum'
# not './my_md5sum'.
#
$0=~ s/^.*\/(.+)$/$1/;
my ($opt_check, $opt_help)= undef;
GetOptions(
"check|c" => \$opt_check,
"help|h" => \$opt_help,
) || usage();
#
# Put all the [file1 file2 file3 ...]'s into an array
#
my @files = @ARGV;
#
# Give the "--help" text if:
# - "--help|-h" was specified
# - The number of files given as arguments is nil
# - The "--check|-c" option is used with more than one [file] argument
#
usage() if $opt_help || $#files == -1 || ($opt_check && $#files > 0);
# If "--check|-c", then go into checking
if ($opt_check)
{
open (CHECKFILE, $files[0]) or die "$files[0]: $!";
while (<CHECKFILE>)
{
#
# Goto the next line in the file if it does not match a typical
# digest line like:
#
# f1007efa2c72daa693981ec764cdeaca Bootstrap
#
next if $_!~ m/^([a-z0-9]{32})\s+(.+)$/;
# Collect the trappings from the above regex
my $checksum= $1;
my $checkfile= $2;
# Generate a fresh MD5 for the file in question
my $digest= &mkmd5($checkfile);
# Check the fresh MD5 against what is recorded in the file
# Print an error message if they don't match, else print OK
print "$checkfile: FAILED\n" if $digest ne $checksum;
print "$checkfile: OK\n" if $digest eq $checksum;
}
}
# Else generate the MD5 digest to STDOUT
else
{
foreach my $file (@files)
{
my $digest= &mkmd5($file);
print "$digest $file\n";
}
}
#
# This routine generates the MD5 digest of a file
#
sub mkmd5
{
my $file= shift;
open (FILE, $file) or die "$file: $!";
binmode(FILE);
my $digest= Digest::MD5->new->addfile(*FILE)->hexdigest;
close FILE;
return $digest;
}
#
# Print the help text
#
sub usage
{
print <<EOF;
$0 version $VER by Matt Wagner <matt\@mysql.com>
Usage:
$0 [-c [file]] | [file1...]
Generates or checks MD5 message digests.
Options:
-c, --check Check message digests (default is generate)
-h, --help Display this text and exit
The input for -c should be the list of message digests and file names that is
printed on STDOUT by this program when it generates digests.
EOF
exit(0);
}
...@@ -777,14 +777,15 @@ AC_DEFUN(MYSQL_FIND_OPENSSL, [ ...@@ -777,14 +777,15 @@ AC_DEFUN(MYSQL_FIND_OPENSSL, [
---) ---)
for d in /usr/ssl/include /usr/local/ssl/include /usr/include \ for d in /usr/ssl/include /usr/local/ssl/include /usr/include \
/usr/include/ssl /opt/ssl/include /opt/openssl/include \ /usr/include/ssl /opt/ssl/include /opt/openssl/include \
/usr/local/ssl/include /usr/local/include ; do /usr/local/ssl/include /usr/local/include /usr/freeware/include ; do
if test -f $d/openssl/ssl.h ; then if test -f $d/openssl/ssl.h ; then
OPENSSL_INCLUDE=-I$d OPENSSL_INCLUDE=-I$d
fi fi
done done
for d in /usr/ssl/lib /usr/local/ssl/lib /usr/lib/openssl \ for d in /usr/ssl/lib /usr/local/ssl/lib /usr/lib/openssl \
/usr/lib /usr/lib64 /opt/ssl/lib /opt/openssl/lib /usr/local/lib/ ; do /usr/lib /usr/lib64 /opt/ssl/lib /opt/openssl/lib \
/usr/freeware/lib32 /usr/local/lib/ ; do
if test -f $d/libssl.a || test -f $d/libssl.so || test -f $d/libssl.dylib ; then if test -f $d/libssl.a || test -f $d/libssl.so || test -f $d/libssl.dylib ; then
OPENSSL_LIB=$d OPENSSL_LIB=$d
fi fi
......
...@@ -323,7 +323,7 @@ typedef struct st_mysql_parameters ...@@ -323,7 +323,7 @@ typedef struct st_mysql_parameters
unsigned long *p_net_buffer_length; unsigned long *p_net_buffer_length;
} MYSQL_PARAMETERS; } MYSQL_PARAMETERS;
#if !defined(MYSQL_CLIENT) && !defined(MYSQL_SERVER) && !defined(EMBEDDED_LIBRARY) #if !defined(MYSQL_SERVER) && !defined(EMBEDDED_LIBRARY)
#define max_allowed_packet (*mysql_get_parameters()->p_max_allowed_packet) #define max_allowed_packet (*mysql_get_parameters()->p_max_allowed_packet)
#define net_buffer_length (*mysql_get_parameters()->p_net_buffer_length) #define net_buffer_length (*mysql_get_parameters()->p_net_buffer_length)
#endif #endif
......
...@@ -89,7 +89,7 @@ mach_read_from_4( ...@@ -89,7 +89,7 @@ mach_read_from_4(
/* out: ulint integer */ /* out: ulint integer */
byte* b); /* in: pointer to four bytes */ byte* b); /* in: pointer to four bytes */
/************************************************************* /*************************************************************
Writes a ulint in a compressed form. */ Writes a ulint in a compressed form (1..5 bytes). */
UNIV_INLINE UNIV_INLINE
ulint ulint
mach_write_compressed( mach_write_compressed(
...@@ -168,7 +168,7 @@ mach_read_from_8( ...@@ -168,7 +168,7 @@ mach_read_from_8(
/* out: dulint integer */ /* out: dulint integer */
byte* b); /* in: pointer to 8 bytes */ byte* b); /* in: pointer to 8 bytes */
/************************************************************* /*************************************************************
Writes a dulint in a compressed form. */ Writes a dulint in a compressed form (5..9 bytes). */
UNIV_INLINE UNIV_INLINE
ulint ulint
mach_dulint_write_compressed( mach_dulint_write_compressed(
...@@ -193,7 +193,7 @@ mach_dulint_read_compressed( ...@@ -193,7 +193,7 @@ mach_dulint_read_compressed(
/* out: read dulint */ /* out: read dulint */
byte* b); /* in: pointer to memory from where to read */ byte* b); /* in: pointer to memory from where to read */
/************************************************************* /*************************************************************
Writes a dulint in a compressed form. */ Writes a dulint in a compressed form (1..11 bytes). */
UNIV_INLINE UNIV_INLINE
ulint ulint
mach_dulint_write_much_compressed( mach_dulint_write_much_compressed(
......
...@@ -366,7 +366,7 @@ mach_read_from_6( ...@@ -366,7 +366,7 @@ mach_read_from_6(
} }
/************************************************************* /*************************************************************
Writes a dulint in a compressed form. */ Writes a dulint in a compressed form (5..9 bytes). */
UNIV_INLINE UNIV_INLINE
ulint ulint
mach_dulint_write_compressed( mach_dulint_write_compressed(
...@@ -422,7 +422,7 @@ mach_dulint_read_compressed( ...@@ -422,7 +422,7 @@ mach_dulint_read_compressed(
} }
/************************************************************* /*************************************************************
Writes a dulint in a compressed form. */ Writes a dulint in a compressed form (1..11 bytes). */
UNIV_INLINE UNIV_INLINE
ulint ulint
mach_dulint_write_much_compressed( mach_dulint_write_much_compressed(
......
...@@ -121,7 +121,9 @@ mlog_close( ...@@ -121,7 +121,9 @@ mlog_close(
mtr_t* mtr, /* in: mtr */ mtr_t* mtr, /* in: mtr */
byte* ptr); /* in: buffer space from ptr up was not used */ byte* ptr); /* in: buffer space from ptr up was not used */
/************************************************************ /************************************************************
Writes the initial part of a log record. */ Writes the initial part of a log record (3..11 bytes).
If the implementation of this function is changed, all
size parameters to mlog_open() should be adjusted accordingly! */
UNIV_INLINE UNIV_INLINE
byte* byte*
mlog_write_initial_log_record_fast( mlog_write_initial_log_record_fast(
......
...@@ -137,7 +137,9 @@ mlog_catenate_dulint_compressed( ...@@ -137,7 +137,9 @@ mlog_catenate_dulint_compressed(
} }
/************************************************************ /************************************************************
Writes the initial part of a log record. */ Writes the initial part of a log record (3..11 bytes).
If the implementation of this function is changed, all
size parameters to mlog_open() should be adjusted accordingly! */
UNIV_INLINE UNIV_INLINE
byte* byte*
mlog_write_initial_log_record_fast( mlog_write_initial_log_record_fast(
......
...@@ -22,6 +22,7 @@ static ulint mem_n_allocations = 0; ...@@ -22,6 +22,7 @@ static ulint mem_n_allocations = 0;
static ulint mem_total_allocated_memory = 0; static ulint mem_total_allocated_memory = 0;
ulint mem_current_allocated_memory = 0; ulint mem_current_allocated_memory = 0;
static ulint mem_max_allocated_memory = 0; static ulint mem_max_allocated_memory = 0;
static ulint mem_last_print_info = 0;
/* Size of the hash table for memory management tracking */ /* Size of the hash table for memory management tracking */
#define MEM_HASH_SIZE 997 #define MEM_HASH_SIZE 997
......
This diff is collapsed.
...@@ -114,11 +114,34 @@ ID [a-z_A-Z][a-z_A-Z0-9]* ...@@ -114,11 +114,34 @@ ID [a-z_A-Z][a-z_A-Z0-9]*
} }
"'" { "'" {
/* Quoted character string literals are handled in an explicit
start state 'quoted'. This state is entered and the buffer for
the scanned string is emptied upon encountering a starting quote.
In the state 'quoted', only two actions are possible (defined below). */
BEGIN(quoted); BEGIN(quoted);
stringbuf_len = 0; stringbuf_len = 0;
} }
<quoted>[^\']+ string_append(yytext, yyleng); <quoted>[^\']+ {
<quoted>"'"+ { string_append(yytext, yyleng / 2); /* Got a sequence of characters other than "'":
append to string buffer */
string_append(yytext, yyleng);
}
<quoted>"'"+ {
/* Got a sequence of "'" characters:
append half of them to string buffer,
as "''" represents a single "'".
We apply truncating division,
so that "'''" will result in "'". */
string_append(yytext, yyleng / 2);
/* If we got an odd number of quotes, then the
last quote we got is the terminating quote.
At the end of the string, we return to the
initial start state and report the scanned
string literal. */
if (yyleng % 2) { if (yyleng % 2) {
BEGIN(INITIAL); BEGIN(INITIAL);
yylval = sym_tab_add_str_lit( yylval = sym_tab_add_str_lit(
......
...@@ -59,6 +59,9 @@ ...@@ -59,6 +59,9 @@
#include <sql_common.h> #include <sql_common.h>
#include "client_settings.h" #include "client_settings.h"
#undef net_buffer_length
#undef max_allowed_packet
ulong net_buffer_length=8192; ulong net_buffer_length=8192;
ulong max_allowed_packet= 1024L*1024L*1024L; ulong max_allowed_packet= 1024L*1024L*1024L;
ulong net_read_timeout= CLIENT_NET_READ_TIMEOUT; ulong net_read_timeout= CLIENT_NET_READ_TIMEOUT;
......
.TH mysqlaccess 1 "19 December 2000" "MySQL @MYSQL_BASE_VERSION@" "MySQL database" .TH mysqlaccess 1 "19 December 2000" "MySQL @MYSQL_BASE_VERSION@" "MySQL database"
.SH NAME .SH NAME
.BR mysqlaccess .BR mysqlaccess \- Create new users to mysql.
\- Create new users to mysql.
.SH USAGE .SH USAGE
mysqlaccess [host [user [db]]] OPTIONS mysqlaccess [host [user [db]]] OPTIONS
.SH SYNOPSIS .SH SYNOPSIS
......
.TH mysqldump 1 "19 December 2000" "MySQL @MYSQL_BASE_VERSION@" "MySQL database" .TH mysqldump 1 "19 December 2000" "MySQL @MYSQL_BASE_VERSION@" "MySQL database"
.SH NAME .SH NAME
mysqldump \- text-based client for dumping or backing up mysql databases , tables and or data. mysqldump \- text\-based client for dumping or backing up mysql databases, tables and or data.
.SH USAGE .SH USAGE
.BR "mysqldump [\fP\fIOPTIONS\fP] database [\fP\fItables\fP]" .BR "mysqldump [\fP\fIOPTIONS\fP] database [\fP\fItables\fP]"
......
...@@ -691,7 +691,7 @@ report_stats () { ...@@ -691,7 +691,7 @@ report_stats () {
# #
$RM -f $MY_LOG_DIR/warnings $MY_LOG_DIR/warnings.tmp $RM -f $MY_LOG_DIR/warnings $MY_LOG_DIR/warnings.tmp
# Remove some non fatal warnings from the log files # Remove some non fatal warnings from the log files
$SED -e 's!Warning: Table:.* on delete!!g' \ $SED -e 's!Warning: Table:.* on delete!!g' -e 's!Warning: Setting lower_case_table_names=2!!g' -e 's!Warning: One can only use the --user.*root!!g' \
$MY_LOG_DIR/*.err \ $MY_LOG_DIR/*.err \
| $SED -e 's!Warning: Table:.* on rename!!g' \ | $SED -e 's!Warning: Table:.* on rename!!g' \
> $MY_LOG_DIR/warnings.tmp > $MY_LOG_DIR/warnings.tmp
......
...@@ -1181,6 +1181,40 @@ a ...@@ -1181,6 +1181,40 @@ a
A A
a a
drop table t1; drop table t1;
create table t1(
pk1 text not null, pk2 text not null, pk3 char(4),
key1 int, key2 int,
primary key(pk1(4), pk2(4), pk3), key(key1), key(key2)
) engine=bdb;
insert into t1 values (concat('aaa-', repeat('A', 4000)),
concat('eee-', repeat('e', 4000)), 'a++a', 1, 1);
insert into t1 values (concat('bbb-', repeat('B', 4000)),
concat('ggg-', repeat('G', 4000)), 'b++b', 1, 1);
select substring(pk1, 1, 4), substring(pk1, 4001),
substring(pk2, 1, 4), substring(pk2, 4001), pk3, key1, key2
from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
substring(pk1, 1, 4) substring(pk1, 4001) substring(pk2, 1, 4) substring(pk2, 4001) pk3 key1 key2
aaa- AAAA eee- eeee a++a 1 1
bbb- BBBB ggg- GGGG b++b 1 1
drop table t1;
create table t1 (
pk1 varchar(8) not null default '',
pk2 varchar(4) not null default '',
key1 int(11) default null,
key2 int(11) default null,
primary key (pk1,pk2),
key key1 (key1),
key key2 (key2)) engine=bdb;
insert into t1 values ('','empt',2,2), ('a','a--a',2,2),
('bb','b--b',2,2), ('ccc','c--c',2,2), ('dddd','d--d',2,2);
select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
pk1 pk2 key1 key2
empt 2 2
a a--a 2 2
bb b--b 2 2
ccc c--c 2 2
dddd d--d 2 2
drop table t1;
set autocommit=0; set autocommit=0;
create table t1(b varchar(30)) engine=bdb; create table t1(b varchar(30)) engine=bdb;
insert into t1 values ('one'); insert into t1 values ('one');
......
drop table if exists t1;
create table t1 (a int not null auto_increment primary key);
insert into t1 values(0);
lock table t1 read;
flush table t1;
check table t1;
Table Op Msg_type Msg_text
test.t1 check status OK
drop table t1;
drop database if exists test_test;
create database test_test;
use test_test;
create table t1(table_id char(20) primary key);
insert into t1 values ('test_test.t1');
insert into t1 values ('');
handler t1 open;
handler t1 read first limit 9;
table_id
test_test.t1
create table t2(table_id char(20) primary key);
insert into t2 values ('test_test.t2');
insert into t2 values ('');
handler t2 open;
handler t2 read first limit 9;
table_id
test_test.t2
use test;
drop table if exists t1;
create table t1(table_id char(20) primary key);
insert into t1 values ('test.t1');
insert into t1 values ('');
handler t1 open;
handler t1 read first limit 9;
table_id
test.t1
use test;
handler test.t1 read first limit 9;
table_id
test.t1
handler test.t2 read first limit 9;
Unknown table 't2' in HANDLER
handler test_test.t1 read first limit 9;
table_id
test_test.t1
handler test_test.t2 read first limit 9;
table_id
test_test.t2
handler test_test.t1 close;
drop table test_test.t1;
handler test_test.t2 close;
drop table test_test.t2;
drop database test_test;
use test;
handler test.t1 close;
drop table test.t1;
drop table if exists t1;
drop table if exists t2;
create table t1(table_id char(20) primary key);
create table t2(table_id char(20) primary key);
insert into t1 values ('test.t1');
insert into t1 values ('');
insert into t2 values ('test.t2');
insert into t2 values ('');
handler t1 open as a1;
handler t1 open as a2;
handler t2 open;
handler a1 read first limit 9;
table_id
test.t1
handler a2 read first limit 9;
table_id
test.t1
handler t2 read first limit 9;
table_id
test.t2
flush tables;
handler a1 read first limit 9;
Unknown table 'a1' in HANDLER
handler a2 read first limit 9;
Unknown table 'a2' in HANDLER
handler t2 read first limit 9;
Unknown table 't2' in HANDLER
handler t1 open as a1;
handler t1 open as a2;
handler t2 open;
handler a1 read first limit 9;
table_id
test.t1
handler a2 read first limit 9;
table_id
test.t1
handler t2 read first limit 9;
table_id
test.t2
flush table t1;
handler a1 read first limit 9;
Unknown table 'a1' in HANDLER
handler a2 read first limit 9;
Unknown table 'a2' in HANDLER
handler t2 read first limit 9;
table_id
test.t2
flush table t2;
handler t2 close;
Unknown table 't2' in HANDLER
drop table t1;
drop table t2;
...@@ -98,7 +98,7 @@ commit; ...@@ -98,7 +98,7 @@ commit;
show status like "Qcache_queries_in_cache"; show status like "Qcache_queries_in_cache";
Variable_name Value Variable_name Value
Qcache_queries_in_cache 1 Qcache_queries_in_cache 1
drop table if exists t1; drop table t3,t2,t1;
CREATE TABLE t1 (id int(11) NOT NULL auto_increment, PRIMARY KEY (id)) ENGINE=InnoDB; CREATE TABLE t1 (id int(11) NOT NULL auto_increment, PRIMARY KEY (id)) ENGINE=InnoDB;
select count(*) from t1; select count(*) from t1;
count(*) count(*)
...@@ -108,3 +108,22 @@ select count(*) from t1; ...@@ -108,3 +108,22 @@ select count(*) from t1;
count(*) count(*)
1 1
drop table t1; drop table t1;
set GLOBAL query_cache_size=1355776;
CREATE TABLE t1 ( id int(10) NOT NULL auto_increment, a varchar(25) default NULL, PRIMARY KEY (id), UNIQUE KEY a (a)) TYPE=innodb;
CREATE TABLE t2 ( id int(10) NOT NULL auto_increment, b varchar(25) default NULL, PRIMARY KEY (id), UNIQUE KEY b (b)) TYPE=innodb;
CREATE TABLE t3 ( id int(10) NOT NULL auto_increment, t1_id int(10) NOT NULL default '0', t2_id int(10) NOT NULL default '0', state int(11) default NULL, PRIMARY KEY (id), UNIQUE KEY t1_id (t1_id,t2_id), KEY t2_id (t2_id,t1_id), CONSTRAINT `t3_ibfk_1` FOREIGN KEY (`t1_id`) REFERENCES `t1` (`id`), CONSTRAINT `t3_ibfk_2` FOREIGN KEY (`t2_id`) REFERENCES `t2` (`id`)) TYPE=innodb;
INSERT INTO t1 VALUES (1,'me');
INSERT INTO t2 VALUES (1,'you');
INSERT INTO t3 VALUES (2,1,1,2);
delete from t3 where t1_id = 1 and t2_id = 1;
select t1.* from t1, t2, t3 where t3.state & 1 = 0 and t3.t1_id = t1.id and t3.t2_id = t2.id and t1.id = 1 order by t1.a asc;
id a
begin;
insert into t3 VALUES ( NULL, 1, 1, 2 );
insert into t3 VALUES ( NULL, 1, 1, 2 );
Duplicate entry '1-1' for key 2
commit;
select t1.* from t1, t2, t3 where t3.state & 1 = 0 and t3.t1_id = t1.id and t3.t2_id = t2.id and t1.id = 1 order by t1.a asc;
id a
1 me
drop table t3,t2,t1;
...@@ -121,3 +121,13 @@ LOCATION ...@@ -121,3 +121,13 @@ LOCATION
Mic-5 Mic-5
Mic-6 Mic-6
drop table T1; drop table T1;
create table T1 (A int);
alter table T1 add index (A);
show tables like 'T1%';
Tables_in_test (T1%)
T1
alter table t1 add index (A);
show tables like 't1%';
Tables_in_test (t1%)
t1
drop table t1;
...@@ -244,7 +244,7 @@ id select_type table type possible_keys key key_len ref rows Extra ...@@ -244,7 +244,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range x x 5 NULL 2 Using where 1 SIMPLE t2 range x x 5 NULL 2 Using where
explain select count(*) from t1 where x in (1); explain select count(*) from t1 where x in (1);
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range x x 5 NULL 1 Using where; Using index 1 SIMPLE t1 ref x x 5 NULL 1 Using where; Using index
explain select count(*) from t1 where x in (1,2); explain select count(*) from t1 where x in (1,2);
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range x x 5 NULL 2 Using where; Using index 1 SIMPLE t1 range x x 5 NULL 2 Using where; Using index
......
...@@ -823,6 +823,42 @@ explain select a from t1; ...@@ -823,6 +823,42 @@ explain select a from t1;
select a from t1; select a from t1;
drop table t1; drop table t1;
#
# bug#2686 - index_merge select on BerkeleyDB table with varchar PK causes mysqld to crash
#
create table t1(
pk1 text not null, pk2 text not null, pk3 char(4),
key1 int, key2 int,
primary key(pk1(4), pk2(4), pk3), key(key1), key(key2)
) engine=bdb;
insert into t1 values (concat('aaa-', repeat('A', 4000)),
concat('eee-', repeat('e', 4000)), 'a++a', 1, 1);
insert into t1 values (concat('bbb-', repeat('B', 4000)),
concat('ggg-', repeat('G', 4000)), 'b++b', 1, 1);
select substring(pk1, 1, 4), substring(pk1, 4001),
substring(pk2, 1, 4), substring(pk2, 4001), pk3, key1, key2
from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
drop table t1;
#
# bug#2688 - Wrong index_merge query results for BDB table with variable length primary key
#
create table t1 (
pk1 varchar(8) not null default '',
pk2 varchar(4) not null default '',
key1 int(11) default null,
key2 int(11) default null,
primary key (pk1,pk2),
key key1 (key1),
key key2 (key2)) engine=bdb;
insert into t1 values ('','empt',2,2), ('a','a--a',2,2),
('bb','b--b',2,2), ('ccc','c--c',2,2), ('dddd','d--d',2,2);
select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
drop table t1;
# #
# Bug #4000: problem with active cursor. # Bug #4000: problem with active cursor.
# #
......
...@@ -4,10 +4,111 @@ ...@@ -4,10 +4,111 @@
# Test of flush table # Test of flush table
# #
#drop table if exists t1; drop table if exists t1;
#create table t1 (a int not null auto_increment primary key); create table t1 (a int not null auto_increment primary key);
#insert into t1 values(0); insert into t1 values(0);
#lock table t1 read; lock table t1 read;
#flush table t1; flush table t1;
#check table t1; check table t1;
#drop table t1; drop table t1;
#
# Check if two database names beginning the same are seen as different.
#
# This database begins like the usual 'test' database.
#
--disable_warnings
drop database if exists test_test;
--enable_warnings
create database test_test;
use test_test;
create table t1(table_id char(20) primary key);
insert into t1 values ('test_test.t1');
insert into t1 values ('');
handler t1 open;
handler t1 read first limit 9;
create table t2(table_id char(20) primary key);
insert into t2 values ('test_test.t2');
insert into t2 values ('');
handler t2 open;
handler t2 read first limit 9;
#
# This is the usual 'test' database.
#
use test;
--disable_warnings
drop table if exists t1;
--enable_warnings
create table t1(table_id char(20) primary key);
insert into t1 values ('test.t1');
insert into t1 values ('');
handler t1 open;
handler t1 read first limit 9;
#
# Check accesibility of all the tables.
#
use test;
handler test.t1 read first limit 9;
--error 1109;
handler test.t2 read first limit 9;
handler test_test.t1 read first limit 9;
handler test_test.t2 read first limit 9;
#
# Cleanup.
#
handler test_test.t1 close;
drop table test_test.t1;
handler test_test.t2 close;
drop table test_test.t2;
drop database test_test;
#
use test;
handler test.t1 close;
drop table test.t1;
#
# In the following test FLUSH TABLES produces a deadlock
# (hang forever) if the fix for bug#3565 is missing.
#
--disable_warnings
drop table if exists t1;
drop table if exists t2;
--enable_warnings
create table t1(table_id char(20) primary key);
create table t2(table_id char(20) primary key);
insert into t1 values ('test.t1');
insert into t1 values ('');
insert into t2 values ('test.t2');
insert into t2 values ('');
handler t1 open as a1;
handler t1 open as a2;
handler t2 open;
handler a1 read first limit 9;
handler a2 read first limit 9;
handler t2 read first limit 9;
flush tables;
--error 1109;
handler a1 read first limit 9;
--error 1109;
handler a2 read first limit 9;
--error 1109;
handler t2 read first limit 9;
#
handler t1 open as a1;
handler t1 open as a2;
handler t2 open;
handler a1 read first limit 9;
handler a2 read first limit 9;
handler t2 read first limit 9;
flush table t1;
--error 1109;
handler a1 read first limit 9;
--error 1109;
handler a2 read first limit 9;
handler t2 read first limit 9;
flush table t2;
--error 1109;
handler t2 close;
drop table t1;
drop table t2;
...@@ -52,10 +52,31 @@ show status like "Qcache_queries_in_cache"; ...@@ -52,10 +52,31 @@ show status like "Qcache_queries_in_cache";
show status like "Qcache_hits"; show status like "Qcache_hits";
commit; commit;
show status like "Qcache_queries_in_cache"; show status like "Qcache_queries_in_cache";
drop table t3,t2,t1;
drop table if exists t1;
CREATE TABLE t1 (id int(11) NOT NULL auto_increment, PRIMARY KEY (id)) ENGINE=InnoDB; CREATE TABLE t1 (id int(11) NOT NULL auto_increment, PRIMARY KEY (id)) ENGINE=InnoDB;
select count(*) from t1; select count(*) from t1;
insert into t1 (id) values (0); insert into t1 (id) values (0);
select count(*) from t1; select count(*) from t1;
drop table t1; drop table t1;
#
# one statement roll back inside transation
#
set GLOBAL query_cache_size=1355776;
CREATE TABLE t1 ( id int(10) NOT NULL auto_increment, a varchar(25) default NULL, PRIMARY KEY (id), UNIQUE KEY a (a)) TYPE=innodb;
CREATE TABLE t2 ( id int(10) NOT NULL auto_increment, b varchar(25) default NULL, PRIMARY KEY (id), UNIQUE KEY b (b)) TYPE=innodb;
CREATE TABLE t3 ( id int(10) NOT NULL auto_increment, t1_id int(10) NOT NULL default '0', t2_id int(10) NOT NULL default '0', state int(11) default NULL, PRIMARY KEY (id), UNIQUE KEY t1_id (t1_id,t2_id), KEY t2_id (t2_id,t1_id), CONSTRAINT `t3_ibfk_1` FOREIGN KEY (`t1_id`) REFERENCES `t1` (`id`), CONSTRAINT `t3_ibfk_2` FOREIGN KEY (`t2_id`) REFERENCES `t2` (`id`)) TYPE=innodb;
INSERT INTO t1 VALUES (1,'me');
INSERT INTO t2 VALUES (1,'you');
INSERT INTO t3 VALUES (2,1,1,2);
delete from t3 where t1_id = 1 and t2_id = 1;
select t1.* from t1, t2, t3 where t3.state & 1 = 0 and t3.t1_id = t1.id and t3.t2_id = t2.id and t1.id = 1 order by t1.a asc;
begin;
insert into t3 VALUES ( NULL, 1, 1, 2 );
-- error 1062
insert into t3 VALUES ( NULL, 1, 1, 2 );
commit;
select t1.* from t1, t2, t3 where t3.state & 1 = 0 and t3.t1_id = t1.id and t3.t2_id = t2.id and t1.id = 1 order by t1.a asc;
drop table t3,t2,t1;
...@@ -89,3 +89,14 @@ SELECT LOCATION FROM T1 WHERE EVENT_ID=2 UNION ALL SELECT LOCATION FROM T1 WHER ...@@ -89,3 +89,14 @@ SELECT LOCATION FROM T1 WHERE EVENT_ID=2 UNION ALL SELECT LOCATION FROM T1 WHER
SELECT LOCATION FROM T1 WHERE EVENT_ID=2 UNION ALL SELECT LOCATION FROM T1 WHERE EVENT_ID=3; SELECT LOCATION FROM T1 WHERE EVENT_ID=2 UNION ALL SELECT LOCATION FROM T1 WHERE EVENT_ID=3;
SELECT LOCATION FROM T1 WHERE EVENT_ID=2 UNION ALL SELECT LOCATION FROM T1 WHERE EVENT_ID=3; SELECT LOCATION FROM T1 WHERE EVENT_ID=2 UNION ALL SELECT LOCATION FROM T1 WHERE EVENT_ID=3;
drop table T1; drop table T1;
#
# Test name conversion with ALTER TABLE / CREATE INDEX (Bug #3109)
#
create table T1 (A int);
alter table T1 add index (A);
show tables like 'T1%';
alter table t1 add index (A);
show tables like 't1%';
drop table t1;
...@@ -122,7 +122,8 @@ static uint hash_rec_mask(HASH *hash,HASH_LINK *pos,uint buffmax, ...@@ -122,7 +122,8 @@ static uint hash_rec_mask(HASH *hash,HASH_LINK *pos,uint buffmax,
#if !defined(__SUNPRO_C) && !defined(__USLC__) /* broken compilers */ /* for compilers which can not handle inline */
#if !defined(__SUNPRO_C) && !defined(__USLC__) && !defined(__sgi)
inline inline
#endif #endif
unsigned int rec_hashnr(HASH *hash,const byte *record) unsigned int rec_hashnr(HASH *hash,const byte *record)
......
...@@ -110,6 +110,9 @@ print_debug "Copying sql-bench to $DIRNAME/bench" ...@@ -110,6 +110,9 @@ print_debug "Copying sql-bench to $DIRNAME/bench"
mkdir $DIRNAME/bench mkdir $DIRNAME/bench
cp -fr sql-bench/* $DIRNAME/bench cp -fr sql-bench/* $DIRNAME/bench
print_debug "Copying support-files to $DIRNAME"
cp support-files/* $DIRNAME
# Files for bin # Files for bin
for i in client_release/* client_debug/mysqld.exe lib_release/libmySQL.dll for i in client_release/* client_debug/mysqld.exe lib_release/libmySQL.dll
do do
...@@ -124,7 +127,7 @@ do ...@@ -124,7 +127,7 @@ do
cp $i $DIRNAME/include cp $i $DIRNAME/include
done done
# Windows users are used to having dbug.h # Windows users are used to having dbug.h ?
cp include/my_dbug.h $DIRNAME/include/dbug.h cp include/my_dbug.h $DIRNAME/include/dbug.h
# Libraries found in lib_release and lib_debug # Libraries found in lib_release and lib_debug
......
...@@ -287,6 +287,12 @@ do ...@@ -287,6 +287,12 @@ do
fi fi
done done
#
# support files
#
mkdir $BASE/support-files
cp support-files/*.cnf $BASE/support-files
# #
# Raw dirs from source tree # Raw dirs from source tree
# #
......
...@@ -4684,6 +4684,42 @@ uint32 Field_blob::get_length(const char *pos) ...@@ -4684,6 +4684,42 @@ uint32 Field_blob::get_length(const char *pos)
} }
/*
Put a blob length field into a record buffer.
SYNOPSIS
Field_blob::put_length()
pos Pointer into the record buffer.
length The length value to put.
DESCRIPTION
Depending on the maximum length of a blob, its length field is
put into 1 to 4 bytes. This is a property of the blob object,
described by 'packlength'.
RETURN
nothing
*/
void Field_blob::put_length(char *pos, uint32 length)
{
switch (packlength) {
case 1:
*pos= (char) length;
break;
case 2:
int2store(pos, length);
break;
case 3:
int3store(pos, length);
break;
case 4:
int4store(pos, length);
break;
}
}
int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
{ {
if (!length) if (!length)
...@@ -5058,6 +5094,50 @@ char *Field_blob::pack_key(char *to, const char *from, uint max_length) ...@@ -5058,6 +5094,50 @@ char *Field_blob::pack_key(char *to, const char *from, uint max_length)
return to+length; return to+length;
} }
/*
Unpack a blob key into a record buffer.
SYNOPSIS
Field_blob::unpack_key()
to Pointer into the record buffer.
from Pointer to the packed key.
max_length Key length limit from key description.
DESCRIPTION
A blob key has a maximum size of 64K-1.
In its packed form, the length field is one or two bytes long,
depending on 'max_length'.
Depending on the maximum length of a blob, its length field is
put into 1 to 4 bytes. This is a property of the blob object,
described by 'packlength'.
Blobs are internally stored apart from the record buffer, which
contains a pointer to the blob buffer.
RETURN
Pointer into 'from' past the last byte copied from packed key.
*/
const char *Field_blob::unpack_key(char *to, const char *from, uint max_length)
{
/* get length of the blob key */
uint32 length= *((uchar*) from++);
if (max_length > 255)
length+= (*((uchar*) from++)) << 8;
/* put the length into the record buffer */
put_length(to, length);
/* put the address of the blob buffer or NULL */
if (length)
memcpy_fixed(to + packlength, &from, sizeof(from));
else
bzero(to + packlength, sizeof(from));
/* point to first byte of next field in 'from' */
return from + length;
}
/* Create a packed key that will be used for storage from a MySQL key */ /* Create a packed key that will be used for storage from a MySQL key */
char *Field_blob::pack_key_from_key_image(char *to, const char *from, char *Field_blob::pack_key_from_key_image(char *to, const char *from,
......
...@@ -251,6 +251,10 @@ class Field ...@@ -251,6 +251,10 @@ class Field
{ {
return pack(to,from,max_length); return pack(to,from,max_length);
} }
virtual const char *unpack_key(char* to, const char *from, uint max_length)
{
return unpack(to,from);
}
virtual uint packed_col_length(const char *to, uint length) virtual uint packed_col_length(const char *to, uint length)
{ return length;} { return length;}
virtual uint max_packed_col_length(uint max_length) virtual uint max_packed_col_length(uint max_length)
...@@ -1017,6 +1021,7 @@ class Field_blob :public Field_str { ...@@ -1017,6 +1021,7 @@ class Field_blob :public Field_str {
inline uint32 get_length(uint row_offset=0) inline uint32 get_length(uint row_offset=0)
{ return get_length(ptr+row_offset); } { return get_length(ptr+row_offset); }
uint32 get_length(const char *ptr); uint32 get_length(const char *ptr);
void put_length(char *pos, uint32 length);
inline void get_ptr(char **str) inline void get_ptr(char **str)
{ {
memcpy_fixed(str,ptr+packlength,sizeof(char*)); memcpy_fixed(str,ptr+packlength,sizeof(char*));
...@@ -1049,6 +1054,7 @@ class Field_blob :public Field_str { ...@@ -1049,6 +1054,7 @@ class Field_blob :public Field_str {
const char *unpack(char *to, const char *from); const char *unpack(char *to, const char *from);
char *pack_key(char *to, const char *from, uint max_length); char *pack_key(char *to, const char *from, uint max_length);
char *pack_key_from_key_image(char* to, const char *from, uint max_length); char *pack_key_from_key_image(char* to, const char *from, uint max_length);
const char *unpack_key(char* to, const char *from, uint max_length);
int pack_cmp(const char *a, const char *b, uint key_length); int pack_cmp(const char *a, const char *b, uint key_length);
int pack_cmp(const char *b, uint key_length); int pack_cmp(const char *b, uint key_length);
uint packed_col_length(const char *col_ptr, uint length); uint packed_col_length(const char *col_ptr, uint length);
......
...@@ -724,8 +724,8 @@ void ha_berkeley::unpack_key(char *record, DBT *key, uint index) ...@@ -724,8 +724,8 @@ void ha_berkeley::unpack_key(char *record, DBT *key, uint index)
} }
record[key_part->null_offset]&= ~key_part->null_bit; record[key_part->null_offset]&= ~key_part->null_bit;
} }
pos= (char*) key_part->field->unpack(record + key_part->field->offset(), pos= (char*) key_part->field->unpack_key(record + key_part->field->offset(),
pos); pos, key_part->length);
} }
} }
...@@ -1643,13 +1643,44 @@ int ha_berkeley::rnd_pos(byte * buf, byte *pos) ...@@ -1643,13 +1643,44 @@ int ha_berkeley::rnd_pos(byte * buf, byte *pos)
(char*) buf, primary_key, &current_row, (DBT*) 0, 0)); (char*) buf, primary_key, &current_row, (DBT*) 0, 0));
} }
/*
Set a reference to the current record in (ref,ref_length).
SYNOPSIS
ha_berkeley::position()
record The current record buffer
DESCRIPTION
The BDB handler stores the primary key in (ref,ref_length).
There is either an explicit primary key, or an implicit (hidden)
primary key.
During open(), 'ref_length' is calculated as the maximum primary
key length. When an actual key is shorter than that, the rest of
the buffer must be cleared out. The row cannot be identified, if
garbage follows behind the end of the key. There is no length
field for the current key, so that the whole ref_length is used
for comparison.
RETURN
nothing
*/
void ha_berkeley::position(const byte *record) void ha_berkeley::position(const byte *record)
{ {
DBT key; DBT key;
DBUG_ENTER("ha_berkeley::position");
if (hidden_primary_key) if (hidden_primary_key)
{
DBUG_ASSERT(ref_length == BDB_HIDDEN_PRIMARY_KEY_LENGTH);
memcpy_fixed(ref, (char*) current_ident, BDB_HIDDEN_PRIMARY_KEY_LENGTH); memcpy_fixed(ref, (char*) current_ident, BDB_HIDDEN_PRIMARY_KEY_LENGTH);
}
else else
{
create_key(&key, primary_key, (char*) ref, record); create_key(&key, primary_key, (char*) ref, record);
if (key.size < ref_length)
bzero(ref + key.size, ref_length - key.size);
}
DBUG_VOID_RETURN;
} }
......
...@@ -625,13 +625,12 @@ int ha_rollback_trans(THD *thd, THD_TRANS *trans) ...@@ -625,13 +625,12 @@ int ha_rollback_trans(THD *thd, THD_TRANS *trans)
reinit_io_cache(&thd->transaction.trans_log, reinit_io_cache(&thd->transaction.trans_log,
WRITE_CACHE, (my_off_t) 0, 0, 1); WRITE_CACHE, (my_off_t) 0, 0, 1);
thd->transaction.trans_log.end_of_file= max_binlog_cache_size; thd->transaction.trans_log.end_of_file= max_binlog_cache_size;
if (operation_done)
thd->transaction.cleanup();
} }
thd->variables.tx_isolation=thd->session_tx_isolation; thd->variables.tx_isolation=thd->session_tx_isolation;
if (operation_done) if (operation_done)
{
statistic_increment(ha_rollback_count,&LOCK_status); statistic_increment(ha_rollback_count,&LOCK_status);
thd->transaction.cleanup();
}
} }
#endif /* USING_TRANSACTIONS */ #endif /* USING_TRANSACTIONS */
DBUG_RETURN(error); DBUG_RETURN(error);
......
...@@ -671,8 +671,9 @@ my_bool mysqld_show_warnings(THD *thd, ulong levels_to_show); ...@@ -671,8 +671,9 @@ my_bool mysqld_show_warnings(THD *thd, ulong levels_to_show);
/* sql_handler.cc */ /* sql_handler.cc */
int mysql_ha_open(THD *thd, TABLE_LIST *tables); int mysql_ha_open(THD *thd, TABLE_LIST *tables);
int mysql_ha_close(THD *thd, TABLE_LIST *tables, bool dont_send_ok=0); int mysql_ha_close(THD *thd, TABLE_LIST *tables,
int mysql_ha_closeall(THD *thd, TABLE_LIST *tables); bool dont_send_ok=0, bool dont_lock=0, bool no_alias=0);
int mysql_ha_close_list(THD *thd, TABLE_LIST *tables, bool flushed=0);
int mysql_ha_read(THD *, TABLE_LIST *,enum enum_ha_read_modes,char *, int mysql_ha_read(THD *, TABLE_LIST *,enum enum_ha_read_modes,char *,
List<Item> *,enum ha_rkey_function,Item *,ha_rows,ha_rows); List<Item> *,enum ha_rkey_function,Item *,ha_rows,ha_rows);
......
...@@ -300,6 +300,7 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh, ...@@ -300,6 +300,7 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
thd->proc_info="Flushing tables"; thd->proc_info="Flushing tables";
close_old_data_files(thd,thd->open_tables,1,1); close_old_data_files(thd,thd->open_tables,1,1);
mysql_ha_close_list(thd, tables);
bool found=1; bool found=1;
/* Wait until all threads has closed all the tables we had locked */ /* Wait until all threads has closed all the tables we had locked */
DBUG_PRINT("info", DBUG_PRINT("info",
...@@ -850,6 +851,9 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name, ...@@ -850,6 +851,9 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
DBUG_RETURN(0); DBUG_RETURN(0);
} }
/* close handler tables which are marked for flush */
mysql_ha_close_list(thd, (TABLE_LIST*) NULL, /*flushed*/ 1);
for (table=(TABLE*) hash_search(&open_cache,(byte*) key,key_length) ; for (table=(TABLE*) hash_search(&open_cache,(byte*) key,key_length) ;
table && table->in_use ; table && table->in_use ;
table = (TABLE*) hash_next(&open_cache,(byte*) key,key_length)) table = (TABLE*) hash_next(&open_cache,(byte*) key,key_length))
...@@ -1220,6 +1224,7 @@ bool wait_for_tables(THD *thd) ...@@ -1220,6 +1224,7 @@ bool wait_for_tables(THD *thd)
{ {
thd->some_tables_deleted=0; thd->some_tables_deleted=0;
close_old_data_files(thd,thd->open_tables,0,dropping_tables != 0); close_old_data_files(thd,thd->open_tables,0,dropping_tables != 0);
mysql_ha_close_list(thd, (TABLE_LIST*) NULL, /*flushed*/ 1);
if (!table_is_used(thd->open_tables,1)) if (!table_is_used(thd->open_tables,1))
break; break;
(void) pthread_cond_wait(&COND_refresh,&LOCK_open); (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
......
...@@ -43,7 +43,9 @@ ...@@ -43,7 +43,9 @@
thd->handler_tables=tmp; } thd->handler_tables=tmp; }
static TABLE **find_table_ptr_by_name(THD *thd,const char *db, static TABLE **find_table_ptr_by_name(THD *thd,const char *db,
const char *table_name, bool is_alias); const char *table_name,
bool is_alias, bool dont_lock,
bool *was_flushed);
int mysql_ha_open(THD *thd, TABLE_LIST *tables) int mysql_ha_open(THD *thd, TABLE_LIST *tables)
{ {
...@@ -66,25 +68,61 @@ int mysql_ha_open(THD *thd, TABLE_LIST *tables) ...@@ -66,25 +68,61 @@ int mysql_ha_open(THD *thd, TABLE_LIST *tables)
return 0; return 0;
} }
int mysql_ha_close(THD *thd, TABLE_LIST *tables, bool dont_send_ok)
/*
Close a HANDLER table.
SYNOPSIS
mysql_ha_close()
thd Thread identifier.
tables A list of tables with the first entry to close.
dont_send_ok Suppresses the commands' ok message and
error message and error return.
dont_lock Suppresses the normal locking of LOCK_open.
DESCRIPTION
Though this function takes a list of tables, only the first list entry
will be closed. Broadcasts a COND_refresh condition.
If mysql_ha_close() is not called from the parser, 'dont_send_ok'
must be set.
If the caller did already lock LOCK_open, it must set 'dont_lock'.
IMPLEMENTATION
find_table_ptr_by_name() closes the table, if a FLUSH TABLE is outstanding.
It returns a NULL pointer in this case, but flags the situation in
'was_flushed'. In that case the normal ER_UNKNOWN_TABLE error messages
is suppressed.
RETURN
0 ok
-1 error
*/
int mysql_ha_close(THD *thd, TABLE_LIST *tables,
bool dont_send_ok, bool dont_lock, bool no_alias)
{ {
TABLE **ptr=find_table_ptr_by_name(thd, tables->db, tables->alias, 1); TABLE **table_ptr;
bool was_flushed;
if (*ptr) table_ptr= find_table_ptr_by_name(thd, tables->db, tables->alias,
!no_alias, dont_lock, &was_flushed);
if (*table_ptr)
{ {
(*ptr)->file->ha_index_or_rnd_end(); (*ptr)->file->ha_index_or_rnd_end();
VOID(pthread_mutex_lock(&LOCK_open)); if (!dont_lock)
if (close_thread_table(thd, ptr)) VOID(pthread_mutex_lock(&LOCK_open));
if (close_thread_table(thd, table_ptr))
{ {
/* Tell threads waiting for refresh that something has happened */ /* Tell threads waiting for refresh that something has happened */
VOID(pthread_cond_broadcast(&COND_refresh)); VOID(pthread_cond_broadcast(&COND_refresh));
} }
VOID(pthread_mutex_unlock(&LOCK_open)); if (!dont_lock)
VOID(pthread_mutex_unlock(&LOCK_open));
} }
else else if (!was_flushed && !dont_send_ok)
{ {
my_printf_error(ER_UNKNOWN_TABLE,ER(ER_UNKNOWN_TABLE),MYF(0), my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0),
tables->alias, "HANDLER"); tables->alias, "HANDLER");
return -1; return -1;
} }
if (!dont_send_ok) if (!dont_send_ok)
...@@ -92,16 +130,64 @@ int mysql_ha_close(THD *thd, TABLE_LIST *tables, bool dont_send_ok) ...@@ -92,16 +130,64 @@ int mysql_ha_close(THD *thd, TABLE_LIST *tables, bool dont_send_ok)
return 0; return 0;
} }
int mysql_ha_closeall(THD *thd, TABLE_LIST *tables)
/*
Close a list of HANDLER tables.
SYNOPSIS
mysql_ha_close_list()
thd Thread identifier.
tables The list of tables to close. If NULL,
close all HANDLER tables.
flushed Close only tables which are marked flushed.
Used only if tables is NULL.
DESCRIPTION
The list of HANDLER tables may be NULL, in which case all HANDLER
tables are closed. Broadcasts a COND_refresh condition, for
every table closed. If 'tables' is NULL and 'flushed' is set,
all HANDLER tables marked for flush are closed.
The caller must lock LOCK_open.
IMPLEMENTATION
find_table_ptr_by_name() closes the table, if it is marked for flush.
It returns a NULL pointer in this case, but flags the situation in
'was_flushed'. In that case the normal ER_UNKNOWN_TABLE error messages
is suppressed.
RETURN
0 ok
*/
int mysql_ha_close_list(THD *thd, TABLE_LIST *tables, bool flushed)
{ {
TABLE **ptr=find_table_ptr_by_name(thd, tables->db, tables->real_name, 0); TABLE_LIST *tl_item;
if (*ptr) TABLE **table_ptr;
if (tables)
{ {
(*ptr)->file->ha_index_or_rnd_end(); for (tl_item= tables ; tl_item; tl_item= tl_item->next)
if (close_thread_table(thd, ptr))
{ {
/* Tell threads waiting for refresh that something has happened */ mysql_ha_close(thd, tl_item, /*dont_send_ok*/ 1,
VOID(pthread_cond_broadcast(&COND_refresh)); /*dont_lock*/ 1, /*no_alias*/ 1);
}
}
else
{
table_ptr= &(thd->handler_tables);
while (*table_ptr)
{
if (! flushed || ((*table_ptr)->version != refresh_version))
{
(*table_ptr)->file->ha_index_or_rnd_end();
if (close_thread_table(thd, table_ptr))
{
/* Tell threads waiting for refresh that something has happened */
VOID(pthread_cond_broadcast(&COND_refresh));
}
continue;
}
table_ptr= &((*table_ptr)->next);
} }
} }
return 0; return 0;
...@@ -117,7 +203,10 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, ...@@ -117,7 +203,10 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
ha_rows select_limit,ha_rows offset_limit) ha_rows select_limit,ha_rows offset_limit)
{ {
int err, keyno=-1; int err, keyno=-1;
TABLE *table=*find_table_ptr_by_name(thd, tables->db, tables->alias, 1); bool was_flushed;
TABLE *table= *find_table_ptr_by_name(thd, tables->db, tables->alias,
/*is_alias*/ 1, /*dont_lock*/ 0,
&was_flushed);
if (!table) if (!table)
{ {
my_printf_error(ER_UNKNOWN_TABLE,ER(ER_UNKNOWN_TABLE),MYF(0), my_printf_error(ER_UNKNOWN_TABLE,ER(ER_UNKNOWN_TABLE),MYF(0),
...@@ -298,17 +387,51 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, ...@@ -298,17 +387,51 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
} }
/*
Find a HANDLER table by name.
SYNOPSIS
find_table_ptr_by_name()
thd Thread identifier.
db Database (schema) name.
table_name Table name ;-).
is_alias Table name may be an alias name.
dont_lock Suppresses the normal locking of LOCK_open.
DESCRIPTION
Find the table 'db'.'table_name' in the list of HANDLER tables of the
thread 'thd'. If the table has been marked by FLUSH TABLE(S), close it,
flag this situation in '*was_flushed' and broadcast a COND_refresh
condition.
An empty database (schema) name matches all database (schema) names.
If the caller did already lock LOCK_open, it must set 'dont_lock'.
IMPLEMENTATION
Just in case that the table is twice in 'thd->handler_tables' (!?!),
the loop does not break when the table was flushed. If another table
by that name was found and not flushed, '*was_flushed' is cleared again,
since a pointer to an open HANDLER table is returned.
RETURN
*was_flushed Table has been closed due to FLUSH TABLE.
NULL A HANDLER Table by that name does not exist (any more).
!= NULL Pointer to the TABLE structure.
*/
static TABLE **find_table_ptr_by_name(THD *thd, const char *db, static TABLE **find_table_ptr_by_name(THD *thd, const char *db,
const char *table_name, bool is_alias) const char *table_name,
bool is_alias, bool dont_lock,
bool *was_flushed)
{ {
int dblen; int dblen;
TABLE **ptr; TABLE **table_ptr;
DBUG_ASSERT(db); DBUG_ASSERT(db);
dblen= strlen(db); dblen= strlen(db);
ptr= &(thd->handler_tables); table_ptr= &(thd->handler_tables);
*was_flushed= FALSE;
for (TABLE *table= *ptr; table ; table= *ptr) for (TABLE *table= *table_ptr; table ; table= *table_ptr)
{ {
if ((db == any_db || !memcmp(table->table_cache_key, db, dblen)) && if ((db == any_db || !memcmp(table->table_cache_key, db, dblen)) &&
!my_strcasecmp(system_charset_info, !my_strcasecmp(system_charset_info,
...@@ -317,18 +440,22 @@ static TABLE **find_table_ptr_by_name(THD *thd, const char *db, ...@@ -317,18 +440,22 @@ static TABLE **find_table_ptr_by_name(THD *thd, const char *db,
{ {
if (table->version != refresh_version) if (table->version != refresh_version)
{ {
VOID(pthread_mutex_lock(&LOCK_open)); if (!dont_lock)
if (close_thread_table(thd, ptr)) VOID(pthread_mutex_lock(&LOCK_open));
if (close_thread_table(thd, table_ptr))
{ {
/* Tell threads waiting for refresh that something has happened */ /* Tell threads waiting for refresh that something has happened */
VOID(pthread_cond_broadcast(&COND_refresh)); VOID(pthread_cond_broadcast(&COND_refresh));
} }
VOID(pthread_mutex_unlock(&LOCK_open)); if (!dont_lock)
VOID(pthread_mutex_unlock(&LOCK_open));
*was_flushed= TRUE;
continue; continue;
} }
*was_flushed= FALSE;
break; break;
} }
ptr= &(table->next); table_ptr= &(table->next);
} }
return ptr; return table_ptr;
} }
...@@ -2283,7 +2283,7 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level, ...@@ -2283,7 +2283,7 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
!(cond_func->used_tables() & OUTER_REF_TABLE_BIT)) !(cond_func->used_tables() & OUTER_REF_TABLE_BIT))
add_key_field(key_fields,*and_level,cond_func, add_key_field(key_fields,*and_level,cond_func,
((Item_field*) (cond_func->key_item()->real_item()))-> ((Item_field*) (cond_func->key_item()->real_item()))->
field, 0, field, cond_func->argument_count() == 2,
cond_func->arguments()+1, cond_func->argument_count()-1, cond_func->arguments()+1, cond_func->argument_count()-1,
usable_tables); usable_tables);
break; break;
......
...@@ -191,7 +191,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, ...@@ -191,7 +191,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
for (table=tables ; table ; table=table->next) for (table=tables ; table ; table=table->next)
{ {
char *db=table->db; char *db=table->db;
mysql_ha_closeall(thd, table); mysql_ha_close(thd, table, /*dont_send_ok*/ 1, /*dont_lock*/ 1);
if (!close_temporary_table(thd, db, table->real_name)) if (!close_temporary_table(thd, db, table->real_name))
{ {
tmp_table_deleted=1; tmp_table_deleted=1;
...@@ -1727,7 +1727,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables, ...@@ -1727,7 +1727,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
if (protocol->send_fields(&field_list, 1)) if (protocol->send_fields(&field_list, 1))
DBUG_RETURN(-1); DBUG_RETURN(-1);
mysql_ha_closeall(thd, tables); mysql_ha_close(thd, tables, /*dont_send_ok*/ 1, /*dont_lock*/ 1);
for (table = tables; table; table = table->next) for (table = tables; table; table = table->next)
{ {
char table_name[NAME_LEN*2+2]; char table_name[NAME_LEN*2+2];
...@@ -2254,7 +2254,7 @@ int mysql_discard_or_import_tablespace(THD *thd, ...@@ -2254,7 +2254,7 @@ int mysql_discard_or_import_tablespace(THD *thd,
thd->tablespace_op=TRUE; /* we set this flag so that ha_innobase::open thd->tablespace_op=TRUE; /* we set this flag so that ha_innobase::open
and ::external_lock() do not complain when we and ::external_lock() do not complain when we
lock the table */ lock the table */
mysql_ha_closeall(thd, table_list); mysql_ha_close(thd, table_list, /*dont_send_ok*/ 1, /*dont_lock*/ 1);
if (!(table=open_ltable(thd,table_list,TL_WRITE))) if (!(table=open_ltable(thd,table_list,TL_WRITE)))
{ {
...@@ -2533,7 +2533,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -2533,7 +2533,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
new_db= db; new_db= db;
used_fields=create_info->used_fields; used_fields=create_info->used_fields;
mysql_ha_closeall(thd, table_list); mysql_ha_close(thd, table_list, /*dont_send_ok*/ 1, /*dont_lock*/ 1);
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */ /* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */
if (alter_info->tablespace_op != NO_TABLESPACE_OP) if (alter_info->tablespace_op != NO_TABLESPACE_OP)
...@@ -2588,7 +2588,10 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -2588,7 +2588,10 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
} }
} }
else else
new_alias= new_name= table_name; {
new_alias= (lower_case_table_names == 2) ? alias : table_name;
new_name= table_name;
}
old_db_type=table->db_type; old_db_type=table->db_type;
if (create_info->db_type == DB_TYPE_DEFAULT) if (create_info->db_type == DB_TYPE_DEFAULT)
......
...@@ -91,7 +91,12 @@ main(int argc __attribute__((unused)), char** argv) ...@@ -91,7 +91,12 @@ main(int argc __attribute__((unused)), char** argv)
struct sockaddr_in sa_cli; struct sockaddr_in sa_cli;
int listen_sd; int listen_sd;
int err; int err;
#if defined(__sgi) && _NO_XOPEN4 && _NO_XOPEN5
socklen_t client_len;
#else
size_t client_len; size_t client_len;
#endif
int reuseaddr = 1; /* better testing, uh? */ int reuseaddr = 1; /* better testing, uh? */
MY_INIT(argv[0]); MY_INIT(argv[0]);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment