Merge work:/home/bk/mysql-4.1 into mashka.mysql.fi:/home/my/mysql-4.1

This commit is contained in:
monty@mashka.mysql.fi 2003-01-09 22:43:23 +02:00
commit c9dc5a206b
37 changed files with 707 additions and 227 deletions

View File

@ -135,6 +135,7 @@ $ENV{'MYSQL_UNIX_PORT'}=$mysql_unix_port="$opt_tmp/mysql$opt_suffix.build";
$ENV{"PERL5LIB"}="$pwd/$host/perl5:$pwd/$host/perl5/site_perl";
$slave_port=$mysql_tcp_port+16;
$manager_port=$mysql_tcp_port+1;
$mysqladmin_args="--no-defaults -u root --connect_timeout=5 --shutdown_timeout=20";
if ($opt_stage == 0)
{
@ -154,13 +155,18 @@ log_timestamp();
if (-x "$host/bin/mysqladmin")
{
log_system("$host/bin/mysqladmin --no-defaults -u root -S $mysql_unix_port -s shutdown");
log_system("$host/bin/mysqladmin --no-defaults -u root -P $mysql_tcp_port -h $host -s shutdown");
log_system("$host/bin/mysqladmin --no-defaults -u root -P $slave_port -h $host -s shutdown");
log_system("$host/bin/mysqladmin --no-defaults -u root -P 9306 -h $host -s shutdown");
log_system("$host/bin/mysqladmin --no-defaults -u root -P 9307 -h $host -s shutdown");
log_system("$host/bin/mysqladmin $mysqladmin_args -S $mysql_unix_port -s shutdown");
log_system("$host/bin/mysqladmin $mysqladmin_args -P $mysql_tcp_port -h $host -s shutdown");
log_system("$host/bin/mysqladmin $mysqladmin_args -P $slave_port -h $host -s shutdown");
log_system("$host/bin/mysqladmin $mysqladmin_args -P 9306 -h $host -s shutdown");
log_system("$host/bin/mysqladmin $mysqladmin_args -P 9307 -h $host -s shutdown");
}
kill_all("mysqlmanager");
#
# Kill all old processes that are in the build directories
# This is to find any old mysqld servers left from previous builds
kill_all("$pwd/host/mysql");
kill_all("$pwd/host/test");
if ($opt_stage == 0)
{
@ -308,8 +314,9 @@ if ($opt_stage <= 4 && !$opt_no_test)
$tar_file =~ /(mysql[^\/]*)\.tar/;
$ver=$1;
$test_dir="$pwd/$host/test/$ver";
$ENV{"LD_LIBRARY_PATH"}= "$test_dir/lib:" . $ENV{"LD_LIBRARY_PATH"};
$ENV{"LD_LIBRARY_PATH"}= ("$test_dir/lib" .
(defined($ENV{"LD_LIBRARY_PATH"}) ?
":" . $ENV{"LD_LIBRARY_PATH"} : ""));
#
# Run the test suite
#
@ -328,7 +335,7 @@ if (!$opt_no_test && !$opt_no_benchmark)
{
my $extra;
safe_cd($test_dir);
log_system("./bin/mysqladmin --no-defaults -u root -S $mysql_unix_port -s shutdown") || info("There was no mysqld running\n");
log_system("./bin/mysqladmin $mysqladmin_args -S $mysql_unix_port -s shutdown") || info("There was no mysqld running\n");
sleep(2);
log_system("rm -f ./data/mysql/*");
check_system("scripts/mysql_install_db --no-defaults --skip-locking","https://order");
@ -418,7 +425,7 @@ if ($opt_stage <= 9 && !$opt_no_test && !$opt_no_benchmark)
rm_all($bench_tmpdir);
rm_all("$opt_tmp") if ($new_opt_tmp);
log_system("$pwd/$host/bin/mysqladmin --no-defaults -S $mysql_unix_port -u root shutdown");
log_system("$pwd/$host/bin/mysqladmin $mysqladmin_args -S $mysql_unix_port -u root shutdown");
print LOG "ok\n";
close LOG;
print "$host: ok\n";
@ -429,7 +436,7 @@ exit 0;
sub usage
{
print <<EOF;
$0 version 1.4
$0 version 1.5
$0 takes the following options:

View File

@ -96,13 +96,84 @@ cached for each user/database combination.
Many use of @code{GROUP BY} or @code{DISTINCT} caches all found rows in
a @code{HEAP} table. (This is a very quick in-memory table with hash index.)
@item Join Row Cache
@item Join buffer Cache
For every full join in a @code{SELECT} statement (a full join here means
there were no keys that one could use to find the next table in a list),
the found rows are cached in a join cache. One @code{SELECT} query can
use many join caches in the worst case.
@end table
@node join_buffer_size, flush tables, caching, Top
@subchapter How MySQL uses the join_buffer cache
Basic information about @code{join_buffer_size}:
@itemize @bullet
@item
It's only used in the case when join type is of type @code{ALL} or
@code{index}; In other words: no possible keys can be used.
@item
A join buffer is never allocated for the first not-const table,
even it it would be of type @code{ALL}/@code{index}.
@item
The buffer is allocated when we need to do a each full join between two
tables and freed after the query is done.
@item
Accepted row combinations of tables before the @code{ALL}/@code{index}
able is stored in the cache and is used to compare against each read
row in the @code{ALL} table.
@item
We only store the used fields in the join_buffer cache, not the
whole rows.
@end itemize
Assume you have the following join:
@example
Table name Type
t1 range
t2 ref
t3 @code{ALL}
@end example
The join is then done as follows:
@example
- While rows in t1 matching range
- Read through all rows in t2 according to reference key
- Store used fields form t1,t2 in cache
- If cache is full
- Read through all rows in t3
- Compare t3 row against all t1,t2 combination in cache
- If rows satisfying join condition, send it to client
- Empty cache
- Read through all rows in t3
- Compare t3 row against all stored t1,t2 combinations in cache
- If rows satisfying join condition, send it to client
@end example
The above means that table t3 is scanned
@example
(size-of-stored-row(t1,t2) * accepted-row-cominations(t1,t2))/
join_buffer_size+1
@end example
times.
Some conclusions:
@itemize @bullet
@item
The larger the join_buff_size, the fewer scans of t3.
If @code{join_buff_size} is already large enough to hold all previous row
combinations then there is no speed to gain by making it bigger.
@item
If there is several tables of @code{ALL}/@code{index} then the we
allocate one @code{join_buffer_size buffer} for each of them and use the
same algorithm described above to handle it. (In other words, we store
the same row combination several times into different buffers)
@end itemize
@node flush tables, filesort, caching, Top
@chapter How MySQL Handles @code{FLUSH TABLES}

View File

@ -25,7 +25,7 @@
#include <sys/stat.h>
#include <mysql.h>
#define ADMIN_VERSION "8.38"
#define ADMIN_VERSION "8.39"
#define MAX_MYSQL_VAR 128
#define SHUTDOWN_DEF_TIMEOUT 3600 /* Wait for shutdown */
#define MAX_TRUNC_LENGTH 3
@ -76,8 +76,8 @@ static void print_relative_header();
static void print_relative_line();
static void truncate_names();
static my_bool get_pidfile(MYSQL *mysql, char *pidfile);
static void wait_pidfile(char *pidfile, time_t last_modified,
struct stat *pidfile_status);
static my_bool wait_pidfile(char *pidfile, time_t last_modified,
struct stat *pidfile_status);
static void store_values(MYSQL_RES *result);
/*
@ -513,7 +513,8 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
printf("Shutdown signal sent to server; Waiting for pid file to disappear\n");
/* Wait until pid file is gone */
wait_pidfile(pidfile, last_modified, &pidfile_status);
if (wait_pidfile(pidfile, last_modified, &pidfile_status))
return -1;
}
break;
}
@ -1150,34 +1151,51 @@ static my_bool get_pidfile(MYSQL *mysql, char *pidfile)
return 1; /* Error */
}
/*
Return 1 if pid file didn't disappear or change
*/
static void wait_pidfile(char *pidfile, time_t last_modified,
struct stat *pidfile_status)
static my_bool wait_pidfile(char *pidfile, time_t last_modified,
struct stat *pidfile_status)
{
char buff[FN_REFLEN];
int fd = -1;
uint count=0;
int error= 1;
uint count= 0;
DBUG_ENTER("wait_pidfile");
system_filename(buff, pidfile);
while (count++ <= opt_shutdown_timeout && !interrupted &&
(!last_modified || (last_modified == pidfile_status->st_mtime)) &&
(fd= my_open(buff, O_RDONLY, MYF(0))) >= 0)
do
{
if (!my_close(fd,MYF(0)))
fd= -1;
int fd;
if ((fd= my_open(buff, O_RDONLY, MYF(0))) < 0)
{
error= 0;
break;
}
(void) my_close(fd,MYF(0));
if (last_modified && !stat(pidfile, pidfile_status))
{
if (last_modified != pidfile_status->st_mtime)
{
/* File changed; Let's assume that mysqld did restart */
if (opt_verbose)
printf("pid file '%s' changed while waiting for it to disappear!\nmysqld did probably restart\n",
buff);
error= 0;
break;
}
}
if (count++ == opt_shutdown_timeout)
break;
sleep(1);
if (last_modified && stat(pidfile, pidfile_status))
last_modified= 0;
}
if (opt_verbose && last_modified &&
last_modified != pidfile_status->st_mtime)
printf("Warning; pid file '%s' changed while waiting for it to disappear!\n",
buff);
if (fd >= 0)
} while (!interrupted);
if (error)
{
my_close(fd,MYF(0));
DBUG_PRINT("warning",("Pid file didn't disappear"));
fprintf(stderr,
"Warning; Aborted waiting on pid file: '%s' after %d seconds\n",
buff, count-1);
}
DBUG_RETURN(error);
}

View File

@ -42,7 +42,7 @@
**********************************************************************/
#define MTEST_VERSION "1.25"
#define MTEST_VERSION "1.26"
#include <my_global.h>
#include <mysql_embed.h>
@ -1809,10 +1809,8 @@ int read_query(struct st_query** q_ptr)
static struct my_option my_long_options[] =
{
#ifndef DBUG_OFF
{"debug", '#', "Output debug log. Often this is 'd:t:o,filename'",
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
#endif
{"database", 'D', "Database to use.", (gptr*) &db, (gptr*) &db, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"basedir", 'b', "Basedir for tests", (gptr*) &opt_basedir,
@ -1905,7 +1903,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
{
switch(optid) {
case '#':
#ifndef DBUG_OFF
DBUG_PUSH(argument ? argument : "d:t:S:i:O,/tmp/mysqltest.trace");
#endif
break;
case 'r':
record = 1;
@ -1983,7 +1983,7 @@ int parse_args(int argc, char **argv)
default_argv= argv;
if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
exit(ho_error);
exit(1);
if (argc > 1)
{

View File

@ -18,7 +18,7 @@ INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include
LDADD = @CLIENT_EXTRA_LDFLAGS@ ../mysys/libmysys.a \
../dbug/libdbug.a ../strings/libmystrings.a
bin_PROGRAMS = replace comp_err perror resolveip my_print_defaults \
resolve_stack_dump mysql_install
resolve_stack_dump mysql_install mysql_waitpid
# Don't update the files from bitkeeper
%::SCCS/s.%

86
extra/mysql_waitpid.c Normal file
View File

@ -0,0 +1,86 @@
#include <sys/types.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
#include <my_global.h>
#include <my_getopt.h>
static const char *VER= "1.1";
static char *progname;
static my_bool verbose;
void usage(void);
static struct my_option my_long_options[] =
{
{"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
0, 0, 0, 0, 0},
{"help", 'I', "Synonym for -?.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
0, 0, 0, 0, 0},
{"verbose", 'v',
"Be more verbose. Give a warning, if kill can't handle signal 0.",
(gptr*) &verbose, (gptr*) &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"version", 'V', "Print version information and exit.", 0, 0, 0,
GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
static my_bool
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
char *argument __attribute__((unused)))
{
switch(optid) {
case 'V':
printf("%s version %s by Jani Tolonen\n", progname, VER);
exit(-1);
case 'I':
case '?':
usage();
}
return 0;
}
int main(int argc, char *argv[])
{
int pid= 0, t= 0, sig= 0;
progname= argv[0];
if (handle_options(&argc, &argv, my_long_options, get_one_option))
exit(-1);
if (!argv[0] || !argv[1] || (pid= atoi(argv[0])) <= 0 ||
(t= atoi(argv[1])) <= 0)
usage();
for (; t > 0; t--)
{
if (kill((pid_t) pid, sig))
{
if (errno == EINVAL)
{
if (verbose)
printf("WARNING: kill couldn't handle signal 0, using signal 1.\n");
sig= 1;
t++;
continue;
}
return 0;
}
sleep(1);
}
return 1;
}
void usage(void)
{
printf("%s version %s by Jani Tolonen\n\n", progname, VER);
printf("usage: %s [options] #pid #time\n\n", progname);
printf("Description: Waits for a program, which program id is #pid, to\n");
printf("terminate within #time seconds. If the program terminates within\n");
printf("this time, or if the #pid no longer exists, value 0 is returned.\n");
printf("Otherwise 1 is returned. Both #pid and #time must be positive\n");
printf("integer arguments.\n\n");
printf("Options:\n");
my_print_help(my_long_options);
exit(-1);
}

View File

@ -264,6 +264,7 @@ enum ha_base_keytype {
#define MBR_EQUAL 8192
#define MBR_DATA 16384
#define SEARCH_NULL_ARE_EQUAL 32768 /* NULL in keys are equal */
#define SEARCH_NULL_ARE_NOT_EQUAL 65536 /* NULL in keys are not equal */
/* bits in opt_flag */
#define QUICK_USED 1

View File

@ -97,6 +97,7 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio)
r=_mi_search(aio->info, aio->keyinfo, aio->keybuff, keylen,
SEARCH_FIND | SEARCH_PREFIX, aio->key_root);
aio->info->update|= HA_STATE_AKTIV; /* for _mi_test_if_changed() */
while (!r)
{

View File

@ -601,7 +601,8 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
if (*keys != 1L) /* not first_key */
{
uint diff;
ha_key_cmp(keyinfo->seg,info->lastkey,key,USE_WHOLE_KEY,SEARCH_FIND,
ha_key_cmp(keyinfo->seg,info->lastkey,key,USE_WHOLE_KEY,
SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL,
&diff);
param->unique_count[diff-1]++;
}

View File

@ -55,12 +55,17 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
/*
Free buffers and reset the following flags:
EXTRA_CACHE, EXTRA_WRITE_CACHE, EXTRA_KEYREAD, EXTRA_QUICK
If the row buffer cache is large (for dynamic tables), reduce it
to save memory.
*/
if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
{
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
error=end_io_cache(&info->rec_cache);
}
if (share->base.blobs)
mi_alloc_rec_buff(info, -1, &info->rec_buff);
#if defined(HAVE_MMAP) && defined(HAVE_MADVICE)
if (info->opt_flag & MEMMAP_USED)
madvise(share->file_map,share->state.state.data_file_length,MADV_RANDOM);

View File

@ -573,28 +573,36 @@ err:
DBUG_RETURN (NULL);
} /* mi_open */
byte *mi_alloc_rec_buff(MI_INFO *info, ulong length, byte **buf)
{
uint extra;
uint32 old_length;
LINT_INIT(old_length);
if (! *buf || length > mi_get_rec_buff_len(info, *buf))
if (! *buf || length > (old_length=mi_get_rec_buff_len(info, *buf)))
{
byte *newptr = *buf;
/* to simplify initial init of info->rec_buf in mi_open and mi_extra */
if (length == (ulong) -1)
{
length= max(info->s->base.pack_reclength+info->s->base.pack_bits,
info->s->base.max_key_length);
/* Avoid unnecessary realloc */
if (newptr && length == old_length)
return newptr;
}
extra= ((info->s->options & HA_OPTION_PACK_RECORD) ?
ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER)+MI_SPLIT_LENGTH+
MI_REC_BUFF_OFFSET : 0);
if (extra && newptr)
newptr-=MI_REC_BUFF_OFFSET;
newptr-= MI_REC_BUFF_OFFSET;
if (!(newptr=(byte*) my_realloc((gptr)newptr, length+extra+8,
MYF(MY_ALLOW_ZERO_PTR))))
return newptr;
*((uint *)newptr)=length;
*((uint32 *) newptr)= (uint32) length;
*buf= newptr+(extra ? MI_REC_BUFF_OFFSET : 0);
}
return *buf;

View File

@ -260,9 +260,11 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
uchar *key, uint key_len, uint nextflag, uchar **ret_pos,
uchar *buff, my_bool *last_key)
{
/* my_flag is raw comparison result to be changed according to
SEARCH_NO_FIND,SEARCH_LAST and HA_REVERSE_SORT flags.
flag is the value returned by ha_key_cmp and as treated as final */
/*
my_flag is raw comparison result to be changed according to
SEARCH_NO_FIND,SEARCH_LAST and HA_REVERSE_SORT flags.
flag is the value returned by ha_key_cmp and as treated as final
*/
int flag=0, my_flag=-1;
uint nod_flag, length, len, matched, cmplen, kseg_len;
uint prefix_len,suffix_len;

View File

@ -385,7 +385,7 @@ typedef struct st_mi_sort_param
#define MI_DYN_ALIGN_SIZE 4 /* Align blocks on this */
#define MI_MAX_DYN_HEADER_BYTE 13 /* max header byte for dynamic rows */
#define MI_MAX_BLOCK_LENGTH ((((ulong) 1 << 24)-1) & (~ (ulong) (MI_DYN_ALIGN_SIZE-1)))
#define MI_REC_BUFF_OFFSET ALIGN_SIZE(MI_DYN_DELETE_BLOCK_HEADER+sizeof(uint))
#define MI_REC_BUFF_OFFSET ALIGN_SIZE(MI_DYN_DELETE_BLOCK_HEADER+sizeof(uint32))
#define MEMMAP_EXTRA_MARGIN 7 /* Write this as a suffix for file */
@ -554,7 +554,7 @@ extern byte *mi_alloc_rec_buff(MI_INFO *,ulong, byte**);
((((info)->s->options & HA_OPTION_PACK_RECORD) && (buf)) ? \
(buf) - MI_REC_BUFF_OFFSET : (buf))
#define mi_get_rec_buff_len(info,buf) \
(*((uint *)(mi_get_rec_buff_ptr(info,buf))))
(*((uint32 *)(mi_get_rec_buff_ptr(info,buf))))
extern ulong _mi_rec_unpack(MI_INFO *info,byte *to,byte *from,
ulong reclength);

View File

@ -88,6 +88,7 @@ sleep_until_file_created ()
wait_for_pid()
{
pid=$1
#$WAIT_PID pid $SLEEP_TIME_FOR_DELETE
}
# No paths below as we can't be sure where the program is!
@ -347,9 +348,9 @@ while test $# -gt 0; do
;;
--debug)
EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT \
--debug=d:t:i:O,$MYSQL_TEST_DIR/var/log/master.trace"
--debug=d:t:i:A,$MYSQL_TEST_DIR/var/log/master.trace"
EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT \
--debug=d:t:i:O,$MYSQL_TEST_DIR/var/log/slave.trace"
--debug=d:t:i:A,$MYSQL_TEST_DIR/var/log/slave.trace"
EXTRA_MYSQL_TEST_OPT="$EXTRA_MYSQL_TEST_OPT --debug"
;;
--fast)
@ -423,6 +424,7 @@ if [ x$SOURCE_DIST = x1 ] ; then
fi
MYSQLADMIN="$BASEDIR/client/mysqladmin"
WAIT_PID="$BASEDIR/extra/mysql_waitpid"
MYSQL_MANAGER_CLIENT="$BASEDIR/client/mysqlmanagerc"
MYSQL_MANAGER="$BASEDIR/tools/mysqlmanager"
MYSQL_MANAGER_PWGEN="$BASEDIR/client/mysqlmanager-pwgen"
@ -439,6 +441,7 @@ else
fi
MYSQL_TEST="$BASEDIR/bin/mysqltest"
MYSQLADMIN="$BASEDIR/bin/mysqladmin"
WAIT_PID="$BASEDIR/bin/mysql_waitpid"
MYSQL_MANAGER="$BASEDIR/bin/mysqlmanager"
MYSQL_MANAGER_CLIENT="$BASEDIR/bin/mysqlmanagerc"
MYSQL_MANAGER_PWGEN="$BASEDIR/bin/mysqlmanager-pwgen"
@ -753,9 +756,9 @@ manager_term()
{
pid=$1
ident=$2
shift
if [ $USE_MANAGER = 0 ] ; then
$MYSQLADMIN --no-defaults -uroot --socket=$MYSQL_TMP_DIR/$ident.sock --connect_timeout=5 --shutdown_timeout=20 shutdown >> $MYSQL_MANAGER_LOG 2>&1
# Shutdown time must be high as slave may be in reconnect
$MYSQLADMIN --no-defaults -uroot --socket=$MYSQL_TMP_DIR/$ident.sock --connect_timeout=5 --shutdown_timeout=70 shutdown >> $MYSQL_MANAGER_LOG 2>&1
res=$?
# Some systems require an extra connect
$MYSQLADMIN --no-defaults -uroot --socket=$MYSQL_TMP_DIR/$ident.sock --connect_timeout=1 ping >> $MYSQL_MANAGER_LOG 2>&1
@ -875,8 +878,8 @@ start_slave()
[ x$SKIP_SLAVE = x1 ] && return
eval "this_slave_running=\$SLAVE$1_RUNNING"
[ x$this_slave_running = 1 ] && return
#when testing fail-safe replication, we will have more than one slave
#in this case, we start secondary slaves with an argument
# When testing fail-safe replication, we will have more than one slave
# in this case, we start secondary slaves with an argument
slave_ident="slave$1"
if [ -n "$1" ] ;
then
@ -984,9 +987,12 @@ EOF
mysql_start ()
{
$ECHO "Starting MySQL daemon"
start_master
start_slave
# We should not start the deamon here as we don't know the argumens
# for the test. Better to let the test start the deamon
# $ECHO "Starting MySQL daemon"
# start_master
# start_slave
cd $MYSQL_TEST_DIR
return 1
}
@ -1087,8 +1093,6 @@ run_testcase ()
slave_init_script=$TESTDIR/$tname-slave.sh
slave_master_info_file=$TESTDIR/$tname-slave-master-info.opt
echo $tname > $CURRENT_TEST
echo "CURRENT_TEST: $tname" >> $SLAVE_MYERR
echo "CURRENT_TEST: $tname" >> $MASTER_MYERR
SKIP_SLAVE=`$EXPR \( $tname : rpl \) = 0`
if [ $USE_MANAGER = 1 ] ; then
many_slaves=`$EXPR \( $tname : rpl_failsafe \) != 0`
@ -1125,13 +1129,17 @@ run_testcase ()
then
EXTRA_MASTER_OPT=`$CAT $master_opt_file | $SED -e "s;\\$MYSQL_TEST_DIR;$MYSQL_TEST_DIR;"`
stop_master
echo "CURRENT_TEST: $tname" >> $MASTER_MYERR
start_master
else
if [ ! -z "$EXTRA_MASTER_OPT" ] || [ x$MASTER_RUNNING != x1 ] ;
then
EXTRA_MASTER_OPT=""
stop_master
echo "CURRENT_TEST: $tname" >> $MASTER_MYERR
start_master
else
echo "CURRENT_TEST: $tname" >> $MASTER_MYERR
fi
fi
@ -1161,7 +1169,10 @@ run_testcase ()
if [ x$do_slave_restart = x1 ] ; then
stop_slave
echo "CURRENT_TEST: $tname" >> $SLAVE_MYERR
start_slave
else
echo "CURRENT_TEST: $tname" >> $SLAVE_MYERR
fi
if [ x$many_slaves = x1 ]; then
start_slave 1

View File

@ -1,4 +1,4 @@
drop table if exists t1;
drop table if exists t1,t2;
CREATE TABLE t1 (
STRING_DATA char(255) default NULL,
KEY string_data (STRING_DATA)
@ -316,3 +316,51 @@ CREATE TABLE t1 (a varchar(255), b varchar(255), c varchar(255));
ALTER TABLE t1 ADD INDEX t1 (a, b, c);
Specified key was too long. Max key length is 500
DROP TABLE t1;
CREATE TABLE t1 (a int not null, b int, c int, key(b), key(c), key(a,b), key(c,a));
INSERT into t1 values (0, null, 0), (0, null, 1), (0, null, 2), (0, null,3), (1,1,4);
create table t2 (a int not null, b int, c int, key(b), key(c), key(a));
INSERT into t2 values (1,1,1), (2,2,2);
optimize table t1;
Table Op Msg_type Msg_text
test.t1 optimize status OK
show index from t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
t1 1 b 1 b A 5 NULL NULL YES BTREE
t1 1 c 1 c A 5 NULL NULL YES BTREE
t1 1 a 1 a A 1 NULL NULL BTREE
t1 1 a 2 b A 5 NULL NULL YES BTREE
t1 1 c_2 1 c A 5 NULL NULL YES BTREE
t1 1 c_2 2 a A 5 NULL NULL BTREE
explain select * from t1,t2 where t1.a=t2.a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL a NULL NULL NULL 5
1 SIMPLE t2 ALL a NULL NULL NULL 2 Using where
explain select * from t1,t2 force index(a) where t1.a=t2.a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL a NULL NULL NULL 2
1 SIMPLE t1 ALL a NULL NULL NULL 5 Using where
explain select * from t1 force index(a),t2 force index(a) where t1.a=t2.a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL a NULL NULL NULL 2
1 SIMPLE t1 ref a a 4 t2.a 3
explain select * from t1,t2 where t1.b=t2.b;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL b NULL NULL NULL 2
1 SIMPLE t1 ref b b 5 t2.b 1 Using where
explain select * from t1,t2 force index(c) where t1.a=t2.a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL a NULL NULL NULL 5
1 SIMPLE t2 ALL NULL NULL NULL NULL 2 Using where
explain select * from t1 where a=0 or a=2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL a NULL NULL NULL 5 Using where
explain select * from t1 force index (a) where a=0 or a=2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range a a 4 NULL 4 Using where
explain select * from t1 where c=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref c,c_2 c 5 const 1 Using where
explain select * from t1 use index() where c=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where
drop table t1,t2;

View File

@ -2,10 +2,15 @@
# Test bugs in the MyISAM code
#
# Initialise
--disable_warnings
drop table if exists t1;
drop table if exists t1,t2;
--enable_warnings
#
# Test problem with CHECK TABLE;
#
CREATE TABLE t1 (
STRING_DATA char(255) default NULL,
KEY string_data (STRING_DATA)
@ -327,3 +332,23 @@ CREATE TABLE t1 (a varchar(255), b varchar(255), c varchar(255));
ALTER TABLE t1 ADD INDEX t1 (a, b, c);
DROP TABLE t1;
#
# Test of cardinality of keys with NULL
#
CREATE TABLE t1 (a int not null, b int, c int, key(b), key(c), key(a,b), key(c,a));
INSERT into t1 values (0, null, 0), (0, null, 1), (0, null, 2), (0, null,3), (1,1,4);
create table t2 (a int not null, b int, c int, key(b), key(c), key(a));
INSERT into t2 values (1,1,1), (2,2,2);
optimize table t1;
show index from t1;
explain select * from t1,t2 where t1.a=t2.a;
explain select * from t1,t2 force index(a) where t1.a=t2.a;
explain select * from t1 force index(a),t2 force index(a) where t1.a=t2.a;
explain select * from t1,t2 where t1.b=t2.b;
explain select * from t1,t2 force index(c) where t1.a=t2.a;
explain select * from t1 where a=0 or a=2;
explain select * from t1 force index (a) where a=0 or a=2;
explain select * from t1 where c=1;
explain select * from t1 use index() where c=1;
drop table t1,t2;

View File

@ -40,15 +40,33 @@ static int compare_bin(uchar *a, uint a_length, uchar *b, uint b_length,
return (int) (a_length-b_length);
}
#define FCMP(A,B) ((int) (A) - (int) (B))
/*
Compare two keys
Returns <0, 0, >0 acording to which is bigger
Key_length specifies length of key to use. Number-keys can't be splited
If flag <> SEARCH_FIND compare also position
SYNOPSIS
ha_key_cmp()
keyseg Key segments of key to compare
a First key to compare, in format from _mi_pack_key()
This is normally key specified by user
b Second key to compare. This is always from a row
key_length Length of key to compare. This can be shorter than
a to just compare sub keys
next_flag How keys should be compared
If bit SEARCH_FIND is not set the keys includes the row
position and this should also be compared
NOTES
Number-keys can't be splited
RETURN VALUES
<0 If a < b
0 If a == b
>0 If a > b
*/
#define FCMP(A,B) ((int) (A) - (int) (B))
int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
register uchar *b, uint key_length, uint nextflag,
uint *diff_pos)
@ -59,9 +77,10 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
uint32 u_1,u_2;
float f_1,f_2;
double d_1,d_2;
uint next_key_length;
*diff_pos=0;
for ( ; (int) key_length >0 ; keyseg++)
for ( ; (int) key_length >0 ; key_length=next_key_length, keyseg++)
{
uchar *end;
uint piks=! (keyseg->flag & HA_NO_SORT);
@ -81,10 +100,21 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
{
if (nextflag == (SEARCH_FIND | SEARCH_UPDATE))
nextflag=SEARCH_SAME; /* Allow duplicate keys */
else if (nextflag & SEARCH_NULL_ARE_NOT_EQUAL)
{
/*
This is only used from mi_check() to calculate cardinality.
It can't be used when searching for a key as this would cause
compare of (a,b) and (b,a) to return the same value.
*/
return -1;
}
next_key_length=key_length;
continue; /* To next key part */
}
}
end= a+ min(keyseg->length,key_length);
next_key_length=key_length-keyseg->length;
switch ((enum ha_base_keytype) keyseg->type) {
case HA_KEYTYPE_TEXT: /* Ascii; Key is converted */
@ -93,12 +123,12 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
int a_length,b_length,pack_length;
get_key_length(a_length,a);
get_key_pack_length(b_length,pack_length,b);
key_length-= b_length + pack_length;
next_key_length=key_length-b_length-pack_length;
if (piks &&
(flag= mi_compare_text(keyseg->charset,a,a_length,b,b_length,
(my_bool) ((nextflag & SEARCH_PREFIX) &&
key_length <= 0))))
(flag=mi_compare_text(keyseg->charset,a,a_length,b,b_length,
(my_bool) ((nextflag & SEARCH_PREFIX) &&
next_key_length <= 0))))
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a+=a_length;
b+=b_length;
@ -107,7 +137,6 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
else
{
uint length=(uint) (end-a), a_length=length, b_length=length;
key_length-= keyseg->length;
if (!(nextflag & SEARCH_PREFIX))
{
while (a_length && a[a_length-1] == ' ')
@ -116,9 +145,9 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
b_length--;
}
if (piks &&
(flag= mi_compare_text(keyseg->charset,a,a_length,b,b_length,
(my_bool) ((nextflag & SEARCH_PREFIX) &&
key_length <= 0))))
(flag= mi_compare_text(keyseg->charset, a, a_length, b, b_length,
(my_bool) ((nextflag & SEARCH_PREFIX) &&
next_key_length <= 0))))
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a=end;
b+=length;
@ -130,12 +159,12 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
int a_length,b_length,pack_length;
get_key_length(a_length,a);
get_key_pack_length(b_length,pack_length,b);
key_length-= b_length + pack_length;
next_key_length=key_length-b_length-pack_length;
if (piks &&
(flag=compare_bin(a,a_length,b,b_length,
(my_bool) ((nextflag & SEARCH_PREFIX) &&
key_length <= 0))))
next_key_length <= 0))))
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a+=a_length;
b+=b_length;
@ -144,11 +173,10 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
else
{
uint length=keyseg->length;
key_length-= keyseg->length;
if (piks &&
(flag=compare_bin(a,length,b,length,
(my_bool) ((nextflag & SEARCH_PREFIX) &&
key_length <= 0))))
next_key_length <= 0))))
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a+=length;
b+=length;
@ -159,12 +187,12 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
int a_length,b_length,pack_length;
get_key_length(a_length,a);
get_key_pack_length(b_length,pack_length,b);
key_length-= b_length + pack_length;
next_key_length=key_length-b_length-pack_length;
if (piks &&
(flag= mi_compare_text(keyseg->charset,a,a_length,b,b_length,
(my_bool) ((nextflag & SEARCH_PREFIX) &&
key_length <= 0))))
next_key_length <= 0))))
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a+=a_length;
b+=b_length;
@ -176,12 +204,12 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
int a_length,b_length,pack_length;
get_key_length(a_length,a);
get_key_pack_length(b_length,pack_length,b);
key_length-= b_length + pack_length;
next_key_length=key_length-b_length-pack_length;
if (piks &&
(flag=compare_bin(a,a_length,b,b_length,
(my_bool) ((nextflag & SEARCH_PREFIX) &&
key_length <= 0))))
next_key_length <= 0))))
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a+=a_length;
b+=b_length;
@ -196,7 +224,6 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a= end;
b++;
key_length-= keyseg->length;
break;
}
case HA_KEYTYPE_SHORT_INT:
@ -206,7 +233,6 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a= end;
b+= 2; /* sizeof(short int); */
key_length-= keyseg->length;
break;
case HA_KEYTYPE_USHORT_INT:
{
@ -217,7 +243,6 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a= end;
b+=2; /* sizeof(short int); */
key_length-= keyseg->length;
break;
}
case HA_KEYTYPE_LONG_INT:
@ -227,7 +252,6 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a= end;
b+= 4; /* sizeof(long int); */
key_length-= keyseg->length;
break;
case HA_KEYTYPE_ULONG_INT:
u_1= mi_sint4korr(a);
@ -236,7 +260,6 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a= end;
b+= 4; /* sizeof(long int); */
key_length-= keyseg->length;
break;
case HA_KEYTYPE_INT24:
l_1=mi_sint3korr(a);
@ -245,7 +268,6 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a= end;
b+= 3;
key_length-= keyseg->length;
break;
case HA_KEYTYPE_UINT24:
l_1=mi_uint3korr(a);
@ -254,7 +276,6 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a= end;
b+= 3;
key_length-= keyseg->length;
break;
case HA_KEYTYPE_FLOAT:
mi_float4get(f_1,a);
@ -263,7 +284,6 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a= end;
b+= 4; /* sizeof(float); */
key_length-= keyseg->length;
break;
case HA_KEYTYPE_DOUBLE:
mi_float8get(d_1,a);
@ -272,13 +292,12 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a= end;
b+= 8; /* sizeof(double); */
key_length-= keyseg->length;
break;
case HA_KEYTYPE_NUM: /* Numeric key */
{
int swap_flag= 0;
int alength,blength;
if (keyseg->flag & HA_REVERSE_SORT)
{
swap(uchar*,a,b);
@ -289,7 +308,7 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
{
alength= *a++; blength= *b++;
end=a+alength;
key_length-= blength + 1;
next_key_length=key_length-blength-1;
}
else
{
@ -298,9 +317,7 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
/* remove pre space from keys */
for ( ; alength && *a == ' ' ; a++, alength--) ;
for ( ; blength && *b == ' ' ; b++, blength--) ;
key_length-= keyseg->length;
}
if (piks)
{
if (*a == '-')
@ -350,7 +367,6 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a= end;
b+= 8;
key_length-= keyseg->length;
break;
}
case HA_KEYTYPE_ULONGLONG:
@ -362,7 +378,6 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
a= end;
b+= 8;
key_length-= keyseg->length;
break;
}
#endif

View File

@ -48,7 +48,10 @@ $opt_optimization="None";
$opt_hw="";
$opt_threads=5;
$opt_time_limit=10*60; # Don't wait more than 10 min for some tests
if (!defined($opt_time_limit))
{
$opt_time_limit=10*60; # Don't wait more than 10 min for some tests
}
$log_prog_args=join(" ", skip_arguments(\@ARGV,"comments","cmp","server",
"user", "host", "database", "password",

View File

@ -39,7 +39,7 @@
# as such, and clarify ones such as "mediumint" with comments such as
# "3-byte int" or "same as xxx".
$version="1.59";
$version="1.60";
use DBI;
use Getopt::Long;
@ -50,7 +50,7 @@ $opt_server="mysql"; $opt_host="localhost"; $opt_database="test";
$opt_dir="limits";
$opt_user=$opt_password="";$opt_verbose="";
$opt_debug=$opt_help=$opt_Information=$opt_restart=$opt_force=$opt_quick=0;
$opt_log_all_queries=$opt_fix_limit_file=$opt_batch_mode=0;
$opt_log_all_queries=$opt_fix_limit_file=$opt_batch_mode=$opt_version=0;
$opt_db_start_cmd=""; # the db server start command
$opt_check_server=0; # Check if server is alive before each query
$opt_sleep=10; # time to sleep while starting the db server
@ -68,8 +68,10 @@ GetOptions("Information","help","server=s","debug","user=s","password=s",
"database=s","restart","force","quick","log-all-queries","comment=s",
"host=s","fix-limit-file","dir=s","db-start-cmd=s","sleep=s","suffix=s",
"batch-mode","config-file=s","log-queries-to-file=s","check-server",
"version",
"verbose!" => \$opt_verbose) || usage();
usage() if ($opt_help || $opt_Information);
version() && exit(0) if ($opt_version);
$opt_suffix = '-'.$opt_suffix if (length($opt_suffix) != 0);
$opt_config_file = "$pwd/$opt_dir/$opt_server$opt_suffix.cfg"
@ -1190,7 +1192,7 @@ else
# Test: NOROUND
{
my $resultat = 'undefined';
my $result = 'undefined';
my $error;
print "NOROUND: ";
save_incomplete('func_extra_noround','Function NOROUND');
@ -1199,21 +1201,25 @@ else
$error = safe_query_l('func_extra_noround',"select noround(22.6) $end_query");
if ($error ne 1) # syntax error -- noround is not supported
{
$resultat = 'no'
} else # Ok, now check if it really works
{
$result = 'no'
}
else # Ok, now check if it really works
{
$error=safe_query_l('func_extra_noround',
["create table crash_me_nr (a int)",
"insert into crash_me_nr values(noround(10.2))",
"drop table crash_me_nr $drop_attr"]);
if ($error eq 1) {
$resultat = "syntax only";
} else {
$resultat = 'yes';
}
}
print "$resultat\n";
save_config_data('func_extra_noround',$resultat,"Function NOROUND");
if ($error == 1)
{
$result= "syntax only";
}
else
{
$result= 'yes';
}
}
print "$result\n";
save_config_data('func_extra_noround',$result,"Function NOROUND");
}
check_parenthesis("func_sql_","CURRENT_USER");
@ -1377,7 +1383,7 @@ if ($limits{'type_sql_date'} eq 'yes')
# Test: WEEK()
{
my $resultat="no";
my $result="no";
my $error;
print "WEEK:";
save_incomplete('func_odbc_week','WEEK');
@ -1388,17 +1394,17 @@ if ($limits{'type_sql_date'} eq 'yes')
# and 0 - EURO weeks
if ($error == -1) {
if ($last_result == 4) {
$resultat = 'USA';
$result = 'USA';
} else {
$resultat='error';
$result='error';
add_log('func_odbc_week',
" must return 4 or 5, but $last_result");
}
} elsif ($error == 0) {
$resultat = 'EURO';
$result = 'EURO';
}
print " $resultat\n";
save_config_data('func_odbc_week',$resultat,"WEEK");
print " $result\n";
save_config_data('func_odbc_week',$result,"WEEK");
}
my $insert_query ='insert into crash_me_d values('.
@ -1498,7 +1504,7 @@ if ($limits{'type_sql_date'} eq 'yes')
# NOT id BETWEEN a and b
if ($limits{'func_where_not_between'} eq 'yes')
{
my $resultat = 'error';
my $result = 'error';
my $err;
my $key='not_id_between';
my $prompt='NOT ID BETWEEN interprets as ID NOT BETWEEN';
@ -1512,15 +1518,15 @@ if ($limits{'func_where_not_between'} eq 'yes')
5,0);
if ($err eq 1) {
if (not defined($last_result)) {
$resultat='no';
$result='no';
};
};
if ( $err eq 0) {
$resultat = 'yes';
$result = 'yes';
};
safe_query_l($key,["drop table crash_me_b"]);
save_config_data($key,$resultat,$prompt);
print "$resultat\n";
save_config_data($key,$result,$prompt);
print "$result\n";
};
@ -2018,37 +2024,44 @@ report("views","views",
# Test: foreign key
{
my $resultat = 'undefined';
my $result = 'undefined';
my $error;
print "foreign keys: ";
save_incomplete('foreign_key','foreign keys');
# 1) check if foreign keys are supported
safe_query_l('foreign_key',create_table("crash_me_qf",["a integer not null"],
["primary key (a)"]));
$error = safe_query_l('foreign_key',
create_table("crash_me_qf2",["a integer not null",
"foreign key (a) references crash_me_qf (a)"], []));
if ($error eq 1) # OK -- syntax is supported
safe_query_l('foreign_key',
create_table("crash_me_qf",
["a integer not null"],
["primary key (a)"]));
$error= safe_query_l('foreign_key',
create_table("crash_me_qf2",
["a integer not null",
"foreign key (a) references crash_me_qf (a)"],
[]));
if ($error == 1) # OK -- syntax is supported
{
$resultat = 'error';
$result = 'error';
# now check if foreign key really works
safe_query_l('foreign_key', "insert into crash_me_qf values (1)");
if (safe_query_l('foreign_key', "insert into crash_me_qf2 values (2)") eq 1)
if (safe_query_l('foreign_key', "insert into crash_me_qf2 values (2)") eq 1)
{
$resultat = 'syntax only';
} else {
$resultat = 'yes';
}
} else {
$resultat = "no";
}
safe_query_l('foreign_key',
"drop table crash_me_qf2 $drop_attr","drop table crash_me_qf $drop_attr");
print "$resultat\n";
save_config_data('foreign_key',$resultat,"foreign keys");
$result = 'syntax only';
}
else
{
$result = 'yes';
}
}
else
{
$result = "no";
}
safe_query_l('foreign_key', "drop table crash_me_qf2 $drop_attr");
safe_query_l('foreign_key', "drop table crash_me_qf $drop_attr");
print "$result\n";
save_config_data('foreign_key',$result,"foreign keys");
}
report("Create SCHEMA","create_schema",
@ -2607,7 +2620,7 @@ sub detect_null_position
sub check_parenthesis {
my $prefix=shift;
my $fn=shift;
my $resultat='no';
my $result='no';
my $param_name=$prefix.lc($fn);
my $r;
@ -2616,18 +2629,18 @@ sub check_parenthesis {
add_log($param_name,$safe_query_log);
if ($r == 1)
{
$resultat="yes";
$result="yes";
}
else{
$r = safe_query("select $fn() $end_query");
add_log($param_name,$safe_query_log);
if ( $r == 1)
{
$resultat="with_parenthesis";
$result="with_parenthesis";
}
}
save_config_data($param_name,$resultat,$fn);
save_config_data($param_name,$result,$fn);
}
sub check_constraint {
@ -2699,10 +2712,16 @@ sub make_date {
}
sub version
{
print "$0 Ver $version\n";
}
sub usage
{
version();
print <<EOF;
$0 Ver $version
This program tries to find all limits and capabilities for a SQL
server. As it will use the server in some 'unexpected' ways, one
@ -3048,7 +3067,7 @@ sub safe_query_l {
my $r = safe_query($q);
add_log($key,$safe_query_log);
return $r;
}
}
sub safe_query
{
@ -3110,7 +3129,6 @@ sub safe_query
$retry = $retry_limit;
$retry_ok = 1;
$safe_query_log .= "> OK\n";
}
$sth->finish;
}

View File

@ -27,6 +27,7 @@ $opt_start_field_count=8; # start with this many fields
$opt_loop_count=20; # How many tests to do
$opt_row_count=1000; # Rows in the table
$opt_field_count=1000; # Add until this many fields.
$opt_time_limit=10*60; # Don't wait more than 10 min for some tests
chomp($pwd = `pwd`); $pwd = "." if ($pwd eq '');
require "$pwd/bench-init.pl" || die "Can't read Configuration file: $!\n";
@ -113,10 +114,9 @@ if ($opt_fast)
}
else
{
$add=1 if (!$limits{'alter_add_multi_col'});
$add=1 if (!$limits->{'alter_add_multi_col'});
}
$count=0;
while ($field_count < $opt_field_count)
{
@ -131,19 +131,43 @@ while ($field_count < $opt_field_count)
$tmp="" if (!$multi_add); # Adabas
}
do_query($dbh,"ALTER TABLE bench " . substr($fields,1));
$end_time=new Benchmark;
last if ($estimated=predict_query_time($loop_time,$end_time,\$count,$count,
$opt_field_count/$add+1));
}
$end_time=new Benchmark;
print "Time for alter_table_add ($count): " .
if ($estimated)
{ print "Estimated time"; }
else
{ print "Time"; }
print " for alter_table_add ($count): " .
timestr(timediff($end_time, $loop_time),"all") . "\n\n";
#
# If estimated, fix table to have known number of fields
#
if ($estimated && $field_count < $opt_field_count)
{
$fields="";
$tmp="ADD ";
while ($field_count < $opt_field_count)
{
$field_count++;
$fields.=",$tmp i${field_count} integer";
$tmp="" if (!$multi_add); # Adabas
}
do_query($dbh,"ALTER TABLE bench " . substr($fields,1));
}
####
#### Test adding and deleting index on the first $opt_start_fields
####
$loop_time=new Benchmark;
for ($i=1; $i < $opt_start_field_count ; $i++)
$count= 0;
for ($i=1; $i <= $opt_start_field_count ; $i++)
{
$dbh->do("CREATE INDEX bench_ind$i ON bench (i${i})") || die $DBI::errstr;
}
@ -153,7 +177,7 @@ print "Time for create_index ($opt_start_field_count): " .
timestr(timediff($end_time, $loop_time),"all") . "\n\n";
$loop_time=new Benchmark;
for ($i=1; $i < $opt_start_field_count ; $i++)
for ($i=1; $i <= $opt_start_field_count ; $i++)
{
$dbh->do($server->drop_index("bench","bench_ind$i")) || die $DBI::errstr;
}
@ -182,10 +206,17 @@ while ($field_count > $opt_start_field_count)
}
$dbh->do("ALTER TABLE bench " . substr($fields,1) . $server->{'drop_attr'})
|| die $DBI::errstr;
$end_time=new Benchmark;
last if ($estimated=predict_query_time($loop_time,$end_time,\$count,$count,
$opt_field_count/$add+1));
}
$end_time=new Benchmark;
print "Time for alter_table_drop ($count): " .
if ($estimated)
{ print "Estimated time"; }
else
{ print "Time"; }
print " for alter_table_drop ($count): " .
timestr(timediff($end_time, $loop_time),"all") . "\n\n";
skip_dropcol:

View File

@ -21,10 +21,11 @@
# $opt_loop_count rows in random order
#
# changes made for Oracle compatibility
# - $limits{'func_odbc_mod'} is OK from crash-me, but it fails here so set we
# - $limits->{'func_odbc_mod'} is OK from crash-me, but it fails here so set we
# set it to 0 in server-cfg
# - the default server config runs out of rollback segments, so I added a couple
# of disconnect/connects to reset
# - the default server config runs out of rollback segments, so we added a
# couple of disconnect/connects to reset
#
##################### Standard benchmark inits ##############################
use DBI;

View File

@ -161,6 +161,7 @@ static SYMBOL symbols[] = {
{ "FLUSH", SYM(FLUSH_SYM),0,0},
{ "FALSE", SYM(FALSE_SYM),0,0},
{ "FOREIGN", SYM(FOREIGN),0,0},
{ "FORCE", SYM(FORCE_SYM),0,0},
{ "RAID_TYPE", SYM(RAID_TYPE),0,0},
{ "RAID_CHUNKS", SYM(RAID_CHUNKS),0,0},
{ "RAID_CHUNKSIZE", SYM(RAID_CHUNKSIZE),0,0},

View File

@ -294,7 +294,19 @@ Log_event::Log_event(const char* buf, bool old_format)
****************************************************************************/
int Log_event::exec_event(struct st_relay_log_info* rli)
{
if (rli) // QQ When is this not true ?
/*
rli is null when (as far as I (Guilhem) know)
the caller is
Load_log_event::exec_event *and* that one is called from
Execute_load_log_event::exec_event.
In this case, we don't do anything here ;
Execute_load_log_event::exec_event will call Log_event::exec_event
again later with the proper rli.
Strictly speaking, if we were sure that rli is null
only in the case discussed above, 'if (rli)' is useless here.
But as we are not 100% sure, keep it for now.
*/
if (rli)
{
if (rli->inside_transaction)
rli->inc_pending(get_event_len());
@ -1435,13 +1447,36 @@ void Load_log_event::set_fields(List<Item> &field_list)
}
#endif // !MYSQL_CLIENT
/*****************************************************************************
Load_log_event::exec_event()
****************************************************************************/
#ifndef MYSQL_CLIENT
int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli)
/*
Does the data loading job when executing a LOAD DATA on the slave
SYNOPSIS
Load_log_event::exec_event
net
rli
use_rli_only_for_errors - if set to 1, rli is provided to
Load_log_event::exec_event only for this
function to have RPL_LOG_NAME and
rli->last_slave_error, both being used by
error reports. rli's position advancing
is skipped (done by the caller which is
Execute_load_log_event::exec_event).
- if set to 0, rli is provided for full use,
i.e. for error reports and position
advancing.
DESCRIPTION
Does the data loading job when executing a LOAD DATA on the slave
RETURN VALUE
0 Success
1 Failure
*/
int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
bool use_rli_only_for_errors)
{
init_sql_alloc(&thd->mem_root, 8192,0);
thd->db = rewrite_db((char*)db);
@ -1503,9 +1538,15 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli)
TL_WRITE))
thd->query_error = 1;
if (thd->cuted_fields)
{
/*
log_pos is the position of the LOAD
event in the master log
*/
sql_print_error("Slave: load data infile at position %s in log \
'%s' produced %d warning(s)", llstr(rli->master_log_pos,llbuff), RPL_LOG_NAME,
'%s' produced %d warning(s)", llstr(log_pos,llbuff), RPL_LOG_NAME,
thd->cuted_fields );
}
if (net)
net->pkt_nr= thd->net.pkt_nr;
}
@ -1544,7 +1585,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli)
return 1;
}
return Log_event::exec_event(rli);
return ( use_rli_only_for_errors ? 0 : Log_event::exec_event(rli) );
}
#endif // !MYSQL_CLIENT
@ -2680,7 +2721,11 @@ int Execute_load_log_event::exec_event(struct st_relay_log_info* rli)
save_options = thd->options;
thd->options &= ~ (ulong) (OPTION_BIN_LOG);
lev->thd = thd;
if (lev->exec_event(0,0))
/*
lev->exec_event should use rli only for errors
i.e. should not advance rli's position
*/
if (lev->exec_event(0,rli,1))
{
slave_print_error(rli,my_errno, "Failed executing load from '%s'", fname);
thd->options = save_options;

View File

@ -460,9 +460,10 @@ public:
const char* get_db() { return db; }
int exec_event(struct st_relay_log_info* rli)
{
return exec_event(thd->slave_net,rli);
return exec_event(thd->slave_net,rli,0);
}
int exec_event(NET* net, struct st_relay_log_info* rli);
int exec_event(NET* net, struct st_relay_log_info* rli,
bool use_rli_only_for_errors);
#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif

View File

@ -235,6 +235,10 @@ void debug_sync_point(const char* lock_name, uint lock_timeout);
#define SHOW_LOG_STATUS_FREE "FREE"
#define SHOW_LOG_STATUS_INUSE "IN USE"
/* Options to add_table_to_list() */
#define TL_OPTION_UPDATING 1
#define TL_OPTION_FORCE_INDEX 2
/* Some portable defines */
#define portable_sizeof_char_ptr 8
@ -820,7 +824,6 @@ uint calc_week(TIME *ltime, bool with_year, bool sunday_first_day_of_week,
void find_date(char *pos,uint *vek,uint flag);
TYPELIB *convert_strings_to_array_type(my_string *typelibs, my_string *end);
TYPELIB *typelib(List<String> &strings);
void clean_up(bool print_message=1);
ulong get_form_pos(File file, uchar *head, TYPELIB *save_names);
ulong make_new_entry(File file,uchar *fileinfo,TYPELIB *formnames,
const char *newname);

View File

@ -491,6 +491,7 @@ extern "C" pthread_handler_decl(handle_slave,arg);
static uint set_maximum_open_files(uint max_file_limit);
#endif
static ulong find_bit_type(const char *x, TYPELIB *bit_lib);
static void clean_up(bool print_message);
/****************************************************************************
** Code to end mysqld
@ -763,13 +764,13 @@ void kill_mysql(void)
#if defined(OS2)
extern "C" void kill_server(int sig_ptr)
#define RETURN_FROM_KILL_SERVER return
#define RETURN_FROM_KILL_SERVER DBUG_RETURN
#elif !defined(__WIN__)
static void *kill_server(void *sig_ptr)
#define RETURN_FROM_KILL_SERVER return 0
#define RETURN_FROM_KILL_SERVER DBUG_RETURN(0)
#else
static void __cdecl kill_server(int sig_ptr)
#define RETURN_FROM_KILL_SERVER return
#define RETURN_FROM_KILL_SERVER DBUG_RETURN
#endif
{
int sig=(int) (long) sig_ptr; // This is passed a int
@ -848,7 +849,7 @@ extern "C" sig_handler print_signal_warning(int sig)
void unireg_end(void)
{
clean_up();
clean_up(1);
my_thread_end();
#ifdef SIGNALS_DONT_BREAK_READ
exit(0);
@ -863,7 +864,7 @@ extern "C" void unireg_abort(int exit_code)
DBUG_ENTER("unireg_abort");
if (exit_code)
sql_print_error("Aborting\n");
clean_up(); /* purecov: inspected */
clean_up(1); /* purecov: inspected */
DBUG_PRINT("quit",("done with cleanup in unireg_abort"));
my_thread_end();
exit(exit_code); /* purecov: inspected */
@ -908,12 +909,12 @@ void clean_up(bool print_message)
regex_end();
#endif
if (print_message && errmesg)
sql_print_error(ER(ER_SHUTDOWN_COMPLETE),my_progname);
#if !defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
if (!opt_bootstrap)
(void) my_delete(pidfile_name,MYF(0)); // This may not always exist
#endif
if (print_message && errmesg)
sql_print_error(ER(ER_SHUTDOWN_COMPLETE),my_progname);
x_free((gptr) my_errmsg[ERRMAPP]); /* Free messages */
DBUG_PRINT("quit", ("Error messages freed"));
/* Tell main we are ready */
@ -923,6 +924,10 @@ void clean_up(bool print_message)
/* do the broadcast inside the lock to ensure that my_end() is not called */
(void) pthread_cond_broadcast(&COND_thread_count);
(void) pthread_mutex_unlock(&LOCK_thread_count);
/*
The following lines may never be executed as the main thread may have
killed us
*/
DBUG_PRINT("quit", ("done with cleanup"));
} /* clean_up */
@ -1502,7 +1507,7 @@ static void init_signals(void)
/* Change limits so that we will get a core file */
struct rlimit rl;
rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
if (setrlimit(RLIMIT_CORE, &rl))
if (setrlimit(RLIMIT_CORE, &rl) && global_system_variables.log_warnings)
sql_print_error("Warning: setrlimit could not change the size of core files to 'infinity'; We may not be able to generate a core file on signals");
}
#endif
@ -1571,8 +1576,11 @@ extern "C" void *signal_hand(void *arg __attribute__((unused)))
my_thread_init(); // Init new thread
DBUG_ENTER("signal_hand");
SIGNAL_THD;
/* Setup alarm handler */
init_thr_alarm(max_connections+max_insert_delayed_threads);
/*
Setup alarm handler
The two extra handlers are for slave threads
*/
init_thr_alarm(max_connections+max_insert_delayed_threads+2);
#if SIGINT != THR_KILL_SIGNAL
(void) sigemptyset(&set); // Setup up SIGINT for debug
(void) sigaddset(&set,SIGINT); // For debugging
@ -1660,12 +1668,15 @@ extern "C" void *signal_hand(void *arg __attribute__((unused)))
}
break;
case SIGHUP:
reload_acl_and_cache((THD*) 0,
(REFRESH_LOG | REFRESH_TABLES | REFRESH_FAST |
REFRESH_STATUS | REFRESH_GRANT | REFRESH_THREADS |
REFRESH_HOSTS),
(TABLE_LIST*) 0); // Flush logs
mysql_print_status((THD*) 0); // Send debug some info
if (!abort_loop)
{
reload_acl_and_cache((THD*) 0,
(REFRESH_LOG | REFRESH_TABLES | REFRESH_FAST |
REFRESH_STATUS | REFRESH_GRANT |
REFRESH_THREADS | REFRESH_HOSTS),
(TABLE_LIST*) 0); // Flush logs
mysql_print_status((THD*) 0); // Send debug some info
}
break;
#ifdef USE_ONE_SIGNAL_HAND
case THR_SERVER_ALARM:

View File

@ -603,12 +603,14 @@ int SQL_SELECT::test_quick_select(key_map keys_to_use, table_map prev_tables,
records++; /* purecov: inspected */
scan_time=(double) records / TIME_FOR_COMPARE+1;
read_time=(double) head->file->scan_time()+ scan_time + 1.0;
if (head->force_index)
scan_time= read_time= DBL_MAX;
if (limit < records)
read_time=(double) records+scan_time+1; // Force to use index
else if (read_time <= 2.0 && !force_quick_range)
DBUG_RETURN(0); /* No need for quick select */
DBUG_PRINT("info",("Time to scan table: %ld",(long) read_time));
DBUG_PRINT("info",("Time to scan table: %g", read_time));
keys_to_use&=head->keys_in_use_for_query;
if (keys_to_use)

View File

@ -171,7 +171,10 @@ net_printf(THD *thd, uint errcode, ...)
{
if (thd->bootstrap)
{
/* In bootstrap it's ok to print on stderr */
/*
In bootstrap it's ok to print on stderr
This may also happen when we get an error from a slave thread
*/
fprintf(stderr,"ERROR: %d %s\n",errcode,text_pos);
thd->fatal_error=1;
}

View File

@ -413,6 +413,7 @@ int terminate_slave_threads(MASTER_INFO* mi,int thread_mask,bool skip_lock)
}
if ((thread_mask & (SLAVE_IO|SLAVE_FORCE_ALL)) && mi->slave_running)
{
DBUG_PRINT("info",("Terminating IO thread"));
mi->abort_slave=1;
if ((error=terminate_slave_thread(mi->io_thd,io_lock,
io_cond_lock,
@ -423,6 +424,7 @@ int terminate_slave_threads(MASTER_INFO* mi,int thread_mask,bool skip_lock)
}
if ((thread_mask & (SLAVE_SQL|SLAVE_FORCE_ALL)) && mi->rli.slave_running)
{
DBUG_PRINT("info",("Terminating SQL thread"));
DBUG_ASSERT(mi->rli.sql_thd != 0) ;
mi->rli.abort_slave=1;
if ((error=terminate_slave_thread(mi->rli.sql_thd,sql_lock,
@ -2572,12 +2574,6 @@ static int process_io_rotate(MASTER_INFO *mi, Rotate_log_event *rev)
memcpy(mi->master_log_name, rev->new_log_ident, rev->ident_len+1);
mi->master_log_pos= rev->pos;
pthread_mutex_lock(&mi->rli.data_lock);
memcpy(mi->rli.master_log_name, rev->new_log_ident, rev->ident_len+1);
mi->rli.master_log_pos= rev->pos;
pthread_mutex_unlock(&mi->rli.data_lock);
DBUG_PRINT("info", ("master_log_pos: '%s' %d",
mi->master_log_name, (ulong) mi->master_log_pos));
#ifndef DBUG_OFF

View File

@ -747,7 +747,7 @@ TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list)
table->tablenr=thd->current_tablenr++;
table->used_fields=0;
table->const_table=0;
table->outer_join=table->null_row=table->maybe_null=0;
table->outer_join= table->null_row= table->maybe_null= table->force_index= 0;
table->status=STATUS_NO_RECORD;
table->keys_in_use_for_query= table->keys_in_use;
table->used_keys= table->keys_for_keyread;
@ -906,7 +906,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
table->tablenr=thd->current_tablenr++;
table->used_fields=0;
table->const_table=0;
table->outer_join=table->null_row=table->maybe_null=0;
table->outer_join= table->null_row= table->maybe_null= table->force_index= 0;
table->status=STATUS_NO_RECORD;
table->keys_in_use_for_query= table->keys_in_use;
table->used_keys= table->keys_for_keyread;
@ -977,6 +977,7 @@ bool reopen_table(TABLE *table,bool locked)
tmp.status= table->status;
tmp.keys_in_use_for_query= tmp.keys_in_use;
tmp.used_keys= tmp.keys_for_keyread;
tmp.force_index= tmp.force_index;
/* Get state */
tmp.key_length= table->key_length;
@ -1969,6 +1970,7 @@ bool setup_tables(TABLE_LIST *tables)
table->maybe_null=test(table->outer_join=table_list->outer_join);
table->tablenr=tablenr;
table->map= (table_map) 1 << tablenr;
table->force_index= table_list->force_index;
if (table_list->use_index)
{
key_map map= get_key_map_from_key_list(table,

View File

@ -1171,13 +1171,14 @@ List<String>* st_select_lex_node::get_use_index() { return 0; }
List<String>* st_select_lex_node::get_ignore_index() { return 0; }
TABLE_LIST *st_select_lex_node::add_table_to_list(THD *thd, Table_ident *table,
LEX_STRING *alias,
bool updating,
ulong table_join_options,
thr_lock_type flags,
List<String> *use_index,
List<String> *ignore_index)
{
return 0;
}
ulong st_select_lex_node::get_table_join_options() { return 0; }
/*
This is used for UNION & subselect to create a new table list of all used
@ -1334,6 +1335,11 @@ List<String>* st_select_lex::get_ignore_index()
return ignore_index_ptr;
}
ulong st_select_lex::get_table_join_options()
{
return table_join_options;
}
/*
There are st_select_lex::add_table_to_list &
st_select_lex::set_lock_for_tables in sql_parse.cc

View File

@ -243,9 +243,10 @@ public:
virtual List<Item>* get_item_list();
virtual List<String>* get_use_index();
virtual List<String>* get_ignore_index();
virtual ulong get_table_join_options();
virtual TABLE_LIST *add_table_to_list(THD *thd, Table_ident *table,
LEX_STRING *alias,
bool updating,
ulong table_options,
thr_lock_type flags= TL_UNLOCK,
List<String> *use_index= 0,
List<String> *ignore_index= 0);
@ -336,6 +337,7 @@ public:
List<Item_func_match> ftfunc_list_alloc;
JOIN *join; /* after JOIN::prepare it is pointer to corresponding JOIN */
const char *type; /* type of select for EXPLAIN */
ulong table_join_options;
uint in_sum_expr;
uint select_number; /* number of select (used for EXPLAIN) */
bool braces; /* SELECT ... UNION (SELECT ... ) <- this braces */
@ -373,9 +375,10 @@ public:
List<Item>* get_item_list();
List<String>* get_use_index();
List<String>* get_ignore_index();
ulong get_table_join_options();
TABLE_LIST* add_table_to_list(THD *thd, Table_ident *table,
LEX_STRING *alias,
bool updating,
ulong table_options,
thr_lock_type flags= TL_UNLOCK,
List<String> *use_index= 0,
List<String> *ignore_index= 0);

View File

@ -518,7 +518,8 @@ check_connections(THD *thd)
vio_in_addr(net->vio,&thd->remote.sin_addr);
thd->host=ip_to_hostname(&thd->remote.sin_addr,&connect_errors);
/* Cut very long hostnames to avoid possible overflows */
thd->host[min(strlen(thd->host), HOSTNAME_LENGTH)]= 0;
if (thd->host)
thd->host[min(strlen(thd->host), HOSTNAME_LENGTH)]= 0;
if (connect_errors > max_connect_errors)
return(ER_HOST_IS_BLOCKED);
}
@ -3597,11 +3598,30 @@ bool add_to_list(THD *thd, SQL_LIST &list,Item *item,bool asc)
}
/*
Add a table to list of used tables
SYNOPSIS
add_table_to_list()
table Table to add
alias alias for table (or null if no alias)
table_options A set of the following bits:
TL_OPTION_UPDATING Table will be updated
TL_OPTION_FORCE_INDEX Force usage of index
lock_type How table should be locked
use_index List of indexed used in USE INDEX
ignore_index List of indexed used in IGNORE INDEX
RETURN
0 Error
# Pointer to TABLE_LIST element added to the total table list
*/
TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
Table_ident *table,
LEX_STRING *alias,
bool updating,
thr_lock_type flags,
ulong table_options,
thr_lock_type lock_type,
List<String> *use_index,
List<String> *ignore_index)
{
@ -3658,8 +3678,9 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
}
ptr->real_name=table->table.str;
ptr->real_name_length=table->table.length;
ptr->lock_type=flags;
ptr->updating=updating;
ptr->lock_type= lock_type;
ptr->updating= test(table_options & TL_OPTION_UPDATING);
ptr->force_index= test(table_options & TL_OPTION_FORCE_INDEX);
ptr->derived= (SELECT_LEX_UNIT *) table->sel;
if (use_index)
ptr->use_index=(List<String> *) thd->memdup((gptr) use_index,
@ -3669,7 +3690,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
sizeof(*ignore_index));
/* check that used name is unique */
if (flags != TL_IGNORE)
if (lock_type != TL_IGNORE)
{
for (TABLE_LIST *tables=(TABLE_LIST*) table_list.first ;
tables ;

View File

@ -2305,7 +2305,8 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
!(s->quick && best_key && s->quick->index == best_key->key &&
best_max_key_part >= s->table->quick_key_parts[best_key->key]) &&
!((s->table->file->table_flags() & HA_TABLE_SCAN_ON_INDEX) &&
s->table->used_keys && best_key))
s->table->used_keys && best_key) &&
!(s->table->force_index && best_key))
{ // Check full join
if (s->on_expr)
{

View File

@ -1497,6 +1497,7 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
case SHOW_RPL_STATUS:
end= strmov(buff, rpl_status_type[(int)rpl_status]);
break;
#ifndef EMBEDDED_LIBRARY
case SHOW_SLAVE_RUNNING:
{
LOCK_ACTIVE_MI;
@ -1505,6 +1506,7 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
UNLOCK_ACTIVE_MI;
break;
}
#endif
case SHOW_OPENTABLES:
end= int10_to_str((long) cached_tables(), buff, 10);
break;

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2000-2001 MySQL AB
/* Copyright (C) 2000-2003 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -222,6 +222,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token FIRST_SYM
%token FIXED_SYM
%token FLOAT_NUM
%token FORCE_SYM
%token FOREIGN
%token FROM
%token FULL
@ -823,7 +824,8 @@ create:
($2 &
HA_LEX_CREATE_TMP_TABLE ?
&tmp_table_alias :
(LEX_STRING*) 0),1,
(LEX_STRING*) 0),
TL_OPTION_UPDATING,
((using_update_log)?
TL_READ_NO_INSERT:
TL_READ)))
@ -844,7 +846,8 @@ create:
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_CREATE_INDEX;
if (!lex->current_select->add_table_to_list(lex->thd, $7,NULL,1))
if (!lex->current_select->add_table_to_list(lex->thd, $7, NULL,
TL_OPTION_UPDATING))
YYABORT;
lex->create_list.empty();
lex->key_list.empty();
@ -1380,6 +1383,7 @@ opt_unique_or_fulltext:
key_alg:
/* empty */ { $$= HA_KEY_ALG_UNDEF; }
| USING opt_btree_or_rtree { $$= $2; };
| TYPE_SYM opt_btree_or_rtree { $$= $2; };
opt_btree_or_rtree:
BTREE_SYM { $$= HA_KEY_ALG_BTREE; }
@ -1413,7 +1417,8 @@ alter:
LEX *lex=&thd->lex;
lex->sql_command = SQLCOM_ALTER_TABLE;
lex->name=0;
if (!lex->select_lex.add_table_to_list(thd, $4, NULL,1))
if (!lex->select_lex.add_table_to_list(thd, $4, NULL,
TL_OPTION_UPDATING))
YYABORT;
lex->drop_primary=0;
lex->create_list.empty();
@ -1679,8 +1684,10 @@ table_to_table:
{
LEX *lex=Lex;
SELECT_LEX_NODE *sl= lex->current_select;
if (!sl->add_table_to_list(lex->thd, $1,NULL,1,TL_IGNORE) ||
!sl->add_table_to_list(lex->thd, $3,NULL,1,TL_IGNORE))
if (!sl->add_table_to_list(lex->thd, $1,NULL,TL_OPTION_UPDATING,
TL_IGNORE) ||
!sl->add_table_to_list(lex->thd, $3,NULL,TL_OPTION_UPDATING,
TL_IGNORE))
YYABORT;
};
@ -2532,12 +2539,14 @@ join_table:
{
SELECT_LEX *sel= Select->select_lex();
sel->use_index_ptr=sel->ignore_index_ptr=0;
sel->table_join_options= 0;
}
table_ident opt_table_alias opt_key_definition
{
LEX *lex= Lex;
SELECT_LEX_NODE *sel= lex->current_select;
if (!($$= sel->add_table_to_list(lex->thd, $2, $3, 0,
if (!($$= sel->add_table_to_list(lex->thd, $2, $3,
sel->get_table_join_options(),
lex->lock_option,
sel->get_use_index(),
sel->get_ignore_index())))
@ -2583,6 +2592,13 @@ opt_key_definition:
sel->use_index= *$2;
sel->use_index_ptr= &sel->use_index;
}
| FORCE_SYM key_usage_list
{
SELECT_LEX *sel= Select->select_lex();
sel->use_index= *$2;
sel->use_index_ptr= &sel->use_index;
sel->table_join_options|= TL_OPTION_FORCE_INDEX;
}
| IGNORE_SYM key_usage_list
{
SELECT_LEX *sel= Select->select_lex();
@ -2592,8 +2608,14 @@ opt_key_definition:
key_usage_list:
key_or_index { Select->select_lex()->interval_list.empty(); }
'(' key_usage_list2 ')'
{ $$= &Select->select_lex()->interval_list; };
'(' key_list_or_empty ')'
{ $$= &Select->select_lex()->interval_list; }
;
key_list_or_empty:
/* empty */ {}
| key_usage_list2 {}
;
key_usage_list2:
key_usage_list2 ',' ident
@ -2954,7 +2976,8 @@ drop:
lex->drop_list.empty();
lex->drop_list.push_back(new Alter_drop(Alter_drop::KEY,
$3.str));
if (!lex->current_select->add_table_to_list(lex->thd, $5,NULL, 1))
if (!lex->current_select->add_table_to_list(lex->thd, $5, NULL,
TL_OPTION_UPDATING))
YYABORT;
}
| DROP DATABASE if_exists ident
@ -2978,7 +3001,11 @@ table_list:
table_name:
table_ident
{ if (!Select->add_table_to_list(YYTHD, $1, NULL, 1)) YYABORT; };
{
if (!Select->add_table_to_list(YYTHD, $1, NULL, TL_OPTION_UPDATING))
YYABORT;
}
;
if_exists:
/* empty */ { $$= 0; }
@ -3213,7 +3240,8 @@ delete:
single_multi:
FROM table_ident
{
if (!Select->add_table_to_list(YYTHD, $2, NULL, 1, Lex->lock_option))
if (!Select->add_table_to_list(YYTHD, $2, NULL, TL_OPTION_UPDATING,
Lex->lock_option))
YYABORT;
}
where_clause opt_order_clause
@ -3234,14 +3262,15 @@ table_wild_list:
table_wild_one:
ident opt_wild opt_table_alias
{
if (!Select->add_table_to_list(YYTHD, new Table_ident($1), $3, 1,
Lex->lock_option))
if (!Select->add_table_to_list(YYTHD, new Table_ident($1), $3,
TL_OPTION_UPDATING, Lex->lock_option))
YYABORT;
}
| ident '.' ident opt_wild opt_table_alias
{
if (!Select->add_table_to_list(YYTHD, new Table_ident($1, $3, 0),
$5, 1, Lex->lock_option))
$5, TL_OPTION_UPDATING,
Lex->lock_option))
YYABORT;
}
;
@ -3405,7 +3434,7 @@ show_param:
| CREATE TABLE_SYM table_ident
{
Lex->sql_command = SQLCOM_SHOW_CREATE;
if(!Select->add_table_to_list(YYTHD, $3, NULL,0))
if (!Select->add_table_to_list(YYTHD, $3, NULL,0))
YYABORT;
}
| MASTER_SYM STATUS_SYM
@ -3574,14 +3603,14 @@ load: LOAD DATA_SYM load_data_lock opt_local INFILE TEXT_STRING
opt_duplicate INTO TABLE_SYM table_ident opt_field_term opt_line_term
opt_ignore_lines opt_field_spec
{
if (!Select->add_table_to_list(YYTHD, $11, NULL, 1))
if (!Select->add_table_to_list(YYTHD, $11, NULL, TL_OPTION_UPDATING))
YYABORT;
}
|
LOAD TABLE_SYM table_ident FROM MASTER_SYM
{
Lex->sql_command = SQLCOM_LOAD_MASTER_TABLE;
if (!Select->add_table_to_list(YYTHD, $3, NULL, 1))
if (!Select->add_table_to_list(YYTHD, $3, NULL, TL_OPTION_UPDATING))
YYABORT;
}

View File

@ -91,6 +91,7 @@ struct st_table {
my_bool copy_blobs; /* copy_blobs when storing */
my_bool null_row; /* All columns are null */
my_bool maybe_null,outer_join; /* Used with OUTER JOIN */
my_bool force_index;
my_bool distinct,const_table,no_rows;
my_bool key_read, bulk_insert;
my_bool crypted;
@ -168,6 +169,7 @@ typedef struct st_table_list
bool straight; /* optimize with prev table */
bool updating; /* for replicate-do/ignore table */
bool do_redirect; /* To get the struct in UNION's */
bool force_index; /* Prefer index over table scan */
} TABLE_LIST;
typedef struct st_changed_table_list