diff --git a/.bzrignore b/.bzrignore
index 70ecba34c3a88593686ae5c53f1747c0187b35ad..1f577634845e9858749cfa5c9356036fcab168da 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 87d1c7b5b713cbb4f2975c23c44c5a0970102015..7949e7be7766ac182f8cc5ce2a02cb9592f5a684 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 5c9218da1634d29c724d94c4980e4fc4f912f8f7..2010670599fac23c13ddc50820cd8a962d502ec3 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 4c1b265355dd0b8beddc5825cf3a1629c17013fe..9f341695cbfc54985b2e4e8cf960503de35dc58b 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 fe99dda1ac351547dee8d314f6c8c714de6684d6..9e411e5f28f10d64e8c2c7fa9fb291c2db63d39b 100644
--- a/client/mysqltest.c
+++ b/client/mysqltest.c
@@ -42,7 +42,7 @@
 
 **********************************************************************/
 
-#define MTEST_VERSION "1.26"
+#define MTEST_VERSION "1.27"
 
 #include <my_global.h>
 #include <mysql_embed.h>
@@ -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 de3fe6e196ed67b009f4d08fb047edb415ba4c9f..5c5ed934a9b36a8db630ba52a49745d0b3bb0915 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 14feca5d5c5412561847bc82d229da9bc6361b2f..ee762a1222132dc7b9784b06b3e7fde9aa7fc8cc 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 bb49e9080ce0cbde77508f04c361ea2857210b1d..1ea6e3e30185daa6768340e25ce752035ada12a4 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 e308baa7bd029a7913d9c1e64aec72d5b623c49a..2bcf95f467d075e992d7a304e1cd981ba7e29824 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 5c6366c9890c4c7cf21d8ceed4094a8fbec8eecb..a5011a81c19799f8ab5360b7711558cd701c982a 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 2552d9f80cdc6fdb36c56a02a47414b907ce30ac..bfc4ccd9c08825aefa65fbae63b51ce331a766c4 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 ef6ceaff8da9a9c3a9b9e07d378a3e3c52efb4d6..a386f11c0105e31515a010e98695a5a93b3df745 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 e10fd5890925de2c84d8a7dccd53ad137ca89fe6..6664581072f881b932f0d035ecbb6ed418c90597 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 e57eb7a4d0754504442ac46489cab3b07071f8db..144fc21237201d6a3fffcddb81a7aa8e6a390be5 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 0ae06dca137ddd99353165dc3b0dbfd275f20c63..c1c61d4a8a7c931865fcfb7a7f778b10d0fd8fb5 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 1e435006bb2c9fb50141590a6363fa218358589c..9d7d73aad21e1343dacaa68992353b035234ee6c 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 1f87eb9cf32a668ff5a77a172be32a75eff73718..0a6fcccbef2056f6db972b08dff070f6f9ea7ae3 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 b7aa77f656d6f470316b9e9c826eefde9a1d9e5c..68b9d1e876f22f9b4c8b9d78f57cd28769af790e 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 c900d193929ad4230a60b7244694b4427bc882fb..b8271c848cceb67af83769dae49ea696791e69c6 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 b9e5aa33791e6a8278e71de2b33c6455718a80d6..b4aba2ade135bda717deae683a7e6d2f55d2eff3 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 661b2cd02c8a446f72558ce203db444650c8a78f..b6aceec82e325120f4b4655d8215ea013e41f2f0 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 7adf99ea7722a3102d4448dfd5e4b82f4beb97a0..38a51593ba1887ce24936852c73b7eabaf2bcd62 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 38ffe9980277336bc8430e8cd373a98d1bbe6322..7c3b79f605bb9c6dbc52d516fc7baf4c31b80ecf 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 8aa2dd53027cd9316967d6e53afd2f91c874a215..039066c5b37d16a83dd3a626a88ece6f28a47d97 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 b373693e6e0aef3b077926365af30cd6e16474cb..ddba40214e7d233c81d4c53dd00f99a09443d15a 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 876846a523618f8ed29391893fb3ed54deb4c447..fa15165722dd42c61e5a78f36a492a8f74aee9b4 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 ddddb3fa07df32bc0834996c5b6633b7c8027e04..02773f2eb447145cfe26da4a3c122275309de7e8 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 96113dcdc8b501398a133f3e5c132658462f9e97..ff608825b9c62095d63e7052f9f71028b2bd75f3 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 31a01ae136061d938e9cb848c7c5e059870874e2..8a41ebe5b4f6affee60babc4658ea2cb421768e3 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 328b696ac05453becac3c9f7997b1878fc527ed5..bc01577c24985163f84999cfff5f38b9a1b204df 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 18006e8fd2246553aa894ad84f5e1ed521dadeb4..f58281af0030e69c03b611005ea7b66bad30ddf0 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 247e3399b8b95029da4434cb92eee8fd74239d31..09259779855d70ac9cbb7bd84c0dab206bf5937f 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 <<END_OF_DATA
+$cmd <<END_OF_DATA
 ALTER TABLE user type=MyISAM;
 ALTER TABLE db type=MyISAM;
 ALTER TABLE host type=MyISAM;
@@ -28,7 +36,7 @@ echo ""
 echo "If your tables are already up to date or partially up to date you will"
 echo "get some warnings about 'Duplicated column name'. You can safely ignore these!"
 
-@bindir@/mysql -f --user=root --password="$root_password" --host="$host" mysql <<END_OF_DATA
+$cmd <<END_OF_DATA
 alter table user change password password char(16) NOT NULL;
 alter table user add File_priv enum('N','Y') NOT NULL;
 CREATE TABLE if not exists func (
@@ -45,7 +53,7 @@ echo ""
 
 echo "Creating Grant Alter and Index privileges if they don't exists"
 echo "You can ignore any Duplicate column errors"
-@bindir@/mysql --user=root --password="$root_password" --host="$host" mysql <<END_OF_DATA
+$cmd <<END_OF_DATA
 alter table user add Grant_priv enum('N','Y') NOT NULL,add References_priv enum('N','Y') NOT NULL,add Index_priv enum('N','Y') NOT NULL,add Alter_priv enum('N','Y') NOT NULL;
 alter table host add Grant_priv enum('N','Y') NOT NULL,add References_priv enum('N','Y') NOT NULL,add Index_priv enum('N','Y') NOT NULL,add Alter_priv enum('N','Y') NOT NULL;
 alter table db add Grant_priv enum('N','Y') NOT NULL,add References_priv enum('N','Y') NOT NULL,add Index_priv enum('N','Y') NOT NULL,add Alter_priv enum('N','Y') NOT NULL;
@@ -59,7 +67,7 @@ echo ""
 if test $res = 0
 then
   echo "Setting default privileges for the new grant, index and alter privileges"
-  @bindir@/mysql --user=root --password="$root_password" --host="$host" mysql <<END_OF_DATA
+  $cmd <<END_OF_DATA
   UPDATE user SET Grant_priv=File_priv,References_priv=Create_priv,Index_priv=Create_priv,Alter_priv=Create_priv;
   UPDATE db SET References_priv=Create_priv,Index_priv=Create_priv,Alter_priv=Create_priv;
   UPDATE host SET References_priv=Create_priv,Index_priv=Create_priv,Alter_priv=Create_priv;
@@ -72,7 +80,7 @@ fi
 
 echo "Adding columns needed by GRANT .. REQUIRE (openssl)"
 echo "You can ignore any Duplicate column errors"
-@bindir@/mysql -f --user=root --password="$root_password" --host="$host" mysql <<END_OF_DATA
+$cmd <<END_OF_DATA
 ALTER TABLE user
 ADD ssl_type enum('','ANY','X509', 'SPECIFIED') NOT NULL,
 ADD ssl_cipher BLOB NOT NULL,
@@ -88,7 +96,7 @@ echo ""
 
 echo "Creating the new table and column privilege tables"
 
-@bindir@/mysql -f --user=root --password="$root_password"  --host="$host" mysql <<END_OF_DATA
+$cmd <<END_OF_DATA
 CREATE TABLE IF NOT EXISTS tables_priv (
   Host char(60) DEFAULT '' NOT NULL,
   Db char(60) DEFAULT '' NOT NULL,
@@ -119,7 +127,7 @@ END_OF_DATA
 echo "Changing name of columns_priv.Type -> 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
+$cmd <<END_OF_DATA
 ALTER TABLE columns_priv change Type Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL;
 END_OF_DATA
 echo ""
@@ -131,7 +139,7 @@ echo ""
 echo "Fixing the func table"
 echo "You can ignore any Duplicate column errors"
 
-@bindir@/mysql --user=root --password=$root_password mysql <<EOF
+$cmd <<EOF
 alter table func add type enum ('function','aggregate') NOT NULL;
 EOF
 echo ""
@@ -143,7 +151,7 @@ echo ""
 echo "Adding new fields used by MySQL 4.0.2 to the privilege tables"
 echo "You can ignore any Duplicate column errors"
 
-@bindir@/mysql --user=root --password="$root_password" --host="$host" mysql <<END_OF_DATA
+$cmd <<END_OF_DATA
 alter table user
 add Show_db_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER alter_priv,
 add Super_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Show_db_priv,
@@ -159,7 +167,7 @@ then
   # Convert privileges so that users have similar privileges as before
   echo ""
   echo "Updating new privileges in MySQL 4.0.2 from old ones"
-  @bindir@/mysql --user=root --password="$root_password" --host="$host" mysql <<END_OF_DATA
+  $cmd <<END_OF_DATA
   update user set show_db_priv= select_priv, super_priv=process_priv, execute_priv=process_priv, create_tmp_table_priv='Y', Lock_tables_priv='Y', Repl_slave_priv=file_priv, Repl_client_priv=file_priv where user<>"";
 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 <<END_OF_DATA
+$cmd <<END_OF_DATA
 alter table user
 add max_questions int(11) NOT NULL AFTER x509_subject,
 add max_updates   int(11) unsigned NOT NULL AFTER max_questions,
@@ -179,7 +187,7 @@ END_OF_DATA
 # Add Create_tmp_table_priv and Lock_tables_priv to db and host
 #
 
-@bindir@/mysql --user=root --password="$root_password" --host="$host" mysql <<END_OF_DATA
+$cmd <<END_OF_DATA
 alter table db
 add Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL,
 add Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL;
diff --git a/scripts/mysqlaccess.sh b/scripts/mysqlaccess.sh
index 355eb53d2b5cab7aeb29e54ef76d0632b8b48711..824dba7b65a55ef536fd89102d4c7f0e18a67d56 100644
--- a/scripts/mysqlaccess.sh
+++ b/scripts/mysqlaccess.sh
@@ -13,7 +13,7 @@ BEGIN {
 	$script      = $1;
         $script      = 'MySQLAccess' unless $script;
 	$script_conf = "$script.conf";
-	$script_log  = "~/$script.log";
+	$script_log  = $ENV{'HOME'}."/$script.log";
 
 	# ****************************
 	# information on MySQL
diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh
index 211cc8ceced73637163c8adee25a5d80d081ef89..b68c6f5601522d6d890576ab40995999ff86d911 100644
--- a/scripts/mysqld_safe.sh
+++ b/scripts/mysqld_safe.sh
@@ -12,6 +12,8 @@
 
 trap '' 1 2 3 15			# we shouldn't let anyone kill us
 
+umask 007
+
 defaults=
 case "$1" in
     --no-defaults|--defaults-file=*|--defaults-extra-file=*)
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index b4fe6130e9b658c3c3d38404532c9b7742375245..b1cb45be6b3abd88aa04357d6d092ded0cb79126 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -4166,6 +4166,16 @@ ha_innobase::store_lock(
       			lock_type = TL_WRITE_ALLOW_WRITE;
       		}
 
+		/* In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
+		MySQL would use the lock TL_READ_NO_INSERT on t2, and that
+		would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
+		to t2. Convert the lock to a normal read lock to allow
+		concurrent inserts to t2. */
+      		
+		if (lock_type == TL_READ_NO_INSERT && !thd->in_lock_tables) {
+			lock_type = TL_READ;
+		}
+		
  		lock.type=lock_type;
   	}
 
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 45f54e420de48a6e49ab05407efdfb50d9e5d377..e243a953c63f86f4f581873eebba679af85d74d5 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 b8689a28a5437dd684669ad0f456cef800b7554f..30c345f8030e85e6f3e19102d3cdba213990d3ec 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 a9bb22fb8f74366b19b45e3c10a55ec094949180..9091784bbf33ec3bee55697cab9c99acaec875df 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 e805cf74f1921a6c60c3674cd920136304d7bcb5..4cb46c00bed9d0305c0ddd9069dc6479b5162eca 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 5bf3a1c0bcd6faee0db1811e167f60066829858b..0b6170f1e37b6a8380f6654ad6b00094b1b1aa5b 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 237197ba6bedcfe9864af0fd005861d86a388848..e811c55ed1b58b73f6a8d335dd1e3c2cf5489dc4 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 (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 (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 266bf8aefa9ec03bd679724a3763111f10d8fc5b..c04b4871b4d821ca32bde44922e1937488728047 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 c5f3d4e4b2a71c209bdea339974044f5abffaf01..89b5d8c03e990b3f323ec49055519b1936adad37 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 \