Merge work:/home/bk/mysql-4.1 into mashka.mysql.fi:/home/my/mysql-4.1
This commit is contained in:
commit
c9dc5a206b
@ -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";
|
$ENV{"PERL5LIB"}="$pwd/$host/perl5:$pwd/$host/perl5/site_perl";
|
||||||
$slave_port=$mysql_tcp_port+16;
|
$slave_port=$mysql_tcp_port+16;
|
||||||
$manager_port=$mysql_tcp_port+1;
|
$manager_port=$mysql_tcp_port+1;
|
||||||
|
$mysqladmin_args="--no-defaults -u root --connect_timeout=5 --shutdown_timeout=20";
|
||||||
|
|
||||||
if ($opt_stage == 0)
|
if ($opt_stage == 0)
|
||||||
{
|
{
|
||||||
@ -154,13 +155,18 @@ log_timestamp();
|
|||||||
|
|
||||||
if (-x "$host/bin/mysqladmin")
|
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 $mysqladmin_args -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 $mysqladmin_args -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 $mysqladmin_args -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 $mysqladmin_args -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 -P 9307 -h $host -s shutdown");
|
||||||
}
|
}
|
||||||
kill_all("mysqlmanager");
|
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)
|
if ($opt_stage == 0)
|
||||||
{
|
{
|
||||||
@ -308,8 +314,9 @@ if ($opt_stage <= 4 && !$opt_no_test)
|
|||||||
$tar_file =~ /(mysql[^\/]*)\.tar/;
|
$tar_file =~ /(mysql[^\/]*)\.tar/;
|
||||||
$ver=$1;
|
$ver=$1;
|
||||||
$test_dir="$pwd/$host/test/$ver";
|
$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
|
# Run the test suite
|
||||||
#
|
#
|
||||||
@ -328,7 +335,7 @@ if (!$opt_no_test && !$opt_no_benchmark)
|
|||||||
{
|
{
|
||||||
my $extra;
|
my $extra;
|
||||||
safe_cd($test_dir);
|
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);
|
sleep(2);
|
||||||
log_system("rm -f ./data/mysql/*");
|
log_system("rm -f ./data/mysql/*");
|
||||||
check_system("scripts/mysql_install_db --no-defaults --skip-locking","https://order");
|
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($bench_tmpdir);
|
||||||
rm_all("$opt_tmp") if ($new_opt_tmp);
|
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";
|
print LOG "ok\n";
|
||||||
close LOG;
|
close LOG;
|
||||||
print "$host: ok\n";
|
print "$host: ok\n";
|
||||||
@ -429,7 +436,7 @@ exit 0;
|
|||||||
sub usage
|
sub usage
|
||||||
{
|
{
|
||||||
print <<EOF;
|
print <<EOF;
|
||||||
$0 version 1.4
|
$0 version 1.5
|
||||||
|
|
||||||
$0 takes the following options:
|
$0 takes the following options:
|
||||||
|
|
||||||
|
@ -96,13 +96,84 @@ cached for each user/database combination.
|
|||||||
Many use of @code{GROUP BY} or @code{DISTINCT} caches all found rows in
|
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.)
|
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
|
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),
|
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
|
the found rows are cached in a join cache. One @code{SELECT} query can
|
||||||
use many join caches in the worst case.
|
use many join caches in the worst case.
|
||||||
@end table
|
@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
|
@node flush tables, filesort, caching, Top
|
||||||
@chapter How MySQL Handles @code{FLUSH TABLES}
|
@chapter How MySQL Handles @code{FLUSH TABLES}
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <mysql.h>
|
#include <mysql.h>
|
||||||
|
|
||||||
#define ADMIN_VERSION "8.38"
|
#define ADMIN_VERSION "8.39"
|
||||||
#define MAX_MYSQL_VAR 128
|
#define MAX_MYSQL_VAR 128
|
||||||
#define SHUTDOWN_DEF_TIMEOUT 3600 /* Wait for shutdown */
|
#define SHUTDOWN_DEF_TIMEOUT 3600 /* Wait for shutdown */
|
||||||
#define MAX_TRUNC_LENGTH 3
|
#define MAX_TRUNC_LENGTH 3
|
||||||
@ -76,8 +76,8 @@ static void print_relative_header();
|
|||||||
static void print_relative_line();
|
static void print_relative_line();
|
||||||
static void truncate_names();
|
static void truncate_names();
|
||||||
static my_bool get_pidfile(MYSQL *mysql, char *pidfile);
|
static my_bool get_pidfile(MYSQL *mysql, char *pidfile);
|
||||||
static void wait_pidfile(char *pidfile, time_t last_modified,
|
static my_bool wait_pidfile(char *pidfile, time_t last_modified,
|
||||||
struct stat *pidfile_status);
|
struct stat *pidfile_status);
|
||||||
static void store_values(MYSQL_RES *result);
|
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");
|
printf("Shutdown signal sent to server; Waiting for pid file to disappear\n");
|
||||||
|
|
||||||
/* Wait until pid file is gone */
|
/* Wait until pid file is gone */
|
||||||
wait_pidfile(pidfile, last_modified, &pidfile_status);
|
if (wait_pidfile(pidfile, last_modified, &pidfile_status))
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1150,34 +1151,51 @@ static my_bool get_pidfile(MYSQL *mysql, char *pidfile)
|
|||||||
return 1; /* Error */
|
return 1; /* Error */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Return 1 if pid file didn't disappear or change
|
||||||
|
*/
|
||||||
|
|
||||||
static void wait_pidfile(char *pidfile, time_t last_modified,
|
static my_bool wait_pidfile(char *pidfile, time_t last_modified,
|
||||||
struct stat *pidfile_status)
|
struct stat *pidfile_status)
|
||||||
{
|
{
|
||||||
char buff[FN_REFLEN];
|
char buff[FN_REFLEN];
|
||||||
int fd = -1;
|
int error= 1;
|
||||||
uint count=0;
|
uint count= 0;
|
||||||
|
DBUG_ENTER("wait_pidfile");
|
||||||
|
|
||||||
system_filename(buff, pidfile);
|
system_filename(buff, pidfile);
|
||||||
while (count++ <= opt_shutdown_timeout && !interrupted &&
|
do
|
||||||
(!last_modified || (last_modified == pidfile_status->st_mtime)) &&
|
|
||||||
(fd= my_open(buff, O_RDONLY, MYF(0))) >= 0)
|
|
||||||
{
|
{
|
||||||
if (!my_close(fd,MYF(0)))
|
int fd;
|
||||||
fd= -1;
|
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);
|
sleep(1);
|
||||||
if (last_modified && stat(pidfile, pidfile_status))
|
} while (!interrupted);
|
||||||
last_modified= 0;
|
|
||||||
}
|
if (error)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
my_close(fd,MYF(0));
|
DBUG_PRINT("warning",("Pid file didn't disappear"));
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Warning; Aborted waiting on pid file: '%s' after %d seconds\n",
|
"Warning; Aborted waiting on pid file: '%s' after %d seconds\n",
|
||||||
buff, count-1);
|
buff, count-1);
|
||||||
}
|
}
|
||||||
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
|
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
|
||||||
#define MTEST_VERSION "1.25"
|
#define MTEST_VERSION "1.26"
|
||||||
|
|
||||||
#include <my_global.h>
|
#include <my_global.h>
|
||||||
#include <mysql_embed.h>
|
#include <mysql_embed.h>
|
||||||
@ -1809,10 +1809,8 @@ int read_query(struct st_query** q_ptr)
|
|||||||
|
|
||||||
static struct my_option my_long_options[] =
|
static struct my_option my_long_options[] =
|
||||||
{
|
{
|
||||||
#ifndef DBUG_OFF
|
|
||||||
{"debug", '#', "Output debug log. Often this is 'd:t:o,filename'",
|
{"debug", '#', "Output debug log. Often this is 'd:t:o,filename'",
|
||||||
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
|
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
|
||||||
#endif
|
|
||||||
{"database", 'D', "Database to use.", (gptr*) &db, (gptr*) &db, 0,
|
{"database", 'D', "Database to use.", (gptr*) &db, (gptr*) &db, 0,
|
||||||
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||||
{"basedir", 'b', "Basedir for tests", (gptr*) &opt_basedir,
|
{"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) {
|
switch(optid) {
|
||||||
case '#':
|
case '#':
|
||||||
|
#ifndef DBUG_OFF
|
||||||
DBUG_PUSH(argument ? argument : "d:t:S:i:O,/tmp/mysqltest.trace");
|
DBUG_PUSH(argument ? argument : "d:t:S:i:O,/tmp/mysqltest.trace");
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
record = 1;
|
record = 1;
|
||||||
@ -1983,7 +1983,7 @@ int parse_args(int argc, char **argv)
|
|||||||
default_argv= argv;
|
default_argv= argv;
|
||||||
|
|
||||||
if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
|
if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
|
||||||
exit(ho_error);
|
exit(1);
|
||||||
|
|
||||||
if (argc > 1)
|
if (argc > 1)
|
||||||
{
|
{
|
||||||
|
@ -18,7 +18,7 @@ INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include
|
|||||||
LDADD = @CLIENT_EXTRA_LDFLAGS@ ../mysys/libmysys.a \
|
LDADD = @CLIENT_EXTRA_LDFLAGS@ ../mysys/libmysys.a \
|
||||||
../dbug/libdbug.a ../strings/libmystrings.a
|
../dbug/libdbug.a ../strings/libmystrings.a
|
||||||
bin_PROGRAMS = replace comp_err perror resolveip my_print_defaults \
|
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
|
# Don't update the files from bitkeeper
|
||||||
%::SCCS/s.%
|
%::SCCS/s.%
|
||||||
|
86
extra/mysql_waitpid.c
Normal file
86
extra/mysql_waitpid.c
Normal 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);
|
||||||
|
}
|
@ -264,6 +264,7 @@ enum ha_base_keytype {
|
|||||||
#define MBR_EQUAL 8192
|
#define MBR_EQUAL 8192
|
||||||
#define MBR_DATA 16384
|
#define MBR_DATA 16384
|
||||||
#define SEARCH_NULL_ARE_EQUAL 32768 /* NULL in keys are equal */
|
#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 */
|
/* bits in opt_flag */
|
||||||
#define QUICK_USED 1
|
#define QUICK_USED 1
|
||||||
|
@ -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,
|
r=_mi_search(aio->info, aio->keyinfo, aio->keybuff, keylen,
|
||||||
SEARCH_FIND | SEARCH_PREFIX, aio->key_root);
|
SEARCH_FIND | SEARCH_PREFIX, aio->key_root);
|
||||||
|
aio->info->update|= HA_STATE_AKTIV; /* for _mi_test_if_changed() */
|
||||||
|
|
||||||
while (!r)
|
while (!r)
|
||||||
{
|
{
|
||||||
|
@ -601,7 +601,8 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
|
|||||||
if (*keys != 1L) /* not first_key */
|
if (*keys != 1L) /* not first_key */
|
||||||
{
|
{
|
||||||
uint diff;
|
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);
|
&diff);
|
||||||
param->unique_count[diff-1]++;
|
param->unique_count[diff-1]++;
|
||||||
}
|
}
|
||||||
|
@ -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:
|
Free buffers and reset the following flags:
|
||||||
EXTRA_CACHE, EXTRA_WRITE_CACHE, EXTRA_KEYREAD, EXTRA_QUICK
|
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))
|
if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
|
||||||
{
|
{
|
||||||
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);
|
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 defined(HAVE_MMAP) && defined(HAVE_MADVICE)
|
||||||
if (info->opt_flag & MEMMAP_USED)
|
if (info->opt_flag & MEMMAP_USED)
|
||||||
madvise(share->file_map,share->state.state.data_file_length,MADV_RANDOM);
|
madvise(share->file_map,share->state.state.data_file_length,MADV_RANDOM);
|
||||||
|
@ -573,28 +573,36 @@ err:
|
|||||||
DBUG_RETURN (NULL);
|
DBUG_RETURN (NULL);
|
||||||
} /* mi_open */
|
} /* mi_open */
|
||||||
|
|
||||||
|
|
||||||
byte *mi_alloc_rec_buff(MI_INFO *info, ulong length, byte **buf)
|
byte *mi_alloc_rec_buff(MI_INFO *info, ulong length, byte **buf)
|
||||||
{
|
{
|
||||||
uint extra;
|
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;
|
byte *newptr = *buf;
|
||||||
|
|
||||||
/* to simplify initial init of info->rec_buf in mi_open and mi_extra */
|
/* to simplify initial init of info->rec_buf in mi_open and mi_extra */
|
||||||
if (length == (ulong) -1)
|
if (length == (ulong) -1)
|
||||||
|
{
|
||||||
length= max(info->s->base.pack_reclength+info->s->base.pack_bits,
|
length= max(info->s->base.pack_reclength+info->s->base.pack_bits,
|
||||||
info->s->base.max_key_length);
|
info->s->base.max_key_length);
|
||||||
|
/* Avoid unnecessary realloc */
|
||||||
|
if (newptr && length == old_length)
|
||||||
|
return newptr;
|
||||||
|
}
|
||||||
|
|
||||||
extra= ((info->s->options & HA_OPTION_PACK_RECORD) ?
|
extra= ((info->s->options & HA_OPTION_PACK_RECORD) ?
|
||||||
ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER)+MI_SPLIT_LENGTH+
|
ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER)+MI_SPLIT_LENGTH+
|
||||||
MI_REC_BUFF_OFFSET : 0);
|
MI_REC_BUFF_OFFSET : 0);
|
||||||
if (extra && newptr)
|
if (extra && newptr)
|
||||||
newptr-=MI_REC_BUFF_OFFSET;
|
newptr-= MI_REC_BUFF_OFFSET;
|
||||||
if (!(newptr=(byte*) my_realloc((gptr)newptr, length+extra+8,
|
if (!(newptr=(byte*) my_realloc((gptr)newptr, length+extra+8,
|
||||||
MYF(MY_ALLOW_ZERO_PTR))))
|
MYF(MY_ALLOW_ZERO_PTR))))
|
||||||
return newptr;
|
return newptr;
|
||||||
*((uint *)newptr)=length;
|
*((uint32 *) newptr)= (uint32) length;
|
||||||
*buf= newptr+(extra ? MI_REC_BUFF_OFFSET : 0);
|
*buf= newptr+(extra ? MI_REC_BUFF_OFFSET : 0);
|
||||||
}
|
}
|
||||||
return *buf;
|
return *buf;
|
||||||
|
@ -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 *key, uint key_len, uint nextflag, uchar **ret_pos,
|
||||||
uchar *buff, my_bool *last_key)
|
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.
|
my_flag is raw comparison result to be changed according to
|
||||||
flag is the value returned by ha_key_cmp and as treated as final */
|
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;
|
int flag=0, my_flag=-1;
|
||||||
uint nod_flag, length, len, matched, cmplen, kseg_len;
|
uint nod_flag, length, len, matched, cmplen, kseg_len;
|
||||||
uint prefix_len,suffix_len;
|
uint prefix_len,suffix_len;
|
||||||
|
@ -385,7 +385,7 @@ typedef struct st_mi_sort_param
|
|||||||
#define MI_DYN_ALIGN_SIZE 4 /* Align blocks on this */
|
#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_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_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 */
|
#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)) ? \
|
((((info)->s->options & HA_OPTION_PACK_RECORD) && (buf)) ? \
|
||||||
(buf) - MI_REC_BUFF_OFFSET : (buf))
|
(buf) - MI_REC_BUFF_OFFSET : (buf))
|
||||||
#define mi_get_rec_buff_len(info,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,
|
extern ulong _mi_rec_unpack(MI_INFO *info,byte *to,byte *from,
|
||||||
ulong reclength);
|
ulong reclength);
|
||||||
|
@ -88,6 +88,7 @@ sleep_until_file_created ()
|
|||||||
wait_for_pid()
|
wait_for_pid()
|
||||||
{
|
{
|
||||||
pid=$1
|
pid=$1
|
||||||
|
#$WAIT_PID pid $SLEEP_TIME_FOR_DELETE
|
||||||
}
|
}
|
||||||
|
|
||||||
# No paths below as we can't be sure where the program is!
|
# No paths below as we can't be sure where the program is!
|
||||||
@ -347,9 +348,9 @@ while test $# -gt 0; do
|
|||||||
;;
|
;;
|
||||||
--debug)
|
--debug)
|
||||||
EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT \
|
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 \
|
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"
|
EXTRA_MYSQL_TEST_OPT="$EXTRA_MYSQL_TEST_OPT --debug"
|
||||||
;;
|
;;
|
||||||
--fast)
|
--fast)
|
||||||
@ -423,6 +424,7 @@ if [ x$SOURCE_DIST = x1 ] ; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
MYSQLADMIN="$BASEDIR/client/mysqladmin"
|
MYSQLADMIN="$BASEDIR/client/mysqladmin"
|
||||||
|
WAIT_PID="$BASEDIR/extra/mysql_waitpid"
|
||||||
MYSQL_MANAGER_CLIENT="$BASEDIR/client/mysqlmanagerc"
|
MYSQL_MANAGER_CLIENT="$BASEDIR/client/mysqlmanagerc"
|
||||||
MYSQL_MANAGER="$BASEDIR/tools/mysqlmanager"
|
MYSQL_MANAGER="$BASEDIR/tools/mysqlmanager"
|
||||||
MYSQL_MANAGER_PWGEN="$BASEDIR/client/mysqlmanager-pwgen"
|
MYSQL_MANAGER_PWGEN="$BASEDIR/client/mysqlmanager-pwgen"
|
||||||
@ -439,6 +441,7 @@ else
|
|||||||
fi
|
fi
|
||||||
MYSQL_TEST="$BASEDIR/bin/mysqltest"
|
MYSQL_TEST="$BASEDIR/bin/mysqltest"
|
||||||
MYSQLADMIN="$BASEDIR/bin/mysqladmin"
|
MYSQLADMIN="$BASEDIR/bin/mysqladmin"
|
||||||
|
WAIT_PID="$BASEDIR/bin/mysql_waitpid"
|
||||||
MYSQL_MANAGER="$BASEDIR/bin/mysqlmanager"
|
MYSQL_MANAGER="$BASEDIR/bin/mysqlmanager"
|
||||||
MYSQL_MANAGER_CLIENT="$BASEDIR/bin/mysqlmanagerc"
|
MYSQL_MANAGER_CLIENT="$BASEDIR/bin/mysqlmanagerc"
|
||||||
MYSQL_MANAGER_PWGEN="$BASEDIR/bin/mysqlmanager-pwgen"
|
MYSQL_MANAGER_PWGEN="$BASEDIR/bin/mysqlmanager-pwgen"
|
||||||
@ -753,9 +756,9 @@ manager_term()
|
|||||||
{
|
{
|
||||||
pid=$1
|
pid=$1
|
||||||
ident=$2
|
ident=$2
|
||||||
shift
|
|
||||||
if [ $USE_MANAGER = 0 ] ; then
|
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=$?
|
res=$?
|
||||||
# Some systems require an extra connect
|
# 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
|
$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
|
[ x$SKIP_SLAVE = x1 ] && return
|
||||||
eval "this_slave_running=\$SLAVE$1_RUNNING"
|
eval "this_slave_running=\$SLAVE$1_RUNNING"
|
||||||
[ x$this_slave_running = 1 ] && return
|
[ x$this_slave_running = 1 ] && return
|
||||||
#when testing fail-safe replication, we will have more than one slave
|
# When testing fail-safe replication, we will have more than one slave
|
||||||
#in this case, we start secondary slaves with an argument
|
# in this case, we start secondary slaves with an argument
|
||||||
slave_ident="slave$1"
|
slave_ident="slave$1"
|
||||||
if [ -n "$1" ] ;
|
if [ -n "$1" ] ;
|
||||||
then
|
then
|
||||||
@ -984,9 +987,12 @@ EOF
|
|||||||
|
|
||||||
mysql_start ()
|
mysql_start ()
|
||||||
{
|
{
|
||||||
$ECHO "Starting MySQL daemon"
|
# We should not start the deamon here as we don't know the argumens
|
||||||
start_master
|
# for the test. Better to let the test start the deamon
|
||||||
start_slave
|
|
||||||
|
# $ECHO "Starting MySQL daemon"
|
||||||
|
# start_master
|
||||||
|
# start_slave
|
||||||
cd $MYSQL_TEST_DIR
|
cd $MYSQL_TEST_DIR
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
@ -1087,8 +1093,6 @@ run_testcase ()
|
|||||||
slave_init_script=$TESTDIR/$tname-slave.sh
|
slave_init_script=$TESTDIR/$tname-slave.sh
|
||||||
slave_master_info_file=$TESTDIR/$tname-slave-master-info.opt
|
slave_master_info_file=$TESTDIR/$tname-slave-master-info.opt
|
||||||
echo $tname > $CURRENT_TEST
|
echo $tname > $CURRENT_TEST
|
||||||
echo "CURRENT_TEST: $tname" >> $SLAVE_MYERR
|
|
||||||
echo "CURRENT_TEST: $tname" >> $MASTER_MYERR
|
|
||||||
SKIP_SLAVE=`$EXPR \( $tname : rpl \) = 0`
|
SKIP_SLAVE=`$EXPR \( $tname : rpl \) = 0`
|
||||||
if [ $USE_MANAGER = 1 ] ; then
|
if [ $USE_MANAGER = 1 ] ; then
|
||||||
many_slaves=`$EXPR \( $tname : rpl_failsafe \) != 0`
|
many_slaves=`$EXPR \( $tname : rpl_failsafe \) != 0`
|
||||||
@ -1125,13 +1129,17 @@ run_testcase ()
|
|||||||
then
|
then
|
||||||
EXTRA_MASTER_OPT=`$CAT $master_opt_file | $SED -e "s;\\$MYSQL_TEST_DIR;$MYSQL_TEST_DIR;"`
|
EXTRA_MASTER_OPT=`$CAT $master_opt_file | $SED -e "s;\\$MYSQL_TEST_DIR;$MYSQL_TEST_DIR;"`
|
||||||
stop_master
|
stop_master
|
||||||
|
echo "CURRENT_TEST: $tname" >> $MASTER_MYERR
|
||||||
start_master
|
start_master
|
||||||
else
|
else
|
||||||
if [ ! -z "$EXTRA_MASTER_OPT" ] || [ x$MASTER_RUNNING != x1 ] ;
|
if [ ! -z "$EXTRA_MASTER_OPT" ] || [ x$MASTER_RUNNING != x1 ] ;
|
||||||
then
|
then
|
||||||
EXTRA_MASTER_OPT=""
|
EXTRA_MASTER_OPT=""
|
||||||
stop_master
|
stop_master
|
||||||
|
echo "CURRENT_TEST: $tname" >> $MASTER_MYERR
|
||||||
start_master
|
start_master
|
||||||
|
else
|
||||||
|
echo "CURRENT_TEST: $tname" >> $MASTER_MYERR
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -1161,7 +1169,10 @@ run_testcase ()
|
|||||||
|
|
||||||
if [ x$do_slave_restart = x1 ] ; then
|
if [ x$do_slave_restart = x1 ] ; then
|
||||||
stop_slave
|
stop_slave
|
||||||
|
echo "CURRENT_TEST: $tname" >> $SLAVE_MYERR
|
||||||
start_slave
|
start_slave
|
||||||
|
else
|
||||||
|
echo "CURRENT_TEST: $tname" >> $SLAVE_MYERR
|
||||||
fi
|
fi
|
||||||
if [ x$many_slaves = x1 ]; then
|
if [ x$many_slaves = x1 ]; then
|
||||||
start_slave 1
|
start_slave 1
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
drop table if exists t1;
|
drop table if exists t1,t2;
|
||||||
CREATE TABLE t1 (
|
CREATE TABLE t1 (
|
||||||
STRING_DATA char(255) default NULL,
|
STRING_DATA char(255) default NULL,
|
||||||
KEY string_data (STRING_DATA)
|
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);
|
ALTER TABLE t1 ADD INDEX t1 (a, b, c);
|
||||||
Specified key was too long. Max key length is 500
|
Specified key was too long. Max key length is 500
|
||||||
DROP TABLE t1;
|
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;
|
||||||
|
@ -2,10 +2,15 @@
|
|||||||
# Test bugs in the MyISAM code
|
# Test bugs in the MyISAM code
|
||||||
#
|
#
|
||||||
|
|
||||||
|
# Initialise
|
||||||
--disable_warnings
|
--disable_warnings
|
||||||
drop table if exists t1;
|
drop table if exists t1,t2;
|
||||||
--enable_warnings
|
--enable_warnings
|
||||||
|
|
||||||
|
#
|
||||||
|
# Test problem with CHECK TABLE;
|
||||||
|
#
|
||||||
|
|
||||||
CREATE TABLE t1 (
|
CREATE TABLE t1 (
|
||||||
STRING_DATA char(255) default NULL,
|
STRING_DATA char(255) default NULL,
|
||||||
KEY string_data (STRING_DATA)
|
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);
|
ALTER TABLE t1 ADD INDEX t1 (a, b, c);
|
||||||
DROP TABLE t1;
|
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;
|
||||||
|
@ -40,15 +40,33 @@ static int compare_bin(uchar *a, uint a_length, uchar *b, uint b_length,
|
|||||||
return (int) (a_length-b_length);
|
return (int) (a_length-b_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FCMP(A,B) ((int) (A) - (int) (B))
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Compare two keys
|
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
|
SYNOPSIS
|
||||||
If flag <> SEARCH_FIND compare also position
|
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,
|
int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
|
||||||
register uchar *b, uint key_length, uint nextflag,
|
register uchar *b, uint key_length, uint nextflag,
|
||||||
uint *diff_pos)
|
uint *diff_pos)
|
||||||
@ -59,9 +77,10 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
|
|||||||
uint32 u_1,u_2;
|
uint32 u_1,u_2;
|
||||||
float f_1,f_2;
|
float f_1,f_2;
|
||||||
double d_1,d_2;
|
double d_1,d_2;
|
||||||
|
uint next_key_length;
|
||||||
|
|
||||||
*diff_pos=0;
|
*diff_pos=0;
|
||||||
for ( ; (int) key_length >0 ; keyseg++)
|
for ( ; (int) key_length >0 ; key_length=next_key_length, keyseg++)
|
||||||
{
|
{
|
||||||
uchar *end;
|
uchar *end;
|
||||||
uint piks=! (keyseg->flag & HA_NO_SORT);
|
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))
|
if (nextflag == (SEARCH_FIND | SEARCH_UPDATE))
|
||||||
nextflag=SEARCH_SAME; /* Allow duplicate keys */
|
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 */
|
continue; /* To next key part */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end= a+ min(keyseg->length,key_length);
|
end= a+ min(keyseg->length,key_length);
|
||||||
|
next_key_length=key_length-keyseg->length;
|
||||||
|
|
||||||
switch ((enum ha_base_keytype) keyseg->type) {
|
switch ((enum ha_base_keytype) keyseg->type) {
|
||||||
case HA_KEYTYPE_TEXT: /* Ascii; Key is converted */
|
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;
|
int a_length,b_length,pack_length;
|
||||||
get_key_length(a_length,a);
|
get_key_length(a_length,a);
|
||||||
get_key_pack_length(b_length,pack_length,b);
|
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 &&
|
if (piks &&
|
||||||
(flag= mi_compare_text(keyseg->charset,a,a_length,b,b_length,
|
(flag=mi_compare_text(keyseg->charset,a,a_length,b,b_length,
|
||||||
(my_bool) ((nextflag & SEARCH_PREFIX) &&
|
(my_bool) ((nextflag & SEARCH_PREFIX) &&
|
||||||
key_length <= 0))))
|
next_key_length <= 0))))
|
||||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
a+=a_length;
|
a+=a_length;
|
||||||
b+=b_length;
|
b+=b_length;
|
||||||
@ -107,7 +137,6 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint length=(uint) (end-a), a_length=length, b_length=length;
|
uint length=(uint) (end-a), a_length=length, b_length=length;
|
||||||
key_length-= keyseg->length;
|
|
||||||
if (!(nextflag & SEARCH_PREFIX))
|
if (!(nextflag & SEARCH_PREFIX))
|
||||||
{
|
{
|
||||||
while (a_length && a[a_length-1] == ' ')
|
while (a_length && a[a_length-1] == ' ')
|
||||||
@ -116,9 +145,9 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
|
|||||||
b_length--;
|
b_length--;
|
||||||
}
|
}
|
||||||
if (piks &&
|
if (piks &&
|
||||||
(flag= mi_compare_text(keyseg->charset,a,a_length,b,b_length,
|
(flag= mi_compare_text(keyseg->charset, a, a_length, b, b_length,
|
||||||
(my_bool) ((nextflag & SEARCH_PREFIX) &&
|
(my_bool) ((nextflag & SEARCH_PREFIX) &&
|
||||||
key_length <= 0))))
|
next_key_length <= 0))))
|
||||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
a=end;
|
a=end;
|
||||||
b+=length;
|
b+=length;
|
||||||
@ -130,12 +159,12 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
|
|||||||
int a_length,b_length,pack_length;
|
int a_length,b_length,pack_length;
|
||||||
get_key_length(a_length,a);
|
get_key_length(a_length,a);
|
||||||
get_key_pack_length(b_length,pack_length,b);
|
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 &&
|
if (piks &&
|
||||||
(flag=compare_bin(a,a_length,b,b_length,
|
(flag=compare_bin(a,a_length,b,b_length,
|
||||||
(my_bool) ((nextflag & SEARCH_PREFIX) &&
|
(my_bool) ((nextflag & SEARCH_PREFIX) &&
|
||||||
key_length <= 0))))
|
next_key_length <= 0))))
|
||||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
a+=a_length;
|
a+=a_length;
|
||||||
b+=b_length;
|
b+=b_length;
|
||||||
@ -144,11 +173,10 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint length=keyseg->length;
|
uint length=keyseg->length;
|
||||||
key_length-= keyseg->length;
|
|
||||||
if (piks &&
|
if (piks &&
|
||||||
(flag=compare_bin(a,length,b,length,
|
(flag=compare_bin(a,length,b,length,
|
||||||
(my_bool) ((nextflag & SEARCH_PREFIX) &&
|
(my_bool) ((nextflag & SEARCH_PREFIX) &&
|
||||||
key_length <= 0))))
|
next_key_length <= 0))))
|
||||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
a+=length;
|
a+=length;
|
||||||
b+=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;
|
int a_length,b_length,pack_length;
|
||||||
get_key_length(a_length,a);
|
get_key_length(a_length,a);
|
||||||
get_key_pack_length(b_length,pack_length,b);
|
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 &&
|
if (piks &&
|
||||||
(flag= mi_compare_text(keyseg->charset,a,a_length,b,b_length,
|
(flag= mi_compare_text(keyseg->charset,a,a_length,b,b_length,
|
||||||
(my_bool) ((nextflag & SEARCH_PREFIX) &&
|
(my_bool) ((nextflag & SEARCH_PREFIX) &&
|
||||||
key_length <= 0))))
|
next_key_length <= 0))))
|
||||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
a+=a_length;
|
a+=a_length;
|
||||||
b+=b_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;
|
int a_length,b_length,pack_length;
|
||||||
get_key_length(a_length,a);
|
get_key_length(a_length,a);
|
||||||
get_key_pack_length(b_length,pack_length,b);
|
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 &&
|
if (piks &&
|
||||||
(flag=compare_bin(a,a_length,b,b_length,
|
(flag=compare_bin(a,a_length,b,b_length,
|
||||||
(my_bool) ((nextflag & SEARCH_PREFIX) &&
|
(my_bool) ((nextflag & SEARCH_PREFIX) &&
|
||||||
key_length <= 0))))
|
next_key_length <= 0))))
|
||||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
a+=a_length;
|
a+=a_length;
|
||||||
b+=b_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);
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
a= end;
|
a= end;
|
||||||
b++;
|
b++;
|
||||||
key_length-= keyseg->length;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case HA_KEYTYPE_SHORT_INT:
|
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);
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
a= end;
|
a= end;
|
||||||
b+= 2; /* sizeof(short int); */
|
b+= 2; /* sizeof(short int); */
|
||||||
key_length-= keyseg->length;
|
|
||||||
break;
|
break;
|
||||||
case HA_KEYTYPE_USHORT_INT:
|
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);
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
a= end;
|
a= end;
|
||||||
b+=2; /* sizeof(short int); */
|
b+=2; /* sizeof(short int); */
|
||||||
key_length-= keyseg->length;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case HA_KEYTYPE_LONG_INT:
|
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);
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
a= end;
|
a= end;
|
||||||
b+= 4; /* sizeof(long int); */
|
b+= 4; /* sizeof(long int); */
|
||||||
key_length-= keyseg->length;
|
|
||||||
break;
|
break;
|
||||||
case HA_KEYTYPE_ULONG_INT:
|
case HA_KEYTYPE_ULONG_INT:
|
||||||
u_1= mi_sint4korr(a);
|
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);
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
a= end;
|
a= end;
|
||||||
b+= 4; /* sizeof(long int); */
|
b+= 4; /* sizeof(long int); */
|
||||||
key_length-= keyseg->length;
|
|
||||||
break;
|
break;
|
||||||
case HA_KEYTYPE_INT24:
|
case HA_KEYTYPE_INT24:
|
||||||
l_1=mi_sint3korr(a);
|
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);
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
a= end;
|
a= end;
|
||||||
b+= 3;
|
b+= 3;
|
||||||
key_length-= keyseg->length;
|
|
||||||
break;
|
break;
|
||||||
case HA_KEYTYPE_UINT24:
|
case HA_KEYTYPE_UINT24:
|
||||||
l_1=mi_uint3korr(a);
|
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);
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
a= end;
|
a= end;
|
||||||
b+= 3;
|
b+= 3;
|
||||||
key_length-= keyseg->length;
|
|
||||||
break;
|
break;
|
||||||
case HA_KEYTYPE_FLOAT:
|
case HA_KEYTYPE_FLOAT:
|
||||||
mi_float4get(f_1,a);
|
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);
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
a= end;
|
a= end;
|
||||||
b+= 4; /* sizeof(float); */
|
b+= 4; /* sizeof(float); */
|
||||||
key_length-= keyseg->length;
|
|
||||||
break;
|
break;
|
||||||
case HA_KEYTYPE_DOUBLE:
|
case HA_KEYTYPE_DOUBLE:
|
||||||
mi_float8get(d_1,a);
|
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);
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
a= end;
|
a= end;
|
||||||
b+= 8; /* sizeof(double); */
|
b+= 8; /* sizeof(double); */
|
||||||
key_length-= keyseg->length;
|
|
||||||
break;
|
break;
|
||||||
case HA_KEYTYPE_NUM: /* Numeric key */
|
case HA_KEYTYPE_NUM: /* Numeric key */
|
||||||
{
|
{
|
||||||
int swap_flag= 0;
|
int swap_flag= 0;
|
||||||
int alength,blength;
|
int alength,blength;
|
||||||
|
|
||||||
if (keyseg->flag & HA_REVERSE_SORT)
|
if (keyseg->flag & HA_REVERSE_SORT)
|
||||||
{
|
{
|
||||||
swap(uchar*,a,b);
|
swap(uchar*,a,b);
|
||||||
@ -289,7 +308,7 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
|
|||||||
{
|
{
|
||||||
alength= *a++; blength= *b++;
|
alength= *a++; blength= *b++;
|
||||||
end=a+alength;
|
end=a+alength;
|
||||||
key_length-= blength + 1;
|
next_key_length=key_length-blength-1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -298,9 +317,7 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
|
|||||||
/* remove pre space from keys */
|
/* remove pre space from keys */
|
||||||
for ( ; alength && *a == ' ' ; a++, alength--) ;
|
for ( ; alength && *a == ' ' ; a++, alength--) ;
|
||||||
for ( ; blength && *b == ' ' ; b++, blength--) ;
|
for ( ; blength && *b == ' ' ; b++, blength--) ;
|
||||||
key_length-= keyseg->length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (piks)
|
if (piks)
|
||||||
{
|
{
|
||||||
if (*a == '-')
|
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);
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
a= end;
|
a= end;
|
||||||
b+= 8;
|
b+= 8;
|
||||||
key_length-= keyseg->length;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case HA_KEYTYPE_ULONGLONG:
|
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);
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
a= end;
|
a= end;
|
||||||
b+= 8;
|
b+= 8;
|
||||||
key_length-= keyseg->length;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -48,7 +48,10 @@ $opt_optimization="None";
|
|||||||
$opt_hw="";
|
$opt_hw="";
|
||||||
$opt_threads=5;
|
$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",
|
$log_prog_args=join(" ", skip_arguments(\@ARGV,"comments","cmp","server",
|
||||||
"user", "host", "database", "password",
|
"user", "host", "database", "password",
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
# as such, and clarify ones such as "mediumint" with comments such as
|
# as such, and clarify ones such as "mediumint" with comments such as
|
||||||
# "3-byte int" or "same as xxx".
|
# "3-byte int" or "same as xxx".
|
||||||
|
|
||||||
$version="1.59";
|
$version="1.60";
|
||||||
|
|
||||||
use DBI;
|
use DBI;
|
||||||
use Getopt::Long;
|
use Getopt::Long;
|
||||||
@ -50,7 +50,7 @@ $opt_server="mysql"; $opt_host="localhost"; $opt_database="test";
|
|||||||
$opt_dir="limits";
|
$opt_dir="limits";
|
||||||
$opt_user=$opt_password="";$opt_verbose="";
|
$opt_user=$opt_password="";$opt_verbose="";
|
||||||
$opt_debug=$opt_help=$opt_Information=$opt_restart=$opt_force=$opt_quick=0;
|
$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_db_start_cmd=""; # the db server start command
|
||||||
$opt_check_server=0; # Check if server is alive before each query
|
$opt_check_server=0; # Check if server is alive before each query
|
||||||
$opt_sleep=10; # time to sleep while starting the db server
|
$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",
|
"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",
|
"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",
|
"batch-mode","config-file=s","log-queries-to-file=s","check-server",
|
||||||
|
"version",
|
||||||
"verbose!" => \$opt_verbose) || usage();
|
"verbose!" => \$opt_verbose) || usage();
|
||||||
usage() if ($opt_help || $opt_Information);
|
usage() if ($opt_help || $opt_Information);
|
||||||
|
version() && exit(0) if ($opt_version);
|
||||||
|
|
||||||
$opt_suffix = '-'.$opt_suffix if (length($opt_suffix) != 0);
|
$opt_suffix = '-'.$opt_suffix if (length($opt_suffix) != 0);
|
||||||
$opt_config_file = "$pwd/$opt_dir/$opt_server$opt_suffix.cfg"
|
$opt_config_file = "$pwd/$opt_dir/$opt_server$opt_suffix.cfg"
|
||||||
@ -1190,7 +1192,7 @@ else
|
|||||||
|
|
||||||
# Test: NOROUND
|
# Test: NOROUND
|
||||||
{
|
{
|
||||||
my $resultat = 'undefined';
|
my $result = 'undefined';
|
||||||
my $error;
|
my $error;
|
||||||
print "NOROUND: ";
|
print "NOROUND: ";
|
||||||
save_incomplete('func_extra_noround','Function 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");
|
$error = safe_query_l('func_extra_noround',"select noround(22.6) $end_query");
|
||||||
if ($error ne 1) # syntax error -- noround is not supported
|
if ($error ne 1) # syntax error -- noround is not supported
|
||||||
{
|
{
|
||||||
$resultat = 'no'
|
$result = 'no'
|
||||||
} else # Ok, now check if it really works
|
}
|
||||||
{
|
else # Ok, now check if it really works
|
||||||
|
{
|
||||||
$error=safe_query_l('func_extra_noround',
|
$error=safe_query_l('func_extra_noround',
|
||||||
["create table crash_me_nr (a int)",
|
["create table crash_me_nr (a int)",
|
||||||
"insert into crash_me_nr values(noround(10.2))",
|
"insert into crash_me_nr values(noround(10.2))",
|
||||||
"drop table crash_me_nr $drop_attr"]);
|
"drop table crash_me_nr $drop_attr"]);
|
||||||
if ($error eq 1) {
|
if ($error == 1)
|
||||||
$resultat = "syntax only";
|
{
|
||||||
} else {
|
$result= "syntax only";
|
||||||
$resultat = 'yes';
|
}
|
||||||
}
|
else
|
||||||
}
|
{
|
||||||
print "$resultat\n";
|
$result= 'yes';
|
||||||
save_config_data('func_extra_noround',$resultat,"Function NOROUND");
|
}
|
||||||
|
}
|
||||||
|
print "$result\n";
|
||||||
|
save_config_data('func_extra_noround',$result,"Function NOROUND");
|
||||||
}
|
}
|
||||||
|
|
||||||
check_parenthesis("func_sql_","CURRENT_USER");
|
check_parenthesis("func_sql_","CURRENT_USER");
|
||||||
@ -1377,7 +1383,7 @@ if ($limits{'type_sql_date'} eq 'yes')
|
|||||||
|
|
||||||
# Test: WEEK()
|
# Test: WEEK()
|
||||||
{
|
{
|
||||||
my $resultat="no";
|
my $result="no";
|
||||||
my $error;
|
my $error;
|
||||||
print "WEEK:";
|
print "WEEK:";
|
||||||
save_incomplete('func_odbc_week','WEEK');
|
save_incomplete('func_odbc_week','WEEK');
|
||||||
@ -1388,17 +1394,17 @@ if ($limits{'type_sql_date'} eq 'yes')
|
|||||||
# and 0 - EURO weeks
|
# and 0 - EURO weeks
|
||||||
if ($error == -1) {
|
if ($error == -1) {
|
||||||
if ($last_result == 4) {
|
if ($last_result == 4) {
|
||||||
$resultat = 'USA';
|
$result = 'USA';
|
||||||
} else {
|
} else {
|
||||||
$resultat='error';
|
$result='error';
|
||||||
add_log('func_odbc_week',
|
add_log('func_odbc_week',
|
||||||
" must return 4 or 5, but $last_result");
|
" must return 4 or 5, but $last_result");
|
||||||
}
|
}
|
||||||
} elsif ($error == 0) {
|
} elsif ($error == 0) {
|
||||||
$resultat = 'EURO';
|
$result = 'EURO';
|
||||||
}
|
}
|
||||||
print " $resultat\n";
|
print " $result\n";
|
||||||
save_config_data('func_odbc_week',$resultat,"WEEK");
|
save_config_data('func_odbc_week',$result,"WEEK");
|
||||||
}
|
}
|
||||||
|
|
||||||
my $insert_query ='insert into crash_me_d values('.
|
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
|
# NOT id BETWEEN a and b
|
||||||
if ($limits{'func_where_not_between'} eq 'yes')
|
if ($limits{'func_where_not_between'} eq 'yes')
|
||||||
{
|
{
|
||||||
my $resultat = 'error';
|
my $result = 'error';
|
||||||
my $err;
|
my $err;
|
||||||
my $key='not_id_between';
|
my $key='not_id_between';
|
||||||
my $prompt='NOT ID BETWEEN interprets as ID NOT 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);
|
5,0);
|
||||||
if ($err eq 1) {
|
if ($err eq 1) {
|
||||||
if (not defined($last_result)) {
|
if (not defined($last_result)) {
|
||||||
$resultat='no';
|
$result='no';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
if ( $err eq 0) {
|
if ( $err eq 0) {
|
||||||
$resultat = 'yes';
|
$result = 'yes';
|
||||||
};
|
};
|
||||||
safe_query_l($key,["drop table crash_me_b"]);
|
safe_query_l($key,["drop table crash_me_b"]);
|
||||||
save_config_data($key,$resultat,$prompt);
|
save_config_data($key,$result,$prompt);
|
||||||
print "$resultat\n";
|
print "$result\n";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -2018,37 +2024,44 @@ report("views","views",
|
|||||||
|
|
||||||
# Test: foreign key
|
# Test: foreign key
|
||||||
{
|
{
|
||||||
my $resultat = 'undefined';
|
my $result = 'undefined';
|
||||||
my $error;
|
my $error;
|
||||||
print "foreign keys: ";
|
print "foreign keys: ";
|
||||||
save_incomplete('foreign_key','foreign keys');
|
save_incomplete('foreign_key','foreign keys');
|
||||||
|
|
||||||
# 1) check if foreign keys are supported
|
# 1) check if foreign keys are supported
|
||||||
safe_query_l('foreign_key',create_table("crash_me_qf",["a integer not null"],
|
safe_query_l('foreign_key',
|
||||||
["primary key (a)"]));
|
create_table("crash_me_qf",
|
||||||
$error = safe_query_l('foreign_key',
|
["a integer not null"],
|
||||||
create_table("crash_me_qf2",["a integer not null",
|
["primary key (a)"]));
|
||||||
"foreign key (a) references crash_me_qf (a)"], []));
|
$error= safe_query_l('foreign_key',
|
||||||
|
create_table("crash_me_qf2",
|
||||||
if ($error eq 1) # OK -- syntax is supported
|
["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
|
# now check if foreign key really works
|
||||||
safe_query_l('foreign_key', "insert into crash_me_qf values (1)");
|
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';
|
$result = 'syntax only';
|
||||||
} else {
|
}
|
||||||
$resultat = 'yes';
|
else
|
||||||
}
|
{
|
||||||
|
$result = 'yes';
|
||||||
} else {
|
}
|
||||||
$resultat = "no";
|
}
|
||||||
}
|
else
|
||||||
safe_query_l('foreign_key',
|
{
|
||||||
"drop table crash_me_qf2 $drop_attr","drop table crash_me_qf $drop_attr");
|
$result = "no";
|
||||||
print "$resultat\n";
|
}
|
||||||
save_config_data('foreign_key',$resultat,"foreign keys");
|
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",
|
report("Create SCHEMA","create_schema",
|
||||||
@ -2607,7 +2620,7 @@ sub detect_null_position
|
|||||||
sub check_parenthesis {
|
sub check_parenthesis {
|
||||||
my $prefix=shift;
|
my $prefix=shift;
|
||||||
my $fn=shift;
|
my $fn=shift;
|
||||||
my $resultat='no';
|
my $result='no';
|
||||||
my $param_name=$prefix.lc($fn);
|
my $param_name=$prefix.lc($fn);
|
||||||
my $r;
|
my $r;
|
||||||
|
|
||||||
@ -2616,18 +2629,18 @@ sub check_parenthesis {
|
|||||||
add_log($param_name,$safe_query_log);
|
add_log($param_name,$safe_query_log);
|
||||||
if ($r == 1)
|
if ($r == 1)
|
||||||
{
|
{
|
||||||
$resultat="yes";
|
$result="yes";
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
$r = safe_query("select $fn() $end_query");
|
$r = safe_query("select $fn() $end_query");
|
||||||
add_log($param_name,$safe_query_log);
|
add_log($param_name,$safe_query_log);
|
||||||
if ( $r == 1)
|
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 {
|
sub check_constraint {
|
||||||
@ -2699,10 +2712,16 @@ sub make_date {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
sub version
|
||||||
|
{
|
||||||
|
print "$0 Ver $version\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
sub usage
|
sub usage
|
||||||
{
|
{
|
||||||
|
version();
|
||||||
print <<EOF;
|
print <<EOF;
|
||||||
$0 Ver $version
|
|
||||||
|
|
||||||
This program tries to find all limits and capabilities for a SQL
|
This program tries to find all limits and capabilities for a SQL
|
||||||
server. As it will use the server in some 'unexpected' ways, one
|
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);
|
my $r = safe_query($q);
|
||||||
add_log($key,$safe_query_log);
|
add_log($key,$safe_query_log);
|
||||||
return $r;
|
return $r;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub safe_query
|
sub safe_query
|
||||||
{
|
{
|
||||||
@ -3110,7 +3129,6 @@ sub safe_query
|
|||||||
$retry = $retry_limit;
|
$retry = $retry_limit;
|
||||||
$retry_ok = 1;
|
$retry_ok = 1;
|
||||||
$safe_query_log .= "> OK\n";
|
$safe_query_log .= "> OK\n";
|
||||||
|
|
||||||
}
|
}
|
||||||
$sth->finish;
|
$sth->finish;
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ $opt_start_field_count=8; # start with this many fields
|
|||||||
$opt_loop_count=20; # How many tests to do
|
$opt_loop_count=20; # How many tests to do
|
||||||
$opt_row_count=1000; # Rows in the table
|
$opt_row_count=1000; # Rows in the table
|
||||||
$opt_field_count=1000; # Add until this many fields.
|
$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 '');
|
chomp($pwd = `pwd`); $pwd = "." if ($pwd eq '');
|
||||||
require "$pwd/bench-init.pl" || die "Can't read Configuration file: $!\n";
|
require "$pwd/bench-init.pl" || die "Can't read Configuration file: $!\n";
|
||||||
@ -113,10 +114,9 @@ if ($opt_fast)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$add=1 if (!$limits{'alter_add_multi_col'});
|
$add=1 if (!$limits->{'alter_add_multi_col'});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$count=0;
|
$count=0;
|
||||||
while ($field_count < $opt_field_count)
|
while ($field_count < $opt_field_count)
|
||||||
{
|
{
|
||||||
@ -131,19 +131,43 @@ while ($field_count < $opt_field_count)
|
|||||||
$tmp="" if (!$multi_add); # Adabas
|
$tmp="" if (!$multi_add); # Adabas
|
||||||
}
|
}
|
||||||
do_query($dbh,"ALTER TABLE bench " . substr($fields,1));
|
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;
|
$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";
|
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
|
#### Test adding and deleting index on the first $opt_start_fields
|
||||||
####
|
####
|
||||||
|
|
||||||
$loop_time=new Benchmark;
|
$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;
|
$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";
|
timestr(timediff($end_time, $loop_time),"all") . "\n\n";
|
||||||
|
|
||||||
$loop_time=new Benchmark;
|
$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;
|
$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'})
|
$dbh->do("ALTER TABLE bench " . substr($fields,1) . $server->{'drop_attr'})
|
||||||
|| die $DBI::errstr;
|
|| 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;
|
$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";
|
timestr(timediff($end_time, $loop_time),"all") . "\n\n";
|
||||||
|
|
||||||
skip_dropcol:
|
skip_dropcol:
|
||||||
|
@ -21,10 +21,11 @@
|
|||||||
# $opt_loop_count rows in random order
|
# $opt_loop_count rows in random order
|
||||||
#
|
#
|
||||||
# changes made for Oracle compatibility
|
# 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
|
# set it to 0 in server-cfg
|
||||||
# - the default server config runs out of rollback segments, so I added a couple
|
# - the default server config runs out of rollback segments, so we added a
|
||||||
# of disconnect/connects to reset
|
# couple of disconnect/connects to reset
|
||||||
|
#
|
||||||
##################### Standard benchmark inits ##############################
|
##################### Standard benchmark inits ##############################
|
||||||
|
|
||||||
use DBI;
|
use DBI;
|
||||||
|
@ -161,6 +161,7 @@ static SYMBOL symbols[] = {
|
|||||||
{ "FLUSH", SYM(FLUSH_SYM),0,0},
|
{ "FLUSH", SYM(FLUSH_SYM),0,0},
|
||||||
{ "FALSE", SYM(FALSE_SYM),0,0},
|
{ "FALSE", SYM(FALSE_SYM),0,0},
|
||||||
{ "FOREIGN", SYM(FOREIGN),0,0},
|
{ "FOREIGN", SYM(FOREIGN),0,0},
|
||||||
|
{ "FORCE", SYM(FORCE_SYM),0,0},
|
||||||
{ "RAID_TYPE", SYM(RAID_TYPE),0,0},
|
{ "RAID_TYPE", SYM(RAID_TYPE),0,0},
|
||||||
{ "RAID_CHUNKS", SYM(RAID_CHUNKS),0,0},
|
{ "RAID_CHUNKS", SYM(RAID_CHUNKS),0,0},
|
||||||
{ "RAID_CHUNKSIZE", SYM(RAID_CHUNKSIZE),0,0},
|
{ "RAID_CHUNKSIZE", SYM(RAID_CHUNKSIZE),0,0},
|
||||||
|
@ -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)
|
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)
|
if (rli->inside_transaction)
|
||||||
rli->inc_pending(get_event_len());
|
rli->inc_pending(get_event_len());
|
||||||
@ -1435,13 +1447,36 @@ void Load_log_event::set_fields(List<Item> &field_list)
|
|||||||
}
|
}
|
||||||
#endif // !MYSQL_CLIENT
|
#endif // !MYSQL_CLIENT
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
|
|
||||||
Load_log_event::exec_event()
|
|
||||||
|
|
||||||
****************************************************************************/
|
|
||||||
#ifndef MYSQL_CLIENT
|
#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);
|
init_sql_alloc(&thd->mem_root, 8192,0);
|
||||||
thd->db = rewrite_db((char*)db);
|
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))
|
TL_WRITE))
|
||||||
thd->query_error = 1;
|
thd->query_error = 1;
|
||||||
if (thd->cuted_fields)
|
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 \
|
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 );
|
thd->cuted_fields );
|
||||||
|
}
|
||||||
if (net)
|
if (net)
|
||||||
net->pkt_nr= thd->net.pkt_nr;
|
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 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Log_event::exec_event(rli);
|
return ( use_rli_only_for_errors ? 0 : Log_event::exec_event(rli) );
|
||||||
}
|
}
|
||||||
#endif // !MYSQL_CLIENT
|
#endif // !MYSQL_CLIENT
|
||||||
|
|
||||||
@ -2680,7 +2721,11 @@ int Execute_load_log_event::exec_event(struct st_relay_log_info* rli)
|
|||||||
save_options = thd->options;
|
save_options = thd->options;
|
||||||
thd->options &= ~ (ulong) (OPTION_BIN_LOG);
|
thd->options &= ~ (ulong) (OPTION_BIN_LOG);
|
||||||
lev->thd = thd;
|
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);
|
slave_print_error(rli,my_errno, "Failed executing load from '%s'", fname);
|
||||||
thd->options = save_options;
|
thd->options = save_options;
|
||||||
|
@ -460,9 +460,10 @@ public:
|
|||||||
const char* get_db() { return db; }
|
const char* get_db() { return db; }
|
||||||
int exec_event(struct st_relay_log_info* rli)
|
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
|
#else
|
||||||
void print(FILE* file, bool short_form = 0, char* last_db = 0);
|
void print(FILE* file, bool short_form = 0, char* last_db = 0);
|
||||||
#endif
|
#endif
|
||||||
|
@ -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_FREE "FREE"
|
||||||
#define SHOW_LOG_STATUS_INUSE "IN USE"
|
#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 */
|
/* Some portable defines */
|
||||||
|
|
||||||
#define portable_sizeof_char_ptr 8
|
#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);
|
void find_date(char *pos,uint *vek,uint flag);
|
||||||
TYPELIB *convert_strings_to_array_type(my_string *typelibs, my_string *end);
|
TYPELIB *convert_strings_to_array_type(my_string *typelibs, my_string *end);
|
||||||
TYPELIB *typelib(List<String> &strings);
|
TYPELIB *typelib(List<String> &strings);
|
||||||
void clean_up(bool print_message=1);
|
|
||||||
ulong get_form_pos(File file, uchar *head, TYPELIB *save_names);
|
ulong get_form_pos(File file, uchar *head, TYPELIB *save_names);
|
||||||
ulong make_new_entry(File file,uchar *fileinfo,TYPELIB *formnames,
|
ulong make_new_entry(File file,uchar *fileinfo,TYPELIB *formnames,
|
||||||
const char *newname);
|
const char *newname);
|
||||||
|
@ -491,6 +491,7 @@ extern "C" pthread_handler_decl(handle_slave,arg);
|
|||||||
static uint set_maximum_open_files(uint max_file_limit);
|
static uint set_maximum_open_files(uint max_file_limit);
|
||||||
#endif
|
#endif
|
||||||
static ulong find_bit_type(const char *x, TYPELIB *bit_lib);
|
static ulong find_bit_type(const char *x, TYPELIB *bit_lib);
|
||||||
|
static void clean_up(bool print_message);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
** Code to end mysqld
|
** Code to end mysqld
|
||||||
@ -763,13 +764,13 @@ void kill_mysql(void)
|
|||||||
|
|
||||||
#if defined(OS2)
|
#if defined(OS2)
|
||||||
extern "C" void kill_server(int sig_ptr)
|
extern "C" void kill_server(int sig_ptr)
|
||||||
#define RETURN_FROM_KILL_SERVER return
|
#define RETURN_FROM_KILL_SERVER DBUG_RETURN
|
||||||
#elif !defined(__WIN__)
|
#elif !defined(__WIN__)
|
||||||
static void *kill_server(void *sig_ptr)
|
static void *kill_server(void *sig_ptr)
|
||||||
#define RETURN_FROM_KILL_SERVER return 0
|
#define RETURN_FROM_KILL_SERVER DBUG_RETURN(0)
|
||||||
#else
|
#else
|
||||||
static void __cdecl kill_server(int sig_ptr)
|
static void __cdecl kill_server(int sig_ptr)
|
||||||
#define RETURN_FROM_KILL_SERVER return
|
#define RETURN_FROM_KILL_SERVER DBUG_RETURN
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
int sig=(int) (long) sig_ptr; // This is passed a int
|
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)
|
void unireg_end(void)
|
||||||
{
|
{
|
||||||
clean_up();
|
clean_up(1);
|
||||||
my_thread_end();
|
my_thread_end();
|
||||||
#ifdef SIGNALS_DONT_BREAK_READ
|
#ifdef SIGNALS_DONT_BREAK_READ
|
||||||
exit(0);
|
exit(0);
|
||||||
@ -863,7 +864,7 @@ extern "C" void unireg_abort(int exit_code)
|
|||||||
DBUG_ENTER("unireg_abort");
|
DBUG_ENTER("unireg_abort");
|
||||||
if (exit_code)
|
if (exit_code)
|
||||||
sql_print_error("Aborting\n");
|
sql_print_error("Aborting\n");
|
||||||
clean_up(); /* purecov: inspected */
|
clean_up(1); /* purecov: inspected */
|
||||||
DBUG_PRINT("quit",("done with cleanup in unireg_abort"));
|
DBUG_PRINT("quit",("done with cleanup in unireg_abort"));
|
||||||
my_thread_end();
|
my_thread_end();
|
||||||
exit(exit_code); /* purecov: inspected */
|
exit(exit_code); /* purecov: inspected */
|
||||||
@ -908,12 +909,12 @@ void clean_up(bool print_message)
|
|||||||
regex_end();
|
regex_end();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (print_message && errmesg)
|
||||||
|
sql_print_error(ER(ER_SHUTDOWN_COMPLETE),my_progname);
|
||||||
#if !defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
|
#if !defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
|
||||||
if (!opt_bootstrap)
|
if (!opt_bootstrap)
|
||||||
(void) my_delete(pidfile_name,MYF(0)); // This may not always exist
|
(void) my_delete(pidfile_name,MYF(0)); // This may not always exist
|
||||||
#endif
|
#endif
|
||||||
if (print_message && errmesg)
|
|
||||||
sql_print_error(ER(ER_SHUTDOWN_COMPLETE),my_progname);
|
|
||||||
x_free((gptr) my_errmsg[ERRMAPP]); /* Free messages */
|
x_free((gptr) my_errmsg[ERRMAPP]); /* Free messages */
|
||||||
DBUG_PRINT("quit", ("Error messages freed"));
|
DBUG_PRINT("quit", ("Error messages freed"));
|
||||||
/* Tell main we are ready */
|
/* 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 */
|
/* do the broadcast inside the lock to ensure that my_end() is not called */
|
||||||
(void) pthread_cond_broadcast(&COND_thread_count);
|
(void) pthread_cond_broadcast(&COND_thread_count);
|
||||||
(void) pthread_mutex_unlock(&LOCK_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"));
|
DBUG_PRINT("quit", ("done with cleanup"));
|
||||||
} /* clean_up */
|
} /* clean_up */
|
||||||
|
|
||||||
@ -1502,7 +1507,7 @@ static void init_signals(void)
|
|||||||
/* Change limits so that we will get a core file */
|
/* Change limits so that we will get a core file */
|
||||||
struct rlimit rl;
|
struct rlimit rl;
|
||||||
rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
|
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");
|
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
|
#endif
|
||||||
@ -1571,8 +1576,11 @@ extern "C" void *signal_hand(void *arg __attribute__((unused)))
|
|||||||
my_thread_init(); // Init new thread
|
my_thread_init(); // Init new thread
|
||||||
DBUG_ENTER("signal_hand");
|
DBUG_ENTER("signal_hand");
|
||||||
SIGNAL_THD;
|
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
|
#if SIGINT != THR_KILL_SIGNAL
|
||||||
(void) sigemptyset(&set); // Setup up SIGINT for debug
|
(void) sigemptyset(&set); // Setup up SIGINT for debug
|
||||||
(void) sigaddset(&set,SIGINT); // For debugging
|
(void) sigaddset(&set,SIGINT); // For debugging
|
||||||
@ -1660,12 +1668,15 @@ extern "C" void *signal_hand(void *arg __attribute__((unused)))
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SIGHUP:
|
case SIGHUP:
|
||||||
reload_acl_and_cache((THD*) 0,
|
if (!abort_loop)
|
||||||
(REFRESH_LOG | REFRESH_TABLES | REFRESH_FAST |
|
{
|
||||||
REFRESH_STATUS | REFRESH_GRANT | REFRESH_THREADS |
|
reload_acl_and_cache((THD*) 0,
|
||||||
REFRESH_HOSTS),
|
(REFRESH_LOG | REFRESH_TABLES | REFRESH_FAST |
|
||||||
(TABLE_LIST*) 0); // Flush logs
|
REFRESH_STATUS | REFRESH_GRANT |
|
||||||
mysql_print_status((THD*) 0); // Send debug some info
|
REFRESH_THREADS | REFRESH_HOSTS),
|
||||||
|
(TABLE_LIST*) 0); // Flush logs
|
||||||
|
mysql_print_status((THD*) 0); // Send debug some info
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
#ifdef USE_ONE_SIGNAL_HAND
|
#ifdef USE_ONE_SIGNAL_HAND
|
||||||
case THR_SERVER_ALARM:
|
case THR_SERVER_ALARM:
|
||||||
|
@ -603,12 +603,14 @@ int SQL_SELECT::test_quick_select(key_map keys_to_use, table_map prev_tables,
|
|||||||
records++; /* purecov: inspected */
|
records++; /* purecov: inspected */
|
||||||
scan_time=(double) records / TIME_FOR_COMPARE+1;
|
scan_time=(double) records / TIME_FOR_COMPARE+1;
|
||||||
read_time=(double) head->file->scan_time()+ scan_time + 1.0;
|
read_time=(double) head->file->scan_time()+ scan_time + 1.0;
|
||||||
|
if (head->force_index)
|
||||||
|
scan_time= read_time= DBL_MAX;
|
||||||
if (limit < records)
|
if (limit < records)
|
||||||
read_time=(double) records+scan_time+1; // Force to use index
|
read_time=(double) records+scan_time+1; // Force to use index
|
||||||
else if (read_time <= 2.0 && !force_quick_range)
|
else if (read_time <= 2.0 && !force_quick_range)
|
||||||
DBUG_RETURN(0); /* No need for quick select */
|
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;
|
keys_to_use&=head->keys_in_use_for_query;
|
||||||
if (keys_to_use)
|
if (keys_to_use)
|
||||||
|
@ -171,7 +171,10 @@ net_printf(THD *thd, uint errcode, ...)
|
|||||||
{
|
{
|
||||||
if (thd->bootstrap)
|
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);
|
fprintf(stderr,"ERROR: %d %s\n",errcode,text_pos);
|
||||||
thd->fatal_error=1;
|
thd->fatal_error=1;
|
||||||
}
|
}
|
||||||
|
@ -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)
|
if ((thread_mask & (SLAVE_IO|SLAVE_FORCE_ALL)) && mi->slave_running)
|
||||||
{
|
{
|
||||||
|
DBUG_PRINT("info",("Terminating IO thread"));
|
||||||
mi->abort_slave=1;
|
mi->abort_slave=1;
|
||||||
if ((error=terminate_slave_thread(mi->io_thd,io_lock,
|
if ((error=terminate_slave_thread(mi->io_thd,io_lock,
|
||||||
io_cond_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)
|
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) ;
|
DBUG_ASSERT(mi->rli.sql_thd != 0) ;
|
||||||
mi->rli.abort_slave=1;
|
mi->rli.abort_slave=1;
|
||||||
if ((error=terminate_slave_thread(mi->rli.sql_thd,sql_lock,
|
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);
|
memcpy(mi->master_log_name, rev->new_log_ident, rev->ident_len+1);
|
||||||
mi->master_log_pos= rev->pos;
|
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",
|
DBUG_PRINT("info", ("master_log_pos: '%s' %d",
|
||||||
mi->master_log_name, (ulong) mi->master_log_pos));
|
mi->master_log_name, (ulong) mi->master_log_pos));
|
||||||
#ifndef DBUG_OFF
|
#ifndef DBUG_OFF
|
||||||
|
@ -747,7 +747,7 @@ TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list)
|
|||||||
table->tablenr=thd->current_tablenr++;
|
table->tablenr=thd->current_tablenr++;
|
||||||
table->used_fields=0;
|
table->used_fields=0;
|
||||||
table->const_table=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->status=STATUS_NO_RECORD;
|
||||||
table->keys_in_use_for_query= table->keys_in_use;
|
table->keys_in_use_for_query= table->keys_in_use;
|
||||||
table->used_keys= table->keys_for_keyread;
|
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->tablenr=thd->current_tablenr++;
|
||||||
table->used_fields=0;
|
table->used_fields=0;
|
||||||
table->const_table=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->status=STATUS_NO_RECORD;
|
||||||
table->keys_in_use_for_query= table->keys_in_use;
|
table->keys_in_use_for_query= table->keys_in_use;
|
||||||
table->used_keys= table->keys_for_keyread;
|
table->used_keys= table->keys_for_keyread;
|
||||||
@ -977,6 +977,7 @@ bool reopen_table(TABLE *table,bool locked)
|
|||||||
tmp.status= table->status;
|
tmp.status= table->status;
|
||||||
tmp.keys_in_use_for_query= tmp.keys_in_use;
|
tmp.keys_in_use_for_query= tmp.keys_in_use;
|
||||||
tmp.used_keys= tmp.keys_for_keyread;
|
tmp.used_keys= tmp.keys_for_keyread;
|
||||||
|
tmp.force_index= tmp.force_index;
|
||||||
|
|
||||||
/* Get state */
|
/* Get state */
|
||||||
tmp.key_length= table->key_length;
|
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->maybe_null=test(table->outer_join=table_list->outer_join);
|
||||||
table->tablenr=tablenr;
|
table->tablenr=tablenr;
|
||||||
table->map= (table_map) 1 << tablenr;
|
table->map= (table_map) 1 << tablenr;
|
||||||
|
table->force_index= table_list->force_index;
|
||||||
if (table_list->use_index)
|
if (table_list->use_index)
|
||||||
{
|
{
|
||||||
key_map map= get_key_map_from_key_list(table,
|
key_map map= get_key_map_from_key_list(table,
|
||||||
|
@ -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; }
|
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,
|
TABLE_LIST *st_select_lex_node::add_table_to_list(THD *thd, Table_ident *table,
|
||||||
LEX_STRING *alias,
|
LEX_STRING *alias,
|
||||||
bool updating,
|
ulong table_join_options,
|
||||||
thr_lock_type flags,
|
thr_lock_type flags,
|
||||||
List<String> *use_index,
|
List<String> *use_index,
|
||||||
List<String> *ignore_index)
|
List<String> *ignore_index)
|
||||||
{
|
{
|
||||||
return 0;
|
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
|
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;
|
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 &
|
There are st_select_lex::add_table_to_list &
|
||||||
st_select_lex::set_lock_for_tables in sql_parse.cc
|
st_select_lex::set_lock_for_tables in sql_parse.cc
|
||||||
|
@ -243,9 +243,10 @@ public:
|
|||||||
virtual List<Item>* get_item_list();
|
virtual List<Item>* get_item_list();
|
||||||
virtual List<String>* get_use_index();
|
virtual List<String>* get_use_index();
|
||||||
virtual List<String>* get_ignore_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,
|
virtual TABLE_LIST *add_table_to_list(THD *thd, Table_ident *table,
|
||||||
LEX_STRING *alias,
|
LEX_STRING *alias,
|
||||||
bool updating,
|
ulong table_options,
|
||||||
thr_lock_type flags= TL_UNLOCK,
|
thr_lock_type flags= TL_UNLOCK,
|
||||||
List<String> *use_index= 0,
|
List<String> *use_index= 0,
|
||||||
List<String> *ignore_index= 0);
|
List<String> *ignore_index= 0);
|
||||||
@ -336,6 +337,7 @@ public:
|
|||||||
List<Item_func_match> ftfunc_list_alloc;
|
List<Item_func_match> ftfunc_list_alloc;
|
||||||
JOIN *join; /* after JOIN::prepare it is pointer to corresponding JOIN */
|
JOIN *join; /* after JOIN::prepare it is pointer to corresponding JOIN */
|
||||||
const char *type; /* type of select for EXPLAIN */
|
const char *type; /* type of select for EXPLAIN */
|
||||||
|
ulong table_join_options;
|
||||||
uint in_sum_expr;
|
uint in_sum_expr;
|
||||||
uint select_number; /* number of select (used for EXPLAIN) */
|
uint select_number; /* number of select (used for EXPLAIN) */
|
||||||
bool braces; /* SELECT ... UNION (SELECT ... ) <- this braces */
|
bool braces; /* SELECT ... UNION (SELECT ... ) <- this braces */
|
||||||
@ -373,9 +375,10 @@ public:
|
|||||||
List<Item>* get_item_list();
|
List<Item>* get_item_list();
|
||||||
List<String>* get_use_index();
|
List<String>* get_use_index();
|
||||||
List<String>* get_ignore_index();
|
List<String>* get_ignore_index();
|
||||||
|
ulong get_table_join_options();
|
||||||
TABLE_LIST* add_table_to_list(THD *thd, Table_ident *table,
|
TABLE_LIST* add_table_to_list(THD *thd, Table_ident *table,
|
||||||
LEX_STRING *alias,
|
LEX_STRING *alias,
|
||||||
bool updating,
|
ulong table_options,
|
||||||
thr_lock_type flags= TL_UNLOCK,
|
thr_lock_type flags= TL_UNLOCK,
|
||||||
List<String> *use_index= 0,
|
List<String> *use_index= 0,
|
||||||
List<String> *ignore_index= 0);
|
List<String> *ignore_index= 0);
|
||||||
|
@ -518,7 +518,8 @@ check_connections(THD *thd)
|
|||||||
vio_in_addr(net->vio,&thd->remote.sin_addr);
|
vio_in_addr(net->vio,&thd->remote.sin_addr);
|
||||||
thd->host=ip_to_hostname(&thd->remote.sin_addr,&connect_errors);
|
thd->host=ip_to_hostname(&thd->remote.sin_addr,&connect_errors);
|
||||||
/* Cut very long hostnames to avoid possible overflows */
|
/* 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)
|
if (connect_errors > max_connect_errors)
|
||||||
return(ER_HOST_IS_BLOCKED);
|
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_LIST *st_select_lex::add_table_to_list(THD *thd,
|
||||||
Table_ident *table,
|
Table_ident *table,
|
||||||
LEX_STRING *alias,
|
LEX_STRING *alias,
|
||||||
bool updating,
|
ulong table_options,
|
||||||
thr_lock_type flags,
|
thr_lock_type lock_type,
|
||||||
List<String> *use_index,
|
List<String> *use_index,
|
||||||
List<String> *ignore_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=table->table.str;
|
||||||
ptr->real_name_length=table->table.length;
|
ptr->real_name_length=table->table.length;
|
||||||
ptr->lock_type=flags;
|
ptr->lock_type= lock_type;
|
||||||
ptr->updating=updating;
|
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;
|
ptr->derived= (SELECT_LEX_UNIT *) table->sel;
|
||||||
if (use_index)
|
if (use_index)
|
||||||
ptr->use_index=(List<String> *) thd->memdup((gptr) 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));
|
sizeof(*ignore_index));
|
||||||
|
|
||||||
/* check that used name is unique */
|
/* check that used name is unique */
|
||||||
if (flags != TL_IGNORE)
|
if (lock_type != TL_IGNORE)
|
||||||
{
|
{
|
||||||
for (TABLE_LIST *tables=(TABLE_LIST*) table_list.first ;
|
for (TABLE_LIST *tables=(TABLE_LIST*) table_list.first ;
|
||||||
tables ;
|
tables ;
|
||||||
|
@ -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 &&
|
!(s->quick && best_key && s->quick->index == best_key->key &&
|
||||||
best_max_key_part >= s->table->quick_key_parts[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->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
|
{ // Check full join
|
||||||
if (s->on_expr)
|
if (s->on_expr)
|
||||||
{
|
{
|
||||||
|
@ -1497,6 +1497,7 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
|
|||||||
case SHOW_RPL_STATUS:
|
case SHOW_RPL_STATUS:
|
||||||
end= strmov(buff, rpl_status_type[(int)rpl_status]);
|
end= strmov(buff, rpl_status_type[(int)rpl_status]);
|
||||||
break;
|
break;
|
||||||
|
#ifndef EMBEDDED_LIBRARY
|
||||||
case SHOW_SLAVE_RUNNING:
|
case SHOW_SLAVE_RUNNING:
|
||||||
{
|
{
|
||||||
LOCK_ACTIVE_MI;
|
LOCK_ACTIVE_MI;
|
||||||
@ -1505,6 +1506,7 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
|
|||||||
UNLOCK_ACTIVE_MI;
|
UNLOCK_ACTIVE_MI;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
case SHOW_OPENTABLES:
|
case SHOW_OPENTABLES:
|
||||||
end= int10_to_str((long) cached_tables(), buff, 10);
|
end= int10_to_str((long) cached_tables(), buff, 10);
|
||||||
break;
|
break;
|
||||||
|
@ -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
|
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
|
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 FIRST_SYM
|
||||||
%token FIXED_SYM
|
%token FIXED_SYM
|
||||||
%token FLOAT_NUM
|
%token FLOAT_NUM
|
||||||
|
%token FORCE_SYM
|
||||||
%token FOREIGN
|
%token FOREIGN
|
||||||
%token FROM
|
%token FROM
|
||||||
%token FULL
|
%token FULL
|
||||||
@ -823,7 +824,8 @@ create:
|
|||||||
($2 &
|
($2 &
|
||||||
HA_LEX_CREATE_TMP_TABLE ?
|
HA_LEX_CREATE_TMP_TABLE ?
|
||||||
&tmp_table_alias :
|
&tmp_table_alias :
|
||||||
(LEX_STRING*) 0),1,
|
(LEX_STRING*) 0),
|
||||||
|
TL_OPTION_UPDATING,
|
||||||
((using_update_log)?
|
((using_update_log)?
|
||||||
TL_READ_NO_INSERT:
|
TL_READ_NO_INSERT:
|
||||||
TL_READ)))
|
TL_READ)))
|
||||||
@ -844,7 +846,8 @@ create:
|
|||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
LEX *lex=Lex;
|
||||||
lex->sql_command= SQLCOM_CREATE_INDEX;
|
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;
|
YYABORT;
|
||||||
lex->create_list.empty();
|
lex->create_list.empty();
|
||||||
lex->key_list.empty();
|
lex->key_list.empty();
|
||||||
@ -1380,6 +1383,7 @@ opt_unique_or_fulltext:
|
|||||||
key_alg:
|
key_alg:
|
||||||
/* empty */ { $$= HA_KEY_ALG_UNDEF; }
|
/* empty */ { $$= HA_KEY_ALG_UNDEF; }
|
||||||
| USING opt_btree_or_rtree { $$= $2; };
|
| USING opt_btree_or_rtree { $$= $2; };
|
||||||
|
| TYPE_SYM opt_btree_or_rtree { $$= $2; };
|
||||||
|
|
||||||
opt_btree_or_rtree:
|
opt_btree_or_rtree:
|
||||||
BTREE_SYM { $$= HA_KEY_ALG_BTREE; }
|
BTREE_SYM { $$= HA_KEY_ALG_BTREE; }
|
||||||
@ -1413,7 +1417,8 @@ alter:
|
|||||||
LEX *lex=&thd->lex;
|
LEX *lex=&thd->lex;
|
||||||
lex->sql_command = SQLCOM_ALTER_TABLE;
|
lex->sql_command = SQLCOM_ALTER_TABLE;
|
||||||
lex->name=0;
|
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;
|
YYABORT;
|
||||||
lex->drop_primary=0;
|
lex->drop_primary=0;
|
||||||
lex->create_list.empty();
|
lex->create_list.empty();
|
||||||
@ -1679,8 +1684,10 @@ table_to_table:
|
|||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
LEX *lex=Lex;
|
||||||
SELECT_LEX_NODE *sl= lex->current_select;
|
SELECT_LEX_NODE *sl= lex->current_select;
|
||||||
if (!sl->add_table_to_list(lex->thd, $1,NULL,1,TL_IGNORE) ||
|
if (!sl->add_table_to_list(lex->thd, $1,NULL,TL_OPTION_UPDATING,
|
||||||
!sl->add_table_to_list(lex->thd, $3,NULL,1,TL_IGNORE))
|
TL_IGNORE) ||
|
||||||
|
!sl->add_table_to_list(lex->thd, $3,NULL,TL_OPTION_UPDATING,
|
||||||
|
TL_IGNORE))
|
||||||
YYABORT;
|
YYABORT;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2532,12 +2539,14 @@ join_table:
|
|||||||
{
|
{
|
||||||
SELECT_LEX *sel= Select->select_lex();
|
SELECT_LEX *sel= Select->select_lex();
|
||||||
sel->use_index_ptr=sel->ignore_index_ptr=0;
|
sel->use_index_ptr=sel->ignore_index_ptr=0;
|
||||||
|
sel->table_join_options= 0;
|
||||||
}
|
}
|
||||||
table_ident opt_table_alias opt_key_definition
|
table_ident opt_table_alias opt_key_definition
|
||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
SELECT_LEX_NODE *sel= lex->current_select;
|
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,
|
lex->lock_option,
|
||||||
sel->get_use_index(),
|
sel->get_use_index(),
|
||||||
sel->get_ignore_index())))
|
sel->get_ignore_index())))
|
||||||
@ -2583,6 +2592,13 @@ opt_key_definition:
|
|||||||
sel->use_index= *$2;
|
sel->use_index= *$2;
|
||||||
sel->use_index_ptr= &sel->use_index;
|
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
|
| IGNORE_SYM key_usage_list
|
||||||
{
|
{
|
||||||
SELECT_LEX *sel= Select->select_lex();
|
SELECT_LEX *sel= Select->select_lex();
|
||||||
@ -2592,8 +2608,14 @@ opt_key_definition:
|
|||||||
|
|
||||||
key_usage_list:
|
key_usage_list:
|
||||||
key_or_index { Select->select_lex()->interval_list.empty(); }
|
key_or_index { Select->select_lex()->interval_list.empty(); }
|
||||||
'(' key_usage_list2 ')'
|
'(' key_list_or_empty ')'
|
||||||
{ $$= &Select->select_lex()->interval_list; };
|
{ $$= &Select->select_lex()->interval_list; }
|
||||||
|
;
|
||||||
|
|
||||||
|
key_list_or_empty:
|
||||||
|
/* empty */ {}
|
||||||
|
| key_usage_list2 {}
|
||||||
|
;
|
||||||
|
|
||||||
key_usage_list2:
|
key_usage_list2:
|
||||||
key_usage_list2 ',' ident
|
key_usage_list2 ',' ident
|
||||||
@ -2954,7 +2976,8 @@ drop:
|
|||||||
lex->drop_list.empty();
|
lex->drop_list.empty();
|
||||||
lex->drop_list.push_back(new Alter_drop(Alter_drop::KEY,
|
lex->drop_list.push_back(new Alter_drop(Alter_drop::KEY,
|
||||||
$3.str));
|
$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;
|
YYABORT;
|
||||||
}
|
}
|
||||||
| DROP DATABASE if_exists ident
|
| DROP DATABASE if_exists ident
|
||||||
@ -2978,7 +3001,11 @@ table_list:
|
|||||||
|
|
||||||
table_name:
|
table_name:
|
||||||
table_ident
|
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:
|
if_exists:
|
||||||
/* empty */ { $$= 0; }
|
/* empty */ { $$= 0; }
|
||||||
@ -3213,7 +3240,8 @@ delete:
|
|||||||
single_multi:
|
single_multi:
|
||||||
FROM table_ident
|
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;
|
YYABORT;
|
||||||
}
|
}
|
||||||
where_clause opt_order_clause
|
where_clause opt_order_clause
|
||||||
@ -3234,14 +3262,15 @@ table_wild_list:
|
|||||||
table_wild_one:
|
table_wild_one:
|
||||||
ident opt_wild opt_table_alias
|
ident opt_wild opt_table_alias
|
||||||
{
|
{
|
||||||
if (!Select->add_table_to_list(YYTHD, new Table_ident($1), $3, 1,
|
if (!Select->add_table_to_list(YYTHD, new Table_ident($1), $3,
|
||||||
Lex->lock_option))
|
TL_OPTION_UPDATING, Lex->lock_option))
|
||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
| ident '.' ident opt_wild opt_table_alias
|
| ident '.' ident opt_wild opt_table_alias
|
||||||
{
|
{
|
||||||
if (!Select->add_table_to_list(YYTHD, new Table_ident($1, $3, 0),
|
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;
|
YYABORT;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
@ -3405,7 +3434,7 @@ show_param:
|
|||||||
| CREATE TABLE_SYM table_ident
|
| CREATE TABLE_SYM table_ident
|
||||||
{
|
{
|
||||||
Lex->sql_command = SQLCOM_SHOW_CREATE;
|
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;
|
YYABORT;
|
||||||
}
|
}
|
||||||
| MASTER_SYM STATUS_SYM
|
| 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_duplicate INTO TABLE_SYM table_ident opt_field_term opt_line_term
|
||||||
opt_ignore_lines opt_field_spec
|
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;
|
YYABORT;
|
||||||
}
|
}
|
||||||
|
|
|
|
||||||
LOAD TABLE_SYM table_ident FROM MASTER_SYM
|
LOAD TABLE_SYM table_ident FROM MASTER_SYM
|
||||||
{
|
{
|
||||||
Lex->sql_command = SQLCOM_LOAD_MASTER_TABLE;
|
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;
|
YYABORT;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -91,6 +91,7 @@ struct st_table {
|
|||||||
my_bool copy_blobs; /* copy_blobs when storing */
|
my_bool copy_blobs; /* copy_blobs when storing */
|
||||||
my_bool null_row; /* All columns are null */
|
my_bool null_row; /* All columns are null */
|
||||||
my_bool maybe_null,outer_join; /* Used with OUTER JOIN */
|
my_bool maybe_null,outer_join; /* Used with OUTER JOIN */
|
||||||
|
my_bool force_index;
|
||||||
my_bool distinct,const_table,no_rows;
|
my_bool distinct,const_table,no_rows;
|
||||||
my_bool key_read, bulk_insert;
|
my_bool key_read, bulk_insert;
|
||||||
my_bool crypted;
|
my_bool crypted;
|
||||||
@ -168,6 +169,7 @@ typedef struct st_table_list
|
|||||||
bool straight; /* optimize with prev table */
|
bool straight; /* optimize with prev table */
|
||||||
bool updating; /* for replicate-do/ignore table */
|
bool updating; /* for replicate-do/ignore table */
|
||||||
bool do_redirect; /* To get the struct in UNION's */
|
bool do_redirect; /* To get the struct in UNION's */
|
||||||
|
bool force_index; /* Prefer index over table scan */
|
||||||
} TABLE_LIST;
|
} TABLE_LIST;
|
||||||
|
|
||||||
typedef struct st_changed_table_list
|
typedef struct st_changed_table_list
|
||||||
|
Loading…
x
Reference in New Issue
Block a user