summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <monty@mashka.mysql.fi>2003-01-09 03:55:26 +0200
committerunknown <monty@mashka.mysql.fi>2003-01-09 03:55:26 +0200
commit0396f97e6e009c76f646ca55586eb4abb002cbbe (patch)
treeaf09adc5a3ec6814545553d72fda1d33e443d162
parent997418c5e3e72f818d66b453bbd3f5a6699639b8 (diff)
parentf5310091748db98072769e7f36ced7fafcc35a11 (diff)
downloadmariadb-git-0396f97e6e009c76f646ca55586eb4abb002cbbe.tar.gz
merge with 4.0.9
To get bug fixes for TCP/IP connections, FORCE INDEX and OPTIMIZE TABLE with NULL keys client/mysqladmin.c: Auto merged client/mysqltest.c: Auto merged extra/Makefile.am: Auto merged include/my_base.h: Auto merged innobase/log/log0log.c: Auto merged myisam/ft_nlq_search.c: Auto merged myisam/mi_open.c: Auto merged myisam/myisamdef.h: Auto merged mysql-test/mysql-test-run.sh: Auto merged mysql-test/r/myisam.result: Auto merged sql/lex.h: Auto merged sql/log_event.h: Auto merged sql/mysqld.cc: Auto merged sql/opt_range.cc: Auto merged sql/protocol.cc: Auto merged sql/slave.cc: Auto merged sql/sql_base.cc: Auto merged sql/sql_select.cc: Auto merged sql-bench/crash-me.sh: Auto merged sql-bench/test-insert.sh: Auto merged sql/sql_show.cc: Auto merged sql/table.h: Auto merged configure.in: merge with 4.0.9 innobase/btr/btr0pcur.c: merge with 4.0.9 myisam/mi_check.c: merge with 4.0.9 myisam/mi_search.c: merge with 4.0.9 mysql-test/t/myisam.test: merge with 4.0.9 sql/log_event.cc: merge with 4.0.9 sql/mysql_priv.h: merge with 4.0.9 sql/sql_lex.h: merge with 4.0.9 sql/sql_parse.cc: merge with 4.0.9 sql/sql_yacc.yy: merge with 4.0.9
-rwxr-xr-xBuild-tools/Do-compile27
-rw-r--r--Docs/internals.texi73
-rw-r--r--client/mysqladmin.c62
-rw-r--r--client/mysqltest.c8
-rw-r--r--extra/Makefile.am2
-rw-r--r--extra/mysql_waitpid.c86
-rw-r--r--include/my_base.h1
-rw-r--r--innobase/mem/mem0pool.c13
-rw-r--r--myisam/ft_nlq_search.c1
-rw-r--r--myisam/mi_check.c3
-rw-r--r--myisam/mi_extra.c5
-rw-r--r--myisam/mi_open.c14
-rw-r--r--myisam/mi_search.c8
-rw-r--r--myisam/myisamdef.h4
-rw-r--r--mysql-test/mysql-test-run.sh33
-rw-r--r--mysql-test/r/myisam.result44
-rw-r--r--mysql-test/t/myisam.test25
-rw-r--r--sql-bench/bench-init.pl.sh5
-rw-r--r--sql-bench/crash-me.sh126
-rw-r--r--sql-bench/test-alter-table.sh43
-rw-r--r--sql-bench/test-insert.sh7
-rw-r--r--sql/lex.h1
-rw-r--r--sql/log_event.cc65
-rw-r--r--sql/log_event.h5
-rw-r--r--sql/mysql_priv.h5
-rw-r--r--sql/mysqld.cc43
-rw-r--r--sql/opt_range.cc4
-rw-r--r--sql/protocol.cc5
-rw-r--r--sql/slave.cc8
-rw-r--r--sql/sql_base.cc6
-rw-r--r--sql/sql_lex.h7
-rw-r--r--sql/sql_parse.cc5
-rw-r--r--sql/sql_select.cc3
-rw-r--r--sql/sql_show.cc2
-rw-r--r--sql/sql_yacc.yy47
-rw-r--r--sql/table.h2
36 files changed, 601 insertions, 197 deletions
diff --git a/Build-tools/Do-compile b/Build-tools/Do-compile
index 4351a4f69f4..8695c72b913 100755
--- a/Build-tools/Do-compile
+++ b/Build-tools/Do-compile
@@ -135,6 +135,7 @@ $ENV{'MYSQL_UNIX_PORT'}=$mysql_unix_port="$opt_tmp/mysql$opt_suffix.build";
$ENV{"PERL5LIB"}="$pwd/$host/perl5:$pwd/$host/perl5/site_perl";
$slave_port=$mysql_tcp_port+16;
$manager_port=$mysql_tcp_port+1;
+$mysqladmin_args="--no-defaults -u root --connect_timeout=5 --shutdown_timeout=20";
if ($opt_stage == 0)
{
@@ -154,13 +155,18 @@ log_timestamp();
if (-x "$host/bin/mysqladmin")
{
- log_system("$host/bin/mysqladmin --no-defaults -u root -S $mysql_unix_port -s shutdown");
- log_system("$host/bin/mysqladmin --no-defaults -u root -P $mysql_tcp_port -h $host -s shutdown");
- log_system("$host/bin/mysqladmin --no-defaults -u root -P $slave_port -h $host -s shutdown");
- log_system("$host/bin/mysqladmin --no-defaults -u root -P 9306 -h $host -s shutdown");
- log_system("$host/bin/mysqladmin --no-defaults -u root -P 9307 -h $host -s shutdown");
+ log_system("$host/bin/mysqladmin $mysqladmin_args -S $mysql_unix_port -s shutdown");
+ log_system("$host/bin/mysqladmin $mysqladmin_args -P $mysql_tcp_port -h $host -s shutdown");
+ log_system("$host/bin/mysqladmin $mysqladmin_args -P $slave_port -h $host -s shutdown");
+ log_system("$host/bin/mysqladmin $mysqladmin_args -P 9306 -h $host -s shutdown");
+ log_system("$host/bin/mysqladmin $mysqladmin_args -P 9307 -h $host -s shutdown");
}
kill_all("mysqlmanager");
+#
+# Kill all old processes that are in the build directories
+# This is to find any old mysqld servers left from previous builds
+kill_all("$pwd/host/mysql");
+kill_all("$pwd/host/test");
if ($opt_stage == 0)
{
@@ -308,8 +314,9 @@ if ($opt_stage <= 4 && !$opt_no_test)
$tar_file =~ /(mysql[^\/]*)\.tar/;
$ver=$1;
$test_dir="$pwd/$host/test/$ver";
-$ENV{"LD_LIBRARY_PATH"}= "$test_dir/lib:" . $ENV{"LD_LIBRARY_PATH"};
-
+$ENV{"LD_LIBRARY_PATH"}= ("$test_dir/lib" .
+ (defined($ENV{"LD_LIBRARY_PATH"}) ?
+ ":" . $ENV{"LD_LIBRARY_PATH"} : ""));
#
# Run the test suite
#
@@ -328,7 +335,7 @@ if (!$opt_no_test && !$opt_no_benchmark)
{
my $extra;
safe_cd($test_dir);
- log_system("./bin/mysqladmin --no-defaults -u root -S $mysql_unix_port -s shutdown") || info("There was no mysqld running\n");
+ log_system("./bin/mysqladmin $mysqladmin_args -S $mysql_unix_port -s shutdown") || info("There was no mysqld running\n");
sleep(2);
log_system("rm -f ./data/mysql/*");
check_system("scripts/mysql_install_db --no-defaults --skip-locking","https://order");
@@ -418,7 +425,7 @@ if ($opt_stage <= 9 && !$opt_no_test && !$opt_no_benchmark)
rm_all($bench_tmpdir);
rm_all("$opt_tmp") if ($new_opt_tmp);
-log_system("$pwd/$host/bin/mysqladmin --no-defaults -S $mysql_unix_port -u root shutdown");
+log_system("$pwd/$host/bin/mysqladmin $mysqladmin_args -S $mysql_unix_port -u root shutdown");
print LOG "ok\n";
close LOG;
print "$host: ok\n";
@@ -429,7 +436,7 @@ exit 0;
sub usage
{
print <<EOF;
-$0 version 1.4
+$0 version 1.5
$0 takes the following options:
diff --git a/Docs/internals.texi b/Docs/internals.texi
index 6719bd4a6fa..a94158f84f8 100644
--- a/Docs/internals.texi
+++ b/Docs/internals.texi
@@ -96,13 +96,84 @@ cached for each user/database combination.
Many use of @code{GROUP BY} or @code{DISTINCT} caches all found rows in
a @code{HEAP} table. (This is a very quick in-memory table with hash index.)
-@item Join Row Cache
+@item Join buffer Cache
For every full join in a @code{SELECT} statement (a full join here means
there were no keys that one could use to find the next table in a list),
the found rows are cached in a join cache. One @code{SELECT} query can
use many join caches in the worst case.
@end table
+@node join_buffer_size, flush tables, caching, Top
+@subchapter How MySQL uses the join_buffer cache
+
+Basic information about @code{join_buffer_size}:
+
+@itemize @bullet
+@item
+It's only used in the case when join type is of type @code{ALL} or
+@code{index}; In other words: no possible keys can be used.
+@item
+A join buffer is never allocated for the first not-const table,
+even it it would be of type @code{ALL}/@code{index}.
+@item
+The buffer is allocated when we need to do a each full join between two
+tables and freed after the query is done.
+@item
+Accepted row combinations of tables before the @code{ALL}/@code{index}
+able is stored in the cache and is used to compare against each read
+row in the @code{ALL} table.
+@item
+We only store the used fields in the join_buffer cache, not the
+whole rows.
+@end itemize
+
+Assume you have the following join:
+
+@example
+Table name Type
+t1 range
+t2 ref
+t3 @code{ALL}
+@end example
+
+The join is then done as follows:
+
+@example
+- While rows in t1 matching range
+ - Read through all rows in t2 according to reference key
+ - Store used fields form t1,t2 in cache
+ - If cache is full
+ - Read through all rows in t3
+ - Compare t3 row against all t1,t2 combination in cache
+ - If rows satisfying join condition, send it to client
+ - Empty cache
+
+- Read through all rows in t3
+ - Compare t3 row against all stored t1,t2 combinations in cache
+ - If rows satisfying join condition, send it to client
+@end example
+
+The above means that table t3 is scanned
+
+@example
+(size-of-stored-row(t1,t2) * accepted-row-cominations(t1,t2))/
+join_buffer_size+1
+@end example
+times.
+
+Some conclusions:
+
+@itemize @bullet
+@item
+The larger the join_buff_size, the fewer scans of t3.
+If @code{join_buff_size} is already large enough to hold all previous row
+combinations then there is no speed to gain by making it bigger.
+@item
+If there is several tables of @code{ALL}/@code{index} then the we
+allocate one @code{join_buffer_size buffer} for each of them and use the
+same algorithm described above to handle it. (In other words, we store
+the same row combination several times into different buffers)
+@end itemize
@node flush tables, filesort, caching, Top
@chapter How MySQL Handles @code{FLUSH TABLES}
diff --git a/client/mysqladmin.c b/client/mysqladmin.c
index 2c8314d83ca..2fc77552d5f 100644
--- a/client/mysqladmin.c
+++ b/client/mysqladmin.c
@@ -25,7 +25,7 @@
#include <sys/stat.h>
#include <mysql.h>
-#define ADMIN_VERSION "8.38"
+#define ADMIN_VERSION "8.39"
#define MAX_MYSQL_VAR 128
#define SHUTDOWN_DEF_TIMEOUT 3600 /* Wait for shutdown */
#define MAX_TRUNC_LENGTH 3
@@ -76,8 +76,8 @@ static void print_relative_header();
static void print_relative_line();
static void truncate_names();
static my_bool get_pidfile(MYSQL *mysql, char *pidfile);
-static void wait_pidfile(char *pidfile, time_t last_modified,
- struct stat *pidfile_status);
+static my_bool wait_pidfile(char *pidfile, time_t last_modified,
+ struct stat *pidfile_status);
static void store_values(MYSQL_RES *result);
/*
@@ -513,7 +513,8 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
printf("Shutdown signal sent to server; Waiting for pid file to disappear\n");
/* Wait until pid file is gone */
- wait_pidfile(pidfile, last_modified, &pidfile_status);
+ if (wait_pidfile(pidfile, last_modified, &pidfile_status))
+ return -1;
}
break;
}
@@ -1150,34 +1151,51 @@ static my_bool get_pidfile(MYSQL *mysql, char *pidfile)
return 1; /* Error */
}
+/*
+ Return 1 if pid file didn't disappear or change
+*/
-static void wait_pidfile(char *pidfile, time_t last_modified,
- struct stat *pidfile_status)
+static my_bool wait_pidfile(char *pidfile, time_t last_modified,
+ struct stat *pidfile_status)
{
char buff[FN_REFLEN];
- int fd = -1;
- uint count=0;
+ int error= 1;
+ uint count= 0;
+ DBUG_ENTER("wait_pidfile");
system_filename(buff, pidfile);
- while (count++ <= opt_shutdown_timeout && !interrupted &&
- (!last_modified || (last_modified == pidfile_status->st_mtime)) &&
- (fd= my_open(buff, O_RDONLY, MYF(0))) >= 0)
+ do
{
- if (!my_close(fd,MYF(0)))
- fd= -1;
+ int fd;
+ if ((fd= my_open(buff, O_RDONLY, MYF(0))) < 0)
+ {
+ error= 0;
+ break;
+ }
+ (void) my_close(fd,MYF(0));
+ if (last_modified && !stat(pidfile, pidfile_status))
+ {
+ if (last_modified != pidfile_status->st_mtime)
+ {
+ /* File changed; Let's assume that mysqld did restart */
+ if (opt_verbose)
+ printf("pid file '%s' changed while waiting for it to disappear!\nmysqld did probably restart\n",
+ buff);
+ error= 0;
+ break;
+ }
+ }
+ if (count++ == opt_shutdown_timeout)
+ break;
sleep(1);
- if (last_modified && stat(pidfile, pidfile_status))
- last_modified= 0;
- }
- if (opt_verbose && last_modified &&
- last_modified != pidfile_status->st_mtime)
- printf("Warning; pid file '%s' changed while waiting for it to disappear!\n",
- buff);
- if (fd >= 0)
+ } while (!interrupted);
+
+ if (error)
{
- my_close(fd,MYF(0));
+ DBUG_PRINT("warning",("Pid file didn't disappear"));
fprintf(stderr,
"Warning; Aborted waiting on pid file: '%s' after %d seconds\n",
buff, count-1);
}
+ DBUG_RETURN(error);
}
diff --git a/client/mysqltest.c b/client/mysqltest.c
index ed95efc282e..f3037fcc173 100644
--- a/client/mysqltest.c
+++ b/client/mysqltest.c
@@ -42,7 +42,7 @@
**********************************************************************/
-#define MTEST_VERSION "1.25"
+#define MTEST_VERSION "1.26"
#include <my_global.h>
#include <mysql_embed.h>
@@ -1809,10 +1809,8 @@ int read_query(struct st_query** q_ptr)
static struct my_option my_long_options[] =
{
-#ifndef DBUG_OFF
{"debug", '#', "Output debug log. Often this is 'd:t:o,filename'",
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
-#endif
{"database", 'D', "Database to use.", (gptr*) &db, (gptr*) &db, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"basedir", 'b', "Basedir for tests", (gptr*) &opt_basedir,
@@ -1905,7 +1903,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
{
switch(optid) {
case '#':
+#ifndef DBUG_OFF
DBUG_PUSH(argument ? argument : "d:t:S:i:O,/tmp/mysqltest.trace");
+#endif
break;
case 'r':
record = 1;
@@ -1983,7 +1983,7 @@ int parse_args(int argc, char **argv)
default_argv= argv;
if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
- exit(ho_error);
+ exit(1);
if (argc > 1)
{
diff --git a/extra/Makefile.am b/extra/Makefile.am
index 6895d7a09f8..8107beb2657 100644
--- a/extra/Makefile.am
+++ b/extra/Makefile.am
@@ -18,7 +18,7 @@ INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include
LDADD = @CLIENT_EXTRA_LDFLAGS@ ../mysys/libmysys.a \
../dbug/libdbug.a ../strings/libmystrings.a
bin_PROGRAMS = replace comp_err perror resolveip my_print_defaults \
- resolve_stack_dump mysql_install
+ resolve_stack_dump mysql_install mysql_waitpid
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/extra/mysql_waitpid.c b/extra/mysql_waitpid.c
new file mode 100644
index 00000000000..14d3f893c60
--- /dev/null
+++ b/extra/mysql_waitpid.c
@@ -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);
+}
diff --git a/include/my_base.h b/include/my_base.h
index 6efac979a4e..b16a545b937 100644
--- a/include/my_base.h
+++ b/include/my_base.h
@@ -264,6 +264,7 @@ enum ha_base_keytype {
#define MBR_EQUAL 8192
#define MBR_DATA 16384
#define SEARCH_NULL_ARE_EQUAL 32768 /* NULL in keys are equal */
+#define SEARCH_NULL_ARE_NOT_EQUAL 65536 /* NULL in keys are not equal */
/* bits in opt_flag */
#define QUICK_USED 1
diff --git a/innobase/mem/mem0pool.c b/innobase/mem/mem0pool.c
index 1c32a4d02a6..382e505b63f 100644
--- a/innobase/mem/mem0pool.c
+++ b/innobase/mem/mem0pool.c
@@ -259,19 +259,6 @@ mem_pool_fill_free_list(
/* We come here when we have run out of space in the
memory pool: */
- if (mem_out_of_mem_err_msg_count % 1000000000 == 0) {
- /* We do not print the message every time: */
-
- ut_print_timestamp(stderr);
-
- fprintf(stderr,
- " InnoDB: Out of memory in additional memory pool.\n"
- "InnoDB: InnoDB will start allocating memory from the OS.\n"
- "InnoDB: You may get better performance if you configure a bigger\n"
- "InnoDB: value in the MySQL my.cnf file for\n"
- "InnoDB: innodb_additional_mem_pool_size.\n");
- }
-
mem_out_of_mem_err_msg_count++;
return(FALSE);
diff --git a/myisam/ft_nlq_search.c b/myisam/ft_nlq_search.c
index f9c276de32f..858a8dcbe06 100644
--- a/myisam/ft_nlq_search.c
+++ b/myisam/ft_nlq_search.c
@@ -97,6 +97,7 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio)
r=_mi_search(aio->info, aio->keyinfo, aio->keybuff, keylen,
SEARCH_FIND | SEARCH_PREFIX, aio->key_root);
+ aio->info->update|= HA_STATE_AKTIV; /* for _mi_test_if_changed() */
while (!r)
{
diff --git a/myisam/mi_check.c b/myisam/mi_check.c
index 1ca342f3998..28c28e628ea 100644
--- a/myisam/mi_check.c
+++ b/myisam/mi_check.c
@@ -601,7 +601,8 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
if (*keys != 1L) /* not first_key */
{
uint diff;
- ha_key_cmp(keyinfo->seg,info->lastkey,key,USE_WHOLE_KEY,SEARCH_FIND,
+ ha_key_cmp(keyinfo->seg,info->lastkey,key,USE_WHOLE_KEY,
+ SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL,
&diff);
param->unique_count[diff-1]++;
}
diff --git a/myisam/mi_extra.c b/myisam/mi_extra.c
index 8429b22dad4..75057dd4e6a 100644
--- a/myisam/mi_extra.c
+++ b/myisam/mi_extra.c
@@ -55,12 +55,17 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
/*
Free buffers and reset the following flags:
EXTRA_CACHE, EXTRA_WRITE_CACHE, EXTRA_KEYREAD, EXTRA_QUICK
+
+ If the row buffer cache is large (for dynamic tables), reduce it
+ to save memory.
*/
if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
{
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
error=end_io_cache(&info->rec_cache);
}
+ if (share->base.blobs)
+ mi_alloc_rec_buff(info, -1, &info->rec_buff);
#if defined(HAVE_MMAP) && defined(HAVE_MADVICE)
if (info->opt_flag & MEMMAP_USED)
madvise(share->file_map,share->state.state.data_file_length,MADV_RANDOM);
diff --git a/myisam/mi_open.c b/myisam/mi_open.c
index 8f0da612c3a..ef1906e0c00 100644
--- a/myisam/mi_open.c
+++ b/myisam/mi_open.c
@@ -573,28 +573,36 @@ err:
DBUG_RETURN (NULL);
} /* mi_open */
+
byte *mi_alloc_rec_buff(MI_INFO *info, ulong length, byte **buf)
{
uint extra;
+ uint32 old_length;
+ LINT_INIT(old_length);
- if (! *buf || length > mi_get_rec_buff_len(info, *buf))
+ if (! *buf || length > (old_length=mi_get_rec_buff_len(info, *buf)))
{
byte *newptr = *buf;
/* to simplify initial init of info->rec_buf in mi_open and mi_extra */
if (length == (ulong) -1)
+ {
length= max(info->s->base.pack_reclength+info->s->base.pack_bits,
info->s->base.max_key_length);
+ /* Avoid unnecessary realloc */
+ if (newptr && length == old_length)
+ return newptr;
+ }
extra= ((info->s->options & HA_OPTION_PACK_RECORD) ?
ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER)+MI_SPLIT_LENGTH+
MI_REC_BUFF_OFFSET : 0);
if (extra && newptr)
- newptr-=MI_REC_BUFF_OFFSET;
+ newptr-= MI_REC_BUFF_OFFSET;
if (!(newptr=(byte*) my_realloc((gptr)newptr, length+extra+8,
MYF(MY_ALLOW_ZERO_PTR))))
return newptr;
- *((uint *)newptr)=length;
+ *((uint32 *) newptr)= (uint32) length;
*buf= newptr+(extra ? MI_REC_BUFF_OFFSET : 0);
}
return *buf;
diff --git a/myisam/mi_search.c b/myisam/mi_search.c
index 8aeccbbf559..04803d7a901 100644
--- a/myisam/mi_search.c
+++ b/myisam/mi_search.c
@@ -260,9 +260,11 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
uchar *key, uint key_len, uint nextflag, uchar **ret_pos,
uchar *buff, my_bool *last_key)
{
- /* my_flag is raw comparison result to be changed according to
- SEARCH_NO_FIND,SEARCH_LAST and HA_REVERSE_SORT flags.
- flag is the value returned by ha_key_cmp and as treated as final */
+ /*
+ my_flag is raw comparison result to be changed according to
+ SEARCH_NO_FIND,SEARCH_LAST and HA_REVERSE_SORT flags.
+ flag is the value returned by ha_key_cmp and as treated as final
+ */
int flag=0, my_flag=-1;
uint nod_flag, length, len, matched, cmplen, kseg_len;
uint prefix_len,suffix_len;
diff --git a/myisam/myisamdef.h b/myisam/myisamdef.h
index e5cac1f090e..005c36271bf 100644
--- a/myisam/myisamdef.h
+++ b/myisam/myisamdef.h
@@ -385,7 +385,7 @@ typedef struct st_mi_sort_param
#define MI_DYN_ALIGN_SIZE 4 /* Align blocks on this */
#define MI_MAX_DYN_HEADER_BYTE 13 /* max header byte for dynamic rows */
#define MI_MAX_BLOCK_LENGTH ((((ulong) 1 << 24)-1) & (~ (ulong) (MI_DYN_ALIGN_SIZE-1)))
-#define MI_REC_BUFF_OFFSET ALIGN_SIZE(MI_DYN_DELETE_BLOCK_HEADER+sizeof(uint))
+#define MI_REC_BUFF_OFFSET ALIGN_SIZE(MI_DYN_DELETE_BLOCK_HEADER+sizeof(uint32))
#define MEMMAP_EXTRA_MARGIN 7 /* Write this as a suffix for file */
@@ -554,7 +554,7 @@ extern byte *mi_alloc_rec_buff(MI_INFO *,ulong, byte**);
((((info)->s->options & HA_OPTION_PACK_RECORD) && (buf)) ? \
(buf) - MI_REC_BUFF_OFFSET : (buf))
#define mi_get_rec_buff_len(info,buf) \
- (*((uint *)(mi_get_rec_buff_ptr(info,buf))))
+ (*((uint32 *)(mi_get_rec_buff_ptr(info,buf))))
extern ulong _mi_rec_unpack(MI_INFO *info,byte *to,byte *from,
ulong reclength);
diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh
index 34f3d365d7d..edd573f50a3 100644
--- a/mysql-test/mysql-test-run.sh
+++ b/mysql-test/mysql-test-run.sh
@@ -88,6 +88,7 @@ sleep_until_file_created ()
wait_for_pid()
{
pid=$1
+ #$WAIT_PID pid $SLEEP_TIME_FOR_DELETE
}
# No paths below as we can't be sure where the program is!
@@ -347,9 +348,9 @@ while test $# -gt 0; do
;;
--debug)
EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT \
- --debug=d:t:i:O,$MYSQL_TEST_DIR/var/log/master.trace"
+ --debug=d:t:i:A,$MYSQL_TEST_DIR/var/log/master.trace"
EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT \
- --debug=d:t:i:O,$MYSQL_TEST_DIR/var/log/slave.trace"
+ --debug=d:t:i:A,$MYSQL_TEST_DIR/var/log/slave.trace"
EXTRA_MYSQL_TEST_OPT="$EXTRA_MYSQL_TEST_OPT --debug"
;;
--fast)
@@ -423,6 +424,7 @@ if [ x$SOURCE_DIST = x1 ] ; then
fi
MYSQLADMIN="$BASEDIR/client/mysqladmin"
+ WAIT_PID="$BASEDIR/extra/mysql_waitpid"
MYSQL_MANAGER_CLIENT="$BASEDIR/client/mysqlmanagerc"
MYSQL_MANAGER="$BASEDIR/tools/mysqlmanager"
MYSQL_MANAGER_PWGEN="$BASEDIR/client/mysqlmanager-pwgen"
@@ -439,6 +441,7 @@ else
fi
MYSQL_TEST="$BASEDIR/bin/mysqltest"
MYSQLADMIN="$BASEDIR/bin/mysqladmin"
+ WAIT_PID="$BASEDIR/bin/mysql_waitpid"
MYSQL_MANAGER="$BASEDIR/bin/mysqlmanager"
MYSQL_MANAGER_CLIENT="$BASEDIR/bin/mysqlmanagerc"
MYSQL_MANAGER_PWGEN="$BASEDIR/bin/mysqlmanager-pwgen"
@@ -753,9 +756,9 @@ manager_term()
{
pid=$1
ident=$2
- shift
if [ $USE_MANAGER = 0 ] ; then
- $MYSQLADMIN --no-defaults -uroot --socket=$MYSQL_TMP_DIR/$ident.sock --connect_timeout=5 --shutdown_timeout=20 shutdown >> $MYSQL_MANAGER_LOG 2>&1
+ # Shutdown time must be high as slave may be in reconnect
+ $MYSQLADMIN --no-defaults -uroot --socket=$MYSQL_TMP_DIR/$ident.sock --connect_timeout=5 --shutdown_timeout=70 shutdown >> $MYSQL_MANAGER_LOG 2>&1
res=$?
# Some systems require an extra connect
$MYSQLADMIN --no-defaults -uroot --socket=$MYSQL_TMP_DIR/$ident.sock --connect_timeout=1 ping >> $MYSQL_MANAGER_LOG 2>&1
@@ -875,8 +878,8 @@ start_slave()
[ x$SKIP_SLAVE = x1 ] && return
eval "this_slave_running=\$SLAVE$1_RUNNING"
[ x$this_slave_running = 1 ] && return
- #when testing fail-safe replication, we will have more than one slave
- #in this case, we start secondary slaves with an argument
+ # When testing fail-safe replication, we will have more than one slave
+ # in this case, we start secondary slaves with an argument
slave_ident="slave$1"
if [ -n "$1" ] ;
then
@@ -984,9 +987,12 @@ EOF
mysql_start ()
{
- $ECHO "Starting MySQL daemon"
- start_master
- start_slave
+# We should not start the deamon here as we don't know the argumens
+# for the test. Better to let the test start the deamon
+
+# $ECHO "Starting MySQL daemon"
+# start_master
+# start_slave
cd $MYSQL_TEST_DIR
return 1
}
@@ -1087,8 +1093,6 @@ run_testcase ()
slave_init_script=$TESTDIR/$tname-slave.sh
slave_master_info_file=$TESTDIR/$tname-slave-master-info.opt
echo $tname > $CURRENT_TEST
- echo "CURRENT_TEST: $tname" >> $SLAVE_MYERR
- echo "CURRENT_TEST: $tname" >> $MASTER_MYERR
SKIP_SLAVE=`$EXPR \( $tname : rpl \) = 0`
if [ $USE_MANAGER = 1 ] ; then
many_slaves=`$EXPR \( $tname : rpl_failsafe \) != 0`
@@ -1125,13 +1129,17 @@ run_testcase ()
then
EXTRA_MASTER_OPT=`$CAT $master_opt_file | $SED -e "s;\\$MYSQL_TEST_DIR;$MYSQL_TEST_DIR;"`
stop_master
+ echo "CURRENT_TEST: $tname" >> $MASTER_MYERR
start_master
else
if [ ! -z "$EXTRA_MASTER_OPT" ] || [ x$MASTER_RUNNING != x1 ] ;
then
EXTRA_MASTER_OPT=""
stop_master
+ echo "CURRENT_TEST: $tname" >> $MASTER_MYERR
start_master
+ else
+ echo "CURRENT_TEST: $tname" >> $MASTER_MYERR
fi
fi
@@ -1161,7 +1169,10 @@ run_testcase ()
if [ x$do_slave_restart = x1 ] ; then
stop_slave
+ echo "CURRENT_TEST: $tname" >> $SLAVE_MYERR
start_slave
+ else
+ echo "CURRENT_TEST: $tname" >> $SLAVE_MYERR
fi
if [ x$many_slaves = x1 ]; then
start_slave 1
diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result
index f06194bb412..3d4b1dbd46d 100644
--- a/mysql-test/r/myisam.result
+++ b/mysql-test/r/myisam.result
@@ -1,4 +1,4 @@
-drop table if exists t1;
+drop table if exists t1,t2;
CREATE TABLE t1 (
STRING_DATA char(255) default NULL,
KEY string_data (STRING_DATA)
@@ -316,3 +316,45 @@ CREATE TABLE t1 (a varchar(255), b varchar(255), c varchar(255));
ALTER TABLE t1 ADD INDEX t1 (a, b, c);
Specified key was too long. Max key length is 500
DROP TABLE t1;
+CREATE TABLE t1 (a int not null, b int, c int, key(b), key(c), key(a,b), key(c,a));
+INSERT into t1 values (0, null, 0), (0, null, 1), (0, null, 2), (0, null,3), (1,1,4);
+create table t2 (a int not null, b int, c int, key(b), key(c), key(a));
+INSERT into t2 values (1,1,1), (2,2,2);
+optimize table t1;
+Table Op Msg_type Msg_text
+test.t1 optimize status OK
+show index from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t1 1 b 1 b A 5 NULL NULL YES BTREE
+t1 1 c 1 c A 5 NULL NULL YES BTREE
+t1 1 a 1 a A 1 NULL NULL BTREE
+t1 1 a 2 b A 5 NULL NULL YES BTREE
+t1 1 c_2 1 c A 5 NULL NULL YES BTREE
+t1 1 c_2 2 a A 5 NULL NULL BTREE
+explain select * from t1,t2 where t1.a=t2.a;
+table type possible_keys key key_len ref rows Extra
+t1 ALL a NULL NULL NULL 5
+t2 ALL a NULL NULL NULL 2 Using where
+explain select * from t1,t2 force index(a) where t1.a=t2.a;
+table type possible_keys key key_len ref rows Extra
+t2 ALL a NULL NULL NULL 2
+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;
+table type possible_keys key key_len ref rows Extra
+t2 ALL a NULL NULL NULL 2
+t1 ref a a 4 t2.a 3
+explain select * from t1,t2 where t1.b=t2.b;
+table type possible_keys key key_len ref rows Extra
+t2 ALL b NULL NULL NULL 2
+t1 ref b b 5 t2.b 1 Using where
+explain select * from t1,t2 force index(c) where t1.a=t2.a;
+table type possible_keys key key_len ref rows Extra
+t1 ALL a NULL NULL NULL 5
+t2 ALL NULL NULL NULL NULL 2 Using where
+explain select * from t1 where a=0 or a=2;
+table type possible_keys key key_len ref rows Extra
+t1 ALL a NULL NULL NULL 5 Using where
+explain select * from t1 force index (a) where a=0 or a=2;
+table type possible_keys key key_len ref rows Extra
+t1 range a a 4 NULL 4 Using where
+drop table t1,t2;
diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test
index 780a060e204..7b541d98cef 100644
--- a/mysql-test/t/myisam.test
+++ b/mysql-test/t/myisam.test
@@ -2,10 +2,15 @@
# Test bugs in the MyISAM code
#
+# Initialise
--disable_warnings
-drop table if exists t1;
+drop table if exists t1,t2;
--enable_warnings
+#
+# Test problem with CHECK TABLE;
+#
+
CREATE TABLE t1 (
STRING_DATA char(255) default NULL,
KEY string_data (STRING_DATA)
@@ -327,3 +332,21 @@ CREATE TABLE t1 (a varchar(255), b varchar(255), c varchar(255));
ALTER TABLE t1 ADD INDEX t1 (a, b, c);
DROP TABLE t1;
+#
+# Test of cardinality of keys with NULL
+#
+
+CREATE TABLE t1 (a int not null, b int, c int, key(b), key(c), key(a,b), key(c,a));
+INSERT into t1 values (0, null, 0), (0, null, 1), (0, null, 2), (0, null,3), (1,1,4);
+create table t2 (a int not null, b int, c int, key(b), key(c), key(a));
+INSERT into t2 values (1,1,1), (2,2,2);
+optimize table t1;
+show index from t1;
+explain select * from t1,t2 where t1.a=t2.a;
+explain select * from t1,t2 force index(a) where t1.a=t2.a;
+explain select * from t1 force index(a),t2 force index(a) where t1.a=t2.a;
+explain select * from t1,t2 where t1.b=t2.b;
+explain select * from t1,t2 force index(c) where t1.a=t2.a;
+explain select * from t1 where a=0 or a=2;
+explain select * from t1 force index (a) where a=0 or a=2;
+drop table t1,t2;
diff --git a/sql-bench/bench-init.pl.sh b/sql-bench/bench-init.pl.sh
index 9b999ee7f95..b7d2b962e13 100644
--- a/sql-bench/bench-init.pl.sh
+++ b/sql-bench/bench-init.pl.sh
@@ -48,7 +48,10 @@ $opt_optimization="None";
$opt_hw="";
$opt_threads=5;
-$opt_time_limit=10*60; # Don't wait more than 10 min for some tests
+if (!defined($opt_time_limit))
+{
+ $opt_time_limit=10*60; # Don't wait more than 10 min for some tests
+}
$log_prog_args=join(" ", skip_arguments(\@ARGV,"comments","cmp","server",
"user", "host", "database", "password",
diff --git a/sql-bench/crash-me.sh b/sql-bench/crash-me.sh
index ea18431f8da..130816de0be 100644
--- a/sql-bench/crash-me.sh
+++ b/sql-bench/crash-me.sh
@@ -39,7 +39,7 @@
# as such, and clarify ones such as "mediumint" with comments such as
# "3-byte int" or "same as xxx".
-$version="1.59";
+$version="1.60";
use DBI;
use Getopt::Long;
@@ -50,7 +50,7 @@ $opt_server="mysql"; $opt_host="localhost"; $opt_database="test";
$opt_dir="limits";
$opt_user=$opt_password="";$opt_verbose="";
$opt_debug=$opt_help=$opt_Information=$opt_restart=$opt_force=$opt_quick=0;
-$opt_log_all_queries=$opt_fix_limit_file=$opt_batch_mode=0;
+$opt_log_all_queries=$opt_fix_limit_file=$opt_batch_mode=$opt_version=0;
$opt_db_start_cmd=""; # the db server start command
$opt_check_server=0; # Check if server is alive before each query
$opt_sleep=10; # time to sleep while starting the db server
@@ -68,8 +68,10 @@ GetOptions("Information","help","server=s","debug","user=s","password=s",
"database=s","restart","force","quick","log-all-queries","comment=s",
"host=s","fix-limit-file","dir=s","db-start-cmd=s","sleep=s","suffix=s",
"batch-mode","config-file=s","log-queries-to-file=s","check-server",
+"version",
"verbose!" => \$opt_verbose) || usage();
usage() if ($opt_help || $opt_Information);
+version() && exit(0) if ($opt_version);
$opt_suffix = '-'.$opt_suffix if (length($opt_suffix) != 0);
$opt_config_file = "$pwd/$opt_dir/$opt_server$opt_suffix.cfg"
@@ -1190,7 +1192,7 @@ else
# Test: NOROUND
{
- my $resultat = 'undefined';
+ my $result = 'undefined';
my $error;
print "NOROUND: ";
save_incomplete('func_extra_noround','Function NOROUND');
@@ -1199,21 +1201,25 @@ else
$error = safe_query_l('func_extra_noround',"select noround(22.6) $end_query");
if ($error ne 1) # syntax error -- noround is not supported
{
- $resultat = 'no'
- } else # Ok, now check if it really works
- {
+ $result = 'no'
+ }
+ else # Ok, now check if it really works
+ {
$error=safe_query_l('func_extra_noround',
["create table crash_me_nr (a int)",
"insert into crash_me_nr values(noround(10.2))",
"drop table crash_me_nr $drop_attr"]);
- if ($error eq 1) {
- $resultat = "syntax only";
- } else {
- $resultat = 'yes';
- }
- }
- print "$resultat\n";
- save_config_data('func_extra_noround',$resultat,"Function NOROUND");
+ if ($error == 1)
+ {
+ $result= "syntax only";
+ }
+ else
+ {
+ $result= 'yes';
+ }
+ }
+ print "$result\n";
+ save_config_data('func_extra_noround',$result,"Function NOROUND");
}
check_parenthesis("func_sql_","CURRENT_USER");
@@ -1377,7 +1383,7 @@ if ($limits{'type_sql_date'} eq 'yes')
# Test: WEEK()
{
- my $resultat="no";
+ my $result="no";
my $error;
print "WEEK:";
save_incomplete('func_odbc_week','WEEK');
@@ -1388,17 +1394,17 @@ if ($limits{'type_sql_date'} eq 'yes')
# and 0 - EURO weeks
if ($error == -1) {
if ($last_result == 4) {
- $resultat = 'USA';
+ $result = 'USA';
} else {
- $resultat='error';
+ $result='error';
add_log('func_odbc_week',
" must return 4 or 5, but $last_result");
}
} elsif ($error == 0) {
- $resultat = 'EURO';
+ $result = 'EURO';
}
- print " $resultat\n";
- save_config_data('func_odbc_week',$resultat,"WEEK");
+ print " $result\n";
+ save_config_data('func_odbc_week',$result,"WEEK");
}
my $insert_query ='insert into crash_me_d values('.
@@ -1498,7 +1504,7 @@ if ($limits{'type_sql_date'} eq 'yes')
# NOT id BETWEEN a and b
if ($limits{'func_where_not_between'} eq 'yes')
{
- my $resultat = 'error';
+ my $result = 'error';
my $err;
my $key='not_id_between';
my $prompt='NOT ID BETWEEN interprets as ID NOT BETWEEN';
@@ -1512,15 +1518,15 @@ if ($limits{'func_where_not_between'} eq 'yes')
5,0);
if ($err eq 1) {
if (not defined($last_result)) {
- $resultat='no';
+ $result='no';
};
};
if ( $err eq 0) {
- $resultat = 'yes';
+ $result = 'yes';
};
safe_query_l($key,["drop table crash_me_b"]);
- save_config_data($key,$resultat,$prompt);
- print "$resultat\n";
+ save_config_data($key,$result,$prompt);
+ print "$result\n";
};
@@ -2018,37 +2024,44 @@ report("views","views",
# Test: foreign key
{
- my $resultat = 'undefined';
+ my $result = 'undefined';
my $error;
print "foreign keys: ";
save_incomplete('foreign_key','foreign keys');
# 1) check if foreign keys are supported
- safe_query_l('foreign_key',create_table("crash_me_qf",["a integer not null"],
- ["primary key (a)"]));
- $error = safe_query_l('foreign_key',
- create_table("crash_me_qf2",["a integer not null",
- "foreign key (a) references crash_me_qf (a)"], []));
-
- if ($error eq 1) # OK -- syntax is supported
+ safe_query_l('foreign_key',
+ create_table("crash_me_qf",
+ ["a integer not null"],
+ ["primary key (a)"]));
+ $error= safe_query_l('foreign_key',
+ create_table("crash_me_qf2",
+ ["a integer not null",
+ "foreign key (a) references crash_me_qf (a)"],
+ []));
+
+ if ($error == 1) # OK -- syntax is supported
{
- $resultat = 'error';
+ $result = 'error';
# now check if foreign key really works
safe_query_l('foreign_key', "insert into crash_me_qf values (1)");
- if (safe_query_l('foreign_key', "insert into crash_me_qf2 values (2)") eq 1)
+ if (safe_query_l('foreign_key', "insert into crash_me_qf2 values (2)") eq 1)
{
- $resultat = 'syntax only';
- } else {
- $resultat = 'yes';
- }
-
- } else {
- $resultat = "no";
- }
- safe_query_l('foreign_key',
- "drop table crash_me_qf2 $drop_attr","drop table crash_me_qf $drop_attr");
- print "$resultat\n";
- save_config_data('foreign_key',$resultat,"foreign keys");
+ $result = 'syntax only';
+ }
+ else
+ {
+ $result = 'yes';
+ }
+ }
+ else
+ {
+ $result = "no";
+ }
+ safe_query_l('foreign_key', "drop table crash_me_qf2 $drop_attr");
+ safe_query_l('foreign_key', "drop table crash_me_qf $drop_attr");
+ print "$result\n";
+ save_config_data('foreign_key',$result,"foreign keys");
}
report("Create SCHEMA","create_schema",
@@ -2607,7 +2620,7 @@ sub detect_null_position
sub check_parenthesis {
my $prefix=shift;
my $fn=shift;
- my $resultat='no';
+ my $result='no';
my $param_name=$prefix.lc($fn);
my $r;
@@ -2616,18 +2629,18 @@ sub check_parenthesis {
add_log($param_name,$safe_query_log);
if ($r == 1)
{
- $resultat="yes";
+ $result="yes";
}
else{
$r = safe_query("select $fn() $end_query");
add_log($param_name,$safe_query_log);
if ( $r == 1)
{
- $resultat="with_parenthesis";
+ $result="with_parenthesis";
}
}
- save_config_data($param_name,$resultat,$fn);
+ save_config_data($param_name,$result,$fn);
}
sub check_constraint {
@@ -2699,10 +2712,16 @@ sub make_date {
}
+sub version
+{
+ print "$0 Ver $version\n";
+}
+
+
sub usage
{
+ version();
print <<EOF;
-$0 Ver $version
This program tries to find all limits and capabilities for a SQL
server. As it will use the server in some 'unexpected' ways, one
@@ -3048,7 +3067,7 @@ sub safe_query_l {
my $r = safe_query($q);
add_log($key,$safe_query_log);
return $r;
-}
+}
sub safe_query
{
@@ -3110,7 +3129,6 @@ sub safe_query
$retry = $retry_limit;
$retry_ok = 1;
$safe_query_log .= "> OK\n";
-
}
$sth->finish;
}
diff --git a/sql-bench/test-alter-table.sh b/sql-bench/test-alter-table.sh
index cc6453188de..f338792e9ef 100644
--- a/sql-bench/test-alter-table.sh
+++ b/sql-bench/test-alter-table.sh
@@ -27,6 +27,7 @@ $opt_start_field_count=8; # start with this many fields
$opt_loop_count=20; # How many tests to do
$opt_row_count=1000; # Rows in the table
$opt_field_count=1000; # Add until this many fields.
+$opt_time_limit=10*60; # Don't wait more than 10 min for some tests
chomp($pwd = `pwd`); $pwd = "." if ($pwd eq '');
require "$pwd/bench-init.pl" || die "Can't read Configuration file: $!\n";
@@ -113,10 +114,9 @@ if ($opt_fast)
}
else
{
- $add=1 if (!$limits{'alter_add_multi_col'});
+ $add=1 if (!$limits->{'alter_add_multi_col'});
}
-
$count=0;
while ($field_count < $opt_field_count)
{
@@ -131,19 +131,43 @@ while ($field_count < $opt_field_count)
$tmp="" if (!$multi_add); # Adabas
}
do_query($dbh,"ALTER TABLE bench " . substr($fields,1));
+ $end_time=new Benchmark;
+ last if ($estimated=predict_query_time($loop_time,$end_time,\$count,$count,
+ $opt_field_count/$add+1));
}
$end_time=new Benchmark;
-print "Time for alter_table_add ($count): " .
+if ($estimated)
+{ print "Estimated time"; }
+else
+{ print "Time"; }
+print " for alter_table_add ($count): " .
timestr(timediff($end_time, $loop_time),"all") . "\n\n";
+#
+# If estimated, fix table to have known number of fields
+#
+if ($estimated && $field_count < $opt_field_count)
+{
+ $fields="";
+ $tmp="ADD ";
+ while ($field_count < $opt_field_count)
+ {
+ $field_count++;
+ $fields.=",$tmp i${field_count} integer";
+ $tmp="" if (!$multi_add); # Adabas
+ }
+ do_query($dbh,"ALTER TABLE bench " . substr($fields,1));
+}
+
####
#### Test adding and deleting index on the first $opt_start_fields
####
$loop_time=new Benchmark;
-for ($i=1; $i < $opt_start_field_count ; $i++)
+$count= 0;
+for ($i=1; $i <= $opt_start_field_count ; $i++)
{
$dbh->do("CREATE INDEX bench_ind$i ON bench (i${i})") || die $DBI::errstr;
}
@@ -153,7 +177,7 @@ print "Time for create_index ($opt_start_field_count): " .
timestr(timediff($end_time, $loop_time),"all") . "\n\n";
$loop_time=new Benchmark;
-for ($i=1; $i < $opt_start_field_count ; $i++)
+for ($i=1; $i <= $opt_start_field_count ; $i++)
{
$dbh->do($server->drop_index("bench","bench_ind$i")) || die $DBI::errstr;
}
@@ -182,10 +206,17 @@ while ($field_count > $opt_start_field_count)
}
$dbh->do("ALTER TABLE bench " . substr($fields,1) . $server->{'drop_attr'})
|| die $DBI::errstr;
+ $end_time=new Benchmark;
+ last if ($estimated=predict_query_time($loop_time,$end_time,\$count,$count,
+ $opt_field_count/$add+1));
}
$end_time=new Benchmark;
-print "Time for alter_table_drop ($count): " .
+if ($estimated)
+{ print "Estimated time"; }
+else
+{ print "Time"; }
+print " for alter_table_drop ($count): " .
timestr(timediff($end_time, $loop_time),"all") . "\n\n";
skip_dropcol:
diff --git a/sql-bench/test-insert.sh b/sql-bench/test-insert.sh
index 93bc2840b3b..c26ed42f7ed 100644
--- a/sql-bench/test-insert.sh
+++ b/sql-bench/test-insert.sh
@@ -21,10 +21,11 @@
# $opt_loop_count rows in random order
#
# changes made for Oracle compatibility
-# - $limits{'func_odbc_mod'} is OK from crash-me, but it fails here so set we
+# - $limits->{'func_odbc_mod'} is OK from crash-me, but it fails here so set we
# set it to 0 in server-cfg
-# - the default server config runs out of rollback segments, so I added a couple
-# of disconnect/connects to reset
+# - the default server config runs out of rollback segments, so we added a
+# couple of disconnect/connects to reset
+#
##################### Standard benchmark inits ##############################
use DBI;
diff --git a/sql/lex.h b/sql/lex.h
index 2ddc540991b..a505911ccf6 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -161,6 +161,7 @@ static SYMBOL symbols[] = {
{ "FLUSH", SYM(FLUSH_SYM),0,0},
{ "FALSE", SYM(FALSE_SYM),0,0},
{ "FOREIGN", SYM(FOREIGN),0,0},
+ { "FORCE", SYM(FORCE_SYM),0,0},
{ "RAID_TYPE", SYM(RAID_TYPE),0,0},
{ "RAID_CHUNKS", SYM(RAID_CHUNKS),0,0},
{ "RAID_CHUNKSIZE", SYM(RAID_CHUNKSIZE),0,0},
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 8f98fa511a0..d025f8a57a7 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -294,7 +294,19 @@ Log_event::Log_event(const char* buf, bool old_format)
****************************************************************************/
int Log_event::exec_event(struct st_relay_log_info* rli)
{
- if (rli) // QQ When is this not true ?
+ /*
+ rli is null when (as far as I (Guilhem) know)
+ the caller is
+ Load_log_event::exec_event *and* that one is called from
+ Execute_load_log_event::exec_event.
+ In this case, we don't do anything here ;
+ Execute_load_log_event::exec_event will call Log_event::exec_event
+ again later with the proper rli.
+ Strictly speaking, if we were sure that rli is null
+ only in the case discussed above, 'if (rli)' is useless here.
+ But as we are not 100% sure, keep it for now.
+ */
+ if (rli)
{
if (rli->inside_transaction)
rli->inc_pending(get_event_len());
@@ -1435,13 +1447,36 @@ void Load_log_event::set_fields(List<Item> &field_list)
}
#endif // !MYSQL_CLIENT
-/*****************************************************************************
-
- Load_log_event::exec_event()
-
- ****************************************************************************/
#ifndef MYSQL_CLIENT
-int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli)
+
+/*
+ Does the data loading job when executing a LOAD DATA on the slave
+
+ SYNOPSIS
+ Load_log_event::exec_event
+ net
+ rli
+ use_rli_only_for_errors - if set to 1, rli is provided to
+ Load_log_event::exec_event only for this
+ function to have RPL_LOG_NAME and
+ rli->last_slave_error, both being used by
+ error reports. rli's position advancing
+ is skipped (done by the caller which is
+ Execute_load_log_event::exec_event).
+ - if set to 0, rli is provided for full use,
+ i.e. for error reports and position
+ advancing.
+
+ DESCRIPTION
+ Does the data loading job when executing a LOAD DATA on the slave
+
+ RETURN VALUE
+ 0 Success
+ 1 Failure
+*/
+
+int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
+ bool use_rli_only_for_errors)
{
init_sql_alloc(&thd->mem_root, 8192,0);
thd->db = rewrite_db((char*)db);
@@ -1503,9 +1538,15 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli)
TL_WRITE))
thd->query_error = 1;
if (thd->cuted_fields)
+ {
+ /*
+ log_pos is the position of the LOAD
+ event in the master log
+ */
sql_print_error("Slave: load data infile at position %s in log \
-'%s' produced %d warning(s)", llstr(rli->master_log_pos,llbuff), RPL_LOG_NAME,
+'%s' produced %d warning(s)", llstr(log_pos,llbuff), RPL_LOG_NAME,
thd->cuted_fields );
+ }
if (net)
net->pkt_nr= thd->net.pkt_nr;
}
@@ -1544,7 +1585,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli)
return 1;
}
- return Log_event::exec_event(rli);
+ return ( use_rli_only_for_errors ? 0 : Log_event::exec_event(rli) );
}
#endif // !MYSQL_CLIENT
@@ -2680,7 +2721,11 @@ int Execute_load_log_event::exec_event(struct st_relay_log_info* rli)
save_options = thd->options;
thd->options &= ~ (ulong) (OPTION_BIN_LOG);
lev->thd = thd;
- if (lev->exec_event(0,0))
+ /*
+ lev->exec_event should use rli only for errors
+ i.e. should not advance rli's position
+ */
+ if (lev->exec_event(0,rli,1))
{
slave_print_error(rli,my_errno, "Failed executing load from '%s'", fname);
thd->options = save_options;
diff --git a/sql/log_event.h b/sql/log_event.h
index ec3b4819e74..80c448e1550 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -460,9 +460,10 @@ public:
const char* get_db() { return db; }
int exec_event(struct st_relay_log_info* rli)
{
- return exec_event(thd->slave_net,rli);
+ return exec_event(thd->slave_net,rli,0);
}
- int exec_event(NET* net, struct st_relay_log_info* rli);
+ int exec_event(NET* net, struct st_relay_log_info* rli,
+ bool use_rli_only_for_errors);
#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 655e4d7b972..cdc668d9b28 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -235,6 +235,10 @@ void debug_sync_point(const char* lock_name, uint lock_timeout);
#define SHOW_LOG_STATUS_FREE "FREE"
#define SHOW_LOG_STATUS_INUSE "IN USE"
+/* Options to add_table_to_list() */
+#define TL_OPTION_UPDATING 1
+#define TL_OPTION_FORCE_INDEX 2
+
/* Some portable defines */
#define portable_sizeof_char_ptr 8
@@ -820,7 +824,6 @@ uint calc_week(TIME *ltime, bool with_year, bool sunday_first_day_of_week,
void find_date(char *pos,uint *vek,uint flag);
TYPELIB *convert_strings_to_array_type(my_string *typelibs, my_string *end);
TYPELIB *typelib(List<String> &strings);
-void clean_up(bool print_message=1);
ulong get_form_pos(File file, uchar *head, TYPELIB *save_names);
ulong make_new_entry(File file,uchar *fileinfo,TYPELIB *formnames,
const char *newname);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index d6a5c0b8412..f66122e72a6 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -491,6 +491,7 @@ extern "C" pthread_handler_decl(handle_slave,arg);
static uint set_maximum_open_files(uint max_file_limit);
#endif
static ulong find_bit_type(const char *x, TYPELIB *bit_lib);
+static void clean_up(bool print_message);
/****************************************************************************
** Code to end mysqld
@@ -763,13 +764,13 @@ void kill_mysql(void)
#if defined(OS2)
extern "C" void kill_server(int sig_ptr)
-#define RETURN_FROM_KILL_SERVER return
+#define RETURN_FROM_KILL_SERVER DBUG_RETURN
#elif !defined(__WIN__)
static void *kill_server(void *sig_ptr)
-#define RETURN_FROM_KILL_SERVER return 0
+#define RETURN_FROM_KILL_SERVER DBUG_RETURN(0)
#else
static void __cdecl kill_server(int sig_ptr)
-#define RETURN_FROM_KILL_SERVER return
+#define RETURN_FROM_KILL_SERVER DBUG_RETURN
#endif
{
int sig=(int) (long) sig_ptr; // This is passed a int
@@ -848,7 +849,7 @@ extern "C" sig_handler print_signal_warning(int sig)
void unireg_end(void)
{
- clean_up();
+ clean_up(1);
my_thread_end();
#ifdef SIGNALS_DONT_BREAK_READ
exit(0);
@@ -863,7 +864,7 @@ extern "C" void unireg_abort(int exit_code)
DBUG_ENTER("unireg_abort");
if (exit_code)
sql_print_error("Aborting\n");
- clean_up(); /* purecov: inspected */
+ clean_up(1); /* purecov: inspected */
DBUG_PRINT("quit",("done with cleanup in unireg_abort"));
my_thread_end();
exit(exit_code); /* purecov: inspected */
@@ -908,12 +909,12 @@ void clean_up(bool print_message)
regex_end();
#endif
+ if (print_message && errmesg)
+ sql_print_error(ER(ER_SHUTDOWN_COMPLETE),my_progname);
#if !defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
if (!opt_bootstrap)
(void) my_delete(pidfile_name,MYF(0)); // This may not always exist
#endif
- if (print_message && errmesg)
- sql_print_error(ER(ER_SHUTDOWN_COMPLETE),my_progname);
x_free((gptr) my_errmsg[ERRMAPP]); /* Free messages */
DBUG_PRINT("quit", ("Error messages freed"));
/* Tell main we are ready */
@@ -923,6 +924,10 @@ void clean_up(bool print_message)
/* do the broadcast inside the lock to ensure that my_end() is not called */
(void) pthread_cond_broadcast(&COND_thread_count);
(void) pthread_mutex_unlock(&LOCK_thread_count);
+ /*
+ The following lines may never be executed as the main thread may have
+ killed us
+ */
DBUG_PRINT("quit", ("done with cleanup"));
} /* clean_up */
@@ -1502,7 +1507,7 @@ static void init_signals(void)
/* Change limits so that we will get a core file */
struct rlimit rl;
rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
- if (setrlimit(RLIMIT_CORE, &rl))
+ if (setrlimit(RLIMIT_CORE, &rl) && global_system_variables.log_warnings)
sql_print_error("Warning: setrlimit could not change the size of core files to 'infinity'; We may not be able to generate a core file on signals");
}
#endif
@@ -1571,8 +1576,11 @@ extern "C" void *signal_hand(void *arg __attribute__((unused)))
my_thread_init(); // Init new thread
DBUG_ENTER("signal_hand");
SIGNAL_THD;
- /* Setup alarm handler */
- init_thr_alarm(max_connections+max_insert_delayed_threads);
+ /*
+ Setup alarm handler
+ The two extra handlers are for slave threads
+ */
+ init_thr_alarm(max_connections+max_insert_delayed_threads+2);
#if SIGINT != THR_KILL_SIGNAL
(void) sigemptyset(&set); // Setup up SIGINT for debug
(void) sigaddset(&set,SIGINT); // For debugging
@@ -1660,12 +1668,15 @@ extern "C" void *signal_hand(void *arg __attribute__((unused)))
}
break;
case SIGHUP:
- reload_acl_and_cache((THD*) 0,
- (REFRESH_LOG | REFRESH_TABLES | REFRESH_FAST |
- REFRESH_STATUS | REFRESH_GRANT | REFRESH_THREADS |
- REFRESH_HOSTS),
- (TABLE_LIST*) 0); // Flush logs
- mysql_print_status((THD*) 0); // Send debug some info
+ if (!abort_loop)
+ {
+ reload_acl_and_cache((THD*) 0,
+ (REFRESH_LOG | REFRESH_TABLES | REFRESH_FAST |
+ REFRESH_STATUS | REFRESH_GRANT |
+ REFRESH_THREADS | REFRESH_HOSTS),
+ (TABLE_LIST*) 0); // Flush logs
+ mysql_print_status((THD*) 0); // Send debug some info
+ }
break;
#ifdef USE_ONE_SIGNAL_HAND
case THR_SERVER_ALARM:
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 887ce6c561a..0adde4d39e0 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -603,12 +603,14 @@ int SQL_SELECT::test_quick_select(key_map keys_to_use, table_map prev_tables,
records++; /* purecov: inspected */
scan_time=(double) records / TIME_FOR_COMPARE+1;
read_time=(double) head->file->scan_time()+ scan_time + 1.0;
+ if (head->force_index)
+ scan_time= read_time= DBL_MAX;
if (limit < records)
read_time=(double) records+scan_time+1; // Force to use index
else if (read_time <= 2.0 && !force_quick_range)
DBUG_RETURN(0); /* No need for quick select */
- DBUG_PRINT("info",("Time to scan table: %ld",(long) read_time));
+ DBUG_PRINT("info",("Time to scan table: %g", read_time));
keys_to_use&=head->keys_in_use_for_query;
if (keys_to_use)
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 15f4ca9ad94..48ef9ecb71e 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -171,7 +171,10 @@ net_printf(THD *thd, uint errcode, ...)
{
if (thd->bootstrap)
{
- /* In bootstrap it's ok to print on stderr */
+ /*
+ In bootstrap it's ok to print on stderr
+ This may also happen when we get an error from a slave thread
+ */
fprintf(stderr,"ERROR: %d %s\n",errcode,text_pos);
thd->fatal_error=1;
}
diff --git a/sql/slave.cc b/sql/slave.cc
index 342a35b8821..271fe8bc2d6 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -413,6 +413,7 @@ int terminate_slave_threads(MASTER_INFO* mi,int thread_mask,bool skip_lock)
}
if ((thread_mask & (SLAVE_IO|SLAVE_FORCE_ALL)) && mi->slave_running)
{
+ DBUG_PRINT("info",("Terminating IO thread"));
mi->abort_slave=1;
if ((error=terminate_slave_thread(mi->io_thd,io_lock,
io_cond_lock,
@@ -423,6 +424,7 @@ int terminate_slave_threads(MASTER_INFO* mi,int thread_mask,bool skip_lock)
}
if ((thread_mask & (SLAVE_SQL|SLAVE_FORCE_ALL)) && mi->rli.slave_running)
{
+ DBUG_PRINT("info",("Terminating SQL thread"));
DBUG_ASSERT(mi->rli.sql_thd != 0) ;
mi->rli.abort_slave=1;
if ((error=terminate_slave_thread(mi->rli.sql_thd,sql_lock,
@@ -2572,12 +2574,6 @@ static int process_io_rotate(MASTER_INFO *mi, Rotate_log_event *rev)
memcpy(mi->master_log_name, rev->new_log_ident, rev->ident_len+1);
mi->master_log_pos= rev->pos;
-
- pthread_mutex_lock(&mi->rli.data_lock);
- memcpy(mi->rli.master_log_name, rev->new_log_ident, rev->ident_len+1);
- mi->rli.master_log_pos= rev->pos;
- pthread_mutex_unlock(&mi->rli.data_lock);
-
DBUG_PRINT("info", ("master_log_pos: '%s' %d",
mi->master_log_name, (ulong) mi->master_log_pos));
#ifndef DBUG_OFF
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index b5178076258..a384e723e32 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -747,7 +747,7 @@ TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list)
table->tablenr=thd->current_tablenr++;
table->used_fields=0;
table->const_table=0;
- table->outer_join=table->null_row=table->maybe_null=0;
+ table->outer_join= table->null_row= table->maybe_null= table->force_index= 0;
table->status=STATUS_NO_RECORD;
table->keys_in_use_for_query= table->keys_in_use;
table->used_keys= table->keys_for_keyread;
@@ -906,7 +906,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
table->tablenr=thd->current_tablenr++;
table->used_fields=0;
table->const_table=0;
- table->outer_join=table->null_row=table->maybe_null=0;
+ table->outer_join= table->null_row= table->maybe_null= table->force_index= 0;
table->status=STATUS_NO_RECORD;
table->keys_in_use_for_query= table->keys_in_use;
table->used_keys= table->keys_for_keyread;
@@ -977,6 +977,7 @@ bool reopen_table(TABLE *table,bool locked)
tmp.status= table->status;
tmp.keys_in_use_for_query= tmp.keys_in_use;
tmp.used_keys= tmp.keys_for_keyread;
+ tmp.force_index= tmp.force_index;
/* Get state */
tmp.key_length= table->key_length;
@@ -1969,6 +1970,7 @@ bool setup_tables(TABLE_LIST *tables)
table->maybe_null=test(table->outer_join=table_list->outer_join);
table->tablenr=tablenr;
table->map= (table_map) 1 << tablenr;
+ table->force_index= table_list->force_index;
if (table_list->use_index)
{
key_map map= get_key_map_from_key_list(table,
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 9b8f4a47515..b32e4489b01 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -243,9 +243,10 @@ public:
virtual List<Item>* get_item_list();
virtual List<String>* get_use_index();
virtual List<String>* get_ignore_index();
+ virtual ulong table_join_options();
virtual TABLE_LIST *add_table_to_list(THD *thd, Table_ident *table,
LEX_STRING *alias,
- bool updating,
+ ulong table_options,
thr_lock_type flags= TL_UNLOCK,
List<String> *use_index= 0,
List<String> *ignore_index= 0);
@@ -336,6 +337,7 @@ public:
List<Item_func_match> ftfunc_list_alloc;
JOIN *join; /* after JOIN::prepare it is pointer to corresponding JOIN */
const char *type; /* type of select for EXPLAIN */
+ ulong table_join_options;
uint in_sum_expr;
uint select_number; /* number of select (used for EXPLAIN) */
bool braces; /* SELECT ... UNION (SELECT ... ) <- this braces */
@@ -373,9 +375,10 @@ public:
List<Item>* get_item_list();
List<String>* get_use_index();
List<String>* get_ignore_index();
+ ulong table_join_options();
TABLE_LIST* add_table_to_list(THD *thd, Table_ident *table,
LEX_STRING *alias,
- bool updating,
+ ulong table_options,
thr_lock_type flags= TL_UNLOCK,
List<String> *use_index= 0,
List<String> *ignore_index= 0);
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index f6e21e421d9..ce8bd41d3a6 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -518,7 +518,8 @@ check_connections(THD *thd)
vio_in_addr(net->vio,&thd->remote.sin_addr);
thd->host=ip_to_hostname(&thd->remote.sin_addr,&connect_errors);
/* Cut very long hostnames to avoid possible overflows */
- thd->host[min(strlen(thd->host), HOSTNAME_LENGTH)]= 0;
+ if (thd->host)
+ thd->host[min(strlen(thd->host), HOSTNAME_LENGTH)]= 0;
if (connect_errors > max_connect_errors)
return(ER_HOST_IS_BLOCKED);
}
@@ -3669,7 +3670,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
sizeof(*ignore_index));
/* check that used name is unique */
- if (flags != TL_IGNORE)
+ if (lock_type != TL_IGNORE)
{
for (TABLE_LIST *tables=(TABLE_LIST*) table_list.first ;
tables ;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index c5a4362c71e..8b1886fd438 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -2305,7 +2305,8 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
!(s->quick && best_key && s->quick->index == best_key->key &&
best_max_key_part >= s->table->quick_key_parts[best_key->key]) &&
!((s->table->file->table_flags() & HA_TABLE_SCAN_ON_INDEX) &&
- s->table->used_keys && best_key))
+ s->table->used_keys && best_key) &&
+ !(s->table->force_index && best_key))
{ // Check full join
if (s->on_expr)
{
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index c66764d673f..53e18f918f6 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1480,6 +1480,7 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
case SHOW_RPL_STATUS:
end= strmov(buff, rpl_status_type[(int)rpl_status]);
break;
+#ifndef EMBEDDED_LIBRARY
case SHOW_SLAVE_RUNNING:
{
LOCK_ACTIVE_MI;
@@ -1488,6 +1489,7 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
UNLOCK_ACTIVE_MI;
break;
}
+#endif
case SHOW_OPENTABLES:
end= int10_to_str((long) cached_tables(), buff, 10);
break;
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 77325bad3a0..106fa61e535 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2001 MySQL AB
+/* Copyright (C) 2000-2003 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -222,6 +222,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token FIRST_SYM
%token FIXED_SYM
%token FLOAT_NUM
+%token FORCE_SYM
%token FOREIGN
%token FROM
%token FULL
@@ -822,7 +823,8 @@ create:
($2 &
HA_LEX_CREATE_TMP_TABLE ?
&tmp_table_alias :
- (LEX_STRING*) 0),1,
+ (LEX_STRING*) 0),
+ TL_OPTION_UPDATING,
((using_update_log)?
TL_READ_NO_INSERT:
TL_READ)))
@@ -843,7 +845,8 @@ create:
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_CREATE_INDEX;
- if (!lex->current_select->add_table_to_list(lex->thd, $7,NULL,1))
+ if (!lex->current_select->add_table_to_list(lex->thd, $7, NULL,
+ TL_OPTION_UPDATING))
YYABORT;
lex->create_list.empty();
lex->key_list.empty();
@@ -1390,7 +1393,8 @@ alter:
LEX *lex=&thd->lex;
lex->sql_command = SQLCOM_ALTER_TABLE;
lex->name=0;
- if (!lex->select_lex.add_table_to_list(thd, $4, NULL,1))
+ if (!lex->select_lex.add_table_to_list(thd, $4, NULL,
+ TL_OPTION_UPDATING))
YYABORT;
lex->drop_primary=0;
lex->create_list.empty();
@@ -1657,8 +1661,10 @@ table_to_table:
{
LEX *lex=Lex;
SELECT_LEX_NODE *sl= lex->current_select;
- if (!sl->add_table_to_list(lex->thd, $1,NULL,1,TL_IGNORE) ||
- !sl->add_table_to_list(lex->thd, $3,NULL,1,TL_IGNORE))
+ if (!sl->add_table_to_list(lex->thd, $1,NULL,TL_OPTION_UPDATING,
+ TL_IGNORE) ||
+ !sl->add_table_to_list(lex->thd, $3,NULL,TL_OPTION_UPDATING,
+ TL_IGNORE))
YYABORT;
};
@@ -2510,12 +2516,14 @@ join_table:
{
SELECT_LEX *sel= Select->select_lex();
sel->use_index_ptr=sel->ignore_index_ptr=0;
+ sel->table_join_ptions= 0;
}
table_ident opt_table_alias opt_key_definition
{
LEX *lex= Lex;
SELECT_LEX_NODE *sel= lex->current_select;
- if (!($$= sel->add_table_to_list(lex->thd, $2, $3, 0,
+ if (!($$= sel->add_table_to_list(lex->thd, $2, $3,
+ lex->table_join_options(),
lex->lock_option,
sel->get_use_index(),
sel->get_ignore_index())))
@@ -2932,7 +2940,8 @@ drop:
lex->drop_list.empty();
lex->drop_list.push_back(new Alter_drop(Alter_drop::KEY,
$3.str));
- if (!lex->current_select->add_table_to_list(lex->thd, $5,NULL, 1))
+ if (!lex->current_select->add_table_to_list(lex->thd, $5, NULL,
+ TL_OPTION_UPDATING))
YYABORT;
}
| DROP DATABASE if_exists ident
@@ -2956,7 +2965,11 @@ table_list:
table_name:
table_ident
- { if (!Select->add_table_to_list(YYTHD, $1, NULL, 1)) YYABORT; };
+ {
+ if (!Select->add_table_to_list(YYTHD, $1, NULL, TL_OPTION_UPDATING))
+ YYABORT;
+ }
+ ;
if_exists:
/* empty */ { $$= 0; }
@@ -3191,7 +3204,8 @@ delete:
single_multi:
FROM table_ident
{
- if (!Select->add_table_to_list(YYTHD, $2, NULL, 1, Lex->lock_option))
+ if (!Select->add_table_to_list(YYTHD, $2, NULL, TL_OPTION_UPDATING,
+ Lex->lock_option))
YYABORT;
}
where_clause opt_order_clause
@@ -3212,14 +3226,15 @@ table_wild_list:
table_wild_one:
ident opt_wild opt_table_alias
{
- if (!Select->add_table_to_list(YYTHD, new Table_ident($1), $3, 1,
- Lex->lock_option))
+ if (!Select->add_table_to_list(YYTHD, new Table_ident($1), $3,
+ TL_OPTION_UPDATING, Lex->lock_option))
YYABORT;
}
| ident '.' ident opt_wild opt_table_alias
{
if (!Select->add_table_to_list(YYTHD, new Table_ident($1, $3, 0),
- $5, 1, Lex->lock_option))
+ $5, TL_OPTION_UPDATING,
+ Lex->lock_option))
YYABORT;
}
;
@@ -3383,7 +3398,7 @@ show_param:
| CREATE TABLE_SYM table_ident
{
Lex->sql_command = SQLCOM_SHOW_CREATE;
- if(!Select->add_table_to_list(YYTHD, $3, NULL,0))
+ if (!Select->add_table_to_list(YYTHD, $3, NULL,0))
YYABORT;
}
| MASTER_SYM STATUS_SYM
@@ -3552,14 +3567,14 @@ load: LOAD DATA_SYM load_data_lock opt_local INFILE TEXT_STRING
opt_duplicate INTO TABLE_SYM table_ident opt_field_term opt_line_term
opt_ignore_lines opt_field_spec
{
- if (!Select->add_table_to_list(YYTHD, $11, NULL, 1))
+ if (!Select->add_table_to_list(YYTHD, $11, NULL, TL_OPTION_UPDATING))
YYABORT;
}
|
LOAD TABLE_SYM table_ident FROM MASTER_SYM
{
Lex->sql_command = SQLCOM_LOAD_MASTER_TABLE;
- if (!Select->add_table_to_list(YYTHD, $3, NULL, 1))
+ if (!Select->add_table_to_list(YYTHD, $3, NULL, TL_OPTION_UPDATING))
YYABORT;
}
diff --git a/sql/table.h b/sql/table.h
index d24e4e1e422..6291b250787 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -91,6 +91,7 @@ struct st_table {
my_bool copy_blobs; /* copy_blobs when storing */
my_bool null_row; /* All columns are null */
my_bool maybe_null,outer_join; /* Used with OUTER JOIN */
+ my_bool force_index;
my_bool distinct,const_table,no_rows;
my_bool key_read, bulk_insert;
my_bool crypted;
@@ -168,6 +169,7 @@ typedef struct st_table_list
bool straight; /* optimize with prev table */
bool updating; /* for replicate-do/ignore table */
bool do_redirect; /* To get the struct in UNION's */
+ bool force_index; /* Prefer index over table scan */
} TABLE_LIST;
typedef struct st_changed_table_list