diff --git a/VC++Files/libmysql/libmysql.dsp b/VC++Files/libmysql/libmysql.dsp
index bddf1988e03779d024d20de611310178a5fdfedc..43dee62061ffa15639fc0c8dbf3160f80e2f2032 100644
--- a/VC++Files/libmysql/libmysql.dsp
+++ b/VC++Files/libmysql/libmysql.dsp
@@ -25,7 +25,7 @@ CFG=libmysql - Win32 Debug
 # PROP AllowPerConfigDependencies 0
 # PROP Scc_ProjName ""
 # PROP Scc_LocalPath ""
-CPP=cl.exe
+CPP=xicl6.exe
 MTL=midl.exe
 RSC=rc.exe
 
@@ -52,14 +52,14 @@ RSC=rc.exe
 BSC32=bscmake.exe
 # ADD BASE BSC32 /nologo
 # ADD BSC32 /nologo
-LINK32=link.exe
+LINK32=xilink6.exe
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
 # ADD LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 /def:"libmysql.def" /out:"..\lib_release\libmysql.dll" /libpath:"." /libpath:"..\lib_release"
 # SUBTRACT LINK32 /pdb:none
 # Begin Special Build Tool
 SOURCE="$(InputPath)"
-PostBuild_Desc=Copy .lib file
-PostBuild_Cmds=xcopy  release\libmysql.lib   ..\lib_release\
+PostBuild_Desc=Move DLL export lib
+PostBuild_Cmds=xcopy release\libmysql.lib ..\lib_release /y
 # End Special Build Tool
 
 !ELSEIF  "$(CFG)" == "libmysql - Win32 Debug"
@@ -85,14 +85,14 @@ PostBuild_Cmds=xcopy  release\libmysql.lib   ..\lib_release\
 BSC32=bscmake.exe
 # ADD BASE BSC32 /nologo
 # ADD BSC32 /nologo
-LINK32=link.exe
+LINK32=xilink6.exe
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
 # ADD LINK32 zlib.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /machine:I386 /def:"libmysql.def" /out:"..\lib_debug\libmysql.dll" /pdbtype:sept /libpath:"." /libpath:"..\lib_debug"
 # SUBTRACT LINK32 /pdb:none
 # Begin Special Build Tool
 SOURCE="$(InputPath)"
-PostBuild_Desc=Copy .lib file
-PostBuild_Cmds=xcopy   ..\lib_debug\libmysql.dll   C:\winnt\system32\  	xcopy  debug\libmysql.lib   ..\lib_debug\
+PostBuild_Desc=Move DLL export lib
+PostBuild_Cmds=xcopy ..\lib_debug\libmysql.dll C:\winnt\system32\ /y	xcopy     debug\libmysql.lib ..\lib_debug\ /y
 # End Special Build Tool
 
 !ENDIF
@@ -239,6 +239,10 @@ SOURCE=..\mysys\mf_pack.c
 # End Source File
 # Begin Source File
 
+SOURCE=..\mysys\mf_path.c
+# End Source File
+# Begin Source File
+
 SOURCE=..\mysys\mf_unixpath.c
 # End Source File
 # Begin Source File
@@ -395,6 +399,10 @@ SOURCE=..\client\select_test.c
 # End Source File
 # Begin Source File
 
+SOURCE=..\mysys\sha1.c
+# End Source File
+# Begin Source File
+
 SOURCE=..\client\sql_string.cpp
 # End Source File
 # Begin Source File
diff --git a/myisam/mi_key.c b/myisam/mi_key.c
index 9ec1ca99e0eddfd54b7cddc5a1ac001f5bf42683..5b167cc9ab01b786a51d129925a26a0bb2176fba 100644
--- a/myisam/mi_key.c
+++ b/myisam/mi_key.c
@@ -136,11 +136,26 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
 } /* _mi_make_key */
 
 
-	/* Pack a key to intern format from given format (c_rkey) */
-	/* returns length of packed key */
+/*
+  Pack a key to intern format from given format (c_rkey)
+
+  SYNOPSIS
+    _mi_pack_key()
+    info		MyISAM handler
+    uint keynr		key number
+    key			Store packed key here
+    old			Not packed key
+    k_length		Length of 'old' to use
+    last_used_keyseg	out parameter.  May be NULL
+
+   RETURN
+     length of packed key
+
+     last_use_keyseg 	Store pointer to the keyseg after the last used one
+*/
 
 uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
-		  uint k_length)
+		  uint k_length, MI_KEYSEG **last_used_keyseg)
 {
   uint length;
   uchar *pos,*end,*start_key=key;
@@ -211,6 +226,8 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
     key+= length;
     k_length-=length;
   }
+  if (last_used_keyseg)
+    *last_used_keyseg= keyseg;
 
 #ifdef NOT_USED
   if (keyseg->type)
diff --git a/myisam/mi_range.c b/myisam/mi_range.c
index 70694bf462065106f6c7201e2fe91fd4da410e2f..8e85afc5f805a5abb9452659691d0cbd83a4fd3e 100644
--- a/myisam/mi_range.c
+++ b/myisam/mi_range.c
@@ -83,7 +83,8 @@ static ha_rows _mi_record_pos(MI_INFO *info, const byte *key, uint key_len,
   if (key_len == 0)
     key_len=USE_WHOLE_KEY;
   key_buff=info->lastkey+info->s->base.max_key_length;
-  key_len=_mi_pack_key(info,inx,key_buff,(uchar*) key,key_len);
+  key_len=_mi_pack_key(info,inx,key_buff,(uchar*) key,key_len,
+		       (MI_KEYSEG**) 0);
   DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE,keyinfo->seg,
 				    (uchar*) key_buff,key_len););
   nextflag=myisam_read_vec[search_flag];
diff --git a/myisam/mi_rkey.c b/myisam/mi_rkey.c
index 86547d3ef04b0139f18e20495846b6659b03ecc1..60dec0449a01a90ef37aebdda4e56e20021b462b 100644
--- a/myisam/mi_rkey.c
+++ b/myisam/mi_rkey.c
@@ -23,10 +23,12 @@
 	/* Ordinary search_flag is 0 ; Give error if no record with key */
 
 int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
-	     enum ha_rkey_function search_flag)
+	    enum ha_rkey_function search_flag)
 {
   uchar *key_buff;
   MYISAM_SHARE *share=info->s;
+  MI_KEYDEF *keyinfo;
+  MI_KEYSEG *last_used_keyseg;
   uint pack_key_length, use_key_length, nextflag;
   DBUG_ENTER("mi_rkey");
   DBUG_PRINT("enter",("base: %lx  inx: %d  search_flag: %d",
@@ -36,23 +38,27 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
     DBUG_RETURN(my_errno);
 
   info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
+  keyinfo= share->keyinfo + inx;
 
   if (!info->use_packed_key)
   {
     if (key_len == 0)
       key_len=USE_WHOLE_KEY;
     key_buff=info->lastkey+info->s->base.max_key_length;
-    pack_key_length=_mi_pack_key(info,(uint) inx,key_buff,(uchar*) key,key_len);
-    info->last_rkey_length=pack_key_length;
-    DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE,share->keyinfo[inx].seg,
-				     key_buff,pack_key_length););
+    pack_key_length=_mi_pack_key(info, (uint) inx, key_buff, (uchar*) key,
+				 key_len, &last_used_keyseg);
+    DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE, keyinfo->seg,
+				     key_buff, pack_key_length););
   }
   else
   {
-    /* key is already packed! */
+    /*
+      key is already packed!;  This happens when we are using a MERGE TABLE
+    */
     key_buff=info->lastkey+info->s->base.max_key_length;
-    info->last_rkey_length=pack_key_length=key_len;
+    pack_key_length= key_len;
     bmove(key_buff,key,key_len);
+    last_used_keyseg= 0;
   }
 
   if (fast_mi_readinfo(info))
@@ -65,8 +71,8 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
   if (!(nextflag & (SEARCH_FIND | SEARCH_NO_FIND | SEARCH_LAST)))
     use_key_length=USE_WHOLE_KEY;
 
-  if (!_mi_search(info,info->s->keyinfo+inx,key_buff,use_key_length,
-		  myisam_read_vec[search_flag],info->s->state.key_root[inx]))
+  if (!_mi_search(info,keyinfo, key_buff, use_key_length,
+		  myisam_read_vec[search_flag], info->s->state.key_root[inx]))
   {
     while (info->lastpos >= info->state->data_file_length)
     {
@@ -76,7 +82,7 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
 	exact key, because the keys are sorted according to position
       */
 
-      if  (_mi_search_next(info,info->s->keyinfo+inx,info->lastkey,
+      if  (_mi_search_next(info, keyinfo, info->lastkey,
 			   info->lastkey_length,
 			   myisam_readnext_vec[search_flag],
 			   info->s->state.key_root[inx]))
@@ -86,6 +92,12 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
   if (share->concurrent_insert)
     rw_unlock(&share->key_root_lock[inx]);
 
+  /* Calculate length of the found key;  Used by mi_rnext_same */
+  if ((keyinfo->flag & HA_VAR_LENGTH_KEY) && last_used_keyseg)
+    info->last_rkey_length= _mi_keylength_part(keyinfo, info->lastkey,
+					       last_used_keyseg);
+  else
+    info->last_rkey_length= pack_key_length;
   if (!buf)
     DBUG_RETURN(info->lastpos==HA_OFFSET_ERROR ? my_errno : 0);
 
@@ -99,6 +111,7 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
 
   /* Store key for read next */
   memcpy(info->lastkey,key_buff,pack_key_length);
+  info->last_rkey_length= pack_key_length;
   bzero((char*) info->lastkey+pack_key_length,info->s->base.rec_reflength);
   info->lastkey_length=pack_key_length+info->s->base.rec_reflength;
 
diff --git a/myisam/mi_search.c b/myisam/mi_search.c
index 41d53e762419f90b7f98d0e02fd96468efef784b..32db69144d86985f8f73f89e86024886e022e8d8 100644
--- a/myisam/mi_search.c
+++ b/myisam/mi_search.c
@@ -1441,6 +1441,37 @@ uint _mi_keylength(MI_KEYDEF *keyinfo, register uchar *key)
 } /* _mi_keylength */
 
 
+/*
+  Calculate length of part key.
+
+  Used in mi_rkey() to find the key found for the key-part that was used.
+  This is needed in case of multi-byte character sets where we may search
+  after '0xDF' but find 'ss'
+*/
+
+uint _mi_keylength_part(MI_KEYDEF *keyinfo, register uchar *key,
+			MI_KEYSEG *end)
+{
+  reg1 MI_KEYSEG *keyseg;
+  uchar *start= key;
+
+  for (keyseg=keyinfo->seg ; keyseg != end ; keyseg++)
+  {
+    if (keyseg->flag & HA_NULL_PART)
+      if (!*key++)
+        continue;
+    if (keyseg->flag & (HA_SPACE_PACK | HA_BLOB_PART | HA_VAR_LENGTH))
+    {
+      uint length;
+      get_key_length(length,key);
+      key+=length;
+    }
+    else
+      key+= keyseg->length;
+  }
+  return (uint) (key-start);
+}
+
         /* Move a key */
 
 uchar *_mi_move_key(MI_KEYDEF *keyinfo, uchar *to, uchar *from)
diff --git a/myisam/mi_test2.c b/myisam/mi_test2.c
index 93538e3ead71a1aae521a0173d583f5e4e3b76ca..e3a2ecfbb1f00404ad400dd12aacc14376008b21 100644
--- a/myisam/mi_test2.c
+++ b/myisam/mi_test2.c
@@ -639,14 +639,14 @@ int main(int argc, char *argv[])
       if ((long) range_records < (long) records*7/10-2 ||
 	  (long) range_records > (long) records*14/10+2)
       {
-	printf("mi_records_range for key: %d returned %ld; Should be about %ld\n",
-	       i, range_records, records);
+	printf("mi_records_range for key: %d returned %lu; Should be about %lu\n",
+	       i, (ulong) range_records, (ulong) records);
 	goto end;
       }
       if (verbose && records)
       {
-	printf("mi_records_range returned %ld;  Exact is %ld  (diff: %4.2g %%)\n",
-	       range_records,records,
+	printf("mi_records_range returned %lu;  Exact is %lu  (diff: %4.2g %%)\n",
+	       (ulong) range_records, (ulong) records,
 	       labs((long) range_records-(long) records)*100.0/records);
 
       }
@@ -660,8 +660,8 @@ int main(int argc, char *argv[])
       || info.keys != keys)
   {
     puts("Wrong info from mi_info");
-    printf("Got: records: %ld  delete: %ld  i_keys: %d\n",
-	   info.records,info.deleted,info.keys);
+    printf("Got: records: %lu  delete: %lu  i_keys: %d\n",
+	   (ulong) info.records, (ulong) info.deleted, info.keys);
   }
   if (verbose)
   {
diff --git a/myisam/myisamdef.h b/myisam/myisamdef.h
index 7c035bc60974181a53814f614279d8725613f2bb..7631b245b9b2a5df5a5464d50d3b5a9da7f2defa 100644
--- a/myisam/myisamdef.h
+++ b/myisam/myisamdef.h
@@ -505,6 +505,8 @@ extern uchar *_mi_get_last_key(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *keypos,
 extern uchar *_mi_get_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page,
 			  uchar *key, uchar *keypos, uint *return_key_length);
 extern uint _mi_keylength(MI_KEYDEF *keyinfo,uchar *key);
+extern uint _mi_keylength_part(MI_KEYDEF *keyinfo, register uchar *key,
+			       MI_KEYSEG *end);
 extern uchar *_mi_move_key(MI_KEYDEF *keyinfo,uchar *to,uchar *from);
 extern int _mi_search_next(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *key,
 			   uint key_length,uint nextflag,my_off_t pos);
@@ -519,7 +521,7 @@ extern my_off_t _mi_new(MI_INFO *info,MI_KEYDEF *keyinfo);
 extern uint _mi_make_key(MI_INFO *info,uint keynr,uchar *key,
 			 const byte *record,my_off_t filepos);
 extern uint _mi_pack_key(MI_INFO *info,uint keynr,uchar *key,uchar *old,
-			 uint key_length);
+			 uint key_length, MI_KEYSEG **last_used_keyseg);
 extern int _mi_read_key_record(MI_INFO *info,my_off_t filepos,byte *buf);
 extern int _mi_read_cache(IO_CACHE *info,byte *buff,my_off_t pos,
 			  uint length,int re_read_if_possibly);
diff --git a/myisam/sort.c b/myisam/sort.c
index ddf565d5092d22108aaece03e4bab01fa5ebf230..224b4ad842081e07101079dc6b9d66fce9e99a26 100644
--- a/myisam/sort.c
+++ b/myisam/sort.c
@@ -163,8 +163,8 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages,
   if (maxbuffer == 0)
   {
     if (!no_messages)
-      printf("  - Dumping %lu keys\n",records);
-    if (write_index(info,sort_keys,(uint) records))
+      printf("  - Dumping %lu keys\n", (ulong) records);
+    if (write_index(info,sort_keys, (uint) records))
       goto err; /* purecov: inspected */
   }
   else
@@ -173,7 +173,7 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages,
     if (maxbuffer >= MERGEBUFF2)
     {
       if (!no_messages)
-	printf("  - Merging %lu keys\n",records); /* purecov: tested */
+	printf("  - Merging %lu keys\n", (ulong) records); /* purecov: tested */
       if (merge_many_buff(info,keys,sort_keys,
                   dynamic_element(&buffpek,0,BUFFPEK *),&maxbuffer,&tempfile))
 	goto err;				/* purecov: inspected */
diff --git a/mysql-test/r/ctype_latin1_de.result b/mysql-test/r/ctype_latin1_de.result
index b79bc67138c177dc7fb4b5fc7b02dd73faf89649..630fef9b679113a29cdce01441d86e38ee259acb 100644
--- a/mysql-test/r/ctype_latin1_de.result
+++ b/mysql-test/r/ctype_latin1_de.result
@@ -212,3 +212,55 @@ select * from t1 where match a against ("te*" in boolean mode)+0;
 a
 test
 drop table t1;
+create table t1 (word varchar(255) not null, word2 varchar(255) not null, index(word));
+insert into t1 (word) values ('ss'),(0xDF),(0xE4),('ae');
+update t1 set word2=word;
+select word, word=0xdf as t from t1 having t > 0;
+word	t
+ß	1
+select word, word=cast(0xdf AS CHAR) as t from t1 having t > 0;
+word	t
+ss	1
+ß	1
+select * from t1 where word=0xDF;
+word	word2
+ß	ß
+select * from t1 where word=CAST(0xDF as CHAR);
+word	word2
+ss	ss
+ß	ß
+select * from t1 where word2=0xDF;
+word	word2
+ß	ß
+select * from t1 where word2=CAST(0xDF as CHAR);
+word	word2
+ss	ss
+ß	ß
+select * from t1 where word='ae';
+word	word2
+ä	ä
+ae	ae
+select * from t1 where word= 0xe4 or word=CAST(0xe4 as CHAR);
+word	word2
+ä	ä
+ae	ae
+select * from t1 where word between 0xDF and 0xDF;
+word	word2
+ß	ß
+select * from t1 where word between CAST(0xDF AS CHAR) and CAST(0xDF AS CHAR);
+word	word2
+ss	ss
+ß	ß
+select * from t1 where word like 'ae';
+word	word2
+ae	ae
+select * from t1 where word like 'AE';
+word	word2
+ae	ae
+select * from t1 where word like 0xDF;
+word	word2
+ß	ß
+select * from t1 where word like CAST(0xDF as CHAR);
+word	word2
+ß	ß
+drop table t1;
diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result
index 1b5766e3ab45c57f41815288ddfc2fdf9a276021..e063b5c3e02004f7dd012c8b31c7ce849a19b2f4 100644
--- a/mysql-test/r/join.result
+++ b/mysql-test/r/join.result
@@ -273,8 +273,16 @@ cust	20
 SELECT emp.rate_code, lr.base_rate FROM t1 AS emp LEFT JOIN t2 AS lr USING (siteid, rate_code) WHERE lr.siteid = 'rivercats' AND emp.emp_id = 'psmith';
 rate_code	base_rate
 cust	20
+drop table t1,t2;
+CREATE TABLE t1 (ID INTEGER NOT NULL PRIMARY KEY, Value1 VARCHAR(255));
+CREATE TABLE t2 (ID INTEGER NOT NULL PRIMARY KEY, Value2 VARCHAR(255));
+INSERT INTO t1 VALUES (1, 'A');
+INSERT INTO t2 VALUES (1, 'B');
+SELECT * FROM t1 NATURAL JOIN t2 WHERE 1 AND (Value1 = 'A' AND Value2 <> 'B');
 ID	Value1	ID	Value2
+SELECT * FROM t1 NATURAL JOIN t2 WHERE 1 AND Value1 = 'A' AND Value2 <> 'B';
 ID	Value1	ID	Value2
+SELECT * FROM t1 NATURAL JOIN t2 WHERE (Value1 = 'A' AND Value2 <> 'B') AND 1;
 ID	Value1	ID	Value2
 drop table t1,t2;
 create table t1 (i int);
diff --git a/mysql-test/r/repair.result b/mysql-test/r/repair.result
index 8b50f9a92e81174a05b83fb1b9a4e9ed4bb542ae..adc09ded0e2ac14dd0fdfe79edede5ac4df13034 100644
--- a/mysql-test/r/repair.result
+++ b/mysql-test/r/repair.result
@@ -4,4 +4,8 @@ repair table t1 use_frm;
 Table	Op	Msg_type	Msg_text
 test.t1	repair	warning	Number of rows changed from 0 to 1
 test.t1	repair	status	OK
-drop table if exists t1;
+alter table t1 TYPE=HEAP;
+repair table t1 use_frm;
+Table	Op	Msg_type	Msg_text
+test.t1	repair	error	The handler for the table doesn't support repair
+drop table t1;
diff --git a/mysql-test/r/rpl_alter.result b/mysql-test/r/rpl_alter.result
index 1dc73c6524a6ca711307ec54782b4faf5b2e6a11..729c7df6808452cca04a76a3c52561d9ef8c92ac 100644
--- a/mysql-test/r/rpl_alter.result
+++ b/mysql-test/r/rpl_alter.result
@@ -4,18 +4,18 @@ reset master;
 reset slave;
 drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
 slave start;
-drop database if exists d1;
-create database d1;
-create table d1.t1 ( n int);
-alter table d1.t1 add m int;
-insert into d1.t1 values (1,2);
-create table d1.t2 (n int);
-insert into d1.t2 values (45);
-rename table d1.t2 to d1.t3, d1.t1 to d1.t2;
-select * from d1.t2;
+drop database if exists test_$1;
+create database test_$1;
+create table test_$1.t1 ( n int);
+alter table test_$1.t1 add m int;
+insert into test_$1.t1 values (1,2);
+create table test_$1.t2 (n int);
+insert into test_$1.t2 values (45);
+rename table test_$1.t2 to test_$1.t3, test_$1.t1 to test_$1.t2;
+select * from test_$1.t2;
 n	m
 1	2
-select * from d1.t3;
+select * from test_$1.t3;
 n
 45
-drop database d1;
+drop database test_$1;
diff --git a/mysql-test/t/ctype_latin1_de-master.opt b/mysql-test/t/ctype_latin1_de-master.opt
index 98accd58c462dddc11e919b46ecb563759f078c0..895a62364d62e63a189c7278854801f81162a739 100644
--- a/mysql-test/t/ctype_latin1_de-master.opt
+++ b/mysql-test/t/ctype_latin1_de-master.opt
@@ -1 +1,2 @@
---default-character-set=latin1_de
+--default-character-set=latin1_de --new
+
diff --git a/mysql-test/t/ctype_latin1_de.test b/mysql-test/t/ctype_latin1_de.test
index 4b96f5f58674e4ea368ab9be636672dcc66c0a77..6353650f420b432750d20e650611819c7147ec0f 100644
--- a/mysql-test/t/ctype_latin1_de.test
+++ b/mysql-test/t/ctype_latin1_de.test
@@ -45,3 +45,26 @@ select * from t1 where a like "test%";
 select * from t1 where a like "te_t"; 
 select * from t1 where match a against ("te*" in boolean mode)+0;
 drop table t1;
+
+#
+# Test bug report #152 (problem with index on latin1_de)
+#
+
+create table t1 (word varchar(255) not null, word2 varchar(255) not null, index(word));
+insert into t1 (word) values ('ss'),(0xDF),(0xE4),('ae');
+update t1 set word2=word;
+select word, word=0xdf as t from t1 having t > 0;
+select word, word=cast(0xdf AS CHAR) as t from t1 having t > 0;
+select * from t1 where word=0xDF;
+select * from t1 where word=CAST(0xDF as CHAR);
+select * from t1 where word2=0xDF;
+select * from t1 where word2=CAST(0xDF as CHAR);
+select * from t1 where word='ae';
+select * from t1 where word= 0xe4 or word=CAST(0xe4 as CHAR);
+select * from t1 where word between 0xDF and 0xDF;
+select * from t1 where word between CAST(0xDF AS CHAR) and CAST(0xDF AS CHAR);
+select * from t1 where word like 'ae';
+select * from t1 where word like 'AE';
+select * from t1 where word like 0xDF;
+select * from t1 where word like CAST(0xDF as CHAR);
+drop table t1;
diff --git a/mysql-test/t/repair.test b/mysql-test/t/repair.test
index 6d79014b23db50d0dd5d32bb128abb032b69a7ea..b901fb3467fc974d38ea09def7fc8d18b2fb410d 100644
--- a/mysql-test/t/repair.test
+++ b/mysql-test/t/repair.test
@@ -5,4 +5,6 @@
 drop table if exists t1;
 create table t1 SELECT 1,"table 1";
 repair table t1 use_frm;
-drop table if exists t1;
+alter table t1 TYPE=HEAP;
+repair table t1 use_frm;
+drop table t1;
diff --git a/sql/field.cc b/sql/field.cc
index eb7d3dc56864b600f823327b11d976a854d3842b..a2663626723ddc9c625c1cc4fa57471a06634539 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -162,6 +162,14 @@ static bool test_if_real(const char *str,int length)
 }
 
 
+static inline uint field_length_without_space(const char *ptr, uint length)
+{
+  const char *end= ptr+length;
+  while (end > ptr && end[-1] == ' ')
+    end--;
+  return (uint) (end-ptr);
+}
+
 /****************************************************************************
 ** Functions for the base classes
 ** This is an unpacked number.
@@ -3673,8 +3681,21 @@ int Field_string::cmp(const char *a_ptr, const char *b_ptr)
 {
   if (binary_flag)
     return memcmp(a_ptr,b_ptr,field_length);
-  else
-    return my_sortcmp(a_ptr,b_ptr,field_length);
+#ifdef USE_STRCOLL
+  if (use_strcoll(default_charset_info))
+  {
+    /*
+      We have to remove end space to be able to compare multi-byte-characters
+      like in latin_de 'ae' and 0xe4
+    */
+    uint a_length= field_length_without_space(a_ptr, field_length);
+    uint b_length= field_length_without_space(b_ptr, field_length);
+    return my_strnncoll(default_charset_info,
+			(const uchar*) a_ptr, a_length,
+			(const uchar*) b_ptr, b_length);
+  }
+#endif
+  return my_sortcmp(a_ptr,b_ptr,field_length);
 }
 
 void Field_string::sort_string(char *to,uint length)
diff --git a/sql/item.cc b/sql/item.cc
index 4fefae7358fe83461c2aafc89b8b802ad0b386b4..79501755cbf01bd5b3949b2ab64a60ed3efc24b1 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -576,6 +576,14 @@ inline uint char_val(char X)
 		 X-'a'+10);
 }
 
+/* In MySQL 4.1 this will always return STRING_RESULT */
+
+enum Item_result Item_varbinary::result_type () const
+{
+  return (current_thd->variables.new_mode) ? STRING_RESULT : INT_RESULT;
+}
+
+
 Item_varbinary::Item_varbinary(const char *str, uint str_length)
 {
   name=(char*) str-2;				// Lex makes this start with 0x
diff --git a/sql/item.h b/sql/item.h
index 5e2c2ccc05659aba9944dfea7a6055ec4dee6342..09d428509d053073bb3a0a3fdbc359a3ce3333cb 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -353,7 +353,7 @@ class Item_varbinary :public Item
   String *val_str(String*) { return &str_value; }
   bool save_in_field(Field *field, bool no_conversions);
   void make_field(Send_field *field);
-  enum Item_result result_type () const { return INT_RESULT; }
+  enum Item_result result_type () const;
   unsigned int size_of() { return sizeof(*this);}  
 };
 
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index fc2baf5784c5763563a747342eab6dd1b7924c07..2799bdf9f541cfb5a910377266502abfae52765b 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -204,12 +204,12 @@ static char **opt_argv;
 #ifdef __WIN__
 #undef MYSQL_SERVER_SUFFIX
 #ifdef __NT__
-#if defined(HAVE_INNOBASE_DB) || defined(HAVE_BERKELEY_DB)
+#if defined(HAVE_BERKELEY_DB)
 #define MYSQL_SERVER_SUFFIX "-max-nt"
 #else
 #define MYSQL_SERVER_SUFFIX "-nt"
 #endif /* ...DB */
-#elif defined(HAVE_INNOBASE_DB) || defined(HAVE_BERKELEY_DB)
+#elif defined(HAVE_BERKELEY_DB)
 #define MYSQL_SERVER_SUFFIX "-max"
 #else
 #define MYSQL_SERVER_SUFFIX ""
diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc
index 5d3f9a0595cc7eb8b282360295430372302976ce..d6abe6497dfb860a312f76b7a9c1a72605598760 100644
--- a/sql/sql_analyse.cc
+++ b/sql/sql_analyse.cc
@@ -284,7 +284,6 @@ void field_str::add()
   char buff[MAX_FIELD_WIDTH], *ptr;
   String s(buff, sizeof(buff)), *res;
   ulong length;
-  TREE_ELEMENT *element;
 
   if (!(res = item->val_str(&s)))
   {
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 0379c1de287c536fdc3aece0c620212e1c9ff29e..e02f457fd773e455173a19a645ea7577a2d90f95 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1029,7 +1029,7 @@ extern "C" pthread_handler_decl(handle_delayed_insert,arg)
 #else
 	error=pthread_cond_timedwait(&di->cond,&di->mutex,&abstime);
 #ifdef EXTRA_DEBUG
-	if (error && error != EINTR)
+	if (error && error != EINTR && error != ETIMEDOUT)
 	{
 	  fprintf(stderr, "Got error %d from pthread_cond_timedwait\n",error);
 	  DBUG_PRINT("error",("Got error %d from pthread_cond_timedwait",
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index d670c673b4acd327a98c966c98fcd8d419a5477c..283dd20a56c128e573a64afe5496014097cdb813 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -1042,6 +1042,9 @@ int show_binlog_events(THD* thd)
   }
 
   send_eof(&thd->net);
+  pthread_mutex_lock(&LOCK_thread_count);
+  thd->current_linfo = 0;
+  pthread_mutex_unlock(&LOCK_thread_count);
   DBUG_RETURN(0);
 }
 
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index f870f8f5178064c5a3718ad1f125faf87b7621dd..79ba13a3339d621450867489bbbf8c6bef8c02f0 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -2631,6 +2631,9 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
 					join->thd->select_limit)) < 0)
 	      DBUG_RETURN(1);				// Impossible range
 	    sel->cond=orig_cond;
+	    /* Fix for EXPLAIN */
+	    if (sel->quick)
+	      join->best_positions[i].records_read= sel->quick->records;
 	  }
 	  else
 	  {
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 0fbb5807c57a8cbe347234e15a81b259d6373805..1b1b5112e0bb903ff398e6e5bd407b779d232dab 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -23,6 +23,7 @@
 #endif
 #include <hash.h>
 #include <myisam.h>
+#include <my_dir.h>
 #include <assert.h>
 
 #ifdef __WIN__
@@ -1046,12 +1047,31 @@ static int prepare_for_repair(THD* thd, TABLE_LIST* table,
   }
   else
   {
+    /*
+      User gave us USE_FRM which means that the header in the index file is
+      trashed.
+      In this case we will try to fix the table the following way:
+      - Rename the data file to a temporary name
+      - Truncate the table
+      - Replace the new data file with the old one
+      - Run a normal repair using the new index file and the old data file
+    */
 
-    char from[FN_REFLEN],tmp[FN_REFLEN];
-    char* db = thd->db ? thd->db : table->db;
+    char from[FN_REFLEN],tmp[FN_REFLEN+32];
+    const char **ext= table->table->file->bas_ext();
+    MY_STAT stat_info;
+
+    /*
+      Check if this is a table type that stores index and data separately,
+      like ISAM or MyISAM
+    */
+    if (!ext[0] || !ext[1])
+      DBUG_RETURN(0);				// No data file
+
+    strxmov(from, table->table->path, ext[1], NullS);	// Name of data file
+    if (!my_stat(from, &stat_info, MYF(0)))
+      DBUG_RETURN(0);				// Can't use USE_FRM flag
 
-    sprintf(from, "%s/%s/%s", mysql_real_data_home, db, table->real_name);
-    fn_format(from, from, "", MI_NAME_DEXT, 4);
     sprintf(tmp,"%s-%lx_%lx", from, current_pid, thd->thread_id);
 
     pthread_mutex_lock(&LOCK_open);
@@ -1067,7 +1087,7 @@ static int prepare_for_repair(THD* thd, TABLE_LIST* table,
       unlock_table_name(thd, table);
       pthread_mutex_unlock(&LOCK_open);
       DBUG_RETURN(send_check_errmsg(thd, table, "repair",
-				    "Failed renaming .MYD file"));
+				    "Failed renaming data file"));
     }
     if (mysql_truncate(thd, table, 1))
     {
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index d7a0c15e9b965f044cf79821789d44af607ba26b..f895c809366c541b94cd067dd428e299593b3934 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -2310,16 +2310,12 @@ olap_opt:
 	| WITH CUBE_SYM
           {
 	    LEX *lex=Lex;
-	    lex->olap = true;
-	    lex->select->olap= CUBE_TYPE;
 	    net_printf(&lex->thd->net, ER_NOT_SUPPORTED_YET, "CUBE");
 	    YYABORT;	/* To be deleted in 4.1 */
 	  }
 	| WITH ROLLUP_SYM
           {
 	    LEX *lex=Lex;
-	    lex->olap = true;
-	    lex->select->olap= ROLLUP_TYPE;
 	    net_printf(&lex->thd->net, ER_NOT_SUPPORTED_YET, "ROLLUP");
 	    YYABORT;	/* To be deleted in 4.1 */
 	  }
@@ -2407,7 +2403,7 @@ delete_limit_clause:
 
 ULONG_NUM:
 	NUM	    { $$= strtoul($1.str,NULL,10); }
-	| LONG_NUM  { $$= (ulonglong) strtoll($1.str,NULL,10); }
+	| LONG_NUM  { $$= (ulong) strtoll($1.str,NULL,10); }
 	| ULONGLONG_NUM { $$= (ulong) strtoull($1.str,NULL,10); }
 	| REAL_NUM  { $$= strtoul($1.str,NULL,10); }
 	| FLOAT_NUM { $$= strtoul($1.str,NULL,10); };