diff --git a/.bzrignore b/.bzrignore index 70ecba34c3a..1f577634845 100644 --- a/.bzrignore +++ b/.bzrignore @@ -522,3 +522,4 @@ vio/test-ssl vio/test-sslclient vio/test-sslserver vio/viotest-ssl +extra/mysql_waitpid diff --git a/Makefile.am b/Makefile.am index 87d1c7b5b71..7949e7be776 100644 --- a/Makefile.am +++ b/Makefile.am @@ -21,10 +21,10 @@ AUTOMAKE_OPTIONS = foreign # These are built from source in the Docs directory EXTRA_DIST = INSTALL-SOURCE README \ COPYING COPYING.LIB -SUBDIRS = include @docs_dirs@ @readline_dir@ \ +SUBDIRS = . include @docs_dirs@ @readline_dir@ \ @thread_dirs@ pstack @sql_client_dirs@ \ - @sql_server_dirs@ @libmysqld_dirs@ scripts man \ - tests BUILD os2 \ + @sql_server_dirs@ scripts man tests \ + BUILD os2 libmysql_r @libmysqld_dirs@ \ @bench_dirs@ support-files @fs_dirs@ @tools_dirs@ # Relink after clean diff --git a/bdb/dist/aclocal/mutex.m4 b/bdb/dist/aclocal/mutex.m4 index 5c9218da163..2010670599f 100644 --- a/bdb/dist/aclocal/mutex.m4 +++ b/bdb/dist/aclocal/mutex.m4 @@ -279,7 +279,7 @@ fi dnl Sparc/gcc: SunOS, Solaris dnl The sparc/gcc code doesn't always work, specifically, I've seen assembler dnl failures from the stbar instruction on SunOS 4.1.4/sun4c and gcc 2.7.2.2. -if test "$db_cv_mutex" = DOESNT_WORK; then +if test "$db_cv_mutex" = no; then AC_TRY_RUN([main(){ #if defined(__sparc__) #if defined(__GNUC__) diff --git a/bdb/include/mutex.h b/bdb/include/mutex.h index 4c1b265355d..9f341695cbf 100644 --- a/bdb/include/mutex.h +++ b/bdb/include/mutex.h @@ -327,7 +327,7 @@ typedef unsigned char tsl_t; */ #define MUTEX_SET(tsl) ({ \ register tsl_t *__l = (tsl); \ - int __r; \ + unsigned char __r; \ asm volatile("tas %1; \n \ seq %0" \ : "=dm" (__r), "=m" (*__l) \ diff --git a/client/mysqltest.c b/client/mysqltest.c index fe99dda1ac3..9e411e5f28f 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -42,7 +42,7 @@ **********************************************************************/ -#define MTEST_VERSION "1.26" +#define MTEST_VERSION "1.27" #include #include @@ -677,7 +677,7 @@ int open_file(const char* name) if (*cur_file && cur_file == file_stack_end) die("Source directives are nesting too deep"); - if (!(*(cur_file+1) = my_fopen(buff, O_RDONLY, MYF(MY_WME)))) + if (!(*(cur_file+1) = my_fopen(buff, O_RDONLY | O_BINARY, MYF(MY_WME)))) die(NullS); cur_file++; *++lineno=1; @@ -1912,7 +1912,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), argument= buff; } fn_format(buff, argument, "", "", 4); - if (!(*++cur_file = my_fopen(buff, O_RDONLY, MYF(MY_WME)))) + if (!(*++cur_file = my_fopen(buff, O_RDONLY | O_BINARY, MYF(MY_WME)))) die("Could not open %s: errno = %d", argument, errno); break; } diff --git a/innobase/btr/btr0sea.c b/innobase/btr/btr0sea.c index de3fe6e196e..5c5ed934a9b 100644 --- a/innobase/btr/btr0sea.c +++ b/innobase/btr/btr0sea.c @@ -508,6 +508,14 @@ btr_search_check_guess( /*===================*/ /* out: TRUE if success */ btr_cur_t* cursor, /* in: guessed cursor position */ + ibool can_only_compare_to_cursor_rec, + /* in: if we do not have a latch on the page + of cursor, but only a latch on + btr_search_latch, then ONLY the columns + of the record UNDER the cursor are + protected, not the next or previous record + in the chain: we cannot look at the next or + previous record to check our guess! */ dtuple_t* tuple, /* in: data tuple */ ulint mode, /* in: PAGE_CUR_L, PAGE_CUR_LE, PAGE_CUR_G, or PAGE_CUR_GE */ @@ -566,6 +574,13 @@ btr_search_check_guess( } } + if (can_only_compare_to_cursor_rec) { + /* Since we could not determine if our guess is right just by + looking at the record under the cursor, return FALSE */ + + return(FALSE); + } + match = 0; bytes = 0; @@ -670,6 +685,7 @@ btr_search_guess_on_hash( ulint fold; ulint tuple_n_fields; dulint tree_id; + ibool can_only_compare_to_cursor_rec = TRUE; #ifdef notdefined btr_cur_t cursor2; btr_pcur_t pcur; @@ -744,6 +760,8 @@ btr_search_guess_on_hash( goto failure; } + can_only_compare_to_cursor_rec = FALSE; + buf_page_dbg_add_level(page, SYNC_TREE_NODE_FROM_HASH); } @@ -775,7 +793,15 @@ btr_search_guess_on_hash( fold); */ } else { - success = btr_search_check_guess(cursor, tuple, mode, mtr); + /* If we only have the latch on btr_search_latch, not on the + page, it only protects the columns of the record the cursor + is positioned on. We cannot look at the next of the previous + record to determine if our guess for the cursor position is + right. */ + + success = btr_search_check_guess(cursor, + can_only_compare_to_cursor_rec, + tuple, mode, mtr); } if (!success) { diff --git a/innobase/include/btr0sea.h b/innobase/include/btr0sea.h index 14feca5d5c5..ee762a12221 100644 --- a/innobase/include/btr0sea.h +++ b/innobase/include/btr0sea.h @@ -234,10 +234,16 @@ struct btr_search_sys_struct{ extern btr_search_sys_t* btr_search_sys; /* The latch protecting the adaptive search system: this latch protects the -(1) positions of records on those pages where a hash index has been built. -NOTE: It does not protect values of non-ordering fields within a record from -being updated in-place! We can use fact (1) to perform unique searches to -indexes. */ +(1) hash index; +(2) columns of a record to which we have a pointer in the hash index; + +but does NOT protect: + +(3) next record offset field in a record; +(4) next or previous records on the same page. + +Bear in mind (3) and (4) when using the hash index. +*/ extern rw_lock_t* btr_search_latch_temp; diff --git a/innobase/page/page0cur.c b/innobase/page/page0cur.c index bb49e9080ce..1ea6e3e3018 100644 --- a/innobase/page/page0cur.c +++ b/innobase/page/page0cur.c @@ -253,7 +253,8 @@ page_cur_search_with_match( up_matched_bytes = cur_matched_bytes; } - } else if ((mode == PAGE_CUR_G) || (mode == PAGE_CUR_LE)) { + } else if (mode == PAGE_CUR_G || mode == PAGE_CUR_LE + || mode == PAGE_CUR_LE_OR_EXTENDS) { low = mid; low_matched_fields = cur_matched_fields; low_matched_bytes = cur_matched_bytes; @@ -308,7 +309,8 @@ page_cur_search_with_match( up_matched_fields = cur_matched_fields; up_matched_bytes = cur_matched_bytes; } - } else if ((mode == PAGE_CUR_G) || (mode == PAGE_CUR_LE)) { + } else if (mode == PAGE_CUR_G || mode == PAGE_CUR_LE + || mode == PAGE_CUR_LE_OR_EXTENDS) { low_rec = mid_rec; low_matched_fields = cur_matched_fields; low_matched_bytes = cur_matched_bytes; diff --git a/libmysql/Makefile.shared b/libmysql/Makefile.shared index e308baa7bd0..2bcf95f467d 100644 --- a/libmysql/Makefile.shared +++ b/libmysql/Makefile.shared @@ -84,6 +84,8 @@ clean-local: rm -f `echo $(mystringsobjects) | sed "s;\.lo;.c;g"` \ `echo $(dbugobjects) | sed "s;\.lo;.c;g"` \ `echo $(mysysobjects) | sed "s;\.lo;.c;g"` \ + `echo $(vio_objects) | sed "s;\.lo;.c;g"` \ + $(CHARSET_SRCS) $(CHARSET_OBJS) \ $(mystringsextra) $(mystringsgen) $(mysysheaders) \ ctype_extra_sources.c net.c ../linked_client_sources diff --git a/ltconfig b/ltconfig index 5c6366c9890..a5011a81c19 100755 --- a/ltconfig +++ b/ltconfig @@ -3009,6 +3009,16 @@ hardcode_action=$hardcode_action # This must work even if \$libdir does not exist. hardcode_libdir_flag_spec=$hardcode_libdir_flag_spec +# Check if debuild is being run by the current shell. If it is then, +# the DEB_BUILD_ARCH variable should be of non-zero length, indicating +# that we are in the middle of a Debian package build (assuming the +# user isn't doing anything strange with environment variables). +if test -n "`dpkg-architecture -qDEB_BUILD_ARCH`" && ps | grep debuild | grep -v grep > /dev/null; then + # Debian policy mandates that rpaths should not be encoded into a binary + # so it is overridden. + hardcode_libdir_flag_spec=" -D_DEBIAN_PATCHED_LIBTOOL_ " +fi + # Whether we need a single -rpath flag with a separated argument. hardcode_libdir_separator=$hardcode_libdir_separator diff --git a/man/isamchk.1 b/man/isamchk.1 index 2552d9f80cd..bfc4ccd9c08 100644 --- a/man/isamchk.1 +++ b/man/isamchk.1 @@ -1,4 +1,4 @@ -.TH ISAMCHK 1 "19 December 2000" +.TH isamchk 1 "19 December 2000" "MySQL 3.23" "MySQL database" .SH NAME .BR isamchk \- Description, check and repair of ISAM tables. diff --git a/man/isamlog.1 b/man/isamlog.1 index ef6ceaff8da..a386f11c010 100644 --- a/man/isamlog.1 +++ b/man/isamlog.1 @@ -1,4 +1,4 @@ -.TH ISAMLOG 1 "20 December 2000" +.TH isamlog 1 "19 December 2000" "MySQL 3.23" "MySQL database" .SH NAME isamlog - Write info about whats in a nisam log file. .SH USAGE diff --git a/man/mysql.1 b/man/mysql.1 index e10fd589092..6664581072f 100644 --- a/man/mysql.1 +++ b/man/mysql.1 @@ -1,4 +1,4 @@ -.TH MYSQL 1 "13 June 1997" +.TH mysql 1 "19 December 2000" "MySQL 3.23" "MySQL database" .SH NAME mysql \- text-based client for mysqld, a SQL-based relational database daemon .SH SYNOPSIS diff --git a/man/mysql_zap.1 b/man/mysql_zap.1 index e57eb7a4d07..144fc212372 100644 --- a/man/mysql_zap.1 +++ b/man/mysql_zap.1 @@ -1,4 +1,4 @@ -.TH ZAP 1 "20 December 2000" +.TH zap 1 "19 December 2000" "MySQL 3.23" "MySQL database" .SH NAME zap - a perl script used to kill processes .SH USAGE diff --git a/man/mysqlaccess.1 b/man/mysqlaccess.1 index 0ae06dca137..c1c61d4a8a7 100644 --- a/man/mysqlaccess.1 +++ b/man/mysqlaccess.1 @@ -1,4 +1,4 @@ -.TH MYSQLACCESS 1 "19 December 2000" +.TH mysqlaccess 1 "19 December 2000" "MySQL 3.23" "MySQL database" .SH NAME .BR mysqlaccess \- Create new users to mysql. diff --git a/man/mysqladmin.1 b/man/mysqladmin.1 index 1e435006bb2..9d7d73aad21 100644 --- a/man/mysqladmin.1 +++ b/man/mysqladmin.1 @@ -1,4 +1,4 @@ -.TH MYSQLADMIN 1 "18 December 2000" +.TH mysqladmin 1 "19 December 2000" "MySQL 3.23" "MySQL database" .SH NAME mysqladmin [OPTIONS] command command.... \- A utility for performing administrative operations .SH OPTION SYNOPSIS diff --git a/man/mysqld.1 b/man/mysqld.1 index 1f87eb9cf32..0a6fcccbef2 100644 --- a/man/mysqld.1 +++ b/man/mysqld.1 @@ -1,4 +1,4 @@ -.TH MYSQLD 1 "19 December 2000" +.TH mysqld 1 "19 December 2000" "MySQL 3.23" "MySQL database" .SH NAME .BR mysqld \- Starts the MySQL server demon diff --git a/man/mysqld_multi.1 b/man/mysqld_multi.1 index b7aa77f656d..68b9d1e876f 100644 --- a/man/mysqld_multi.1 +++ b/man/mysqld_multi.1 @@ -1,4 +1,4 @@ -.TH MYSQLD_MULTI 1 "20 December 2000" +.TH mysqld_multi 1 "19 December 2000" "MySQL 3.23" "MySQL database" .SH NAME mysqld_multi - is meant for managing several mysqld processes running in different UNIX sockets and TCP/IP ports. .SH USAGE diff --git a/man/mysqld_safe.1 b/man/mysqld_safe.1 index c900d193929..b8271c848cc 100644 --- a/man/mysqld_safe.1 +++ b/man/mysqld_safe.1 @@ -1,4 +1,4 @@ -.TH SAFE_MYSQLD 1 "19 December 2000" "safe_mysqld (mysql)" mysql.com +.TH safe_mysqld 1 "19 December 2000" "MySQL 3.23" "MySQL database" .SH NAME mysqld_safe \- start the mysqld daemon on Unix. .SH SYNOPSIS diff --git a/man/mysqldump.1 b/man/mysqldump.1 index b9e5aa33791..b4aba2ade13 100644 --- a/man/mysqldump.1 +++ b/man/mysqldump.1 @@ -1,4 +1,4 @@ -.TH MYSQLDUMP 1 "19 December 2000" +.TH mysqldump 1 "19 December 2000" "MySQL 3.23" "MySQL database" .SH NAME mysqldump \- text-based client for dumping or backing up mysql databases , tables and or data. @@ -123,7 +123,7 @@ Connect to host. Lock all tables for read. .TP .BR \-n | \-\-no\-create\-db -'CREATE DATABASE /*!32312 IF NOT EXISTS*/ db_name;' +\&'CREATE DATABASE /*!32312 IF NOT EXISTS*/ db_name;' will not be put in the output. The above line will be added otherwise, if .BR \-\-databases @@ -270,4 +270,4 @@ Manual page by L. (Kill-9) Pedersen (kill-9@kill-9.dk), Mercurmedia Data Model Architect / system developer (http://www.mercurmedia.com) -.\" end of man page \ No newline at end of file +.\" end of man page diff --git a/man/mysqlshow.1 b/man/mysqlshow.1 index 661b2cd02c8..b6aceec82e3 100644 --- a/man/mysqlshow.1 +++ b/man/mysqlshow.1 @@ -1,4 +1,4 @@ -.TH MYSQLSHOW 1 "19 December 2000" +.TH mysqlshow 1 "19 December 2000" "MySQL 3.23" "MySQL database" .SH NAME .BR mysqlshow \- Shows the structure of a mysql database (databases,tables and columns) diff --git a/man/perror.1 b/man/perror.1 index 7adf99ea772..38a51593ba1 100644 --- a/man/perror.1 +++ b/man/perror.1 @@ -1,4 +1,4 @@ -.TH PERROR 1 "19 December 2000" +.TH perror 1 "19 December 2000" "MySQL 3.23" "MySQL database" .SH NAME .BR perror can be used to display a description for a system error code, or an MyISAM/ISAM table handler error code. The error messages are mostly system dependent. diff --git a/man/replace.1 b/man/replace.1 index 38ffe998027..7c3b79f605b 100644 --- a/man/replace.1 +++ b/man/replace.1 @@ -1,4 +1,4 @@ -.TH REPLACE 1 "20 December 2000" +.TH replace 1 "19 December 2000" "MySQL 3.23" "MySQL database" .SH NAME .TP replace - A utility program that is used by msql2mysql, but that has more general applicability as well. replace changes strings in place in files or on the standard input. Uses a finite state machine to match longer strings first. Can be used to swap strings. diff --git a/myisam/mi_create.c b/myisam/mi_create.c index 8aa2dd53027..039066c5b37 100644 --- a/myisam/mi_create.c +++ b/myisam/mi_create.c @@ -228,7 +228,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, if (uniques) { max_key_block_length= myisam_block_size; - max_key_length= MI_UNIQUE_HASH_LENGTH; + max_key_length= MI_UNIQUE_HASH_LENGTH + pointer; } for (i=0, keydef=keydefs ; i < keys ; i++ , keydef++) diff --git a/myisam/mi_unique.c b/myisam/mi_unique.c index b373693e6e0..ddba40214e7 100644 --- a/myisam/mi_unique.c +++ b/myisam/mi_unique.c @@ -24,7 +24,7 @@ my_bool mi_check_unique(MI_INFO *info, MI_UNIQUEDEF *def, byte *record, { my_off_t lastpos=info->lastpos; MI_KEYDEF *key= &info->s->keyinfo[def->key]; - uchar *key_buff=info->lastkey+info->s->base.max_key_length; + uchar *key_buff=info->lastkey2; DBUG_ENTER("mi_check_unique"); mi_unique_store(record+key->seg->start, unique_hash); @@ -80,7 +80,16 @@ ha_checksum mi_unique_hash(MI_UNIQUEDEF *def, const byte *record) if (keyseg->null_bit) { if (record[keyseg->null_pos] & keyseg->null_bit) + { + /* + Change crc in a way different from an empty string or 0. + (This is an optimisation; The code will work even if this isn't + done) + */ + crc=((crc << 8) + 511+ + (crc >> (8*sizeof(ha_checksum)-8))); continue; + } } pos= record+keyseg->start; if (keyseg->flag & HA_VAR_LENGTH) diff --git a/mysql-test/r/explain.result b/mysql-test/r/explain.result index 876846a5236..fa15165722d 100644 --- a/mysql-test/r/explain.result +++ b/mysql-test/r/explain.result @@ -1,5 +1,8 @@ drop table if exists t1; create table t1 (id int not null, str char(10), unique(str)); +explain select * from t1; +table type possible_keys key key_len ref rows Extra +t1 system NULL NULL NULL NULL 0 const row not found insert into t1 values (1, null),(2, null),(3, "foo"),(4, "bar"); select * from t1 where str is null; id str diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index ddddb3fa07d..02773f2eb44 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -467,3 +467,17 @@ NOT NULL); max(value) 4 drop table t1,t2,t3; +create table t1 (a blob null); +insert into t1 values (NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(""),(""),(""),("b"); +select a,count(*) from t1 group by a; +a count(*) +NULL 9 + 3 +b 1 +set option sql_big_tables=1; +select a,count(*) from t1 group by a; +a count(*) +NULL 9 + 3 +b 1 +drop table t1; diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result index 96113dcdc8b..ff608825b9c 100644 --- a/mysql-test/r/join.result +++ b/mysql-test/r/join.result @@ -14,8 +14,7 @@ insert into t1 values (101); insert into t1 values (105); insert into t1 values (106); insert into t1 values (107); -insert into t2 values (107); -insert into t2 values (75); +insert into t2 values (107),(75),(1000); select t1.id, t2.id from t1, t2 where t2.id = t1.id; id id 107 107 @@ -28,6 +27,16 @@ select t1.id, count(t2.id) from t1,t2 where t2.id = t1.id group by t2.id; id count(t2.id) 75 1 107 1 +select t1.id,t2.id from t2 left join t1 on t1.id>=74 and t1.id<=0 where t2.id=75 and t1.id is null; +id id +NULL 75 +explain select t1.id,t2.id from t2 left join t1 on t1.id>=74 and t1.id<=0 where t2.id=75 and t1.id is null; +table type possible_keys key key_len ref rows Extra +t1 const PRIMARY NULL NULL NULL 1 Impossible ON condition +t2 ALL NULL NULL NULL NULL 3 Using where +explain select t1.id, t2.id from t1, t2 where t2.id = t1.id and t1.id <0 and t1.id > 0; +Comment +Impossible WHERE noticed after reading const tables drop table t1,t2; CREATE TABLE t1 ( id int(11) NOT NULL auto_increment, diff --git a/mysql-test/t/explain.test b/mysql-test/t/explain.test index 31a01ae1360..8a41ebe5b4f 100644 --- a/mysql-test/t/explain.test +++ b/mysql-test/t/explain.test @@ -3,6 +3,7 @@ drop table if exists t1; create table t1 (id int not null, str char(10), unique(str)); +explain select * from t1; insert into t1 values (1, null),(2, null),(3, "foo"),(4, "bar"); select * from t1 where str is null; select * from t1 where str="foo"; @@ -12,8 +13,10 @@ explain select * from t1 ignore key (str) where str="foo"; explain select * from t1 use key (str,str) where str="foo"; #The following should give errors -!$1072 explain select * from t1 use key (str,str,foo) where str="foo"; -!$1072 explain select * from t1 ignore key (str,str,foo) where str="foo"; +--error 1072 +explain select * from t1 use key (str,str,foo) where str="foo"; +--error 1072 +explain select * from t1 ignore key (str,str,foo) where str="foo"; drop table t1; explain select 1; diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test index 328b696ac05..bc01577c249 100644 --- a/mysql-test/t/group_by.test +++ b/mysql-test/t/group_by.test @@ -354,3 +354,14 @@ m.c1id = c1.id AND c1.active = 'Yes' LEFT JOIN t3 AS c2 ON m.c2id = c2.id AND c2.active = 'Yes' WHERE m.pid=1 AND (c1.id IS NOT NULL OR c2.id IS NOT NULL); drop table t1,t2,t3; + +# +# Test bug in GROUP BY on BLOB that is NULL or empty +# + +create table t1 (a blob null); +insert into t1 values (NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(""),(""),(""),("b"); +select a,count(*) from t1 group by a; +set option sql_big_tables=1; +select a,count(*) from t1 group by a; +drop table t1; diff --git a/mysql-test/t/join.test b/mysql-test/t/join.test index 18006e8fd22..f58281af003 100644 --- a/mysql-test/t/join.test +++ b/mysql-test/t/join.test @@ -19,13 +19,18 @@ insert into t1 values (105); insert into t1 values (106); insert into t1 values (107); -insert into t2 values (107); -insert into t2 values (75); +insert into t2 values (107),(75),(1000); select t1.id, t2.id from t1, t2 where t2.id = t1.id; select t1.id, count(t2.id) from t1,t2 where t2.id = t1.id group by t1.id; select t1.id, count(t2.id) from t1,t2 where t2.id = t1.id group by t2.id; +# +# Test problems with impossible ON or WHERE +# +select t1.id,t2.id from t2 left join t1 on t1.id>=74 and t1.id<=0 where t2.id=75 and t1.id is null; +explain select t1.id,t2.id from t2 left join t1 on t1.id>=74 and t1.id<=0 where t2.id=75 and t1.id is null; +explain select t1.id, t2.id from t1, t2 where t2.id = t1.id and t1.id <0 and t1.id > 0; drop table t1,t2; # diff --git a/scripts/mysql_fix_privilege_tables.sh b/scripts/mysql_fix_privilege_tables.sh index 247e3399b8b..09259779855 100644 --- a/scripts/mysql_fix_privilege_tables.sh +++ b/scripts/mysql_fix_privilege_tables.sh @@ -1,19 +1,27 @@ #!/bin/sh echo "This scripts updates the mysql.user, mysql.db, mysql.host and the" -echo "mysql.func table to MySQL 3.22.14 and above." +echo "mysql.func tables to MySQL 3.22.14 and above." echo "" echo "This is needed if you want to use the new GRANT functions," -echo "CREATE AGGREAGATE FUNCTION or want to use the more secure passwords in 3.23" +echo "CREATE AGGREGATE FUNCTION or want to use the more secure passwords in 3.23" echo "" -echo "If you get Access denied errors, you should run this script again" -echo "and give the MySQL root user password as a argument!" +echo "If you get 'Access denied' errors, you should run this script again" +echo "and give the MySQL root user password as an argument!" root_password="$1" host="localhost" +user="root" + +if test -z $1 ; then + cmd="@bindir@/mysql -f --user=$user --host=$host mysql" +else + root_password="$1" + cmd="@bindir@/mysql -f --user=$user --password=$root_password --host=$host mysql" +fi echo "Converting all privilege tables to MyISAM format" -@bindir@/mysql -f --user=root --password="$root_password" --host="$host" mysql < columns_priv.Column_priv" echo "You can ignore any Unknown column errors from this" -@bindir@/mysql -f --user=root --password="$root_password" --host="$host" mysql <""; END_OF_DATA echo "" @@ -168,7 +176,7 @@ fi # Add fields that can be used to limit number of questions and connections # for some users. -@bindir@/mysql -f --user=root --password="$root_password" --host="$host" mysql <in_lock_tables) { + lock_type = TL_READ; + } + lock.type=lock_type; } diff --git a/sql/log_event.cc b/sql/log_event.cc index 45f54e420de..e243a953c63 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1702,10 +1702,11 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli) if (db_ok(thd->db, replicate_do_db, replicate_ignore_db)) { - thd->query = (char*)query; thd->set_time((time_t)when); thd->current_tablenr = 0; + thd->query_length= q_len; VOID(pthread_mutex_lock(&LOCK_thread_count)); + thd->query = (char*)query; thd->query_id = query_id++; VOID(pthread_mutex_unlock(&LOCK_thread_count)); thd->query_error = 0; // clear error @@ -1760,7 +1761,9 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli) else { // master could be inconsistent, abort and tell DBA to check/fix it + VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->db = thd->query = 0; + VOID(pthread_mutex_unlock(&LOCK_thread_count)); thd->variables.convert_set = 0; close_thread_tables(thd); free_root(&thd->mem_root,0); @@ -1768,7 +1771,9 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli) } } thd->db= 0; // prevent db from being freed + VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query= 0; // just to be sure + VOID(pthread_mutex_unlock(&LOCK_thread_count)); // assume no convert for next query unless set explictly thd->variables.convert_set = 0; close_thread_tables(thd); @@ -1816,7 +1821,8 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, { init_sql_alloc(&thd->mem_root, 8192,0); thd->db = rewrite_db((char*)db); - thd->query = 0; + DBUG_ASSERT(thd->query == 0); + thd->query = 0; // Should not be needed thd->query_error = 0; if (db_ok(thd->db, replicate_do_db, replicate_ignore_db)) diff --git a/sql/slave.cc b/sql/slave.cc index b8689a28a54..30c345f8030 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -867,6 +867,7 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db, const char* table_name) { ulong packet_len = my_net_read(net); // read create table statement + char *query; Vio* save_vio; HA_CHECK_OPT check_opt; TABLE_LIST tables; @@ -886,15 +887,23 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db, return 1; } thd->command = COM_TABLE_DUMP; - thd->query = sql_alloc(packet_len + 1); - if (!thd->query) + /* Note that we should not set thd->query until the area is initalized */ + if (!(query = sql_alloc(packet_len + 1))) { sql_print_error("create_table_from_dump: out of memory"); net_printf(&thd->net, ER_GET_ERRNO, "Out of memory"); return 1; } - memcpy(thd->query, net->read_pos, packet_len); - thd->query[packet_len] = 0; + memcpy(query, net->read_pos, packet_len); + query[packet_len]= 0; + thd->query_length= packet_len; + /* + We make the following lock in an attempt to ensure that the compiler will + not rearrange the code so that thd->query is set too soon + */ + VOID(pthread_mutex_lock(&LOCK_thread_count)); + thd->query= query; + VOID(pthread_mutex_unlock(&LOCK_thread_count)); thd->current_tablenr = 0; thd->query_error = 0; thd->net.no_send_ok = 1; @@ -2049,7 +2058,9 @@ err: // print the current replication position sql_print_error("Slave I/O thread exiting, read up to log '%s', position %s", IO_RPL_LOG_NAME, llstr(mi->master_log_pos,llbuff)); + VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query = thd->db = 0; // extra safety + VOID(pthread_mutex_unlock(&LOCK_thread_count)); if (mysql) { mc_mysql_close(mysql); @@ -2183,7 +2194,9 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \ RPL_LOG_NAME, llstr(rli->master_log_pos,llbuff)); err: + VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query = thd->db = 0; // extra safety + VOID(pthread_mutex_unlock(&LOCK_thread_count)); thd->proc_info = "Waiting for slave mutex on exit"; pthread_mutex_lock(&rli->run_lock); DBUG_ASSERT(rli->slave_running == 1); // tracking buffer overrun diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index a9bb22fb8f7..9091784bbf3 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -2322,6 +2322,7 @@ my_bool grant_init(THD *org_thd) if (t_table->file->index_first(t_table->record[0])) { t_table->file->index_end(); + return_val= 0; goto end_unlock; } grant_option= TRUE; diff --git a/sql/sql_db.cc b/sql/sql_db.cc index e805cf74f19..4cb46c00bed 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -78,9 +78,9 @@ int mysql_create_db(THD *thd, char *db, uint create_options, bool silent) if (!thd->query) { /* The client used the old obsolete mysql_create_db() call */ - thd->query = path; - thd->query_length = (uint) (strxmov(path,"create database `", db, "`", - NullS) - path); + thd->query_length= (uint) (strxmov(path,"create database `", db, "`", + NullS) - path); + thd->query= path; } { mysql_update_log.write(thd,thd->query, thd->query_length); @@ -92,8 +92,9 @@ int mysql_create_db(THD *thd, char *db, uint create_options, bool silent) } if (thd->query == path) { - thd->query = 0; // just in case - thd->query_length = 0; + VOID(pthread_mutex_lock(&LOCK_thread_count)); + thd->query= 0; + VOID(pthread_mutex_unlock(&LOCK_thread_count)); } send_ok(&thd->net, result); } @@ -167,9 +168,10 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) { if (!thd->query) { - thd->query = path; - thd->query_length = (uint) (strxmov(path,"drop database ", db, NullS)- - path); + thd->query_length= (uint) (strxmov(path,"drop database `", db, "`", + NullS)- + path); + thd->query= path; } mysql_update_log.write(thd, thd->query, thd->query_length); if (mysql_bin_log.is_open()) @@ -179,8 +181,9 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) } if (thd->query == path) { - thd->query = 0; // just in case - thd->query_length = 0; + VOID(pthread_mutex_lock(&LOCK_thread_count)); + thd->query= 0; + VOID(pthread_mutex_unlock(&LOCK_thread_count)); } send_ok(&thd->net,(ulong) deleted); } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 5bf3a1c0bcd..0b6170f1e37 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -852,7 +852,7 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd) goto err; } net_flush(&thd->net); - if ((error = table->file->dump(thd,fd))) + if ((error= table->file->dump(thd,fd))) my_error(ER_GET_ERRNO, MYF(0)); err: @@ -958,7 +958,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd, tbl_name[tbl_len] = 0; if (mysql_table_dump(thd, db, tbl_name, -1)) send_error(&thd->net); // dump to NET - break; } case COM_CHANGE_USER: diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 237197ba6be..e811c55ed1b 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB +/* Copyright (C) 2000-2003 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 @@ -1009,7 +1009,6 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds, table_map found_const_table_map,all_table_map; TABLE **table_vector; JOIN_TAB *stat,*stat_end,*s,**stat_ref; - SQL_SELECT *select; KEYUSE *keyuse,*start_keyuse; table_map outer_join=0; JOIN_TAB *stat_vector[MAX_TABLES+1]; @@ -1021,7 +1020,6 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds, table_vector=(TABLE**) join->thd->alloc(sizeof(TABLE*)*(table_count*2)); if (!stat || !stat_ref || !table_vector) DBUG_RETURN(1); // Eom /* purecov: inspected */ - select=0; join->best_ref=stat_vector; @@ -1205,7 +1203,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds, { // Found everything for ref. int tmp; ref_changed = 1; - s->type=JT_CONST; + s->type= JT_CONST; join->const_table_map|=table->map; set_position(join,const_count++,s,start_keyuse); if (create_ref_for_key(join, s, start_keyuse, @@ -1256,23 +1254,44 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds, if (s->const_keys) { ha_rows records; - if (!select) - select=make_select(s->table, found_const_table_map, - found_const_table_map, - and_conds(conds,s->on_expr),&error); - records=get_quick_record_count(select,s->table, s->const_keys, - join->row_limit); + SQL_SELECT *select; + select= make_select(s->table, found_const_table_map, + found_const_table_map, + s->on_expr ? s->on_expr : conds, + &error); + records= get_quick_record_count(select,s->table, s->const_keys, + join->row_limit); s->quick=select->quick; s->needed_reg=select->needed_reg; select->quick=0; + if (records == 0 && s->table->reginfo.impossible_range) + { + /* + Impossible WHERE or ON expression + In case of ON, we mark that the we match one empty NULL row. + In case of WHERE, don't set found_const_table_map to get the + caller to abort with a zero row result. + */ + join->const_table_map|= s->table->map; + set_position(join,const_count++,s,(KEYUSE*) 0); + s->type= JT_CONST; + if (s->on_expr) + { + /* Generate empty row */ + s->info= "Impossible ON condition"; + found_const_table_map|= s->table->map; + s->type= JT_CONST; + mark_as_null_row(s->table); // All fields are NULL + } + } if (records != HA_POS_ERROR) { s->found_records=records; s->read_time= (ha_rows) (s->quick ? s->quick->read_time : 0.0); } + delete select; } } - delete select; /* Find best combination and return it */ join->join_tab=stat; @@ -2367,7 +2386,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse, keyparts != keyinfo->key_parts) j->type=JT_REF; /* Must read with repeat */ else if (ref_key == j->ref.key_copy) - { /* Should never be reached */ + { /* This happen if we are using a constant expression in the ON part of an LEFT JOIN. @@ -7333,36 +7352,39 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, if (tab->info) item_list.push_back(new Item_string(tab->info,strlen(tab->info))); - else if (tab->select) + else { - if (tab->use_quick == 2) + if (tab->select) { - sprintf(buff_ptr,"; Range checked for each record (index map: %u)", - tab->keys); - buff_ptr=strend(buff_ptr); + if (tab->use_quick == 2) + { + sprintf(buff_ptr,"; Range checked for each record (index map: %u)", + tab->keys); + buff_ptr=strend(buff_ptr); + } + else + buff_ptr=strmov(buff_ptr,"; Using where"); } - else - buff_ptr=strmov(buff_ptr,"; Using where"); + if (key_read) + buff_ptr= strmov(buff_ptr,"; Using index"); + if (table->reginfo.not_exists_optimize) + buff_ptr= strmov(buff_ptr,"; Not exists"); + if (need_tmp_table) + { + need_tmp_table=0; + buff_ptr= strmov(buff_ptr,"; Using temporary"); + } + if (need_order) + { + need_order=0; + buff_ptr= strmov(buff_ptr,"; Using filesort"); + } + if (distinct && test_all_bits(used_tables,thd->used_tables)) + buff_ptr= strmov(buff_ptr,"; Distinct"); + if (buff_ptr == buff) + buff_ptr+= 2; + item_list.push_back(new Item_string(buff+2,(uint) (buff_ptr - buff)-2)); } - if (key_read) - buff_ptr= strmov(buff_ptr,"; Using index"); - if (table->reginfo.not_exists_optimize) - buff_ptr= strmov(buff_ptr,"; Not exists"); - if (need_tmp_table) - { - need_tmp_table=0; - buff_ptr= strmov(buff_ptr,"; Using temporary"); - } - if (need_order) - { - need_order=0; - buff_ptr= strmov(buff_ptr,"; Using filesort"); - } - if (distinct && test_all_bits(used_tables,thd->used_tables)) - buff_ptr= strmov(buff_ptr,"; Distinct"); - if (buff_ptr == buff) - buff_ptr+= 2; - item_list.push_back(new Item_string(buff+2,(uint) (buff_ptr - buff)-2)); // For next iteration used_tables|=table->map; if (result->send_data(item_list)) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 266bf8aefa9..c04b4871b4d 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1771,12 +1771,9 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, /* We changed a temporary table */ if (error) { - /* - * The following function call will also free a - * new_table pointer. - * Therefore, here new_table pointer is not free'd as it is - * free'd in close_temporary() which is called by by the - * close_temporary_table() function. + /* + The following function call will free the new_table pointer, + in close_temporary_table(), so we can safely directly jump to err */ close_temporary_table(thd,new_db,tmp_name); goto err; diff --git a/strings/Makefile.am b/strings/Makefile.am index c5f3d4e4b2a..89b5d8c03e9 100644 --- a/strings/Makefile.am +++ b/strings/Makefile.am @@ -40,6 +40,7 @@ endif libmystrings_a_SOURCES = $(ASRCS) $(CSRCS) noinst_PROGRAMS = conf_to_src +DISTCLEANFILES = ctype_autoconf.c # Default charset definitions EXTRA_DIST = ctype-big5.c ctype-czech.c ctype-euc_kr.c \ ctype-gb2312.c ctype-gbk.c ctype-sjis.c \