From 113ff6aa22c1afc47073d67e62be21e3f9560824 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 5 Jan 2003 21:58:06 +0200 Subject: btr0pcur.c: Fix bug: an index cursor can theoretically be restored in a wrong place log0log.c: Fix bug: if combined log file size is >= 2 GB in a 32-bit computer InnoDB can write log to a wrong position innobase/log/log0log.c: Fix bug: if combined log file size is >= 2 GB in a 32-bit computer InnoDB can write log to a wrong position innobase/btr/btr0pcur.c: Fix bug: an index cursor can theoretically be restored in a wrong place --- innobase/btr/btr0pcur.c | 5 +++++ innobase/log/log0log.c | 32 +++++++++++++++++++++----------- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/innobase/btr/btr0pcur.c b/innobase/btr/btr0pcur.c index b2115dfdd6c..7b817d8263d 100644 --- a/innobase/btr/btr0pcur.c +++ b/innobase/btr/btr0pcur.c @@ -292,6 +292,11 @@ btr_pcur_restore_position( mem_heap_free(heap); + /* We have to store position information, modify clock value, etc. + because the cursor may now be on a different page */ + + btr_pcur_store_position(cursor, mtr); + return(FALSE); } diff --git a/innobase/log/log0log.c b/innobase/log/log0log.c index f9b785ccbd5..539cde337bd 100644 --- a/innobase/log/log0log.c +++ b/innobase/log/log0log.c @@ -437,25 +437,29 @@ log_group_calc_lsn_offset( dulint lsn, /* in: lsn, must be within 4 GB of group->lsn */ log_group_t* group) /* in: log group */ { - dulint gr_lsn; - ulint gr_lsn_size_offset; - ulint difference; - ulint group_size; - ulint offset; + dulint gr_lsn; + ib_longlong gr_lsn_size_offset; + ib_longlong difference; + ib_longlong group_size; + ib_longlong offset; ut_ad(mutex_own(&(log_sys->mutex))); + /* If total log file size is > 2 GB we can easily get overflows + with 32-bit integers. Use 64-bit integers instead. */ + gr_lsn = group->lsn; - gr_lsn_size_offset = log_group_calc_size_offset(group->lsn_offset, - group); - group_size = log_group_get_capacity(group); + gr_lsn_size_offset = (ib_longlong) + log_group_calc_size_offset(group->lsn_offset, group); + + group_size = (ib_longlong) log_group_get_capacity(group); if (ut_dulint_cmp(lsn, gr_lsn) >= 0) { - difference = ut_dulint_minus(lsn, gr_lsn); + difference = (ib_longlong) ut_dulint_minus(lsn, gr_lsn); } else { - difference = ut_dulint_minus(gr_lsn, lsn); + difference = (ib_longlong) ut_dulint_minus(gr_lsn, lsn); difference = difference % group_size; @@ -464,7 +468,13 @@ log_group_calc_lsn_offset( offset = (gr_lsn_size_offset + difference) % group_size; - return(log_group_calc_real_offset(offset, group)); + ut_a(offset <= 0xFFFFFFFF); + + /* printf("Offset is %lu gr_lsn_offset is %lu difference is %lu\n", + (ulint)offset,(ulint)gr_lsn_size_offset, (ulint)difference); + */ + + return(log_group_calc_real_offset((ulint)offset, group)); } /*********************************************************************** -- cgit v1.2.1 From 2773f9e7fd228fecdd12b27fdef936b14a2db4d2 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 7 Jan 2003 16:53:10 +0200 Subject: Portability fixes Fixed test suite for HPUX 10.20 and MacOSX Build-tools/Do-compile: Added timeout to mysqladmin shutdown commands Kill old running mysqld started by earlier runs Removed run time warning from LD_LIBRARY_PATH client/mysqladmin.c: Return 1 if pid file isn't deleted on shutdown. Fix error message if pid file is not deleted client/mysqltest.c: Always allow --debug flag (Makes it easier to run mysql-test-run) mysql-test/mysql-test-run.sh: A lot of safety fixes. This fixes some problems with test suite for HPUX 10.20 and MacOSX sql-bench/bench-init.pl.sh: Allow tests to change time limit. sql-bench/crash-me.sh: Indentation cleanups Added DROP for a created table sql-bench/test-alter-table.sh: Added default time limit Changed test to be estimated to get down run time. Fixed that add_multi_col is detected sql-bench/test-insert.sh: Comment cleanup sql/mysql_priv.h: Removed not needed prototype. sql/mysqld.cc: Removed DBUG warnings Removed default argument for clean_up() and made it static. More comments. Ignore SIGHUP during shutdown sql/net_pkg.cc: More comments sql/slave.cc: Added DBUG_PRINT messages --- Build-tools/Do-compile | 27 +++++---- client/mysqladmin.c | 62 +++++++++++++-------- client/mysqltest.c | 8 +-- mysql-test/mysql-test-run.sh | 33 +++++++---- sql-bench/bench-init.pl.sh | 5 +- sql-bench/crash-me.sh | 126 ++++++++++++++++++++++++------------------ sql-bench/test-alter-table.sh | 43 ++++++++++++-- sql-bench/test-insert.sh | 7 ++- sql/mysql_priv.h | 1 - sql/mysqld.cc | 43 ++++++++------ sql/net_pkg.cc | 5 +- sql/slave.cc | 2 + 12 files changed, 233 insertions(+), 129 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 < -#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 @@ -70,8 +70,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); /* @@ -481,7 +481,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; } @@ -1110,34 +1111,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 20d277ca969..fe99dda1ac3 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -42,7 +42,7 @@ **********************************************************************/ -#define MTEST_VERSION "1.25" +#define MTEST_VERSION "1.26" #include #include @@ -1797,10 +1797,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, @@ -1893,7 +1891,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; @@ -1971,7 +1971,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/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index 5c80e7d538a..408c76d8602 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! @@ -343,9 +344,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) @@ -419,6 +420,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" @@ -435,6 +437,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" @@ -749,9 +752,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 @@ -873,8 +876,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 @@ -982,9 +985,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 } @@ -1085,8 +1091,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` @@ -1123,13 +1127,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 @@ -1159,7 +1167,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/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 <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 085d7cce7f3..38014f7cddf 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/mysql_priv.h b/sql/mysql_priv.h index 3cf6bb2c1a5..2a8b263bf28 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -772,7 +772,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 &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 61ae07c01e7..e7190f575db 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -470,6 +470,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 @@ -742,13 +743,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 @@ -827,7 +828,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); @@ -842,7 +843,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 */ @@ -887,12 +888,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 */ @@ -902,6 +903,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 */ @@ -1481,7 +1486,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 @@ -1550,8 +1555,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 @@ -1639,12 +1647,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/net_pkg.cc b/sql/net_pkg.cc index afedba6a259..30cad3a4177 100644 --- a/sql/net_pkg.cc +++ b/sql/net_pkg.cc @@ -134,7 +134,10 @@ net_printf(NET *net, uint errcode, ...) { if (thd && 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 d254221e726..455b574b355 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -376,6 +376,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, @@ -386,6 +387,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, -- cgit v1.2.1 From 45de45538e4cdd4fb366491870ec92c12833377d Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 7 Jan 2003 19:04:41 +0200 Subject: Added new program, mysql_waitpid. --- extra/Makefile.am | 2 +- extra/mysql_waitpid.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 extra/mysql_waitpid.c diff --git a/extra/Makefile.am b/extra/Makefile.am index 2d7dc95f616..8e4491969b5 100644 --- a/extra/Makefile.am +++ b/extra/Makefile.am @@ -18,7 +18,7 @@ INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include -I../include -I.. 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..6e307209fda --- /dev/null +++ b/extra/mysql_waitpid.c @@ -0,0 +1,86 @@ +#include +#include +#include +#include +#include +#include + +static const char *VER= "1.0"; +static char *progname; +static int verbose= 0; + +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.", 0, 0, 0, + GET_NO_ARG, 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); +} -- cgit v1.2.1 From 0758ca000b8ef440c6ccdc97515f30d21078e7fb Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 7 Jan 2003 21:20:43 +0200 Subject: mem0pool.c: Remove the warning message that mem allocation spills from the additional mem pool to the OS; this does not hit performance with modern malloc libraries innobase/mem/mem0pool.c: Remove the warning message that mem allocation spills from the additional mem pool to the OS; this does not hit performance with modern malloc libraries --- innobase/mem/mem0pool.c | 13 ------------- 1 file changed, 13 deletions(-) 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); -- cgit v1.2.1 From e97c800acb9ddfeaa002f9fbf4df050cf5b4d608 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 7 Jan 2003 23:46:30 -0200 Subject: Fix embedded server crash sql/sql_show.cc: fix embedded server crash --- sql/sql_show.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index a11abf75506..50ee78c1ebc 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1217,6 +1217,7 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables, case SHOW_RPL_STATUS: net_store_data(&packet2, rpl_status_type[(int)rpl_status]); break; +#ifndef EMBEDDED_LIBRARY case SHOW_SLAVE_RUNNING: { LOCK_ACTIVE_MI; @@ -1226,6 +1227,7 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables, UNLOCK_ACTIVE_MI; break; } +#endif case SHOW_OPENTABLES: net_store_data(&packet2,(uint32) cached_tables()); break; -- cgit v1.2.1 From 3b6529bf802cc20c09ec4b53c710ca23a4533dad Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 8 Jan 2003 11:24:39 +0200 Subject: Fix for bug in LOAD DATA INFILE and replication Fix for SHOW VARIABLES in embedded server Docs/internals.texi: Added documentation for join_buffer_size configure.in: Changed version number sql/log_event.cc: Fix for bug in LOAD DATA INFILE sql/log_event.h: Fix for bug in LOAD DATA INFILE sql/slave.cc: Fix for bug in LOAD DATA INFILE sql/sql_show.cc: Fix for SHOW VARIABLES in embedded server --- Docs/internals.texi | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++- configure.in | 2 +- sql/log_event.cc | 56 ++++++++++++++++++++++++++++++++++++---- sql/log_event.h | 5 ++-- sql/slave.cc | 6 ----- sql/sql_show.cc | 2 ++ 6 files changed, 129 insertions(+), 15 deletions(-) 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/configure.in b/configure.in index 0375cc61235..06dc6e03fb6 100644 --- a/configure.in +++ b/configure.in @@ -4,7 +4,7 @@ dnl Process this file with autoconf to produce a configure script. AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! -AM_INIT_AUTOMAKE(mysql, 4.0.8-gamma) +AM_INIT_AUTOMAKE(mysql, 4.0.9-gamma) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 diff --git a/sql/log_event.cc b/sql/log_event.cc index d451a5bc46c..3c2c2fd27b1 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -206,7 +206,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()); @@ -1773,8 +1785,34 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli) return Log_event::exec_event(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) +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); @@ -1836,8 +1874,12 @@ 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; @@ -1877,7 +1919,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) ); } @@ -2132,7 +2174,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 69a70d535ec..5b9f30b3afd 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -417,9 +417,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/slave.cc b/sql/slave.cc index 455b574b355..b8689a28a54 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2343,12 +2343,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_show.cc b/sql/sql_show.cc index a11abf75506..04d3f13a8d0 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1217,6 +1217,7 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables, case SHOW_RPL_STATUS: net_store_data(&packet2, rpl_status_type[(int)rpl_status]); break; +#ifndef EMBEDDED_LIBRARY case SHOW_SLAVE_RUNNING: { LOCK_ACTIVE_MI; @@ -1226,6 +1227,7 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables, UNLOCK_ACTIVE_MI; break; } +#endif case SHOW_OPENTABLES: net_store_data(&packet2,(uint32) cached_tables()); break; -- cgit v1.2.1 From 75c851d3fa7fb9bcb8db727ad77487f16e94fb67 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 8 Jan 2003 15:43:56 +0200 Subject: Fixed a couple of bugs. --- extra/mysql_waitpid.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/extra/mysql_waitpid.c b/extra/mysql_waitpid.c index 6e307209fda..14d3f893c60 100644 --- a/extra/mysql_waitpid.c +++ b/extra/mysql_waitpid.c @@ -5,9 +5,9 @@ #include #include -static const char *VER= "1.0"; +static const char *VER= "1.1"; static char *progname; -static int verbose= 0; +static my_bool verbose; void usage(void); @@ -18,8 +18,8 @@ static struct my_option my_long_options[] = {"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.", 0, 0, 0, - GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, + "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} @@ -52,7 +52,7 @@ int main(int argc, char *argv[]) if (!argv[0] || !argv[1] || (pid= atoi(argv[0])) <= 0 || (t= atoi(argv[1])) <= 0) usage(); - for (; t >= 0; t--) + for (; t > 0; t--) { if (kill((pid_t) pid, sig)) { -- cgit v1.2.1 From f3c729b822ed4705675a03fdeb4ae81ce4f02c27 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 8 Jan 2003 19:40:35 +0100 Subject: ft_nlq_search.c: no _mi_search_next() bug fixed myisam/ft_nlq_search.c: no _mi_search_next() bug fixed --- myisam/ft_nlq_search.c | 1 + 1 file changed, 1 insertion(+) diff --git a/myisam/ft_nlq_search.c b/myisam/ft_nlq_search.c index 8c5d504b8d5..95ff700f815 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) { -- cgit v1.2.1 From 805016c5794752b7bfd2cc9a0c9d356883ac2621 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 9 Jan 2003 02:19:14 +0200 Subject: Don't count NULL values in cardinalty for MyISAM tables. Free row buffer cache after each query for MyISAM tables. Added table join option FORCE INDEX Fixed core dump bug when connecting with hostname that could not be resolved. include/my_base.h: Don't count NULL values in cardinalty myisam/mi_check.c: Don't count NULL values in cardinalty myisam/mi_extra.c: Free row buffer cache after each query myisam/mi_open.c: Avoid realloc if cache size doesn't change myisam/mi_search.c: Don't count NULL values in cardinalty myisam/myisamdef.h: Change buffer length from uint to uint32 to make it more portable/predictable mysql-test/r/myisam.result: Test case for cardinality with NULL keys and FORCE INDEX mysql-test/t/myisam.test: Test case for cardinality with NULL keys and FORCE INDEX sql/lex.h: Added table join option FORCE INDEX sql/mysql_priv.h: Added table join option FORCE INDEX sql/opt_range.cc: Added table join option FORCE INDEX sql/sql_base.cc: Added table join option FORCE INDEX sql/sql_lex.h: Added table join option FORCE INDEX sql/sql_parse.cc: Added table join option FORCE INDEX Don't use strlen() on hostname without first checking if it's not NULL sql/sql_select.cc: Added table join option FORCE INDEX sql/sql_yacc.yy: Added table join option FORCE INDEX sql/table.h: Added table join option FORCE INDEX --- include/my_base.h | 1 + myisam/mi_check.c | 3 ++- myisam/mi_extra.c | 5 +++++ myisam/mi_open.c | 14 +++++++++--- myisam/mi_search.c | 47 ++++++++++++++++++++++++++++++--------- myisam/myisamdef.h | 4 ++-- mysql-test/r/myisam.result | 44 ++++++++++++++++++++++++++++++++++++- mysql-test/t/myisam.test | 26 +++++++++++++++++++++- sql/lex.h | 1 + sql/mysql_priv.h | 6 ++++- sql/opt_range.cc | 4 +++- sql/sql_base.cc | 6 +++-- sql/sql_lex.h | 2 +- sql/sql_parse.cc | 36 +++++++++++++++++++++++------- sql/sql_select.cc | 3 ++- sql/sql_yacc.yy | 55 +++++++++++++++++++++++++++++----------------- sql/table.h | 2 ++ 17 files changed, 207 insertions(+), 52 deletions(-) diff --git a/include/my_base.h b/include/my_base.h index bcb8c8d6a2f..feb5259ef08 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -263,6 +263,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/myisam/mi_check.c b/myisam/mi_check.c index 540f3c92ad3..b65e963bcb7 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; - _mi_key_cmp(keyinfo->seg,info->lastkey,key,USE_WHOLE_KEY,SEARCH_FIND, + _mi_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 aeacf81d90a..0da5ebabf40 100644 --- a/myisam/mi_open.c +++ b/myisam/mi_open.c @@ -559,28 +559,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 d57fd1bb5b2..41d53e76241 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 _mi_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 _mi_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; @@ -695,13 +697,29 @@ static int compare_bin(uchar *a, uint a_length, uchar *b, uint b_length, } - /* - ** Compare two keys - ** Returns <0, 0, >0 acording to which is bigger - ** Key_length specifies length of key to use. Number-keys can't - ** be splited - ** If flag <> SEARCH_FIND compare also position - */ +/* + Compare two keys + + SYNOPSIS + _mi_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)) @@ -738,6 +756,15 @@ int _mi_key_cmp(register MI_KEYSEG *keyseg, register uchar *a, { if (nextflag == (SEARCH_FIND | SEARCH_UPDATE)) nextflag=SEARCH_SAME; /* Allow duplicate keys */ + else if (nextflag & SEARCH_NULL_ARE_NOT_EQUAL) + { + /* + This is only used from mi_check() to calculate cardinality. + It can't be used when searching for a key as this would cause + compare of (a,b) and (b,a) to return the same value. + */ + return -1; + } next_key_length=key_length; continue; /* To next key part */ } diff --git a/myisam/myisamdef.h b/myisam/myisamdef.h index 07744e11e5f..601a9a40aea 100644 --- a/myisam/myisamdef.h +++ b/myisam/myisamdef.h @@ -358,7 +358,7 @@ struct st_myisam_info { #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 */ @@ -529,7 +529,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/r/myisam.result b/mysql-test/r/myisam.result index 4a0eb47efb7..3a3558eedcb 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) @@ -318,3 +318,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 1265d809149..c96a21e73dd 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -2,7 +2,13 @@ # Test bugs in the MyISAM code # -drop table if exists t1; +# Initialise +drop table if exists t1,t2; + +# +# Test problem with CHECK TABLE; +# + CREATE TABLE t1 ( STRING_DATA char(255) default NULL, KEY STRING_DATA (STRING_DATA) @@ -326,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/lex.h b/sql/lex.h index 826b9b4a9ef..82ed322af83 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -151,6 +151,7 @@ static SYMBOL symbols[] = { { "FLOAT8", SYM(DOUBLE_SYM),0,0}, { "FLUSH", SYM(FLUSH_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/mysql_priv.h b/sql/mysql_priv.h index 2a8b263bf28..75bf4e97634 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -226,6 +226,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 @@ -509,7 +513,7 @@ bool add_field_to_list(char *field_name, enum enum_field_types type, void store_position_for_column(const char *name); bool add_to_list(SQL_LIST &list,Item *group,bool asc=0); TABLE_LIST *add_table_to_list(Table_ident *table,LEX_STRING *alias, - bool updating, + ulong table_option, thr_lock_type flags=TL_UNLOCK, List *use_index=0, List *ignore_index=0); diff --git a/sql/opt_range.cc b/sql/opt_range.cc index a18c0178b5d..c607e71c01b 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -605,12 +605,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/sql_base.cc b/sql/sql_base.cc index 7b7c8c01aab..54c3e40244a 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -752,7 +752,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; @@ -910,7 +910,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; @@ -981,6 +981,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; @@ -1888,6 +1889,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 54e72fafdd5..a905871e629 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -110,7 +110,7 @@ typedef struct st_select_lex char *db,*db1,*table1,*db2,*table2; /* For outer join using .. */ Item *where,*having; ha_rows select_limit,offset_limit; - ulong options; + ulong options, table_join_options; List expr_list; List when_list; SQL_LIST order_list,table_list,group_list; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index a0336d0b50b..5bf3a1c0bcd 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -498,7 +498,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); } @@ -3158,12 +3159,30 @@ bool add_to_list(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 *add_table_to_list(Table_ident *table, LEX_STRING *alias, - bool updating, - thr_lock_type flags, + ulong table_options, + thr_lock_type lock_type, List *use_index, - List *ignore_index - ) + List *ignore_index) { register TABLE_LIST *ptr; THD *thd=current_thd; @@ -3211,8 +3230,9 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias, } ptr->real_name=table->table.str; ptr->real_name_length=table->table.length; - ptr->lock_type=flags; - ptr->updating=updating; + ptr->lock_type= lock_type; + ptr->updating= test(table_options & TL_OPTION_UPDATING); + ptr->force_index= test(table_options & TL_OPTION_FORCE_INDEX); if (use_index) ptr->use_index=(List *) thd->memdup((gptr) use_index, sizeof(*use_index)); @@ -3221,7 +3241,7 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias, sizeof(*ignore_index)); /* check that used name is unique */ - if (flags != TL_IGNORE) + if (lock_type != TL_IGNORE) { for (TABLE_LIST *tables=(TABLE_LIST*) thd->lex.select->table_list.first ; tables ; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 28aa21e94ce..237197ba6be 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2057,7 +2057,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_yacc.yy b/sql/sql_yacc.yy index e26e57b8bbd..0e93f048406 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 @@ -198,6 +198,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 @@ -735,7 +736,8 @@ create: lex->sql_command= SQLCOM_CREATE_TABLE; if (!add_table_to_list($5, ($2 & HA_LEX_CREATE_TMP_TABLE ? - &tmp_table_alias : (LEX_STRING*) 0),1)) + &tmp_table_alias : (LEX_STRING*) 0), + TL_OPTION_UPDATING)) YYABORT; lex->create_list.empty(); lex->key_list.empty(); @@ -751,7 +753,7 @@ create: { LEX *lex=Lex; lex->sql_command= SQLCOM_CREATE_INDEX; - if (!add_table_to_list($6,NULL,1)) + if (!add_table_to_list($6, NULL, TL_OPTION_UPDATING)) YYABORT; lex->create_list.empty(); lex->key_list.empty(); @@ -1171,7 +1173,7 @@ alter: LEX *lex=Lex; lex->sql_command = SQLCOM_ALTER_TABLE; lex->name=0; - if (!add_table_to_list($4, NULL,1)) + if (!add_table_to_list($4, NULL, TL_OPTION_UPDATING)) YYABORT; lex->drop_primary=0; lex->create_list.empty(); @@ -1442,8 +1444,9 @@ table_to_table_list: table_to_table: table_ident TO_SYM table_ident - { if (!add_table_to_list($1,NULL,1,TL_IGNORE) || - !add_table_to_list($3,NULL,1,TL_IGNORE)) + { + if (!add_table_to_list($1, NULL, TL_OPTION_UPDATING, TL_IGNORE) || + !add_table_to_list($3, NULL, TL_OPTION_UPDATING, TL_IGNORE)) YYABORT; }; @@ -2127,11 +2130,13 @@ join_table: { SELECT_LEX *sel=Select; sel->use_index_ptr=sel->ignore_index_ptr=0; + sel->table_join_options= 0; } table_ident opt_table_alias opt_key_definition { SELECT_LEX *sel=Select; - if (!($$=add_table_to_list($2,$3,0,TL_UNLOCK, sel->use_index_ptr, + if (!($$=add_table_to_list($2, $3, sel->table_join_options, + TL_UNLOCK, sel->use_index_ptr, sel->ignore_index_ptr))) YYABORT; } @@ -2150,12 +2155,20 @@ opt_key_definition: sel->use_index= *$2; sel->use_index_ptr= &sel->use_index; } + | FORCE_SYM key_usage_list + { + SELECT_LEX *sel=Select; + sel->use_index= *$2; + sel->use_index_ptr= &sel->use_index; + sel->table_join_options|= TL_OPTION_FORCE_INDEX; + } | IGNORE_SYM key_usage_list { SELECT_LEX *sel=Select; sel->ignore_index= *$2; sel->ignore_index_ptr= &sel->ignore_index; - }; + } + ; key_usage_list: key_or_index { Select->interval_list.empty(); } '(' key_usage_list2 ')' @@ -2443,7 +2456,7 @@ drop: lex->drop_list.empty(); lex->drop_list.push_back(new Alter_drop(Alter_drop::KEY, $3.str)); - if (!add_table_to_list($5,NULL, 1)) + if (!add_table_to_list($5, NULL, TL_OPTION_UPDATING)) YYABORT; } | DROP DATABASE if_exists ident @@ -2467,7 +2480,7 @@ table_list: table_name: table_ident - { if (!add_table_to_list($1,NULL,1)) YYABORT; }; + { if (!add_table_to_list($1,NULL,TL_OPTION_UPDATING)) YYABORT; }; if_exists: /* empty */ { $$= 0; } @@ -2678,7 +2691,8 @@ delete: single_multi: FROM table_ident { - if (!add_table_to_list($2, NULL, 1, Lex->lock_option)) + if (!add_table_to_list($2, NULL, TL_OPTION_UPDATING, + Lex->lock_option)) YYABORT; } where_clause opt_order_clause @@ -2699,13 +2713,14 @@ table_wild_list: table_wild_one: ident opt_wild { - if (!add_table_to_list(new Table_ident($1), NULL, 1, - Lex->lock_option)) + if (!add_table_to_list(new Table_ident($1), NULL, + TL_OPTION_UPDATING, Lex->lock_option)) YYABORT; } | ident '.' ident opt_wild { - if (!add_table_to_list(new Table_ident($1,$3,0), NULL, 1, + if (!add_table_to_list(new Table_ident($1,$3,0), NULL, + TL_OPTION_UPDATING, Lex->lock_option)) YYABORT; } @@ -2774,7 +2789,7 @@ show_param: Lex->sql_command= SQLCOM_SHOW_FIELDS; if ($5) $4->change_db($5); - if (!add_table_to_list($4,NULL,0)) + if (!add_table_to_list($4, NULL, 0)) YYABORT; } | NEW_SYM MASTER_SYM FOR_SYM SLAVE WITH MASTER_LOG_FILE_SYM EQ @@ -2807,7 +2822,7 @@ show_param: Lex->sql_command= SQLCOM_SHOW_KEYS; if ($4) $3->change_db($4); - if (!add_table_to_list($3,NULL,0)) + if (!add_table_to_list($3, NULL, 0)) YYABORT; } | STATUS_SYM wild @@ -2834,7 +2849,7 @@ show_param: | CREATE TABLE_SYM table_ident { Lex->sql_command = SQLCOM_SHOW_CREATE; - if(!add_table_to_list($3, NULL,0)) + if(!add_table_to_list($3, NULL, 0)) YYABORT; } | MASTER_SYM STATUS_SYM @@ -2879,7 +2894,7 @@ describe: lex->wild=0; lex->verbose=0; lex->sql_command=SQLCOM_SHOW_FIELDS; - if (!add_table_to_list($2, NULL,0)) + if (!add_table_to_list($2, NULL, 0)) YYABORT; } opt_describe_column {} @@ -2999,14 +3014,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 (!add_table_to_list($11,NULL,1)) + if (!add_table_to_list($11, NULL, TL_OPTION_UPDATING)) YYABORT; } | LOAD TABLE_SYM table_ident FROM MASTER_SYM { Lex->sql_command = SQLCOM_LOAD_MASTER_TABLE; - if (!add_table_to_list($3,NULL,1)) + if (!add_table_to_list($3, NULL, TL_OPTION_UPDATING)) YYABORT; } diff --git a/sql/table.h b/sql/table.h index 3a08cd11a2a..c3f469115b5 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; @@ -157,6 +158,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; -- cgit v1.2.1