List:Internals« Previous MessageNext Message »
From:monty Date:December 6 2004 6:18pm
Subject:bk commit into 5.0 tree (monty:1.1720)
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of monty. When monty does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://www.mysql.com/doc/I/n/Installing_source_tree.html

ChangeSet
  1.1720 04/12/06 19:18:35 monty@stripped +83 -0
  Merge with new VARCHAR code

  strings/ctype-ucs2.c
    1.34 04/12/06 19:18:30 monty@stripped +4 -4
    Added new argument to my_strnncollsp_ucs2()
    Simply code

  strings/ctype-tis620.c
    1.79 04/12/06 19:18:30 monty@stripped +2 -3
    Merge with VARCHAR code

  strings/ctype-mb.c
    1.35 04/12/06 19:18:30 monty@stripped +0 -3
    Don't pad my_like_range with max_str for simple LIKE expression

  sql/table.h
    1.79 04/12/06 19:18:30 monty@stripped +1 -1
    Merge with VARCHAR code

  sql/sql_update.cc
    1.132 04/12/06 19:18:30 monty@stripped +0 -0
    Merge with VARCHAR code

  sql/sql_table.cc
    1.200 04/12/06 19:18:30 monty@stripped +0 -1
    Merge with VARCHAR code

  sql/sql_parse.cc
    1.374 04/12/06 19:18:30 monty@stripped +4 -12
    Merge with VARCHAR code

  sql/sql_acl.cc
    1.115 04/12/06 19:18:30 monty@stripped +35 -51
    Merge with VARCHAR code

  sql/item.cc
    1.98 04/12/06 19:18:30 monty@stripped +0 -9
    Merge with VARCHAR code

  sql/field.cc
    1.207 04/12/06 19:18:30 monty@stripped +2 -4
    Merge with VARCHAR code

  mysql-test/t/innodb.test
    1.68 04/12/06 19:18:30 monty@stripped +8 -8
    Merge with VARCHAR code

  mysql-test/t/heap.test
    1.20 04/12/06 19:18:30 monty@stripped +21 -21
    Merge with VARCHAR code

  mysql-test/t/bdb.test
    1.41 04/12/06 19:18:30 monty@stripped +9 -9
    Merge with VARCHAR code

  mysql-test/r/select.result.es
    1.3 04/12/06 19:18:30 monty@stripped +1 -1
    Merge with VARCHAR code

  mysql-test/r/innodb.result
    1.85 04/12/06 19:18:30 monty@stripped +2 -2
    Merge with VARCHAR code

  mysql-test/r/heap.result
    1.27 04/12/06 19:18:30 monty@stripped +16 -16
    Merge with VARCHAR code

  mysql-test/r/bdb.result
    1.35 04/12/06 19:18:30 monty@stripped +7 -7
    Merge with VARCHAR code

  tests/client_test.c
    1.83 04/12/06 18:04:41 monty@stripped +0 -0
    Auto merged

  strings/decimal.c
    1.32 04/12/06 18:04:40 monty@stripped +0 -0
    Auto merged

  strings/ctype-win1250ch.c
    1.43 04/12/06 18:04:40 monty@stripped +0 -0
    Auto merged

  strings/ctype-utf8.c
    1.79 04/12/06 18:04:40 monty@stripped +0 -0
    Auto merged

  strings/ctype-uca.c
    1.27 04/12/06 18:04:40 monty@stripped +0 -0
    Auto merged

  strings/ctype-czech.c
    1.53 04/12/06 18:04:40 monty@stripped +0 -0
    Auto merged

  sql/table.cc
    1.131 04/12/06 18:04:40 monty@stripped +0 -0
    Auto merged

  sql/structs.h
    1.42 04/12/06 18:04:40 monty@stripped +0 -0
    Auto merged

  sql/sql_yacc.yy
    1.316 04/12/06 18:04:40 monty@stripped +0 -0
    Auto merged

  sql/sql_select.cc
    1.261 04/12/06 18:04:39 monty@stripped +2 -3
    Auto merged

  sql/sql_help.cc
    1.37 04/12/06 18:04:39 monty@stripped +0 -0
    Auto merged

  sql/sql_base.cc
    1.196 04/12/06 18:04:39 monty@stripped +0 -0
    Auto merged

  sql/protocol.cc
    1.86 04/12/06 18:04:39 monty@stripped +0 -0
    Auto merged

  sql/opt_sum.cc
    1.40 04/12/06 18:04:39 monty@stripped +0 -0
    Auto merged

  sql/opt_range.cc
    1.132 04/12/06 18:04:39 monty@stripped +0 -0
    Auto merged

  sql/item_sum.cc
    1.111 04/12/06 18:04:39 monty@stripped +0 -0
    Auto merged

  sql/item_cmpfunc.cc
    1.128 04/12/06 18:04:38 monty@stripped +0 -0
    Auto merged

  sql/handler.h
    1.114 04/12/06 18:04:38 monty@stripped +0 -0
    Auto merged

  sql/ha_ndbcluster.cc
    1.121 04/12/06 18:04:38 monty@stripped +0 -0
    Auto merged

  sql/ha_myisam.cc
    1.138 04/12/06 18:04:38 monty@stripped +0 -0
    Auto merged

  sql/ha_innodb.h
    1.73 04/12/06 18:04:38 monty@stripped +0 -0
    Auto merged

  sql/ha_innodb.cc
    1.128 04/12/06 18:04:38 monty@stripped +0 -0
    Auto merged

  sql/ha_heap.cc
    1.50 04/12/06 18:04:38 monty@stripped +0 -0
    Auto merged

  sql/field_conv.cc
    1.35 04/12/06 18:04:38 monty@stripped +0 -0
    Auto merged

  sql/field.h
    1.124 04/12/06 18:04:38 monty@stripped +0 -0
    Auto merged

  scripts/mysql_fix_privilege_tables.sh
    1.31 04/12/06 18:04:38 monty@stripped +0 -0
    Auto merged

  ndb/src/common/util/NdbSqlUtil.cpp
    1.12 04/12/06 18:04:38 monty@stripped +0 -0
    Auto merged

  mysql-test/t/type_blob.test
    1.24 04/12/06 18:04:38 monty@stripped +0 -0
    Auto merged

  mysql-test/t/strict.test
    1.7 04/12/06 18:04:38 monty@stripped +0 -0
    Auto merged

  mysql-test/t/ps_1general.test
    1.9 04/12/06 18:04:38 monty@stripped +0 -0
    Auto merged

  mysql-test/t/myisam.test
    1.36 04/12/06 18:04:38 monty@stripped +0 -0
    Auto merged

  mysql-test/t/endspace.test
    1.4 04/12/06 18:04:37 monty@stripped +0 -0
    Auto merged

  mysql-test/t/ctype_ucs.test
    1.18 04/12/06 18:04:37 monty@stripped +0 -0
    Auto merged

  mysql-test/r/type_blob.result
    1.43 04/12/06 18:04:37 monty@stripped +0 -0
    Auto merged

  mysql-test/r/subselect.result
    1.93 04/12/06 18:04:37 monty@stripped +0 -0
    Auto merged

  mysql-test/r/strict.result
    1.10 04/12/06 18:04:37 monty@stripped +0 -0
    Auto merged

  mysql-test/r/select.result
    1.44 04/12/06 18:04:37 monty@stripped +0 -0
    Auto merged

  mysql-test/r/ps_6bdb.result
    1.12 04/12/06 18:04:37 monty@stripped +0 -0
    Auto merged

  mysql-test/r/ps_5merge.result
    1.12 04/12/06 18:04:37 monty@stripped +0 -0
    Auto merged

  mysql-test/r/ps_4heap.result
    1.11 04/12/06 18:04:37 monty@stripped +0 -0
    Auto merged

  mysql-test/r/ps_3innodb.result
    1.14 04/12/06 18:04:37 monty@stripped +0 -0
    Auto merged

  mysql-test/r/ps_2myisam.result
    1.12 04/12/06 18:04:37 monty@stripped +0 -0
    Auto merged

  mysql-test/r/ps_1general.result
    1.15 04/12/06 18:04:37 monty@stripped +0 -0
    Auto merged

  mysql-test/r/ps.result
    1.34 04/12/06 18:04:37 monty@stripped +0 -0
    Auto merged

  mysql-test/r/order_by.result
    1.46 04/12/06 18:04:37 monty@stripped +0 -0
    Auto merged

  mysql-test/r/mysqldump.result
    1.24 04/12/06 18:04:37 monty@stripped +0 -0
    Auto merged

  mysql-test/r/myisam.result
    1.48 04/12/06 18:04:37 monty@stripped +0 -0
    Auto merged

  mysql-test/r/ctype_ucs.result
    1.18 04/12/06 18:04:36 monty@stripped +0 -0
    Auto merged

  mysql-test/r/ctype_tis620.result
    1.8 04/12/06 18:04:36 monty@stripped +0 -0
    Auto merged

  myisam/mi_write.c
    1.47 04/12/06 18:04:36 monty@stripped +0 -0
    Auto merged

  myisam/mi_create.c
    1.38 04/12/06 18:04:36 monty@stripped +0 -0
    Auto merged

  myisam/mi_check.c
    1.126 04/12/06 18:04:36 monty@stripped +0 -0
    Auto merged

  libmysqld/Makefile.am
    1.49 04/12/06 18:04:36 monty@stripped +0 -0
    Auto merged

  libmysql/libmysql.c
    1.180 04/12/06 18:04:36 monty@stripped +0 -0
    Auto merged

  include/m_ctype.h
    1.103 04/12/06 18:04:36 monty@stripped +0 -0
    Auto merged

  include/decimal.h
    1.10 04/12/06 18:04:36 monty@stripped +0 -0
    Auto merged

  heap/hp_write.c
    1.20 04/12/06 18:04:36 monty@stripped +0 -0
    Auto merged

  heap/hp_hash.c
    1.37 04/12/06 18:04:36 monty@stripped +0 -0
    Auto merged

  heap/hp_delete.c
    1.13 04/12/06 18:04:36 monty@stripped +0 -0
    Auto merged

  heap/hp_create.c
    1.15 04/12/06 18:04:36 monty@stripped +0 -0
    Auto merged

  client/mysqltest.c
    1.122 04/12/06 18:04:36 monty@stripped +0 -0
    Auto merged

  client/mysqldump.c
    1.157 04/12/06 18:04:36 monty@stripped +0 -0
    Auto merged

  BitKeeper/deleted/.del-ha_isammrg.cc~dc682e4755d77a2e
    1.21 04/12/06 18:04:36 monty@stripped +0 -0
    Auto merged

  BitKeeper/deleted/.del-ha_isam.cc~4dce65904db2675e
    1.36 04/12/06 18:04:35 monty@stripped +0 -0
    Auto merged

  BitKeeper/deleted/.del-acinclude.m4~f4ab416bac5003
    1.125 04/12/06 18:04:35 monty@stripped +0 -0
    Auto merged

  configure.in
    1.235 04/12/06 18:04:35 monty@stripped +0 -0
    Auto merged

  BitKeeper/deleted/.del-ha_isammrg.cc~dc682e4755d77a2e
    1.20 04/12/06 18:04:35 monty@stripped +0 -0
    Merge rename: sql/ha_isammrg.cc ->
BitKeeper/deleted/.del-ha_isammrg.cc~dc682e4755d77a2e

  BitKeeper/deleted/.del-ha_isam.cc~4dce65904db2675e
    1.35 04/12/06 18:04:35 monty@stripped +0 -0
    Merge rename: sql/ha_isam.cc -> BitKeeper/deleted/.del-ha_isam.cc~4dce65904db2675e

  BitKeeper/deleted/.del-acinclude.m4~f4ab416bac5003
    1.119.1.2 04/12/06 18:04:35 monty@stripped +0 -0
    Merge rename: acinclude.m4 -> BitKeeper/deleted/.del-acinclude.m4~f4ab416bac5003

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	monty
# Host:	narttu.mysql.fi
# Root:	/home/my/mysql-5.0/RESYNC

--- 1.119.1.1/acinclude.m4	2004-12-06 01:59:52 +02:00
+++ 1.125/BitKeeper/deleted/.del-acinclude.m4~f4ab416bac5003	2004-12-06 18:04:35 +02:00
@@ -1597,9 +1597,14 @@
   --with-ndb-docs       Include the NDB Cluster ndbapi and mgmapi documentation],
               [ndb_docs="$withval"],
               [ndb_docs=no])
+  AC_ARG_WITH([ndb-port],
+              [
+  --with-ndb-port       Port for NDB Cluster management server],
+              [ndb_port="$withval"],
+              [ndb_port="default"])
   AC_ARG_WITH([ndb-port-base],
               [
-  --with-ndb-port-base  Base port for NDB Cluster],
+  --with-ndb-port-base  Base port for NDB Cluster transporters],
               [ndb_port_base="$withval"],
               [ndb_port_base="default"])
                                                                                 
@@ -1656,6 +1661,7 @@
   have_ndbcluster=no
   ndbcluster_includes=
   ndbcluster_libs=
+  ndb_mgmclient_libs=
   case "$ndbcluster" in
     yes )
       AC_MSG_RESULT([Using NDB Cluster])
@@ -1664,6 +1670,7 @@
       ndbcluster_includes="-I../ndb/include -I../ndb/include/ndbapi"
       ndbcluster_libs="\$(top_builddir)/ndb/src/.libs/libndbclient.a"
       ndbcluster_system_libs=""
+      ndb_mgmclient_libs="\$(top_builddir)/ndb/src/mgmclient/libndbmgmclient.la"
       MYSQL_CHECK_NDB_OPTIONS
       ;;
     * )
@@ -1675,6 +1682,7 @@
   AC_SUBST(ndbcluster_includes)
   AC_SUBST(ndbcluster_libs)
   AC_SUBST(ndbcluster_system_libs)
+  AC_SUBST(ndb_mgmclient_libs)
 ])
                                                                                 
 dnl ---------------------------------------------------------------------------

--- 1.156/client/mysqldump.c	2004-12-06 11:38:51 +02:00
+++ 1.157/client/mysqldump.c	2004-12-06 18:04:36 +02:00
@@ -1623,12 +1623,13 @@
 	   we'll dump in hex only BLOB columns.
 	*/
         is_blob= (opt_hex_blob && field->charsetnr == 63 &&
-                  (field->type == FIELD_TYPE_STRING ||
-                   field->type == FIELD_TYPE_VAR_STRING ||
-                   field->type == FIELD_TYPE_BLOB ||
-                   field->type == FIELD_TYPE_LONG_BLOB ||
-                   field->type == FIELD_TYPE_MEDIUM_BLOB ||
-                   field->type == FIELD_TYPE_TINY_BLOB)) ? 1 : 0;
+                  (field->type == MYSQL_TYPE_STRING ||
+                   field->type == MYSQL_TYPE_VAR_STRING ||
+                   field->type == MYSQL_TYPE_VARCHAR ||
+                   field->type == MYSQL_TYPE_BLOB ||
+                   field->type == MYSQL_TYPE_LONG_BLOB ||
+                   field->type == MYSQL_TYPE_MEDIUM_BLOB ||
+                   field->type == MYSQL_TYPE_TINY_BLOB)) ? 1 : 0;
 	if (extended_insert)
 	{
 	  ulong length = lengths[i];

--- 1.234/configure.in	2004-12-06 02:05:20 +02:00
+++ 1.235/configure.in	2004-12-06 18:04:35 +02:00
@@ -2420,7 +2420,6 @@
 AC_SUBST(readline_link)
 AC_SUBST(readline_h_ln_cmd)
 
-MYSQL_CHECK_ISAM
 MYSQL_CHECK_BDB
 MYSQL_CHECK_INNODB
 MYSQL_CHECK_EXAMPLEDB
@@ -2480,12 +2479,6 @@
   #
   # Configuration for optional table handlers
   #
-
-  if test X"$have_isam" != Xno
-  then
-    sql_server_dirs="$sql_server_dirs isam merge"
-    AC_CONFIG_FILES(isam/Makefile merge/Makefile)
-  fi
 
   if test X"$have_berkeley_db" != Xno; then
     if test X"$have_berkeley_db" != Xyes; then

--- 1.14/heap/hp_create.c	2004-12-02 13:06:11 +02:00
+++ 1.15/heap/hp_create.c	2004-12-06 18:04:36 +02:00
@@ -76,9 +76,21 @@
 	case HA_KEYTYPE_UINT24:
 	case HA_KEYTYPE_INT8:
 	  keyinfo->seg[j].flag|= HA_SWAP_KEY;
+          break;
+        case HA_KEYTYPE_VARBINARY:
+          /* Case-insensitiveness is handled in coll->hash_sort */
+          keyinfo->seg[j].type= HA_KEYTYPE_VARTEXT;
+          /* fall_through */
+        case HA_KEYTYPE_VARTEXT:
+          if (!my_binary_compare(keyinfo->seg[j].charset))
+            keyinfo->flag|= HA_END_SPACE_KEY;
+          keyinfo->flag|= HA_VAR_LENGTH_KEY;
+          break;
 	default:
 	  break;
 	}
+        if (keyinfo->seg[j].flag & HA_END_SPACE_ARE_EQUAL)
+          keyinfo->flag|= HA_END_SPACE_KEY;
       }
       keyinfo->length= length;
       length+= keyinfo->rb_tree.size_of_element + 
@@ -89,7 +101,9 @@
       if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
       {
         key_segs++; /* additional HA_KEYTYPE_END segment */
-        if (keyinfo->flag & HA_NULL_PART_KEY)
+        if (keyinfo->flag & HA_VAR_LENGTH_KEY)
+          keyinfo->get_key_length= hp_rb_var_key_length;
+        else if (keyinfo->flag & HA_NULL_PART_KEY)
           keyinfo->get_key_length= hp_rb_null_key_length;
         else
           keyinfo->get_key_length= hp_rb_key_length;

--- 1.12/heap/hp_delete.c	2004-10-12 17:21:20 +03:00
+++ 1.13/heap/hp_delete.c	2004-12-06 18:04:36 +02:00
@@ -123,7 +123,7 @@
 
   while (pos->ptr_to_rec != recpos)
   {
-    if (flag && !hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec))
+    if (flag && !hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec, 0))
       last_ptr=pos;				/* Previous same key */
     gpos=pos;
     if (!(pos=pos->next_key))

--- 1.36/heap/hp_hash.c	2004-11-16 20:36:27 +02:00
+++ 1.37/heap/hp_hash.c	2004-12-06 18:04:36 +02:00
@@ -262,14 +262,27 @@
     if (seg->type == HA_KEYTYPE_TEXT)
     {
        CHARSET_INFO *cs= seg->charset;
-       uint char_length= (uint) ((uchar*) key - pos);
+       uint length= seg->length;
        if (cs->mbmaxlen > 1)
        {
-         uint length= char_length;
+         uint char_length;
          char_length= my_charpos(cs, pos, pos + length, length/cs->mbmaxlen);
-         set_if_smaller(char_length, length);   /* QQ: ok to remove? */
+         set_if_smaller(length, char_length);
        }
-       cs->coll->hash_sort(cs, pos, char_length, &nr, &nr2);
+       cs->coll->hash_sort(cs, pos, length, &nr, &nr2);
+    }
+    else if (seg->type == HA_KEYTYPE_VARTEXT)
+    {
+       CHARSET_INFO *cs= seg->charset;
+       uint length= uint2korr(pos);
+       if (cs->mbmaxlen > 1)
+       {
+         uint char_length;
+         char_length= my_charpos(cs, pos +2, pos +2 + length,
+                                 seg->length/cs->mbmaxlen);
+         set_if_smaller(length, char_length);
+       }
+       cs->coll->hash_sort(cs, pos+2, length, &nr, &nr2);
     }
     else
     {
@@ -314,6 +327,19 @@
       }
       cs->coll->hash_sort(cs, pos, char_length, &nr, &nr2);
     }
+    else if (seg->type == HA_KEYTYPE_VARTEXT)
+    {
+      CHARSET_INFO *cs= seg->charset;
+      uint length= uint2korr(pos);
+      if (cs->mbmaxlen > 1)
+      {
+        uint char_length;
+        char_length= my_charpos(cs, pos + 2 , pos + 2 + length,
+                                seg->length/cs->mbmaxlen);
+        set_if_smaller(length, char_length);
+      }
+      cs->coll->hash_sort(cs, pos+2, length, &nr, &nr2);
+    }
     else
     {
       for (; pos < end ; pos++)
@@ -366,6 +392,11 @@
     {
       seg->charset->hash_sort(seg->charset,pos,((uchar*)key)-pos,&nr,NULL);
     }
+    else if (seg->type == HA_KEYTYPE_VARTEXT)
+    {
+      uint length= uint2korr(pos);
+      seg->charset->hash_sort(seg->charset, pos+2, length, &nr, NULL);
+    }
     else
     {
       for ( ; pos < (uchar*) key ; pos++)
@@ -400,6 +431,11 @@
     {
       seg->charset->hash_sort(seg->charset,pos,((uchar*)key)-pos,&nr,NULL);
     }
+    else if (seg->type == HA_KEYTYPE_VARTEXT)
+    {
+      uint length= uint2korr(pos);
+      seg->charset->hash_sort(seg->charset, pos+2, length, &nr, NULL);
+    }
     else
     {
       for ( ; pos < end ; pos++)
@@ -415,9 +451,28 @@
 #endif
 
 
-	/* Compare keys for two records. Returns 0 if they are identical */
+/*
+  Compare keys for two records. Returns 0 if they are identical
+
+  SYNOPSIS
+    hp_rec_key_cmp()
+    keydef		Key definition
+    rec1		Record to compare
+    rec2		Other record to compare
+    diff_if_only_endspace_difference
+			Different number of end space is significant    
+
+  NOTES
+    diff_if_only_endspace_difference is used to allow us to insert
+    'a' and 'a ' when there is an an unique key.
+
+  RETURN
+    0		Key is identical
+    <> 0 	Key differes
+*/
 
-int hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
+int hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2,
+                   my_bool diff_if_only_endspace_difference)
 {
   HA_KEYSEG *seg,*endseg;
 
@@ -442,9 +497,9 @@
       {
         uint char_length= seg->length / cs->mbmaxlen;
         char_length1= my_charpos(cs, pos1, pos1 + seg->length, char_length);
-        set_if_smaller(char_length1, seg->length); /* QQ: ok to remove? */
+        set_if_smaller(char_length1, seg->length);
         char_length2= my_charpos(cs, pos2, pos2 + seg->length, char_length);
-        set_if_smaller(char_length2, seg->length); /* QQ: ok to remove? */
+        set_if_smaller(char_length2, seg->length);
       }
       else
       {
@@ -452,7 +507,30 @@
       }
       if (seg->charset->coll->strnncollsp(seg->charset,
       					  pos1,char_length1,
-					  pos2,char_length2))
+					  pos2,char_length2, 0))
+	return 1;
+    }
+    else if (seg->type == HA_KEYTYPE_VARTEXT)
+    {
+      uchar *pos1= (uchar*)rec1 + seg->start;
+      uchar *pos2= (uchar*)rec2 + seg->start;
+      uint char_length1= uint2korr(pos1);
+      uint char_length2= uint2korr(pos2);
+      CHARSET_INFO *cs= seg->charset;
+      if (cs->mbmaxlen > 1)
+      {
+        uint char_length= seg->length / cs->mbmaxlen;
+        char_length1= my_charpos(cs, pos1, pos1 + char_length1, char_length);
+        set_if_smaller(char_length1, seg->length);
+        char_length2= my_charpos(cs, pos2, pos2 + char_length2, char_length);
+        set_if_smaller(char_length2, seg->length);
+      }
+
+      if (cs->coll->strnncollsp(seg->charset,
+                                pos1+2, char_length1,
+                                pos2+2, char_length2,
+                                seg->flag & HA_END_SPACE_ARE_EQUAL ?
+                                0 : diff_if_only_endspace_difference))
 	return 1;
     }
     else
@@ -504,7 +582,31 @@
       
       if (seg->charset->coll->strnncollsp(seg->charset,
 					  (uchar*) pos, char_length_rec,
-					  (uchar*) key, char_length_key))
+					  (uchar*) key, char_length_key, 0))
+	return 1;
+    }
+    else if (seg->type == HA_KEYTYPE_VARTEXT)
+    {
+      uchar *pos= (uchar*) rec + seg->start;
+      CHARSET_INFO *cs= seg->charset;
+      uint char_length_rec= uint2korr(pos);
+      uint char_length_key= uint2korr(key);
+
+      if (cs->mbmaxlen > 1)
+      {
+        uint char_length= seg->length / cs->mbmaxlen;
+        char_length_key= my_charpos(cs, key+2, key +2 + char_length_key,
+                                    char_length);
+        set_if_smaller(char_length_key, seg->length);
+        char_length_rec= my_charpos(cs, pos +2 , pos + 2 + char_length_rec,
+                                    char_length);
+        set_if_smaller(char_length_rec, seg->length);
+      }
+
+
+      if (cs->coll->strnncollsp(seg->charset,
+                                (uchar*) pos+2, char_length_rec,
+                                (uchar*) key+2, char_length_key, 0))
 	return 1;
     }
     else
@@ -541,6 +643,13 @@
   }
 }
 
+#define FIX_LENGTH(cs, pos, length, char_length)                        \
+  do {                                                                  \
+    if (length > char_length)                                           \
+      char_length= my_charpos(cs, pos, pos+length, char_length);        \
+    set_if_smaller(char_length,length);                                 \
+  } while(0)
+
 
 uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key, 
 		    const byte *rec, byte *recpos)
@@ -593,6 +702,24 @@
       }
       continue;
     }
+
+    if (seg->flag & HA_VAR_LENGTH_PART)
+    {
+      uchar *pos=      (uchar*) rec + seg->start;
+      uint length=     seg->length;
+      uint tmp_length= uint2korr(pos);
+      CHARSET_INFO *cs= seg->charset;
+      char_length= length/cs->mbmaxlen;
+
+      pos+=2;					/* Skip VARCHAR length */
+      set_if_smaller(length,tmp_length);
+      FIX_LENGTH(cs, pos, length, char_length);
+      store_key_length_inc(key,char_length);
+      memcpy((byte*) key,(byte*) pos,(size_t) char_length);
+      key+= char_length;
+      continue;
+    }
+
     char_length= seg->length;
     if (seg->charset->mbmaxlen > 1)
     {
@@ -643,6 +770,23 @@
       }
       continue;
     }
+    if (seg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
+    {
+      /* Length of key-part used with heap_rkey() always 2 */
+      uint tmp_length=uint2korr(old);
+      uint length= seg->length;
+      CHARSET_INFO *cs= seg->charset;
+      char_length= length/cs->mbmaxlen;
+
+      k_len-= 2+length;
+      old+= 2;
+      set_if_smaller(length,tmp_length);	/* Safety */
+      FIX_LENGTH(cs, old, length, char_length);
+      store_key_length_inc(key,char_length);
+      memcpy((byte*) key, old,(size_t) char_length);
+      key+= char_length;
+      continue;
+    }
     char_length= seg->length;
     if (seg->charset->mbmaxlen > 1)
     {
@@ -682,6 +826,27 @@
   return key - start_key;
 }
                   
+
+uint hp_rb_var_key_length(HP_KEYDEF *keydef, const byte *key)
+{
+  const byte *start_key= key;
+  HA_KEYSEG *seg, *endseg;
+  
+  for (seg= keydef->seg, endseg= seg + keydef->keysegs; seg < endseg; seg++)
+  {
+    uint length= seg->length;
+    if (seg->null_bit && !*key++)
+      continue;
+    if (seg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
+    {
+      get_key_length(length, key);
+    }
+    key+= length;
+  }
+  return key - start_key;
+}
+
+
 /*
   Test if any of the key parts are NULL.
   Return:

--- 1.19/heap/hp_write.c	2004-10-12 17:21:20 +03:00
+++ 1.20/heap/hp_write.c	2004-12-06 18:04:36 +02:00
@@ -105,7 +105,7 @@
   custom_arg.key_length= hp_rb_make_key(keyinfo, info->recbuf, record, recpos);
   if (keyinfo->flag & HA_NOSAME)
   {
-    custom_arg.search_flag= SEARCH_FIND | SEARCH_SAME;
+    custom_arg.search_flag= SEARCH_FIND | SEARCH_SAME | SEARCH_UPDATE;
     keyinfo->rb_tree.flag= TREE_NO_DUPS;
   }
   else
@@ -369,7 +369,7 @@
       pos=empty;
       do
       {
-	if (! hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec))
+	if (! hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec, 1))
 	{
 	  DBUG_RETURN(my_errno=HA_ERR_FOUND_DUPP_KEY);
 	}

--- 1.102/include/m_ctype.h	2004-11-22 09:58:35 +02:00
+++ 1.103/include/m_ctype.h	2004-12-06 18:04:36 +02:00
@@ -106,7 +106,8 @@
   int     (*strnncoll)(struct charset_info_st *,
 		       const uchar *, uint, const uchar *, uint, my_bool);
   int     (*strnncollsp)(struct charset_info_st *,
-		       const uchar *, uint, const uchar *, uint);
+                         const uchar *, uint, const uchar *, uint,
+                         my_bool diff_if_only_endspace_difference);
   int     (*strnxfrm)(struct charset_info_st *,
 		      uchar *, uint, const uchar *, uint);
   my_bool (*like_range)(struct charset_info_st *,
@@ -259,7 +260,8 @@
 				const uchar *, uint, my_bool);
 
 extern int  my_strnncollsp_simple(CHARSET_INFO *, const uchar *, uint,
-				const uchar *, uint);
+                                  const uchar *, uint,
+                                  my_bool diff_if_only_endspace_difference);
 
 extern void my_hash_sort_simple(CHARSET_INFO *cs,
 				const uchar *key, uint len,

--- 1.179/libmysql/libmysql.c	2004-11-20 19:31:42 +02:00
+++ 1.180/libmysql/libmysql.c	2004-12-06 18:04:36 +02:00
@@ -3151,6 +3151,7 @@
     case MYSQL_TYPE_MEDIUM_BLOB:
     case MYSQL_TYPE_LONG_BLOB:
     case MYSQL_TYPE_BLOB:
+    case MYSQL_TYPE_VARCHAR:
     case MYSQL_TYPE_VAR_STRING:
     case MYSQL_TYPE_STRING:
       param->store_param_func= store_param_str;
@@ -4035,6 +4036,7 @@
       DBUG_ASSERT(param->buffer_length != 0);
       param->fetch_result= fetch_result_bin;
       break;
+    case MYSQL_TYPE_VARCHAR:
     case MYSQL_TYPE_VAR_STRING:
     case MYSQL_TYPE_STRING:
       DBUG_ASSERT(param->buffer_length != 0);
@@ -4099,6 +4101,7 @@
     case MYSQL_TYPE_MEDIUM_BLOB:
     case MYSQL_TYPE_LONG_BLOB:
     case MYSQL_TYPE_BLOB:
+    case MYSQL_TYPE_VARCHAR:
     case MYSQL_TYPE_VAR_STRING:
     case MYSQL_TYPE_STRING:
       param->skip_result= skip_result_string;

--- 1.125/myisam/mi_check.c	2004-11-12 19:15:43 +02:00
+++ 1.126/myisam/mi_check.c	2004-12-06 18:04:36 +02:00
@@ -2033,7 +2033,7 @@
       sort_param.key_length+=keyseg[i].length;
       if (keyseg[i].flag & HA_SPACE_PACK)
 	sort_param.key_length+=get_pack_length(keyseg[i].length);
-      if (keyseg[i].flag & (HA_BLOB_PART | HA_VAR_LENGTH))
+      if (keyseg[i].flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART))
 	sort_param.key_length+=2 + test(keyseg[i].length >= 127);
       if (keyseg[i].flag & HA_NULL_PART)
 	sort_param.key_length++;
@@ -2442,7 +2442,7 @@
       sort_param[i].key_length+=keyseg->length;
       if (keyseg->flag & HA_SPACE_PACK)
         sort_param[i].key_length+=get_pack_length(keyseg->length);
-      if (keyseg->flag & (HA_BLOB_PART | HA_VAR_LENGTH))
+      if (keyseg->flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART))
         sort_param[i].key_length+=2 + test(keyseg->length >= 127);
       if (keyseg->flag & HA_NULL_PART)
         sort_param[i].key_length++;

--- 1.37/myisam/mi_create.c	2004-11-23 16:03:07 +02:00
+++ 1.38/myisam/mi_create.c	2004-12-06 18:04:36 +02:00
@@ -276,8 +276,7 @@
       goto err;
 #endif /*HAVE_SPATIAL*/
     }
-    else
-    if (keydef->flag & HA_FULLTEXT)
+    else if (keydef->flag & HA_FULLTEXT)
     {
       keydef->flag=HA_FULLTEXT | HA_PACK_KEY | HA_VAR_LENGTH_KEY;
       options|=HA_OPTION_PACK_KEYS;             /* Using packed keys */
@@ -311,7 +310,7 @@
 
 	/* Only use HA_PACK_KEY when first segment is a variable length key */
 	if (!(keydef->seg[0].flag & (HA_SPACE_PACK | HA_BLOB_PART |
-				     HA_VAR_LENGTH)))
+				     HA_VAR_LENGTH_PART)))
 	{
 	  /* pack relative to previous key */
 	  keydef->flag&= ~HA_PACK_KEY;
@@ -345,12 +344,18 @@
 	case HA_KEYTYPE_UINT24:
 	case HA_KEYTYPE_INT8:
 	  keyseg->flag|= HA_SWAP_KEY;
-	  /* fall through */
+          break;
+        case HA_KEYTYPE_VARTEXT:
+        case HA_KEYTYPE_VARBINARY:
+          if (!(keyseg->flag & HA_BLOB_PART))
+            keyseg->flag|= HA_VAR_LENGTH_PART;
+          break;
 	default:
 	  break;
 	}
 	if (keyseg->flag & HA_SPACE_PACK)
 	{
+          DBUG_ASSERT(!(keyseg->flag & HA_VAR_LENGTH_PART));
 	  keydef->flag |= HA_SPACE_PACK_USED | HA_VAR_LENGTH_KEY;
 	  options|=HA_OPTION_PACK_KEYS;		/* Using packed keys */
 	  length++;				/* At least one length byte */
@@ -361,7 +366,7 @@
 	    length+=2;
 	  }
 	}
-	if (keyseg->flag & (HA_VAR_LENGTH | HA_BLOB_PART))
+	if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
 	{
 	  keydef->flag|=HA_VAR_LENGTH_KEY;
 	  length++;				/* At least one length byte */

--- 1.46/myisam/mi_write.c	2004-11-25 00:16:06 +02:00
+++ 1.47/myisam/mi_write.c	2004-12-06 18:04:36 +02:00
@@ -248,7 +248,7 @@
     comp_flag=SEARCH_BIGGER;			/* Put after same key */
   else if (keyinfo->flag & (HA_NOSAME|HA_FULLTEXT))
   {
-    comp_flag=SEARCH_FIND | SEARCH_UPDATE;	/* No dupplicates */
+    comp_flag=SEARCH_FIND | SEARCH_UPDATE;	/* No duplicates */
     if (keyinfo->flag & HA_NULL_ARE_EQUAL)
       comp_flag|= SEARCH_NULL_ARE_EQUAL;
   }

--- 1.30/scripts/mysql_fix_privilege_tables.sh	2004-11-28 21:40:01 +02:00
+++ 1.31/scripts/mysql_fix_privilege_tables.sh	2004-12-06 18:04:38 +02:00
@@ -13,7 +13,7 @@
 port=""
 socket=""
 database="mysql"
-bindir=""
+bindir="."
 pkgdatadir="@pkgdatadir@"
 
 file=mysql_fix_privilege_tables.sql
@@ -74,6 +74,7 @@
 # Get first arguments from the my.cfg file, groups [mysqld] and
 # [mysql_install_db], and then merge with the command line arguments
 
+print_defaults=my_print_defaults
 for dir in ./bin @bindir@ @bindir@ extra $bindir/../bin $bindir/../extra
 do
   if test -x $dir/my_print_defaults

--- 1.206/sql/field.cc	2004-12-06 02:05:21 +02:00
+++ 1.207/sql/field.cc	2004-12-06 19:18:30 +02:00
@@ -429,8 +429,7 @@
     copy->length-=table->blob_ptr_size;
     return copy->length;
   }
-  else if (!zero_pack() && (type() == FIELD_TYPE_STRING &&
copy->length > 4 ||
-			    type() == FIELD_TYPE_VAR_STRING))
+  else if (!zero_pack() && (type() == FIELD_TYPE_STRING &&
copy->length >= 4))
     copy->strip=1;				/* Remove end space */
   else
     copy->strip=0;
@@ -479,6 +478,26 @@
   return test(table->file->index_flags(idx, part, 1) & HA_READ_RANGE);
 }
 
+
+Field *Field::new_field(MEM_ROOT *root, struct st_table *new_table)
+{
+  Field *tmp;
+  if (!(tmp= (Field*) memdup_root(root,(char*) this,size_of())))
+    return 0;
+
+  if (tmp->table->maybe_null)
+    tmp->flags&= ~NOT_NULL_FLAG;
+  tmp->table= new_table;
+  tmp->key_start.init(0);
+  tmp->part_of_key.init(0);
+  tmp->part_of_sortkey.init(0);
+  tmp->unireg_check=Field::NONE;
+  tmp->flags&= (NOT_NULL_FLAG | BLOB_FLAG | UNSIGNED_FLAG |
+                ZEROFILL_FLAG | BINARY_FLAG | ENUM_FLAG | SET_FLAG);
+  tmp->reset_fields();
+  return tmp;
+}
+
 /****************************************************************************
   Field_null, a field that always return NULL
 ****************************************************************************/
@@ -4432,7 +4451,7 @@
     return field_charset->coll->strnncollsp(field_charset,
                                             (const uchar*) a_ptr, field_length,
                                             (const uchar*) b_ptr,
-                                            field_length);
+                                            field_length, 0);
   }
   if (field_charset->mbmaxlen != 1)
   {
@@ -4461,20 +4480,22 @@
 {
   THD *thd= table->in_use;
   CHARSET_INFO *cs=res.charset();
-  ulong length= cs->cset->snprintf(cs,(char*) res.ptr(),
-			    res.alloced_length(), "%s(%d)",
-			    (field_length > 3 &&
-			     (table->db_options_in_use &
-			      HA_OPTION_PACK_RECORD) ?
-			      (has_charset() ? "varchar" : "varbinary") :
+  ulong length;
+
+  length= cs->cset->snprintf(cs,(char*) res.ptr(),
+                             res.alloced_length(), "%s(%d)",
+                             ((type() == MYSQL_TYPE_VAR_STRING &&
+                               !thd->variables.new_mode) ?
+                              (has_charset() ? "varchar" : "varbinary") :
 			      (has_charset() ? "char" : "binary")),
-			    (int) field_length / charset()->mbmaxlen);
+                             (int) field_length / charset()->mbmaxlen);
   res.length(length);
   if ((thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)) &&
       has_charset() && (charset()->state & MY_CS_BINSORT))
     res.append(" binary");
 }
 
+
 char *Field_string::pack(char *to, const char *from, uint max_length)
 {
   uint length=      min(field_length,max_length);
@@ -4508,10 +4529,27 @@
 }
 
 
-int Field_string::pack_cmp(const char *a, const char *b, uint length)
+/*
+  Compare two packed keys
+
+  SYNOPSIS
+    pack_cmp()
+     a			New key
+     b			Original key
+     length		Key length
+     insert_or_update	1 if this is an insert or update
+
+  RETURN
+    < 0	  a < b
+    0	  a = b
+    > 0   a > b
+*/
+
+int Field_string::pack_cmp(const char *a, const char *b, uint length,
+                           my_bool insert_or_update)
 {
   uint a_length, b_length;
-  if (field_length > 255)
+  if (length > 255)
   {
     a_length= uint2korr(a);
     b_length= uint2korr(b);
@@ -4523,29 +4561,51 @@
     a_length= (uint) (uchar) *a++;
     b_length= (uint) (uchar) *b++;
   }
-  return my_strnncoll(field_charset,
-		      (const uchar*)a,a_length,
-		      (const uchar*)b,b_length);
+  return field_charset->coll->strnncollsp(field_charset,
+                                          (const uchar*) a, a_length,
+                                          (const uchar*) b, b_length,
+                                          insert_or_update);
 }
 
 
-int Field_string::pack_cmp(const char *b, uint length)
+/*
+  Compare a packed key against row
+
+  SYNOPSIS
+    pack_cmp()
+     key		Original key
+     length		Key length. (May be less than field length)
+     insert_or_update	1 if this is an insert or update
+
+  RETURN
+    < 0	  row < key
+    0	  row = key
+    > 0   row > key
+*/
+
+int Field_string::pack_cmp(const char *key, uint length,
+                           my_bool insert_or_update)
 {
-  uint b_length;
-  if (field_length > 255)
+  uint row_length, key_length;
+  char *end;
+  if (length > 255)
   {
-    b_length= uint2korr(b);
-    b+= 2;
+    key_length= uint2korr(key);
+    key+= 2;
   }
   else
-    b_length= (uint) (uchar) *b++;
-  char *end= ptr + field_length;
+    key_length= (uint) (uchar) *key++;
+  
+  /* Only use 'length' of key, not field_length */
+  end= ptr + length;
   while (end > ptr && end[-1] == ' ')
     end--;
-  uint a_length = (uint) (end - ptr);
-  return my_strnncoll(field_charset,
-		     (const uchar*)ptr,a_length,
-		     (const uchar*)b, b_length);
+  row_length= (uint) (end - ptr);
+
+  return field_charset->coll->strnncollsp(field_charset,
+                                          (const uchar*) ptr, row_length,
+                                          (const uchar*) key, key_length,
+                                          insert_or_update);
 }
 
 
@@ -4553,16 +4613,31 @@
 {
   if (length > 255)
     return uint2korr(data_ptr)+2;
-  else
-    return (uint) ((uchar) *data_ptr)+1;
+  return (uint) ((uchar) *data_ptr)+1;
 }
 
+
 uint Field_string::max_packed_col_length(uint max_length)
 {
   return (max_length > 255 ? 2 : 1)+max_length;
 }
 
 
+Field *Field_string::new_field(MEM_ROOT *root, struct st_table *new_table)
+{
+  if (type() != MYSQL_TYPE_VAR_STRING || table == new_table)
+    return Field::new_field(root, new_table);
+
+  /*
+    Old VARCHAR field which should be modified to a VARCHAR on copy
+    This is done to ensure that ALTER TABLE will convert old VARCHAR fields
+    to now VARCHAR fields.
+  */
+  return new Field_varstring(field_length, maybe_null(),
+                             field_name, new_table,
+                             charset());
+}
+
 /****************************************************************************
 ** VARCHAR type  (Not available for the end user yet)
 ****************************************************************************/
@@ -4571,7 +4646,7 @@
 int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs)
 {
   int error= 0;
-  uint32 not_used;
+  uint32 not_used, copy_length;
   char buff[80];
   String tmpstr(buff,sizeof(buff), &my_charset_bin);
 
@@ -4585,15 +4660,21 @@
     if (conv_errors)
       error= 1;
   }
-  if (length > field_length)
-  {
-    length=field_length;
+  /* 
+    Make sure we don't break a multibyte sequence
+    as well as don't copy a malformed data.
+  */
+  copy_length= field_charset->cset->well_formed_len(field_charset,
+						    from,from+length,
+						    field_length/
+						    field_charset->mbmaxlen);
+  memcpy(ptr + HA_KEY_BLOB_LENGTH, from, copy_length);
+  int2store(ptr, copy_length);
+  
+  if (copy_length < length)
     error= 1;
-  }
   if (error)
     set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
-  memcpy(ptr+HA_KEY_BLOB_LENGTH,from,length);
-  int2store(ptr, length);
   return error;
 }
 
@@ -4640,17 +4721,49 @@
   uint a_length=uint2korr(a_ptr);
   uint b_length=uint2korr(b_ptr);
   int diff;
-  diff= my_strnncoll(field_charset,
-		     (const uchar*) a_ptr+HA_KEY_BLOB_LENGTH,
-		     min(a_length,b_length),
-		     (const uchar*) b_ptr+HA_KEY_BLOB_LENGTH,
-		     min(a_length,b_length));
-  return diff ? diff : (int) (a_length - b_length);
+  diff= field_charset->coll->strnncollsp(field_charset,
+                                         (const uchar*) a_ptr+
+                                         HA_KEY_BLOB_LENGTH,
+                                         a_length,
+                                         (const uchar*) b_ptr+
+                                         HA_KEY_BLOB_LENGTH,
+                                         b_length,0);
+  return diff;
+}
+
+
+int Field_varstring::key_cmp(const byte *key_ptr, uint max_key_length)
+{
+  char *blob1;
+  uint length= uint2korr(ptr);
+  CHARSET_INFO *cs= charset();
+  uint char_length= max_key_length / cs->mbmaxlen;
+
+  char_length= my_charpos(cs, ptr + HA_KEY_BLOB_LENGTH,
+                          ptr + HA_KEY_BLOB_LENGTH + length, char_length);
+  set_if_smaller(length, char_length);
+  return cs->coll->strnncollsp(cs, 
+                               (const uchar*) ptr+2, length,
+                               (const uchar*) key_ptr+HA_KEY_BLOB_LENGTH,
+                               uint2korr(key_ptr), 0);
 }
 
+
+int Field_varstring::key_cmp(const byte *a,const byte *b)
+{
+  CHARSET_INFO *cs= charset();
+  return cs->coll->strnncollsp(cs,
+                               (const uchar*) a + HA_KEY_BLOB_LENGTH,
+                               uint2korr(a),
+                               (const uchar*) b + HA_KEY_BLOB_LENGTH,
+                               uint2korr(b),
+                               0);
+}
+
+
 void Field_varstring::sort_string(char *to,uint length)
 {
-  uint tot_length=uint2korr(ptr);
+  uint tot_length= uint2korr(ptr);
   tot_length= my_strnxfrm(field_charset,
 			  (uchar*) to, length,
 			  (uchar*) ptr+HA_KEY_BLOB_LENGTH,
@@ -4670,9 +4783,11 @@
   res.length(length);
 }
 
+
 char *Field_varstring::pack(char *to, const char *from, uint max_length)
 {
   uint length=uint2korr(from);
+  set_if_smaller(max_length, field_length);
   if (length > max_length)
     length=max_length;
   *to++= (char) (length & 255);
@@ -4687,12 +4802,14 @@
 char *Field_varstring::pack_key(char *to, const char *from, uint max_length)
 {
   uint length=uint2korr(from);
-  uint char_length= (field_charset->mbmaxlen > 1) ?
-              max_length/field_charset->mbmaxlen : max_length;
-  from+=HA_KEY_BLOB_LENGTH;
+  uint char_length= ((field_charset->mbmaxlen > 1) ?
+                     max_length/field_charset->mbmaxlen : max_length);
+  from+= HA_KEY_BLOB_LENGTH;
   if (length > char_length)
+  {
     char_length= my_charpos(field_charset, from, from+length, char_length);
-  set_if_smaller(length, char_length);
+    set_if_smaller(length, char_length);
+  }
   *to++= (char) (length & 255);
   if (max_length > 255)
     *to++= (char) (length >> 8);
@@ -4705,16 +4822,16 @@
 const char *Field_varstring::unpack(char *to, const char *from)
 {
   uint length;
-  if (field_length > 255)
+  if (field_length <= 255)
   {
     length= (uint) (uchar) (*to= *from++);
     to[1]=0;
   }
   else
   {
-    length=uint2korr(from);
-    to[0] = *from++;
-    to[1] = *from++;
+    length= uint2korr(from);
+    to[0]= *from++;
+    to[1]= *from++;
   }
   if (length)
     memcpy(to+HA_KEY_BLOB_LENGTH, from, length);
@@ -4722,77 +4839,122 @@
 }
 
 
-int Field_varstring::pack_cmp(const char *a, const char *b, uint key_length)
+int Field_varstring::pack_cmp(const char *a, const char *b, uint key_length,
+                              my_bool insert_or_update)
 {
   uint a_length;
   uint b_length;
   if (key_length > 255)
   {
-    a_length=uint2korr(a); a+= 2;
-    b_length=uint2korr(b); b+= 2;
+    a_length=uint2korr(a); a+= HA_KEY_BLOB_LENGTH;
+    b_length=uint2korr(b); b+= HA_KEY_BLOB_LENGTH;
   }
   else
   {
     a_length= (uint) (uchar) *a++;
     b_length= (uint) (uchar) *b++;
   }
-  return my_strnncoll(field_charset,
-		     (const uchar*) a, a_length,
-		     (const uchar*) b, b_length);
+  return field_charset->coll->strnncollsp(field_charset,
+                                          (const uchar*) a, a_length,
+                                          (const uchar*) b, b_length,
+                                          insert_or_update);
 }
 
-int Field_varstring::pack_cmp(const char *b, uint key_length)
+
+int Field_varstring::pack_cmp(const char *b, uint key_length,
+                              my_bool insert_or_update)
 {
   char *a= ptr+HA_KEY_BLOB_LENGTH;
   uint a_length= uint2korr(ptr);
   uint b_length;
+  uint char_length= ((field_charset->mbmaxlen > 1) ?
+                     key_length / field_charset->mbmaxlen : key_length);
+
   if (key_length > 255)
   {
-    b_length=uint2korr(b); b+= 2;
+    b_length=uint2korr(b); b+= HA_KEY_BLOB_LENGTH;
   }
   else
-  {
     b_length= (uint) (uchar) *b++;
+
+  if (a_length > char_length)
+  {
+    char_length= my_charpos(field_charset, a, a+a_length, char_length);
+    set_if_smaller(a_length, char_length);
   }
-  return my_strnncoll(field_charset,
-		     (const uchar*) a, a_length,
-		     (const uchar*) b, b_length);
+
+  return field_charset->coll->strnncollsp(field_charset,
+                                          (const uchar*) a,
+                                          a_length,
+                                          (const uchar*) b, b_length,
+                                          insert_or_update);
 }
 
+
 uint Field_varstring::packed_col_length(const char *data_ptr, uint length)
 {
   if (length > 255)
     return uint2korr(data_ptr)+HA_KEY_BLOB_LENGTH;
-  else
-    return (uint) ((uchar) *data_ptr)+1;
+  return (uint) ((uchar) *data_ptr)+1;
 }
 
+
 uint Field_varstring::max_packed_col_length(uint max_length)
 {
   return (max_length > 255 ? 2 : 1)+max_length;
 }
 
-void Field_varstring::get_key_image(char *buff, uint length, CHARSET_INFO *cs,
-				    imagetype type)
+
+void Field_varstring::get_key_image(char *buff, uint length, imagetype type)
 {
-  uint f_length=uint2korr(ptr);
-  if (f_length > length)
-    f_length= length;
-  int2store(buff,length);
-  memcpy(buff+HA_KEY_BLOB_LENGTH, ptr+HA_KEY_BLOB_LENGTH, length);
-#ifdef HAVE_purify
+  uint f_length= uint2korr(ptr);
+  uint char_length= length / field_charset->mbmaxlen;
+  char_length= my_charpos(field_charset, ptr, ptr + HA_KEY_BLOB_LENGTH,
+                          char_length);
+  set_if_smaller(f_length, char_length);
+  int2store(buff,f_length);
+  memcpy(buff+HA_KEY_BLOB_LENGTH, ptr+HA_KEY_BLOB_LENGTH, f_length);
   if (f_length < length)
+  {
+    /*
+      Must clear this as we do a memcmp in opt_range.cc to detect
+      identical keys
+    */
     bzero(buff+HA_KEY_BLOB_LENGTH+f_length, (length-f_length));
-#endif
+  }
 }
 
-void Field_varstring::set_key_image(char *buff,uint length, CHARSET_INFO *cs)
+
+void Field_varstring::set_key_image(char *buff,uint length)
 {
   length=uint2korr(buff);			// Real length is here
-  (void) Field_varstring::store(buff+HA_KEY_BLOB_LENGTH, length, cs);
+  (void) Field_varstring::store(buff+HA_KEY_BLOB_LENGTH, length,
+                                field_charset);
 }
 
 
+int Field_varstring::cmp_binary_offset(uint row_offset)
+{
+  return cmp_binary(ptr, ptr+row_offset);
+}
+
+
+int Field_varstring::cmp_binary(const char *a_ptr, const char *b_ptr,
+                                uint32 max_length)
+{
+  char *a,*b;
+  uint diff;
+  uint32 a_length,b_length;
+
+  a_length= uint2korr(a_ptr);
+  b_length= uint2korr(b_ptr);
+  set_if_smaller(a_length, max_length);
+  set_if_smaller(b_length, max_length);
+  if (a_length != b_length)
+    return 1;
+  return memcmp(a_ptr+2, b_ptr+2, a_length);
+}
+
 
 /****************************************************************************
 ** blob type
@@ -5030,10 +5192,10 @@
 int Field_blob::cmp(const char *a,uint32 a_length, const char *b,
 		    uint32 b_length)
 {
-  return field_charset->coll->strnncoll(field_charset, 
-                                        (const uchar*)a, a_length,
-                                        (const uchar*)b, b_length,
-                                        0);
+  return field_charset->coll->strnncollsp(field_charset, 
+                                          (const uchar*)a, a_length,
+                                          (const uchar*)b, b_length,
+                                          0);
 }
 
 
@@ -5080,8 +5242,7 @@
 
 /* The following is used only when comparing a key */
 
-void Field_blob::get_key_image(char *buff,uint length,
-			       CHARSET_INFO *cs, imagetype type)
+void Field_blob::get_key_image(char *buff, uint length, imagetype type)
 {
   uint32 blob_length= get_length(ptr);
   char *blob;
@@ -5116,8 +5277,9 @@
 #endif /*HAVE_SPATIAL*/
 
   get_ptr(&blob);
-  uint char_length= length / cs->mbmaxlen;
-  char_length= my_charpos(cs, blob, blob + blob_length, char_length);
+  uint char_length= length / field_charset->mbmaxlen;
+  char_length= my_charpos(field_charset, blob, blob + blob_length,
+                          char_length);
   set_if_smaller(blob_length, char_length);
 
   if ((uint32) length > blob_length)
@@ -5133,10 +5295,11 @@
   memcpy(buff+HA_KEY_BLOB_LENGTH, blob, length);
 }
 
-void Field_blob::set_key_image(char *buff,uint length, CHARSET_INFO *cs)
+
+void Field_blob::set_key_image(char *buff,uint length)
 {
   length= uint2korr(buff);
-  (void) Field_blob::store(buff+HA_KEY_BLOB_LENGTH, length, cs);
+  (void) Field_blob::store(buff+HA_KEY_BLOB_LENGTH, length, field_charset);
 }
 
 
@@ -5149,7 +5312,7 @@
   uint char_length= max_key_length / cs->mbmaxlen;
   char_length= my_charpos(cs, blob1, blob1+blob_length, char_length);
   set_if_smaller(blob_length, char_length);
-  return Field_blob::cmp(blob1,min(blob_length, max_key_length),
+  return Field_blob::cmp(blob1, blob_length,
 			 (char*) key_ptr+HA_KEY_BLOB_LENGTH,
 			 uint2korr(key_ptr));
 }
@@ -5241,7 +5404,8 @@
 
 /* Keys for blobs are like keys on varchars */
 
-int Field_blob::pack_cmp(const char *a, const char *b, uint key_length)
+int Field_blob::pack_cmp(const char *a, const char *b, uint key_length,
+                         my_bool insert_or_update)
 {
   uint a_length;
   uint b_length;
@@ -5255,13 +5419,15 @@
     a_length= (uint) (uchar) *a++;
     b_length= (uint) (uchar) *b++;
   }
-  return my_strnncoll(field_charset,
-		     (const uchar*) a, a_length,
-		     (const uchar*) b, b_length);
+  return field_charset->coll->strnncollsp(field_charset,
+                                          (const uchar*) a, a_length,
+                                          (const uchar*) b, b_length,
+                                          insert_or_update);
 }
 
 
-int Field_blob::pack_cmp(const char *b, uint key_length)
+int Field_blob::pack_cmp(const char *b, uint key_length,
+                         my_bool insert_or_update)
 {
   char *a;
   memcpy_fixed(&a,ptr+packlength,sizeof(char*));
@@ -5275,12 +5441,11 @@
     b_length=uint2korr(b); b+=2;
   }
   else
-  {
     b_length= (uint) (uchar) *b++;
-  }
-  return my_strnncoll(field_charset,
-		     (const uchar*) a, a_length,
-		     (const uchar*) b, b_length);
+  return field_charset->coll->strnncollsp(field_charset,
+                                          (const uchar*) a, a_length,
+                                          (const uchar*) b, b_length,
+                                          insert_or_update);
 }
 
 /* Create a packed key that will be used for storage from a MySQL row */
@@ -5290,8 +5455,8 @@
   char *save=ptr;
   ptr=(char*) from;
   uint32 length=get_length();			// Length of from string
-  uint char_length= (field_charset->mbmaxlen > 1) ?
-              max_length/field_charset->mbmaxlen : max_length;
+  uint char_length= ((field_charset->mbmaxlen > 1) ?
+                     max_length/field_charset->mbmaxlen : max_length);
   if (length)
     get_ptr((char**) &from);
   if (length > char_length)
@@ -5365,14 +5530,15 @@
   return to+length;
 }
 
+
 uint Field_blob::packed_col_length(const char *data_ptr, uint length)
 {
   if (length > 255)
     return uint2korr(data_ptr)+2;
-  else
-    return (uint) ((uchar) *data_ptr)+1;
+  return (uint) ((uchar) *data_ptr)+1;
 }
 
+
 uint Field_blob::max_packed_col_length(uint max_length)
 {
   return (max_length > 255 ? 2 : 1)+max_length;
@@ -5381,8 +5547,7 @@
 
 #ifdef HAVE_SPATIAL
 
-void Field_geom::get_key_image(char *buff, uint length, CHARSET_INFO *cs,
-			       imagetype type)
+void Field_geom::get_key_image(char *buff, uint length, imagetype type)
 {
   char *blob;
   const char *dummy;
@@ -5411,11 +5576,6 @@
 }
 
 
-void Field_geom::set_key_image(char *buff, uint length, CHARSET_INFO *cs)
-{
-  Field_blob::set_key_image(buff, length, cs);
-}
-
 void Field_geom::sql_type(String &res) const
 {
   CHARSET_INFO *cs= &my_charset_latin1;
@@ -5864,7 +6024,7 @@
 
 
 /*****************************************************************************
-** Handling of field and create_field
+  Handling of field and create_field
 *****************************************************************************/
 
 void create_field::create_length_to_internal_length(void)
@@ -5876,9 +6036,10 @@
   case MYSQL_TYPE_BLOB:
   case MYSQL_TYPE_VAR_STRING:
   case MYSQL_TYPE_STRING:
+  case MYSQL_TYPE_VARCHAR:
     length*= charset->mbmaxlen;
-    pack_length= calc_pack_length(sql_type == FIELD_TYPE_VAR_STRING ?
-                                  FIELD_TYPE_STRING : sql_type, length);
+    key_length*= charset->mbmaxlen;
+    pack_length= calc_pack_length(sql_type, length);
     break;
   case MYSQL_TYPE_ENUM:
   case MYSQL_TYPE_SET:
@@ -5890,6 +6051,22 @@
   }
 }
 
+
+enum_field_types get_blob_type_from_length(ulong length)
+{
+  enum_field_types type;
+  if (length < 256)
+    type= FIELD_TYPE_TINY_BLOB;
+  else if (length < 65536)
+    type= FIELD_TYPE_BLOB;
+  else if (length < 256L*256L*256L)
+    type= FIELD_TYPE_MEDIUM_BLOB;
+  else
+    type= FIELD_TYPE_LONG_BLOB;
+  return type;
+}
+
+
 /*
   Make a field from the .frm file info
 */
@@ -5897,9 +6074,10 @@
 uint32 calc_pack_length(enum_field_types type,uint32 length)
 {
   switch (type) {
+  case MYSQL_TYPE_VAR_STRING:
   case FIELD_TYPE_STRING:
-  case FIELD_TYPE_DECIMAL: return (length);
-  case FIELD_TYPE_VAR_STRING: return (length+HA_KEY_BLOB_LENGTH);
+  case FIELD_TYPE_DECIMAL:     return (length);
+  case MYSQL_TYPE_VARCHAR:     return (length+HA_KEY_BLOB_LENGTH);
   case FIELD_TYPE_YEAR:
   case FIELD_TYPE_TINY	: return 1;
   case FIELD_TYPE_SHORT : return 2;
@@ -5972,12 +6150,16 @@
   {
     if (!f_is_packed(pack_flag))
     {
-      if (field_type == FIELD_TYPE_STRING ||
+      if (field_type == MYSQL_TYPE_STRING ||
           field_type == FIELD_TYPE_DECIMAL ||   // 3.23 or 4.0 string
-          field_type == FIELD_TYPE_VAR_STRING)
+          field_type == MYSQL_TYPE_VAR_STRING)
         return new Field_string(ptr,field_length,null_pos,null_bit,
                                 unireg_check, field_name, table,
                                 field_charset);
+      if (field_type == MYSQL_TYPE_VARCHAR)
+        return new Field_varstring(ptr,field_length,null_pos,null_bit,
+                                   unireg_check, field_name, table,
+                                   field_charset);
       return 0;                                 // Error
     }
 
@@ -6090,44 +6272,51 @@
   flags=      old_field->flags;
   unireg_check=old_field->unireg_check;
   pack_length=old_field->pack_length();
+  key_length= old_field->key_length();
   sql_type=   old_field->real_type();
   charset=    old_field->charset();		// May be NULL ptr
   comment=    old_field->comment;
+  decimals=   old_field->decimals();
 
   /* Fix if the original table had 4 byte pointer blobs */
   if (flags & BLOB_FLAG)
     pack_length= (pack_length- old_field->table->blob_ptr_size +
 		  portable_sizeof_char_ptr);
 
-  switch (sql_type)
-  {
-    case FIELD_TYPE_BLOB:
-      switch (pack_length - portable_sizeof_char_ptr)
-      {
-        case  1: sql_type= FIELD_TYPE_TINY_BLOB; break;
-        case  2: sql_type= FIELD_TYPE_BLOB; break;
-        case  3: sql_type= FIELD_TYPE_MEDIUM_BLOB; break;
-        default: sql_type= FIELD_TYPE_LONG_BLOB; break;
-      }
-      length=(length+charset->mbmaxlen-1)/charset->mbmaxlen; // QQ: Probably not
needed
-      break;
-    case MYSQL_TYPE_ENUM:
-    case MYSQL_TYPE_SET:
-    case FIELD_TYPE_STRING:
-    case FIELD_TYPE_VAR_STRING:
-      length=(length+charset->mbmaxlen-1)/charset->mbmaxlen;
-      break;
-    default:
-      break;
-  }
-
-  decimals= old_field->decimals();
-  if (sql_type == FIELD_TYPE_STRING)
-  {
+  switch (sql_type) {
+  case FIELD_TYPE_BLOB:
+    switch (pack_length - portable_sizeof_char_ptr) {
+    case  1: sql_type= FIELD_TYPE_TINY_BLOB; break;
+    case  2: sql_type= FIELD_TYPE_BLOB; break;
+    case  3: sql_type= FIELD_TYPE_MEDIUM_BLOB; break;
+    default: sql_type= FIELD_TYPE_LONG_BLOB; break;
+    }
+    length=(length+charset->mbmaxlen-1) / charset->mbmaxlen;
+    key_length/= charset->mbmaxlen;
+    break;
+  case FIELD_TYPE_STRING:
     /* Change CHAR -> VARCHAR if dynamic record length */
-    sql_type=old_field->type();
-    decimals=0;
+    if (old_field->type() == MYSQL_TYPE_VAR_STRING)
+      sql_type= MYSQL_TYPE_VARCHAR;
+    /* fall through */
+
+  case MYSQL_TYPE_ENUM:
+  case MYSQL_TYPE_SET:
+  case MYSQL_TYPE_VARCHAR:
+  case MYSQL_TYPE_VAR_STRING:
+    /* These are corrected in create_length_to_internal_length */
+    length= (length+charset->mbmaxlen-1) / charset->mbmaxlen;
+    key_length/= charset->mbmaxlen;
+    break;
+#ifdef HAVE_SPATIAL
+  case FIELD_TYPE_GEOMETRY:
+    geom_type= ((Field_geom*)old_field)->geom_type;
+    break;
+#endif
+  default:
+    break;
   }
+
   if (flags & (ENUM_FLAG | SET_FLAG))
     interval= ((Field_enum*) old_field)->typelib;
   else
@@ -6152,12 +6341,6 @@
       def= new Item_string(pos, tmp.length(), charset);
     }
   }
-#ifdef HAVE_SPATIAL
-  if (sql_type == FIELD_TYPE_GEOMETRY)
-  {
-    geom_type= ((Field_geom*)old_field)->geom_type;
-  }
-#endif
 }
 
 

--- 1.123/sql/field.h	2004-12-06 02:05:21 +02:00
+++ 1.124/sql/field.h	2004-12-06 18:04:38 +02:00
@@ -184,27 +184,7 @@
   */
   virtual bool can_be_compared_as_longlong() const { return FALSE; }
   virtual void free() {}
-  Field *new_field(MEM_ROOT *root, struct st_table *new_table)
-  {
-    Field *tmp= (Field*) memdup_root(root,(char*) this,size_of());
-    if (tmp)
-    {
-      if (tmp->table->maybe_null)
-	tmp->flags&= ~NOT_NULL_FLAG;
-      tmp->table= new_table;
-      tmp->key_start.init(0);
-      tmp->part_of_key.init(0);
-      tmp->part_of_sortkey.init(0);
-      tmp->unireg_check=Field::NONE;
-      tmp->flags&= (NOT_NULL_FLAG | BLOB_FLAG | UNSIGNED_FLAG |
-		    ZEROFILL_FLAG | BINARY_FLAG | ENUM_FLAG | SET_FLAG);
-#ifdef PROBABLY_WRONG
-      tmp->table_name= new_table->table_name;
-#endif
-      tmp->reset_fields();
-    }
-    return tmp;
-  }
+  virtual Field *new_field(MEM_ROOT *root, struct st_table *new_table);
   inline void move_field(char *ptr_arg,uchar *null_ptr_arg,uchar null_bit_arg)
   {
     ptr=ptr_arg; null_ptr=null_ptr_arg; null_bit=null_bit_arg;
@@ -220,11 +200,10 @@
     { memcpy(buff,ptr,length); }
   inline void set_image(char *buff,uint length, CHARSET_INFO *cs)
     { memcpy(ptr,buff,length); }
-  virtual void get_key_image(char *buff,uint length, CHARSET_INFO *cs,
-			     imagetype type)
-    { get_image(buff,length,cs); }
-  virtual void set_key_image(char *buff,uint length, CHARSET_INFO *cs)
-    { set_image(buff,length,cs); }
+  virtual void get_key_image(char *buff, uint length, imagetype type)
+    { get_image(buff,length, &my_charset_bin); }
+  virtual void set_key_image(char *buff,uint length)
+    { set_image(buff,length, &my_charset_bin); }
   inline longlong val_int_offset(uint row_offset)
     {
       ptr+=row_offset;
@@ -263,9 +242,11 @@
   virtual uint max_packed_col_length(uint max_length)
   { return max_length;}
 
-  virtual int pack_cmp(const char *a,const char *b, uint key_length_arg)
+  virtual int pack_cmp(const char *a,const char *b, uint key_length_arg,
+                       my_bool insert_or_update)
   { return cmp(a,b); }
-  virtual int pack_cmp(const char *b, uint key_length_arg)
+  virtual int pack_cmp(const char *b, uint key_length_arg,
+                       my_bool insert_or_update)
   { return cmp(ptr,b); }
   uint offset();			// Should be inline ...
   void copy_from_tmp(int offset);
@@ -908,8 +889,8 @@
   enum_field_types type() const
   {
     return ((table && table->db_create_options & HA_OPTION_PACK_RECORD
&&
-	     field_length >= 4) ?
-	    FIELD_TYPE_VAR_STRING : FIELD_TYPE_STRING);
+	     field_length >= 4) && table->frm_version < FRM_VER_TRUE_VARCHAR ?
+	    MYSQL_TYPE_VAR_STRING : MYSQL_TYPE_STRING);
   }
   enum ha_base_keytype key_type() const
     { return binary() ? HA_KEYTYPE_BINARY : HA_KEYTYPE_TEXT; }
@@ -926,8 +907,9 @@
   void sql_type(String &str) const;
   char *pack(char *to, const char *from, uint max_length=~(uint) 0);
   const char *unpack(char* to, const char *from);
-  int pack_cmp(const char *a,const char *b,uint key_length);
-  int pack_cmp(const char *b,uint key_length);
+  int pack_cmp(const char *a,const char *b,uint key_length,
+               my_bool insert_or_update);
+  int pack_cmp(const char *b,uint key_length,my_bool insert_or_update);
   uint packed_col_length(const char *to, uint length);
   uint max_packed_col_length(uint max_length);
   uint size_of() const { return sizeof(*this); }
@@ -935,6 +917,7 @@
   bool has_charset(void) const
   { return charset() == &my_charset_bin ? FALSE : TRUE; }
   field_cast_enum field_cast_type() { return FIELD_CAST_STRING; }
+  Field *new_field(MEM_ROOT *root, struct st_table *new_table);
 };
 
 
@@ -954,7 +937,7 @@
 	       NONE, field_name_arg, table_arg, cs)
   {}
 
-  enum_field_types type() const { return FIELD_TYPE_VAR_STRING; }
+  enum_field_types type() const { return MYSQL_TYPE_VARCHAR; }
   enum ha_base_keytype key_type() const
     { return binary() ? HA_KEYTYPE_VARBINARY : HA_KEYTYPE_VARTEXT; }
   bool zero_pack() const { return 0; }
@@ -969,18 +952,23 @@
   String *val_str(String*,String *);
   int cmp(const char *,const char*);
   void sort_string(char *buff,uint length);
-  void get_key_image(char *buff,uint length, CHARSET_INFO *cs, imagetype type);
-  void set_key_image(char *buff,uint length, CHARSET_INFO *cs);
+  void get_key_image(char *buff,uint length, imagetype type);
+  void set_key_image(char *buff,uint length);
   void sql_type(String &str) const;
   char *pack(char *to, const char *from, uint max_length=~(uint) 0);
   char *pack_key(char *to, const char *from, uint max_length);
   const char *unpack(char* to, const char *from);
-  int pack_cmp(const char *a, const char *b, uint key_length);
-  int pack_cmp(const char *b, uint key_length);
+  int pack_cmp(const char *a, const char *b, uint key_length,
+               my_bool insert_or_update);
+  int pack_cmp(const char *b, uint key_length,my_bool insert_or_update);
+  int cmp_binary(const char *a,const char *b, uint32 max_length=~0L);
+  int cmp_binary_offset(uint row_offset);
+  int key_cmp(const byte *,const byte*);
+  int key_cmp(const byte *str, uint length);
   uint packed_col_length(const char *to, uint length);
   uint max_packed_col_length(uint max_length);
   uint size_of() const { return sizeof(*this); }
-  enum_field_types real_type() const { return FIELD_TYPE_VAR_STRING; }
+  enum_field_types real_type() const { return MYSQL_TYPE_VARCHAR; }
   bool has_charset(void) const
   { return charset() == &my_charset_bin ? FALSE : TRUE; }
   field_cast_enum field_cast_type() { return FIELD_CAST_VARSTRING; }
@@ -1049,8 +1037,8 @@
       store_length(length);
       memcpy_fixed(ptr+packlength,&data,sizeof(char*));
     }
-  void get_key_image(char *buff,uint length, CHARSET_INFO *cs, imagetype type);
-  void set_key_image(char *buff,uint length, CHARSET_INFO *cs);
+  void get_key_image(char *buff,uint length, imagetype type);
+  void set_key_image(char *buff,uint length);
   void sql_type(String &str) const;
   inline bool copy()
   { char *tmp;
@@ -1068,8 +1056,9 @@
   char *pack_key(char *to, const char *from, uint max_length);
   char *pack_key_from_key_image(char* to, const char *from, uint max_length);
   const char *unpack_key(char* to, const char *from, uint max_length);
-  int pack_cmp(const char *a, const char *b, uint key_length);
-  int pack_cmp(const char *b, uint key_length);
+  int pack_cmp(const char *a, const char *b, uint key_length,
+               my_bool insert_or_update);
+  int pack_cmp(const char *b, uint key_length,my_bool insert_or_update);
   uint packed_col_length(const char *col_ptr, uint length);
   uint max_packed_col_length(uint max_length);
   void free() { value.free(); }
@@ -1082,6 +1071,7 @@
   uint32 max_length();
 };
 
+
 #ifdef HAVE_SPATIAL
 class Field_geom :public Field_blob {
 public:
@@ -1106,12 +1096,12 @@
   int  store(double nr) { return 1; }
   int  store(longlong nr) { return 1; }
 
-  void get_key_image(char *buff,uint length, CHARSET_INFO *cs,imagetype type);
-  void set_key_image(char *buff,uint length, CHARSET_INFO *cs);
+  void get_key_image(char *buff,uint length,imagetype type);
   field_cast_enum field_cast_type() { return FIELD_CAST_GEOM; }
 };
 #endif /*HAVE_SPATIAL*/
 
+
 class Field_enum :public Field_str {
 protected:
   uint packlength;
@@ -1192,8 +1182,8 @@
   LEX_STRING comment;			// Comment for field
   Item	*def;				// Default value
   enum	enum_field_types sql_type;
-  uint32 length;
-  uint decimals,flags,pack_length;
+  ulong length;
+  uint  decimals, flags, pack_length, key_length;
   Field::utype unireg_check;
   TYPELIB *interval;			// Which interval to use
   List<String> interval_list;
@@ -1258,6 +1248,7 @@
 		  TYPELIB *interval, const char *field_name,
 		  struct st_table *table);
 uint pack_length_to_packflag(uint type);
+enum_field_types get_blob_type_from_length(ulong length);
 uint32 calc_pack_length(enum_field_types type,uint32 length);
 int set_field_to_null(Field *field);
 int set_field_to_null_with_conversions(Field *field, bool no_conversions);

--- 1.34/sql/field_conv.cc	2004-11-13 19:35:41 +02:00
+++ 1.35/sql/field_conv.cc	2004-12-06 18:04:38 +02:00
@@ -353,15 +353,16 @@
 static void do_varstring(Copy_field *copy)
 {
   uint length=uint2korr(copy->from_ptr);
-  if (length > copy->to_length-2)
+  if (length > copy->to_length- HA_KEY_BLOB_LENGTH)
   {
-    length=copy->to_length-2;
+    length=copy->to_length-HA_KEY_BLOB_LENGTH;
     if (current_thd->count_cuted_fields)
       copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
                                   ER_WARN_DATA_TRUNCATED, 1);
   }
   int2store(copy->to_ptr,length);
-  memcpy(copy->to_ptr+2, copy->from_ptr,length);
+  memcpy(copy->to_ptr+HA_KEY_BLOB_LENGTH, copy->from_ptr + HA_KEY_BLOB_LENGTH,
+         length);
 }
 
 /***************************************************************************
@@ -504,7 +505,7 @@
       }
       else if (to->charset() != from->charset())
 	return do_field_string;
-      else if (to->real_type() == FIELD_TYPE_VAR_STRING && to_length !=
+      else if (to->real_type() == MYSQL_TYPE_VARCHAR && to_length !=
 	       from_length)
 	return do_varstring;
       else if (to_length < from_length)

--- 1.49/sql/ha_heap.cc	2004-11-17 21:07:06 +02:00
+++ 1.50/sql/ha_heap.cc	2004-12-06 18:04:38 +02:00
@@ -481,16 +481,20 @@
     {
       uint flag=    key_part->key_type;
       Field *field= key_part->field;
+
       if (pos->algorithm == HA_KEY_ALG_BTREE)
 	seg->type= field->key_type();
       else
       {
-        if ((seg->type = field->key_type()) != (int) HA_KEYTYPE_TEXT)
+        if ((seg->type = field->key_type()) != (int) HA_KEYTYPE_TEXT &&
+            seg->type != HA_KEYTYPE_VARTEXT &&
+            seg->type != HA_KEYTYPE_VARBINARY)
           seg->type= HA_KEYTYPE_BINARY;
       }
       seg->start=   (uint) key_part->offset;
       seg->length=  (uint) key_part->length;
-      seg->flag =   0;
+      seg->flag=    key_part->key_part_flag;
+
       seg->charset= field->charset();
       if (field->null_ptr)
       {

--- 1.137/sql/ha_myisam.cc	2004-11-15 20:26:53 +02:00
+++ 1.138/sql/ha_myisam.cc	2004-12-06 18:04:38 +02:00
@@ -1377,9 +1377,9 @@
     keydef[i].keysegs=pos->key_parts;
     for (j=0 ; j < pos->key_parts ; j++)
     {
-      keydef[i].seg[j].flag=pos->key_part[j].key_part_flag;
       Field *field=pos->key_part[j].field;
       type=field->key_type();
+      keydef[i].seg[j].flag=pos->key_part[j].key_part_flag;
 
       if (options & HA_OPTION_PACK_KEYS ||
 	  (pos->flags & (HA_PACK_KEY | HA_BINARY_PACK_KEY |
@@ -1394,8 +1394,8 @@
 	  if (j == 0)
 	    keydef[i].flag|=HA_PACK_KEY;
 	  if (!(field->flags & ZEROFILL_FLAG) &&
-	      (field->type() == FIELD_TYPE_STRING ||
-	       field->type() == FIELD_TYPE_VAR_STRING ||
+	      (field->type() == MYSQL_TYPE_STRING ||
+	       field->type() == MYSQL_TYPE_VAR_STRING ||
 	       ((int) (pos->key_part[j].length - field->decimals()))
 	       >= 4))
 	    keydef[i].seg[j].flag|=HA_SPACE_PACK;
@@ -1474,30 +1474,31 @@
     {
       recinfo_pos->type= (int) FIELD_BLOB;
     }
-    else if (!(options & HA_OPTION_PACK_RECORD))
+    else if (!(options & HA_OPTION_PACK_RECORD) ||
+             found->type() == MYSQL_TYPE_VARCHAR)
       recinfo_pos->type= (int) FIELD_NORMAL;
     else if (found->zero_pack())
       recinfo_pos->type= (int) FIELD_SKIP_ZERO;
     else
       recinfo_pos->type= (int) ((length <= 3 ||
-				      (found->flags & ZEROFILL_FLAG)) ?
-				     FIELD_NORMAL :
-				     found->type() == FIELD_TYPE_STRING ||
-				     found->type() == FIELD_TYPE_VAR_STRING ?
-				     FIELD_SKIP_ENDSPACE :
-				     FIELD_SKIP_PRESPACE);
+                                 (found->flags & ZEROFILL_FLAG)) ?
+                                FIELD_NORMAL :
+                                found->type() == MYSQL_TYPE_STRING ||
+                                found->type() == MYSQL_TYPE_VAR_STRING ?
+                                FIELD_SKIP_ENDSPACE :
+                                FIELD_SKIP_PRESPACE);
     if (found->null_ptr)
     {
       recinfo_pos->null_bit=found->null_bit;
       recinfo_pos->null_pos= (uint) (found->null_ptr-
-				  (uchar*) table_arg->record[0]);
+                                     (uchar*) table_arg->record[0]);
     }
     else
     {
       recinfo_pos->null_bit=0;
       recinfo_pos->null_pos=0;
     }
-    (recinfo_pos++) ->length=(uint16) length;
+    (recinfo_pos++)->length= (uint16) length;
     recpos=minpos+length;
     DBUG_PRINT("loop",("length: %d  type: %d",
 		       recinfo_pos[-1].length,recinfo_pos[-1].type));

--- 1.113/sql/handler.h	2004-12-06 02:05:21 +02:00
+++ 1.114/sql/handler.h	2004-12-06 18:04:38 +02:00
@@ -74,6 +74,7 @@
 #define HA_HAS_CHECKSUM        (1 << 24)
 /* Table data are stored in separate files (for lower_case_table_names) */
 #define HA_FILE_BASED	       (1 << 26)
+#define HA_NO_VARCHAR	       (1 << 27)
 
 
 /* bits in index_flags(index_number) for what you can do with index */
@@ -252,6 +253,7 @@
   uint merge_insert_method;
   bool table_existed;			/* 1 in create if table existed */
   bool frm_only;                        /* 1 if no ha_create_table() */
+  bool varchar;                         /* 1 if table has a VARCHAR */
 } HA_CREATE_INFO;
 
 

--- 1.97/sql/item.cc	2004-12-06 17:15:48 +02:00
+++ 1.98/sql/item.cc	2004-12-06 19:18:30 +02:00
@@ -188,7 +188,6 @@
 {
   DBUG_ENTER("Item_ident::cleanup");
 #ifdef CANT_BE_USED_AS_MEMORY_IS_FREED
-  DBUG_PRINT("enter", ("b:%s(%s), t:%s(%s), f:%s(%s)",
 		       db_name ? db_name : "(null)",
                        orig_db_name ? orig_db_name : "(null)",
 		       table_name ? table_name : "(null)",
@@ -2237,18 +2236,29 @@
 
 void Item_empty_string::make_field(Send_field *tmp_field)
 {
-  init_make_field(tmp_field,FIELD_TYPE_VAR_STRING);
+  init_make_field(tmp_field, MYSQL_TYPE_VARCHAR);
 }
 
 
 enum_field_types Item::field_type() const
 {
-  return ((result_type() == STRING_RESULT) ? FIELD_TYPE_VAR_STRING :
+  return ((result_type() == STRING_RESULT) ? MYSQL_TYPE_VARCHAR :
 	  (result_type() == INT_RESULT) ? FIELD_TYPE_LONGLONG :
 	  FIELD_TYPE_DOUBLE);
 }
 
 
+/*
+  Create a field based on field_type of argument
+
+  For now, this is only used to create a field for
+  IFNULL(x,something)
+
+  RETURN
+    0  error
+    #  Created field
+*/
+
 Field *Item::tmp_table_field_from_field_type(TABLE *table)
 {
   /*
@@ -2304,12 +2314,17 @@
   case MYSQL_TYPE_ENUM:
   case MYSQL_TYPE_SET:
   case MYSQL_TYPE_VAR_STRING:
-    if (max_length > 255)
-      break;					// If blob
+    if (max_length > MAX_FIELD_CHARLENGTH)
+      break;					// convert to blob
+    return new Field_varstring(max_length, maybe_null, name, table,
+			       collation.collation);
+  case MYSQL_TYPE_VARCHAR:
+    if (max_length > CONVERT_IF_BIGGER_TO_BLOB)
+      break;					// convert to blob
     return new Field_varstring(max_length, maybe_null, name, table,
 			       collation.collation);
   case MYSQL_TYPE_STRING:
-    if (max_length > 255)			// If blob
+    if (max_length > MAX_FIELD_CHARLENGTH)	// If blob
       break;
     return new Field_string(max_length, maybe_null, name, table,
 			    collation.collation);
@@ -2637,6 +2652,7 @@
   case MYSQL_TYPE_GEOMETRY:
   case MYSQL_TYPE_STRING:
   case MYSQL_TYPE_VAR_STRING:
+  case MYSQL_TYPE_VARCHAR:
   {
     String *res;
     if ((res=val_str(buffer)))

--- 1.127/sql/item_cmpfunc.cc	2004-12-06 02:05:21 +02:00
+++ 1.128/sql/item_cmpfunc.cc	2004-12-06 18:04:38 +02:00
@@ -1726,7 +1726,7 @@
 {
   return cs->coll->strnncollsp(cs,
                                (uchar *) x->ptr(),x->length(),
-                               (uchar *) y->ptr(),y->length());
+                               (uchar *) y->ptr(),y->length(), 0);
 }
 
 

--- 1.110/sql/item_sum.cc	2004-11-20 19:31:44 +02:00
+++ 1.111/sql/item_sum.cc	2004-12-06 18:04:39 +02:00
@@ -1194,7 +1194,7 @@
   uint len=item->key_length;
   return cs->coll->strnncollsp(cs, 
 			       (const uchar*) key1, len, 
-			       (const uchar*) key2, len);
+			       (const uchar*) key2, len, 0);
 }
 
 /*
@@ -1344,10 +1344,9 @@
 	about other fields
       */
       Field* field = table->field[0];
-      switch(field->type())
-      {
-      case FIELD_TYPE_STRING:
-      case FIELD_TYPE_VAR_STRING:
+      switch (field->type()) {
+      case MYSQL_TYPE_STRING:
+      case MYSQL_TYPE_VAR_STRING:
 	if (field->binary())
 	{
 	  compare_key = (qsort_cmp2)simple_raw_key_cmp;

--- 1.85/sql/protocol.cc	2004-11-24 18:22:22 +02:00
+++ 1.86/sql/protocol.cc	2004-12-06 18:04:39 +02:00
@@ -511,6 +511,11 @@
     CHARSET_INFO *cs= system_charset_info;
     Send_field field;
     item->make_field(&field);
+
+    /* Keep things compatible for old clients */
+    if (field.type == MYSQL_TYPE_VARCHAR)
+      field.type= MYSQL_TYPE_VAR_STRING;
+
     prot.prepare_for_resend();
 
     if (thd->client_capabilities & CLIENT_PROTOCOL_41)

--- 1.131/sql/opt_range.cc	2004-11-28 20:01:33 +02:00
+++ 1.132/sql/opt_range.cc	2004-12-06 18:04:39 +02:00
@@ -1749,8 +1749,10 @@
           objects are not allowed so don't use ROR-intersection for
           table deletes.
         */
-        if ((thd->lex->sql_command != SQLCOM_DELETE) )//&& 
-//          (thd->lex->sql_command != SQLCOM_UPDATE))
+        if ((thd->lex->sql_command != SQLCOM_DELETE))
+#ifdef NOT_USED
+          if ((thd->lex->sql_command != SQLCOM_UPDATE))
+#endif
         {
           /*
             Get best non-covering ROR-intersection plan and prepare data for
@@ -3693,8 +3695,7 @@
     DBUG_RETURN(0);
   if (maybe_null)
     *str= (char) field->is_real_null();		// Set to 1 if null
-  field->get_key_image(str+maybe_null, key_part->length,
-		       field->charset(), key_part->image_type);
+  field->get_key_image(str+maybe_null, key_part->length, key_part->image_type);
   if (copies == 2)
   {
     /*
@@ -8444,7 +8445,7 @@
       key++;					// Skip null byte
       store_length--;
     }
-    field->set_key_image((char*) key, key_part->length, field->charset());
+    field->set_key_image((char*) key, key_part->length);
     field->val_str(&tmp);
     fwrite(tmp.ptr(),sizeof(char),tmp.length(),DBUG_FILE);
     if (key+store_length < key_end)

--- 1.39/sql/opt_sum.cc	2004-11-21 19:35:29 +02:00
+++ 1.40/sql/opt_sum.cc	2004-12-06 18:04:39 +02:00
@@ -562,8 +562,7 @@
       store_val_in_field(part->field, args[between && max_fl ? 2 : 1]);
       if (part->null_bit) 
         *key_ptr++= (byte) test(part->field->is_null());
-      part->field->get_key_image((char*) key_ptr, part->length,
-                                 part->field->charset(), Field::itRAW);
+      part->field->get_key_image((char*) key_ptr, part->length, Field::itRAW);
     }
     if (is_field_part)
     {

--- 1.114/sql/sql_acl.cc	2004-12-06 17:15:48 +02:00
+++ 1.115/sql/sql_acl.cc	2004-12-06 19:18:30 +02:00
@@ -1053,9 +1053,8 @@
 ulong acl_get(const char *host, const char *ip,
               const char *user, const char *db, my_bool db_is_pattern)
 {
-  ulong host_access,db_access;
+  ulong host_access= ~0, db_access= 0;
   uint i,key_length;
-  db_access=0; host_access= ~0;
   char key[ACL_KEY_LENGTH],*tmp_db,*end;
   acl_entry *entry;
   DBUG_ENTER("acl_get");
@@ -1438,6 +1437,7 @@
   TABLE_LIST tables;
   TABLE *table;
   bool error=1;
+  char user_key[MAX_KEY_LENGTH];
   DBUG_ENTER("update_user_table");
   DBUG_PRINT("enter",("user: %s  host: %s",user,host));
 
@@ -1467,11 +1467,12 @@
     DBUG_RETURN(1); /* purecov: deadcode */
   table->field[0]->store(host,(uint) strlen(host), system_charset_info);
   table->field[1]->store(user,(uint) strlen(user), system_charset_info);
+  key_copy(user_key, table->record[0], table->key_info,
+           table->key_info->key_length);
 
   table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
-  if (table->file->index_read_idx(table->record[0],0,
-				  (byte*) table->field[0]->ptr,
-				  table->key_info[0].key_length,
+  if (table->file->index_read_idx(table->record[0], 0,
+				  user_key, table->key_info->key_length,
 				  HA_READ_KEY_EXACT))
   {
     my_message(ER_PASSWORD_NO_MATCH, ER(ER_PASSWORD_NO_MATCH),
@@ -1531,8 +1532,10 @@
   const char *password= "";
   uint password_len= 0;
   char what= (revoke_grant) ? 'N' : 'Y';
-  DBUG_ENTER("replace_user_table");
+  byte user_key[MAX_KEY_LENGTH];
   LEX *lex= thd->lex;
+  DBUG_ENTER("replace_user_table");
+
   safe_mutex_assert_owner(&acl_cache->lock);
 
   if (combo.password.str && combo.password.str[0])
@@ -1549,11 +1552,13 @@
 
   table->field[0]->store(combo.host.str,combo.host.length, system_charset_info);
   table->field[1]->store(combo.user.str,combo.user.length, system_charset_info);
+  key_copy(user_key, table->record[0], table->key_info,
+           table->key_info->key_length);
+
   table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
   if (table->file->index_read_idx(table->record[0], 0,
-				  (byte*) table->field[0]->ptr,
-				  table->key_info[0].key_length,
-				  HA_READ_KEY_EXACT))
+                                  user_key, table->key_info->key_length,
+                                  HA_READ_KEY_EXACT))
   {
     /* what == 'N' means revoke */
     if (what == 'N')
@@ -1742,6 +1747,7 @@
   bool old_row_exists=0;
   int error;
   char what= (revoke_grant) ? 'N' : 'Y';
+  byte user_key[MAX_KEY_LENGTH];
   DBUG_ENTER("replace_db_table");
 
   if (!initialized)
@@ -1760,11 +1766,13 @@
   table->field[0]->store(combo.host.str,combo.host.length, system_charset_info);
   table->field[1]->store(db,(uint) strlen(db), system_charset_info);
   table->field[2]->store(combo.user.str,combo.user.length, system_charset_info);
+  key_copy(user_key, table->record[0], table->key_info,
+           table->key_info->key_length);
+
   table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
   if (table->file->index_read_idx(table->record[0],0,
-				  (byte*) table->field[0]->ptr,
-				  table->key_info[0].key_length,
-				  HA_READ_KEY_EXACT))
+                                  user_key, table->key_info->key_length,
+                                  HA_READ_KEY_EXACT))
   {
     if (what == 'N')
     { // no row, no revoke
@@ -1935,22 +1943,25 @@
                    0,0,0, (hash_get_key) get_key_column,0,0);
   if (cols)
   {
-    int key_len;
+    uint key_prefix_len;
+    KEY_PART_INFO *key_part= col_privs->key_info->key_part;
     col_privs->field[0]->store(orig_host,(uint) strlen(orig_host),
                                system_charset_info);
     col_privs->field[1]->store(db,(uint) strlen(db), system_charset_info);
     col_privs->field[2]->store(user,(uint) strlen(user), system_charset_info);
     col_privs->field[3]->store(tname,(uint) strlen(tname), system_charset_info);
-    key_len=(col_privs->field[0]->pack_length()+
-             col_privs->field[1]->pack_length()+
-             col_privs->field[2]->pack_length()+
-             col_privs->field[3]->pack_length());
-    key_copy(key,col_privs->record[0],col_privs->key_info,key_len);
+
+    key_prefix_len= (key_part[0].store_length +
+                     key_part[1].store_length +
+                     key_part[2].store_length +
+                     key_part[3].store_length);
+    key_copy(key, col_privs->record[0], col_privs->key_info, key_prefix_len);
     col_privs->field[4]->store("",0, &my_charset_latin1);
+
     col_privs->file->ha_index_init(0);
     if (col_privs->file->index_read(col_privs->record[0],
-                                    (byte*) col_privs->field[0]->ptr,
-                                    key_len, HA_READ_KEY_EXACT))
+                                    (byte*) key,
+                                    key_prefix_len, HA_READ_KEY_EXACT))
     {
       cols = 0; /* purecov: deadcode */
       col_privs->file->ha_index_end();
@@ -1972,7 +1983,7 @@
       }
       my_hash_insert(&hash_columns, (byte *) mem_check);
     } while (!col_privs->file->index_next(col_privs->record[0]) &&
-             !key_cmp_if_same(col_privs,key,0,key_len));
+             !key_cmp_if_same(col_privs,key,0,key_prefix_len));
     col_privs->file->ha_index_end();
   }
 }
@@ -2053,19 +2064,22 @@
 				ulong rights, bool revoke_grant)
 {
   int error=0,result=0;
-  uint key_length;
   byte key[MAX_KEY_LENGTH];
+  uint key_prefix_length;
+  KEY_PART_INFO *key_part= table->key_info->key_part;
   DBUG_ENTER("replace_column_table");
 
   table->field[0]->store(combo.host.str,combo.host.length, system_charset_info);
   table->field[1]->store(db,(uint) strlen(db), system_charset_info);
   table->field[2]->store(combo.user.str,combo.user.length, system_charset_info);
   table->field[3]->store(table_name,(uint) strlen(table_name),
system_charset_info);
-  key_length=(table->field[0]->pack_length()+ table->field[1]->pack_length()+
-	      table->field[2]->pack_length()+ table->field[3]->pack_length());
-  key_copy(key,table->record[0],table->key_info,key_length);
 
-  rights &= COL_ACLS;				// Only ACL for columns
+  /* Get length of 3 first key parts */
+  key_prefix_length= (key_part[0].store_length + key_part[1].store_length +
+                      key_part[2].store_length + key_part[3].store_length);
+  key_copy(key, table->record[0], table->key_info, key_prefix_length);
+
+  rights&= COL_ACLS;				// Only ACL for columns
 
   /* first fix privileges for all columns in column list */
 
@@ -2076,14 +2090,20 @@
   {
     ulong privileges = xx->rights;
     bool old_row_exists=0;
-    key_restore(table->record[0],key,table->key_info,key_length);
+    byte user_key[MAX_KEY_LENGTH];
+
+    key_restore(table->record[0],key,table->key_info,
+                key_prefix_length);
     table->field[4]->store(xx->column.ptr(),xx->column.length(),
                            system_charset_info);
+    /* Get key for the first 4 columns */
+    key_copy(user_key, table->record[0], table->key_info,
+             table->key_info->key_length);
 
     table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
-    if (table->file->index_read(table->record[0],(byte*)
table->field[0]->ptr,
-				table->key_info[0].key_length,
-				HA_READ_KEY_EXACT))
+    if (table->file->index_read(table->record[0], user_key,
+				table->key_info->key_length,
+                                HA_READ_KEY_EXACT))
     {
       if (revoke_grant)
       {
@@ -2095,7 +2115,8 @@
       }
       old_row_exists = 0;
       restore_record(table,default_values);		// Get empty record
-      key_restore(table->record[0],key,table->key_info,key_length);
+      key_restore(table->record[0],key,table->key_info,
+                  key_prefix_length);
       table->field[4]->store(xx->column.ptr(),xx->column.length(),
                              system_charset_info);
     }
@@ -2152,10 +2173,14 @@
 
   if (revoke_grant)
   {
+    byte user_key[MAX_KEY_LENGTH];
+    key_copy(user_key, table->record[0], table->key_info,
+             key_prefix_length);
+
     table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
-    if (table->file->index_read(table->record[0], (byte*)
table->field[0]->ptr,
-                                key_length,
-				HA_READ_KEY_EXACT))
+    if (table->file->index_read(table->record[0], user_key,
+				key_prefix_length,
+                                HA_READ_KEY_EXACT))
       goto end;
 
     /* Scan through all rows with the same host,db,user and table */
@@ -2169,7 +2194,8 @@
       {
 	GRANT_COLUMN *grant_column = NULL;
 	char  colum_name_buf[HOSTNAME_LENGTH+1];
-	String column_name(colum_name_buf,sizeof(colum_name_buf),system_charset_info);
+	String column_name(colum_name_buf,sizeof(colum_name_buf),
+                           system_charset_info);
 
 	privileges&= ~rights;
 	table->field[6]->store((longlong)
@@ -2205,7 +2231,7 @@
 	}
       }
     } while (!table->file->index_next(table->record[0]) &&
-	     !key_cmp_if_same(table,key,0,key_length));
+	     !key_cmp_if_same(table, key, 0, key_prefix_length));
   }
 
 end:
@@ -2224,6 +2250,7 @@
   int old_row_exists = 1;
   int error=0;
   ulong store_table_rights, store_col_rights;
+  byte user_key[MAX_KEY_LENGTH];
   DBUG_ENTER("replace_table_table");
 
   strxmov(grantor, thd->user, "@", thd->host_or_ip, NullS);
@@ -2245,10 +2272,12 @@
   table->field[2]->store(combo.user.str,combo.user.length, system_charset_info);
   table->field[3]->store(table_name,(uint) strlen(table_name),
system_charset_info);
   store_record(table,record[1]);			// store at pos 1
+  key_copy(user_key, table->record[0], table->key_info,
+           table->key_info->key_length);
+
   table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
-  if (table->file->index_read_idx(table->record[0],0,
-				  (byte*) table->field[0]->ptr,
-				  table->key_info[0].key_length,
+  if (table->file->index_read_idx(table->record[0], 0,
+                                  user_key, table->key_info->key_length,
 				  HA_READ_KEY_EXACT))
   {
     /*
@@ -3702,6 +3731,8 @@
                               Field *user_field, LEX_USER *user_to)
 {
   int error;
+  TABLE *table;
+  byte user_key[MAX_KEY_LENGTH];
   DBUG_ENTER("modify_grant_table");
 
   if (user_to)
@@ -3769,6 +3800,7 @@
   char *user_str= user_from->user.str;
   const char *host;
   const char *user;
+  uint key_prefix_length;
   DBUG_ENTER("handle_grant_table");
 
   if (! table_no) // mysql.user table
@@ -3786,8 +3818,13 @@
                        table->real_name, user_str, host_str));
     host_field->store(host_str, user_from->host.length, system_charset_info);
     user_field->store(user_str, user_from->user.length, system_charset_info);
+
+    key_prefix_length= (table->key_info->key_part[0].store_length +
+                        table->key_info->key_part[1].store_length);
+    key_copy(user_key, table->record[0], table->key_info, key_prefix_length);
+
     if ((error= table->file->index_read_idx(table->record[0], 0,
-                                            (byte*) host_field->ptr, 0,
+                                            user_key, key_prefix_length,
                                             HA_READ_KEY_EXACT)))
     {
       if (error != HA_ERR_KEY_NOT_FOUND)
@@ -4058,7 +4095,8 @@
   else
   {
     /* Handle user array. */
-    if ((handle_grant_struct(0, drop, user_from, user_to) && ! result) || found)
+    if ((handle_grant_struct(0, drop, user_from, user_to) && ! result) ||
+        found)
     {
       result= 1; /* At least one record/element found. */
       /* If search is requested, we do not need to search further. */
@@ -4120,6 +4158,7 @@
   DBUG_RETURN(result);
 }
 
+
 static void append_user(String *str, LEX_USER *user)
 {
   if (str->length())
@@ -4131,6 +4170,7 @@
   str->append('\'');
 }
 
+
 /*
   Create a list of users.
 
@@ -4298,6 +4338,7 @@
   DBUG_RETURN(result);
 }
 
+
 /*
   Revoke all privileges from a list of users.
 
@@ -4332,9 +4373,8 @@
   {
     if (!check_acl_user(lex_user, &counter))
     {
-      sql_print_error("REVOKE ALL PRIVILEGES, GRANT: User '%s'@'%s' not exists",
-		      lex_user->user.str,
-		      lex_user->host.str);
+      sql_print_error("REVOKE ALL PRIVILEGES, GRANT: User '%s'@'%s' does not "
+                      "exists", lex_user->user.str, lex_user->host.str);
       result= -1;
       continue;
     }

--- 1.195/sql/sql_base.cc	2004-12-06 02:05:23 +02:00
+++ 1.196/sql/sql_base.cc	2004-12-06 18:04:39 +02:00
@@ -1063,31 +1063,6 @@
     for (uint i=0 ; i < table->fields ; i++)
       table->field[i]->table_name=table->table_name;
   }
-#if MYSQL_VERSION_ID < 40100
-  /*
-    If per-connection "new" variable (represented by variables.new_mode)
-    is set then we should pretend that the length of TIMESTAMP field is 19.
-    The cheapest (from perfomance viewpoint) way to achieve that is to set
-    field_length of all Field_timestamp objects in a table after opening
-    it (to 19 if new_mode is true or to original field length otherwise).
-    We save value of new_mode variable in TABLE::timestamp_mode to
-    not perform this setup if new_mode value is the same between sequential
-    table opens.
-  */
-  my_bool new_mode= thd->variables.new_mode;
-  if (table->timestamp_mode != new_mode)
-  {
-    for (uint i=0 ; i < table->fields ; i++)
-    {
-      Field *field= table->field[i];
-
-      if (field->type() == FIELD_TYPE_TIMESTAMP)
-        field->field_length= new_mode ? 19 :
-                             ((Field_timestamp *)(field))->orig_field_length;
-    }
-    table->timestamp_mode= new_mode;
-  }
-#endif
   /* These variables are also set in reopen_table() */
   table->tablenr=thd->current_tablenr++;
   table->used_fields=0;

--- 1.373/sql/sql_parse.cc	2004-12-06 17:15:48 +02:00
+++ 1.374/sql/sql_parse.cc	2004-12-06 19:18:30 +02:00
@@ -118,15 +118,20 @@
 static bool end_active_trans(THD *thd)
 {
   int error=0;
+  DBUG_ENTER("end_active_trans");
   if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN |
 		      OPTION_TABLE_LOCK))
   {
+    DBUG_PRINT("info",("options: 0x%lx", (ulong) thd->options));
     thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
+    /* Safety if one did "drop table" on locked tables */
+    if (!thd->locked_tables)
+      thd->options&= ~OPTION_TABLE_LOCK;
     thd->server_status&= ~SERVER_STATUS_IN_TRANS;
     if (ha_commit(thd))
       error=1;
   }
-  return error;
+  DBUG_RETURN(error);
 }
 
 
@@ -4736,7 +4741,7 @@
   LEX  *lex= thd->lex;
   uint allowed_type_modifier=0;
   uint sign_len;
-  char warn_buff[MYSQL_ERRMSG_SIZE];
+  ulong max_field_charlength= MAX_FIELD_CHARLENGTH;
   DBUG_ENTER("add_field_to_list");
 
   if (strlen(field_name) > NAME_LEN)
@@ -4812,7 +4817,7 @@
   new_field->length=0;
   new_field->change=change;
   new_field->interval=0;
-  new_field->pack_length=0;
+  new_field->pack_length= new_field->key_length= 0;
   new_field->charset=cs;
   new_field->geom_type= (Field::geometry_type) uint_geom_type;
 
@@ -4884,36 +4889,22 @@
 	new_field->length++;
     }
     break;
-  case FIELD_TYPE_STRING:
-  case FIELD_TYPE_VAR_STRING:
-    if (new_field->length <= MAX_FIELD_CHARLENGTH || default_value)
-      break;
-    /* Convert long CHAR() and VARCHAR columns to TEXT or BLOB */
-    new_field->sql_type= FIELD_TYPE_BLOB;
-    sprintf(warn_buff, ER(ER_AUTO_CONVERT), field_name, "CHAR",
-	    (cs == &my_charset_bin) ? "BLOB" : "TEXT");
-    push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_AUTO_CONVERT,
-		 warn_buff);
-    /* fall through */
+  case MYSQL_TYPE_VARCHAR:
+    /*
+      We can't use pack_length as this includes the field length
+      Long VARCHAR's are automaticly converted to blobs in mysql_prepare_table
+      if they don't have a default value
+    */
+    new_field->key_length= new_field->length;
+    max_field_charlength= MAX_FIELD_VARCHARLENGTH;
+    break;
+  case MYSQL_TYPE_STRING:
+    break;
   case FIELD_TYPE_BLOB:
   case FIELD_TYPE_TINY_BLOB:
   case FIELD_TYPE_LONG_BLOB:
   case FIELD_TYPE_MEDIUM_BLOB:
   case FIELD_TYPE_GEOMETRY:
-    if (new_field->length)
-    {
-      /* The user has given a length to the blob column */
-      if (new_field->length < 256)
-	type= FIELD_TYPE_TINY_BLOB;
-      if (new_field->length < 65536)
-	type= FIELD_TYPE_BLOB;
-      else if (new_field->length < 256L*256L*256L)
-	type= FIELD_TYPE_MEDIUM_BLOB;
-      else
-	type= FIELD_TYPE_LONG_BLOB;
-      new_field->length= 0;
-    }
-    new_field->sql_type= type;
     if (default_value)				// Allow empty as default value
     {
       String str,*res;
@@ -5055,8 +5046,8 @@
         when we know the character set of the column
       */
       new_field->length= 1;
+      break;
     }
-    break;
   case FIELD_TYPE_ENUM:
     {
       // Should be safe
@@ -5067,18 +5058,23 @@
       while ((tmp= it++))
         new_field->interval_list.push_back(tmp);
       new_field->length= 1; // See comment for FIELD_TYPE_SET above.
-    }
+      break;
+   }
+  case MYSQL_TYPE_VAR_STRING:
+    DBUG_ASSERT(0);                             // Impossible
     break;
   }
 
-  if ((new_field->length > MAX_FIELD_CHARLENGTH && type != FIELD_TYPE_SET
&& 
-       type != FIELD_TYPE_ENUM) ||
-      (!new_field->length && !(new_field->flags & BLOB_FLAG) &&
-       type != FIELD_TYPE_STRING &&
-       type != FIELD_TYPE_VAR_STRING && type != FIELD_TYPE_GEOMETRY))
+  if (!(new_field->flags & BLOB_FLAG) &&
+      ((new_field->length > max_field_charlength && type != FIELD_TYPE_SET
&& 
+        type != FIELD_TYPE_ENUM &&
+        (type != MYSQL_TYPE_VARCHAR || default_value)) ||
+       (!new_field->length &&
+        type != MYSQL_TYPE_STRING &&
+        type != MYSQL_TYPE_VARCHAR && type != FIELD_TYPE_GEOMETRY)))
   {
     my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0),
-                    field_name, MAX_FIELD_CHARLENGTH);/* purecov: inspected */
+             field_name, max_field_charlength); /* purecov: inspected */
     DBUG_RETURN(1);				/* purecov: inspected */
   }
   type_modifier&= AUTO_INCREMENT_FLAG;
@@ -5088,11 +5084,10 @@
     DBUG_RETURN(1);
   }
   if (!new_field->pack_length)
-    new_field->pack_length=calc_pack_length(new_field->sql_type ==
-					    FIELD_TYPE_VAR_STRING ?
-					    FIELD_TYPE_STRING :
-					    new_field->sql_type,
-					    new_field->length);
+    new_field->pack_length= calc_pack_length(new_field->sql_type,
+                                             new_field->length);
+  if (!new_field->key_length)
+    new_field->key_length= new_field->pack_length;
   lex->create_list.push_back(new_field);
   lex->last_field=new_field;
   DBUG_RETURN(0);
@@ -5136,7 +5131,6 @@
   {
 #ifdef USE_MB
     int l;
-/*    if ((l = ismbchar(name, name+MBMAXLEN))) { Wei He: I think it's wrong */
     if (use_mb(system_charset_info) &&
         (l = my_ismbchar(system_charset_info, name, strend)))
     {

--- 1.260/sql/sql_select.cc	2004-12-06 17:15:49 +02:00
+++ 1.261/sql/sql_select.cc	2004-12-06 18:04:39 +02:00
@@ -7539,7 +7539,8 @@
   Field *new_field;
 
   if (convert_blob_length && org_field->flags & BLOB_FLAG)
-    new_field= new Field_varstring(convert_blob_length, org_field->maybe_null(),
+    new_field= new Field_varstring(convert_blob_length,
+                                   org_field->maybe_null(),
                                    org_field->field_name, table,
                                    org_field->charset());
   else
@@ -7552,7 +7553,8 @@
       new_field->field_name= item->name;
     if (org_field->maybe_null())
       new_field->flags&= ~NOT_NULL_FLAG;	// Because of outer join
-    if (org_field->type() == FIELD_TYPE_VAR_STRING)
+    if (org_field->type() == MYSQL_TYPE_VAR_STRING ||
+        org_field->type() == MYSQL_TYPE_VARCHAR)
       table->db_create_options|= HA_OPTION_PACK_RECORD;
   }
   return new_field;
@@ -7759,6 +7761,11 @@
   for send_fields
 */
 
+#define STRING_TOTAL_LENGTH_TO_PACK_ROWS 128
+#define AVG_STRING_LENGTH_TO_PACK_ROWS   64
+#define RATIO_TO_PACK_ROWS	       2
+#define MIN_STRING_LENGTH_TO_PACK_ROWS   10
+
 TABLE *
 create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
 		 ORDER *group, bool distinct, bool save_sum_fields,
@@ -7766,10 +7773,13 @@
 		 char *table_alias)
 {
   TABLE *table;
-  uint	i,field_count,reclength,null_count,null_pack_length,
-        hidden_null_count, hidden_null_pack_length, hidden_field_count,
-	blob_count,group_null_items;
-  bool	using_unique_constraint=0;
+  uint	i,field_count,null_count,null_pack_length;
+  uint  hidden_null_count, hidden_null_pack_length, hidden_field_count;
+  uint  blob_count,group_null_items, string_count;
+  uint  temp_pool_slot=MY_BIT_NONE;
+  ulong reclength, string_total_length;
+  bool  using_unique_constraint= 0;
+  bool  use_packed_rows= 0;
   bool  not_all_columns= !(select_options & TMP_TABLE_ALL_COLUMNS);
   char	*tmpname,path[FN_REFLEN], filename[FN_REFLEN];
   byte	*pos,*group_buff;
@@ -7780,8 +7790,6 @@
   KEY_PART_INFO *key_part_info;
   Item **copy_func;
   MI_COLUMNDEF *recinfo;
-  uint temp_pool_slot=MY_BIT_NONE;
-
   DBUG_ENTER("create_tmp_table");
   DBUG_PRINT("enter",("distinct: %d  save_sum_fields: %d  rows_limit: %lu  group: %d",
 		      (int) distinct, (int) save_sum_fields,
@@ -7876,7 +7884,8 @@
 
   /* Calculate which type of fields we will store in the temporary table */
 
-  reclength=blob_count=null_count=hidden_null_count=group_null_items=0;
+  reclength= string_total_length= 0;
+  blob_count= string_count= null_count= hidden_null_count= group_null_items= 0;
   param->using_indirect_summary_function=0;
 
   List_iterator_fast<Item> li(fields);
@@ -7923,6 +7932,12 @@
 	    *blob_field++= new_field;
 	    blob_count++;
 	  }
+          if (new_field->real_type() == MYSQL_TYPE_STRING ||
+              new_field->real_type() == MYSQL_TYPE_VARCHAR)
+          {
+            string_count++;
+            string_total_length+= new_field->pack_length();
+          }
           thd->change_item_tree(argp, new Item_field(new_field));
 	  if (!(new_field->flags & NOT_NULL_FLAG))
           {
@@ -8016,6 +8031,12 @@
   reclength+=null_pack_length;
   if (!reclength)
     reclength=1;				// Dummy select
+  /* Use packed rows if there is blobs or a lot of space to gain */
+  if (blob_count ||
+      string_total_length >= STRING_TOTAL_LENGTH_TO_PACK_ROWS &&
+      (reclength / string_total_length <= RATIO_TO_PACK_ROWS ||
+       string_total_length / string_count >= AVG_STRING_LENGTH_TO_PACK_ROWS))
+    use_packed_rows= 1;
 
   table->fields=field_count;
   table->reclength=reclength;
@@ -8090,10 +8111,9 @@
     recinfo->length=length;
     if (field->flags & BLOB_FLAG)
       recinfo->type= (int) FIELD_BLOB;
-    else if (!field->zero_pack() &&
-	     (field->type() == FIELD_TYPE_STRING ||
-	      field->type() == FIELD_TYPE_VAR_STRING) &&
-	     length >= 10 && blob_count)
+    else if (use_packed_rows &&
+             field->real_type() == MYSQL_TYPE_STRING &&
+	     length >= MIN_STRING_LENGTH_TO_PACK_ROWS)
       recinfo->type=FIELD_SKIP_ENDSPACE;
     else
       recinfo->type=FIELD_NORMAL;
@@ -8168,6 +8188,8 @@
 	}
 	else
 	  group->field->move_field((char*) group_buff);
+        /* In GROUP BY 'a' and 'a ' are equal for VARCHAR fields */
+        key_part_info->key_part_flag|= HA_END_SPACE_ARE_EQUAL;
 	group_buff+= key_part_info->length;
       }
       keyinfo->key_length+=  key_part_info->length;
@@ -8338,12 +8360,10 @@
       }
       else
       {
-	seg->type=
-	  ((keyinfo->key_part[i].key_type & FIELDFLAG_BINARY) ?
-	   HA_KEYTYPE_BINARY : HA_KEYTYPE_TEXT);
-	if (!(field->flags & ZEROFILL_FLAG) &&
-	    (field->type() == FIELD_TYPE_STRING ||
-	     field->type() == FIELD_TYPE_VAR_STRING) &&
+	seg->type= ((keyinfo->key_part[i].key_type & FIELDFLAG_BINARY) ?
+                    HA_KEYTYPE_BINARY : HA_KEYTYPE_TEXT);
+        /* Tell handler if it can do suffic space compression */
+	if (field->real_type() == MYSQL_TYPE_STRING &&
 	    keyinfo->key_part[i].length > 4)
 	  seg->flag|=HA_SPACE_PACK;
       }
@@ -9846,6 +9866,7 @@
   DBUG_RETURN(0);
 }
 
+
 /* Like end_update, but this is done with unique constraints instead of keys */
 
 static int
@@ -9993,11 +10014,11 @@
 	/*
 	  We can remove binary fields and numerical fields except float,
 	  as float comparison isn't 100 % secure
-	  We have to keep binary strings to be able to check for end spaces
+	  We have to keep normal strings to be able to check for end spaces
 	*/
 	if (field->binary() &&
-	    field->real_type() != FIELD_TYPE_STRING &&
-	    field->real_type() != FIELD_TYPE_VAR_STRING &&
+	    field->real_type() != MYSQL_TYPE_STRING &&
+	    field->real_type() != MYSQL_TYPE_VARCHAR &&
 	    (field->type() != FIELD_TYPE_FLOAT || field->decimals() == 0))
 	{
 	  return !store_val_in_field(field,right_item);

--- 1.199/sql/sql_table.cc	2004-12-06 17:15:49 +02:00
+++ 1.200/sql/sql_table.cc	2004-12-06 19:18:30 +02:00
@@ -433,6 +433,9 @@
   DESCRIPTION
     Prepares the table and key structures for table creation.
 
+  NOTES
+    sets create_info->varchar if the table has a varchar or blob.
+
   RETURN VALUES
     0	ok
     -1	error
@@ -447,20 +450,24 @@
   const char	*key_name;
   create_field	*sql_field,*dup_field;
   uint		field,null_fields,blob_columns;
+  uint		max_key_length= file->max_key_length();
   ulong		pos;
   KEY		*key_info;
   KEY_PART_INFO *key_part_info;
   int		timestamps= 0, timestamps_with_niladic= 0;
   int		field_no,dup_no;
   int		select_field_pos,auto_increment=0;
+  List_iterator<create_field> it(fields),it2(fields);
   DBUG_ENTER("mysql_prepare_table");
 
-  List_iterator<create_field> it(fields),it2(fields);
   select_field_pos=fields.elements - select_field_count;
   null_fields=blob_columns=0;
+  create_info->varchar= 0;
 
   for (field_no=0; (sql_field=it++) ; field_no++)
   {
+    CHARSET_INFO *save_cs;
+
     if (!sql_field->charset)
       sql_field->charset= create_info->default_table_charset;
     /*
@@ -472,13 +479,13 @@
     if (create_info->table_charset && sql_field->charset !=
&my_charset_bin)
       sql_field->charset= create_info->table_charset;
 
-    CHARSET_INFO *savecs= sql_field->charset;
+    save_cs= sql_field->charset;
     if ((sql_field->flags & BINCMP_FLAG) &&
 	!(sql_field->charset= get_charset_by_csname(sql_field->charset->csname,
 						    MY_CS_BINSORT,MYF(0))))
     {
       char tmp[64];
-      strmake(strmake(tmp, savecs->csname, sizeof(tmp)-4), "_bin", 4);
+      strmake(strmake(tmp, save_cs->csname, sizeof(tmp)-4), "_bin", 4);
       my_error(ER_UNKNOWN_COLLATION, MYF(0), tmp);
       DBUG_RETURN(-1);
     }
@@ -569,10 +576,41 @@
     }
 
     sql_field->create_length_to_internal_length();
+    if (sql_field->length > MAX_FIELD_VARCHARLENGTH &&
+        !(sql_field->flags & BLOB_FLAG))
+    {
+      /* Convert long VARCHAR columns to TEXT or BLOB */
+      char warn_buff[MYSQL_ERRMSG_SIZE];
+
+      if (sql_field->def)
+      {
+        my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), sql_field->field_name,
+                 MAX_FIELD_VARCHARLENGTH / sql_field->charset->mbmaxlen);
+        DBUG_RETURN(-1);
+      }
+      sql_field->sql_type= FIELD_TYPE_BLOB;
+      sql_field->flags|= BLOB_FLAG;
+      sprintf(warn_buff, ER(ER_AUTO_CONVERT), sql_field->field_name,
+              "VARCHAR",
+              (sql_field->charset == &my_charset_bin) ? "BLOB" : "TEXT");
+      push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_AUTO_CONVERT,
+                   warn_buff);
+    }
+    
+    if ((sql_field->flags & BLOB_FLAG) && sql_field->length)
+    {
+      if (sql_field->sql_type == FIELD_TYPE_BLOB)
+      {
+        /* The user has given a length to the blob column */
+        sql_field->sql_type= get_blob_type_from_length(sql_field->length);
+        sql_field->pack_length= calc_pack_length(sql_field->sql_type, 0);
+      }
+      sql_field->length= 0;                     // Probably from an item
+    }
 
-    /* Don't pack keys in old tables if the user has requested this */
+    /* Don't pack rows in old tables if the user has requested this */
     if ((sql_field->flags & BLOB_FLAG) ||
-	sql_field->sql_type == FIELD_TYPE_VAR_STRING &&
+	sql_field->sql_type == MYSQL_TYPE_VARCHAR &&
 	create_info->row_type != ROW_TYPE_FIXED)
     {
       db_options|=HA_OPTION_PACK_RECORD;
@@ -646,6 +684,7 @@
       sql_field->length=8;			// Unireg field length
       sql_field->unireg_check=Field::BLOB_FIELD;
       blob_columns++;
+      create_info->varchar= 1;
       break;
     case FIELD_TYPE_GEOMETRY:
 #ifdef HAVE_SPATIAL
@@ -662,17 +701,37 @@
       sql_field->length=8;			// Unireg field length
       sql_field->unireg_check=Field::BLOB_FIELD;
       blob_columns++;
+      create_info->varchar= 1;
       break;
 #else
       my_error(ER_FEATURE_DISABLED, MYF(0),
                sym_group_geom.name, sym_group_geom.needed_define);
       DBUG_RETURN(-1);
 #endif /*HAVE_SPATIAL*/
-    case FIELD_TYPE_VAR_STRING:
-    case FIELD_TYPE_STRING:
+    case MYSQL_TYPE_VARCHAR:
+#ifndef QQ_ALL_HANDLERS_SUPPORT_VARCHAR
+      if (file->table_flags() & HA_NO_VARCHAR)
+      {
+        /* convert VARCHAR to CHAR because handler is not yet up to date */
+        sql_field->sql_type=    MYSQL_TYPE_VAR_STRING;
+        sql_field->pack_length= calc_pack_length(sql_field->sql_type,
+                                                 (uint) sql_field->length);
+        if ((sql_field->length / sql_field->charset->mbmaxlen) >
+            MAX_FIELD_CHARLENGTH)
+        {
+          my_printf_error(ER_TOO_BIG_FIELDLENGTH, ER(ER_TOO_BIG_FIELDLENGTH),
+                          MYF(0), sql_field->field_name, MAX_FIELD_CHARLENGTH);
+          DBUG_RETURN(-1);
+        }
+      }
+      else
+#endif
+        create_info->varchar= 1;
+      /* fall through */
+    case MYSQL_TYPE_STRING:
       sql_field->pack_flag=0;
       if (sql_field->charset->state & MY_CS_BINSORT)
-	sql_field->pack_flag|=FIELDFLAG_BINARY;
+	sql_field->pack_flag|= FIELDFLAG_BINARY;
       break;
     case FIELD_TYPE_ENUM:
       sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
@@ -953,6 +1012,7 @@
     CHARSET_INFO *ft_key_charset=0;  // for FULLTEXT
     for (uint column_nr=0 ; (column=cols++) ; column_nr++)
     {
+      uint length;
       key_part_spec *dup_column;
 
       it.rewind();
@@ -981,8 +1041,8 @@
       cols2.rewind();
       if (key->type == Key::FULLTEXT)
       {
-	if ((sql_field->sql_type != FIELD_TYPE_STRING &&
-	     sql_field->sql_type != FIELD_TYPE_VAR_STRING &&
+	if ((sql_field->sql_type != MYSQL_TYPE_STRING &&
+	     sql_field->sql_type != MYSQL_TYPE_VARCHAR &&
 	     !f_is_blob(sql_field->pack_flag)) ||
 	    sql_field->charset == &my_charset_bin ||
 	    sql_field->charset->mbminlen > 1 || // ucs2 doesn't work yet
@@ -1019,15 +1079,15 @@
 	  }
 	}
 #ifdef HAVE_SPATIAL
-	if (key->type  == Key::SPATIAL)
+	if (key->type == Key::SPATIAL)
 	{
-	  if (!column->length )
+	  if (!column->length)
 	  {
 	    /*
-	    BAR: 4 is: (Xmin,Xmax,Ymin,Ymax), this is for 2D case
-		 Lately we'll extend this code to support more dimensions
+              4 is: (Xmin,Xmax,Ymin,Ymax), this is for 2D case
+              Lately we'll extend this code to support more dimensions
 	    */
-	    column->length=4*sizeof(double);
+	    column->length= 4*sizeof(double);
 	  }
 	}
 #endif
@@ -1063,7 +1123,8 @@
       key_part_info->fieldnr= field;
       key_part_info->offset=  (uint16) sql_field->offset;
       key_part_info->key_type=sql_field->pack_flag;
-      uint length=sql_field->pack_length;
+      length= sql_field->key_length;
+
       if (column->length)
       {
 	if (f_is_blob(sql_field->pack_flag))
@@ -1128,12 +1189,13 @@
       /* Use packed keys for long strings on the first column */
       if (!(db_options & HA_OPTION_NO_PACK_KEYS) &&
 	  (length >= KEY_DEFAULT_PACK_LENGTH &&
-	   (sql_field->sql_type == FIELD_TYPE_STRING ||
-	    sql_field->sql_type == FIELD_TYPE_VAR_STRING ||
+	   (sql_field->sql_type == MYSQL_TYPE_STRING ||
+	    sql_field->sql_type == MYSQL_TYPE_VARCHAR ||
 	    sql_field->pack_flag & FIELDFLAG_BLOB)))
       {
-	if (column_nr == 0 && (sql_field->pack_flag & FIELDFLAG_BLOB))
-	  key_info->flags|= HA_BINARY_PACK_KEY;
+	if (column_nr == 0 && (sql_field->pack_flag & FIELDFLAG_BLOB) ||
+            sql_field->sql_type == MYSQL_TYPE_VARCHAR)
+	  key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
 	else
 	  key_info->flags|= HA_PACK_KEY;
       }
@@ -1173,7 +1235,6 @@
     if (!(key_info->flags & HA_NULL_PART_KEY))
       unique_key=1;
     key_info->key_length=(uint16) key_length;
-    uint max_key_length= file->max_key_length();
     if (key_length > max_key_length && key->type != Key::FULLTEXT)
     {
       my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);

--- 1.315/sql/sql_yacc.yy	2004-12-06 02:05:24 +02:00
+++ 1.316/sql/sql_yacc.yy	2004-12-06 18:04:40 +02:00
@@ -2773,13 +2773,13 @@
 					  Lex->charset=&my_charset_bin;
 					  $$=FIELD_TYPE_STRING; }
 	| varchar '(' NUM ')' opt_binary { Lex->length=$3.str;
-					  $$=FIELD_TYPE_VAR_STRING; }
+					  $$= MYSQL_TYPE_VARCHAR; }
 	| nvarchar '(' NUM ')'		{ Lex->length=$3.str;
-					  $$=FIELD_TYPE_VAR_STRING;
+					  $$= MYSQL_TYPE_VARCHAR;
 					  Lex->charset=national_charset_info; }
 	| VARBINARY '(' NUM ')' 	{ Lex->length=$3.str;
 					  Lex->charset=&my_charset_bin;
-					  $$=FIELD_TYPE_VAR_STRING; }
+					  $$= MYSQL_TYPE_VARCHAR; }
 	| YEAR_SYM opt_len field_options { $$=FIELD_TYPE_YEAR; }
 	| DATE_SYM			{ $$=FIELD_TYPE_DATE; }
 	| TIME_SYM			{ $$=FIELD_TYPE_TIME; }

--- 1.41/sql/structs.h	2004-11-18 13:53:18 +02:00
+++ 1.42/sql/structs.h	2004-12-06 18:04:40 +02:00
@@ -98,6 +98,7 @@
   union {
     int  bdb_return_if_eq;
   } handler;
+  struct st_table *table;
 } KEY;
 
 

--- 1.130/sql/table.cc	2004-11-25 15:33:29 +02:00
+++ 1.131/sql/table.cc	2004-12-06 18:04:40 +02:00
@@ -139,7 +139,8 @@
   *fn_ext(outparam->path)='\0';		// Remove extension
 
   if (head[0] != (uchar) 254 || head[1] != 1 ||
-      (head[2] != FRM_VER && head[2] != FRM_VER+1 && head[2] !=
FRM_VER+3))
+      (head[2] != FRM_VER && head[2] != FRM_VER+1 &&
+       ! (head[2] >= FRM_VER+3 && head[2] <= FRM_VER+4)))
     goto err_not_open;				/* purecov: inspected */
   new_field_pack_flag=head[27];
   new_frm_ver= (head[2] - FRM_VER);
@@ -215,7 +216,8 @@
 
   for (i=0 ; i < keys ; i++, keyinfo++)
   {
-    if (new_frm_ver == 3)
+    keyinfo->table= outparam;
+    if (new_frm_ver >= 3)
     {
       keyinfo->flags=	   (uint) uint2korr(strpos) ^ HA_NOSAME;
       keyinfo->key_length= (uint) uint2korr(strpos+2);
@@ -433,7 +435,7 @@
     Field::geometry_type geom_type= Field::GEOM_GEOMETRY;
     LEX_STRING comment;
 
-    if (new_frm_ver == 3)
+    if (new_frm_ver >= 3)
     {
       /* new frm file in 4.1 */
       field_length= uint2korr(strpos+3);
@@ -441,11 +443,10 @@
       pack_flag=    uint2korr(strpos+8);
       unireg_type=  (uint) strpos[10];
       interval_nr=  (uint) strpos[12];
-
       uint comment_length=uint2korr(strpos+15);
       field_type=(enum_field_types) (uint) strpos[13];
 
-      // charset and geometry_type share the same byte in frm
+      /* charset and geometry_type share the same byte in frm */
       if (field_type == FIELD_TYPE_GEOMETRY)
       {
 #ifdef HAVE_SPATIAL
@@ -609,10 +610,12 @@
 	    keyinfo->key_length+= HA_KEY_NULL_LENGTH;
 	  }
 	  if (field->type() == FIELD_TYPE_BLOB ||
-	      field->real_type() == FIELD_TYPE_VAR_STRING)
+	      field->real_type() == MYSQL_TYPE_VARCHAR)
 	  {
 	    if (field->type() == FIELD_TYPE_BLOB)
 	      key_part->key_part_flag|= HA_BLOB_PART;
+            else
+              key_part->key_part_flag|= HA_VAR_LENGTH_PART;
 	    keyinfo->extra_length+=HA_KEY_BLOB_LENGTH;
 	    key_part->store_length+=HA_KEY_BLOB_LENGTH;
 	    keyinfo->key_length+= HA_KEY_BLOB_LENGTH;
@@ -1232,7 +1235,11 @@
   if ((file=my_create(name,CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0)
   {
     bzero((char*) fileinfo,64);
-    fileinfo[0]=(uchar) 254; fileinfo[1]= 1; fileinfo[2]= FRM_VER+3; // Header
+    /* header */
+    fileinfo[0]=(uchar) 254;
+    fileinfo[1]= 1;
+    fileinfo[2]= FRM_VER+3+ test(create_info->varchar);
+
     fileinfo[3]= (uchar) ha_checktype(create_info->db_type);
     fileinfo[4]=1;
     int2store(fileinfo+6,IO_SIZE);		/* Next block starts here */
@@ -1385,7 +1392,7 @@
     if (use_mb(system_charset_info))
     {
       int len=my_ismbchar(system_charset_info, name, 
-		name+system_charset_info->mbmaxlen);
+                          name+system_charset_info->mbmaxlen);
       if (len)
       {
         name += len;
@@ -1462,7 +1469,7 @@
     if (use_mb(system_charset_info))
     {
       int len=my_ismbchar(system_charset_info, name, 
-		name+system_charset_info->mbmaxlen);
+                          name+system_charset_info->mbmaxlen);
       if (len)
       {
         name += len;
@@ -1497,7 +1504,8 @@
   error=my_read(file,(byte*) head,4,MYF(MY_NABP));
   my_close(file,MYF(0));
   if (error || head[0] != (uchar) 254 || head[1] != 1 ||
-      (head[2] != FRM_VER && head[2] != FRM_VER+1 && head[2] !=
FRM_VER+3))
+      (head[2] != FRM_VER && head[2] != FRM_VER+1 &&
+       (head[2] < FRM_VER+3 || head[2] > FRM_VER+4)))
     DBUG_RETURN(DB_TYPE_UNKNOWN);
   DBUG_RETURN(ha_checktype((enum db_type) (uint) *(head+3)));
 }

--- 1.78/sql/table.h	2004-11-25 02:26:56 +02:00
+++ 1.79/sql/table.h	2004-12-06 19:18:30 +02:00
@@ -160,7 +160,8 @@
   my_bool no_keyread, no_cache;
   my_bool clear_query_id;               /* To reset query_id for tables and cols */
   my_bool auto_increment_field_not_null;
-  my_bool alias_name_used; /* true if table_name is alias */
+  my_bool insert_or_update;             /* Can be used by the handler */
+  my_bool alias_name_used;		/* true if table_name is alias */
   Field *next_number_field,		/* Set if next_number is activated */
 	*found_next_number_field,	/* Set on open */
         *rowid_field;

--- 1.52/strings/ctype-czech.c	2004-11-22 09:58:35 +02:00
+++ 1.53/strings/ctype-czech.c	2004-12-06 18:04:40 +02:00
@@ -275,8 +275,9 @@
 
 static
 int my_strnncollsp_czech(CHARSET_INFO * cs, 
-			const uchar *s, uint slen, 
-			const uchar *t, uint tlen)
+                         const uchar *s, uint slen, 
+                         const uchar *t, uint tlen,
+                         my_bool diff_if_only_endspace_difference)
 {
   for ( ; slen && s[slen-1] == ' ' ; slen--);
   for ( ; tlen && t[tlen-1] == ' ' ; tlen--);
@@ -352,7 +353,7 @@
 
 #ifdef REAL_MYSQL
 
-#define min_sort_char ' '
+#define min_sort_char 0
 #define max_sort_char '9'
 
 #define EXAMPLE
@@ -391,8 +392,17 @@
 
     *min_str++= *max_str++ = *ptr;
   }
-  *min_length= (uint) (min_str - min_org);
+
+  if (cs->state & MY_CS_BINSORT)
+    *min_length= (uint) (min_str - min_org);
+  else
+  {
+    /* 'a\0\0... is the smallest possible string */
+    *min_length= res_length;
+  }
+  /* a\ff\ff... is the biggest possible string */
   *max_length= res_length;
+
   while (min_str != min_end)
   {
     *min_str++ = min_sort_char;	/* Because of key compression */

--- 1.78/strings/ctype-tis620.c	2004-11-16 14:45:32 +02:00
+++ 1.79/strings/ctype-tis620.c	2004-12-06 19:18:30 +02:00
@@ -320,7 +320,7 @@
     /*0xFC*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
     /*0xFD*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
     /*0xFE*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
-/* Utilize 0xFF for max_sort_chr in my_like_range_tis620 */
+    /* Utilize 0xFF for max_sort_chr in my_like_range_tis620 */
     /*0xFF*/ { 255 /*IGNORE*/, IGNORE, IGNORE, IGNORE, X },
 };
 
@@ -559,12 +559,16 @@
 static
 int my_strnncollsp_tis620(CHARSET_INFO * cs __attribute__((unused)),
 			  const uchar *a0, uint a_length, 
-			  const uchar *b0, uint b_length)
+			  const uchar *b0, uint b_length,
+                          my_bool diff_if_only_endspace_difference)
 {
-  uchar	buf[80] ;
-  uchar *end, *a, *b, *alloced= NULL;
+  uchar	buf[80], *end, *a, *b, alloced= NULL;
   uint length;
   int res= 0;
+
+#ifndef VARCHAR_WITH_DIFF_ENDSPACE_ARE_DIFFERENT_FOR_UNIQUE
+  diff_if_only_endspace_difference= 0;
+#endif
   
   a= buf;
   if ((a_length + b_length +2) > (int) sizeof(buf))
@@ -590,6 +594,8 @@
   if (a_length != b_length)
   {
     int swap= 0;
+    if (diff_if_only_endspace_difference)
+      res= 1;                                   /* Assume 'a' is bigger */
     /*
       Check the next not space character of the longer key. If it's < ' ',
       then it's smaller than the other key.
@@ -600,6 +606,7 @@
       a_length= b_length;
       a= b;
       swap= -1;					/* swap sign of result */
+      res= -res;
     }
     for (end= a + a_length-length; a < end ; a++)
     {
@@ -683,8 +690,14 @@
     }
     if (*ptr == w_many)				/* '%' in SQL */
     {
-      *min_length= (uint) (min_str - min_org);
-      *max_length=res_length;
+      /*
+        Calculate length of keys:
+        'a\0\0... is the smallest possible string when we have space expand
+        a\ff\ff... is the biggest possible string
+      */
+      *min_length= ((cs->state & MY_CS_BINSORT) ? (uint) (min_str - min_org) :
+                    res_length);
+      *max_length= res_length;
       do
       {
 	*min_str++ = 0;
@@ -694,10 +707,10 @@
     }
     *min_str++= *max_str++ = *ptr;
   }
-  *min_length= *max_length = (uint) (min_str - min_org);
 
+ *min_length= *max_length = (uint) (min_str - min_org);
   while (min_str != min_end)
-    *min_str++ = *max_str++ = ' ';	/* Because of key compression */
+    *min_str++= *max_str++ = ' ';      /* Because of key compression */
   return 0;
 }
 

--- 1.7/mysql-test/r/ctype_tis620.result	2004-11-15 19:26:09 +02:00
+++ 1.8/mysql-test/r/ctype_tis620.result	2004-12-06 18:04:36 +02:00
@@ -259,8 +259,8 @@
 ¡Ñ³°ªÒ
 ¡Ñ³°Ô¡Ò
 ¡Ñ³·ÔÁÒ
-¡Ñ¹µì
 ¡Ñ¹µÔ¡Ã
+¡Ñ¹µì
 ¡Ñ¹¸ÔªÒ
 ¡Ñ¹¸ÔÁÒ
 ¡Ñ¹ÂÒÃѵ¹ì
@@ -272,8 +272,8 @@
 ¡Ò­¨¹ó
 ¡Ò­¨¹Ò
 ¡Ò¹´Ò
-¡Ò¹µì
 ¡Ò¹µìÃÇÕ
+¡Ò¹µì
 ¡ÒÂÊÔ·¸Ôì
 ¡ÒÃÇÔÍÃ
 ¡ÒÃØ³Õ
@@ -350,8 +350,8 @@
 õÔÈÑ¡´Ôì
 õÔÊÇÑÊ´Ôì
 à¡×éÍ¡ÙÅ
-á¡éÇ
 á¡éÇã¨
+á¡éÇ
 â¡Ážѹ¸ì
 â¡àÁÈ
 â¡ÅºÍÅ ¤Í¹à¹ç¤ªÑè¹Êì
@@ -368,8 +368,8 @@
 ¢¨õÔ
 ¢¨ÃÈÃÕ
 ¢¨ÃÈÑ¡´Ôì
-¢¹Ôɰì
 ¢¹ÔɰÒ
+¢¹Ôɰì
 ¢ÇÑ­ã¨
 ¢ÇÑ­ªÑÂ
 ¢ÇÑ­à´×͹
@@ -412,8 +412,8 @@
 ठÊËÒÂÍÔÁà»ê¡«ì
 à¤.«Õ.¾Õ. áÁªªÕ¹à¹ÍÃÕè
 षշÕÅÔÊ«Ôè§
-ह áÁ¡«ì (»ÃÐà·Èä·Â)
 ह áÁç¡«ì (»ÃÐà·Èä·Â)
+ह áÁ¡«ì (»ÃÐà·Èä·Â)
 à¤Ã×ÍÇÑÅÂì
 ᤹¹Ù ÍÔ¹ô
 á¤Ð¨éÍÂ
@@ -494,12 +494,12 @@
 ¨ÓàÃÔ­
 ¨ÓÅͧ
 ¨Ô³³ì
-¨Ôµµì
 ¨Ôµµì¹ÔÉÒ
 ¨ÔµµÁÒÊ
 ¨ÔµµÒ
 ¨ÔµµÔ
 ¨ÔµµÔ¹¹Ñ¹·ì
+¨Ôµµì
 ¨ÔµÃÅ´Ò
 ¨ÔµÃÒ
 ¨Ôµóì
@@ -627,10 +627,10 @@
 ªÇ¹¾ÔÈ
 ªÇÅÔµ
 ªÇÔÈÒ
-ªèÍ
 ªèͩѵÃ
 ªèÍ·Ô¾Âì
 ªèÍÍÑ­ªÑ­
+ªèÍ
 ªÐ¹ÔÅ
 ªÐÍé͹
 ªÑªªÑÂ
@@ -758,12 +758,12 @@
 ³¸ÔµÒ
 ³ÀÑ·Ã
 ³ÀÑ·áóì
-³ç¤ì
 ³ç¤ìªÑÂ
 ³ç¤ì¾ÑªÃì
 ³ç¤ìÄ·¸Ôì
 ³ç¤ìÇÔ·Âì
 ³ç¤ìÈÑ¡´Ôì
+³ç¤ì
 ³çÃÑ¡Éì
 ³çÄ·¸Ôì
 ³çÈÑ¡´Ôì
@@ -862,11 +862,11 @@
 µÐÇѹ
 µÑ觨Ñè§ËÅÍ´ä¿
 µÒà¿ç´
-µØê
 µØê¡µÒ
 µØéÁ
 µØëÂ
 µØÅÒÅѡɳì
+µØê
 àµçÁà´ª
 àµ×͹ã¨
 àµ×͹µÒ
@@ -917,8 +917,8 @@
 ·Ñº·ÔÁ
 ·Ñȹó
 ·ÑȹվÃ
-·ÑȹÕÂì
 ·ÑȹÕÂÒ
+·ÑȹÕÂì
 ·ó
 ·èÒ·ÃÒÂá¨é§ÇѲ¹Ò
 ·Ô¦ÑÁ¾Ã
@@ -1088,8 +1088,8 @@
 ¹þÅ
 ¹ÃÀÑ·Ãì
 ¹ÃÒ
-¹ÃÔ¹·Ãì
 ¹ÃÔ¹·Ãìà´ª
+¹ÃÔ¹·Ãì
 ¹ÃÔÈ
 ¹ÃÔɰ
 ¹ÃÕ
@@ -1115,8 +1115,8 @@
 ¹Ñ·¸Á¹
 ¹Ñ¹ªÑÂ
 ¹Ñ¹·ªÑÂ
-¹Ñ¹·¹ì
 ¹Ñ¹·¹Ò
+¹Ñ¹·¹ì
 ¹Ñ¹·¾Ã
 ¹Ñ¹·¾Å
 ¹Ñ¹·ÁÒÊ
@@ -1148,14 +1148,14 @@
 ¹Ôà«Ð
 ¹Ô´
 ¹Ô´Ò
-¹ÔµÂì
 ¹ÔµÂÒ
+¹ÔµÂì
 ¹ÔµÔ
 ¹ÔµÔ¾§Éì
 ¹ÔµÔÁÒ
 ¹Ô·ÃÒ
-¹Ô·Ñȹì
 ¹Ô·ÑȹÕÂì
+¹Ô·Ñȹì
 ¹Ô¸ÔÇ´Õ
 ¹Ô»»Í¹à¾¹µì(»ÃÐà·Èä·Â)
 ¹Ô¾¹¸ì
@@ -1349,8 +1349,8 @@
 »ÃÒ³ÕÂì
 »ÃÒâÁ·Âì
 »ö¹Ò
-»ÃÔ­­ì
 »ÃÔ­­Ò
+»ÃÔ­­ì
 »ÃÔ­´Ò
 »ÃÔ³´Ò
 »ÃÔ·ÑÈ
@@ -1454,10 +1454,10 @@
 ¾§ÉìÈÑ¡´Ôì
 ¾§ÉìÊѹµì
 ¾§Éì͹ѹµì
-¾¨¹ì
 ¾¨¹Ò
 ¾¨¹ö
 ¾¨¹ÕÂì
+¾¨¹ì
 ¾¨ÁÒ¹
 ¾¨ÁÒÅÂì
 ¾¹Á
@@ -1504,8 +1504,8 @@
 ¾äì
 ¾ÃËÁ¾Ñ²¹ì
 ¾ÃéÍÁªÑÂ
-¾ÃлÃÐá´§ Î͹´éÒ¤ÒÃìÊì
 ¾ÃлÃÐá´§ Î͹´éÒ¤ÒÃìÊì ¨Ó¡Ñ´
+¾ÃлÃÐá´§ Î͹´éÒ¤ÒÃìÊì
 ¾ÃÐÃÒÁ 3 ¤ÒÃìà«ç¹àµÍÃì
 ¾ÃÐÃÒÁ 3 Î͹´éÒ¤ÒÃìÊì
 ¾ÃÔéÁà¾ÃÒ
@@ -1604,10 +1604,10 @@
 ¾Ùŷͧ¾Ãç;à¾ÍÃìµÕé_
 ¾ÙżÅ
 à¾ç§ ¿Ù ËÅÔ¹
-à¾çªÃì
 ྪÃÃѵ¹ì
 ྪÃÅ´Ò
 ྪÃÔ¹·Ãì
+à¾çªÃì
 à¾ç­¨Ñ¹·Ãì
 à¾ç­·Ô¾Âì
 à¾ç­¹ÀÒ
@@ -1831,7 +1831,6 @@
 ÃÒàÁÈÃì
 ÃÒÂÕ¹
 Ã×è¹ÇÃÒËì
-ÃØé§
 ÃØè§·Ô¾Âì
 ÃØè§·ÔÇÒ
 ÃØè§¹ÀÒ
@@ -1840,11 +1839,12 @@
 ÃØè§Ãѵ¹ì
 ÃØè§ÃÑÈÁÕ
 ÃØè§àÃ×ͧ
-è¹ì
 è¹ì¢¹Êè§
+è¹ì
 ó
 ÃØè§ÇÔ·Âì
 ÃØè§ÍÃØ³
+ÃØé§
 ÃØ¨Ò
 ÃØ¨ÒÀÒ
 ÃØËйÒ
@@ -1861,8 +1861,8 @@
 þᾤ ¤Í¹ÊµÃѤªÑè¹
 ç§Ò¹àËÅç¡¡ÃØ§à·¾Ï
 è¹ì»ÃÐàÊÃÔ°
-Ä·¸Ôì
 Ä·¸ÔªÑÂ
+Ä·¸Ôì
 ÅÅÔ´Ò
 ÅÅÔµÒ
 ÅÐÁèÍÁ
@@ -2050,8 +2050,8 @@
 ó
 ÇÔÇ
 ø¹ì
-ÇÔÇѲ¹ì
 ÇÔÇѲ¹ìªÑÂ
+ÇÔÇѲ¹ì
 ÇÔȹÕ
 ÇÔÈÃØµ
 ÇÔÈÒÅ
@@ -2146,11 +2146,11 @@
 ÈÈÔÇÔÁÅ
 ÈÈÔÉÒ
 ÈÑ¡´Ò
-ÈÑ¡´Ôì
 ÈÑ¡´ÔìªÑÂ
 ÈÑ¡´ÔìàªÇ§
 ÈÑ¡´Ôì´Ò
 ÈÑ¡´ÔìÇÔºÙÅÂì
+ÈÑ¡´Ôì
 ÈÑ¡ÃÔ¹·Ãì
 ÈѹʹÕÂì
 ÈÒ¹µÔᏴì
@@ -2348,18 +2348,18 @@
 ÊÓÃÒ­
 ÊÓÄ·¸Ôì
 ÊÓÅÕ
-ÊÔ§Ëì
 ÊÔ§Ëì¾Å
 ÊÔ§ËÒ
+ÊÔ§Ëì
 ÊԵҹѹ
 ÊÔµÒ¾Ã
 ÊÔ·¸Ò
-ÊÔ·¸Ôì
 ÊÔ·¸ÔªÑÂ
 ÊÔ·¸Ôà´ª
 ÊÔ·¸Ô¾Ã
 ÊÔ·¸Ô¾ó
 ÊÔ·¸Ô¾Å
+ÊÔ·¸Ôì
 ÊÔ¹·ÇÕ
 ÊÔÃÔªÑÂ
 ÊÔÃÔà´ª
@@ -2393,15 +2393,15 @@
 ÊØ¢ÊÇÑÊ´šÒÃ
 ÊØ¢Êѹµì
 ÊØ¢ØÁ
-ÊØ¤¹¸ì
 ÊØ¤¹¸Ò
+ÊØ¤¹¸ì
 ÊØ¨ÒÃÕ
 ÊØ¨Ôµ
 ÊØ¨ÔµµÒ
 ÊØ¨ÔµÃÒ
 ÊØ¨Ô¹´Ò
-ÊØ¨Ô¹µì
 ÊØ¨Ô¹µ¹ì
+ÊØ¨Ô¹µì
 ÊØªÅ
 ÊØªÑÂ
 ÊØªÒ´Ò
@@ -2443,13 +2443,13 @@
 ÊØ¸Ô´Ò
 ÊØ¸ÔÈÑ¡´Ôì
 ÊØ¸Õ
-ÊØ¸ÕÃì
 ÊØ¸ÕÃÒ
+ÊØ¸ÕÃì
 ÊØ¹·Ã
 ÊØ¹·ÃÕ
 ÊØ¹Ñ··Õ
-ÊØ¹Ñ¹·ì
 ÊØ¹Ñ¹·Ò
+ÊØ¹Ñ¹·ì
 ÊØ¹ÔµÒ
 ÊØ¹ÔÈÒ
 ÊØ¹ÔÉÒ
@@ -2511,10 +2511,10 @@
 ÊØÃÈÑ¡´Ôì
 ÊØÃÊÔ·¸Ôì
 ÊØÃѪ¹Õ¡Ã
-ÊØÃѵ¹ì
 ÊØÃѵ¹Ç´Õ
 ÊØÃѵ¹ìÇ´Õ
 ÊØÃѵ¹Ò
+ÊØÃѵ¹ì
 ÊØÃѵÂÒ
 ÊØÃÒ§¤¹Ò
 ÊØÃÔªÑÂ
@@ -2529,8 +2529,8 @@
 ÊØÃÕ¸Ò¾Ã
 ÊØÃÕ¾Ã
 ÊØÃÕÁÒÈ
-ÊØÃÕÂì
 ÊØÃÕÂì¾Ã
+ÊØÃÕÂì
 ÊØÃÕÃѵ¹ì
 ÊØÅÑ´´Ò
 ÊØÇÀÑ·Ãì
@@ -2540,9 +2540,9 @@
 óÕ
 óÕÂì
 ÊØÇÃѵ¹ì
-ÊØÇѲ¹ì
 ÊØÇѲ¹ìªÑÂ
 ÊØÇѲ¹Ò
+ÊØÇѲ¹ì
 ÊØÇѵªÑÂ
 ÊØÇÒÃÕ
 ÊØÇÔªÑÂ
@@ -2623,8 +2623,8 @@
 ͹¹·ì
 ͹ÇѪ
 ͹ѭ­Ò
-͹ѹµì
 ͹ѹµÈÑ¡´Ôì
+͹ѹµì
 ͹ءԵÔ
 ͹ءÙÅ
 ͹تÒ
@@ -2770,8 +2770,8 @@
 ÍÒÃÒ¾Ã
 ÍÒÃÔÂÒ
 ÍÒÃÕ
-ÍÒÃÕÂì
 ÍÒÃÕÂì  àÊÁÒ©ÔÁ  (ä·Âູ¡Ñ¹
+ÍÒÃÕÂì
 ÍÒÃÕÃѵ¹ì
 ó
 ÍÓ¹ÇÂ

--- 1.26/strings/ctype-uca.c	2004-11-24 18:07:20 +02:00
+++ 1.27/strings/ctype-uca.c	2004-12-06 18:04:40 +02:00
@@ -7048,6 +7048,9 @@
     slen	First string length
     t		Second string
     tlen	Seconf string length
+    diff_if_only_endspace_difference
+		        Set to 1 if the strings should be regarded as different
+                        if they only difference in end space
   
   NOTES:
     Works exactly the same with my_strnncoll_uca(),
@@ -7085,13 +7088,16 @@
 static int my_strnncollsp_uca(CHARSET_INFO *cs, 
                               my_uca_scanner_handler *scanner_handler,
                               const uchar *s, uint slen,
-                              const uchar *t, uint tlen)
+                              const uchar *t, uint tlen,
+                              my_bool diff_if_only_endspace_difference)
 {
-  my_uca_scanner sscanner;
-  my_uca_scanner tscanner;
-  int s_res;
-  int t_res;
+  my_uca_scanner sscanner, tscanner;
+  int s_res, t_res;
   
+#ifndef VARCHAR_WITH_DIFF_ENDSPACE_ARE_DIFFERENT_FOR_UNIQUE
+  diff_if_only_endspace_difference= 0;
+#endif
+
   scanner_handler->init(&sscanner, cs, s, slen);
   scanner_handler->init(&tscanner, cs, t, tlen);
   
@@ -7113,7 +7119,7 @@
         return (s_res - t_res);
       s_res= scanner_handler->next(&sscanner);
     } while (s_res > 0);
-    return 0;
+    return diff_if_only_endspace_difference ? 1 : 0;
   }
     
   if (s_res < 0 && t_res > 0)
@@ -7128,7 +7134,7 @@
         return (s_res - t_res);
       t_res= scanner_handler->next(&tscanner);
     } while (t_res > 0);
-    return 0;
+    return diff_if_only_endspace_difference ? -1 : 0;
   }
   
   return ( s_res - t_res );
@@ -7941,11 +7947,13 @@
 }
 
 static int my_strnncollsp_any_uca(CHARSET_INFO *cs,
-                              const uchar *s, uint slen,
-                              const uchar *t, uint tlen)
+                                  const uchar *s, uint slen,
+                                  const uchar *t, uint tlen,
+                                  my_bool diff_if_only_endspace_difference)
 {
   return my_strnncollsp_uca(cs, &my_any_uca_scanner_handler,
-                            s, slen, t, tlen);
+                            s, slen, t, tlen,
+                            diff_if_only_endspace_difference);
 }   
 
 static void my_hash_sort_any_uca(CHARSET_INFO *cs,
@@ -7978,11 +7986,13 @@
 }
 
 static int my_strnncollsp_ucs2_uca(CHARSET_INFO *cs,
-                              const uchar *s, uint slen,
-                              const uchar *t, uint tlen)
+                                   const uchar *s, uint slen,
+                                   const uchar *t, uint tlen,
+                                   my_bool diff_if_only_endspace_difference)
 {
   return my_strnncollsp_uca(cs, &my_ucs2_uca_scanner_handler,
-                            s, slen, t, tlen);
+                            s, slen, t, tlen,
+                            diff_if_only_endspace_difference);
 }   
 
 static void my_hash_sort_ucs2_uca(CHARSET_INFO *cs,

--- 1.17/mysql-test/r/ctype_ucs.result	2004-12-06 02:05:20 +02:00
+++ 1.18/mysql-test/r/ctype_ucs.result	2004-12-06 18:04:36 +02:00
@@ -23,16 +23,24 @@
 binary 'a  a' > 'a'	binary 'a  \0' > 'a'	binary 'a\0' > 'a'
 1	1	1
 SET CHARACTER SET koi8r;
-CREATE TABLE t1 (word VARCHAR(64) CHARACTER SET ucs2);
-INSERT INTO t1 VALUES (_koi8r'ò'), (X'2004');
+CREATE TABLE t1 (word VARCHAR(64) CHARACTER SET ucs2, word2 CHAR(64) CHARACTER SET ucs2);
+INSERT INTO t1 VALUES (_koi8r'ò',_koi8r'ò'), (X'2004',X'2004');
 SELECT hex(word) FROM t1 ORDER BY word;
 hex(word)
 0420
 2004
+SELECT hex(word2) FROM t1 ORDER BY word2;
+hex(word2)
+0420
+2004
 DELETE FROM t1;
-INSERT INTO t1 VALUES (X'042000200020'), (X'200400200020');
+INSERT INTO t1 VALUES (X'042000200020',X'042000200020'), (X'200400200020',
X'200400200020');
 SELECT hex(word) FROM t1 ORDER BY word;
 hex(word)
+042000200020
+200400200020
+SELECT hex(word2) FROM t1 ORDER BY word2;
+hex(word2)
 0420
 2004
 DROP TABLE t1;

--- 1.17/mysql-test/t/ctype_ucs.test	2004-12-06 02:05:20 +02:00
+++ 1.18/mysql-test/t/ctype_ucs.test	2004-12-06 18:04:37 +02:00
@@ -20,17 +20,19 @@
 # which contains 0x20 in the high byte.
 #
 
-CREATE TABLE t1 (word VARCHAR(64) CHARACTER SET ucs2);
-INSERT INTO t1 VALUES (_koi8r'ò'), (X'2004');
+CREATE TABLE t1 (word VARCHAR(64) CHARACTER SET ucs2, word2 CHAR(64) CHARACTER SET ucs2);
+INSERT INTO t1 VALUES (_koi8r'ò',_koi8r'ò'), (X'2004',X'2004');
 SELECT hex(word) FROM t1 ORDER BY word;
+SELECT hex(word2) FROM t1 ORDER BY word2;
 DELETE FROM t1;
 
 #
 # Check that real spaces are correctly trimmed.
 #
 
-INSERT INTO t1 VALUES (X'042000200020'), (X'200400200020');
+INSERT INTO t1 VALUES (X'042000200020',X'042000200020'), (X'200400200020',
X'200400200020');
 SELECT hex(word) FROM t1 ORDER BY word;
+SELECT hex(word2) FROM t1 ORDER BY word2;
 DROP TABLE t1;
 
 #
@@ -52,7 +54,6 @@
 SHOW CREATE TABLE t1;
 DROP TABLE t1;
 
-
 #
 # BUG3946
 #
@@ -61,6 +62,7 @@
 insert into t2 values ("103000"), ("22720000"), ("3401200"), ("78000");
 select lpad(f1, 12, "-o-/") from t2;
 drop table t2;
+
 ######################################################
 #
 # Test of like

--- 1.33/strings/ctype-ucs2.c	2004-12-01 17:25:00 +02:00
+++ 1.34/strings/ctype-ucs2.c	2004-12-06 19:18:30 +02:00
@@ -137,6 +137,9 @@
   int res;
   const uchar *e=s+slen;
 
+  while (e > s+1 && e[-1] == ' ' && e[-2] == '\0')
+    e-= 2;
+
   while ((s < e) && (res=my_ucs2_uni(cs,&wc, (uchar *)s, (uchar*)e))
>0)
   {
     int plane = (wc>>8) & 0xFF;
@@ -247,14 +250,16 @@
 
 static int my_strnncollsp_ucs2(CHARSET_INFO *cs __attribute__((unused)),
                                const uchar *s, uint slen,
-                               const uchar *t, uint tlen)
+                               const uchar *t, uint tlen,
+                               my_bool diff_if_only_endspace_difference
+			       __attribute__((unused)))
 {
   const uchar *se, *te;
   uint minlen;
 
   /* extra safety to make sure the lengths are even numbers */
-  slen= (slen >> 1) << 1;
-  tlen= (tlen >> 1) << 1;
+  slen&= ~1;
+  tlen&= ~1;
 
   se= s + slen;
   te= t + tlen;
@@ -1354,8 +1359,10 @@
 
 static int my_strnncollsp_ucs2_bin(CHARSET_INFO *cs, 
                                    const uchar *s, uint slen, 
-                                   const uchar *t, uint tlen)
+                                   const uchar *t, uint tlen,
+                                   my_bool diff_if_only_endspace_difference)
 {
+  /* TODO: Needs to be fixed to handle end space! */
   return my_strnncoll_ucs2_bin(cs,s,slen,t,tlen,0);
 }
 
@@ -1444,8 +1451,14 @@
     }
     if (ptr[0] == '\0' && ptr[1] == w_many)	/* '%' in SQL */
     {
-      *min_length= (uint) (min_str - min_org);
-      *max_length=res_length;
+      /*
+        Calculate length of keys:
+        'a\0\0... is the smallest possible string when we have space expand
+        a\ff\ff... is the biggest possible string
+      */
+      *min_length= ((cs->state & MY_CS_BINSORT) ? (uint) (min_str - min_org) :
+                    res_length);
+      *max_length= res_length;
       do {
         *min_str++ = 0;
 	*min_str++ = 0;
@@ -1457,7 +1470,6 @@
     *min_str++= *max_str++ = ptr[0];
     *min_str++= *max_str++ = ptr[1];
   }
-  *min_length= *max_length = (uint) (min_str - min_org);
 
   /* Temporary fix for handling w_one at end of string (key compression) */
   {
@@ -1469,13 +1481,15 @@
     }
   }
   
+  *min_length= *max_length = (uint) (min_str - min_org);
   while (min_str + 1 < min_end)
   {
     *min_str++ = *max_str++ = '\0';
-    *min_str++ = *max_str++ = ' ';	/* Because if key compression */
+    *min_str++ = *max_str++ = ' ';      /* Because if key compression */
   }
   return 0;
 }
+
 
 static MY_COLLATION_HANDLER my_collation_ucs2_general_ci_handler =
 {

--- 1.34/strings/ctype-mb.c	2004-11-19 12:25:21 +02:00
+++ 1.35/strings/ctype-mb.c	2004-12-06 19:18:30 +02:00
@@ -362,6 +362,9 @@
     slen		Length of 's'
     t			String to compare
     tlen		Length of 't'
+    diff_if_only_endspace_difference
+		        Set to 1 if the strings should be regarded as different
+                        if they only difference in end space
 
   NOTE
    This function is used for character strings with binary collations.
@@ -376,10 +379,16 @@
 
 static int my_strnncollsp_mb_bin(CHARSET_INFO * cs __attribute__((unused)),
                                  const uchar *a, uint a_length, 
-                                 const uchar *b, uint b_length)
+                                 const uchar *b, uint b_length,
+                                 my_bool diff_if_only_endspace_difference)
 {
   const uchar *end;
   uint length;
+  int res;
+
+#ifndef VARCHAR_WITH_DIFF_ENDSPACE_ARE_DIFFERENT_FOR_UNIQUE
+  diff_if_only_endspace_difference= 0;
+#endif
   
   end= a + (length= min(a_length, b_length));
   while (a < end)
@@ -387,9 +396,12 @@
     if (*a++ != *b++)
       return ((int) a[-1] - (int) b[-1]);
   }
+  res= 0;
   if (a_length != b_length)
   {
     int swap= 0;
+    if (diff_if_only_endspace_difference)
+      res= 1;                                   /* Assume 'a' is bigger */
     /*
       Check the next not space character of the longer key. If it's < ' ',
       then it's smaller than the other key.
@@ -400,6 +412,7 @@
       a_length= b_length;
       a= b;
       swap= -1;					/* swap sign of result */
+      res= -res;
     }
     for (end= a + a_length-length; a < end ; a++)
     {
@@ -407,7 +420,7 @@
 	return ((int) *a - (int) ' ') ^ swap;
     }
   }
-  return 0;
+  return res;
 }
 
 
@@ -523,9 +536,15 @@
       if (charlen < (uint) (min_str - min_org))
         min_str= min_org + charlen;
       
-      /* Write min key  */
-      *min_length= (uint) (min_str - min_org);
+      /*
+        Calculate length of keys:
+        'a\0\0... is the smallest possible string when we have space expand
+        a\ff\ff... is the biggest possible string
+      */
+      *min_length= ((cs->state & MY_CS_BINSORT) ? (uint) (min_str - min_org) :
+                    res_length);
       *max_length= res_length;
+      /* Create min key  */
       do
       {
 	*min_str++= (char) cs->min_sort_char;
@@ -541,13 +560,13 @@
     }
     *min_str++= *max_str++ = *ptr;
   }
-  *min_length= *max_length = (uint) (min_str - min_org);
 
+ *min_length= *max_length = (uint) (min_str - min_org);
   while (min_str != min_end)
-    *min_str++= ' ';		/* Because if key compression */
-  pad_max_char(cs, max_str, max_end);
+    *min_str++= *max_str= ' ';            /* Because if key compression */
   return 0;
 }
+
 
 static int my_wildcmp_mb_bin(CHARSET_INFO *cs,
 		  const char *str,const char *str_end,

--- 1.78/strings/ctype-utf8.c	2004-11-24 18:07:20 +02:00
+++ 1.79/strings/ctype-utf8.c	2004-12-06 18:04:40 +02:00
@@ -1923,12 +1923,20 @@
   }
 }
 
-static void my_hash_sort_utf8(CHARSET_INFO *cs, const uchar *s, uint slen, ulong *n1,
ulong *n2)
+static void my_hash_sort_utf8(CHARSET_INFO *cs, const uchar *s, uint slen,
+                              ulong *n1, ulong *n2)
 {
   my_wc_t wc;
   int res;
   const uchar *e=s+slen;
 
+  /*
+    Remove end space. We have to do this to be able to compare
+    'A ' and 'A' as identical
+  */
+  while (e > s && e[-1] == ' ')
+    e--;
+
   while ((s < e) && (res=my_utf8_uni(cs,&wc, (uchar *)s, (uchar*)e))>0
)
   {
     int plane = (wc>>8) & 0xFF;
@@ -2021,6 +2029,9 @@
     a_length            Length of 'a'
     b                   Second string to compare
     b_length            Length of 'b'
+    diff_if_only_endspace_difference
+		        Set to 1 if the strings should be regarded as different
+                        if they only difference in end space
 
   IMPLEMENTATION
     If one string is shorter as the other, then we space extend the other
@@ -2039,13 +2050,17 @@
 */
 
 static int my_strnncollsp_utf8(CHARSET_INFO *cs,
-                             const uchar *s, uint slen,
-                             const uchar *t, uint tlen)
+                               const uchar *s, uint slen,
+                               const uchar *t, uint tlen,
+                               my_bool diff_if_only_endspace_difference)
 {
-  int s_res,t_res;
+  int s_res, t_res, res;
   my_wc_t s_wc,t_wc;
-  const uchar *se= s+slen;
-  const uchar *te= t+tlen;
+  const uchar *se= s+slen, *te= t+tlen;
+
+#ifndef VARCHAR_WITH_DIFF_ENDSPACE_ARE_DIFFERENT_FOR_UNIQUE
+  diff_if_only_endspace_difference= 0;
+#endif
 
   while ( s < se && t < te )
   {
@@ -2074,16 +2089,20 @@
 
   slen= se-s;
   tlen= te-t;
+  res= 0;
 
   if (slen != tlen)
   {
     int swap= 0;
+    if (diff_if_only_endspace_difference)
+      res= 1;                                   /* Assume 'a' is bigger */
     if (slen < tlen)
     {
       slen= tlen;
       s= t;
       se= te;
       swap= -1;
+      res= -res;
     }
     /*
       This following loop uses the fact that in UTF-8
@@ -2101,7 +2120,7 @@
         return ((int)*s -  (int) ' ') ^ swap;
     }
   }
-  return 0;
+  return res;
 }
 
 

--- 1.42/strings/ctype-win1250ch.c	2004-11-22 09:58:35 +02:00
+++ 1.43/strings/ctype-win1250ch.c	2004-12-06 18:04:40 +02:00
@@ -479,7 +479,8 @@
 static
 int my_strnncollsp_win1250ch(CHARSET_INFO * cs, 
 			     const uchar *s, uint slen, 
-			     const uchar *t, uint tlen)
+			     const uchar *t, uint tlen,
+                             my_bool diff_if_only_endspace_difference)
 {
   for ( ; slen && s[slen-1] == ' ' ; slen--);
   for ( ; tlen && t[tlen-1] == ' ' ; tlen--);
@@ -594,11 +595,19 @@
     if (*min_str != min_sort_char)
       only_min_found= 0;
     min_str++;
-    *max_str++ = like_range_prefix_max_win1250ch[(uint)(*ptr)];
+    *max_str++= like_range_prefix_max_win1250ch[(uint)(*ptr)];
   }
 
-  *min_length = (uint) (min_str - min_org);
-  *max_length = res_length;
+  if (cs->state & MY_CS_BINSORT)
+    *min_length= (uint) (min_str - min_org);
+  else
+  {
+    /* 'a\0\0... is the smallest possible string */
+    *min_length= res_length;
+  }
+  /* a\ff\ff... is the biggest possible string */
+  *max_length= res_length;
+
   while (min_str != min_end)
   {
     *min_str++ = min_sort_char;

--- 1.92/mysql-test/r/subselect.result	2004-12-06 02:05:20 +02:00
+++ 1.93/mysql-test/r/subselect.result	2004-12-06 18:04:37 +02:00
@@ -361,10 +361,10 @@
 INSERT INTO t8 (pseudo,email) VALUES ('2joce1','2test1');
 EXPLAIN EXTENDED SELECT pseudo,(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8
WHERE pseudo='joce')) FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce');
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	PRIMARY	t8	const	PRIMARY	PRIMARY	35	const	1	Using index
-4	SUBQUERY	t8	const	PRIMARY	PRIMARY	35		1	Using index
-2	SUBQUERY	t8	const	PRIMARY	PRIMARY	35	const	1	
-3	SUBQUERY	t8	const	PRIMARY	PRIMARY	35		1	Using index
+1	PRIMARY	t8	ref	PRIMARY	PRIMARY	37	const	1	Using where; Using index
+4	SUBQUERY	t8	ref	PRIMARY	PRIMARY	37		1	
+2	SUBQUERY	t8	ref	PRIMARY	PRIMARY	37	const	1	Using where
+3	SUBQUERY	t8	ref	PRIMARY	PRIMARY	37		1	
 Warnings:
 Note	1003	select `test`.`t8`.`pseudo` AS `pseudo`,(select `test`.`t8`.`email` AS `email`
from `test`.`t8` where (`test`.`t8`.`pseudo` = (select `test`.`t8`.`pseudo` AS `pseudo`
from `test`.`t8` where (`test`.`t8`.`pseudo` = _latin1'joce')))) AS `(SELECT email FROM
t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce'))` from `test`.`t8` where
(`test`.`t8`.`pseudo` = (select `test`.`t8`.`pseudo` AS `pseudo` from `test`.`t8` where
(`test`.`t8`.`pseudo` = _latin1'joce')))
 SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo,email FROM
@@ -390,13 +390,13 @@
 ('43506','2002-10-02','joce'),('40143','2002-08-03','joce');
 EXPLAIN EXTENDED SELECT DISTINCT date FROM t1 WHERE date='2002-08-03';
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t1	index	NULL	PRIMARY	41	NULL	2	Using where; Using index
+1	SIMPLE	t1	index	NULL	PRIMARY	43	NULL	2	Using where; Using index
 Warnings:
 Note	1003	select distinct `test`.`t1`.`date` AS `date` from `test`.`t1` where
(`test`.`t1`.`date` = 20020803)
 EXPLAIN EXTENDED SELECT (SELECT DISTINCT date FROM t1 WHERE date='2002-08-03');
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
-2	SUBQUERY	t1	index	NULL	PRIMARY	41	NULL	2	Using where; Using index
+2	SUBQUERY	t1	index	NULL	PRIMARY	43	NULL	2	Using where; Using index
 Warnings:
 Note	1003	select (select distinct `test`.`t1`.`date` AS `date` from `test`.`t1` where
(`test`.`t1`.`date` = 20020803)) AS `(SELECT DISTINCT date FROM t1 WHERE
date='2002-08-03')`
 SELECT DISTINCT date FROM t1 WHERE date='2002-08-03';

--- 1.14/mysql-test/r/ps_1general.result	2004-11-25 22:55:43 +02:00
+++ 1.15/mysql-test/r/ps_1general.result	2004-12-06 18:04:37 +02:00
@@ -277,7 +277,7 @@
 prepare stmt4 from ' show table status from test like ''t9%'' ';
 execute stmt4;
 Name	Engine	Version	Row_format	Rows	Avg_row_length	Data_length	Max_data_length	Index_length	Data_free	Auto_increment	Create_time	Update_time	Check_time	Collation	Checksum	Create_options	Comment
-t9	MyISAM	9	Dynamic	2	220	440	4294967295	2048	0	NULL	#	#	#	latin1_swedish_ci	NULL		
+t9	MyISAM	10	Dynamic	2	222	444	4294967295	2048	0	NULL	#	#	#	latin1_swedish_ci	NULL		
 prepare stmt4 from ' show status like ''Threads_running'' ';
 execute stmt4;
 Variable_name	Value
@@ -291,7 +291,7 @@
 prepare stmt4 from ' show full processlist ';
 execute stmt4;
 Id	User	Host	db	Command	Time	State	Info
-number	root	localhost	test	Query	0	NULL	show full processlist
+number	root	localhost	test	Query	seconds	NULL	show full processlist
 prepare stmt4 from ' show grants for user ';
 prepare stmt4 from ' show create table t2 ';
 ERROR HY000: This command is not supported in the prepared statement protocol yet

--- 1.11/mysql-test/r/ps_2myisam.result	2004-11-11 19:54:00 +02:00
+++ 1.12/mysql-test/r/ps_2myisam.result	2004-12-06 18:04:37 +02:00
@@ -69,7 +69,7 @@
 def	test	t9	t9	c18	c18	1	1	1	Y	32768	0	63
 def	test	t9	t9	c19	c19	1	1	1	Y	32768	0	63
 def	test	t9	t9	c20	c20	254	1	1	Y	0	0	8
-def	test	t9	t9	c21	c21	253	10	10	Y	0	0	8
+def	test	t9	t9	c21	c21	254	10	10	Y	0	0	8
 def	test	t9	t9	c22	c22	253	30	30	Y	0	0	8
 def	test	t9	t9	c23	c23	252	255	8	Y	144	0	63
 def	test	t9	t9	c24	c24	252	255	8	Y	16	0	8
@@ -1705,8 +1705,8 @@
 info: Records: 3  Duplicates: 0  Warnings: 0
 select a,b from t2 order by a ;
 a	b
-3	duplicate
-4	duplicate
+3	duplicate 
+4	duplicate 
 103	three
 delete from t2 ;
 prepare stmt1 from ' insert into t2 (b,a) 
@@ -1777,11 +1777,11 @@
   `param04` longtext,
   `const05` binary(3) NOT NULL default '',
   `param05` longblob,
-  `const06` varchar(10) NOT NULL default '',
+  `const06` char(10) NOT NULL default '',
   `param06` longtext,
   `const07` date default NULL,
   `param07` longblob,
-  `const08` varchar(19) NOT NULL default '',
+  `const08` char(19) NOT NULL default '',
   `param08` longtext,
   `const09` datetime default NULL,
   `param09` longblob,
@@ -1807,11 +1807,11 @@
 def	test	t5	t5	param04	param04	252	16777215	3	Y	16	0	8
 def	test	t5	t5	const05	const05	254	3	3	N	129	0	63
 def	test	t5	t5	param05	param05	252	16777215	3	Y	144	0	63
-def	test	t5	t5	const06	const06	253	10	10	N	1	0	8
+def	test	t5	t5	const06	const06	254	10	10	N	1	0	8
 def	test	t5	t5	param06	param06	252	16777215	10	Y	16	0	8
 def	test	t5	t5	const07	const07	10	10	10	Y	128	0	63
 def	test	t5	t5	param07	param07	252	16777215	10	Y	144	0	63
-def	test	t5	t5	const08	const08	253	19	19	N	1	0	8
+def	test	t5	t5	const08	const08	254	19	19	N	1	0	8
 def	test	t5	t5	param08	param08	252	16777215	19	Y	16	0	8
 def	test	t5	t5	const09	const09	12	19	19	Y	128	0	63
 def	test	t5	t5	param09	param09	252	16777215	19	Y	144	0	63

--- 1.13/mysql-test/r/ps_3innodb.result	2004-11-11 19:54:00 +02:00
+++ 1.14/mysql-test/r/ps_3innodb.result	2004-12-06 18:04:37 +02:00
@@ -69,8 +69,8 @@
 def	test	t9	t9	c18	c18	1	1	1	Y	32768	0	63
 def	test	t9	t9	c19	c19	1	1	1	Y	32768	0	63
 def	test	t9	t9	c20	c20	254	1	1	Y	0	0	8
-def	test	t9	t9	c21	c21	253	10	10	Y	0	0	8
-def	test	t9	t9	c22	c22	253	30	30	Y	0	0	8
+def	test	t9	t9	c21	c21	254	10	10	Y	0	0	8
+def	test	t9	t9	c22	c22	254	30	30	Y	0	0	8
 def	test	t9	t9	c23	c23	252	255	8	Y	144	0	63
 def	test	t9	t9	c24	c24	252	255	8	Y	16	0	8
 def	test	t9	t9	c25	c25	252	65535	4	Y	144	0	63
@@ -1760,11 +1760,11 @@
   `param04` longtext,
   `const05` binary(3) NOT NULL default '',
   `param05` longblob,
-  `const06` varchar(10) NOT NULL default '',
+  `const06` char(10) NOT NULL default '',
   `param06` longtext,
   `const07` date default NULL,
   `param07` longblob,
-  `const08` varchar(19) NOT NULL default '',
+  `const08` char(19) NOT NULL default '',
   `param08` longtext,
   `const09` datetime default NULL,
   `param09` longblob,
@@ -1790,11 +1790,11 @@
 def	test	t5	t5	param04	param04	252	16777215	3	Y	16	0	8
 def	test	t5	t5	const05	const05	254	3	3	N	129	0	63
 def	test	t5	t5	param05	param05	252	16777215	3	Y	144	0	63
-def	test	t5	t5	const06	const06	253	10	10	N	1	0	8
+def	test	t5	t5	const06	const06	254	10	10	N	1	0	8
 def	test	t5	t5	param06	param06	252	16777215	10	Y	16	0	8
 def	test	t5	t5	const07	const07	10	10	10	Y	128	0	63
 def	test	t5	t5	param07	param07	252	16777215	10	Y	144	0	63
-def	test	t5	t5	const08	const08	253	19	19	N	1	0	8
+def	test	t5	t5	const08	const08	254	19	19	N	1	0	8
 def	test	t5	t5	param08	param08	252	16777215	19	Y	16	0	8
 def	test	t5	t5	const09	const09	12	19	19	Y	128	0	63
 def	test	t5	t5	param09	param09	252	16777215	19	Y	144	0	63

--- 1.10/mysql-test/r/ps_4heap.result	2004-11-11 19:54:00 +02:00
+++ 1.11/mysql-test/r/ps_4heap.result	2004-12-06 18:04:37 +02:00
@@ -13,9 +13,9 @@
 c9  double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
 c13 date, c14 datetime, c15 timestamp(14), c16 time,
 c17 year, c18 bit, c19 bool, c20 char,
-c21 char(10), c22 varchar(30), c23 char(100), c24 char(100),
-c25 char(100), c26 char(100), c27 char(100), c28 char(100),
-c29 char(100), c30 char(100), c31 enum('one', 'two', 'three'),
+c21 char(10), c22 varchar(30), c23 varchar(100), c24 varchar(100),
+c25 varchar(100), c26 varchar(100), c27 varchar(100), c28 varchar(100),
+c29 varchar(100), c30 varchar(100), c31 enum('one', 'two', 'three'),
 c32 set('monday', 'tuesday', 'wednesday'),
 primary key(c1)
 ) engine = 'HEAP'  ;
@@ -70,7 +70,7 @@
 def	test	t9	t9	c18	c18	1	1	1	Y	32768	0	63
 def	test	t9	t9	c19	c19	1	1	1	Y	32768	0	63
 def	test	t9	t9	c20	c20	254	1	1	Y	0	0	8
-def	test	t9	t9	c21	c21	253	10	10	Y	0	0	8
+def	test	t9	t9	c21	c21	254	10	10	Y	0	0	8
 def	test	t9	t9	c22	c22	253	30	30	Y	0	0	8
 def	test	t9	t9	c23	c23	253	100	8	Y	0	0	8
 def	test	t9	t9	c24	c24	253	100	8	Y	0	0	8
@@ -1689,8 +1689,8 @@
 info: Records: 3  Duplicates: 0  Warnings: 0
 select a,b from t2 order by a ;
 a	b
-3	duplicate
-4	duplicate
+3	duplicate 
+4	duplicate 
 103	three
 delete from t2 ;
 prepare stmt1 from ' insert into t2 (b,a) 
@@ -1761,11 +1761,11 @@
   `param04` longtext,
   `const05` binary(3) NOT NULL default '',
   `param05` longblob,
-  `const06` varchar(10) NOT NULL default '',
+  `const06` char(10) NOT NULL default '',
   `param06` longtext,
   `const07` date default NULL,
   `param07` longblob,
-  `const08` varchar(19) NOT NULL default '',
+  `const08` char(19) NOT NULL default '',
   `param08` longtext,
   `const09` datetime default NULL,
   `param09` longblob,
@@ -1791,11 +1791,11 @@
 def	test	t5	t5	param04	param04	252	16777215	3	Y	16	0	8
 def	test	t5	t5	const05	const05	254	3	3	N	129	0	63
 def	test	t5	t5	param05	param05	252	16777215	3	Y	144	0	63
-def	test	t5	t5	const06	const06	253	10	10	N	1	0	8
+def	test	t5	t5	const06	const06	254	10	10	N	1	0	8
 def	test	t5	t5	param06	param06	252	16777215	10	Y	16	0	8
 def	test	t5	t5	const07	const07	10	10	10	Y	128	0	63
 def	test	t5	t5	param07	param07	252	16777215	10	Y	144	0	63
-def	test	t5	t5	const08	const08	253	19	19	N	1	0	8
+def	test	t5	t5	const08	const08	254	19	19	N	1	0	8
 def	test	t5	t5	param08	param08	252	16777215	19	Y	16	0	8
 def	test	t5	t5	const09	const09	12	19	19	Y	128	0	63
 def	test	t5	t5	param09	param09	252	16777215	19	Y	144	0	63

--- 1.11/mysql-test/r/ps_5merge.result	2004-11-11 19:54:00 +02:00
+++ 1.12/mysql-test/r/ps_5merge.result	2004-12-06 18:04:37 +02:00
@@ -112,7 +112,7 @@
 def	test	t9	t9	c18	c18	1	1	1	Y	32768	0	63
 def	test	t9	t9	c19	c19	1	1	1	Y	32768	0	63
 def	test	t9	t9	c20	c20	254	1	1	Y	0	0	8
-def	test	t9	t9	c21	c21	253	10	10	Y	0	0	8
+def	test	t9	t9	c21	c21	254	10	10	Y	0	0	8
 def	test	t9	t9	c22	c22	253	30	30	Y	0	0	8
 def	test	t9	t9	c23	c23	252	255	8	Y	144	0	63
 def	test	t9	t9	c24	c24	252	255	8	Y	16	0	8
@@ -1700,11 +1700,11 @@
   `param04` longtext,
   `const05` binary(3) NOT NULL default '',
   `param05` longblob,
-  `const06` varchar(10) NOT NULL default '',
+  `const06` char(10) NOT NULL default '',
   `param06` longtext,
   `const07` date default NULL,
   `param07` longblob,
-  `const08` varchar(19) NOT NULL default '',
+  `const08` char(19) NOT NULL default '',
   `param08` longtext,
   `const09` datetime default NULL,
   `param09` longblob,
@@ -1730,11 +1730,11 @@
 def	test	t5	t5	param04	param04	252	16777215	3	Y	16	0	8
 def	test	t5	t5	const05	const05	254	3	3	N	129	0	63
 def	test	t5	t5	param05	param05	252	16777215	3	Y	144	0	63
-def	test	t5	t5	const06	const06	253	10	10	N	1	0	8
+def	test	t5	t5	const06	const06	254	10	10	N	1	0	8
 def	test	t5	t5	param06	param06	252	16777215	10	Y	16	0	8
 def	test	t5	t5	const07	const07	10	10	10	Y	128	0	63
 def	test	t5	t5	param07	param07	252	16777215	10	Y	144	0	63
-def	test	t5	t5	const08	const08	253	19	19	N	1	0	8
+def	test	t5	t5	const08	const08	254	19	19	N	1	0	8
 def	test	t5	t5	param08	param08	252	16777215	19	Y	16	0	8
 def	test	t5	t5	const09	const09	12	19	19	Y	128	0	63
 def	test	t5	t5	param09	param09	252	16777215	19	Y	144	0	63
@@ -3121,7 +3121,7 @@
 def	test	t9	t9	c18	c18	1	1	1	Y	32768	0	63
 def	test	t9	t9	c19	c19	1	1	1	Y	32768	0	63
 def	test	t9	t9	c20	c20	254	1	1	Y	0	0	8
-def	test	t9	t9	c21	c21	253	10	10	Y	0	0	8
+def	test	t9	t9	c21	c21	254	10	10	Y	0	0	8
 def	test	t9	t9	c22	c22	253	30	30	Y	0	0	8
 def	test	t9	t9	c23	c23	252	255	8	Y	144	0	63
 def	test	t9	t9	c24	c24	252	255	8	Y	16	0	8
@@ -4709,11 +4709,11 @@
   `param04` longtext,
   `const05` binary(3) NOT NULL default '',
   `param05` longblob,
-  `const06` varchar(10) NOT NULL default '',
+  `const06` char(10) NOT NULL default '',
   `param06` longtext,
   `const07` date default NULL,
   `param07` longblob,
-  `const08` varchar(19) NOT NULL default '',
+  `const08` char(19) NOT NULL default '',
   `param08` longtext,
   `const09` datetime default NULL,
   `param09` longblob,
@@ -4739,11 +4739,11 @@
 def	test	t5	t5	param04	param04	252	16777215	3	Y	16	0	8
 def	test	t5	t5	const05	const05	254	3	3	N	129	0	63
 def	test	t5	t5	param05	param05	252	16777215	3	Y	144	0	63
-def	test	t5	t5	const06	const06	253	10	10	N	1	0	8
+def	test	t5	t5	const06	const06	254	10	10	N	1	0	8
 def	test	t5	t5	param06	param06	252	16777215	10	Y	16	0	8
 def	test	t5	t5	const07	const07	10	10	10	Y	128	0	63
 def	test	t5	t5	param07	param07	252	16777215	10	Y	144	0	63
-def	test	t5	t5	const08	const08	253	19	19	N	1	0	8
+def	test	t5	t5	const08	const08	254	19	19	N	1	0	8
 def	test	t5	t5	param08	param08	252	16777215	19	Y	16	0	8
 def	test	t5	t5	const09	const09	12	19	19	Y	128	0	63
 def	test	t5	t5	param09	param09	252	16777215	19	Y	144	0	63

--- 1.11/mysql-test/r/ps_6bdb.result	2004-11-11 19:54:00 +02:00
+++ 1.12/mysql-test/r/ps_6bdb.result	2004-12-06 18:04:37 +02:00
@@ -69,7 +69,7 @@
 def	test	t9	t9	c18	c18	1	1	1	Y	32768	0	63
 def	test	t9	t9	c19	c19	1	1	1	Y	32768	0	63
 def	test	t9	t9	c20	c20	254	1	1	Y	0	0	8
-def	test	t9	t9	c21	c21	253	10	10	Y	0	0	8
+def	test	t9	t9	c21	c21	254	10	10	Y	0	0	8
 def	test	t9	t9	c22	c22	253	30	30	Y	0	0	8
 def	test	t9	t9	c23	c23	252	255	8	Y	144	0	63
 def	test	t9	t9	c24	c24	252	255	8	Y	16	0	8
@@ -1688,8 +1688,8 @@
 info: Records: 3  Duplicates: 0  Warnings: 0
 select a,b from t2 order by a ;
 a	b
-3	duplicate
-4	duplicate
+3	duplicate 
+4	duplicate 
 103	three
 delete from t2 ;
 prepare stmt1 from ' insert into t2 (b,a) 
@@ -1760,11 +1760,11 @@
   `param04` longtext,
   `const05` binary(3) NOT NULL default '',
   `param05` longblob,
-  `const06` varchar(10) NOT NULL default '',
+  `const06` char(10) NOT NULL default '',
   `param06` longtext,
   `const07` date default NULL,
   `param07` longblob,
-  `const08` varchar(19) NOT NULL default '',
+  `const08` char(19) NOT NULL default '',
   `param08` longtext,
   `const09` datetime default NULL,
   `param09` longblob,
@@ -1790,11 +1790,11 @@
 def	test	t5	t5	param04	param04	252	16777215	3	Y	16	0	8
 def	test	t5	t5	const05	const05	254	3	3	N	129	0	63
 def	test	t5	t5	param05	param05	252	16777215	3	Y	144	0	63
-def	test	t5	t5	const06	const06	253	10	10	N	1	0	8
+def	test	t5	t5	const06	const06	254	10	10	N	1	0	8
 def	test	t5	t5	param06	param06	252	16777215	10	Y	16	0	8
 def	test	t5	t5	const07	const07	10	10	10	Y	128	0	63
 def	test	t5	t5	param07	param07	252	16777215	10	Y	144	0	63
-def	test	t5	t5	const08	const08	253	19	19	N	1	0	8
+def	test	t5	t5	const08	const08	254	19	19	N	1	0	8
 def	test	t5	t5	param08	param08	252	16777215	19	Y	16	0	8
 def	test	t5	t5	const09	const09	12	19	19	Y	128	0	63
 def	test	t5	t5	param09	param09	252	16777215	19	Y	144	0	63

--- 1.8/mysql-test/t/ps_1general.test	2004-11-29 23:47:39 +02:00
+++ 1.9/mysql-test/t/ps_1general.test	2004-12-06 18:04:38 +02:00
@@ -317,7 +317,7 @@
 execute stmt4;
 --enable_result_log
 prepare stmt4 from ' show full processlist ';
---replace_column 1 number
+--replace_column 1 number 6 seconds
 execute stmt4;
 prepare stmt4 from ' show grants for user ';
 --error 1295

--- 1.2/mysql-test/r/select.result.es	2004-12-02 14:08:07 +02:00
+++ 1.3/mysql-test/r/select.result.es	2004-12-06 19:18:30 +02:00
@@ -1,5 +1,7 @@
 drop table if exists t1,t2,t3,t4;
 drop table if exists t1_1,t1_2,t9_1,t9_2;
+drop table if exists t1_1,t1_2,t9_1,t9_2;
+drop view if exists v1;
 CREATE TABLE t1 (
 Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL,
 Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL
@@ -2079,10 +2081,8 @@
 SELECT a.gvid, (SUM(CASE b.sampletid WHEN 140 THEN b.samplevalue ELSE 0 END)) as
the_success,(SUM(CASE b.sampletid WHEN 141 THEN b.samplevalue ELSE 0 END)) as
the_fail,(SUM(CASE b.sampletid WHEN 142 THEN b.samplevalue ELSE 0 END)) as
the_size,(SUM(CASE b.sampletid WHEN 143 THEN b.samplevalue ELSE 0 END)) as the_time FROM
t1 a, t2 b WHERE a.hmid = b.hmid AND a.volid = b.volid AND b.sampletime >=
'wrong-date-value' AND b.sampletime < 'wrong-date-value' AND b.sampletid IN (140, 141,
142, 143) GROUP BY a.gvid;
 gvid	the_success	the_fail	the_size	the_time
 Warnings:
-Warning	1292	Truncated incorrect datetime value: 'wrong-date-value'
-Warning	1292	Truncated incorrect datetime value: 'wrong-date-value'
-Warning	1292	Truncated incorrect datetime value: 'wrong-date-value'
-Warning	1292	Truncated incorrect datetime value: 'wrong-date-value'
+Warning	1292	Incorrect datetime value: 'wrong-date-value' for column 'sampletime' at row
1
+Warning	1292	Incorrect datetime value: 'wrong-date-value' for column 'sampletime' at row
1
 SELECT a.gvid, (SUM(CASE b.sampletid WHEN 140 THEN b.samplevalue ELSE 0 END)) as
the_success,(SUM(CASE b.sampletid WHEN 141 THEN b.samplevalue ELSE 0 END)) as
the_fail,(SUM(CASE b.sampletid WHEN 142 THEN b.samplevalue ELSE 0 END)) as
the_size,(SUM(CASE b.sampletid WHEN 143 THEN b.samplevalue ELSE 0 END)) as the_time FROM
t1 a, t2 b WHERE a.hmid = b.hmid AND a.volid = b.volid AND b.sampletime >= NULL AND
b.sampletime < NULL AND b.sampletid IN (140, 141, 142, 143) GROUP BY a.gvid;
 gvid	the_success	the_fail	the_size	the_time
 DROP TABLE t1,t2;
@@ -2345,7 +2345,7 @@
 s
 select * from t3 where s = 'one';
 s
-one
+one 
 select * from t1,t2 where t1.s = t2.s;
 s	s
 two		two	

--- 1.11/ndb/src/common/util/NdbSqlUtil.cpp	2004-11-18 12:48:59 +02:00
+++ 1.12/ndb/src/common/util/NdbSqlUtil.cpp	2004-12-06 18:04:38 +02:00
@@ -410,7 +410,7 @@
   CHARSET_INFO* cs = (CHARSET_INFO*)(info);
   // length in bytes including null padding to Uint32
   uint l1 = (full << 2);
-  int k = (*cs->coll->strnncollsp)(cs, u1.v, l1, u2.v, l1);
+  int k = (*cs->coll->strnncollsp)(cs, u1.v, l1, u2.v, l1, 0);
   return k < 0 ? -1 : k > 0 ? +1 : 0;
 }
 
@@ -559,7 +559,7 @@
     CHARSET_INFO* cs = (CHARSET_INFO*)(info);
     // length in bytes including null padding to Uint32
     uint l1 = (full << 2);
-    int k = (*cs->coll->strnncollsp)(cs, u1.v, l1, u2.v, l1);
+    int k = (*cs->coll->strnncollsp)(cs, u1.v, l1, u2.v, l1,0);
     return k < 0 ? -1 : k > 0 ? +1 : 0;
   }
   return CmpUnknown;

--- 1.120/sql/ha_ndbcluster.cc	2004-11-30 19:58:14 +02:00
+++ 1.121/sql/ha_ndbcluster.cc	2004-12-06 18:04:38 +02:00
@@ -406,6 +406,7 @@
     return TRUE;
   case MYSQL_TYPE_NULL:   
   case MYSQL_TYPE_GEOMETRY:
+  case MYSQL_TYPE_VARCHAR:
     break;
   }
   return FALSE;
@@ -1843,7 +1844,7 @@
 	  (new_row[key_part->null_offset] & key_part->null_bit))
 	return 1;
     }
-    if (key_part->key_part_flag & (HA_BLOB_PART | HA_VAR_LENGTH))
+    if (key_part->key_part_flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART))
     {
 
       if (key_part->field->cmp_binary((char*) (old_row + key_part->offset),
@@ -3774,6 +3775,7 @@
   m_table_flags(HA_REC_NOT_IN_SEQ |
 		HA_NULL_IN_KEY |
 		HA_AUTO_PART_KEY |
+                HA_NO_VARCHAR |
 		HA_NO_PREFIX_CHAR_KEYS),
   m_share(0),
   m_use_write(FALSE),

--- 1.26/mysql-test/r/heap.result	2004-12-06 02:05:20 +02:00
+++ 1.27/mysql-test/r/heap.result	2004-12-06 19:18:30 +02:00
@@ -1,4 +1,4 @@
-drop table if exists t1;
+drop table if exists t1,t2,t3;
 create table t1 (a int not null,b int not null, primary key (a)) engine=heap
comment="testing heaps" avg_row_length=100 min_rows=1 max_rows=100;
 insert into t1 values(1,1),(2,2),(3,3),(4,4);
 delete from t1 where a=1 or a=0;
@@ -249,3 +249,421 @@
 3
 2
 drop table t1;
+set storage_engine=HEAP;
+create table t1 (v varchar(10), c char(10), t varchar(50));
+insert into t1 values('+ ', '+ ', '+ ');
+set @a=repeat(' ',20);
+insert into t1 values (concat('+',@a),concat('+',@a),concat('+',@a));
+Warnings:
+Warning	1265	Data truncated for column 'v' at row 1
+select concat('*',v,'*',c,'*',t,'*') from t1;
+concat('*',v,'*',c,'*',t,'*')
+*+ *+*+ *
+*+         *+*+                    *
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `v` varchar(10) default NULL,
+  `c` char(10) default NULL,
+  `t` varchar(50) default NULL
+) ENGINE=HEAP DEFAULT CHARSET=latin1
+create table t2 like t1;
+show create table t2;
+Table	Create Table
+t2	CREATE TABLE `t2` (
+  `v` varchar(10) default NULL,
+  `c` char(10) default NULL,
+  `t` varchar(50) default NULL
+) ENGINE=HEAP DEFAULT CHARSET=latin1
+create table t3 select * from t1;
+show create table t3;
+Table	Create Table
+t3	CREATE TABLE `t3` (
+  `v` varchar(10) default NULL,
+  `c` char(10) default NULL,
+  `t` varchar(50) default NULL
+) ENGINE=HEAP DEFAULT CHARSET=latin1
+alter table t1 modify c varchar(10);
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `v` varchar(10) default NULL,
+  `c` varchar(10) default NULL,
+  `t` varchar(50) default NULL
+) ENGINE=HEAP DEFAULT CHARSET=latin1
+alter table t1 modify v char(10);
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `v` char(10) default NULL,
+  `c` varchar(10) default NULL,
+  `t` varchar(50) default NULL
+) ENGINE=HEAP DEFAULT CHARSET=latin1
+alter table t1 modify t varchar(10);
+Warnings:
+Warning	1265	Data truncated for column 't' at row 2
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `v` char(10) default NULL,
+  `c` varchar(10) default NULL,
+  `t` varchar(10) default NULL
+) ENGINE=HEAP DEFAULT CHARSET=latin1
+select concat('*',v,'*',c,'*',t,'*') from t1;
+concat('*',v,'*',c,'*',t,'*')
+*+*+*+ *
+*+*+*+         *
+drop table t1,t2,t3;
+create table t1 (v varchar(10), c char(10), t varchar(50), key(v), key(c), key(t(10)));
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `v` varchar(10) default NULL,
+  `c` char(10) default NULL,
+  `t` varchar(50) default NULL,
+  KEY `v` (`v`),
+  KEY `c` (`c`),
+  KEY `t` (`t`(10))
+) ENGINE=HEAP DEFAULT CHARSET=latin1
+select count(*) from t1;
+count(*)
+270
+insert into t1 values(concat('a',char(1)),concat('a',char(1)),concat('a',char(1)));
+select count(*) from t1 where v='a';
+count(*)
+10
+select count(*) from t1 where c='a';
+count(*)
+10
+select count(*) from t1 where t='a';
+count(*)
+10
+select count(*) from t1 where v='a  ';
+count(*)
+10
+select count(*) from t1 where c='a  ';
+count(*)
+10
+select count(*) from t1 where t='a  ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ' and v between 'a  ' and 'b\n';
+count(*)
+10
+select count(*) from t1 where v like 'a%';
+count(*)
+11
+select count(*) from t1 where c like 'a%';
+count(*)
+11
+select count(*) from t1 where t like 'a%';
+count(*)
+11
+select count(*) from t1 where v like 'a %';
+count(*)
+9
+explain select count(*) from t1 where v='a  ';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ref	v	v	13	const	10	Using where
+explain select count(*) from t1 where c='a  ';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ref	c	c	11	const	10	Using where
+explain select count(*) from t1 where t='a  ';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ref	t	t	13	const	10	Using where
+explain select count(*) from t1 where v like 'a%';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ALL	v	NULL	NULL	NULL	271	Using where
+explain select count(*) from t1 where v between 'a' and 'a ';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ALL	v	NULL	NULL	NULL	271	Using where
+explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a  ' and
'b\n';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ALL	v	NULL	NULL	NULL	271	Using where
+alter table t1 add unique(v);
+ERROR 23000: Duplicate entry '{ ' for key 1
+alter table t1 add key(v);
+select concat('*',v,'*',c,'*',t,'*') as qq from t1 where v='a';
+qq
+*a         *a*a         *
+*a        *a*a        *
+*a       *a*a       *
+*a      *a*a      *
+*a     *a*a     *
+*a    *a*a    *
+*a   *a*a   *
+*a  *a*a  *
+*a *a*a *
+*a*a*a*
+explain select * from t1 where v='a';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ref	v,v_2	v	13	const	10	Using where
+select v,count(*) from t1 group by v limit 10;
+v	count(*)
+a	1
+a	10
+b	10
+c	10
+d	10
+e	10
+f	10
+g	10
+h	10
+i	10
+select v,count(t) from t1 group by v limit 10;
+v	count(t)
+a	1
+a	10
+b	10
+c	10
+d	10
+e	10
+f	10
+g	10
+h	10
+i	10
+select v,count(c) from t1 group by v limit 10;
+v	count(c)
+a	1
+a	10
+b	10
+c	10
+d	10
+e	10
+f	10
+g	10
+h	10
+i	10
+select sql_big_result v,count(t) from t1 group by v limit 10;
+v	count(t)
+a	1
+a 	10
+b     	10
+c    	10
+d   	10
+e  	10
+f     	10
+g    	10
+h	10
+i     	10
+select sql_big_result v,count(c) from t1 group by v limit 10;
+v	count(c)
+a	1
+a 	10
+b     	10
+c    	10
+d   	10
+e  	10
+f     	10
+g    	10
+h	10
+i     	10
+select c,count(*) from t1 group by c limit 10;
+c	count(*)
+a	1
+a	10
+b	10
+c	10
+d	10
+e	10
+f	10
+g	10
+h	10
+i	10
+select c,count(t) from t1 group by c limit 10;
+c	count(t)
+a	1
+a	10
+b	10
+c	10
+d	10
+e	10
+f	10
+g	10
+h	10
+i	10
+select sql_big_result c,count(t) from t1 group by c limit 10;
+c	count(t)
+a	1
+a	10
+b	10
+c	10
+d	10
+e	10
+f	10
+g	10
+h	10
+i	10
+select t,count(*) from t1 group by t limit 10;
+t	count(*)
+a	1
+a	10
+b	10
+c	10
+d	10
+e	10
+f	10
+g	10
+h	10
+i	10
+select t,count(t) from t1 group by t limit 10;
+t	count(t)
+a	1
+a	10
+b	10
+c	10
+d	10
+e	10
+f	10
+g	10
+h	10
+i	10
+select sql_big_result t,count(t) from t1 group by t limit 10;
+t	count(t)
+a	1
+a 	10
+b     	10
+c    	10
+d   	10
+e  	10
+f     	10
+g    	10
+h	10
+i     	10
+drop table t1;
+create table t1 (a char(10), unique (a));
+insert into t1 values ('a');
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a' for key 1
+alter table t1 modify a varchar(10);
+insert into t1 values ('a '),('a  '),('a   '),('a         ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+insert into t1 values ('a     ');
+ERROR 23000: Duplicate entry 'a     ' for key 1
+insert into t1 values ('a          ');
+ERROR 23000: Duplicate entry 'a         ' for key 1
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+update t1 set a='a      ' where a like 'a ';
+update t1 set a='a  ' where a like 'a      ';
+drop table t1;
+create table t1 (v varchar(10), c char(10), t varchar(50), key using btree (v), key using
btree (c), key using btree (t(10)));
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `v` varchar(10) default NULL,
+  `c` char(10) default NULL,
+  `t` varchar(50) default NULL,
+  KEY `v` TYPE BTREE (`v`),
+  KEY `c` TYPE BTREE (`c`),
+  KEY `t` TYPE BTREE (`t`(10))
+) ENGINE=HEAP DEFAULT CHARSET=latin1
+select count(*) from t1;
+count(*)
+270
+insert into t1 values(concat('a',char(1)),concat('a',char(1)),concat('a',char(1)));
+select count(*) from t1 where v='a';
+count(*)
+10
+select count(*) from t1 where c='a';
+count(*)
+10
+select count(*) from t1 where t='a';
+count(*)
+10
+select count(*) from t1 where v='a  ';
+count(*)
+10
+select count(*) from t1 where c='a  ';
+count(*)
+10
+select count(*) from t1 where t='a  ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ' and v between 'a  ' and 'b\n';
+count(*)
+10
+explain select count(*) from t1 where v='a  ';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ref	v	v	13	const	#	Using where
+explain select count(*) from t1 where c='a  ';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ref	c	c	11	const	#	Using where
+explain select count(*) from t1 where t='a  ';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ref	t	t	13	const	#	Using where
+explain select count(*) from t1 where v like 'a%';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	v	v	13	NULL	#	Using where
+explain select count(*) from t1 where v between 'a' and 'a ';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	v	v	13	NULL	#	Using where
+explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a  ' and
'b\n';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	v	v	13	NULL	#	Using where
+alter table t1 add unique(v);
+ERROR 23000: Duplicate entry '{ ' for key 1
+alter table t1 add key(v);
+select concat('*',v,'*',c,'*',t,'*') as qq from t1 where v='a';
+qq
+*a*a*a*
+*a *a*a *
+*a  *a*a  *
+*a   *a*a   *
+*a    *a*a    *
+*a     *a*a     *
+*a      *a*a      *
+*a       *a*a       *
+*a        *a*a        *
+*a         *a*a         *
+explain select * from t1 where v='a';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ref	v,v_2	v	13	const	7	Using where
+drop table t1;
+create table t1 (a char(10), unique using btree (a)) engine=heap;
+insert into t1 values ('a');
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a' for key 1
+alter table t1 modify a varchar(10);
+insert into t1 values ('a '),('a  '),('a   '),('a         ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+insert into t1 values ('a     ');
+ERROR 23000: Duplicate entry 'a     ' for key 1
+insert into t1 values ('a          ');
+ERROR 23000: Duplicate entry 'a         ' for key 1
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+update t1 set a='a      ' where a like 'a ';
+update t1 set a='a  ' where a like 'a      ';
+drop table t1;
+create table t1 (v varchar(10), c char(10), t varchar(50), key(v(5)), key(c(5)),
key(t(5)));
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `v` varchar(10) default NULL,
+  `c` char(10) default NULL,
+  `t` varchar(50) default NULL,
+  KEY `v` (`v`(5)),
+  KEY `c` (`c`(5)),
+  KEY `t` (`t`(5))
+) ENGINE=HEAP DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (v varchar(65530), key(v(10)));
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `v` varchar(65530) default NULL,
+  KEY `v` (`v`(10))
+) ENGINE=HEAP DEFAULT CHARSET=latin1
+insert into t1 values(repeat('a',65530));
+select length(v) from t1 where v=repeat('a',65530);
+length(v)
+65530
+drop table t1;
+set storage_engine=MyISAM;

--- 1.84/mysql-test/r/innodb.result	2004-12-06 17:15:48 +02:00
+++ 1.85/mysql-test/r/innodb.result	2004-12-06 19:18:30 +02:00
@@ -1421,19 +1421,19 @@
 insert t3 select * from t1;
 checksum table t1, t2, t3, t4 quick;
 Table	Checksum
-test.t1	968604391
+test.t1	272226711
 test.t2	NULL
 test.t3	NULL
 test.t4	NULL
 checksum table t1, t2, t3, t4;
 Table	Checksum
-test.t1	968604391
+test.t1	272226711
 test.t2	968604391
 test.t3	968604391
 test.t4	NULL
 checksum table t1, t2, t3, t4 extended;
 Table	Checksum
-test.t1	968604391
+test.t1	272226711
 test.t2	968604391
 test.t3	968604391
 test.t4	NULL
@@ -1700,3 +1700,5 @@
 show status like "Innodb_rows_updated";
 Variable_name	Value
 Innodb_rows_updated	29530
+create table t1 (v varchar(16384)) engine=innodb;
+ERROR 42000: Column length too big for column 'v' (max = 255); use BLOB instead

--- 1.45/mysql-test/r/order_by.result	2004-11-25 18:02:36 +02:00
+++ 1.46/mysql-test/r/order_by.result	2004-12-06 18:04:37 +02:00
@@ -272,7 +272,7 @@
 insert into t1 values (1, NULL, NULL), (1, NULL, 'b'), (1, 1, NULL), (1, 1, 'b'), (1, 1,
'b'), (2, 1, 'a'), (2, 1, 'b'), (2, 2, 'a'), (2, 2, 'b'), (2, 3, 'c'),(1,3,'b');
 explain select * from t1 where (a = 1 and b is null and c = 'b') or (a > 2) order by a
desc;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t1	index	a	a	20	NULL	11	Using where; Using index
+1	SIMPLE	t1	index	a	a	22	NULL	11	Using where; Using index
 select * from t1 where (a = 1 and b is null and c = 'b') or (a > 2) order by a desc;
 a	b	c
 1	NULL	b
@@ -348,7 +348,7 @@
 Warning	1265	Data truncated for column 'c' at row 3
 explain select * from t1 order by a, b, c;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t1	index	NULL	a	18	NULL	11	Using index
+1	SIMPLE	t1	index	NULL	a	20	NULL	11	Using index
 select * from t1 order by a, b, c;
 a	b	c
 1	0	
@@ -364,7 +364,7 @@
 2	3	c
 explain select * from t1 order by a desc, b desc, c desc;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t1	index	NULL	a	18	NULL	11	Using index
+1	SIMPLE	t1	index	NULL	a	20	NULL	11	Using index
 select * from t1 order by a desc, b desc, c desc;
 a	b	c
 2	3	c
@@ -380,7 +380,7 @@
 1	0	
 explain select * from t1 where (a = 1 and b = 1 and c = 'b') or (a > 2) order by a
desc;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t1	range	a	a	18	NULL	3	Using where; Using index
+1	SIMPLE	t1	range	a	a	20	NULL	3	Using where; Using index
 select * from t1 where (a = 1 and b = 1 and c = 'b') or (a > 2) order by a desc;
 a	b	c
 1	1	b
@@ -574,7 +574,7 @@
 INSERT INTO t1 VALUES ('0',3,'0'),('0',2,'1'),('0',1,'2'),('1',2,'1'),('1',1,'3'),
('1',0,'2'),('2',3,'0'),('2',2,'1'),('2',1,'2'),('2',3,'0'),('2',2,'1'),('2',1,'2'),('3',2,'1'),('3',1,'2'),('3','3','3');
 EXPLAIN SELECT * FROM t1 WHERE FieldKey = '1' ORDER BY LongVal;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t1	ref	FieldKey,LongField,StringField	LongField	36	const	3	Using where
+1	SIMPLE	t1	ref	FieldKey,LongField,StringField	LongField	38	const	3	Using where
 SELECT * FROM t1 WHERE FieldKey = '1' ORDER BY LongVal;
 FieldKey	LongVal	StringVal
 1	0	2
@@ -582,7 +582,7 @@
 1	2	1
 EXPLAIN SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY LongVal;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t1	range	FieldKey,LongField,StringField	FieldKey	36	NULL	4	Using where; Using
filesort
+1	SIMPLE	t1	range	FieldKey,LongField,StringField	FieldKey	38	NULL	4	Using where; Using
filesort
 SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY LongVal;
 FieldKey	LongVal	StringVal
 3	1	2
@@ -590,7 +590,7 @@
 3	3	3
 EXPLAIN SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY FieldKey, LongVal;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t1	range	FieldKey,LongField,StringField	LongField	36	NULL	4	Using where
+1	SIMPLE	t1	range	FieldKey,LongField,StringField	LongField	38	NULL	4	Using where
 SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY FieldKey, LongVal;
 FieldKey	LongVal	StringVal
 3	1	2

--- 1.43/mysql-test/r/select.result	2004-11-28 21:41:57 +02:00
+++ 1.44/mysql-test/r/select.result	2004-12-06 18:04:37 +02:00
@@ -2313,7 +2313,7 @@
 s
 select * from t3 where s = 'one';
 s
-one
+one 
 select * from t1,t2 where t1.s = t2.s;
 s	s
 two		two	

--- 1.42/mysql-test/r/type_blob.result	2004-11-22 21:54:42 +02:00
+++ 1.43/mysql-test/r/type_blob.result	2004-12-06 18:04:37 +02:00
@@ -4,17 +4,19 @@
 Field	Type	Null	Key	Default	Extra
 a	blob	YES		NULL	
 b	text	YES		NULL	
-c	blob	YES		NULL	
+c	tinyblob	YES		NULL	
 d	mediumtext	YES		NULL	
 e	longtext	YES		NULL	
-CREATE TABLE t2 (a char(257), b varbinary(70000), c varchar(70000000));
+CREATE TABLE t2 (a char(255), b varbinary(70000), c varchar(70000000));
 Warnings:
-Note	1246	Converting column 'a' from CHAR to TEXT
-Note	1246	Converting column 'b' from CHAR to BLOB
-Note	1246	Converting column 'c' from CHAR to TEXT
+Note	1246	Converting column 'b' from VARCHAR to BLOB
+Note	1246	Converting column 'c' from VARCHAR to TEXT
+CREATE TABLE t4 (c varchar(65530) character set utf8 not null);
+Warnings:
+Note	1246	Converting column 'c' from VARCHAR to TEXT
 show columns from t2;
 Field	Type	Null	Key	Default	Extra
-a	text	YES		NULL	
+a	char(255)	YES		NULL	
 b	mediumblob	YES		NULL	
 c	longtext	YES		NULL	
 create table t3 (a long, b long byte);
@@ -24,10 +26,18 @@
   `a` mediumtext,
   `b` mediumblob
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
-drop table t1,t2,t3
-#;
+show create TABLE t4;
+Table	Create Table
+t4	CREATE TABLE `t4` (
+  `c` mediumtext character set utf8 NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1,t2,t3,t4;
 CREATE TABLE t1 (a char(257) default "hello");
 ERROR 42000: Column length too big for column 'a' (max = 255); use BLOB instead
+CREATE TABLE t2 (a char(256));
+ERROR 42000: Column length too big for column 'a' (max = 255); use BLOB instead
+CREATE TABLE t1 (a varchar(70000) default "hello");
+ERROR 42000: Column length too big for column 'a' (max = 65535); use BLOB instead
 CREATE TABLE t2 (a blob default "hello");
 ERROR 42000: BLOB/TEXT column 'a' can't have a default value
 drop table if exists t1,t2;
@@ -71,16 +81,16 @@
 show full fields from t1;
 Field	Type	Collation	Null	Key	Default	Extra	Privileges	Comment
 t	text	latin1_swedish_ci	YES		NULL		select,insert,update,references	
-c	varchar(10)	latin1_swedish_ci	YES		NULL		select,insert,update,references	
+c	char(10)	latin1_swedish_ci	YES		NULL		select,insert,update,references	
 b	blob	NULL	YES		NULL		select,insert,update,references	
-d	varbinary(10)	NULL	YES		NULL		select,insert,update,references	
+d	binary(10)	NULL	YES		NULL		select,insert,update,references	
 lock tables t1 WRITE;
 show full fields from t1;
 Field	Type	Collation	Null	Key	Default	Extra	Privileges	Comment
 t	text	latin1_swedish_ci	YES		NULL		select,insert,update,references	
-c	varchar(10)	latin1_swedish_ci	YES		NULL		select,insert,update,references	
+c	char(10)	latin1_swedish_ci	YES		NULL		select,insert,update,references	
 b	blob	NULL	YES		NULL		select,insert,update,references	
-d	varbinary(10)	NULL	YES		NULL		select,insert,update,references	
+d	binary(10)	NULL	YES		NULL		select,insert,update,references	
 unlock tables;
 select t from t1 where t like "hello";
 t
@@ -520,6 +530,11 @@
 drop table t1;
 create table t1 (id integer primary key auto_increment, txt text not null, unique index
txt_index (txt (20)));
 insert into t1 (txt) values ('Chevy'), ('Chevy ');
+ERROR 23000: Duplicate entry 'Chevy ' for key 2
+insert into t1 (txt) values ('Chevy'), ('CHEVY');
+ERROR 23000: Duplicate entry 'Chevy' for key 2
+alter table t1 drop index txt_index, add index txt_index (txt(20));
+insert into t1 (txt) values ('Chevy ');
 select * from t1 where txt='Chevy';
 id	txt
 1	Chevy
@@ -589,7 +604,7 @@
 2	Chevy 
 3	Ford
 drop table t1;
-create table t1 (id integer primary key auto_increment, txt text, unique index txt_index
(txt (20)));
+create table t1 (id integer primary key auto_increment, txt text, index txt_index (txt
(20)));
 insert into t1 (txt) values ('Chevy'), ('Chevy '), (NULL);
 select * from t1 where txt='Chevy' or txt is NULL;
 id	txt

--- 1.19/mysql-test/t/heap.test	2004-12-02 13:06:11 +02:00
+++ 1.20/mysql-test/t/heap.test	2004-12-06 19:18:30 +02:00
@@ -3,7 +3,7 @@
 #
 
 --disable_warnings
-drop table if exists t1;
+drop table if exists t1,t2,t3;
 --enable_warnings
 
 create table t1 (a int not null,b int not null, primary key (a)) engine=heap
comment="testing heaps" avg_row_length=100 min_rows=1 max_rows=100;
@@ -195,3 +195,214 @@
 insert into t1 values ('2'), ('3');
 select * from t1;
 drop table t1;
+
+#
+# Test varchar
+# We can't use varchar.inc becasue heap doesn't support blob's
+#
+
+let $default=`select @@storage_engine`;
+set storage_engine=HEAP;
+
+#
+# Simple basic test that endspace is saved
+#
+
+create table t1 (v varchar(10), c char(10), t varchar(50));
+insert into t1 values('+ ', '+ ', '+ ');
+set @a=repeat(' ',20);
+insert into t1 values (concat('+',@a),concat('+',@a),concat('+',@a));
+select concat('*',v,'*',c,'*',t,'*') from t1;
+
+# Check how columns are copied
+show create table t1;
+create table t2 like t1;
+show create table t2;
+create table t3 select * from t1;
+show create table t3;
+alter table t1 modify c varchar(10);
+show create table t1;
+alter table t1 modify v char(10);
+show create table t1;
+alter table t1 modify t varchar(10);
+show create table t1;
+select concat('*',v,'*',c,'*',t,'*') from t1;
+drop table t1,t2,t3;
+
+#
+# Testing of keys
+#
+create table t1 (v varchar(10), c char(10), t varchar(50), key(v), key(c), key(t(10)));
+show create table t1;
+disable_query_log;
+let $1=10;
+while ($1)
+{
+  let $2=27;
+  eval set @space=repeat(' ',10-$1);
+  while ($2)
+  {
+    eval set @char=char(ascii('a')+$2-1);
+    insert into t1
values(concat(@char,@space),concat(@char,@space),concat(@char,@space));
+    dec $2;
+  }
+  dec $1;
+}
+enable_query_log;
+select count(*) from t1;
+insert into t1 values(concat('a',char(1)),concat('a',char(1)),concat('a',char(1)));
+select count(*) from t1 where v='a';
+select count(*) from t1 where c='a';
+select count(*) from t1 where t='a';
+select count(*) from t1 where v='a  ';
+select count(*) from t1 where c='a  ';
+select count(*) from t1 where t='a  ';
+select count(*) from t1 where v between 'a' and 'a ';
+select count(*) from t1 where v between 'a' and 'a ' and v between 'a  ' and 'b\n';
+select count(*) from t1 where v like 'a%';
+select count(*) from t1 where c like 'a%';
+select count(*) from t1 where t like 'a%';
+select count(*) from t1 where v like 'a %';
+explain select count(*) from t1 where v='a  ';
+explain select count(*) from t1 where c='a  ';
+explain select count(*) from t1 where t='a  ';
+explain select count(*) from t1 where v like 'a%';
+explain select count(*) from t1 where v between 'a' and 'a ';
+explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a  ' and
'b\n';
+
+--error 1062
+alter table t1 add unique(v);
+alter table t1 add key(v);
+select concat('*',v,'*',c,'*',t,'*') as qq from t1 where v='a';
+explain select * from t1 where v='a';
+
+# GROUP BY
+
+select v,count(*) from t1 group by v limit 10;
+select v,count(t) from t1 group by v limit 10;
+select v,count(c) from t1 group by v limit 10;
+select sql_big_result v,count(t) from t1 group by v limit 10;
+select sql_big_result v,count(c) from t1 group by v limit 10;
+select c,count(*) from t1 group by c limit 10;
+select c,count(t) from t1 group by c limit 10;
+select sql_big_result c,count(t) from t1 group by c limit 10;
+select t,count(*) from t1 group by t limit 10;
+select t,count(t) from t1 group by t limit 10;
+select sql_big_result t,count(t) from t1 group by t limit 10;
+drop table t1;
+
+#
+# Test unique keys
+#
+
+create table t1 (a char(10), unique (a));
+insert into t1 values ('a');
+--error 1062
+insert into t1 values ('a ');
+
+alter table t1 modify a varchar(10);
+--error 1062
+insert into t1 values ('a '),('a  '),('a   '),('a         ');
+--error 1062
+insert into t1 values ('a     ');
+--error 1062
+insert into t1 values ('a          ');
+--error 1062
+insert into t1 values ('a ');
+update t1 set a='a      ' where a like 'a ';
+update t1 set a='a  ' where a like 'a      ';
+drop table t1;
+
+#
+# Testing of btree keys
+#
+
+create table t1 (v varchar(10), c char(10), t varchar(50), key using btree (v), key using
btree (c), key using btree (t(10)));
+show create table t1;
+disable_query_log;
+let $1=10;
+while ($1)
+{
+  let $2=27;
+  eval set @space=repeat(' ',10-$1);
+  while ($2)
+  {
+    eval set @char=char(ascii('a')+$2-1);
+    insert into t1
values(concat(@char,@space),concat(@char,@space),concat(@char,@space));
+    dec $2;
+  }
+  dec $1;
+}
+enable_query_log;
+select count(*) from t1;
+insert into t1 values(concat('a',char(1)),concat('a',char(1)),concat('a',char(1)));
+select count(*) from t1 where v='a';
+select count(*) from t1 where c='a';
+select count(*) from t1 where t='a';
+select count(*) from t1 where v='a  ';
+select count(*) from t1 where c='a  ';
+select count(*) from t1 where t='a  ';
+select count(*) from t1 where v between 'a' and 'a ';
+--replace_column 9 #
+select count(*) from t1 where v between 'a' and 'a ' and v between 'a  ' and 'b\n';
+--replace_column 9 #
+explain select count(*) from t1 where v='a  ';
+--replace_column 9 #
+explain select count(*) from t1 where c='a  ';
+--replace_column 9 #
+explain select count(*) from t1 where t='a  ';
+--replace_column 9 #
+explain select count(*) from t1 where v like 'a%';
+--replace_column 9 #
+explain select count(*) from t1 where v between 'a' and 'a ';
+--replace_column 9 #
+explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a  ' and
'b\n';
+
+--error 1062
+alter table t1 add unique(v);
+alter table t1 add key(v);
+select concat('*',v,'*',c,'*',t,'*') as qq from t1 where v='a';
+explain select * from t1 where v='a';
+
+drop table t1;
+
+#
+# Test unique btree keys
+#
+
+create table t1 (a char(10), unique using btree (a)) engine=heap;
+insert into t1 values ('a');
+--error 1062
+insert into t1 values ('a ');
+
+alter table t1 modify a varchar(10);
+--error 1062
+insert into t1 values ('a '),('a  '),('a   '),('a         ');
+--error 1062
+insert into t1 values ('a     ');
+--error 1062
+insert into t1 values ('a          ');
+--error 1062
+insert into t1 values ('a ');
+update t1 set a='a      ' where a like 'a ';
+update t1 set a='a  ' where a like 'a      ';
+drop table t1;
+
+#
+# test show create table
+#
+
+create table t1 (v varchar(10), c char(10), t varchar(50), key(v(5)), key(c(5)),
key(t(5)));
+show create table t1;
+drop table t1;
+
+create table t1 (v varchar(65530), key(v(10)));
+show create table t1;
+insert into t1 values(repeat('a',65530));
+select length(v) from t1 where v=repeat('a',65530);
+drop table t1;
+
+#
+# Reset varchar test
+#
+eval set storage_engine=$default;

--- 1.67/mysql-test/t/innodb.test	2004-11-22 22:33:09 +02:00
+++ 1.68/mysql-test/t/innodb.test	2004-12-06 19:18:30 +02:00
@@ -1210,3 +1210,15 @@
 show status like "Innodb_rows_inserted";
 show status like "Innodb_rows_read";
 show status like "Innodb_rows_updated";
+#
+# Test varchar
+#
+
+#let $default=`select @@storage_engine`;
+#set storage_engine=INNODB;
+#source include/varchar.inc;
+#eval set storage_engine=$default;
+
+# InnoDB specific varchar tests
+--error 1074
+create table t1 (v varchar(16384)) engine=innodb;

--- 1.23/mysql-test/t/type_blob.test	2004-11-22 20:06:53 +02:00
+++ 1.24/mysql-test/t/type_blob.test	2004-12-06 18:04:38 +02:00
@@ -18,12 +18,14 @@
 show columns from t1;
 # PS doesn't give errors on prepare yet
 --disable_ps_protocol
-CREATE TABLE t2 (a char(257), b varbinary(70000), c varchar(70000000));
+CREATE TABLE t2 (a char(255), b varbinary(70000), c varchar(70000000));
+CREATE TABLE t4 (c varchar(65530) character set utf8 not null);
 --enable_ps_protocol
 show columns from t2;
 create table t3 (a long, b long byte);
 show create TABLE t3;
-drop table t1,t2,t3
+show create TABLE t4;
+drop table t1,t2,t3,t4;
 
 #
 # Check errors with blob
@@ -31,6 +33,10 @@
 
 --error 1074
 CREATE TABLE t1 (a char(257) default "hello");
+--error 1074
+CREATE TABLE t2 (a char(256));
+--error 1074
+CREATE TABLE t1 (a varchar(70000) default "hello");
 --error 1101
 CREATE TABLE t2 (a blob default "hello");
 
@@ -316,10 +322,16 @@
 
 #
 # Test blob's with end space (Bug #1651)
+# This is a bit changed since we now have true varchar
 #
 
 create table t1 (id integer primary key auto_increment, txt text not null, unique index
txt_index (txt (20)));
+--error 1062
 insert into t1 (txt) values ('Chevy'), ('Chevy ');
+--error 1062
+insert into t1 (txt) values ('Chevy'), ('CHEVY');
+alter table t1 drop index txt_index, add index txt_index (txt(20));
+insert into t1 (txt) values ('Chevy ');
 select * from t1 where txt='Chevy';
 select * from t1 where txt='Chevy ';
 select * from t1 where txt='Chevy ' or txt='Chevy';
@@ -340,7 +352,7 @@
 select * from t1 where txt >= 'Chevy';
 drop table t1;
 
-create table t1 (id integer primary key auto_increment, txt text, unique index txt_index
(txt (20)));
+create table t1 (id integer primary key auto_increment, txt text, index txt_index (txt
(20)));
 insert into t1 (txt) values ('Chevy'), ('Chevy '), (NULL);
 select * from t1 where txt='Chevy' or txt is NULL;
 explain select * from t1 where txt='Chevy' or txt is NULL;

--- 1.127/sql/ha_innodb.cc	2004-12-03 17:57:37 +02:00
+++ 1.128/sql/ha_innodb.cc	2004-12-06 18:04:38 +02:00
@@ -2010,11 +2010,12 @@
 	switch (mysql_tp) {
 
 	case FIELD_TYPE_STRING:
-	case FIELD_TYPE_VAR_STRING:
+	case MYSQL_TYPE_VAR_STRING:
 	case FIELD_TYPE_TINY_BLOB:
 	case FIELD_TYPE_MEDIUM_BLOB:
 	case FIELD_TYPE_BLOB:
 	case FIELD_TYPE_LONG_BLOB:
+        case MYSQL_TYPE_VARCHAR:
 		/* Use the charset number to pick the right charset struct for
 		the comparison. Since the MySQL function get_charset may be
 		slow before Bar removes the mutex operation there, we first
@@ -2042,7 +2043,7 @@
 
                 ret = charset->coll->strnncollsp(charset,
                                   a, a_length,
-                                  b, b_length);
+                                                 b, b_length, 0);
 		if (ret < 0) {
 		        return(-1);
 		} else if (ret > 0) {
@@ -2071,17 +2072,11 @@
 	8 bits: this is used in ibuf and also when DATA_NOT_NULL is ORed to
 	the type */
 
-	DBUG_ASSERT((ulint)FIELD_TYPE_STRING < 256);
-	DBUG_ASSERT((ulint)FIELD_TYPE_VAR_STRING < 256);
-	DBUG_ASSERT((ulint)FIELD_TYPE_DOUBLE < 256);
-	DBUG_ASSERT((ulint)FIELD_TYPE_FLOAT < 256);
-	DBUG_ASSERT((ulint)FIELD_TYPE_DECIMAL < 256);
-
 	switch (field->type()) {
 	        /* NOTE that we only allow string types in DATA_MYSQL
 		and DATA_VARMYSQL */
-		case FIELD_TYPE_VAR_STRING: if (field->binary()) {
-
+                case MYSQL_TYPE_VAR_STRING:
+                case MYSQL_TYPE_VARCHAR: if (field->binary()) {
 						return(DATA_BINARY);
 					} else if (strcmp(
 						  field->charset()->name,
@@ -2648,12 +2643,12 @@
 
 	if (len == UNIV_SQL_NULL) {
 		data = NULL;
-	} else if (col_type == DATA_VARCHAR || col_type == DATA_BINARY
-		   || col_type == DATA_VARMYSQL) {
-	        /* Remove trailing spaces */
-        	while (len > 0 && data[len - 1] == ' ') {
-	                len--;
-	        }
+        } else if (col_type == DATA_VARCHAR || col_type == DATA_BINARY
+                   || col_type == DATA_VARMYSQL) {
+                /* Remove trailing spaces */
+                while (len > 0 && data[len - 1] == ' ') {
+                        len--;
+                }
 	} else if (col_type == DATA_INT) {
 		/* Store integer data in InnoDB in a big-endian
 		format, sign bit negated, if signed */

--- 1.72/sql/ha_innodb.h	2004-11-30 12:05:18 +02:00
+++ 1.73/sql/ha_innodb.h	2004-12-06 18:04:38 +02:00
@@ -84,6 +84,7 @@
 			  HA_CAN_SQL_HANDLER |
 			  HA_NOT_EXACT_COUNT |
 			  HA_PRIMARY_KEY_IN_READ_INDEX |
+                          HA_NO_VARCHAR |
 			  HA_TABLE_SCAN_ON_INDEX),
 	  last_dup_key((uint) -1),
 	  start_of_scan(0),

--- 1.47/mysql-test/r/myisam.result	2004-11-22 21:54:41 +02:00
+++ 1.48/mysql-test/r/myisam.result	2004-12-06 18:04:37 +02:00
@@ -408,8 +408,8 @@
 test.t1	repair	status	OK
 select concat(a,'.') from t1 where a='aaa';
 concat(a,'.')
-aaa.
 aaa   .
+aaa.
 select concat(a,'.') from t1 where binary a='aaa';
 concat(a,'.')
 aaa.
@@ -461,20 +461,27 @@
 a .
 drop table t1;
 create table t1 (a int not null auto_increment primary key, b text not null, unique b
(b(20)));
-insert into t1 (b) values ('a'),('a '),('a  ');
+insert into t1 (b) values ('a'),('b'),('c');
 select concat(b,'.') from t1;
 concat(b,'.')
 a.
-a .
-a  .
+b.
+c.
 update t1 set b='b ' where a=2;
 update t1 set b='b  ' where a > 1;
 ERROR 23000: Duplicate entry 'b  ' for key 2
+insert into t1 (b) values ('b');
+ERROR 23000: Duplicate entry 'b' for key 2
+select * from t1;
+a	b
+1	a
+2	b  
+3	c
 delete from t1 where b='b';
 select a,concat(b,'.') from t1;
 a	concat(b,'.')
 1	a.
-3	a  .
+3	c.
 drop table t1;
 create table t1 (a int not null);
 create table t2 (a int not null, primary key (a));
@@ -506,18 +513,18 @@
 insert t2 select * from t1;
 checksum table t1, t2, t3 quick;
 Table	Checksum
-test.t1	968604391
+test.t1	272226711
 test.t2	NULL
 test.t3	NULL
 checksum table t1, t2, t3;
 Table	Checksum
-test.t1	968604391
-test.t2	968604391
+test.t1	272226711
+test.t2	272226711
 test.t3	NULL
 checksum table t1, t2, t3 extended;
 Table	Checksum
-test.t1	968604391
-test.t2	968604391
+test.t1	272226711
+test.t2	272226711
 test.t3	NULL
 drop table t1,t2;
 create table t1 (a int, key (a));
@@ -555,3 +562,384 @@
 count(*)
 2
 drop table t1;
+set storage_engine=MyISAM;
+drop table if exists t1,t2,t3;
+--- Testing varchar ---
+--- Testing varchar ---
+create table t1 (v varchar(10), c char(10), t text);
+insert into t1 values('+ ', '+ ', '+ ');
+set @a=repeat(' ',20);
+insert into t1 values (concat('+',@a),concat('+',@a),concat('+',@a));
+Warnings:
+Warning	1265	Data truncated for column 'v' at row 1
+select concat('*',v,'*',c,'*',t,'*') from t1;
+concat('*',v,'*',c,'*',t,'*')
+*+ *+*+ *
+*+         *+*+                    *
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `v` varchar(10) default NULL,
+  `c` char(10) default NULL,
+  `t` text
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+create table t2 like t1;
+show create table t2;
+Table	Create Table
+t2	CREATE TABLE `t2` (
+  `v` varchar(10) default NULL,
+  `c` char(10) default NULL,
+  `t` text
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+create table t3 select * from t1;
+show create table t3;
+Table	Create Table
+t3	CREATE TABLE `t3` (
+  `v` varchar(10) default NULL,
+  `c` char(10) default NULL,
+  `t` text
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+alter table t1 modify c varchar(10);
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `v` varchar(10) default NULL,
+  `c` varchar(10) default NULL,
+  `t` text
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+alter table t1 modify v char(10);
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `v` char(10) default NULL,
+  `c` varchar(10) default NULL,
+  `t` text
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+alter table t1 modify t varchar(10);
+Warnings:
+Warning	1265	Data truncated for column 't' at row 2
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `v` char(10) default NULL,
+  `c` varchar(10) default NULL,
+  `t` varchar(10) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+select concat('*',v,'*',c,'*',t,'*') from t1;
+concat('*',v,'*',c,'*',t,'*')
+*+*+*+ *
+*+*+*+         *
+drop table t1,t2,t3;
+create table t1 (v varchar(10), c char(10), t text, key(v), key(c), key(t(10)));
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `v` varchar(10) default NULL,
+  `c` char(10) default NULL,
+  `t` text,
+  KEY `v` (`v`),
+  KEY `c` (`c`),
+  KEY `t` (`t`(10))
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+select count(*) from t1;
+count(*)
+270
+insert into t1 values(concat('a',char(1)),concat('a',char(1)),concat('a',char(1)));
+select count(*) from t1 where v='a';
+count(*)
+10
+select count(*) from t1 where c='a';
+count(*)
+10
+select count(*) from t1 where t='a';
+count(*)
+10
+select count(*) from t1 where v='a  ';
+count(*)
+10
+select count(*) from t1 where c='a  ';
+count(*)
+10
+select count(*) from t1 where t='a  ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ' and v between 'a  ' and 'b\n';
+count(*)
+10
+select count(*) from t1 where v like 'a%';
+count(*)
+11
+select count(*) from t1 where c like 'a%';
+count(*)
+11
+select count(*) from t1 where t like 'a%';
+count(*)
+11
+select count(*) from t1 where v like 'a %';
+count(*)
+9
+explain select count(*) from t1 where v='a  ';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ref	v	v	13	const	9	Using where; Using index
+explain select count(*) from t1 where c='a  ';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ref	c	c	11	const	9	Using where; Using index
+explain select count(*) from t1 where t='a  ';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	t	t	13	NULL	9	Using where
+explain select count(*) from t1 where v like 'a%';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	v	v	13	NULL	10	Using where; Using index
+explain select count(*) from t1 where v between 'a' and 'a ';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	v	v	13	NULL	9	Using where; Using index
+explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a  ' and
'b\n';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	v	v	13	NULL	9	Using where; Using index
+alter table t1 add unique(v);
+ERROR 23000: Duplicate entry '{ ' for key 1
+alter table t1 add key(v);
+select concat('*',v,'*',c,'*',t,'*') as qq from t1 where v='a';
+qq
+*a*a*a*
+*a *a*a *
+*a  *a*a  *
+*a   *a*a   *
+*a    *a*a    *
+*a     *a*a     *
+*a      *a*a      *
+*a       *a*a       *
+*a        *a*a        *
+*a         *a*a         *
+explain select * from t1 where v='a';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ref	v,v_2	v_2	13	const	7	Using where
+select v,count(*) from t1 group by v limit 10;
+v	count(*)
+a	1
+a	10
+b	10
+c	10
+d	10
+e	10
+f	10
+g	10
+h	10
+i	10
+select v,count(t) from t1 group by v limit 10;
+v	count(t)
+a	1
+a	10
+b	10
+c	10
+d	10
+e	10
+f	10
+g	10
+h	10
+i	10
+select v,count(c) from t1 group by v limit 10;
+v	count(c)
+a	1
+a	10
+b	10
+c	10
+d	10
+e	10
+f	10
+g	10
+h	10
+i	10
+select sql_big_result v,count(t) from t1 group by v limit 10;
+v	count(t)
+a	1
+a	10
+b	10
+c	10
+d	10
+e	10
+f	10
+g	10
+h	10
+i	10
+select sql_big_result v,count(c) from t1 group by v limit 10;
+v	count(c)
+a	1
+a	10
+b	10
+c	10
+d	10
+e	10
+f	10
+g	10
+h	10
+i	10
+select c,count(*) from t1 group by c limit 10;
+c	count(*)
+a	1
+a	10
+b	10
+c	10
+d	10
+e	10
+f	10
+g	10
+h	10
+i	10
+select c,count(t) from t1 group by c limit 10;
+c	count(t)
+a	1
+a	10
+b	10
+c	10
+d	10
+e	10
+f	10
+g	10
+h	10
+i	10
+select sql_big_result c,count(t) from t1 group by c limit 10;
+c	count(t)
+a	1
+a	10
+b	10
+c	10
+d	10
+e	10
+f	10
+g	10
+h	10
+i	10
+select t,count(*) from t1 group by t limit 10;
+t	count(*)
+a	1
+a	10
+b	10
+c	10
+d	10
+e	10
+f	10
+g	10
+h	10
+i	10
+select t,count(t) from t1 group by t limit 10;
+t	count(t)
+a	1
+a	10
+b	10
+c	10
+d	10
+e	10
+f	10
+g	10
+h	10
+i	10
+select sql_big_result t,count(t) from t1 group by t limit 10;
+t	count(t)
+a	1
+a	10
+b	10
+c	10
+d	10
+e	10
+f	10
+g	10
+h	10
+i	10
+drop table t1;
+create table t1 (a char(10), unique (a));
+insert into t1 values ('a   ');
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a' for key 1
+alter table t1 modify a varchar(10);
+insert into t1 values ('a '),('a  '),('a   '),('a         ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+insert into t1 values ('a     ');
+ERROR 23000: Duplicate entry 'a     ' for key 1
+insert into t1 values ('a          ');
+ERROR 23000: Duplicate entry 'a         ' for key 1
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+update t1 set a='a  ' where a like 'a%';
+select concat(a,'.') from t1;
+concat(a,'.')
+a  .
+update t1 set a='abc    ' where a like 'a ';
+select concat(a,'.') from t1;
+concat(a,'.')
+a  .
+update t1 set a='a      ' where a like 'a %';
+select concat(a,'.') from t1;
+concat(a,'.')
+a      .
+update t1 set a='a  ' where a like 'a      ';
+select concat(a,'.') from t1;
+concat(a,'.')
+a  .
+drop table t1;
+create table t1 (v varchar(10), c char(10), t text, key(v(5)), key(c(5)), key(t(5)));
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `v` varchar(10) default NULL,
+  `c` char(10) default NULL,
+  `t` text,
+  KEY `v` (`v`(5)),
+  KEY `c` (`c`(5)),
+  KEY `t` (`t`(5))
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (v char(10) character set utf8);
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `v` char(10) character set utf8 default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (v varchar(10), c char(10)) row_format=fixed;
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `v` varchar(10) default NULL,
+  `c` char(10) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 ROW_FORMAT=FIXED
+insert into t1 values('a','a'),('a ','a ');
+select concat('*',v,'*',c,'*') from t1;
+concat('*',v,'*',c,'*')
+*a*a*
+*a *a*
+drop table t1;
+create table t1 (v varchar(65530), key(v(10)));
+insert into t1 values(repeat('a',65530));
+select length(v) from t1 where v=repeat('a',65530);
+length(v)
+65530
+drop table t1;
+create table t1 (v varchar(65530), key(v));
+Warnings:
+Warning	1071	Specified key was too long; max key length is 1000 bytes
+drop table if exists t1;
+create table t1 (v varchar(65536));
+Warnings:
+Note	1246	Converting column 'v' from VARCHAR to TEXT
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `v` mediumtext
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (v varchar(65530) character set utf8);
+Warnings:
+Note	1246	Converting column 'v' from VARCHAR to TEXT
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `v` mediumtext character set utf8
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+set storage_engine=MyISAM;
+create table t1 (v varchar(65535));
+ERROR 42000: Row size too large. The maximum row size for the used table type, not
counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs

--- 1.35/mysql-test/t/myisam.test	2004-11-22 21:54:42 +02:00
+++ 1.36/mysql-test/t/myisam.test	2004-12-06 18:04:38 +02:00
@@ -450,11 +450,14 @@
 # Test text and unique
 #
 create table t1 (a int not null auto_increment primary key, b text not null, unique b
(b(20)));
-insert into t1 (b) values ('a'),('a '),('a  ');
+insert into t1 (b) values ('a'),('b'),('c');
 select concat(b,'.') from t1;
 update t1 set b='b ' where a=2;
 --error 1062
 update t1 set b='b  ' where a > 1;
+--error 1062
+insert into t1 (b) values ('b');
+select * from t1;
 delete from t1 where b='b';
 select a,concat(b,'.') from t1;
 drop table t1;
@@ -524,3 +527,15 @@
 select count(*) from t1 where a is null;
 drop table t1;
 
+#
+# Test varchar
+#
+
+let $default=`select @@storage_engine`;
+set storage_engine=MyISAM;
+source include/varchar.inc;
+eval set storage_engine=$default;
+
+# MyISAM specific varchar tests
+--error 1118
+create table t1 (v varchar(65535));

--- 1.9/mysql-test/r/strict.result	2004-12-01 01:29:00 +02:00
+++ 1.10/mysql-test/r/strict.result	2004-12-06 18:04:37 +02:00
@@ -811,12 +811,14 @@
 NULL	NULL
 1.79769313486232e+308	0
 DROP TABLE t1;
-CREATE TABLE t1 (col1 CHAR(5), col2 VARCHAR(5));
-INSERT INTO t1 VALUES ('hello', 'hello'),('he', 'he'),('hello   ', 'hello   ');
+CREATE TABLE t1 (col1 CHAR(5), col2 VARCHAR(6));
+INSERT INTO t1 VALUES ('hello', 'hello'),('he', 'he'),('hello   ', 'hello ');
 INSERT INTO t1 (col1) VALUES ('hellobob');
 ERROR 01000: Data truncated for column 'col1' at row 1
 INSERT INTO t1 (col2) VALUES ('hellobob');
 ERROR 01000: Data truncated for column 'col2' at row 1
+INSERT INTO t1 (col2) VALUES ('hello  ');
+ERROR 01000: Data truncated for column 'col2' at row 1
 UPDATE t1 SET col1 ='hellobob' WHERE col1 ='he';
 ERROR 01000: Data truncated for column 'col1' at row 2
 UPDATE t1 SET col2 ='hellobob' WHERE col2 ='he';
@@ -831,9 +833,9 @@
 SELECT * FROM t1;
 col1	col2
 hello	hello
-he	hello
-hello	hello
-hello	hello
+he	hellot
+hello	hello 
+hello	hellob
 DROP TABLE t1;
 CREATE TABLE t1 (col1 enum('red','blue','green'));
 INSERT INTO t1 VALUES ('red'),('blue'),('green');

--- 1.6/mysql-test/t/strict.test	2004-11-26 12:02:35 +02:00
+++ 1.7/mysql-test/t/strict.test	2004-12-06 18:04:38 +02:00
@@ -563,12 +563,14 @@
 
 # Testing INSERT with CHAR/VARCHAR
 
-CREATE TABLE t1 (col1 CHAR(5), col2 VARCHAR(5));
-INSERT INTO t1 VALUES ('hello', 'hello'),('he', 'he'),('hello   ', 'hello   ');
+CREATE TABLE t1 (col1 CHAR(5), col2 VARCHAR(6));
+INSERT INTO t1 VALUES ('hello', 'hello'),('he', 'he'),('hello   ', 'hello ');
 --error 1265
 INSERT INTO t1 (col1) VALUES ('hellobob');
 --error 1265
 INSERT INTO t1 (col2) VALUES ('hellobob');
+--error 1265
+INSERT INTO t1 (col2) VALUES ('hello  ');
 --error 1265
 UPDATE t1 SET col1 ='hellobob' WHERE col1 ='he';
 --error 1265

--- 1.3/mysql-test/t/endspace.test	2004-12-01 17:25:00 +02:00
+++ 1.4/mysql-test/t/endspace.test	2004-12-06 18:04:37 +02:00
@@ -41,16 +41,16 @@
 select concat('|', text1, '|') from t1 where text1='teststring';
 select concat('|', text1, '|') from t1 where text1='teststring ';
 explain select concat('|', text1, '|') from t1 where text1='teststring ';
-select * from t1 where text1 like 'teststring_%';
-select * from t1 where text1='teststring' or text1 like 'teststring_%';
+select concat('|', text1, '|') from t1 where text1 like 'teststring_%';
+select concat('|', text1, '|') from t1 where text1='teststring' or text1 like
'teststring_%';
 select concat('|', text1, '|') from t1 where text1='teststring' or text1 >
'teststring\t';
 select concat('|', text1, '|') from t1 order by text1;
 drop table t1;
 
 create table t1 (text1 varchar(32) not NULL, KEY key1 (text1)) pack_keys=0;
 insert into t1 values ('teststring'), ('nothing'), ('teststring\t');
-select * from t1 where text1='teststring' or text1 like 'teststring_%';
-select * from t1 where text1='teststring' or text1 >= 'teststring\t';
+select concat('|', text1, '|') from t1 where text1='teststring' or text1 like
'teststring_%';
+select concat('|', text1, '|') from t1 where text1='teststring' or text1 >=
'teststring\t';
 drop table t1;
 
 # Test HEAP tables (with BTREE keys)

--- 1.48/libmysqld/Makefile.am	2004-12-06 01:59:59 +02:00
+++ 1.49/libmysqld/Makefile.am	2004-12-06 18:04:36 +02:00
@@ -26,7 +26,7 @@
 			-DDATADIR="\"$(MYSQLDATAdir)\"" \
 			-DSHAREDIR="\"$(MYSQLSHAREdir)\""
 INCLUDES=		@MT_INCLUDES@ @bdb_includes@ -I$(top_srcdir)/include \
-			-I$(top_srcdir)/sql -I$(top_srcdir)/regex \
+			-I$(top_srcdir)/sql -I$(top_srcdir)/sql/examples -I$(top_srcdir)/regex \
 			$(openssl_includes) @ZLIB_INCLUDES@
 
 noinst_LIBRARIES =	libmysqld_int.a
@@ -35,6 +35,7 @@
 libmysqld_sources=	libmysqld.c lib_sql.cc emb_qcache.cc
 libmysqlsources =	errmsg.c get_password.c libmysql.c client.c pack.c \
                         my_time.c
+sqlexamplessources =	ha_example.cc ha_archive.cc ha_tina.cc
 
 noinst_HEADERS =	embedded_priv.h emb_qcache.h
 
@@ -61,7 +62,7 @@
 	sp_head.cc sp_pcontext.cc sp.cc sp_cache.cc sp_rcontext.cc \
 	parse_file.cc sql_view.cc sql_trigger.cc
 
-libmysqld_int_a_SOURCES= $(libmysqld_sources) $(libmysqlsources) $(sqlsources)
+libmysqld_int_a_SOURCES= $(libmysqld_sources) $(libmysqlsources) $(sqlsources)
$(sqlexamplessources)
 libmysqld_a_SOURCES=
 
 # automake misses these
@@ -125,12 +126,16 @@
 	    rm -f $(srcdir)/$$f; \
 	    @LN_CP_F@ $(srcdir)/../libmysql/$$f $(srcdir)/$$f; \
 	  done; \
+	  for f in $(sqlexamplessources); do \
+	    rm -f $(srcdir)/$$f; \
+	    @LN_CP_F@ $(srcdir)/../sql/examples/$$f $(srcdir)/$$f; \
+	  done; \
 	  rm -f $(srcdir)/client_settings.h; \
 	  @LN_CP_F@ $(srcdir)/../libmysql/client_settings.h $(srcdir)/client_settings.h;
 
 
 clean-local:
-	rm -f `echo $(sqlsources) $(libmysqlsources) | sed "s;\.lo;.c;g"` \
+	rm -f `echo $(sqlsources) $(libmysqlsources) $(sqlexamplessources) | sed "s;\.lo;.c;g"`
\
 	       $(top_srcdir)/linked_libmysqld_sources; \
 	rm -f client_settings.h
 

--- 1.121/client/mysqltest.c	2004-11-22 21:54:40 +02:00
+++ 1.122/client/mysqltest.c	2004-12-06 18:04:36 +02:00
@@ -778,7 +778,7 @@
   }
   else
     v = var_reg + digit;
-  return eval_expr(v, var_val, (const char**)&var_val_end);
+  DBUG_RETURN(eval_expr(v, var_val, (const char**)&var_val_end));
 }
 
 

--- 1.23/mysql-test/r/mysqldump.result	2004-11-30 19:58:12 +02:00
+++ 1.24/mysql-test/r/mysqldump.result	2004-12-06 18:04:37 +02:00
@@ -106,7 +106,7 @@
 	<table_structure name="t1">
 		<field Field="a" Type="int(11)" Null="YES" Key="" Extra="" />
 		<field Field="b" Type="text" Null="YES" Key="" Extra="" />
-		<field Field="c" Type="char(3)" Null="YES" Key="" Extra="" />
+		<field Field="c" Type="varchar(3)" Null="YES" Key="" Extra="" />
 	</table_structure>
 	<table_data name="t1">
 	<row>

--- 1.9/include/decimal.h	2004-12-06 01:59:56 +02:00
+++ 1.10/include/decimal.h	2004-12-06 18:04:36 +02:00
@@ -49,13 +49,7 @@
 int decimal_div(decimal *from1, decimal *from2, decimal *to, int scale_incr);
 int decimal_mod(decimal *from1, decimal *from2, decimal *to);
 int decimal_round(decimal *from, decimal *to, int new_scale, decimal_round_mode mode);
-
-/*
-  the following works only on special "zero" decimal, not on any
-  decimal that happen to evaluate to zero
-*/
-
-#define decimal_is_zero(dec) ((dec)->intg1==1 && (dec)->frac1==0 &&
(dec)->buf[0]==0)
+int decimal_is_zero(decimal *from);
 
 /* set a decimal to zero */
 

--- 1.31/strings/decimal.c	2004-12-06 16:08:19 +02:00
+++ 1.32/strings/decimal.c	2004-12-06 18:04:40 +02:00
@@ -98,10 +98,12 @@
       implementation-defined.
 */
 
-#include <decimal.h>
+#include <my_global.h>
 #include <m_ctype.h>
 #include <myisampack.h>
 #include <my_sys.h> /* for my_alloca */
+#include <m_string.h>
+#include <decimal.h>
 
 typedef decimal_digit dec1;
 typedef longlong      dec2;
@@ -308,7 +310,7 @@
   char *s=from, *s1;
   int i, intg, frac, error, intg1, frac1;
   dec1 x,*buf;
-
+  LINT_INIT(error);
   sanity(to);
 
   while (my_isspace(&my_charset_latin1, *s))
@@ -366,6 +368,7 @@
         intg=intg1*DIG_PER_DEC1;
     }
   }
+  /* Error is guranteed to be set here */
   to->intg=intg;
   to->frac=frac;
 
@@ -1353,6 +1356,8 @@
   dec1 *buf0, *buf1=from1->buf, *buf2=from2->buf, *tmp1,
        *start2, *stop2, *stop1, *stop0, norm2, carry, *start1;
   dec2 norm_factor, x, guess, y;
+
+  LINT_INIT(error);
 
   if (mod)
     to=mod;

--- 1.33/mysql-test/r/ps.result	2004-11-22 22:33:09 +02:00
+++ 1.34/mysql-test/r/ps.result	2004-12-06 18:04:37 +02:00
@@ -207,10 +207,10 @@
 prepare stmt1 from ' show table status from test like ''t1%'' ';
 execute stmt1;
 Name	Engine	Version	Row_format	Rows	Avg_row_length	Data_length	Max_data_length	Index_length	Data_free	Auto_increment	Create_time	Update_time	Check_time	Collation	Checksum	Create_options	Comment
-t1	MyISAM	9	Dynamic	0	0	0	4294967295	1024	0	NULL	#	#	#	latin1_swedish_ci	NULL		
+t1	MyISAM	10	Dynamic	0	0	0	4294967295	1024	0	NULL	#	#	#	latin1_swedish_ci	NULL		
 show table status from test like 't1%' ;
 Name	Engine	Version	Row_format	Rows	Avg_row_length	Data_length	Max_data_length	Index_length	Data_free	Auto_increment	Create_time	Update_time	Check_time	Collation	Checksum	Create_options	Comment
-t1	MyISAM	9	Dynamic	0	0	0	4294967295	1024	0	NULL	#	#	#	latin1_swedish_ci	NULL		
+t1	MyISAM	10	Dynamic	0	0	0	4294967295	1024	0	NULL	#	#	#	latin1_swedish_ci	NULL		
 deallocate prepare stmt1 ;
 drop table t1;
 create table t1(a varchar(2), b varchar(3));

--- 1.34/mysql-test/r/bdb.result	2004-11-04 23:37:32 +02:00
+++ 1.35/mysql-test/r/bdb.result	2004-12-06 19:18:30 +02:00
@@ -140,13 +140,13 @@
 1015	102	2
 explain select level from t1 where level=1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t1	ref	level	level	1	const	1	Using index
+1	SIMPLE	t1	ref	level	level	1	const	6	Using index
 explain select level,id from t1 where level=1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t1	ref	level	level	1	const	1	Using index
+1	SIMPLE	t1	ref	level	level	1	const	6	Using index
 explain select level,id,parent_id from t1 where level=1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t1	ref	level	level	1	const	1	
+1	SIMPLE	t1	ref	level	level	1	const	6	
 select level,id from t1 where level=1;
 level	id
 1	1002
@@ -625,7 +625,7 @@
 1016	102	2
 explain select level from t1 where level=1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t1	ref	level	level	1	const	1	Using index
+1	SIMPLE	t1	ref	level	level	1	const	6	Using index
 select level,id from t1 where level=1;
 level	id
 1	1004
@@ -1291,3 +1291,382 @@
 select * from t1;
 a	b
 drop table t1;
+set storage_engine=bdb;
+drop table if exists t1,t2,t3;
+--- Testing varchar ---
+--- Testing varchar ---
+create table t1 (v varchar(10), c char(10), t text);
+insert into t1 values('+ ', '+ ', '+ ');
+set @a=repeat(' ',20);
+insert into t1 values (concat('+',@a),concat('+',@a),concat('+',@a));
+Warnings:
+Warning	1265	Data truncated for column 'v' at row 1
+select concat('*',v,'*',c,'*',t,'*') from t1;
+concat('*',v,'*',c,'*',t,'*')
+*+ *+*+ *
+*+         *+*+                    *
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `v` varchar(10) default NULL,
+  `c` char(10) default NULL,
+  `t` text
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
+create table t2 like t1;
+show create table t2;
+Table	Create Table
+t2	CREATE TABLE `t2` (
+  `v` varchar(10) default NULL,
+  `c` char(10) default NULL,
+  `t` text
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
+create table t3 select * from t1;
+show create table t3;
+Table	Create Table
+t3	CREATE TABLE `t3` (
+  `v` varchar(10) default NULL,
+  `c` char(10) default NULL,
+  `t` text
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
+alter table t1 modify c varchar(10);
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `v` varchar(10) default NULL,
+  `c` varchar(10) default NULL,
+  `t` text
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
+alter table t1 modify v char(10);
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `v` char(10) default NULL,
+  `c` varchar(10) default NULL,
+  `t` text
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
+alter table t1 modify t varchar(10);
+Warnings:
+Warning	1265	Data truncated for column 't' at row 2
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `v` char(10) default NULL,
+  `c` varchar(10) default NULL,
+  `t` varchar(10) default NULL
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
+select concat('*',v,'*',c,'*',t,'*') from t1;
+concat('*',v,'*',c,'*',t,'*')
+*+*+*+ *
+*+*+*+         *
+drop table t1,t2,t3;
+create table t1 (v varchar(10), c char(10), t text, key(v), key(c), key(t(10)));
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `v` varchar(10) default NULL,
+  `c` char(10) default NULL,
+  `t` text,
+  KEY `v` (`v`),
+  KEY `c` (`c`),
+  KEY `t` (`t`(10))
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
+select count(*) from t1;
+count(*)
+270
+insert into t1 values(concat('a',char(1)),concat('a',char(1)),concat('a',char(1)));
+select count(*) from t1 where v='a';
+count(*)
+10
+select count(*) from t1 where c='a';
+count(*)
+10
+select count(*) from t1 where t='a';
+count(*)
+10
+select count(*) from t1 where v='a  ';
+count(*)
+10
+select count(*) from t1 where c='a  ';
+count(*)
+10
+select count(*) from t1 where t='a  ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ' and v between 'a  ' and 'b\n';
+count(*)
+10
+select count(*) from t1 where v like 'a%';
+count(*)
+11
+select count(*) from t1 where c like 'a%';
+count(*)
+11
+select count(*) from t1 where t like 'a%';
+count(*)
+11
+select count(*) from t1 where v like 'a %';
+count(*)
+9
+explain select count(*) from t1 where v='a  ';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ref	v	v	13	const	10	Using where
+explain select count(*) from t1 where c='a  ';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ref	c	c	11	const	10	Using where
+explain select count(*) from t1 where t='a  ';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	t	t	13	NULL	10	Using where
+explain select count(*) from t1 where v like 'a%';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	v	v	13	NULL	11	Using where
+explain select count(*) from t1 where v between 'a' and 'a ';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	v	v	13	NULL	10	Using where
+explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a  ' and
'b\n';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	v	v	13	NULL	10	Using where
+alter table t1 add unique(v);
+ERROR 23000: Duplicate entry '{ ' for key 1
+alter table t1 add key(v);
+select concat('*',v,'*',c,'*',t,'*') as qq from t1 where v='a';
+qq
+*a*a*a*
+*a *a*a *
+*a  *a*a  *
+*a   *a*a   *
+*a    *a*a    *
+*a     *a*a     *
+*a      *a*a      *
+*a       *a*a       *
+*a        *a*a        *
+*a         *a*a         *
+explain select * from t1 where v='a';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ref	v,v_2	v	13	const	10	Using where
+select v,count(*) from t1 group by v limit 10;
+v	count(*)
+a	1
+a	10
+b	10
+c	10
+d	10
+e	10
+f	10
+g	10
+h	10
+i	10
+select v,count(t) from t1 group by v limit 10;
+v	count(t)
+a	1
+a	10
+b	10
+c	10
+d	10
+e	10
+f	10
+g	10
+h	10
+i	10
+select v,count(c) from t1 group by v limit 10;
+v	count(c)
+a	1
+a	10
+b	10
+c	10
+d	10
+e	10
+f	10
+g	10
+h	10
+i	10
+select sql_big_result v,count(t) from t1 group by v limit 10;
+v	count(t)
+a	1
+a	10
+b	10
+c	10
+d	10
+e	10
+f	10
+g	10
+h	10
+i	10
+select sql_big_result v,count(c) from t1 group by v limit 10;
+v	count(c)
+a	1
+a	10
+b	10
+c	10
+d	10
+e	10
+f	10
+g	10
+h	10
+i	10
+select c,count(*) from t1 group by c limit 10;
+c	count(*)
+a	1
+a	10
+b	10
+c	10
+d	10
+e	10
+f	10
+g	10
+h	10
+i	10
+select c,count(t) from t1 group by c limit 10;
+c	count(t)
+a	1
+a	10
+b	10
+c	10
+d	10
+e	10
+f	10
+g	10
+h	10
+i	10
+select sql_big_result c,count(t) from t1 group by c limit 10;
+c	count(t)
+a	1
+a	10
+b	10
+c	10
+d	10
+e	10
+f	10
+g	10
+h	10
+i	10
+select t,count(*) from t1 group by t limit 10;
+t	count(*)
+a	1
+a	10
+b	10
+c	10
+d	10
+e	10
+f	10
+g	10
+h	10
+i	10
+select t,count(t) from t1 group by t limit 10;
+t	count(t)
+a	1
+a	10
+b	10
+c	10
+d	10
+e	10
+f	10
+g	10
+h	10
+i	10
+select sql_big_result t,count(t) from t1 group by t limit 10;
+t	count(t)
+a	1
+a         	10
+b         	10
+c         	10
+d         	10
+e         	10
+f         	10
+g         	10
+h         	10
+i         	10
+drop table t1;
+create table t1 (a char(10), unique (a));
+insert into t1 values ('a   ');
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a' for key 1
+alter table t1 modify a varchar(10);
+insert into t1 values ('a '),('a  '),('a   '),('a         ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+insert into t1 values ('a     ');
+ERROR 23000: Duplicate entry 'a     ' for key 1
+insert into t1 values ('a          ');
+ERROR 23000: Duplicate entry 'a         ' for key 1
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+update t1 set a='a  ' where a like 'a%';
+select concat(a,'.') from t1;
+concat(a,'.')
+a  .
+update t1 set a='abc    ' where a like 'a ';
+select concat(a,'.') from t1;
+concat(a,'.')
+a  .
+update t1 set a='a      ' where a like 'a %';
+select concat(a,'.') from t1;
+concat(a,'.')
+a      .
+update t1 set a='a  ' where a like 'a      ';
+select concat(a,'.') from t1;
+concat(a,'.')
+a  .
+drop table t1;
+create table t1 (v varchar(10), c char(10), t text, key(v(5)), key(c(5)), key(t(5)));
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `v` varchar(10) default NULL,
+  `c` char(10) default NULL,
+  `t` text,
+  KEY `v` (`v`(5)),
+  KEY `c` (`c`(5)),
+  KEY `t` (`t`(5))
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (v char(10) character set utf8);
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `v` char(10) character set utf8 default NULL
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (v varchar(10), c char(10)) row_format=fixed;
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `v` varchar(10) default NULL,
+  `c` char(10) default NULL
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1 ROW_FORMAT=FIXED
+insert into t1 values('a','a'),('a ','a ');
+select concat('*',v,'*',c,'*') from t1;
+concat('*',v,'*',c,'*')
+*a*a*
+*a *a*
+drop table t1;
+create table t1 (v varchar(65530), key(v(10)));
+insert into t1 values(repeat('a',65530));
+select length(v) from t1 where v=repeat('a',65530);
+length(v)
+65530
+drop table t1;
+create table t1 (v varchar(65530), key(v));
+Warnings:
+Warning	1071	Specified key was too long; max key length is 255 bytes
+drop table if exists t1;
+create table t1 (v varchar(65536));
+Warnings:
+Note	1246	Converting column 'v' from VARCHAR to TEXT
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `v` mediumtext
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (v varchar(65530) character set utf8);
+Warnings:
+Note	1246	Converting column 'v' from VARCHAR to TEXT
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `v` mediumtext character set utf8
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
+drop table t1;
+set storage_engine=MyISAM;

--- 1.40/mysql-test/t/bdb.test	2004-11-04 23:37:32 +02:00
+++ 1.41/mysql-test/t/bdb.test	2004-12-06 19:18:30 +02:00
@@ -939,3 +939,12 @@
 select * from t1;
 drop table t1;
 
+
+#
+# Test varchar
+#
+
+let $default=`select @@storage_engine`;
+set storage_engine=bdb;
+source include/varchar.inc;
+eval set storage_engine=$default;

--- 1.82/tests/client_test.c	2004-12-06 11:38:52 +02:00
+++ 1.83/tests/client_test.c	2004-12-06 18:04:41 +02:00
@@ -7651,13 +7651,13 @@
 
   if (!opt_silent)
   {
-    fprintf(stdout, "\n id    : %d", id);
-    fprintf(stdout, "\n name  : %s(%ld)", data, length);
+    fprintf(stdout, "id    : %d\n", id);
+    fprintf(stdout, "name  : %s(%ld)\n", data, length);
   }
 
   DIE_UNLESS(id == 9876);
-  DIE_UNLESS(length == 19); /* Due to VARCHAR(20) */
-  DIE_UNLESS(strcmp(data, "MySQL - Open Source") == 0);
+  DIE_UNLESS(length == 19 || length == 20); /* Due to VARCHAR(20) */
+  DIE_UNLESS(is_prefix(data, "MySQL - Open Source") == 1);
 
   rc= mysql_stmt_fetch(stmt);
   check_execute(stmt, rc);

--- 1.36/sql/sql_help.cc	2004-11-25 02:23:08 +02:00
+++ 1.37/sql/sql_help.cc	2004-12-06 18:04:39 +02:00
@@ -286,8 +286,7 @@
   relations->file->ha_index_init(iindex_relations);
 
   rkey_id->store((longlong) key_id);
-  rkey_id->get_key_image(buff, rkey_id->pack_length(), rkey_id->charset(),
-			 Field::itRAW);
+  rkey_id->get_key_image(buff, rkey_id->pack_length(), Field::itRAW);
   int key_res= relations->file->index_read(relations->record[0],
 					   (byte *)buff, rkey_id->pack_length(),
 					   HA_READ_KEY_EXACT);
@@ -300,8 +299,7 @@
     longlong topic_id= rtopic_id->val_int();
     Field *field= find_fields[help_topic_help_topic_id].field;
     field->store((longlong) topic_id);
-    field->get_key_image(topic_id_buff, field->pack_length(), field->charset(),
-			 Field::itRAW);
+    field->get_key_image(topic_id_buff, field->pack_length(), Field::itRAW);
 
     if (!topics->file->index_read(topics->record[0], (byte *)topic_id_buff,
 				  field->pack_length(), HA_READ_KEY_EXACT))
Thread
bk commit into 5.0 tree (monty:1.1720)monty6 Dec