← Back to team overview

maria-developers team mailing list archive

Re: Sachin weekly report

 

Hi Sergei!

This code  is about adding new long unique key, This is a section of
code from mysql_prepare_create_table, The main problem is can we make
this code more shorter ? And the reason for this code is that we need
to add
Alter_info::ALTER_ADD_CHECK_CONSTRAINT , only if there is unique key
on long columns

Query statements can be like this

alter table t1 add unique key a; // here a is blob

or

alter table t1 add b blob unique;
alter table t1 add c varchar(1000) unique;

This is code

{
    Key *key;
    while ((key=key_it++))          // Add new keys
    {
      if (key->type == Key::FOREIGN_KEY &&
          ((Foreign_key *)key)->validate(new_create_list))
        goto err;

from here
==> if (key->type == Key::UNIQUE)
      {
        List_iterator_fast<Key_part_spec> li(key->columns);
        Key_part_spec *column;
        uint total_length= 0;
        Field **f, *field;
        Create_field *cf;
        bool is_hash_key= false;
        while ((column= li++))
        {
          if (column->length > table->file->max_key_part_length())
          {
            is_hash_key= true;
            break;
          }
          else if (!column->length)
          {
            for (f= table->field; f && (field= *f); f++)
            {
              if (!my_strcasecmp(system_charset_info, field->field_name,
                                column->field_name.str))
              {
                if (field->max_display_length() >
table->file->max_key_part_length())
                {
                  is_hash_key= true;
                  goto exit;
                }
                total_length+= field->max_display_length();
              }
            }
            /*
              Suppose query is like
                alter table t1 add column a blob unique;
                alter table t2 add column a blob,add column c blob,
add unique key(a,b);
              In this case we have to add ALTER_ADD_CHECK_CONSTRAINT_FLAG
              We cant simply add ALTER_ADD_CHECK_CONSTRAINT flag
because it is expensive.
              And there is no other way of doing this type of check.
             */
            field_it.rewind();
            while((cf= field_it++))
            {
              if (!my_strcasecmp(system_charset_info, cf->field_name,
                                 column->field_name.str))
              {
                if (cf->sql_type == MYSQL_TYPE_TINY_BLOB ||
                    cf->sql_type == MYSQL_TYPE_MEDIUM_BLOB ||
                    cf->sql_type == MYSQL_TYPE_LONG_BLOB ||
                    cf->sql_type == MYSQL_TYPE_BLOB)
                {
                  is_hash_key= true;
                  break;
                }
                if ((cf->sql_type == MYSQL_TYPE_VARCHAR ||
                     cf->sql_type == MYSQL_TYPE_VAR_STRING) &&
                    cf->length > table->file->max_key_part_length())
                {
                  is_hash_key= true;
                  break;
                }
                total_length+= cf->length;
              }
            }
          }
        }
        exit:
        if (is_hash_key || total_length > table->file->max_key_length())
        {
          alter_info->flags |= Alter_info::ALTER_ADD_CHECK_CONSTRAINT;
          alter_info->flags |= Alter_info::ALTER_ADD_COLUMN;
        }
      }
      new_key_list.push_back(key, thd->mem_root);
      if (key->name.str &&
      !my_strcasecmp(system_charset_info, key->name.str, primary_key_name))
      {
    my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name.str);
        goto err;
      }
    }
  }

On Wed, Aug 31, 2016 at 8:49 PM, sachin setiya
<sachinsetia1001@xxxxxxxxx> wrote:
> Hi Sergei!
>
>
> On 08/24/2016 11:05 PM, Sergei Golubchik wrote:
>
> Hi, Sachin!
>
> On Aug 13, Sachin Setia wrote:
>
> Hello Sergei!
> Please review  commit 71f9069 onward i have changed
> mysql_prepare_alter_table func.
>
> Okay, here it is. Up to the 03e29c6 (this is one after 71f9069).
>
> Short summary - this all looks pretty good. There're issues, but as a
> whole - great work!
>
> diff --git a/include/my_base.h b/include/my_base.h
> index 1317639..d03ca0f 100644
> --- a/include/my_base.h
> +++ b/include/my_base.h
> @@ -241,6 +241,19 @@ enum ha_base_keytype {
>    HA_KEYTYPE_BIT=19
>  };
>
> +/* Add some constant related to unique long hash column like length hash
> string etc*/
> +
> +#define HA_HASH_KEY_LENGTH_WITHOUT_NULL 8
> +#define HA_HASH_FIELD_LENGTH            8
> +#define HA_HASH_KEY_LENGTH_WITH_NULL    9
> +#define HA_HASH_STR_HEAD                "hash(`" //used in
> mysql_prepare_create_table
> +#define HA_HASH_STR_HEAD_LEN            strlen(HA_HASH_STR_HEAD_LEN)
> +#define HA_HASH_STR                     "hash"
> +#define HA_HASH_STR_LEN                 strlen(HA_HASH_STR)
> +#define HA_HASH_STR_INDEX               "HASH_INDEX"
> +#define HA_HASH_STR_INDEX_LEN           strlen(HA_HASH_STR_INDEX)
> +#define HA_DB_ROW_HASH_STR              "DB_ROW_HASH_"
>
> no need to put all these constants into the very global my_base.h.
> better to define them in sql_show.cc or sql_table.cc (depending on where
> they're used)
>
> Actually first three are needed in files like opt_range.cc. I moved this to
> table.h
>
> +
>  #define HA_MAX_KEYTYPE 31              /* Must be log2-1 */
>
>  /*
> diff --git a/mysql-test/r/features.result b/mysql-test/r/features.result
> index 52650d1..e050efb 100644
> --- a/mysql-test/r/features.result
> +++ b/mysql-test/r/features.result
> @@ -7,6 +7,7 @@ Feature_delay_key_write 0
>  Feature_dynamic_columns        0
>  Feature_fulltext       0
>  Feature_gis    0
> +Feature_hidden_column  0
>
> Great!
> Please, add also a test where it's not 0. I mean, in your hidden_field.test
> you can add
>
>   FLUSH STATUS;
>
> at the beginning of the file and SHOW STATUS LIKE 'Feature_hidden_column';
> somewhere later. This will show that Feature_hidden_column is incremented
> accordingly.
>
> Done.
>
>  Feature_locale 0
>  Feature_subquery       0
>  Feature_timezone       0
> diff --git a/mysql-test/r/hidden_field.result
> b/mysql-test/r/hidden_field.result
> new file mode 100644
> index 0000000..09a2c21
> --- /dev/null
> +++ b/mysql-test/r/hidden_field.result
> @@ -0,0 +1,367 @@
> +create table h_1(abc int primary key, xyz int hidden);
> +desc h_1;
> +Field  Type    Null    Key     Default Extra
> +abc    int(11) NO      PRI     NULL
> +xyz    int(11) YES             NULL    HIDDEN
> +show create table h_1;
> +Table  Create Table
> +h_1    CREATE TABLE `h_1` (
> +  `abc` int(11) NOT NULL,
> +  `xyz` int(11) HIDDEN DEFAULT NULL,
> +  PRIMARY KEY (`abc`)
> +) ENGINE=MyISAM DEFAULT CHARSET=latin1
> +drop table h_1;
> +create table h_2(a1 int hidden);
> +ERROR 42000: A table must have at least 1 column
> +create table h_3(a1 blob,hidden(a1));
> +ERROR 42000: You have an error in your SQL syntax; check the manual that
> corresponds to your MariaDB server version for the right syntax to use near
> 'hidden(a1))' at line 1
> +create table h_4(a1 int primary key hidden ,a2 int unique hidden , a3
> blob,a4
> +int not null hidden unique);
> +ERROR HY000: Hidden column 'a1' either allow null values or it must have
> default value
> +create table h_5(abc int not null hidden);
> +ERROR HY000: Hidden column 'abc' either allow null values or it must have
> default value
> +create table t1(a int hidden, b int);
> +insert into t1 values(1);
> +insert into t1(a) values(1);
> +insert into t1(b) values(1);
>
> better insert 1,2,3 not 1,1,1
> so that in SELECT you could unambigously see what INSERT has added what row
>
> Changed.
>
> +insert into t1(a,b) values(5,5);
> +select * from t1;
> +b
> +1
> +NULL
> +1
> +5
> +select a,b from t1;
> +a      b
> +NULL   1
> +1      NULL
> +NULL   1
> +5      5
> +delete from t1;
> +insert into t1 values(1),(2),(3),(4);
> +select * from t1;
> +b
> +1
> +2
> +3
> +4
> +select a from t1;
> +a
> +NULL
> +NULL
> +NULL
> +NULL
> +drop table t1;
> +create table t1(a int , b int hidden , c int hidden auto_increment unique,
> d blob , e int unique, f int);
> +desc t1;
> +Field  Type    Null    Key     Default Extra
> +a      int(11) YES             NULL
> +b      int(11) YES             NULL    HIDDEN
> +c      int(11) NO      PRI     NULL    auto_increment , HIDDEN
>
> why a space before the comma?
>
> Okay Reverted.
>
> +d      blob    YES             NULL
> +e      int(11) YES     UNI     NULL
> +f      int(11) YES             NULL
> +insert into t1 values(1,'d blob',1,1),(1,'d blob',11,1),(1,'d
> blob',2,1),(1,'d blob',3,1),(1,'d blob',41,1);
> +select * from t1;
> +a      d       e       f
> +1      d blob  1       1
> +1      d blob  11      1
> +1      d blob  2       1
> +1      d blob  3       1
> +1      d blob  41      1
> +drop table t1;
> +create table sdsdsd(a int , b int, hidden(a,b));
> +ERROR 42000: You have an error in your SQL syntax; check the manual that
> corresponds to your MariaDB server version for the right syntax to use near
> 'hidden(a,b))' at line 1
> +create table t1(a int,abc int as (a mod 3) virtual hidden);
> +desc t1;
> +Field  Type    Null    Key     Default Extra
> +a      int(11) YES             NULL
> +abc    int(11) YES             NULL    VIRTUAL , HIDDEN
> +insert into t1 values(1,default);
> +ERROR 21S01: Column count doesn't match value count at row 1
> +insert into t1 values(1),(22),(233);
> +select * from t1;
> +a
> +1
> +22
> +233
> +select a,abc from t1;
> +a      abc
> +1      1
> +22     1
> +233    2
> +drop table t1;
> +create table t1(abc int primary key hidden auto_increment, a int);
> +desc t1;
> +Field  Type    Null    Key     Default Extra
> +abc    int(11) NO      PRI     NULL    auto_increment , HIDDEN
> +a      int(11) YES             NULL
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `abc` int(11) NOT NULL HIDDEN AUTO_INCREMENT,
> +  `a` int(11) DEFAULT NULL,
> +  PRIMARY KEY (`abc`)
> +) ENGINE=MyISAM DEFAULT CHARSET=latin1
> +insert into t1 values(1);
> +insert into t1 values(2);
> +insert into t1 values(3);
> +select * from t1;
> +a
> +1
> +2
> +3
> +select abc,a from t1;
> +abc    a
> +1      1
> +2      2
> +3      3
> +delete  from t1;
> +insert into t1 values(1),(2),(3),(4),(6);
> +select abc,a from t1;
> +abc    a
> +4      1
> +5      2
> +6      3
> +7      4
> +8      6
> +drop table t1;
> +create table t1(abc int);
> +alter table t1 change abc ss int hidden;
> +ERROR 42000: A table must have at least 1 column
> +alter table t1 add column xyz int;
> +alter table t1 modify column abc  int ;
> +desc t1;
> +Field  Type    Null    Key     Default Extra
> +abc    int(11) YES             NULL
> +xyz    int(11) YES             NULL
> +insert into t1 values(22);
> +ERROR 21S01: Column count doesn't match value count at row 1
> +alter table t1 modify column abc  int hidden;
>
> please, add also tests for making hidden fields visible again.
> I think that
>
>   alter table t1 modify column abc int;
>
> will do the job
>
> Okay, Added.
>
> +desc t1;
> +Field  Type    Null    Key     Default Extra
> +abc    int(11) YES             NULL    HIDDEN
> +xyz    int(11) YES             NULL
> +insert into t1 values(12);
> +drop table t1;
> +some test on copy table structure with table data;
> +table with hidden fields and unique keys;
> +create table t1(a int , b int hidden , c int hidden auto_increment unique,
> d blob , e int unique, f int);
> +desc t1;
> +Field  Type    Null    Key     Default Extra
> +a      int(11) YES             NULL
> +b      int(11) YES             NULL    HIDDEN
> +c      int(11) NO      PRI     NULL    auto_increment , HIDDEN
> +d      blob    YES             NULL
> +e      int(11) YES     UNI     NULL
> +f      int(11) YES             NULL
> +insert into t1 values(1,'d blob',1,1),(1,'d blob',11,1),(1,'d
> blob',2,1),(1,'d blob',3,1),(1,'d blob',41,1);
> +select * from t1;
> +a      d       e       f
> +1      d blob  1       1
> +1      d blob  11      1
> +1      d blob  2       1
> +1      d blob  3       1
> +1      d blob  41      1
> +select a,b,c,d,e,f from t1;
> +a      b       c       d       e       f
> +1      NULL    1       d blob  1       1
> +1      NULL    2       d blob  11      1
> +1      NULL    3       d blob  2       1
> +1      NULL    4       d blob  3       1
> +1      NULL    5       d blob  41      1
> +this wont copy hidden fields and keys;
> +create table t2 as select * from t1;
> +desc t2;
> +Field  Type    Null    Key     Default Extra
> +a      int(11) YES             NULL
> +d      blob    YES             NULL
> +e      int(11) YES             NULL
> +f      int(11) YES             NULL
> +select * from t2;
> +a      d       e       f
> +1      d blob  1       1
> +1      d blob  11      1
> +1      d blob  2       1
> +1      d blob  3       1
> +1      d blob  41      1
> +select a,b,c,d,e,f from t2;
> +ERROR 42S22: Unknown column 'b' in 'field list'
> +drop table t2;
> +now this will copy hidden fields
> +create table t2 as select a,b,c,d,e,f from t1;
> +desc t2;
> +Field  Type    Null    Key     Default Extra
> +a      int(11) YES             NULL
> +b      int(11) YES             NULL    HIDDEN
> +c      int(11) NO              0       HIDDEN
> +d      blob    YES             NULL
> +e      int(11) YES             NULL
> +f      int(11) YES             NULL
> +select * from t2;
> +a      d       e       f
> +1      d blob  1       1
> +1      d blob  11      1
> +1      d blob  2       1
> +1      d blob  3       1
> +1      d blob  41      1
> +select a,b,c,d,e,f from t2;
> +a      b       c       d       e       f
> +1      NULL    1       d blob  1       1
> +1      NULL    2       d blob  11      1
> +1      NULL    3       d blob  2       1
> +1      NULL    4       d blob  3       1
> +1      NULL    5       d blob  41      1
> +drop table t2,t1;
> +some test related to copy of data from one table to another;
> +create table t1(a int , b int hidden , c int hidden auto_increment unique,
> d blob , e int unique, f int);
> +insert into t1 values(1,'d blob',1,1),(1,'d blob',11,1),(1,'d
> blob',2,1),(1,'d blob',3,1),(1,'d blob',41,1);
> +select a,b,c,d,e,f from t1;
> +a      b       c       d       e       f
> +1      NULL    1       d blob  1       1
> +1      NULL    2       d blob  11      1
> +1      NULL    3       d blob  2       1
> +1      NULL    4       d blob  3       1
> +1      NULL    5       d blob  41      1
> +create table t2(a int , b int hidden , c int hidden , d blob , e int
> unique, f int);
> +insert into t2 select * from t1;
> +select a,b,c,d,e,f from t2;
> +a      b       c       d       e       f
> +1      NULL    NULL    d blob  1       1
> +1      NULL    NULL    d blob  11      1
> +1      NULL    NULL    d blob  2       1
> +1      NULL    NULL    d blob  3       1
> +1      NULL    NULL    d blob  41      1
> +truncate t2;
> +insert into t2 (a,b,c,d,e,f) select a,b,c,d,e,f from t1;
> +select a,b,c,d,e,f from t2;
> +a      b       c       d       e       f
> +1      NULL    1       d blob  1       1
> +1      NULL    2       d blob  11      1
> +1      NULL    3       d blob  2       1
> +1      NULL    4       d blob  3       1
> +1      NULL    5       d blob  41      1
> +truncate t2;
> +drop table t1,t2;
> +some test related to creating view on table with hidden column;
> +create table t1(a int , b int hidden , c int hidden auto_increment unique,
> d blob , e int unique, f int);
> +insert into t1 values(1,'d blob',1,1),(1,'d blob',11,1),(1,'d
> blob',2,1),(1,'d blob',3,1),(1,'d blob',41,1);
> +create view v as select * from t1;
> +desc v;
> +Field  Type    Null    Key     Default Extra
> +a      int(11) YES             NULL
> +d      blob    YES             NULL
> +e      int(11) YES             NULL
> +f      int(11) YES             NULL
> +select * from v;
> +a      d       e       f
> +1      d blob  1       1
> +1      d blob  11      1
> +1      d blob  2       1
> +1      d blob  3       1
> +1      d blob  41      1
> +v does not have hidden column;
> +select a,b,c,d,e,f from v;
> +ERROR 42S22: Unknown column 'b' in 'field list'
> +insert into v values(1,21,32,4);
> +select * from v;
> +a      d       e       f
> +1      d blob  1       1
> +1      d blob  11      1
> +1      d blob  2       1
> +1      d blob  3       1
> +1      d blob  41      1
> +1      21      32      4
> +insert into v(a,b,c,d,e,f) values(1,12,3,4,5,6);
> +ERROR 42S22: Unknown column 'b' in 'field list'
> +drop view v;
> +create view v as select a,b,c,d,e,f from t1;
> +desc v;
> +Field  Type    Null    Key     Default Extra
> +a      int(11) YES             NULL
> +b      int(11) YES             NULL    HIDDEN
> +c      int(11) NO              0       HIDDEN
> +d      blob    YES             NULL
> +e      int(11) YES             NULL
> +f      int(11) YES             NULL
> +select * from v;
> +a      b       c       d       e       f
> +1      NULL    1       d blob  1       1
> +1      NULL    2       d blob  11      1
> +1      NULL    3       d blob  2       1
> +1      NULL    4       d blob  3       1
> +1      NULL    5       d blob  41      1
> +1      NULL    6       21      32      4
> +v does  have hidden column;
> +select a,b,c,d,e,f from v;
> +a      b       c       d       e       f
> +1      NULL    1       d blob  1       1
> +1      NULL    2       d blob  11      1
> +1      NULL    3       d blob  2       1
> +1      NULL    4       d blob  3       1
> +1      NULL    5       d blob  41      1
> +1      NULL    6       21      32      4
> +insert into v values(1,26,33,4,45,66);
> +select a,b,c,d,e,f from v;
> +a      b       c       d       e       f
> +1      NULL    1       d blob  1       1
> +1      NULL    2       d blob  11      1
> +1      NULL    3       d blob  2       1
> +1      NULL    4       d blob  3       1
> +1      NULL    5       d blob  41      1
> +1      NULL    6       21      32      4
> +1      26      33      4       45      66
> +insert into v(a,b,c,d,e,f) values(1,32,31,41,5,6);
> +select a,b,c,d,e,f from v;
> +a      b       c       d       e       f
> +1      NULL    1       d blob  1       1
> +1      NULL    2       d blob  11      1
> +1      NULL    3       d blob  2       1
> +1      NULL    4       d blob  3       1
> +1      NULL    5       d blob  41      1
> +1      NULL    6       21      32      4
> +1      26      33      4       45      66
> +1      32      31      41      5       6
> +drop view v;
> +drop table t1;
> +now hidden column in where and some join query i think no use of this test
> but anyway;
> +create table t1 (a int unique , b int hidden unique, c int unique  hidden);
> +insert into t1(a,b,c) values(1,1,1);
> +insert into t1(a,b,c) values(2,2,2);
> +insert into t1(a,b,c) values(3,3,3);
> +insert into t1(a,b,c) values(4,4,4);
> +insert into t1(a,b,c) values(21,21,26);
> +insert into t1(a,b,c) values(31,31,35);
> +insert into t1(a,b,c) values(41,41,45);
> +insert into t1(a,b,c) values(22,22,24);
> +insert into t1(a,b,c) values(32,32,33);
> +insert into t1(a,b,c) values(42,42,43);
> +explain select * from t1 where b=3;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      const   b       b       5       const   1
> +select * from t1 where b=3;
> +a
> +3
> +explain select * from t1 where c=3;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      const   c       c       5       const   1
> +select * from t1 where c=3;
> +a
> +3
> +create table t2 as select a,b,c from t1;
> +desc t2;
> +Field  Type    Null    Key     Default Extra
> +a      int(11) YES             NULL
> +b      int(11) YES             NULL    HIDDEN
> +c      int(11) YES             NULL    HIDDEN
> +explain select * from t1,t2 where t1.b = t2.c and t1.c = t2.b;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t2      ALL     NULL    NULL    NULL    NULL    10
> +1      SIMPLE  t1      ALL     b,c     NULL    NULL    NULL    10
> Using where; Using join buffer (flat, BNL join)
> +select * from t1,t2 where t1.b = t2.c and t1.c = t2.b;
> +a      a
> +1      1
> +2      2
> +3      3
> +4      4
> +drop table t1,t2;
> diff --git a/mysql-test/r/long_unique_where.result
> b/mysql-test/r/long_unique_where.result
> new file mode 100644
> index 0000000..e9bd416
> --- /dev/null
> +++ b/mysql-test/r/long_unique_where.result
> @@ -0,0 +1,340 @@
> +create table t1(abc blob unique);
> +insert into t1 values(1),(2),(3),(4),(5),(11),(12),(31),(14),(15),(NULL)
> +,(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),
> +(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),
> +(NULL),(NULL),(NULL),(NULL),(NULL);
> +insert into t1 value(1);
> +ERROR 23000: Duplicate entry '1' for key 'abc'
> +explain select * from t1 where abc=31;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      const   abc     abc     9       const   1
> +select * from t1 where abc=31;
> +abc
> +31
> +# in case of null we do not use any optimization
> +explain select * from t1 where abc is  NULL;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      ALL     NULL    NULL    NULL    NULL    36
> Using where
> +select * from t1 where abc is  NULL limit 1;
> +abc
> +NULL
> +#range query
>
> please clarify it here, for example, like
>
>  #range query (index not used, because it's a hash)
>
> Copied , :).
>
> +explain select * from t1 where abc >1  limit 1;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      ALL     NULL    NULL    NULL    NULL    36
> Using where
> +select * from t1 where abc >1 limit 1;
> +abc
> +2
> +explain select * from t1 where abc >1 and abc <4;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      ALL     NULL    NULL    NULL    NULL    36
> Using where
> +select * from t1 where abc >1 and abc <4;
> +abc
> +2
> +3
> +explain select * from t1 where abc =15 or abc <4 ;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      ALL     NULL    NULL    NULL    NULL    36
> Using where
> +select * from t1 where abc =15 or abc <4 ;
> +abc
> +1
> +2
> +3
> +15
> +drop table t1;
> +create table t1(abc blob unique, xyz int );
> +insert into t1 values(1,1),(2,1),(3,3),(4,1),(5,6),(NULL,3),(NULL,1),
> +(NULL,NULL),(11,11),(12,11),(31,31),
> +(14,1),(15,61),(NULL,32),(NULL,12),(NULL,NULL);
> +insert into t1 value(1,NULL);
> +ERROR 23000: Duplicate entry '1' for key 'abc'
> +explain select * from t1 where abc=15;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      const   abc     abc     9       const   1
> +select * from t1 where abc= 15;
> +abc    xyz
> +15     61
> +explain select * from t1 where abc=15 and xyz =61;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      const   abc     abc     9       const   1
> +select * from t1 where abc= 15 and 61;
>
> type in the where clause
>
> Changed.
>
> +abc    xyz
> +15     61
> +# now xyz has different value
>
> what do you mean by that?
>
> echo # now xyz has a value which is not present in table;
> Added.
>
> +explain select * from t1 where abc=1000;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  NULL    NULL    NULL    NULL    NULL    NULL    NULL
> Impossible WHERE noticed after reading const tables
> +select * from t1 where abc= 1000;
> +abc    xyz
> +explain select * from t1 where abc=14 and xyz =56;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  NULL    NULL    NULL    NULL    NULL    NULL    NULL
> Impossible WHERE noticed after reading const tables
> +select * from t1 where abc=14 and xyz =56;
> +abc    xyz
> +#range query
> +explain select * from t1 where abc >5 limit 1;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      ALL     NULL    NULL    NULL    NULL    16
> Using where
> +select * from t1 where abc >5 limit 1;
> +abc    xyz
> +11     11
> +explain select * from t1 where abc=5 and xyz <56;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      const   abc     abc     9       const   1
> +select * from t1 where abc=5 and xyz <56;
> +abc    xyz
> +5      6
> +explain select * from t1 where abc>=5 and xyz <56;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      ALL     NULL    NULL    NULL    NULL    16
> Using where
> +select * from t1 where abc>=5 and xyz <56;
> +abc    xyz
> +5      6
> +11     11
> +12     11
> +31     31
> +14     1
> +explain select * from t1 where abc>5 and xyz =56;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      ALL     NULL    NULL    NULL    NULL    16
> Using where
> +select * from t1 where abc>5 and xyz =56;
> +abc    xyz
> +drop table t1;
> +create table t1(abc blob unique, xyz blob unique );
> +insert into t1
> values(1,1),(2,11),(3,31),(4,12),(5,63),(NULL,2),(NULL,NULL),
> +(91,19),(92,119),(93,391),(94,192),(95,693);
> +insert into t1 value(1,NULL);
> +ERROR 23000: Duplicate entry '1' for key 'abc'
> +explain select * from t1 where abc=1;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      const   abc     abc     9       const   1
> +select * from t1 where abc=1;
> +abc    xyz
> +1      1
> +explain select * from t1 where xyz=1;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      const   xyz     xyz     9       const   1
> +select * from t1 where xyz=1;
> +abc    xyz
> +1      1
> +explain select * from t1 where abc=5 and xyz=63;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      const   abc     abc     9       const   1
> +select * from t1 where abc=5 and xyz=63;
> +abc    xyz
> +5      63
> +explain select * from t1 where xyz=63 and abc=5;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      const   abc     abc     9       const   1
> +select * from t1 where xyz=63 and abc=5;
> +abc    xyz
> +5      63
> +explain select * from t1 where xyz=63 or abc=5;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      ALL     NULL    NULL    NULL    NULL    12
> Using where
> +select * from t1 where xyz=63 or abc=5;
> +abc    xyz
> +5      63
> +# now the first one does not exist
> +explain select * from t1 where abc=51 and xyz=63;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  NULL    NULL    NULL    NULL    NULL    NULL    NULL
> Impossible WHERE noticed after reading const tables
> +select * from t1 where abc=51 and xyz=63;
> +abc    xyz
> +# now the second one does not exist
> +explain select * from t1 where abc=5 and xyz=613;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  NULL    NULL    NULL    NULL    NULL    NULL    NULL
> Impossible WHERE noticed after reading const tables
> +select * from t1 where abc=5 and xyz=613;
> +abc    xyz
> +explain select * from t1 where abc is NULL;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      ALL     NULL    NULL    NULL    NULL    12
> Using where
> +select * from t1 where abc is NULL;
> +abc    xyz
> +NULL   2
> +NULL   NULL
> +explain select * from t1 where abc is NULL and xyz=2;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      const   xyz     xyz     9       const   1
> +select * from t1 where abc is NULL and xyz=2;
> +abc    xyz
> +NULL   2
> +#range conditions
> +explain select * from t1 where abc>11 limit 5;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      ALL     NULL    NULL    NULL    NULL    12
> Using where
> +select * from t1 where abc>11 limit 5;
> +abc    xyz
> +91     19
> +92     119
> +93     391
> +94     192
> +95     693
> +explain select * from t1 where xyz<11;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      ALL     NULL    NULL    NULL    NULL    12
> Using where
> +select * from t1 where xyz<11;
> +abc    xyz
> +1      1
> +NULL   2
> +explain select * from t1 where abc>=51 and xyz<=63;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      ALL     NULL    NULL    NULL    NULL    12
> Using where
> +select * from t1 where abc>=51 and xyz<=63;
> +abc    xyz
> +91     19
> +explain select * from t1 where abc>5 and xyz<613;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      ALL     NULL    NULL    NULL    NULL    12
> Using where
> +select * from t1 where abc>5 and xyz<613;
> +abc    xyz
> +91     19
> +92     119
> +93     391
> +94     192
> +explain select * from t1 where abc=5 and xyz>1;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      const   abc     abc     9       const   1
> +select * from t1 where abc=5 and xyz>1;
> +abc    xyz
> +5      63
> +explain select * from t1 where abc<55 and xyz=1;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      const   xyz     xyz     9       const   1
> +select * from t1 where abc<55 and xyz=1;
> +abc    xyz
> +1      1
> +explain select * from t1 where abc<=55 or xyz>=1;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      ALL     NULL    NULL    NULL    NULL    12
> Using where
> +select * from t1 where abc<=55 and xyz>=1;
> +abc    xyz
> +1      1
> +2      11
> +3      31
> +4      12
> +5      63
> +drop table t1;
> +#now the unique (a,b,c..........)
> +#let us do more hard test by using unique(a,b,c,d) key first
> +create table t1 (a blob , b blob , c blob , d blob ,unique(a,b,c,d),
> +unique(a,b,c) ,unique (b,c,d));
>
> hmm, better do not use redundant keys. it works now, but tenchnically
> we can implement the optimization where the server will internally
> remove "unique(a,b,c,d)" - will store it in the frm, but won't tell
> the engine about it - because unique(a,b,c) guarantees that (a,b,c,d)
> is *always* unique.
>
> so, if we add this optimization someday your test case will no longer test
> what it was supposed to.
>
> Okay , Changed.
>
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `a` blob DEFAULT NULL,
> +  `b` blob DEFAULT NULL,
> +  `c` blob DEFAULT NULL,
> +  `d` blob DEFAULT NULL,
> +  UNIQUE KEY `a_b_c_d`(`a`,`b`,`c`,`d`),
> +  UNIQUE KEY `a_b_c`(`a`,`b`,`c`),
> +  UNIQUE KEY `b_c_d`(`b`,`c`,`d`)
> +) ENGINE=MyISAM DEFAULT CHARSET=latin1
> +insert into t1 values(1,1,1,1),(2,1,2,1),(1,3,3,1),(4,1,4,1),(1,5,1,5),
> +(6,1,6,1),(1,7,1,7),(8,1,1,8),(1,9,9,1),(2,2,2,2),(4,4,4,4),(5,5,5,5),(6,6,6,6),
> +(126,216,603,640),(603,460,660,706),(806,609,609,605),(62,62,22,33),(64,65,66,76),
> +(16,26,63,64),(63,46,66,76),(86,69,69,65),(622,622,622,633),(644,655,666,776);
> +select * from t1 limit 3;
> +a      b       c       d
> +1      1       1       1
> +2      1       2       1
> +1      3       3       1
> +#simple where
> +#key (a,b,c)
> +explain  select * from t1 where a=1 and b=1 and c=1;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      const   a_b_c   a_b_c   9       const   1
> +select * from t1 where a=1 and b=1 and c=1;
> +a      b       c       d
> +1      1       1       1
> +explain  select * from t1 where a=1 and b=4444 and c=1;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  NULL    NULL    NULL    NULL    NULL    NULL    NULL
> Impossible WHERE noticed after reading const tables
> +select * from t1 where a=1 and b=4444 and c=1;
> +a      b       c       d
> +#incomplete key
> +explain  select * from t1 where a=1 and c=1;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      ALL     NULL    NULL    NULL    NULL    23
> Using where
> +select * from t1 where a=1 and c=1;
> +a      b       c       d
> +1      1       1       1
> +1      5       1       5
> +1      7       1       7
> +explain  select * from t1 where a=1 and b=4444 ;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      ALL     NULL    NULL    NULL    NULL    23
> Using where
> +select * from t1 where a=1 and b=4444 ;
> +a      b       c       d
> +explain  select * from t1 where b=1 and c=1;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      ALL     NULL    NULL    NULL    NULL    23
> Using where
> +select * from t1 where b=1 and c=1;
> +a      b       c       d
> +1      1       1       1
> +8      1       1       8
> +#key (b,c,d)
> +explain  select * from t1 where d=1 and b=1 and c=1;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      const   b_c_d   b_c_d   9       const   1
> +select * from t1 where d=1 and b=1 and c=1;
> +a      b       c       d
> +1      1       1       1
> +explain  select * from t1 where d=1 and b=4444 and c=1;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  NULL    NULL    NULL    NULL    NULL    NULL    NULL
> Impossible WHERE noticed after reading const tables
> +select * from t1 where d=1 and b=4444 and c=1;
> +a      b       c       d
> +#incomplete key
> +explain  select * from t1 where d=1 and c=1;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      ALL     NULL    NULL    NULL    NULL    23
> Using where
> +select * from t1 where d=1 and c=1;
> +a      b       c       d
> +1      1       1       1
> +explain  select * from t1 where d=1 and b=4444 ;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      ALL     NULL    NULL    NULL    NULL    23
> Using where
> +select * from t1 where d=1 and b=4444 ;
> +a      b       c       d
> +explain  select * from t1 where b=1 and c=1;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      ALL     NULL    NULL    NULL    NULL    23
> Using where
> +select * from t1 where b=1 and c=1;
> +a      b       c       d
> +1      1       1       1
> +8      1       1       8
> +#key (a,b,c,d)
> +explain  select * from t1 where a=1 and d=1 and b=1 and c=1;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      const   a_b_c_d a_b_c_d 9       const   1
> +select * from t1 where a=1 and d=1 and b=1 and c=1;
> +a      b       c       d
> +1      1       1       1
> +explain  select * from t1 where a=1 and d=1 and b=4444 and c=1;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  NULL    NULL    NULL    NULL    NULL    NULL    NULL
> Impossible WHERE noticed after reading const tables
> +select * from t1 where a=1 and d=1 and b=4444 and c=1;
> +a      b       c       d
> +#incomplete key
> +explain  select * from t1 where a=1 and d=1 and c=1 ;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      ALL     NULL    NULL    NULL    NULL    23
> Using where
> +select * from t1 where a=1 and d=1 and c=1 ;
> +a      b       c       d
> +1      1       1       1
> +explain  select * from t1 where d=1 and b=4444 and a=1 ;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      ALL     NULL    NULL    NULL    NULL    23
> Using where
> +select * from t1 where d=1 and b=4444 and a=1 ;
> +a      b       c       d
> +explain  select * from t1 where a=1 and c=1;
> +id     select_type     table   type    possible_keys   key     key_len ref
> rows    Extra
> +1      SIMPLE  t1      ALL     NULL    NULL    NULL    NULL    23
> Using where
> +select * from t1 where a=1 and c=1;
> +a      b       c       d
> +1      1       1       1
> +1      5       1       5
> +1      7       1       7
> +drop table t1;
> diff --git a/mysql-test/r/long_uniques.result
> b/mysql-test/r/long_uniques.result
> new file mode 100644
> index 0000000..e410fc1
> --- /dev/null
> +++ b/mysql-test/r/long_uniques.result
> @@ -0,0 +1,1163 @@
> +#Structure of tests
> +#First we will check all option for
> +#table containing single unique column
> +#table containing keys like unique(a,b,c,d) etc
> +#then table containing 2 blob unique etc
> +#table with single long blob column;
> +create table t1(a blob unique);
> +insert into t1
> values(1),(2),(3),(56),('sachin'),('maria'),(123456789034567891),(null),(null),(123456789034567890);
> +#table structure;
> +desc t1;
> +Field  Type    Null    Key     Default Extra
> +a      blob    YES     UNI     NULL
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `a` blob DEFAULT NULL,
> +  UNIQUE KEY `a`(`a`)
> +) ENGINE=MyISAM DEFAULT CHARSET=latin1
> +show keys from t1;
>
> for these statements, use "query_vertical" prefix, like
>
>  query_vertical show keys from t1;
>
> it works better when the result has only few (best: one) row
>
> Added.
>
> +Table  Non_unique      Key_name        Seq_in_index    Column_name
> Collation       Cardinality     Sub_part        Packed  Null    Index_type
> Comment Index_comment
> +t1     1       a       1       a       A       0       NULL    NULL    YES
> HASH_INDEX
>
> here, notice that your index is shown as "non-unique"
>
> Corrected.
>
> +select * from information_schema.columns where table_schema = 'test' and
> table_name = 't1';
> +TABLE_CATALOG  TABLE_SCHEMA    TABLE_NAME      COLUMN_NAME
> ORDINAL_POSITION        COLUMN_DEFAULT  IS_NULLABLE     DATA_TYPE
> CHARACTER_MAXIMUM_LENGTH        CHARACTER_OCTET_LENGTH  NUMERIC_PRECISION
> NUMERIC_SCALE   DATETIME_PRECISION      CHARACTER_SET_NAME
> COLLATION_NAME  COLUMN_TYPE     COLUMN_KEY      EXTRA   PRIVILEGES
> COLUMN_COMMENT
> +def    test    t1      a       1       NULL    YES     blob    65535
> 65535   NULL    NULL    NULL    NULL    NULL    blob    UNI
> select,insert,update,references
> +select * from information_schema.statistics where table_schema = 'test' and
> table_name = 't1';
> +TABLE_CATALOG  TABLE_SCHEMA    TABLE_NAME      NON_UNIQUE      INDEX_SCHEMA
> INDEX_NAME      SEQ_IN_INDEX    COLUMN_NAME     COLLATION       CARDINALITY
> SUB_PART        PACKED  NULLABLE        INDEX_TYPE      COMMENT
> INDEX_COMMENT
> +def    test    t1      1       test    a       1       a       A       0
> NULL    NULL    YES     HASH_INDEX
> +select * from information_schema.key_column_usage where table_schema=
> 'test' and table_name= 't1';
> +CONSTRAINT_CATALOG     CONSTRAINT_SCHEMA       CONSTRAINT_NAME
> TABLE_CATALOG   TABLE_SCHEMA    TABLE_NAME      COLUMN_NAME
> ORDINAL_POSITION        POSITION_IN_UNIQUE_CONSTRAINT
> REFERENCED_TABLE_SCHEMA REFERENCED_TABLE_NAME   REFERENCED_COLUMN_NAME
> +def    test    a       def     test    t1      a       1       NULL    NULL
> NULL    NULL
> +# table select we should not be able to see db_row_hash_column;
>
> "not able to see db_row_hash_1 column"
>
> Changed, Sorry.
>
> +select * from t1;
> +a
> +1
> +2
> +3
> +56
> +sachin
> +maria
> +123456789034567891
> +NULL
> +NULL
> +123456789034567890
> +select db_row_hash_1 from t1;
> +ERROR 42S22: Unknown column 'db_row_hash_1' in 'field list'
> +#duplicate entry test;
> +insert into t1 values(2);
> +ERROR 23000: Duplicate entry '2' for key 'a'
> +insert into t1 values('sachin');
> +ERROR 23000: Duplicate entry 'sachi' for key 'a'
> +insert into t1 values(123456789034567891);
> +ERROR 23000: Duplicate entry '12345' for key 'a'
> +select * from t1;
> +a
> +1
> +2
> +3
> +56
> +sachin
> +maria
> +123456789034567891
> +NULL
> +NULL
> +123456789034567890
> +insert into t1 values(11),(22),(33);
> +insert into t1 values(12),(22);
> +ERROR 23000: Duplicate entry '22' for key 'a'
> +select * from t1;
> +a
> +1
> +2
> +3
> +56
> +sachin
> +maria
> +123456789034567891
> +NULL
> +NULL
> +123456789034567890
> +11
> +22
> +33
> +12
> +insert into t1 values(repeat('s',4000*10)),(repeat('s',4001*10));
> +insert into t1 values(repeat('m',4000*10)),(repeat('m',4000*10));
> +ERROR 23000: Duplicate entry 'mmmmm' for key 'a'
> +insert into t1 values(repeat('m',4001)),(repeat('m',4002));
> +truncate table t1;
> +insert into t1 values(1),(2),(3),(4),(5),(8),(7);
> +#now some alter commands;
> +alter table t1 add column b int;
> +desc t1;
> +Field  Type    Null    Key     Default Extra
> +a      blob    YES     UNI     NULL
> +b      int(11) YES             NULL
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `a` blob DEFAULT NULL,
> +  `b` int(11) DEFAULT NULL,
> +  UNIQUE KEY `a`(`a`)
> +) ENGINE=MyISAM DEFAULT CHARSET=latin1
> +insert into t1 values(1,2);
> +ERROR 23000: Duplicate entry '1' for key 'a'
> +insert into t1 values(2,2);
> +ERROR 23000: Duplicate entry '2' for key 'a'
> +select db_row_hash_1 from t1;
> +ERROR 42S22: Unknown column 'db_row_hash_1' in 'field list'
> +#now try to change db_row_hash_1 column;
> +alter table t1 drop column db_row_hash_1;
> +ERROR 42000: Can't DROP COLUMN `db_row_hash_1`; check that it exists
> +alter table t1 add column d int , add column e int , drop column
> db_row_hash_1;
> +ERROR 42000: Can't DROP COLUMN `db_row_hash_1`; check that it exists
> +alter table t1 modify column db_row_hash_1 int ;
> +ERROR 42S22: Unknown column 'db_row_hash_1' in 't1'
> +alter table t1 add column a int , add column b int, modify column
> db_row_hash_1 int ;
> +ERROR 42S22: Unknown column 'db_row_hash_1' in 't1'
> +alter table t1 change column db_row_hash_1 dsds int;
> +ERROR 42S22: Unknown column 'db_row_hash_1' in 't1'
> +alter table t1 add column asd int, change column db_row_hash_1 dsds int;
> +ERROR 42S22: Unknown column 'db_row_hash_1' in 't1'
> +alter table t1 drop column b , add column c int;
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `a` blob DEFAULT NULL,
> +  `c` int(11) DEFAULT NULL,
> +  UNIQUE KEY `a`(`a`)
> +) ENGINE=MyISAM DEFAULT CHARSET=latin1
> +#now add some column with name db_row_hash;
> +alter table t1 add column db_row_hash_1 int unique;
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `a` blob DEFAULT NULL,
> +  `c` int(11) DEFAULT NULL,
> +  `db_row_hash_1` int(11) DEFAULT NULL,
> +  UNIQUE KEY `db_row_hash_1` (`db_row_hash_1`),
> +  UNIQUE KEY `a`(`a`)
> +) ENGINE=MyISAM DEFAULT CHARSET=latin1
> +insert into t1 values(45,1,55),(46,1,55);
> +ERROR 23000: Duplicate entry '55' for key 'db_row_hash_1'
> +alter table t1 add column db_row_hash_2 int, add column db_row_hash_3 int;
> +desc t1;
> +Field  Type    Null    Key     Default Extra
> +a      blob    YES     UNI     NULL
> +c      int(11) YES             NULL
> +db_row_hash_1  int(11) YES     UNI     NULL
> +db_row_hash_2  int(11) YES             NULL
> +db_row_hash_3  int(11) YES             NULL
> +#this should also drop the unique index ;
> +alter table t1 drop column a;
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `c` int(11) DEFAULT NULL,
> +  `db_row_hash_1` int(11) DEFAULT NULL,
> +  `db_row_hash_2` int(11) DEFAULT NULL,
> +  `db_row_hash_3` int(11) DEFAULT NULL,
> +  UNIQUE KEY `db_row_hash_1` (`db_row_hash_1`)
> +) ENGINE=MyISAM DEFAULT CHARSET=latin1
> +show keys from t1;
> +Table  Non_unique      Key_name        Seq_in_index    Column_name
> Collation       Cardinality     Sub_part        Packed  Null    Index_type
> Comment Index_comment
> +t1     0       db_row_hash_1   1       db_row_hash_1   A       NULL    NULL
> NULL    YES     BTREE
> +#add column with unique index on blob ;
> +alter table t1 add column a blob unique;
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `c` int(11) DEFAULT NULL,
> +  `db_row_hash_1` int(11) DEFAULT NULL,
> +  `db_row_hash_2` int(11) DEFAULT NULL,
> +  `db_row_hash_3` int(11) DEFAULT NULL,
> +  `a` blob DEFAULT NULL,
> +  UNIQUE KEY `db_row_hash_1` (`db_row_hash_1`),
> +  UNIQUE KEY `a`(`a`)
> +) ENGINE=MyISAM DEFAULT CHARSET=latin1
> +# try to change the blob unique column name;
> +#this will change index to b tree;
> +alter table t1 modify  column a  int ;
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `c` int(11) DEFAULT NULL,
> +  `db_row_hash_1` int(11) DEFAULT NULL,
> +  `db_row_hash_2` int(11) DEFAULT NULL,
> +  `db_row_hash_3` int(11) DEFAULT NULL,
> +  `a` int(11) DEFAULT NULL,
> +  UNIQUE KEY `db_row_hash_1` (`db_row_hash_1`),
> +  UNIQUE KEY `a` (`a`)
> +) ENGINE=MyISAM DEFAULT CHARSET=latin1
> +show keys from t1;
> +Table  Non_unique      Key_name        Seq_in_index    Column_name
> Collation       Cardinality     Sub_part        Packed  Null    Index_type
> Comment Index_comment
> +t1     0       db_row_hash_1   1       db_row_hash_1   A       NULL    NULL
> NULL    YES     BTREE
> +t1     0       a       1       a       A       NULL    NULL    NULL    YES
> BTREE
> +alter table t1 add column clm blob unique;
> +#try changing the name ;
> +alter table t1 change column clm clm_changed blob;
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `c` int(11) DEFAULT NULL,
> +  `db_row_hash_1` int(11) DEFAULT NULL,
> +  `db_row_hash_2` int(11) DEFAULT NULL,
> +  `db_row_hash_3` int(11) DEFAULT NULL,
> +  `a` int(11) DEFAULT NULL,
> +  `clm_changed` blob DEFAULT NULL,
> +  UNIQUE KEY `db_row_hash_1` (`db_row_hash_1`),
> +  UNIQUE KEY `a` (`a`),
> +  UNIQUE KEY `clm`(`clm_changed`)
> +) ENGINE=MyISAM DEFAULT CHARSET=latin1
> +show keys from t1;
> +Table  Non_unique      Key_name        Seq_in_index    Column_name
> Collation       Cardinality     Sub_part        Packed  Null    Index_type
> Comment Index_comment
> +t1     0       db_row_hash_1   1       db_row_hash_1   A       NULL    NULL
> NULL    YES     BTREE
> +t1     0       a       1       a       A       NULL    NULL    NULL    YES
> BTREE
> +t1     1       clm     1       clm_changed     A       0       NULL    NULL
> YES     HASH_INDEX
> +#now drop the unique key;
> +alter table t1 drop key clm;
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `c` int(11) DEFAULT NULL,
> +  `db_row_hash_1` int(11) DEFAULT NULL,
> +  `db_row_hash_2` int(11) DEFAULT NULL,
> +  `db_row_hash_3` int(11) DEFAULT NULL,
> +  `a` int(11) DEFAULT NULL,
> +  `clm_changed` blob DEFAULT NULL,
> +  UNIQUE KEY `db_row_hash_1` (`db_row_hash_1`),
> +  UNIQUE KEY `a` (`a`)
> +) ENGINE=MyISAM DEFAULT CHARSET=latin1
> +show keys from t1;
> +Table  Non_unique      Key_name        Seq_in_index    Column_name
> Collation       Cardinality     Sub_part        Packed  Null    Index_type
> Comment Index_comment
> +t1     0       db_row_hash_1   1       db_row_hash_1   A       NULL    NULL
> NULL    YES     BTREE
> +t1     0       a       1       a       A       NULL    NULL    NULL    YES
> BTREE
>
> you can use myisamchk to see *actually created* indexes in MYI file.
> examples are in myisam.test, but in short, it's something like
>
>  let datadir=`select @@datadir`;
>  replace_result $datadir DATADIR;
>  exec $MYISAMCHK -d $datadir/test/t1
>
> the first command needs to be done only once, in the beginning of the file,
> usually. The other pair you do whenever you want to examine the table,
> like, where you do "desc t1" or "show keys".
>
> Done.
>
> +drop table t1;
> +create table t1 (a TEXT CHARSET latin1 COLLATE latin1_german2_ci unique);
> +desc t1;
> +Field  Type    Null    Key     Default Extra
> +a      text    YES     UNI     NULL
> +show keys from t1;
> +Table  Non_unique      Key_name        Seq_in_index    Column_name
> Collation       Cardinality     Sub_part        Packed  Null    Index_type
> Comment Index_comment
> +t1     1       a       1       a       A       0       NULL    NULL    YES
> HASH_INDEX
> +insert into t1 values ('ae');
> +insert into t1 values ('AE');
> +ERROR 23000: Duplicate entry 'AE' for key 'a'
> +insert  into t1 values ('Ä');
>
> good!
>
> +drop table t1;
> +#table with multiple  long blob column and varchar text column ;
> +create table t1(a blob unique, b int , c blob unique , d text unique , e
> varchar(3000) unique);
> +insert into t1
> values(1,2,3,4,5),(2,11,22,33,44),(3111,222,333,444,555),(5611,2222,3333,4444,5555),
> +('sachin','ff','fdf','gfgfgfg','hghgr'),('maria','db','frter','dasd','utyuty'),
> +(123456789034567891,3534534534534,53453453453456,64565464564564,45435345345345),
> +(123456789034567890,435345345345,657567567567,78967657567567,657567567567567676);
> +Warnings:
> +Warning        1366    Incorrect integer value: 'ff' for column 'b' at row
> 5
> +Warning        1366    Incorrect integer value: 'db' for column 'b' at row
> 6
> +Warning        1264    Out of range value for column 'b' at row 7
> +Warning        1264    Out of range value for column 'b' at row 8
>
> did you really need to insert invalid values in this test?
>
> No, I did not see Warning.
>
> +#table structure;
> +desc t1;
> +Field  Type    Null    Key     Default Extra
> +a      blob    YES     UNI     NULL
> +b      int(11) YES             NULL
> +c      blob    YES     UNI     NULL
> +d      text    YES     UNI     NULL
> +e      varchar(3000)   YES     UNI     NULL
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `a` blob DEFAULT NULL,
> +  `b` int(11) DEFAULT NULL,
> +  `c` blob DEFAULT NULL,
> +  `d` text DEFAULT NULL,
> +  `e` varchar(3000) DEFAULT NULL,
> +  UNIQUE KEY `a`(`a`),
> +  UNIQUE KEY `c`(`c`),
> +  UNIQUE KEY `d`(`d`),
> +  UNIQUE KEY `e`(`e`)
> +) ENGINE=MyISAM DEFAULT CHARSET=latin1
> +show keys from t1;
> +Table  Non_unique      Key_name        Seq_in_index    Column_name
> Collation       Cardinality     Sub_part        Packed  Null    Index_type
> Comment Index_comment
> +t1     1       a       1       a       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       c       1       c       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       d       1       d       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       e       1       e       A       0       NULL    NULL    YES
> HASH_INDEX
> +select * from information_schema.columns where table_schema = 'test' and
> table_name = 't1';
> +TABLE_CATALOG  TABLE_SCHEMA    TABLE_NAME      COLUMN_NAME
> ORDINAL_POSITION        COLUMN_DEFAULT  IS_NULLABLE     DATA_TYPE
> CHARACTER_MAXIMUM_LENGTH        CHARACTER_OCTET_LENGTH  NUMERIC_PRECISION
> NUMERIC_SCALE   DATETIME_PRECISION      CHARACTER_SET_NAME
> COLLATION_NAME  COLUMN_TYPE     COLUMN_KEY      EXTRA   PRIVILEGES
> COLUMN_COMMENT
> +def    test    t1      a       1       NULL    YES     blob    65535
> 65535   NULL    NULL    NULL    NULL    NULL    blob    UNI
> select,insert,update,references
> +def    test    t1      b       2       NULL    YES     int     NULL    NULL
> 10      0       NULL    NULL    NULL    int(11)
> select,insert,update,references
> +def    test    t1      c       3       NULL    YES     blob    65535
> 65535   NULL    NULL    NULL    NULL    NULL    blob    UNI
> select,insert,update,references
> +def    test    t1      d       4       NULL    YES     text    65535
> 65535   NULL    NULL    NULL    latin1  latin1_swedish_ci       text    UNI
> select,insert,update,references
> +def    test    t1      e       5       NULL    YES     varchar 3000    3000
> NULL    NULL    NULL    latin1  latin1_swedish_ci       varchar(3000)   UNI
> select,insert,update,references
> +select * from information_schema.statistics where table_schema = 'test' and
> table_name = 't1';
> +TABLE_CATALOG  TABLE_SCHEMA    TABLE_NAME      NON_UNIQUE      INDEX_SCHEMA
> INDEX_NAME      SEQ_IN_INDEX    COLUMN_NAME     COLLATION       CARDINALITY
> SUB_PART        PACKED  NULLABLE        INDEX_TYPE      COMMENT
> INDEX_COMMENT
> +def    test    t1      1       test    a       1       a       A       0
> NULL    NULL    YES     HASH_INDEX
> +def    test    t1      1       test    c       1       c       A       0
> NULL    NULL    YES     HASH_INDEX
> +def    test    t1      1       test    d       1       d       A       0
> NULL    NULL    YES     HASH_INDEX
> +def    test    t1      1       test    e       1       e       A       0
> NULL    NULL    YES     HASH_INDEX
> +select * from information_schema.key_column_usage where table_schema=
> 'test' and table_name= 't1';
> +CONSTRAINT_CATALOG     CONSTRAINT_SCHEMA       CONSTRAINT_NAME
> TABLE_CATALOG   TABLE_SCHEMA    TABLE_NAME      COLUMN_NAME
> ORDINAL_POSITION        POSITION_IN_UNIQUE_CONSTRAINT
> REFERENCED_TABLE_SCHEMA REFERENCED_TABLE_NAME   REFERENCED_COLUMN_NAME
> +def    test    a       def     test    t1      a       1       NULL    NULL
> NULL    NULL
> +def    test    c       def     test    t1      c       1       NULL    NULL
> NULL    NULL
> +def    test    d       def     test    t1      d       1       NULL    NULL
> NULL    NULL
> +def    test    e       def     test    t1      e       1       NULL    NULL
> NULL    NULL
> +#table select we should not be able to see db_row_hash_column;
> +select * from t1;
> +a      b       c       d       e
> +1      2       3       4       5
> +2      11      22      33      44
> +3111   222     333     444     555
> +5611   2222    3333    4444    5555
> +sachin 0       fdf     gfgfgfg hghgr
> +maria  0       frter   dasd    utyuty
> +123456789034567891     2147483647      53453453453456  64565464564564
> 45435345345345
> +123456789034567890     2147483647      657567567567    78967657567567
> 657567567567567676
> +select db_row_hash_1 from t1;
> +ERROR 42S22: Unknown column 'db_row_hash_1' in 'field list'
> +select db_row_hash_2 from t1;
> +ERROR 42S22: Unknown column 'db_row_hash_2' in 'field list'
> +select db_row_hash_3 from t1;
> +ERROR 42S22: Unknown column 'db_row_hash_3' in 'field list'
> +#duplicate entry test;
> +insert into t1 values(21,2,3,42,51);
> +ERROR 23000: Duplicate entry '3' for key 'c'
> +insert into t1 values('sachin',null,null,null,null);
> +ERROR 23000: Duplicate entry 'sachi' for key 'a'
> +insert into t1
> values(1234567890345671890,4353453453451,6575675675617,789676575675617,657567567567567676);
> +ERROR 23000: Duplicate entry '65756' for key 'e'
> +select * from t1;
> +a      b       c       d       e
> +1      2       3       4       5
> +2      11      22      33      44
> +3111   222     333     444     555
> +5611   2222    3333    4444    5555
> +sachin 0       fdf     gfgfgfg hghgr
> +maria  0       frter   dasd    utyuty
> +123456789034567891     2147483647      53453453453456  64565464564564
> 45435345345345
> +123456789034567890     2147483647      657567567567    78967657567567
> 657567567567567676
> +insert into t1
> values(repeat('s',4000*10),100,repeat('s',4000*10),repeat('s',4000*10),
> +repeat('s',400)),(repeat('s',4001*10),1000,repeat('s',4001*10),repeat('s',4001*10),
> +repeat('s',401));
> +insert into t1
> values(repeat('m',4000*11),10,repeat('s',4000*11),repeat('s',4000*11),repeat('s',400));
> +ERROR 23000: Duplicate entry 'sssss' for key 'e'
>
> 400 characters (that you insert into 'e') - that looks a bit too short for
> varchar(3000). Why wouldn't you insert, say, 2990 characters?
> 400 is something that even b-tree can handle, I suspect.
>
> Changed.
>
> +truncate table t1;
> +insert into t1
> values(1,2,3,4,5),(2,11,22,33,44),(3111,222,333,444,555),(5611,2222,3333,4444,5555);
> +#now some alter commands;
> +alter table t1 add column f int;
> +desc t1;
> +Field  Type    Null    Key     Default Extra
> +a      blob    YES     UNI     NULL
> +b      int(11) YES             NULL
> +c      blob    YES     UNI     NULL
> +d      text    YES     UNI     NULL
> +e      varchar(3000)   YES     UNI     NULL
> +f      int(11) YES             NULL
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `a` blob DEFAULT NULL,
> +  `b` int(11) DEFAULT NULL,
> +  `c` blob DEFAULT NULL,
> +  `d` text DEFAULT NULL,
> +  `e` varchar(3000) DEFAULT NULL,
> +  `f` int(11) DEFAULT NULL,
> +  UNIQUE KEY `a`(`a`),
> +  UNIQUE KEY `c`(`c`),
> +  UNIQUE KEY `d`(`d`),
> +  UNIQUE KEY `e`(`e`)
> +) ENGINE=MyISAM DEFAULT CHARSET=latin1
> +#unique key should not break;
> +insert into t1 values(1,2,3,4,5,6);
> +ERROR 23000: Duplicate entry '1' for key 'a'
> +select db_row_hash_1 , db_row_hash_2, db_row_hash_3 from t1;
> +ERROR 42S22: Unknown column 'db_row_hash_1' in 'field list'
> +#now try to change db_row_hash_1 column;
> +alter table t1 drop column db_row_hash_1, drop column db_row_hash_2, drop
> column db_row_hash_3;
> +ERROR 42000: Can't DROP COLUMN `db_row_hash_1`; check that it exists
> +alter table t1 add column dg int , add column ef int , drop column
> db_row_hash_1;
> +ERROR 42000: Can't DROP COLUMN `db_row_hash_1`; check that it exists
> +alter table t1 modify column db_row_hash_1 int , modify column
> db_row_hash_2 int, modify column db_row_hash_3 int;
> +ERROR 42S22: Unknown column 'db_row_hash_1' in 't1'
> +alter table t1 add column ar int , add column rb int, modify column
> db_row_hash_1 int , modify column db_row_hash_3 int;
> +ERROR 42S22: Unknown column 'db_row_hash_1' in 't1'
> +alter table t1 change column db_row_hash_1 dsds int , change column
> db_row_hash_2  dfdf int , change column db_row_hash_3 gdfg int ;
> +ERROR 42S22: Unknown column 'db_row_hash_1' in 't1'
> +alter table t1 add column asd int, drop column a, change column
> db_row_hash_1 dsds int, change db_row_hash_3 fdfdfd int;
> +ERROR 42S22: Unknown column 'db_row_hash_1' in 't1'
> +alter table t1 drop column b , add column g int;
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `a` blob DEFAULT NULL,
> +  `c` blob DEFAULT NULL,
> +  `d` text DEFAULT NULL,
> +  `e` varchar(3000) DEFAULT NULL,
> +  `f` int(11) DEFAULT NULL,
> +  `g` int(11) DEFAULT NULL,
> +  UNIQUE KEY `a`(`a`),
> +  UNIQUE KEY `c`(`c`),
> +  UNIQUE KEY `d`(`d`),
> +  UNIQUE KEY `e`(`e`)
> +) ENGINE=MyISAM DEFAULT CHARSET=latin1
> +#now add some column with name db_row_hash;
> +alter table t1 add column db_row_hash_1 int unique;
> +alter table t1 add column db_row_hash_2 int unique;
> +alter table t1 add column db_row_hash_3 int unique;
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `a` blob DEFAULT NULL,
> +  `c` blob DEFAULT NULL,
> +  `d` text DEFAULT NULL,
> +  `e` varchar(3000) DEFAULT NULL,
> +  `f` int(11) DEFAULT NULL,
> +  `g` int(11) DEFAULT NULL,
> +  `db_row_hash_1` int(11) DEFAULT NULL,
> +  `db_row_hash_2` int(11) DEFAULT NULL,
> +  `db_row_hash_3` int(11) DEFAULT NULL,
> +  UNIQUE KEY `db_row_hash_1` (`db_row_hash_1`),
> +  UNIQUE KEY `db_row_hash_2` (`db_row_hash_2`),
> +  UNIQUE KEY `db_row_hash_3` (`db_row_hash_3`),
> +  UNIQUE KEY `a`(`a`),
> +  UNIQUE KEY `c`(`c`),
> +  UNIQUE KEY `d`(`d`),
> +  UNIQUE KEY `e`(`e`)
> +) ENGINE=MyISAM DEFAULT CHARSET=latin1
> +alter table t1 add column db_row_hash_7 int, add column db_row_hash_5 int ,
> add column db_row_hash_4 int ;
> +alter table t1 drop column db_row_hash_7,drop column db_row_hash_3, drop
> column db_row_hash_4;
> +desc t1;
> +Field  Type    Null    Key     Default Extra
> +a      blob    YES     UNI     NULL
> +c      blob    YES     UNI     NULL
> +d      text    YES     UNI     NULL
> +e      varchar(3000)   YES     UNI     NULL
> +f      int(11) YES             NULL
> +g      int(11) YES             NULL
> +db_row_hash_1  int(11) YES     UNI     NULL
> +db_row_hash_2  int(11) YES     UNI     NULL
> +db_row_hash_5  int(11) YES             NULL
> +#this show now break anything;
> +insert into t1 values(1,2,3,4,5,6,23,5,6);
> +ERROR 23000: Duplicate entry '1' for key 'a'
> +#this should also drop the unique index;
> +alter table t1 drop column a, drop column c;
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `d` text DEFAULT NULL,
> +  `e` varchar(3000) DEFAULT NULL,
> +  `f` int(11) DEFAULT NULL,
> +  `g` int(11) DEFAULT NULL,
> +  `db_row_hash_1` int(11) DEFAULT NULL,
> +  `db_row_hash_2` int(11) DEFAULT NULL,
> +  `db_row_hash_5` int(11) DEFAULT NULL,
> +  UNIQUE KEY `db_row_hash_1` (`db_row_hash_1`),
> +  UNIQUE KEY `db_row_hash_2` (`db_row_hash_2`),
> +  UNIQUE KEY `d`(`d`),
> +  UNIQUE KEY `e`(`e`)
> +) ENGINE=MyISAM DEFAULT CHARSET=latin1
> +show keys from t1;
> +Table  Non_unique      Key_name        Seq_in_index    Column_name
> Collation       Cardinality     Sub_part        Packed  Null    Index_type
> Comment Index_comment
> +t1     0       db_row_hash_1   1       db_row_hash_1   A       NULL    NULL
> NULL    YES     BTREE
> +t1     0       db_row_hash_2   1       db_row_hash_2   A       NULL    NULL
> NULL    YES     BTREE
> +t1     1       d       1       d       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       e       1       e       A       0       NULL    NULL    YES
> HASH_INDEX
> +#add column with unique index on blob;
> +alter table t1 add column a blob unique;
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `d` text DEFAULT NULL,
> +  `e` varchar(3000) DEFAULT NULL,
> +  `f` int(11) DEFAULT NULL,
> +  `g` int(11) DEFAULT NULL,
> +  `db_row_hash_1` int(11) DEFAULT NULL,
> +  `db_row_hash_2` int(11) DEFAULT NULL,
> +  `db_row_hash_5` int(11) DEFAULT NULL,
> +  `a` blob DEFAULT NULL,
> +  UNIQUE KEY `db_row_hash_1` (`db_row_hash_1`),
> +  UNIQUE KEY `db_row_hash_2` (`db_row_hash_2`),
> +  UNIQUE KEY `d`(`d`),
> +  UNIQUE KEY `e`(`e`),
> +  UNIQUE KEY `a`(`a`)
> +) ENGINE=MyISAM DEFAULT CHARSET=latin1
> +show keys from t1;
> +Table  Non_unique      Key_name        Seq_in_index    Column_name
> Collation       Cardinality     Sub_part        Packed  Null    Index_type
> Comment Index_comment
> +t1     0       db_row_hash_1   1       db_row_hash_1   A       NULL    NULL
> NULL    YES     BTREE
> +t1     0       db_row_hash_2   1       db_row_hash_2   A       NULL    NULL
> NULL    YES     BTREE
> +t1     1       d       1       d       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       e       1       e       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       a       1       a       A       0       NULL    NULL    YES
> HASH_INDEX
> +#try to change the blob unique column name;
> +#this will change index to b tree;
> +alter table t1 modify  column a  int ,  modify column e int;
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `d` text DEFAULT NULL,
> +  `e` int(11) DEFAULT NULL,
> +  `f` int(11) DEFAULT NULL,
> +  `g` int(11) DEFAULT NULL,
> +  `db_row_hash_1` int(11) DEFAULT NULL,
> +  `db_row_hash_2` int(11) DEFAULT NULL,
> +  `db_row_hash_5` int(11) DEFAULT NULL,
> +  `a` int(11) DEFAULT NULL,
> +  UNIQUE KEY `db_row_hash_1` (`db_row_hash_1`),
> +  UNIQUE KEY `db_row_hash_2` (`db_row_hash_2`),
> +  UNIQUE KEY `e` (`e`),
> +  UNIQUE KEY `a` (`a`),
> +  UNIQUE KEY `d`(`d`)
> +) ENGINE=MyISAM DEFAULT CHARSET=latin1
> +show keys from t1;
> +Table  Non_unique      Key_name        Seq_in_index    Column_name
> Collation       Cardinality     Sub_part        Packed  Null    Index_type
> Comment Index_comment
> +t1     0       db_row_hash_1   1       db_row_hash_1   A       NULL    NULL
> NULL    YES     BTREE
> +t1     0       db_row_hash_2   1       db_row_hash_2   A       NULL    NULL
> NULL    YES     BTREE
> +t1     0       e       1       e       A       NULL    NULL    NULL    YES
> BTREE
> +t1     0       a       1       a       A       NULL    NULL    NULL    YES
> BTREE
> +t1     1       d       1       d       A       0       NULL    NULL    YES
> HASH_INDEX
> +alter table t1 add column clm1 blob unique,add column clm2 blob unique;
> +#try changing the name;
> +alter table t1 change column clm1 clm_changed1 blob, change column clm2
> clm_changed2 blob;
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `d` text DEFAULT NULL,
> +  `e` int(11) DEFAULT NULL,
> +  `f` int(11) DEFAULT NULL,
> +  `g` int(11) DEFAULT NULL,
> +  `db_row_hash_1` int(11) DEFAULT NULL,
> +  `db_row_hash_2` int(11) DEFAULT NULL,
> +  `db_row_hash_5` int(11) DEFAULT NULL,
> +  `a` int(11) DEFAULT NULL,
> +  `clm_changed1` blob DEFAULT NULL,
> +  `clm_changed2` blob DEFAULT NULL,
> +  UNIQUE KEY `db_row_hash_1` (`db_row_hash_1`),
> +  UNIQUE KEY `db_row_hash_2` (`db_row_hash_2`),
> +  UNIQUE KEY `e` (`e`),
> +  UNIQUE KEY `a` (`a`),
> +  UNIQUE KEY `d`(`d`),
> +  UNIQUE KEY `clm1`(`clm_changed1`),
> +  UNIQUE KEY `clm2`(`clm_changed2`)
> +) ENGINE=MyISAM DEFAULT CHARSET=latin1
> +show keys from t1;
> +Table  Non_unique      Key_name        Seq_in_index    Column_name
> Collation       Cardinality     Sub_part        Packed  Null    Index_type
> Comment Index_comment
> +t1     0       db_row_hash_1   1       db_row_hash_1   A       NULL    NULL
> NULL    YES     BTREE
> +t1     0       db_row_hash_2   1       db_row_hash_2   A       NULL    NULL
> NULL    YES     BTREE
> +t1     0       e       1       e       A       NULL    NULL    NULL    YES
> BTREE
> +t1     0       a       1       a       A       NULL    NULL    NULL    YES
> BTREE
> +t1     1       d       1       d       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       clm1    1       clm_changed1    A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       clm2    1       clm_changed2    A       0       NULL    NULL
> YES     HASH_INDEX
> +#now drop the unique key;
> +alter table t1 drop key clm1, drop key clm2;
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `d` text DEFAULT NULL,
> +  `e` int(11) DEFAULT NULL,
> +  `f` int(11) DEFAULT NULL,
> +  `g` int(11) DEFAULT NULL,
> +  `db_row_hash_1` int(11) DEFAULT NULL,
> +  `db_row_hash_2` int(11) DEFAULT NULL,
> +  `db_row_hash_5` int(11) DEFAULT NULL,
> +  `a` int(11) DEFAULT NULL,
> +  `clm_changed1` blob DEFAULT NULL,
> +  `clm_changed2` blob DEFAULT NULL,
> +  UNIQUE KEY `db_row_hash_1` (`db_row_hash_1`),
> +  UNIQUE KEY `db_row_hash_2` (`db_row_hash_2`),
> +  UNIQUE KEY `e` (`e`),
> +  UNIQUE KEY `a` (`a`),
> +  UNIQUE KEY `d`(`d`)
> +) ENGINE=MyISAM DEFAULT CHARSET=latin1
> +show keys from t1;
> +Table  Non_unique      Key_name        Seq_in_index    Column_name
> Collation       Cardinality     Sub_part        Packed  Null    Index_type
> Comment Index_comment
> +t1     0       db_row_hash_1   1       db_row_hash_1   A       NULL    NULL
> NULL    YES     BTREE
> +t1     0       db_row_hash_2   1       db_row_hash_2   A       NULL    NULL
> NULL    YES     BTREE
> +t1     0       e       1       e       A       NULL    NULL    NULL    YES
> BTREE
> +t1     0       a       1       a       A       NULL    NULL    NULL    YES
> BTREE
> +t1     1       d       1       d       A       0       NULL    NULL    YES
> HASH_INDEX
>
> test also
>
>   alter table ... add unique key (blob_column)
>
> in three different variants:
> 1. there were no duplicates in blob_column, key added successfully,
> 2. there were duplicates, alter table failed.
> 3. there were duplicates, ALTER IGNORE TABLE... succeeds
>
> Already added in later commit.
>
> +drop table t1;
> +#now the table with key on multiple columns; the ultimate test;
> +create table t1(a blob, b int , c varchar(2000) , d text  , e varchar(3000)
> , f longblob , g int , h text ,
> +unique(a,b,c),
> unique(c,d,e),unique(e,f,g,h),unique(a,b,c,d,e,f),unique(d,e,f,g,h),unique(a,b,c,d,e,f,g,h));
> +insert into t1
> values(1,1,1,1,1,1,1,1),(2,2,2,2,2,2,2,2),(3,3,3,3,3,3,3,3),(4,4,4,4,4,4,4,4),(5,5,5,5,5,5,5,5),
> +('maria',6,'maria','maria','maria','maria',6,'maria'),('mariadb',7,'mariadb','mariadb','mariadb','mariadb',8,'mariadb');
> +#table structure;
> +desc t1;
> +Field  Type    Null    Key     Default Extra
> +a      blob    YES     MUL     NULL
> +b      int(11) YES             NULL
> +c      varchar(2000)   YES     MUL     NULL
> +d      text    YES     MUL     NULL
> +e      varchar(3000)   YES     MUL     NULL
> +f      longblob        YES             NULL
> +g      int(11) YES             NULL
> +h      text    YES             NULL
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `a` blob DEFAULT NULL,
> +  `b` int(11) DEFAULT NULL,
> +  `c` varchar(2000) DEFAULT NULL,
> +  `d` text DEFAULT NULL,
> +  `e` varchar(3000) DEFAULT NULL,
> +  `f` longblob DEFAULT NULL,
> +  `g` int(11) DEFAULT NULL,
> +  `h` text DEFAULT NULL,
> +  UNIQUE KEY `a_b_c`(`a`,`b`,`c`),
> +  UNIQUE KEY `c_d_e`(`c`,`d`,`e`),
> +  UNIQUE KEY `e_f_g_h`(`e`,`f`,`g`,`h`),
> +  UNIQUE KEY `a_b_c_d_e_f`(`a`,`b`,`c`,`d`,`e`,`f`),
> +  UNIQUE KEY `d_e_f_g_h`(`d`,`e`,`f`,`g`,`h`),
> +  UNIQUE KEY `a_b_c_d_e_f_g_h`(`a`,`b`,`c`,`d`,`e`,`f`,`g`,`h`)
> +) ENGINE=MyISAM DEFAULT CHARSET=latin1
> +show keys from t1;
> +Table  Non_unique      Key_name        Seq_in_index    Column_name
> Collation       Cardinality     Sub_part        Packed  Null    Index_type
> Comment Index_comment
> +t1     1       a_b_c   1       a       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       a_b_c   2       b       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       a_b_c   3       c       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       c_d_e   1       c       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       c_d_e   2       d       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       c_d_e   3       e       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       e_f_g_h 1       e       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       e_f_g_h 2       f       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       e_f_g_h 3       g       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       e_f_g_h 4       h       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       a_b_c_d_e_f     1       a       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     2       b       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     3       c       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     4       d       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     5       e       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     6       f       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       1       d       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       2       e       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       3       f       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       4       g       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       5       h       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 1       a       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 2       b       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 3       c       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 4       d       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 5       e       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 6       f       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 7       g       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 8       h       A       0       NULL    NULL
> YES     HASH_INDEX
> +select * from information_schema.columns where table_schema = 'test' and
> table_name = 't1';
> +TABLE_CATALOG  TABLE_SCHEMA    TABLE_NAME      COLUMN_NAME
> ORDINAL_POSITION        COLUMN_DEFAULT  IS_NULLABLE     DATA_TYPE
> CHARACTER_MAXIMUM_LENGTH        CHARACTER_OCTET_LENGTH  NUMERIC_PRECISION
> NUMERIC_SCALE   DATETIME_PRECISION      CHARACTER_SET_NAME
> COLLATION_NAME  COLUMN_TYPE     COLUMN_KEY      EXTRA   PRIVILEGES
> COLUMN_COMMENT
> +def    test    t1      a       1       NULL    YES     blob    65535
> 65535   NULL    NULL    NULL    NULL    NULL    blob    MUL
> select,insert,update,references
> +def    test    t1      b       2       NULL    YES     int     NULL    NULL
> 10      0       NULL    NULL    NULL    int(11)
> select,insert,update,references
> +def    test    t1      c       3       NULL    YES     varchar 2000    2000
> NULL    NULL    NULL    latin1  latin1_swedish_ci       varchar(2000)   MUL
> select,insert,update,references
> +def    test    t1      d       4       NULL    YES     text    65535
> 65535   NULL    NULL    NULL    latin1  latin1_swedish_ci       text    MUL
> select,insert,update,references
> +def    test    t1      e       5       NULL    YES     varchar 3000    3000
> NULL    NULL    NULL    latin1  latin1_swedish_ci       varchar(3000)   MUL
> select,insert,update,references
> +def    test    t1      f       6       NULL    YES     longblob
> 4294967295      4294967295      NULL    NULL    NULL    NULL    NULL
> longblob                        select,insert,update,references
> +def    test    t1      g       7       NULL    YES     int     NULL    NULL
> 10      0       NULL    NULL    NULL    int(11)
> select,insert,update,references
> +def    test    t1      h       8       NULL    YES     text    65535
> 65535   NULL    NULL    NULL    latin1  latin1_swedish_ci       text
> select,insert,update,references
> +select * from information_schema.statistics where table_schema = 'test' and
> table_name = 't1';
> +TABLE_CATALOG  TABLE_SCHEMA    TABLE_NAME      NON_UNIQUE      INDEX_SCHEMA
> INDEX_NAME      SEQ_IN_INDEX    COLUMN_NAME     COLLATION       CARDINALITY
> SUB_PART        PACKED  NULLABLE        INDEX_TYPE      COMMENT
> INDEX_COMMENT
> +def    test    t1      1       test    a_b_c   1       a       A       0
> NULL    NULL    YES     HASH_INDEX
> +def    test    t1      1       test    a_b_c   2       b       A       0
> NULL    NULL    YES     HASH_INDEX
> +def    test    t1      1       test    a_b_c   3       c       A       0
> NULL    NULL    YES     HASH_INDEX
> +def    test    t1      1       test    c_d_e   1       c       A       0
> NULL    NULL    YES     HASH_INDEX
> +def    test    t1      1       test    c_d_e   2       d       A       0
> NULL    NULL    YES     HASH_INDEX
> +def    test    t1      1       test    c_d_e   3       e       A       0
> NULL    NULL    YES     HASH_INDEX
> +def    test    t1      1       test    e_f_g_h 1       e       A       0
> NULL    NULL    YES     HASH_INDEX
> +def    test    t1      1       test    e_f_g_h 2       f       A       0
> NULL    NULL    YES     HASH_INDEX
> +def    test    t1      1       test    e_f_g_h 3       g       A       0
> NULL    NULL    YES     HASH_INDEX
> +def    test    t1      1       test    e_f_g_h 4       h       A       0
> NULL    NULL    YES     HASH_INDEX
> +def    test    t1      1       test    a_b_c_d_e_f     1       a       A
> 0       NULL    NULL    YES     HASH_INDEX
> +def    test    t1      1       test    a_b_c_d_e_f     2       b       A
> 0       NULL    NULL    YES     HASH_INDEX
> +def    test    t1      1       test    a_b_c_d_e_f     3       c       A
> 0       NULL    NULL    YES     HASH_INDEX
> +def    test    t1      1       test    a_b_c_d_e_f     4       d       A
> 0       NULL    NULL    YES     HASH_INDEX
> +def    test    t1      1       test    a_b_c_d_e_f     5       e       A
> 0       NULL    NULL    YES     HASH_INDEX
> +def    test    t1      1       test    a_b_c_d_e_f     6       f       A
> 0       NULL    NULL    YES     HASH_INDEX
> +def    test    t1      1       test    d_e_f_g_h       1       d       A
> 0       NULL    NULL    YES     HASH_INDEX
> +def    test    t1      1       test    d_e_f_g_h       2       e       A
> 0       NULL    NULL    YES     HASH_INDEX
> +def    test    t1      1       test    d_e_f_g_h       3       f       A
> 0       NULL    NULL    YES     HASH_INDEX
> +def    test    t1      1       test    d_e_f_g_h       4       g       A
> 0       NULL    NULL    YES     HASH_INDEX
> +def    test    t1      1       test    d_e_f_g_h       5       h       A
> 0       NULL    NULL    YES     HASH_INDEX
> +def    test    t1      1       test    a_b_c_d_e_f_g_h 1       a       A
> 0       NULL    NULL    YES     HASH_INDEX
> +def    test    t1      1       test    a_b_c_d_e_f_g_h 2       b       A
> 0       NULL    NULL    YES     HASH_INDEX
> +def    test    t1      1       test    a_b_c_d_e_f_g_h 3       c       A
> 0       NULL    NULL    YES     HASH_INDEX
> +def    test    t1      1       test    a_b_c_d_e_f_g_h 4       d       A
> 0       NULL    NULL    YES     HASH_INDEX
> +def    test    t1      1       test    a_b_c_d_e_f_g_h 5       e       A
> 0       NULL    NULL    YES     HASH_INDEX
> +def    test    t1      1       test    a_b_c_d_e_f_g_h 6       f       A
> 0       NULL    NULL    YES     HASH_INDEX
> +def    test    t1      1       test    a_b_c_d_e_f_g_h 7       g       A
> 0       NULL    NULL    YES     HASH_INDEX
> +def    test    t1      1       test    a_b_c_d_e_f_g_h 8       h       A
> 0       NULL    NULL    YES     HASH_INDEX
> +select * from information_schema.key_column_usage where table_schema=
> 'test' and table_name= 't1';
> +CONSTRAINT_CATALOG     CONSTRAINT_SCHEMA       CONSTRAINT_NAME
> TABLE_CATALOG   TABLE_SCHEMA    TABLE_NAME      COLUMN_NAME
> ORDINAL_POSITION        POSITION_IN_UNIQUE_CONSTRAINT
> REFERENCED_TABLE_SCHEMA REFERENCED_TABLE_NAME   REFERENCED_COLUMN_NAME
> +def    test    a_b_c   def     test    t1      a       1       NULL    NULL
> NULL    NULL
> +def    test    a_b_c   def     test    t1      b       2       NULL    NULL
> NULL    NULL
> +def    test    a_b_c   def     test    t1      c       3       NULL    NULL
> NULL    NULL
> +def    test    c_d_e   def     test    t1      c       1       NULL    NULL
> NULL    NULL
> +def    test    c_d_e   def     test    t1      d       2       NULL    NULL
> NULL    NULL
> +def    test    c_d_e   def     test    t1      e       3       NULL    NULL
> NULL    NULL
> +def    test    e_f_g_h def     test    t1      e       1       NULL    NULL
> NULL    NULL
> +def    test    e_f_g_h def     test    t1      f       2       NULL    NULL
> NULL    NULL
> +def    test    e_f_g_h def     test    t1      g       3       NULL    NULL
> NULL    NULL
> +def    test    e_f_g_h def     test    t1      h       4       NULL    NULL
> NULL    NULL
> +def    test    a_b_c_d_e_f     def     test    t1      a       1       NULL
> NULL    NULL    NULL
> +def    test    a_b_c_d_e_f     def     test    t1      b       2       NULL
> NULL    NULL    NULL
> +def    test    a_b_c_d_e_f     def     test    t1      c       3       NULL
> NULL    NULL    NULL
> +def    test    a_b_c_d_e_f     def     test    t1      d       4       NULL
> NULL    NULL    NULL
> +def    test    a_b_c_d_e_f     def     test    t1      e       5       NULL
> NULL    NULL    NULL
> +def    test    a_b_c_d_e_f     def     test    t1      f       6       NULL
> NULL    NULL    NULL
> +def    test    d_e_f_g_h       def     test    t1      d       1       NULL
> NULL    NULL    NULL
> +def    test    d_e_f_g_h       def     test    t1      e       2       NULL
> NULL    NULL    NULL
> +def    test    d_e_f_g_h       def     test    t1      f       3       NULL
> NULL    NULL    NULL
> +def    test    d_e_f_g_h       def     test    t1      g       4       NULL
> NULL    NULL    NULL
> +def    test    d_e_f_g_h       def     test    t1      h       5       NULL
> NULL    NULL    NULL
> +def    test    a_b_c_d_e_f_g_h def     test    t1      a       1       NULL
> NULL    NULL    NULL
> +def    test    a_b_c_d_e_f_g_h def     test    t1      b       2       NULL
> NULL    NULL    NULL
> +def    test    a_b_c_d_e_f_g_h def     test    t1      c       3       NULL
> NULL    NULL    NULL
> +def    test    a_b_c_d_e_f_g_h def     test    t1      d       4       NULL
> NULL    NULL    NULL
> +def    test    a_b_c_d_e_f_g_h def     test    t1      e       5       NULL
> NULL    NULL    NULL
> +def    test    a_b_c_d_e_f_g_h def     test    t1      f       6       NULL
> NULL    NULL    NULL
> +def    test    a_b_c_d_e_f_g_h def     test    t1      g       7       NULL
> NULL    NULL    NULL
> +def    test    a_b_c_d_e_f_g_h def     test    t1      h       8       NULL
> NULL    NULL    NULL
> +# table select we should not be able to see db_row_hash_column;
> +select * from t1;
> +a      b       c       d       e       f       g       h
> +1      1       1       1       1       1       1       1
> +2      2       2       2       2       2       2       2
> +3      3       3       3       3       3       3       3
> +4      4       4       4       4       4       4       4
> +5      5       5       5       5       5       5       5
> +maria  6       maria   maria   maria   maria   6       maria
> +mariadb        7       mariadb mariadb mariadb mariadb 8       mariadb
> +select db_row_hash_1 from t1;
> +ERROR 42S22: Unknown column 'db_row_hash_1' in 'field list'
> +select db_row_hash_2 from t1;
> +ERROR 42S22: Unknown column 'db_row_hash_2' in 'field list'
> +select db_row_hash_3 from t1;
> +ERROR 42S22: Unknown column 'db_row_hash_3' in 'field list'
> +#duplicate entry test;
> +#duplicate keys entry;
> +insert into t1 values(1,1,1,0,0,0,0,0);
> +ERROR 23000: Duplicate entry '1-1-1' for key 'a_b_c'
> +insert into t1 values(0,0,1,1,1,0,0,0);
> +ERROR 23000: Duplicate entry '1-1-1' for key 'c_d_e'
> +insert into t1 values(0,0,0,0,1,1,1,1);
> +ERROR 23000: Duplicate entry '1-1-1-1' for key 'e_f_g_h'
> +insert into t1 values(1,1,1,1,1,0,0,0);
> +ERROR 23000: Duplicate entry '1-1-1' for key 'a_b_c'
> +insert into t1 values(0,0,0,0,1,1,1,1);
> +ERROR 23000: Duplicate entry '1-1-1-1' for key 'e_f_g_h'
> +insert into t1 values(1,1,1,1,1,1,1,1);
> +ERROR 23000: Duplicate entry '1-1-1' for key 'a_b_c'
> +select
> db_row_hash_1,db_row_hash_2,db_row_hash_3,db_row_hash_4,db_row_hash_5 from
> t1;
> +ERROR 42S22: Unknown column 'db_row_hash_1' in 'field list'
> +alter table t1 drop column db_row_hash_1, drop column db_row_hash_2, drop
> column db_row_hash_3;
> +ERROR 42000: Can't DROP COLUMN `db_row_hash_1`; check that it exists
> +alter table t1 add column dg int , add column ef int , drop column
> db_row_hash_1;
> +ERROR 42000: Can't DROP COLUMN `db_row_hash_1`; check that it exists
> +alter table t1 modify column db_row_hash_1 int , modify column
> db_row_hash_2 int, modify column db_row_hash_3 int;
> +ERROR 42S22: Unknown column 'db_row_hash_1' in 't1'
> +alter table t1 add column ar int , add column rb int, modify column
> db_row_hash_1 int , modify column db_row_hash_3 int;
> +ERROR 42S22: Unknown column 'db_row_hash_1' in 't1'
> +alter table t1 change column db_row_hash_1 dsds int , change column
> db_row_hash_2  dfdf int , change column db_row_hash_3 gdfg int ;
> +ERROR 42S22: Unknown column 'db_row_hash_1' in 't1'
> +alter table t1 add column asd int, drop column a, change column
> db_row_hash_1 dsds int, change db_row_hash_3 fdfdfd int;
> +ERROR 42S22: Unknown column 'db_row_hash_1' in 't1'
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `a` blob DEFAULT NULL,
> +  `b` int(11) DEFAULT NULL,
> +  `c` varchar(2000) DEFAULT NULL,
> +  `d` text DEFAULT NULL,
> +  `e` varchar(3000) DEFAULT NULL,
> +  `f` longblob DEFAULT NULL,
> +  `g` int(11) DEFAULT NULL,
> +  `h` text DEFAULT NULL,
> +  UNIQUE KEY `a_b_c`(`a`,`b`,`c`),
> +  UNIQUE KEY `c_d_e`(`c`,`d`,`e`),
> +  UNIQUE KEY `e_f_g_h`(`e`,`f`,`g`,`h`),
> +  UNIQUE KEY `a_b_c_d_e_f`(`a`,`b`,`c`,`d`,`e`,`f`),
> +  UNIQUE KEY `d_e_f_g_h`(`d`,`e`,`f`,`g`,`h`),
> +  UNIQUE KEY `a_b_c_d_e_f_g_h`(`a`,`b`,`c`,`d`,`e`,`f`,`g`,`h`)
> +) ENGINE=MyISAM DEFAULT CHARSET=latin1
> +# add column named db_row_hash_*;
> +alter table t1 add column db_row_hash_7 int , add column db_row_hash_5 int,
> +add column db_row_hash_1 int, add column db_row_hash_2 int;
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `a` blob DEFAULT NULL,
> +  `b` int(11) DEFAULT NULL,
> +  `c` varchar(2000) DEFAULT NULL,
> +  `d` text DEFAULT NULL,
> +  `e` varchar(3000) DEFAULT NULL,
> +  `f` longblob DEFAULT NULL,
> +  `g` int(11) DEFAULT NULL,
> +  `h` text DEFAULT NULL,
> +  `db_row_hash_7` int(11) DEFAULT NULL,
> +  `db_row_hash_5` int(11) DEFAULT NULL,
> +  `db_row_hash_1` int(11) DEFAULT NULL,
> +  `db_row_hash_2` int(11) DEFAULT NULL,
> +  UNIQUE KEY `a_b_c`(`a`,`b`,`c`),
> +  UNIQUE KEY `c_d_e`(`c`,`d`,`e`),
> +  UNIQUE KEY `e_f_g_h`(`e`,`f`,`g`,`h`),
> +  UNIQUE KEY `a_b_c_d_e_f`(`a`,`b`,`c`,`d`,`e`,`f`),
> +  UNIQUE KEY `d_e_f_g_h`(`d`,`e`,`f`,`g`,`h`),
> +  UNIQUE KEY `a_b_c_d_e_f_g_h`(`a`,`b`,`c`,`d`,`e`,`f`,`g`,`h`)
> +) ENGINE=MyISAM DEFAULT CHARSET=latin1
> +show keys from t1;
> +Table  Non_unique      Key_name        Seq_in_index    Column_name
> Collation       Cardinality     Sub_part        Packed  Null    Index_type
> Comment Index_comment
> +t1     1       a_b_c   1       a       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       a_b_c   2       b       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       a_b_c   3       c       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       c_d_e   1       c       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       c_d_e   2       d       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       c_d_e   3       e       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       e_f_g_h 1       e       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       e_f_g_h 2       f       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       e_f_g_h 3       g       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       e_f_g_h 4       h       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       a_b_c_d_e_f     1       a       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     2       b       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     3       c       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     4       d       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     5       e       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     6       f       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       1       d       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       2       e       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       3       f       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       4       g       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       5       h       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 1       a       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 2       b       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 3       c       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 4       d       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 5       e       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 6       f       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 7       g       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 8       h       A       0       NULL    NULL
> YES     HASH_INDEX
> +alter table t1 drop column db_row_hash_7  , drop column db_row_hash_5 ,
> +drop column db_row_hash_1, drop column db_row_hash_2 ;
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `a` blob DEFAULT NULL,
> +  `b` int(11) DEFAULT NULL,
> +  `c` varchar(2000) DEFAULT NULL,
> +  `d` text DEFAULT NULL,
> +  `e` varchar(3000) DEFAULT NULL,
> +  `f` longblob DEFAULT NULL,
> +  `g` int(11) DEFAULT NULL,
> +  `h` text DEFAULT NULL,
> +  UNIQUE KEY `a_b_c`(`a`,`b`,`c`),
> +  UNIQUE KEY `c_d_e`(`c`,`d`,`e`),
> +  UNIQUE KEY `e_f_g_h`(`e`,`f`,`g`,`h`),
> +  UNIQUE KEY `a_b_c_d_e_f`(`a`,`b`,`c`,`d`,`e`,`f`),
> +  UNIQUE KEY `d_e_f_g_h`(`d`,`e`,`f`,`g`,`h`),
> +  UNIQUE KEY `a_b_c_d_e_f_g_h`(`a`,`b`,`c`,`d`,`e`,`f`,`g`,`h`)
> +) ENGINE=MyISAM DEFAULT CHARSET=latin1
> +show keys from t1;
> +Table  Non_unique      Key_name        Seq_in_index    Column_name
> Collation       Cardinality     Sub_part        Packed  Null    Index_type
> Comment Index_comment
> +t1     1       a_b_c   1       a       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       a_b_c   2       b       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       a_b_c   3       c       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       c_d_e   1       c       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       c_d_e   2       d       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       c_d_e   3       e       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       e_f_g_h 1       e       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       e_f_g_h 2       f       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       e_f_g_h 3       g       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       e_f_g_h 4       h       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       a_b_c_d_e_f     1       a       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     2       b       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     3       c       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     4       d       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     5       e       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     6       f       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       1       d       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       2       e       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       3       f       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       4       g       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       5       h       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 1       a       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 2       b       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 3       c       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 4       d       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 5       e       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 6       f       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 7       g       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 8       h       A       0       NULL    NULL
> YES     HASH_INDEX
> +#try to change column names;
> +alter table t1 change column a aa blob , change column b bb blob , change
> column d dd blob;
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `aa` blob DEFAULT NULL,
> +  `bb` blob DEFAULT NULL,
> +  `c` varchar(2000) DEFAULT NULL,
> +  `dd` blob DEFAULT NULL,
> +  `e` varchar(3000) DEFAULT NULL,
> +  `f` longblob DEFAULT NULL,
> +  `g` int(11) DEFAULT NULL,
> +  `h` text DEFAULT NULL,
> +  UNIQUE KEY `a_b_c`(`aa`,`bb`,`c`),
> +  UNIQUE KEY `c_d_e`(`c`,`dd`,`e`),
> +  UNIQUE KEY `e_f_g_h`(`e`,`f`,`g`,`h`),
> +  UNIQUE KEY `a_b_c_d_e_f`(`aa`,`bb`,`c`,`dd`,`e`,`f`),
> +  UNIQUE KEY `d_e_f_g_h`(`dd`,`e`,`f`,`g`,`h`),
> +  UNIQUE KEY `a_b_c_d_e_f_g_h`(`aa`,`bb`,`c`,`dd`,`e`,`f`,`g`,`h`)
> +) ENGINE=MyISAM DEFAULT CHARSET=latin1
> +show keys from t1;
> +Table  Non_unique      Key_name        Seq_in_index    Column_name
> Collation       Cardinality     Sub_part        Packed  Null    Index_type
> Comment Index_comment
> +t1     1       a_b_c   1       aa      A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       a_b_c   2       bb      A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       a_b_c   3       c       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       c_d_e   1       c       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       c_d_e   2       dd      A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       c_d_e   3       e       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       e_f_g_h 1       e       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       e_f_g_h 2       f       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       e_f_g_h 3       g       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       e_f_g_h 4       h       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       a_b_c_d_e_f     1       aa      A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     2       bb      A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     3       c       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     4       dd      A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     5       e       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     6       f       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       1       dd      A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       2       e       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       3       f       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       4       g       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       5       h       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 1       aa      A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 2       bb      A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 3       c       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 4       dd      A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 5       e       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 6       f       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 7       g       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 8       h       A       0       NULL    NULL
> YES     HASH_INDEX
> +alter table t1 change column aa a blob , change column bb b blob , change
> column dd d blob;
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `a` blob DEFAULT NULL,
> +  `b` blob DEFAULT NULL,
> +  `c` varchar(2000) DEFAULT NULL,
> +  `d` blob DEFAULT NULL,
> +  `e` varchar(3000) DEFAULT NULL,
> +  `f` longblob DEFAULT NULL,
> +  `g` int(11) DEFAULT NULL,
> +  `h` text DEFAULT NULL,
> +  UNIQUE KEY `a_b_c`(`a`,`b`,`c`),
> +  UNIQUE KEY `c_d_e`(`c`,`d`,`e`),
> +  UNIQUE KEY `e_f_g_h`(`e`,`f`,`g`,`h`),
> +  UNIQUE KEY `a_b_c_d_e_f`(`a`,`b`,`c`,`d`,`e`,`f`),
> +  UNIQUE KEY `d_e_f_g_h`(`d`,`e`,`f`,`g`,`h`),
> +  UNIQUE KEY `a_b_c_d_e_f_g_h`(`a`,`b`,`c`,`d`,`e`,`f`,`g`,`h`)
> +) ENGINE=MyISAM DEFAULT CHARSET=latin1
> +show keys from t1;
> +Table  Non_unique      Key_name        Seq_in_index    Column_name
> Collation       Cardinality     Sub_part        Packed  Null    Index_type
> Comment Index_comment
> +t1     1       a_b_c   1       a       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       a_b_c   2       b       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       a_b_c   3       c       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       c_d_e   1       c       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       c_d_e   2       d       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       c_d_e   3       e       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       e_f_g_h 1       e       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       e_f_g_h 2       f       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       e_f_g_h 3       g       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       e_f_g_h 4       h       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       a_b_c_d_e_f     1       a       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     2       b       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     3       c       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     4       d       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     5       e       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     6       f       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       1       d       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       2       e       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       3       f       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       4       g       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       5       h       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 1       a       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 2       b       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 3       c       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 4       d       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 5       e       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 6       f       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 7       g       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 8       h       A       0       NULL    NULL
> YES     HASH_INDEX
> +#now we will change the data type to int and varchar limit so that we no
> longer  require hash_index;
> +#on key a_b_c;
> +alter table t1 modify column a int , modify column b int , modify column c
> int;
> +Warnings:
> +Warning        1292    Truncated incorrect INTEGER value: 'maria'
> +Warning        1292    Truncated incorrect INTEGER value: 'maria'
> +Warning        1292    Truncated incorrect INTEGER value: 'mariadb'
> +Warning        1292    Truncated incorrect INTEGER value: 'mariadb'
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `a` int(11) DEFAULT NULL,
> +  `b` int(11) DEFAULT NULL,
> +  `c` int(11) DEFAULT NULL,
> +  `d` blob DEFAULT NULL,
> +  `e` varchar(3000) DEFAULT NULL,
> +  `f` longblob DEFAULT NULL,
> +  `g` int(11) DEFAULT NULL,
> +  `h` text DEFAULT NULL,
> +  UNIQUE KEY `a_b_c` (`a`,`b`,`c`),
> +  UNIQUE KEY `c_d_e`(`c`,`d`,`e`),
> +  UNIQUE KEY `e_f_g_h`(`e`,`f`,`g`,`h`),
> +  UNIQUE KEY `a_b_c_d_e_f`(`a`,`b`,`c`,`d`,`e`,`f`),
> +  UNIQUE KEY `d_e_f_g_h`(`d`,`e`,`f`,`g`,`h`),
> +  UNIQUE KEY `a_b_c_d_e_f_g_h`(`a`,`b`,`c`,`d`,`e`,`f`,`g`,`h`)
> +) ENGINE=MyISAM DEFAULT CHARSET=latin1
> +show keys from t1;
> +Table  Non_unique      Key_name        Seq_in_index    Column_name
> Collation       Cardinality     Sub_part        Packed  Null    Index_type
> Comment Index_comment
> +t1     0       a_b_c   1       a       A       NULL    NULL    NULL    YES
> BTREE
> +t1     0       a_b_c   2       b       A       NULL    NULL    NULL    YES
> BTREE
> +t1     0       a_b_c   3       c       A       NULL    NULL    NULL    YES
> BTREE
> +t1     1       c_d_e   1       c       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       c_d_e   2       d       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       c_d_e   3       e       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       e_f_g_h 1       e       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       e_f_g_h 2       f       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       e_f_g_h 3       g       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       e_f_g_h 4       h       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       a_b_c_d_e_f     1       a       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     2       b       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     3       c       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     4       d       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     5       e       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     6       f       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       1       d       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       2       e       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       3       f       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       4       g       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       5       h       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 1       a       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 2       b       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 3       c       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 4       d       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 5       e       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 6       f       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 7       g       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 8       h       A       0       NULL    NULL
> YES     HASH_INDEX
> +#change it back;
> +alter table t1 modify column a blob , modify column b blob , modify column
> c blob;
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `a` blob DEFAULT NULL,
> +  `b` blob DEFAULT NULL,
> +  `c` blob DEFAULT NULL,
> +  `d` blob DEFAULT NULL,
> +  `e` varchar(3000) DEFAULT NULL,
> +  `f` longblob DEFAULT NULL,
> +  `g` int(11) DEFAULT NULL,
> +  `h` text DEFAULT NULL,
> +  UNIQUE KEY `a_b_c`(`a`,`b`,`c`),
> +  UNIQUE KEY `c_d_e`(`c`,`d`,`e`),
> +  UNIQUE KEY `e_f_g_h`(`e`,`f`,`g`,`h`),
> +  UNIQUE KEY `a_b_c_d_e_f`(`a`,`b`,`c`,`d`,`e`,`f`),
> +  UNIQUE KEY `d_e_f_g_h`(`d`,`e`,`f`,`g`,`h`),
> +  UNIQUE KEY `a_b_c_d_e_f_g_h`(`a`,`b`,`c`,`d`,`e`,`f`,`g`,`h`)
> +) ENGINE=MyISAM DEFAULT CHARSET=latin1
> +show keys from t1;
> +Table  Non_unique      Key_name        Seq_in_index    Column_name
> Collation       Cardinality     Sub_part        Packed  Null    Index_type
> Comment Index_comment
> +t1     1       a_b_c   1       a       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       a_b_c   2       b       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       a_b_c   3       c       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       c_d_e   1       c       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       c_d_e   2       d       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       c_d_e   3       e       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       e_f_g_h 1       e       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       e_f_g_h 2       f       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       e_f_g_h 3       g       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       e_f_g_h 4       h       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       a_b_c_d_e_f     1       a       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     2       b       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     3       c       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     4       d       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     5       e       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     6       f       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       1       d       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       2       e       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       3       f       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       4       g       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       5       h       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 1       a       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 2       b       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 3       c       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 4       d       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 5       e       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 6       f       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 7       g       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 8       h       A       0       NULL    NULL
> YES     HASH_INDEX
> +#try to delete blob column in unique;
> +truncate table t1;
> +alter table t1 drop column a, drop column b, drop  column c;
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `d` blob DEFAULT NULL,
> +  `e` varchar(3000) DEFAULT NULL,
> +  `f` longblob DEFAULT NULL,
> +  `g` int(11) DEFAULT NULL,
> +  `h` text DEFAULT NULL,
> +  UNIQUE KEY `c_d_e`(`d`,`e`),
> +  UNIQUE KEY `e_f_g_h`(`e`,`f`,`g`,`h`),
> +  UNIQUE KEY `a_b_c_d_e_f`(`d`,`e`,`f`),
> +  UNIQUE KEY `d_e_f_g_h`(`d`,`e`,`f`,`g`,`h`),
> +  UNIQUE KEY `a_b_c_d_e_f_g_h`(`d`,`e`,`f`,`g`,`h`)
> +) ENGINE=MyISAM DEFAULT CHARSET=latin1
> +show keys from t1;
> +Table  Non_unique      Key_name        Seq_in_index    Column_name
> Collation       Cardinality     Sub_part        Packed  Null    Index_type
> Comment Index_comment
> +t1     1       c_d_e   1       d       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       c_d_e   2       e       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       e_f_g_h 1       e       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       e_f_g_h 2       f       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       e_f_g_h 3       g       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       e_f_g_h 4       h       A       0       NULL    NULL    YES
> HASH_INDEX
> +t1     1       a_b_c_d_e_f     1       d       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     2       e       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     3       f       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       1       d       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       2       e       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       3       f       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       4       g       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       5       h       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 1       d       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 2       e       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 3       f       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 4       g       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 5       h       A       0       NULL    NULL
> YES     HASH_INDEX
> +#now try to delete keys;
> +alter table t1 drop key c_d_e, drop key e_f_g_h;
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `d` blob DEFAULT NULL,
> +  `e` varchar(3000) DEFAULT NULL,
> +  `f` longblob DEFAULT NULL,
> +  `g` int(11) DEFAULT NULL,
> +  `h` text DEFAULT NULL,
> +  UNIQUE KEY `a_b_c_d_e_f`(`d`,`e`,`f`),
> +  UNIQUE KEY `d_e_f_g_h`(`d`,`e`,`f`,`g`,`h`),
> +  UNIQUE KEY `a_b_c_d_e_f_g_h`(`d`,`e`,`f`,`g`,`h`)
> +) ENGINE=MyISAM DEFAULT CHARSET=latin1
> +show keys from t1;
> +Table  Non_unique      Key_name        Seq_in_index    Column_name
> Collation       Cardinality     Sub_part        Packed  Null    Index_type
> Comment Index_comment
> +t1     1       a_b_c_d_e_f     1       d       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     2       e       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f     3       f       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       1       d       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       2       e       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       3       f       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       4       g       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       d_e_f_g_h       5       h       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 1       d       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 2       e       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 3       f       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 4       g       A       0       NULL    NULL
> YES     HASH_INDEX
> +t1     1       a_b_c_d_e_f_g_h 5       h       A       0       NULL    NULL
> YES     HASH_INDEX
> +drop table t1;
> diff --git a/mysql-test/t/hidden_field.test b/mysql-test/t/hidden_field.test
> new file mode 100644
> index 0000000..8f3b452
> --- /dev/null
> +++ b/mysql-test/t/hidden_field.test
> @@ -0,0 +1,152 @@
> +create table h_1(abc int primary key, xyz int hidden);
> +desc h_1;
> +show create table h_1;
> +drop table h_1;
> +--error ER_TABLE_MUST_HAVE_COLUMNS
> +create table h_2(a1 int hidden);
> +--error ER_PARSE_ERROR
> +create table h_3(a1 blob,hidden(a1));
> +--error ER_HIDDEN_NOT_NULL_WOUT_DEFAULT
> +create table h_4(a1 int primary key hidden ,a2 int unique hidden , a3
> blob,a4
> +int not null hidden unique);
> +--error ER_HIDDEN_NOT_NULL_WOUT_DEFAULT
> +create table h_5(abc int not null hidden);
> +create table t1(a int hidden, b int);
> +#should automatically add null
> +insert into t1 values(1);
> +insert into t1(a) values(1);
> +insert into t1(b) values(1);
> +insert into t1(a,b) values(5,5);
> +select * from t1;
> +select a,b from t1;
> +delete from t1;
> +insert into t1 values(1),(2),(3),(4);
> +select * from t1;
> +select a from t1;
> +drop table t1;
> +#echo more complex case of hidden
> +create table t1(a int , b int hidden , c int hidden auto_increment unique,
> d blob , e int unique, f int);
> +desc t1;
> +insert into t1 values(1,'d blob',1,1),(1,'d blob',11,1),(1,'d
> blob',2,1),(1,'d blob',3,1),(1,'d blob',41,1);
> +select * from t1;
> +drop table t1;
> +--error ER_PARSE_ERROR
> +create table sdsdsd(a int , b int, hidden(a,b));
> +create table t1(a int,abc int as (a mod 3) virtual hidden);
> +desc t1;
> +--error ER_WRONG_VALUE_COUNT_ON_ROW
> +insert into t1 values(1,default);
> +insert into t1 values(1),(22),(233);
> +select * from t1;
> +select a,abc from t1;
> +drop table t1;
> +create table t1(abc int primary key hidden auto_increment, a int);
> +desc t1;
> +show create table t1;
> +insert into t1 values(1);
> +insert into t1 values(2);
> +insert into t1 values(3);
> +select * from t1;
> +select abc,a from t1;
> +delete  from t1;
> +insert into t1 values(1),(2),(3),(4),(6);
> +select abc,a from t1;
> +drop table t1;
> +create table t1(abc int);
> +--error ER_TABLE_MUST_HAVE_COLUMNS
> +alter table t1 change abc ss int hidden;
> +alter table t1 add column xyz int;
> +alter table t1 modify column abc  int ;
> +desc t1;
> +--error ER_WRONG_VALUE_COUNT_ON_ROW
> +insert into t1 values(22);
> +alter table t1 modify column abc  int hidden;
> +desc t1;
> +insert into t1 values(12);
> +drop table t1;
> +
> +--echo some test on copy table structure with table data;
>
> in echo's start the message from #-sign to make it better visible in a
> result
>
> Changed.
>
> +
> +--echo table with hidden fields and unique keys;
> +
> +create table t1(a int , b int hidden , c int hidden auto_increment unique,
> d blob , e int unique, f int);
> +desc t1;
> +insert into t1 values(1,'d blob',1,1),(1,'d blob',11,1),(1,'d
> blob',2,1),(1,'d blob',3,1),(1,'d blob',41,1);
> +select * from t1;
> +select a,b,c,d,e,f from t1;
> +--echo this wont copy hidden fields and keys;
> +create table t2 as select * from t1;
> +desc t2;
> +select * from t2;
> +--error ER_BAD_FIELD_ERROR
> +select a,b,c,d,e,f from t2;
> +drop table t2;
> +--echo now this will copy hidden fields
> +create table t2 as select a,b,c,d,e,f from t1;
> +desc t2;
> +select * from t2;
> +select a,b,c,d,e,f from t2;
> +drop table t2,t1;
> +
> +--echo some test related to copy of data from one table to another;
> +create table t1(a int , b int hidden , c int hidden auto_increment unique,
> d blob , e int unique, f int);
> +insert into t1 values(1,'d blob',1,1),(1,'d blob',11,1),(1,'d
> blob',2,1),(1,'d blob',3,1),(1,'d blob',41,1);
> +select a,b,c,d,e,f from t1;
> +create table t2(a int , b int hidden , c int hidden , d blob , e int
> unique, f int);
> +insert into t2 select * from t1;
> +select a,b,c,d,e,f from t2;
> +truncate t2;
> +insert into t2 (a,b,c,d,e,f) select a,b,c,d,e,f from t1;
> +select a,b,c,d,e,f from t2;
> +truncate t2;
> +drop table t1,t2;
> +
> +--echo some test related to creating view on table with hidden column;
> +create table t1(a int , b int hidden , c int hidden auto_increment unique,
> d blob , e int unique, f int);
> +insert into t1 values(1,'d blob',1,1),(1,'d blob',11,1),(1,'d
> blob',2,1),(1,'d blob',3,1),(1,'d blob',41,1);
> +create view v as select * from t1;
> +desc v;
> +select * from v;
> +--echo v does not have hidden column;
> +--error ER_BAD_FIELD_ERROR
> +select a,b,c,d,e,f from v;
> +insert into v values(1,21,32,4);
> +select * from v;
> +--error ER_BAD_FIELD_ERROR
> +insert into v(a,b,c,d,e,f) values(1,12,3,4,5,6);
> +drop view v;
> +
> +create view v as select a,b,c,d,e,f from t1;
> +desc v;
> +select * from v;
> +--echo v does  have hidden column;
> +select a,b,c,d,e,f from v;
> +insert into v values(1,26,33,4,45,66);
> +select a,b,c,d,e,f from v;
> +insert into v(a,b,c,d,e,f) values(1,32,31,41,5,6);
> +select a,b,c,d,e,f from v;
> +drop view v;
> +drop table t1;
> +
> +--echo now hidden column in where and some join query i think no use of
> this test but anyway;
> +create table t1 (a int unique , b int hidden unique, c int unique  hidden);
> +insert into t1(a,b,c) values(1,1,1);
> +insert into t1(a,b,c) values(2,2,2);
> +insert into t1(a,b,c) values(3,3,3);
> +insert into t1(a,b,c) values(4,4,4);
> +insert into t1(a,b,c) values(21,21,26);
> +insert into t1(a,b,c) values(31,31,35);
> +insert into t1(a,b,c) values(41,41,45);
> +insert into t1(a,b,c) values(22,22,24);
> +insert into t1(a,b,c) values(32,32,33);
> +insert into t1(a,b,c) values(42,42,43);
> +explain select * from t1 where b=3;
> +select * from t1 where b=3;
> +explain select * from t1 where c=3;
> +select * from t1 where c=3;
> +
> +create table t2 as select a,b,c from t1;
> +desc t2;
> +explain select * from t1,t2 where t1.b = t2.c and t1.c = t2.b;
> +select * from t1,t2 where t1.b = t2.c and t1.c = t2.b;
> +drop table t1,t2;
> diff --git a/mysql-test/t/long_uniques.test b/mysql-test/t/long_uniques.test
> new file mode 100644
> index 0000000..8777aaa
> --- /dev/null
> +++ b/mysql-test/t/long_uniques.test
> @@ -0,0 +1,294 @@
>
> please add also a test case for innodb. In a separate file,
> long_uniques_innodb.test
> in particular, test this case:
>
>    connection con1;
>    start transaction;
>    insert ('bbbb')
>    connection con2;
>    start transaction;
>    insert ('bbbb')
>
> see? insert the conflicting value in two simultaneously running
> transactions.
> try that in different transaction isolation levels.
> normally the second transaction should *not* see the first 'bbbb' because
> the first transaction is not committed yet. But InnoDB next-key locks
> should guarantee that the second transaction will wait for the first.
>
> TODO
>
> +--echo #Structure of tests
> +--echo #First we will check all option for
> +--echo #table containing single unique column
> +--echo #table containing keys like unique(a,b,c,d) etc
> +--echo #then table containing 2 blob unique etc
> +
> +--echo #table with single long blob column;
> +create table t1(a blob unique);
> +insert into t1
> values(1),(2),(3),(56),('sachin'),('maria'),(123456789034567891),(null),(null),(123456789034567890);
> +
> +--echo #table structure;
> +desc t1;
> +show create table t1;
> +show keys from t1;
> +select * from information_schema.columns where table_schema = 'test' and
> table_name = 't1';
> +select * from information_schema.statistics where table_schema = 'test' and
> table_name = 't1';
> +select * from information_schema.key_column_usage where table_schema=
> 'test' and table_name= 't1';
> +--echo # table select we should not be able to see db_row_hash_column;
> +select * from t1;
> +--error ER_BAD_FIELD_ERROR
> +select db_row_hash_1 from t1;
> +--echo #duplicate entry test;
> +--error ER_DUP_ENTRY
> +insert into t1 values(2);
> +--error ER_DUP_ENTRY
> +insert into t1 values('sachin');
> +--error ER_DUP_ENTRY
> +insert into t1 values(123456789034567891);
> +select * from t1;
> +insert into t1 values(11),(22),(33);
> +--error ER_DUP_ENTRY
> +insert into t1 values(12),(22);
> +select * from t1;
> +insert into t1 values(repeat('s',4000*10)),(repeat('s',4001*10));
> +--error ER_DUP_ENTRY
> +insert into t1 values(repeat('m',4000*10)),(repeat('m',4000*10));
> +insert into t1 values(repeat('m',4001)),(repeat('m',4002));
> +truncate table t1;
> +insert into t1 values(1),(2),(3),(4),(5),(8),(7);
> +
> +--echo #now some alter commands;
> +alter table t1 add column b int;
> +desc t1;
> +show create table t1;
> +--error ER_DUP_ENTRY
> +insert into t1 values(1,2);
> +--error ER_DUP_ENTRY
> +insert into t1 values(2,2);
> +--error ER_BAD_FIELD_ERROR
> +select db_row_hash_1 from t1;
> +--echo #now try to change db_row_hash_1 column;
> +--error ER_CANT_DROP_FIELD_OR_KEY
> +alter table t1 drop column db_row_hash_1;
> +--error ER_CANT_DROP_FIELD_OR_KEY
> +alter table t1 add column d int , add column e int , drop column
> db_row_hash_1;
> +--error ER_BAD_FIELD_ERROR
> +alter table t1 modify column db_row_hash_1 int ;
> +--error ER_BAD_FIELD_ERROR
> +alter table t1 add column a int , add column b int, modify column
> db_row_hash_1 int ;
> +--error ER_BAD_FIELD_ERROR
> +alter table t1 change column db_row_hash_1 dsds int;
> +--error ER_BAD_FIELD_ERROR
> +alter table t1 add column asd int, change column db_row_hash_1 dsds int;
> +alter table t1 drop column b , add column c int;
> +show create table t1;
> +
> +--echo #now add some column with name db_row_hash;
> +alter table t1 add column db_row_hash_1 int unique;
> +show create table t1;
> +--error ER_DUP_ENTRY
> +insert into t1 values(45,1,55),(46,1,55);
> +alter table t1 add column db_row_hash_2 int, add column db_row_hash_3 int;
> +desc t1;
> +--echo #this should also drop the unique index ;
> +alter table t1 drop column a;
> +show create table t1;
> +show keys from t1;
> +--echo #add column with unique index on blob ;
> +alter table t1 add column a blob unique;
> +show create table t1;
> +--echo # try to change the blob unique column name;
> +--echo #this will change index to b tree;
> +alter table t1 modify  column a  int ;
> +show create table t1;
> +show keys from t1;
> +alter table t1 add column clm blob unique;
> +--echo #try changing the name ;
> +alter table t1 change column clm clm_changed blob;
> +show create table t1;
> +show keys from t1;
> +--echo #now drop the unique key;
> +alter table t1 drop key clm;
> +show create table t1;
> +show keys from t1;
> +drop table t1;
> +
> +create table t1 (a TEXT CHARSET latin1 COLLATE latin1_german2_ci unique);
> +desc t1;
> +show keys from t1;
> + insert into t1 values ('ae');
> +--error ER_DUP_ENTRY
> + insert into t1 values ('AE');
> + insert  into t1 values ('Ä');
> +drop table t1;
> +
> +--echo #table with multiple  long blob column and varchar text column ;
> +create table t1(a blob unique, b int , c blob unique , d text unique , e
> varchar(3000) unique);
> +insert into t1
> values(1,2,3,4,5),(2,11,22,33,44),(3111,222,333,444,555),(5611,2222,3333,4444,5555),
> +('sachin','ff','fdf','gfgfgfg','hghgr'),('maria','db','frter','dasd','utyuty'),
> +(123456789034567891,3534534534534,53453453453456,64565464564564,45435345345345),
> +(123456789034567890,435345345345,657567567567,78967657567567,657567567567567676);
> +
> +--echo #table structure;
> +desc t1;
> +show create table t1;
> +show keys from t1;
> +select * from information_schema.columns where table_schema = 'test' and
> table_name = 't1';
> +select * from information_schema.statistics where table_schema = 'test' and
> table_name = 't1';
> +select * from information_schema.key_column_usage where table_schema=
> 'test' and table_name= 't1';
> +--echo #table select we should not be able to see db_row_hash_column;
> +select * from t1;
> +--error ER_BAD_FIELD_ERROR
> +select db_row_hash_1 from t1;
> +--error ER_BAD_FIELD_ERROR
> +select db_row_hash_2 from t1;
> +--error ER_BAD_FIELD_ERROR
> +select db_row_hash_3 from t1;
> +--echo #duplicate entry test;
> +--error ER_DUP_ENTRY
> +insert into t1 values(21,2,3,42,51);
> +--error ER_DUP_ENTRY
> +insert into t1 values('sachin',null,null,null,null);
> +--error ER_DUP_ENTRY
> +insert into t1
> values(1234567890345671890,4353453453451,6575675675617,789676575675617,657567567567567676);
> +select * from t1;
> +insert into t1
> values(repeat('s',4000*10),100,repeat('s',4000*10),repeat('s',4000*10),
> +repeat('s',400)),(repeat('s',4001*10),1000,repeat('s',4001*10),repeat('s',4001*10),
> +repeat('s',401));
> +--error ER_DUP_ENTRY
> +insert into t1
> values(repeat('m',4000*11),10,repeat('s',4000*11),repeat('s',4000*11),repeat('s',400));
> +truncate table t1;
> +insert into t1
> values(1,2,3,4,5),(2,11,22,33,44),(3111,222,333,444,555),(5611,2222,3333,4444,5555);
> +
> +--echo #now some alter commands;
> +alter table t1 add column f int;
> +desc t1;
> +show create table t1;
> +--echo #unique key should not break;
> +--error ER_DUP_ENTRY
> +insert into t1 values(1,2,3,4,5,6);
> +--error ER_BAD_FIELD_ERROR
> +select db_row_hash_1 , db_row_hash_2, db_row_hash_3 from t1;
> +--echo #now try to change db_row_hash_1 column;
> +--error ER_CANT_DROP_FIELD_OR_KEY
> +alter table t1 drop column db_row_hash_1, drop column db_row_hash_2, drop
> column db_row_hash_3;
> +--error ER_CANT_DROP_FIELD_OR_KEY
> +alter table t1 add column dg int , add column ef int , drop column
> db_row_hash_1;
> +--error ER_BAD_FIELD_ERROR
> +alter table t1 modify column db_row_hash_1 int , modify column
> db_row_hash_2 int, modify column db_row_hash_3 int;
> +--error ER_BAD_FIELD_ERROR
> +alter table t1 add column ar int , add column rb int, modify column
> db_row_hash_1 int , modify column db_row_hash_3 int;
> +--error ER_BAD_FIELD_ERROR
> +alter table t1 change column db_row_hash_1 dsds int , change column
> db_row_hash_2  dfdf int , change column db_row_hash_3 gdfg int ;
> +--error ER_BAD_FIELD_ERROR
> +alter table t1 add column asd int, drop column a, change column
> db_row_hash_1 dsds int, change db_row_hash_3 fdfdfd int;
> +alter table t1 drop column b , add column g int;
> +show create table t1;
> +
> +--echo #now add some column with name db_row_hash;
> +alter table t1 add column db_row_hash_1 int unique;
> +alter table t1 add column db_row_hash_2 int unique;
> +alter table t1 add column db_row_hash_3 int unique;
> +show create table t1;
> +
> +alter table t1 add column db_row_hash_7 int, add column db_row_hash_5 int ,
> add column db_row_hash_4 int ;
> +alter table t1 drop column db_row_hash_7,drop column db_row_hash_3, drop
> column db_row_hash_4;
> +desc t1;
> +--echo #this show now break anything;
> +--error ER_DUP_ENTRY
> +insert into t1 values(1,2,3,4,5,6,23,5,6);
> +--echo #this should also drop the unique index;
> +alter table t1 drop column a, drop column c;
> +show create table t1;
> +show keys from t1;
> +--echo #add column with unique index on blob;
> +alter table t1 add column a blob unique;
> +show create table t1;
> +show keys from t1;
> +--echo #try to change the blob unique column name;
> +--echo #this will change index to b tree;
> +alter table t1 modify  column a  int ,  modify column e int;
> +show create table t1;
> +show keys from t1;
> +alter table t1 add column clm1 blob unique,add column clm2 blob unique;
> +--echo #try changing the name;
> +alter table t1 change column clm1 clm_changed1 blob, change column clm2
> clm_changed2 blob;
> +show create table t1;
> +show keys from t1;
> +--echo #now drop the unique key;
> +alter table t1 drop key clm1, drop key clm2;
> +show create table t1;
> +show keys from t1;
> +drop table t1;
> +
> +--echo #now the table with key on multiple columns; the ultimate test;
> +create table t1(a blob, b int , c varchar(2000) , d text  , e varchar(3000)
> , f longblob , g int , h text ,
> +  unique(a,b,c),
> unique(c,d,e),unique(e,f,g,h),unique(a,b,c,d,e,f),unique(d,e,f,g,h),unique(a,b,c,d,e,f,g,h));
> +
> +insert into t1
> values(1,1,1,1,1,1,1,1),(2,2,2,2,2,2,2,2),(3,3,3,3,3,3,3,3),(4,4,4,4,4,4,4,4),(5,5,5,5,5,5,5,5),
> +('maria',6,'maria','maria','maria','maria',6,'maria'),('mariadb',7,'mariadb','mariadb','mariadb','mariadb',8,'mariadb');
> +
> +--echo #table structure;
> +desc t1;
> +show create table t1;
> +show keys from t1;
> +select * from information_schema.columns where table_schema = 'test' and
> table_name = 't1';
> +select * from information_schema.statistics where table_schema = 'test' and
> table_name = 't1';
> +select * from information_schema.key_column_usage where table_schema=
> 'test' and table_name= 't1';
> +--echo # table select we should not be able to see db_row_hash_column;
> +select * from t1;
> +--error ER_BAD_FIELD_ERROR
> +select db_row_hash_1 from t1;
> +--error ER_BAD_FIELD_ERROR
> +select db_row_hash_2 from t1;
> +--error ER_BAD_FIELD_ERROR
> +select db_row_hash_3 from t1;
> +--echo #duplicate entry test;
> +--echo #duplicate keys entry;
> +--error ER_DUP_ENTRY
> +insert into t1 values(1,1,1,0,0,0,0,0);
> +--error ER_DUP_ENTRY
> +insert into t1 values(0,0,1,1,1,0,0,0);
> +--error ER_DUP_ENTRY
> +insert into t1 values(0,0,0,0,1,1,1,1);
> +--error ER_DUP_ENTRY
> +insert into t1 values(1,1,1,1,1,0,0,0);
> +--error ER_DUP_ENTRY
> +insert into t1 values(0,0,0,0,1,1,1,1);
> +--error ER_DUP_ENTRY
> +insert into t1 values(1,1,1,1,1,1,1,1);
> +--error ER_BAD_FIELD_ERROR
> +select
> db_row_hash_1,db_row_hash_2,db_row_hash_3,db_row_hash_4,db_row_hash_5 from
> t1;
> +--error ER_CANT_DROP_FIELD_OR_KEY
> +alter table t1 drop column db_row_hash_1, drop column db_row_hash_2, drop
> column db_row_hash_3;
> +--error ER_CANT_DROP_FIELD_OR_KEY
> +alter table t1 add column dg int , add column ef int , drop column
> db_row_hash_1;
> +--error ER_BAD_FIELD_ERROR
> +alter table t1 modify column db_row_hash_1 int , modify column
> db_row_hash_2 int, modify column db_row_hash_3 int;
> +--error ER_BAD_FIELD_ERROR
> +alter table t1 add column ar int , add column rb int, modify column
> db_row_hash_1 int , modify column db_row_hash_3 int;
> +--error ER_BAD_FIELD_ERROR
> +alter table t1 change column db_row_hash_1 dsds int , change column
> db_row_hash_2  dfdf int , change column db_row_hash_3 gdfg int ;
> +--error ER_BAD_FIELD_ERROR
> +alter table t1 add column asd int, drop column a, change column
> db_row_hash_1 dsds int, change db_row_hash_3 fdfdfd int;
> +
> +show create table t1;
> +--echo # add column named db_row_hash_*;
> +alter table t1 add column db_row_hash_7 int , add column db_row_hash_5 int,
> + add column db_row_hash_1 int, add column db_row_hash_2 int;
> +show create table t1;
> +show keys from t1;
> +alter table t1 drop column db_row_hash_7  , drop column db_row_hash_5 ,
> + drop column db_row_hash_1, drop column db_row_hash_2 ;
> +show create table t1;
> +show keys from t1;
> +
> +--echo #try to change column names;
> +alter table t1 change column a aa blob , change column b bb blob , change
> column d dd blob;
> +show create table t1;
> +show keys from t1;
> +alter table t1 change column aa a blob , change column bb b blob , change
> column dd d blob;
> +show create table t1;
> +show keys from t1;
> +
> +--echo #now we will change the data type to int and varchar limit so that
> we no longer  require hash_index;
> +--echo #on key a_b_c;
> +alter table t1 modify column a int , modify column b int , modify column c
> int;
> +show create table t1;
> +show keys from t1;
> +--echo #change it back;
> +alter table t1 modify column a blob , modify column b blob , modify column
> c blob;
> +show create table t1;
> +show keys from t1;
> +
> +--echo #try to delete blob column in unique;
> +truncate table t1;
> +alter table t1 drop column a, drop column b, drop  column c;
> +show create table t1;
> +show keys from t1;
> +--echo #now try to delete keys;
> +alter table t1 drop key c_d_e, drop key e_f_g_h;
> +show create table t1;
> +show keys from t1;
> +drop table t1;
> diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
> index 8dfa519..9d5b4f5 100644
> --- a/sql/share/errmsg-utf8.txt
> +++ b/sql/share/errmsg-utf8.txt
> @@ -7214,3 +7214,5 @@ ER_CALCULATING_DEFAULT_VALUE
>          eng "Got an error when calculating default value for %`s"
>  ER_EXPRESSION_REFERS_TO_UNINIT_FIELD 01000
>          eng "Expression for field %`-.64s is refering to uninitialized
> field %`s"
> +ER_HIDDEN_NOT_NULL_WOUT_DEFAULT
> +        eng "Hidden column '%s' either allow null values or it must have
> default value"
>
> "... should either allow null values ..."
> or
> "... should either be nullable ..."
>
> Done.
>
> diff --git a/sql/table.h b/sql/table.h
> index 651fab7..9d2b279 100644
> --- a/sql/table.h
> +++ b/sql/table.h
> @@ -330,7 +330,28 @@ enum enum_vcol_update_mode
>    VCOL_UPDATE_ALL
>  };
>
> +/* Field visibility enums */
>
> +enum  field_visible_type{
> +       NOT_HIDDEN=0,
> +       USER_DEFINED_HIDDEN,
> +       MEDIUM_HIDDEN,
> +       FULL_HIDDEN
>
> this could use some comments. Or better names.
> NOT_HIDDEN is very clear.
> USER_DEFINED_HIDDEN is kind of ok too.
> But MEDIUM_HIDDEN is not - what does that mean?
> Please, either add a comment, like
> // pseudo-columns (like ROWID). Can be queried explicitly in SELECT,
> otherwise hidden from anything
> or rename MEDIUM_HIDDEN to something self-explanatory (may be,
> PSEUDO_COLUMN_HIDDEN?).
> FULL_HIDDEN is ok, although FULLY_HIDDEN or COMPLETELY_HIDDEN is a bit
> easier to read, I'd think.
>
>
> +};
> +
> +int rem_field_from_hash_col_str(LEX_STRING *hash_lex, const char
> *field_name);
>
> confus way to abbr words. plz rena to smth lik
>
>   remove_field_from_hash_index
>
> or, may be
>
>   remove_field_from_hash_index_def
>   remove_field_from_hash_index_sql
>
> by the way, this function isn't used anywhere. Forgot to remove it?
>
> Removed.
>
> +
> +int change_field_from_hash_col_str(LEX_STRING *hash_lex,
> +
> const char *old_name, char *new_name);
>
> 1. notice many <Tab> characters on the previous line that indent
> that line way too much.
> 2. this function doesn't seem to be used either
>
> Removed.
>
> +
> +int find_field_name_in_hash(char * hash_str, const char *field_name,
> +
> int hash_str_length);
>
> again, many <Tab>s on the previous line. Prefer spaces, please.
>
> +
> +int find_field_index_in_hash(LEX_STRING * hash_lex, const char *
> field_name);
>
> name's pretty bad, compared to find_field_name_in_hash.
> better rename the previous function to find_field_pos_in_hash_str
> or something like that.
>
> +
> +int fields_in_hash_str(LEX_STRING *hash_lex);
> +
> +Field * field_ptr_in_hash_str(LEX_STRING * hash_str, TABLE *table, int
> index);
>  /**
>    Category of table found in the table share.
>  */
> @@ -1031,6 +1052,19 @@ struct TABLE
>    Field **field;                       /* Pointer to fields */
>
>    uchar *record[2];                    /* Pointer to records */
> +  uchar *check_unique_buf;  /* Pointer to record with same hash */
>
> better comment: /* record buf to resolve hash collisions for long UNIQUE
> constraints */
>
> Changed.
>
> +  handler *update_handler;  /* Handler used in case of update */
>
> I don't think you need to store it in the TABLE. You can
> either pass it as an argument to ha_update_row() or
> invoke check_duplicate_long_entries() before ha_update_row() not from it.
>
> +  /*
> +     In the case of write row for long unique we are unable of find
> +     Whick key is voilated because we in case of duplicate we never reach
> +     handler write_row function so print_error will always print that
> +     key 0 is voilated we store which key is voilated in this variable
> +     by default this should be initialized to -1
> +   */
> +  int dupp_key;
> +  /* If dupp != -1 then this string
> +     store message which should be printed */
> +  char *err_message;
>
> I wonder whether you need it. You can issue an error (with my_error())
> directly from check_duplicate_long_entries(), no need to store
> the error till later. If you issue an error early, you'll
> simply skip handler::print_keydup_error() later.
>
> This wont work because there can be statements like
> alter ignore table t1 add unique key(a);
> Anyway I have removed err_message from table class
> but dupp_key is still there. I need this here
> uint handler::get_dup_key(int error)
> {
>   DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
>               m_lock_type != F_UNLCK);
>   DBUG_ENTER("handler::get_dup_key");
>   table->file->errkey  = (uint) -1;
>   if (table->dupp_key != -1)
>     DBUG_RETURN(table->dupp_key);
>
>    uchar *write_row_record;             /* Used as optimisation in
>                                            THD::write_row */
>    uchar *insert_values;                  /* used by INSERT ... UPDATE */
> diff --git a/sql/field.h b/sql/field.h
> index 05e0615..35a7006 100644
> --- a/sql/field.h
> +++ b/sql/field.h
> @@ -998,9 +1001,9 @@ class Field: public Value_source
>    virtual int cmp(const uchar *,const uchar *)=0;
>    virtual int cmp_binary(const uchar *a,const uchar *b, uint32
> max_length=~0L)
>    { return memcmp(a,b,pack_length()); }
> -  virtual int cmp_offset(uint row_offset)
> +  virtual int cmp_offset(long row_offset)
>
> 1. why is that? because old offset was unsigned?
>
> Yes
>
> 2. better use my_ptrdiff_t type here
>
> Changed.
>
>    { return cmp(ptr,ptr+row_offset); }
> -  virtual int cmp_binary_offset(uint row_offset)
> +  virtual int cmp_binary_offset(long row_offset)
>    { return cmp_binary(ptr, ptr+row_offset); };
>    virtual int key_cmp(const uchar *a,const uchar *b)
>    { return cmp(a, b); }
> diff --git a/sql/sql_select.h b/sql/sql_select.h
> index 92ba74f..dd55d94 100644
> --- a/sql/sql_select.h
> +++ b/sql/sql_select.h
> @@ -1818,6 +1825,27 @@ class store_key_field: public store_key
>        When the implementation of this function will be replaced for a
> proper
>        full version this statement probably should be removed.
>      */
> +    if (is_hash)
> +    {
> +      Field *f= copy_field.from_field;
> +      String str;
>
> Normally in these cases you should use StringBuffer<MAX_FIELD_WIDTH>
> instead of String. It will allocate a char[MAX_FIELD_WIDTH] buffer
> on the stack so the following val_str() will not need to call malloc
> if the value is shorter than MAX_FIELD_WIDTH.
>
> But in this particular case, you're doing long unique, probably for blobs,
> so here the result will typically be larger than MAX_FIELD_WIDTH,
> and this StringBuffer optimization will not actually help.
>
> +      f->val_str(&str);
> +      if (f->is_null())
> +      {
> +        *(copy_field.to_ptr-1)= 1; //set it null
>
> why do you write to copy_field.to_ptr directly?
> store_key methods don't do that anywhere else
>
> Okay, I will change It. But I think in newer version I do not
> require this code. So I will change it later on.
>
> +        null_key= true;
>
> where you reset null_key and copy_field.ptr[-1] back to 0?
>
> +        dbug_tmp_restore_column_map(table->write_set, old_map);
> +        return STORE_KEY_OK;
> +      }
> +      CHARSET_INFO* cs= str.charset();
> +      uchar l[4];
> +      int4store(l,str.length());
> +      cs->coll->hash_sort(cs, l, sizeof(l), &nr1, &nr2);
>
> cs= &my_charset_bin; for hash_sort() above,
> cs= str.charset(); for hash_sort() below.
>
> +      cs->coll->hash_sort(cs, (uchar *)str.ptr(), str.length(), &nr1,
> &nr2);
> +      int8store(copy_field.to_ptr, nr1);
> +      dbug_tmp_restore_column_map(table->write_set, old_map);
> +      return STORE_KEY_OK;
>
> I suppose you don't need to calculate hashes if null_key is already true for
> this row (if it's a multi-column key and one of the previous columns was
> NULL)
>
> btw, could you add a test case for that? a test case where f->is_null() is
> true?
> like, add assert(0); under that if() and try to create a test case that
> will cause it to crash.
>
> +    }
>      bzero(copy_field.to_ptr,copy_field.to_length);
>
>      copy_field.do_copy(&copy_field);
> @@ -1860,6 +1889,26 @@ class store_key_item :public store_key
>                                                       table->write_set);
>      int res= FALSE;
>
> +    if (is_hash)
> +    {
> +      String *str= item->val_str();
> +      if (item->null_value)
> +      {
> +        *(to_field->ptr - 1)= 1;
> +        null_key= true;
> +        dbug_tmp_restore_column_map(table->write_set, old_map);
> +        return STORE_KEY_OK;
> +      }
> +      CHARSET_INFO *cs= str->charset();
> +      uchar l[4];
> +      int4store(l,str->length());
> +      cs->coll->hash_sort(cs,l,sizeof(l), &nr1, &nr2);
> +      cs->coll->hash_sort(cs, (uchar *)str->ptr(), str->length(), &nr1,
> &nr2);
> +      int8store(to_field->ptr, nr1);
> +      //no idea what it does
>
> remove this comment, please :)
> and if you're curious what it does, you can always comment
> dbug_tmp_use_all_columns() and dbug_tmp_restore_column_map() in this
> function
> out and run the test suite in debug build, you'll see how it will crash :)
> or you can ask, that works too...
>
> Okay
>
> +      dbug_tmp_restore_column_map(table->write_set, old_map);
> +      return STORE_KEY_OK;
> +    }
>      /*
>        It looks like the next statement is needed only for a simplified
>        hash function over key values used now in BNLH join.
> @@ -2271,4 +2320,11 @@ class Pushdown_query: public Sql_alloc
>  bool test_if_order_compatible(SQL_I_List<ORDER> &a, SQL_I_List<ORDER> &b);
>  int test_if_group_changed(List<Cached_item> &list);
>  int create_sort_index(THD *thd, JOIN *join, JOIN_TAB *tab, Filesort
> *fsort);
> +/*
> + It compares the record with same hash to key if
> + record is equal then return 0 else fetches next
> + record with same hash and so on if some error
> + then returns error
> +*/
>
> better put this comment where a function is defined, in sql_select.cc
>
> +int compare_hash_and_fetch_next(JOIN_TAB *join);
>  #endif /* SQL_SELECT_INCLUDED */
> diff --git a/sql/mysqld.cc b/sql/mysqld.cc
> index fa8f143..eb1769b 100644
> --- a/sql/mysqld.cc
> +++ b/sql/mysqld.cc
> @@ -8394,6 +8394,7 @@ SHOW_VAR status_vars[]= {
>    {"Feature_dynamic_columns",  (char*) offsetof(STATUS_VAR,
> feature_dynamic_columns), SHOW_LONG_STATUS},
>    {"Feature_fulltext",         (char*) offsetof(STATUS_VAR,
> feature_fulltext), SHOW_LONG_STATUS},
>    {"Feature_gis",              (char*) offsetof(STATUS_VAR, feature_gis),
> SHOW_LONG_STATUS},
> +  {"Feature_hidden_column",    (char*) offsetof(STATUS_VAR,
> feature_hidden_column), SHOW_LONG_STATUS},
>
> I feel that Feature_hidden_columns (plural) would look better here.
>
> I know we aren't consistent, there's Feature_dynamic_columns (plural)
> but Feature_subquery, Feature_timezone (singular), so there is no rule here,
> unfortunately.
>
> Done
>
>    {"Feature_locale",           (char*) offsetof(STATUS_VAR,
> feature_locale), SHOW_LONG_STATUS},
>    {"Feature_subquery",         (char*) offsetof(STATUS_VAR,
> feature_subquery), SHOW_LONG_STATUS},
>    {"Feature_timezone",         (char*) offsetof(STATUS_VAR,
> feature_timezone), SHOW_LONG_STATUS},
> diff --git a/sql/field.cc b/sql/field.cc
> index c684e6a..8c17b76 100644
> --- a/sql/field.cc
> +++ b/sql/field.cc
> @@ -7671,7 +7672,6 @@ uint32 Field_varstring::data_length()
>  {
>    return length_bytes == 1 ? (uint32) *ptr : uint2korr(ptr);
>  }
> -
>
> restore the empty line, please
>
>  /*
>    Functions to create a packed row.
>    Here the number of length bytes are depending on the given max_length
> diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
> index 8bb12ce..45e6cce 100644
> --- a/sql/item_subselect.cc
> +++ b/sql/item_subselect.cc
> @@ -3899,6 +3899,25 @@ bool
> subselect_uniquesubquery_engine::copy_ref_key(bool skip_constants)
>        */
>        DBUG_RETURN(true);
>      }
> +    if ((*copy)->is_hash)
> +    {
> +      if (!(*copy)->null_key && *(copy+1))
> +      {
> +        (*(copy+1))->nr1= (*copy)->nr1;
> +        (*(copy+1))->nr2= (*copy)->nr2;
>
> I don't get it, why *(copy+1) ?
>
> Supoose a key is like unique(a,b,c) then I need to transfer
> nr1,nr2 from one copy var  to another copy var. That is why
> I am doing this.
>
>
>
> +      }
> +      else
> +        break;
> +    }
> +  }
> +  //reset nr1 and nr2
> +  for (store_key **copy=tab->ref.key_copy ; *copy ; copy++)
> +  {
> +    if ((*copy)->is_hash)
> +    {
> +      (*copy)->nr1= 1;
> +      (*copy)->nr2= 4;
> +    }
>    }
>    DBUG_RETURN(false);
>  }
> diff --git a/sql/item_func.cc b/sql/item_func.cc
> index 7f8c89c..3c71e8c 100644
> --- a/sql/item_func.cc
> +++ b/sql/item_func.cc
> @@ -1839,6 +1839,40 @@ void Item_func_int_div::fix_length_and_dec()
>  }
>
>
> +longlong  Item_func_hash::val_int()
> +{
> +  unsigned_flag= true;
> +  ulong nr1= 1,nr2= 4;
> +  CHARSET_INFO *cs;
> +  for(uint i= 0;i<arg_count;i++)
> +  {
> +    String * str = args[i]->val_str();
> +    if(args[i]->null_value)
> +    {
> +      null_value= 1;
> +      return 0;
> +    }
> +    cs= str->charset();
> +    uchar l[4];
> +    int4store(l, str->length());
> +    cs->coll->hash_sort(cs, l, sizeof(l), &nr1, &nr2);
> +    cs->coll->hash_sort(cs, (uchar *)str->ptr(), str->length(), &nr1,
> &nr2);
>
> that's the third time I see these sequence of lines
> (and there's one more below). Why not to put it in a reusable function?
> like
>
>  calc_hash_for_unique(&nr1, &nr2, str) {
>    uchar l[4];
>    int4store(l, str->length());
>    cs= &my_charset_bin;
>    cs->coll->hash_sort(cs, l, sizeof(l), &nr1, &nr2);
>    cs= str->charset();
>    cs->coll->hash_sort(cs, (uchar *)str->ptr(), str->length(), &nr1, &nr2);
>  }
>
> Done.
>
> +  }
> +  null_value= 0;
> +  //for testing purpose
> +  //nr1=12;
>
> remove that, please ^^^
>
> Removed.
>
> +  return   (longlong)nr1;
> +}
> +
> +
> +void  Item_func_hash::fix_length_and_dec()
> +{
> +  maybe_null= 1;
> +  decimals= 0;
> +  max_length= 8;
> +}
> +
> +
>  longlong Item_func_mod::int_op()
>  {
>    DBUG_ASSERT(fixed == 1);
> diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
> index 9d7e735..61022e6 100644
> --- a/sql/sql_yacc.yy
> +++ b/sql/sql_yacc.yy
> @@ -6191,6 +6192,11 @@ vcol_attribute:
>              lex->alter_info.flags|= Alter_info::ALTER_ADD_INDEX;
>            }
>          | COMMENT_SYM TEXT_STRING_sys { Lex->last_field->comment= $2; }
> +        | HIDDEN_SYM
> +          {
> +              LEX *lex =Lex;
> +              lex->last_field->field_visibility=USER_DEFINED_HIDDEN;
> +          }
>
> Please, make HIDDEN keyword non-reserved. For that it should be added
> to the keyword_sp rule. And add a test case for it, like
>
>   --echo # HIDDEN is not reserved
>   create table t1 (hidden int);
>   drop table t1;
>
> Done.
>
>          ;
>
>  parse_vcol_expr:
> @@ -9482,6 +9476,12 @@ function_call_keyword:
>              if ($$ == NULL)
>                MYSQL_YYABORT;
>            }
> +        |HASH_SYM '(' expr_list ')'
>
> You've added it to function_call_keyword rule, but it should
> have been added to the function_call_conflict rule.
> See comments before these both rules.
>
> Done.
>
> +            {
> +                $$= new (thd->mem_root)Item_func_hash(thd,*$3);
> +                if($$==NULL)
> +                    MYSQL_YYABORT;
> +            }
>          | INSERT '(' expr ',' expr ',' expr ',' expr ')'
>            {
>              $$= new (thd->mem_root) Item_func_insert(thd, $3, $5, $7, $9);
> diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
> index 8028779..41f5a55 100644
> --- a/sql/sql_insert.cc
> +++ b/sql/sql_insert.cc
> @@ -198,6 +198,17 @@ static int check_insert_fields(THD *thd, TABLE_LIST
> *table_list,
>    TABLE *table= table_list->table;
>    DBUG_ENTER("check_insert_fields");
>
> +  List_iterator<Item> i_iter(values);
>
> 1. you don't use i_iter here
> 2. I'd move the loop into a separate function or a method of TABLE:
>
>    uint num_of_hiddens_fields() {
>      for (...)
>    }
>
> see below
>
> +  int num_of_hiddens_fields= 0;
> +  if (!fields.elements)
> +  {
> +    Field ** f= table->field, *field;
> +    for (; f && (field= *f); f++)
> +    {
> +      if (field->field_visibility != NOT_HIDDEN)
> +        num_of_hiddens_fields++;
> +    }
> +   }
>    if (!table_list->single_table_updatable())
>    {
>      my_error(ER_NON_INSERTABLE_TABLE, MYF(0), table_list->alias, "INSERT");
> @@ -212,7 +223,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST
> *table_list,
>                 table_list->view_db.str, table_list->view_name.str);
>        DBUG_RETURN(-1);
>      }
> -    if (values.elements != table->s->fields)
> +    if (values.elements+num_of_hiddens_fields != table->s->fields)
>
> then this if() becomes:
>
>  if (values.elements + num_of_hiddens_fields() != table->s->fields)
>
> in fact, you can have a function that counts *visible* fields, then
> this if() becomes simply
>
>  if (values.elements != table->not_hidden_fields())
>
>      {
>        my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), 1L);
>        DBUG_RETURN(-1);
> @@ -1485,7 +1497,28 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST
> *table_list,
>                                 update_values, false, &map);
>        select_lex->no_wrap_view_item= FALSE;
>      }
> -
> +    /*
> +      Reason for this condition
> +      suppose this
> +        create table t1 (a int , b int , c int hidden , d int);
> +        create view v as select a,b,c,d from t1;
> +      now query like this fails
> +        insert into v values(1,1,1)
> +      because in insert_view_fields we copy all the fields
> +      whether they are hidden or not we can not do the change
> +      there because there we have only fields name so we need
> +      to manually setup fields as insert_view_fields is called
> +      by only mysql_prepare_insert_check_table function and
> +      mysql_prepare_insert_check_table is called by only by this
> +      function so it is safe to do here
> +
> +      NOT YET IMPLEMENTED
> +    if (insert_into_view && !is_field_specified_for_view
> +         && fields.elements)
> +    {
> +      Item *ii= fields.pop();
> +    }
> +    **/
>
> 1. I didn't understand the comment, couldn't parse it. Could you, please
>    add some punctuation to it? :)
> 2. I believe you have a test case for it, and it works. Does it mean
>    that the whole commented block is obsolete and should be removed?
>    If yes, don't forget to remove is_field_specified_for_view declaration.
>
> No It does not work.
> I will try to solve this.
> Actually the main problem is
> suppose
> create table t1(a int , b int , c int hidden, d int);
> create view v as select a,b,c,d from t1;
> then query like
>             insert into t1 values(1,1,1);
> fails.
> The problem is desc v shows it is hidden. But it
> is not setting default values for field c
>
>      /* Restore the current context. */
>      ctx_state.restore_state(context, table_list);
>    }
> diff --git a/sql/sql_update.cc b/sql/sql_update.cc
> index d59b8b7..dfe83e7 100644
> --- a/sql/sql_update.cc
> +++ b/sql/sql_update.cc
> @@ -729,7 +729,17 @@ int mysql_update(THD *thd,
>    */
>    can_compare_record= records_are_comparable(table);
>    explain->tracker.on_scan_init();
> -
> +  for (uint i= 0; i < table->s->keys; i++)
> +  {
> +    if (table->key_info[i].flags & HA_UNIQUE_HASH)
> +    {
> +      if (!table->update_handler)
>
> Can table->update_handler be possibly not NULL here?
>
> No it cant be. Changed.
>
> +        table->update_handler=
> table->file->clone(table->s->normalized_path.str,
> +                                                  &table->mem_root);
>
> Note that you create this new handler on the table's memroot!
> This is wrong, as I've explained in an earlier review, memroot can
> only be freed as a whole, so by repeating UPDATE statements, you
> will allocate more and more memory in the table's memroot for
> update_handler's. You need to allocate it in the thd's memroot, because
> update_handler's has a life time of only one statement.
>
> +      table->update_handler->ha_external_lock(current_thd, F_RDLCK);
> +      break;
> +    }
> +  }
>    while (!(error=info.read_record(&info)) && !thd->killed)
>    {
>      explain->tracker.on_record_read();
> @@ -1912,6 +1929,19 @@ multi_update::initialize_tables(JOIN *join)
>
>      if (ignore)
>        table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
> +
> +    for (uint i= 0; i < table->s->keys; i++)
> +    {
> +      if (table->key_info[i].flags & HA_UNIQUE_HASH)
> +      {
> +        if (!table->update_handler)
> +          table->update_handler=
> table->file->clone(table->s->normalized_path.str,
> +                                                    &table->mem_root);
> +        table->update_handler->ha_external_lock(current_thd, F_RDLCK);
> +        break;
> +      }
> +    }
>
> same code as in mysql_update(), right?
> better move it to a small function. For example,
>
>  handler *create_update_handler(THD *thd, TABLE *table)
>  {
>    handler *update_handler= 0;
>    for (uint i= 0; i < table->s->keys; i++)
>    {
>      if (table->key_info[i].flags & HA_UNIQUE_HASH)
>      {
>        update_handler= table->file->clone(table->s->normalized_path.str,
>                                           &table->mem_root);
>        update_handler->ha_external_lock(thd, F_RDLCK);
>        return update_handler;
>      }
>    }
>    return NULL;
>  }
>
> +
>      if (table == main_table)                   // First table in join
>      {
>        if (safe_update_on_fly(thd, join->join_tab, table_ref, all_tables))
> @@ -2039,6 +2069,13 @@ multi_update::~multi_update()
>    for (table= update_tables ; table; table= table->next_local)
>    {
>      table->table->no_keyread= table->table->no_cache= 0;
> +    if (table->table->update_handler)
> +    {
> +      table->table->update_handler->ha_external_lock(current_thd, F_UNLCK);
> +      table->table->update_handler->ha_close();
> +      delete table->table->update_handler;
> +      table->table->update_handler= NULL;
> +    }
>
> same here:
>
>  void delete_update_handler(THD *thd, handler *h)
>  {
>    if (h)
>    {
>      h->ha_external_lock(thd, F_UNLCK);
>      h->ha_close();
>      delete h;
>    }
> }
>
> by the way, try to avoid current_thd, if possible. it is farily
> expensive on some platforms.
>
> Done
>
>      if (ignore)
>        table->table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
>    }
> diff --git a/sql/unireg.cc b/sql/unireg.cc
> index 19d03d2..d502b68 100644
> --- a/sql/unireg.cc
> +++ b/sql/unireg.cc
> @@ -89,6 +89,26 @@ static uchar *extra2_write(uchar *pos, enum
> extra2_frm_value_type type,
>    return extra2_write(pos, type, reinterpret_cast<LEX_STRING *>(str));
>  }
>
> +static uchar *extra2_write_field_visibility_hash_info(uchar *pos,
>
> please, rename to extra2_write_additional_field_properties
> or something like that.
>
> Done.
>
> +                   int number_of_fields,List_iterator<Create_field> * it)
> +{
> +  *pos++=EXTRA2_FIELD_FLAGS;
> +  /*
> +   always 2  first for field visibility
> +   second for is this column represent long unique hash
> +   */
> +  size_t len = 2*number_of_fields;
> +  pos= extra2_write_len(pos,len);
> +  Create_field *cf;
> +  while((cf=(*it)++))
> +  {
> +    *pos++=cf->field_visibility;
> +    *pos++=cf->is_long_column_hash;
>
> you can do one byte per field, field_visibility is only two bits,
> is_long_column_hash is one bit.
>
> Okay , I tried this , but I am not sure if it is rigth or not.
>
> +  }
> +  return pos;
> +}
> +
> +
>  /**
>    Create a frm (table definition) file
>
> @@ -121,6 +141,22 @@ LEX_CUSTRING build_frm_image(THD *thd, const char
> *table,
>    uchar *frm_ptr, *pos;
>    LEX_CUSTRING frm= {0,0};
>    DBUG_ENTER("build_frm_image");
> +  List_iterator<Create_field> it(create_fields);
> +  Create_field *field;
> +  bool is_hidden_fields_present= false;
>
> please, rename to "have_additional_field_properties"
>
> Okay.
>
> +  /*
> +    Loop througt the iterator to find whether we have any field whose
> +    visibility_type != NOT_HIDDEN
> +  */
>
> Please remove the comment above. Remember, a comment needs to say *why* you
> are doing something, it should not say *what* you are doing.  In this case
> your comment merely says what the loop below is doing, the comment is in
> English, the loop in C++, but otherwise they say exactly the same thing. If
> you rename the variable (as I suggested above) this loop will be completely
> clear without any comments anyway.
>
> +  while ((field=it++))
> +  {
> +    if (field->field_visibility != NOT_HIDDEN)
> +    {
> +      is_hidden_fields_present= true;
> +      break;
> +    }
> +  }
> +  it.rewind();
>
>   /* If fixed row records, we need one bit to check for deleted rows */
>    if (!(create_info->table_options & HA_OPTION_PACK_RECORD))
> @@ -265,7 +303,9 @@ LEX_CUSTRING build_frm_image(THD *thd, const char
> *table,
>      pos+= gis_field_options_image(pos, create_fields);
>    }
>  #endif /*HAVE_SPATIAL*/
> -
> +  if (is_hidden_fields_present)
> +
> pos=extra2_write_field_visibility_hash_info(pos,create_fields.elements,&it);
> +  it.rewind();
>
> you can rewind from inside extra2_write_field_visibility_hash_info.
> seems logical - it moves the iterator, it should restore it
>
> Okay
>
>    int4store(pos, filepos); // end of the extra2 segment
>    pos+= 4;
>
> diff --git a/sql/sql_base.cc b/sql/sql_base.cc
> index 3481bf1..ce63a88 100644
> --- a/sql/sql_base.cc
> +++ b/sql/sql_base.cc
> @@ -5287,6 +5287,8 @@ find_field_in_table(THD *thd, TABLE *table, const char
> *name, uint length,
>
>    if (field_ptr && *field_ptr)
>    {
> +    if ((*field_ptr)->field_visibility == FULL_HIDDEN)
> +       DBUG_RETURN((Field*) 0);
>
> good. please add a test case for that, with a subquery and an outer
> reference,
> as I wrote earlier.
>
> Added , but there are some bugs,
>
>      *cached_field_index_ptr= field_ptr - table->field;
>      field= *field_ptr;
>    }
> @@ -7351,6 +7353,10 @@ insert_fields(THD *thd, Name_resolution_context
> *context, const char *db_name,
>
>      for (; !field_iterator.end_of_fields(); field_iterator.next())
>      {
> +      /* Field can be null here details in test case*/
>
> "details in test case" is not very helpful. in what case can field be 0
> here?
>
> Yes it can be
> Test case
> create table t1 (empnum smallint, grp int);
> create table t2 (empnum int, name char(5));
> insert into t1 values(1,1);
> insert into t2 values(1,'bob');
> create view v1 as select * from t2 inner join t1 using (empnum);
> select * from v1;
>
> +      if ((field= field_iterator.field()) &&
> +               field->field_visibility != NOT_HIDDEN)
> +        continue;
>        Item *item;
>
>        if (!(item= field_iterator.create_item(thd)))
> @@ -7986,6 +7992,42 @@ fill_record(THD *thd, TABLE *table, Field **ptr,
> List<Item> &values,
>      only one row.
>    */
>    table->auto_increment_field_not_null= FALSE;
> +  Field **f;
> +  List_iterator<Item> i_iter(values);
> +  uint field_count= 0;
> +  for (f= ptr; f && (field= *f); f++)
> +    field_count++;
> +  /*
> +    This if is required in query like
> +    suppose table
> +      create table t1 (a int , b int hidden , c int , d int hidden );
> +    and query is
> +      create table t2 as select a,b,c,d from t1;
> +    in this case field count will be equal to values.elements
> +   */
> +  if (field_count != values.elements)
> +  {
> +    Name_resolution_context *context= & thd->lex->select_lex.context;
> +    for (f= ptr; f && (field= *f); f++)
> +    {
> +      if (field->field_visibility!=NOT_HIDDEN)
> +      {
> +        if (f == ptr)
> +        {
> +          values.push_front(new (thd->mem_root)
> +                            Item_default_value(thd,context),thd->mem_root);
> +          i_iter.rewind();
> +          i_iter++;
> +        }
> +        else
> +          i_iter.after(new (thd->mem_root)
> Item_default_value(thd,context));
> +      }
> +      else
> +        i_iter++;
> +    }
> +    f= ptr;
> +    i_iter.rewind();
> +  }
>
> I don't understand what this is doing and why. Could you explain, please?
>
> Actually comment is obsolute , so I removed It , It basically  enter the
> deafult values in hidden fields
> For example
> Create table t1 (a int , b int hidden);
> insert into t1 value(1);
> here field_count is 2 but values count is 1 so I have to artifically enter
> default value.
>
>    while ((field = *ptr++) && ! thd->is_error())
>    {
>      /* Ensure that all fields are from the same table */
> diff --git a/sql/handler.cc b/sql/handler.cc
> index 3fbd1b3..99e043b 100644
> --- a/sql/handler.cc
> +++ b/sql/handler.cc
> @@ -5875,6 +5883,132 @@ int handler::ha_reset()
>    DBUG_RETURN(reset());
>  }
>
> +/** @brief
> +    check whether inserted/updated records breaks the
> +    unique constraint on long columns.
> +    In the case of update we just need to check the specic key
> +    reason for that is consider case
> +    create table t1(a blob , b blob , x blob , y blob ,unique(a,b)
> +                                                    ,unique(c,d))
> +    and update statement like this
> +    update t1 set a=23+a; in this case if we try to scan for
> +    whole keys in table then index scan on c_d will return 0
> +    because data is same so in the case of update we take
> +    key as a parameter in normal insert key should be -1
>
> Sorry, I didn't understand this comment. Could you rephrase it?
> btw, there are no columns 'c' and 'd' in your table example.
>
> also, please, explain all function parameters here (use @param).
>
> +   @returns 0 if no duplicate else returns error
> +  */
> +int check_duplicate_long_entries(TABLE *table, handler *h, uchar *new_rec,
> +                                  int key)
> +{
> +  Field *hash_field;
> +  int result;
> +  table->dupp_key= -1;
> +  for (uint i= 0; i < table->s->keys; i++)
> +  {
> +    if (key != -1)
> +      i= key;
> +    if (table->key_info[i].flags & HA_UNIQUE_HASH)
> +    {
>
> you invoke check_duplicate_long_entries() only in two places.
> one is in  check_duplicate_long_entries_update(), inside the loop
> that checks for (table->key_info[i].flags & HA_UNIQUE_HASH).
> So I really don't see why you need to repeat this loop and the check
> here. The second invocation is in ha_write_row(), where key==-1
> and you need a loop, indeed.
> So, the logical thing to do would be to have a function (let's call if F())
> which is the content of this if() and always takes a valid key number
> as an argument. Then check_duplicate_long_entries() would do:
>
>  for (uint i= 0; i < table->s->keys; i++)
>  {
>    if (table->key_info[i].flags & HA_UNIQUE_HASH)
>      F(table, h, new_rec, i);
>  }
>
> and check_duplicate_long_entries_update() would invoke F() directly.
>
> also, note that if a function is only used in one file - like this
> your check_duplicate_long_entries(), it should be declared static.
>
> +      hash_field= table->key_info[i].key_part->field;
> +      DBUG_ASSERT(table->key_info[i].key_length ==
> HA_HASH_KEY_LENGTH_WITH_NULL);
> +      uchar ptr[HA_HASH_KEY_LENGTH_WITH_NULL];
> +
> +      if (hash_field->is_null())
> +        continue;
> +
> +      key_copy(ptr, new_rec, &table->key_info[i],
> +                      table->key_info[i].key_length, false);
> +
> +      if (!table->check_unique_buf)
> +        table->check_unique_buf= (uchar *)alloc_root(&table->mem_root,
> +                                        table->s->reclength*sizeof(uchar));
> +
> +      result= h->ha_index_read_idx_map(table->check_unique_buf,
> +                                  i, ptr, HA_WHOLE_KEY, HA_READ_KEY_EXACT);
> +      if (!result)
> +      {
> +        Item_func_or_sum * temp= static_cast<Item_func_or_sum
> *>(hash_field->
> +
> vcol_info->expr_item);
> +        Item_args * t_item= static_cast<Item_args *>(temp);
> +        uint arg_count= t_item->argument_count();
> +        Item ** arguments= t_item->arguments();
> +        int diff= table->check_unique_buf-new_rec;
> +        Field * t_field;
> +
> +        for (uint j=0; j < arg_count; j++)
> +        {
>
> Add DBUG_ASSERT(arguments[j]->type() == FIELD_ITEM);
>
> +          t_field= static_cast<Item_field *>(arguments[j])->field;
> +          if(t_field->cmp_binary_offset(diff))
> +            continue;
> +        }
> +        table->dupp_key= i;
> +        if (!table->err_message)
> +        {
> +          table->err_message= (char *) alloc_root(&table->mem_root,
> +                                                 MAX_KEY_LENGTH);
> +        }
> +        StringBuffer<MAX_KEY_LENGTH> str;
> +        str.length(0);
> +        for(uint i= 0; i < arg_count; i++)
> +        {
> +          t_field= ((Item_field *)arguments[i])->field;
> +          if (str.length())
> +            str.append('-');
> +          field_unpack(&str, t_field, new_rec, 5,//since blob can be to
> long
> +                       false);
>
> truncation is a great idea. Two comments:
> 1. make this 5 a defined constant. Like
>
>   #define MAX_BLOB_LEN_FOR_ERRMSG 5
>
> 2. perhaps 5 is too short? dunno.
> 3. indicate the truncation. Like
>
>   if (t_field->pack_length() > MAX_BLOB_LEN_FOR_ERRMSG)
>     str.append(STRING_WITH_LEN("..."));
>
> TODO
>
> +        }
> +        memcpy(table->err_message,str.ptr(),str.length());
> +        return HA_ERR_FOUND_DUPP_KEY;
> +      }
> +    }
> +    if (key != -1)
> +      break;
> +  }
> +  return 0;
> +}
> +
> +/** @brief
> +    check whether updated records breaks the
> +    unique constraint on long columns.
> +   @returns 0 if no duplicate else returns error
> +  */
> +int check_duplicate_long_entries_update(TABLE *table, handler *h, uchar
> *new_rec)
> +{
> +  Field **f, *field;
> +  LEX_STRING *ls;
> +  int error;
> +  /*
> +     Here we are comparing whether new record and old record are same
> +     with respect to fields in hash_str
> +   */
> +  long reclength= table->record[1]-table->record[0];
> +  for (uint i= 0; i < table->s->keys; i++)
> +  {
> +    if (table->key_info[i].flags & HA_UNIQUE_HASH)
> +    {
> +      ls= &table->key_info[i].key_part->field->vcol_info->expr_str;
> +      for (f= table->field; f && (field= *f); f++)
> +      {
> +        if (find_field_name_in_hash(ls->str, (char *)field->field_name,
> ls->length) != -1)
>
> ok, I'm confused. Why are you doing that?
> For INSERT you take the HASH Item and iterate its argument array.
> That's fine, I get it.
> For UPDATE you get the vcol expression as a *string* (!!!) and extract
> column
> names from there by looking at commas (???). What was that?
>
> +        {
> +          /* Compare fields if they are different then check for
> duplicates*/
> +          if(field->cmp_binary_offset(reclength))
> +          {
> +            if((error= check_duplicate_long_entries(table,
> table->update_handler,
> +                                                   new_rec, i)))
> +              return error;
> +            /*
> +              break beacuse check_duplicate_long_entries will
> +              take care of remaning fields
> +             */
> +            break;
> +          }
> +        }
> +      }
> +    }
> +  }
> +  return 0;
> +}
>
>  int handler::ha_write_row(uchar *buf)
>  {
> @@ -5921,6 +6057,8 @@ int handler::ha_update_row(const uchar *old_data,
> uchar *new_data)
>
> note that mysql_update can use ha_bulk_update_row() instead of
> ha_update_row()
> for some storage engine. I don't think bulk update can work with
> your code at all, so you need to make sure will_batch is always false
> if long unique indexes are used (this is easy). See sql_update.cc
>
> And there's bulk insert too, start_bulk_insert(), that you probably
> need to disable as well.
>
> TODO
>
>    mark_trx_read_write();
>    increment_statistics(&SSV::ha_update_count);
>
> +  if ((error= check_duplicate_long_entries_update(table, table->file,
> new_data)))
> +    return error;
>    TABLE_IO_WAIT(tracker, m_psi, PSI_TABLE_UPDATE_ROW, active_index, 0,
>                        { error= update_row(old_data, new_data);})
>
> diff --git a/sql/sql_show.cc b/sql/sql_show.cc
> index 30c65e6..a55cccd 100644
> --- a/sql/sql_show.cc
> +++ b/sql/sql_show.cc
> @@ -1972,6 +1976,25 @@ int show_create_table(THD *thd, TABLE_LIST
> *table_list, String *packet,
>      }
>      append_create_options(thd, packet, field->option_list, check_options,
>                            hton->field_options);
> +    //TODO need a better logic to find wheter to put comma or not
> +    int i=1;
> +    bool is_comma_needed=false;
> +    if (*(ptr+i)!=NULL)
> +    {
> +      is_comma_needed=true;
> +      while((*(ptr+i))->field_visibility==MEDIUM_HIDDEN ||
> +            (*(ptr+i))->field_visibility==FULL_HIDDEN)
> +      {
> +        i++;
> +        if(!*(ptr+i))
> +        {
> +          is_comma_needed =false;
> +          break;
> +        }
> +      }
> +    }
> +    if(is_comma_needed)
> +     packet->append(STRING_WITH_LEN(",\n"));
>
> What was wrong with the old logic? Print the comma before every visible
> column, excluding the first one. You only need to replace the "first one"
> condition, like
>
> -   if (ptr != table->field)
> +   if (not_the_first_field)
>      packet->append(STRING_WITH_LEN(",\n"));
> +   not_the_first_field= true;
>
> Changed.
>
>    }
>
>    key_info= table->key_info;
> @@ -1986,6 +2009,19 @@ int show_create_table(THD *thd, TABLE_LIST
> *table_list, String *packet,
>    for (uint i=0 ; i < share->keys ; i++,key_info++)
>    {
>      KEY_PART_INFO *key_part= key_info->key_part;
> +    if (key_info->flags & HA_UNIQUE_HASH)
> +    {
> +      char * column_names= key_part->field->vcol_info->
> +                          expr_str.str + HA_HASH_STR_LEN;
> +      int length= key_part->field->vcol_info->expr_str.length;
> +      length-= HA_HASH_STR_LEN;
> +      packet->append(STRING_WITH_LEN(",\n"));
> +      packet->append(STRING_WITH_LEN("  UNIQUE KEY `"));
> +      packet->append(key_info->name, strlen(key_info->name));
> +      packet->append(STRING_WITH_LEN("`"));
> +      packet->append(column_names, length);
>
> No, I'm afraid you cannot do that. You need to generate the column
> list by iterating arguments and printing them. Add this test case to your
> long_uniques.test:
>
>    create table t1 (a int, b int, c blob, d blob, unique(a,b), unique(c,d));
>    set sql_quote_show_create=0;
>    show create table t1;
>    set sql_quote_show_create=default;
>    show create table t1;
>    set sql_mode=ansi_quotes;
>    show create table t1;
>    set sql_mode=default;
>
> (you don't need create table as above, of course, you can use any
> existing table in the test file).
>
> Changed, Now it uses old logic.
>
> +      continue;
> +    }
>      bool found_primary=0;
>      packet->append(STRING_WITH_LEN(",\n  "));
>
> @@ -5411,6 +5447,10 @@ static int get_schema_column_record(THD *thd,
> TABLE_LIST *tables,
>
>    for (; (field= *ptr) ; ptr++)
>    {
> +    if(field->field_visibility == FULL_HIDDEN ||
> +           field->field_visibility == MEDIUM_HIDDEN)
> +      continue;
> +    /* For now we will only show UNI or MUL for TODO  */
>
> what do you mean by this comment?
>
> It says I have to setup MUL and UNI for desc table having blob unique
> columns.
>
>      uchar *pos;
>      char tmp[MAX_FIELD_WIDTH];
>      String type(tmp,sizeof(tmp), system_charset_info);
> @@ -5465,20 +5505,48 @@ static int get_schema_column_record(THD *thd,
> TABLE_LIST *tables,
>      pos=(uchar*) ((field->flags & PRI_KEY_FLAG) ? "PRI" :
>                   (field->flags & UNIQUE_KEY_FLAG) ? "UNI" :
>                   (field->flags & MULTIPLE_KEY_FLAG) ? "MUL":"");
> +    KEY *key= show_table->key_info;
> +    for (int i=0; i<show_table->s->keys; i++, key++)
> +    {
> +      if (key->flags & HA_UNIQUE_HASH)
> +      {
> +        LEX_STRING * ls= &key->key_part->field->vcol_info->expr_str;
> +        int position= find_field_index_in_hash(ls, field->field_name);
> +        int fields= fields_in_hash_str(ls);
> +        //this is for single  hash(`abc`)
> +        if (position == 0 && fields == 1)
> +        {
> +            pos= (uchar *) "UNI";
> +        }
> +        //this is for   hash(`abc`,`xyzs`)
> +        if (position == 0 && fields > 1)
> +        {
> +          pos=(uchar *) "MUL";
> +        }
> +      }
> +    }
>
> really? why wouldn't you set UNIQUE_KEY_FLAG or MULTIPLE_KEY_FLAG instead
> so that the old code would just work for your new keys?
>
> Done.
>
>      table->field[16]->store((const char*) pos,
>                              strlen((const char*) pos), cs);
> -
> +    StringBuffer<256> buf;
>      if (field->unireg_check == Field::NEXT_NUMBER)
> -      table->field[17]->store(STRING_WITH_LEN("auto_increment"), cs);
> +      buf.set(STRING_WITH_LEN("auto_increment"),cs);
>      if (print_on_update_clause(field, &type, true))
> -      table->field[17]->store(type.ptr(), type.length(), cs);
> +      buf.set(type.ptr(), type.length(),cs);
>      if (field->vcol_info)
>      {
>        if (field->vcol_info->stored_in_db)
> -        table->field[17]->store(STRING_WITH_LEN("PERSISTENT"), cs);
> +        buf.set(STRING_WITH_LEN("PERSISTENT"), cs);
>        else
> -        table->field[17]->store(STRING_WITH_LEN("VIRTUAL"), cs);
> +        buf.set(STRING_WITH_LEN("VIRTUAL"), cs);
> +    }
> +    /*hidden can coexist with auto_increment and virtual */
> +    if(field->field_visibility==USER_DEFINED_HIDDEN)
> +    {
> +      if (buf.length())
> +        buf.append(STRING_WITH_LEN(" , "));
>
> no space before the comma
>
> Changed.
>
> +      buf.append(STRING_WITH_LEN("HIDDEN"),cs);
>      }
> +    table->field[17]->store(buf.ptr(), buf.length(), cs);
>      table->field[19]->store(field->comment.str, field->comment.length, cs);
>      if (schema_table_store_record(thd, table))
>        DBUG_RETURN(1);
> @@ -6030,6 +6098,89 @@ int fill_schema_proc(THD *thd, TABLE_LIST *tables,
> COND *cond)
>    DBUG_RETURN(res);
>  }
>
> +static int print_get_schema_stat_keypart(THD *thd, TABLE_LIST *tables,
> +
> TABLE *table,TABLE *show_table,
> +
> LEX_STRING *db_name,
> +
> LEX_STRING *table_name,
> +
> KEY * key_info,KEY_PART_INFO
> +
> *key_part,Field * field ,int i,int j)
>
> 1. lots of tabs above that mess up the indentation.
> 2. Function comment, please.
> 3. i and j are *really* lousy argument names, please rename.
>
> Removed this whole function.
>
> +{
> +  CHARSET_INFO *cs= system_charset_info;
> +  const char *str;
> +  restore_record(table, s->default_values);
> +  table->field[0]->store(STRING_WITH_LEN("def"), cs);
> +  table->field[1]->store(db_name->str, db_name->length, cs);
> +  table->field[2]->store(table_name->str, table_name->length, cs);
> +  table->field[3]->store((longlong) ((key_info->flags &
> +                                      HA_NOSAME) ? 0 : 1), TRUE);
> +  table->field[4]->store(db_name->str, db_name->length, cs);
> +  table->field[5]->store(key_info->name, strlen(key_info->name), cs);
> +  table->field[6]->store((longlong) (j+1), TRUE);
> +  str=field ? field->field_name :"?unknown field?";
> +  table->field[7]->store(str, strlen(str), cs);
> +  if (show_table->file)
> +  {
> +    if (show_table->file->index_flags(i, j, 0) & HA_READ_ORDER)
> +    {
> +      table->field[8]->store(((key_part->key_part_flag &
> +                               HA_REVERSE_SORT) ?
> +                              "D" : "A"), 1, cs);
> +      table->field[8]->set_notnull();
> +    }
> +    KEY *key=show_table->key_info+i;
> +    if (key->rec_per_key[j])
> +    {
> +      ha_rows records= (ha_rows) ((double) show_table->stat_records() /
> +                                  key->actual_rec_per_key(j));
> +      table->field[9]->store((longlong) records, TRUE);
> +      table->field[9]->set_notnull();
> +    }
> +    /*
> +      In the case of long unique hash as we try
> +      to calc key->rec_per_key[j] it will give zero
> +      so cardinality will be set to null we do not want
> +      this so
> +     */
>
> why not? if you don't know the cardinality - set it to NULL.
> but, in fact, it shouldn't be zero, why is it?
>
> +    if (key_info->flags & HA_UNIQUE_HASH)
> +    {
> +      table->field[9]->store(0, TRUE);
> +      table->field[9]->set_notnull();
> +    }
> +    if (key_info->flags & HA_UNIQUE_HASH)
> +      table->field[13]->store(HA_HASH_STR_INDEX,HA_HASH_STR_INDEX_LEN ,
> cs);
>
> I don't think you need to define that string, just put it here like
>
>  table->field[13]->store(STRING_WITH_LEN("HASH_INDEX") , cs);
>
> +    else
> +    {
> +      str= show_table->file->index_type(i);
> +      table->field[13]->store(str, strlen(str), cs);
> +    }
> +  }
> +  if (!(key_info->flags & HA_FULLTEXT) &&
> +      (key_part->field &&
> +       key_part->length !=
> +       show_table->s->field[key_part->fieldnr-1]->key_length()))
> +  {
> +    table->field[10]->store((longlong) key_part->length /
> +                            key_part->field->charset()->mbmaxlen, TRUE);
> +    table->field[10]->set_notnull();
> +  }
> +  uint flags= key_part->field ? key_part->field->flags : 0;
> +  const char *pos=(char*) ((flags & NOT_NULL_FLAG) ? "" : "YES");
> +  table->field[12]->store(pos, strlen(pos), cs);
> +  if (!show_table->s->keys_in_use.is_set(i))
> +    table->field[14]->store(STRING_WITH_LEN("disabled"), cs);
> +  else
> +    table->field[14]->store("", 0, cs);
> +  table->field[14]->set_notnull();
> +  DBUG_ASSERT(MY_TEST(key_info->flags & HA_USES_COMMENT) ==
> +             (key_info->comment.length > 0));
> +  if (key_info->flags & HA_USES_COMMENT)
> +    table->field[15]->store(key_info->comment.str,
> +                            key_info->comment.length, cs);
> +  if (schema_table_store_record(thd, table))
> +    return 1;
> +  return 0;
> +}
> +
>
>  static int get_schema_stat_record(THD *thd, TABLE_LIST *tables,
>                                   TABLE *table, bool res,
> @@ -6066,67 +6217,34 @@ static int get_schema_stat_record(THD *thd,
> TABLE_LIST *tables,
>                               HA_STATUS_TIME);
>        set_statistics_for_table(thd, show_table);
>      }
>      for (uint i=0 ; i < show_table->s->keys ; i++, key_info++)
>      {
>        KEY_PART_INFO *key_part= key_info->key_part;
> -      const char *str;
>        for (uint j=0 ; j < key_info->user_defined_key_parts; j++,
> key_part++)
>        {
> -        restore_record(table, s->default_values);
> -        table->field[0]->store(STRING_WITH_LEN("def"), cs);
> -        table->field[1]->store(db_name->str, db_name->length, cs);
> -        table->field[2]->store(table_name->str, table_name->length, cs);
> -        table->field[3]->store((longlong) ((key_info->flags &
> -                                            HA_NOSAME) ? 0 : 1), TRUE);
> -        table->field[4]->store(db_name->str, db_name->length, cs);
> -        table->field[5]->store(key_info->name, strlen(key_info->name), cs);
> -        table->field[6]->store((longlong) (j+1), TRUE);
> -        str=(key_part->field ? key_part->field->field_name :
> -             "?unknown field?");
> -        table->field[7]->store(str, strlen(str), cs);
> -        if (show_table->file)
> +
> +        if (key_info->flags & HA_UNIQUE_HASH && key_info->key_part->field)
>          {
> -          if (show_table->file->index_flags(i, j, 0) & HA_READ_ORDER)
> +          LEX_STRING *ls = &key_info->key_part->field->vcol_info->expr_str;
> +          int total_fields= fields_in_hash_str(ls);
> +          int counter= 0;
> +          Field *fld;
> +          while (counter < total_fields)
>            {
> -            table->field[8]->store(((key_part->key_part_flag &
> -                                     HA_REVERSE_SORT) ?
> -                                    "D" : "A"), 1, cs);
> -            table->field[8]->set_notnull();
> -          }
> -          KEY *key=show_table->key_info+i;
> -          if (key->rec_per_key[j])
> -          {
> -            ha_rows records= (ha_rows) ((double) show_table->stat_records()
> /
> -                                        key->actual_rec_per_key(j));
> -            table->field[9]->store((longlong) records, TRUE);
> -            table->field[9]->set_notnull();
> +            fld= field_ptr_in_hash_str(ls, show_table, counter);
>
> parsing strings, again? don't do that, please.
>
> +            if(print_get_schema_stat_keypart(thd, tables, table,
> +                                             show_table, db_name,
> +                                             table_name, key_info,
> +                                             key_part, fld, i, counter))
> +              DBUG_RETURN(1);
> +            counter++;
>            }
> -          str= show_table->file->index_type(i);
> -          table->field[13]->store(str, strlen(str), cs);
> -        }
> -        if (!(key_info->flags & HA_FULLTEXT) &&
> -            (key_part->field &&
> -             key_part->length !=
> -             show_table->s->field[key_part->fieldnr-1]->key_length()))
> -        {
> -          table->field[10]->store((longlong) key_part->length /
> -                                  key_part->field->charset()->mbmaxlen,
> TRUE);
> -          table->field[10]->set_notnull();
> +
> +          continue;
>          }
> -        uint flags= key_part->field ? key_part->field->flags : 0;
> -        const char *pos=(char*) ((flags & NOT_NULL_FLAG) ? "" : "YES");
> -        table->field[12]->store(pos, strlen(pos), cs);
> -        if (!show_table->s->keys_in_use.is_set(i))
> -          table->field[14]->store(STRING_WITH_LEN("disabled"), cs);
> -        else
> -          table->field[14]->store("", 0, cs);
> -        table->field[14]->set_notnull();
> -        DBUG_ASSERT(MY_TEST(key_info->flags & HA_USES_COMMENT) ==
> -                   (key_info->comment.length > 0));
> -        if (key_info->flags & HA_USES_COMMENT)
> -          table->field[15]->store(key_info->comment.str,
> -                                  key_info->comment.length, cs);
> -        if (schema_table_store_record(thd, table))
> +
> +        if(print_get_schema_stat_keypart(thd,
> tables,table,show_table,db_name,
> +
> table_name,key_info,key_part,key_part->field,i,j))
>            DBUG_RETURN(1);
>        }
>      }
> @@ -6134,7 +6252,6 @@ static int get_schema_stat_record(THD *thd, TABLE_LIST
> *tables,
>    DBUG_RETURN(res);
>  }
>
> -
>
> add the empty line back, please
>
>  static int get_schema_views_record(THD *thd, TABLE_LIST *tables,
>                                    TABLE *table, bool res,
>                                    LEX_STRING *db_name,
> diff --git a/sql/table.cc b/sql/table.cc
> index 640ab82..5d5be01 100644
> --- a/sql/table.cc
> +++ b/sql/table.cc
> @@ -685,7 +685,7 @@ static bool create_key_infos(const uchar *strpos, const
> uchar *frm_image_end,
>                               uint keys, KEY *keyinfo,
>                               uint new_frm_ver, uint &ext_key_parts,
>                               TABLE_SHARE *share, uint len,
> -                             KEY *first_keyinfo, char* &keynames)
> +                             KEY *first_keyinfo, char* &keynames,const
> uchar *key_ex_flags)
>
> this new argument seems to be unused
>
> Reverted, was used in previous versions.
>
>  {
>    uint i, j, n_length;
>    KEY_PART_INFO *key_part= NULL;
> @@ -738,7 +738,6 @@ static bool create_key_infos(const uchar *strpos, const
> uchar *frm_image_end,
>        keyinfo->algorithm= HA_KEY_ALG_UNDEF;
>        strpos+=4;
>      }
> -
>
> don't delete empty lines, please, restore them all
>
>      if (i == 0)
>      {
>        ext_key_parts+= (share->use_ext_keys ?
> first_keyinfo->user_defined_key_parts*(keys-1) : 0);
> @@ -801,7 +799,8 @@ static bool create_key_infos(const uchar *strpos, const
> uchar *frm_image_end,
>      keyinfo->ext_key_parts= keyinfo->user_defined_key_parts;
>      keyinfo->ext_key_flags= keyinfo->flags;
>      keyinfo->ext_key_part_map= 0;
> -    if (share->use_ext_keys && i && !(keyinfo->flags & HA_NOSAME))
> +    if (share->use_ext_keys && i && !(keyinfo->flags & HA_NOSAME)
> +  )
>
> revert
>
>      {
>        for (j= 0;
>             j < first_key_parts && keyinfo->ext_key_parts < MAX_REF_PARTS;
> @@ -989,6 +988,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd,
> bool write,
>    const uchar *frm_image_end = frm_image + frm_length;
>    uchar *record, *null_flags, *null_pos, *mysql57_vcol_null_pos;
>    const uchar *disk_buff, *strpos;
> +  const uchar * field_properties=NULL,*key_ex_flags=NULL;
>
> this key_ex_flags is not used for anything
>
>    ulong pos, record_offset;
>    ulong rec_buff_length;
>    handler *handler_file= 0;
> @@ -1056,7 +1056,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd,
> bool write,
>          if (length < 256)
>            goto err;
>        }
> -      if (extra2 + length > e2end)
> +      if ( extra2 + length > e2end)
>
> revert
>
>          goto err;
>        switch (type) {
>        case EXTRA2_TABLEDEF_VERSION:
> @@ -1101,6 +1101,9 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd,
> bool write,
>          }
>  #endif /*HAVE_SPATIAL*/
>          break;
> +      case EXTRA2_FIELD_FLAGS:
> +         field_properties = extra2;
>
> imagine in some later MariaDB version we'll need more flags.
> there may be more than two bytes per column.
> so here you can check the length and fail with an error (no assert!)
> if it's not num_of_fields*2.
>
> Added.
>
> +        break;
>        default:
>          /* abort frm parsing if it's an unknown but important extra2 value
> */
>          if (type >= EXTRA2_ENGINE_IMPORTANT)
> @@ -1795,6 +1797,16 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd,
> bool write,
>      reg_field->field_index= i;
>      reg_field->comment=comment;
>      reg_field->vcol_info= vcol_info;
> +    if(field_properties!=NULL)
> +    {
> +
> reg_field->field_visibility=static_cast<field_visible_type>(*field_properties++);
> +
> reg_field->is_long_column_hash=static_cast<bool>(*field_properties++);
>
> why did you need a cast here? was there compiler warning?
>
> Changed.
>
> +    }
> +    /*
> +       We will add status variable only when we find a user defined hidden
> column
>
> "increment". or, better, remove this comment completely, it's obvious anyway
>
> Removed
>
> +    */
> +    if (reg_field->field_visibility == USER_DEFINED_HIDDEN)
> +      status_var_increment(thd->status_var.feature_hidden_column);
>      if (field_type == MYSQL_TYPE_BIT && !f_bit_as_char(pack_flag))
>      {
>        null_bits_are_used= 1;
> @@ -2004,13 +2016,27 @@ int TABLE_SHARE::init_from_binary_frm_image(THD
> *thd, bool write,
>
>          field= key_part->field= share->field[key_part->fieldnr-1];
>          key_part->type= field->key_type();
> +        /*
> +          Add HA_UNIQUE_HASH flag if keyinfo has only one field
> +          and field has is_long_column_hash flag on
> +        */
> +        if (keyinfo->user_defined_key_parts == 1 &&
> +             field->is_long_column_hash)
> +        {
> +          keyinfo->flags|= HA_UNIQUE_HASH;
> +          keyinfo->ext_key_flags|= HA_UNIQUE_HASH;
>
> why do you set it in ext_key_flags?
>
> It was used in optimizer. Anyway new version does not use this code.
>
> +        }
>          if (field->null_ptr)
>          {
>            key_part->null_offset=(uint) ((uchar*) field->null_ptr -
>                                          share->default_values);
>            key_part->null_bit= field->null_bit;
>            key_part->store_length+=HA_KEY_NULL_LENGTH;
> -          keyinfo->flags|=HA_NULL_PART_KEY;
> +          if (keyinfo->flags & HA_UNIQUE_HASH &&
> +              !(keyinfo->flags & HA_NULL_PART_KEY))
> +          {}
> +          else
> +            keyinfo->flags|=HA_NULL_PART_KEY;
>
> 1. why not simply
>
>   if (!(keyinfo->flags & HA_UNIQUE_HASH))
>     keyinfo->flags|=HA_NULL_PART_KEY;
>
> Actually this was more complex. If keyinfo does not have
> HA_NULL_PART_KEY flag for HA_UNIQUE_HASH , then this means
> Key can not be null. But removed this in newer version.
>
> 2. this needs a comment
>
>            keyinfo->key_length+= HA_KEY_NULL_LENGTH;
>          }
>          if (field->type() == MYSQL_TYPE_BLOB ||
> @@ -2124,6 +2149,11 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd,
> bool write,
>        if ((keyinfo->flags & HA_NOSAME) ||
>            (ha_option & HA_ANY_INDEX_MAY_BE_UNIQUE))
>          set_if_bigger(share->max_unique_length,keyinfo->key_length);
> +      if (keyinfo->flags & HA_UNIQUE_HASH)
> +      {
> +        keyinfo->ext_key_parts= 1;
> +        keyinfo->ext_key_part_map= 0;
> +      }
>
> why?
>
> This is a create_key_info code.
> if (share->use_ext_keys && i && !(keyinfo->flags &HA_NOSAME))
>     {
>       for (j= 0;
>            j < first_key_parts && keyinfo->ext_key_parts < MAX_REF_PARTS;
>            j++)
>       {
>         uint key_parts= keyinfo->user_defined_key_parts;
>         KEY_PART_INFO* curr_key_part= keyinfo->key_part;
>         KEY_PART_INFO* curr_key_part_end= curr_key_part+key_parts;
>         for ( ; curr_key_part < curr_key_part_end; curr_key_part++)
>         {
>           if (curr_key_part->fieldnr == first_key_part[j].fieldnr)
>             break;
>         }
>         if (curr_key_part == curr_key_part_end)
>         {
>           *key_part++= first_key_part[j];
>           *rec_per_key++= 0;
>           keyinfo->ext_key_parts++;
>           keyinfo->ext_key_part_map|= 1 << j;
>         }
>       }
>       if (j == first_key_parts)
>         keyinfo->ext_key_flags= keyinfo->flags | HA_EXT_NOSAME;
> hash key_info does not have HA_NOSAME flag so, its keyinfo->ext_key_parts
> is added. But we do not want this. Anyway removed this in new version.
> Now HA_UNIQUE_HASH key also have HA_NOSAME flag.
>
>      }
>      if (primary_key < MAX_KEY &&
>         (share->keys_in_use.is_set(primary_key)))
> @@ -7808,3 +7842,193 @@ double KEY::actual_rec_per_key(uint i)
>    return (is_statistics_from_stat_tables ?
>            read_stats->get_avg_frequency(i) : (double) rec_per_key[i]);
>  }
> +
> +/*
> +   find out that whether field name exists in hash_str
> +   return index of  hash_str  if found other wise returns
> +   -1
> +*/
> +int find_field_name_in_hash(char * hash_str, const  char * field_name,
> +                            int hash_str_length)
>
> ok, all these manipulations with the expression *string*
> should be removed. Column names might contain commas,
> column names might contain backticks - you don't handle that.
> And you should not, really, don't use vcol_info->expr_str, use
> vcol_info->expr_item instead.
>
> Removed. Now I use expr_item.
>
> +{
> +
> +  int j= 0, i= 0;
> +  for (i= 0; i < hash_str_length; i++)
> +  {
> +    while (*(hash_str+i) == *(field_name+j))
> +    {
> +      i++;
> +      j++;
> +      if(*(field_name+j)=='\0' &&*(hash_str+i)=='`')
> +        goto done;
> +    }
> +    j=0;
> +  }
> +  return -1;
> +  done:
> +  return i;
> +}
> +
> +/*
> +   find out the field positoin in hash_str()
> +   position starts from 0
> +   else return -1;
> +*/
> +int find_field_index_in_hash(LEX_STRING *hash_lex, const char * field_name)
> +{
> +  char *hash_str= hash_lex->str;
> +  int hash_str_length= hash_lex->length;
> +  int field_name_position= find_field_name_in_hash(hash_str, field_name,
> hash_str_length);
> +  if (field_name_position == -1)
> +    return -1;
> +  int index= 0;
> +  for (int i= 0; i < field_name_position; i++)
> +  {
> +    if (hash_str[i] == ',')
> +      index++;
> +  }
> +  return index;
> +}
> +
> +/*
> +   find total number of field in hash_str
> +*/
> +int fields_in_hash_str(LEX_STRING * hash_lex)
> +{
> +  int hash_str_length= hash_lex->length;
> +  char *hash_str= hash_lex->str;
> +  int num_of_fields= 1;
> +  for (int i= 0; i<hash_str_length; i++)
> +  {
> +    if (hash_str[i] == ',' && hash_str[i-1] == '`'
> +         && hash_str[i+1] == '`' )
> +      num_of_fields++;
> +  }
> +  return num_of_fields;
> +}
> +
> +/*
> +   return fields ptr given by hash_str index
> +   for example
> +   hash(`abc`,`xyz`)
> +   index 1 will return pointer to xyz field
> +*/
> +Field * field_ptr_in_hash_str(LEX_STRING * hash_str, TABLE *table, int
> index)
> +{
> +  char field_name[100]; // 100 is enough i think
> +  int temp_index= 0;
> +  char *str= hash_str->str;
> +  int i= strlen("hash"), j;
> +  Field **f, *field;
> +  while (i < hash_str->length)
> +  {
> +    if (str[i] == ',')
> +      temp_index++;
> +    if (temp_index >= index)
> +      break;
> +    i++;
> +  }
> +  i+= 2;  // now i point to first character of field name
> +  for (j= 0; str[i+j] !=  '`'; j++)
> +    field_name[j]= str[i+j];
> +  field_name[j]= '\0';
> +  for (f= table->field; f && (field= *f); f++)
> +  {
> +    if (!my_strcasecmp(system_charset_info, field->field_name, field_name))
> +      break;
> +  }
> +  return field;
> +}
> +
> +/*
> +  Remove field name from db_row_hash_* column vcol info str
> +  For example
> +
> +  hash(`abc`,`xyz`)
> +  remove "abc" will return
> +  0 and hash_str will be set hash(`xyz`) and length will be set
> +
> +  hash(`xyz`)
> +  remove "xyz" will return
> +  0 and hash_str will be set NULL and length will be 0
> +  hash(`xyz`)
> +  remove "xyzff" will return
> +  1 no change to hash_str and length
> +  TODO a better and less complex logic
> +*/
> +int rem_field_from_hash_col_str(LEX_STRING * hash_lex, const char *
> field_name)
> +{
> +   /* first of all find field_name in hash_str*/
> +  char * temp= hash_lex->str;
> +  const char * t_field= field_name;
> +  int i= find_field_name_in_hash(temp, field_name, hash_lex->length);
> +  if ( i != -1)
> +  {
> +    /*
> +      We found the field location
> +      First of all we need to find the
> +      , position and there can be three
> +      situations
> +      1. two , not a problem remove any one
> +      2. one , remove this
> +      3  no , return
> +   */
> +    // see if there is , before field name
> +    int j= strlen(field_name);
> +    if (*(temp + i -j-2) == ',')
> +    {
> +      hash_lex->length= hash_lex->length- j-2-1;//-2 for two '`' and -1 for
> ','
> +      memmove(temp+i-j-2, temp+i+1, hash_lex->length);
> +      return 0;
> +    }
> +    if (*(temp+i+1) == ',')
> +    {
> +      hash_lex->length= hash_lex->length-j-2-1;//-2 for two '`' and -1 for
> ','
> +      memmove(temp+i-j-1, temp+i+2, hash_lex->length);
> +      return 0;
> +    }
> +    if (*(temp+i+1) == ')')
> +    {
> +      hash_lex->length= 0;
> +      hash_lex->str= NULL;
> +      return 0;
> +    }
> +  }
> +  return 1;
> +}
> +/*   returns 1 if old_name not found in hash_lex 0 other wise*/
> +int  change_field_from_hash_col_str(LEX_STRING * hash_lex, const char *
> old_name,
> +                                    char * new_name)
> +{
> +  /* first of all find field_name in hash_lex*/
> +  char * temp= hash_lex->str;
> +  const char * t_field= old_name;
> +  int i= find_field_name_in_hash(temp, old_name, hash_lex->length);
> +  if (i != -1)
> +  {
> +    int len= hash_lex->length-strlen(old_name) + strlen(new_name);
> +    int num= 0;
> +    char  temp_arr[len];
> +    int s_c_position= i - strlen(old_name);//here it represent the posotion
> of
> +                                          //'`' before old f_name
> +    for (int index= 0; index < len; index++)
> +    {
> +      if (index >= s_c_position && index < s_c_position+strlen(new_name))
> +      {
> +        temp_arr[index]= new_name[index-s_c_position];
> +        continue;
> +      }
> +      if (index >= s_c_position+strlen(new_name))
> +      {
> +        temp_arr[index]= temp[i+num];
> +        num++;
> +        continue;
> +      }
> +      temp_arr[index]= temp[index];
> +    }
> +    strcpy(hash_lex->str, temp_arr);
> +    hash_lex->length= len;
> +    return 0;
> +  }
> +  return 1;
> +}
> diff --git a/sql/sql_select.cc b/sql/sql_select.cc
> index 5cc7798..921cf18 100644
> --- a/sql/sql_select.cc
> +++ b/sql/sql_select.cc
>
> this is impressive :)
> but to send you something sooner, I'm going to skip your optimizer
> changes now, I'll send the review of the original project (long UNIQUE
> constraint) first, then I'll finish the review of the optimizer part.
>
> diff --git a/sql/sql_table.cc b/sql/sql_table.cc
> index e745fe8..ed8aa8f 100644
> --- a/sql/sql_table.cc
> +++ b/sql/sql_table.cc
> @@ -3186,6 +3186,177 @@ static void check_duplicate_key(THD *thd,
>    }
>  }
>
> +/*
> +  Add hidden level 3 hash field to table in case of long
> +  unique column
> +  Returns 0 on success
> +  else 1
> +*/
> +
> +int add_hash_field(THD * thd, Alter_info *alter_info, Key *current_key,
> +                KEY *current_key_info, KEY *key_info, CHARSET_INFO *cs)
>
> should be declared static
>
> Done.
>
> +{
> +  int num= 1;
> +  List_iterator<Key> key_iter(alter_info->key_list);
> +  List_iterator<Key_part_spec> key_part_iter(current_key->columns);
> +  List_iterator<Create_field> it(alter_info->create_list);
> +  Create_field *dup_field, * sql_field;
> +  Key_part_spec *temp_colms;
> +
> +  Create_field *cf= new (thd->mem_root) Create_field();
> +  cf->flags|= UNSIGNED_FLAG;
> +  cf->length= cf->char_length= HA_HASH_FIELD_LENGTH;
> +  cf->charset= NULL;
> +  cf->decimals= 0;
> +  char *temp_name= (char *)thd->alloc(30);
> +  strcpy(temp_name, HA_DB_ROW_HASH_STR);
> +  char num_holder[10];    //10 is way more but i think it is ok
> +  sprintf(num_holder, "%d",num);
> +  strcat(temp_name, num_holder);
>
> 1. my_snprintf, not sprintf. for just one number - strtol
> 2. "%u" not "%d"
> 3. with sprintf, you don't need strcat:
>
>    my_snprintf(temp_name, sizeof(temp_name), "DB_ROW_HASH_%u", num);
>
> Okay , Changed.
>
> +  /*
> +    Check for collusions
> +   */
> +  while ((dup_field= it++))
> +  {
> +    if (!my_strcasecmp(system_charset_info, temp_name,
> dup_field->field_name))
> +    {
> +      temp_name[12]= '\0'; //now temp_name='DB_ROW_HASH_'
> +      num++;
> +      sprintf(num_holder, "%d",num);
> +      strcat(temp_name, num_holder);
> +      it.rewind();
> +    }
> +  }
> +  it.rewind();
> +  cf->field_name= temp_name;
> +  cf->sql_type= MYSQL_TYPE_LONGLONG;
> +  /* hash column should be atmost hidden */
>
> should be "fully hidden"
>
> Changed
>
> +  cf->field_visibility= FULL_HIDDEN;
> +  cf->is_long_column_hash= true;
> +  /* add the virtual colmn info */
> +  Virtual_column_info *v= new (thd->mem_root) Virtual_column_info();
> +  char * hash_exp= (char *)thd->alloc(1024);
> +  char * key_name= (char *)thd->alloc(252);
> +  strcpy(hash_exp, HA_HASH_STR_HEAD);
> +  temp_colms= key_part_iter++;
> +  strcat(hash_exp, temp_colms->field_name.str);
> +  strcpy(key_name, temp_colms->field_name.str);
> +  strcat(hash_exp, "`");
> +  while ((temp_colms= key_part_iter++))
> +  {
> +    while ((sql_field= it++) &&
> +           my_strcasecmp(system_charset_info,
> +              temp_colms->field_name.str, sql_field->field_name))
> +    {}
> +    it.rewind();
> +    /*
> +      There should be only one key for db_row_hash_* column
> +      we need to give user a error when the accidently query
> +      like
> +
> +      create table t1(abc blob unique, unique(db_row_hash_1));
> +      alter table t2 add column abc blob unique,add unique
> key(db_row_hash_1);
> +
> +      for this we will iterate through the key_list and
> +      find if and key_part has the same name as of temp_name
> +     */
> +    if (!sql_field || sql_field->is_long_column_hash)
> +    {
> +      my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), temp_name);
> +      return 1;
> +    }
>
> hmm, are you sure this check is needed?
> you've just added a column, there can be no existing key that
> refers to it, can it?
>
> Or, may be, you added a column before the code that checks whether a key is
> valid? In that case, that code will still fail with
> ER_KEY_COLUMN_DOES_NOT_EXITS, because your column is fully hidden.
>
> Either way, your check looks redundant.
>
> Removed this whole part.
>
> +    /*
> +      This test for wrong query like
> +      create table t1(a blob ,unique(a,a));
> +    */
> +    if (find_field_name_in_hash(hash_exp,
> +                 temp_colms->field_name.str, strlen(hash_exp))!=-1)
> +    {
> +      my_error(ER_DUP_FIELDNAME, MYF(0), temp_colms->field_name.str);
> +      return 1;
> +    }
> +    /* If any field can be null add flag */
> +    if (!sql_field->flags & NOT_NULL_FLAG)
> +      current_key_info->flags|= HA_NULL_PART_KEY;
> +    strcat(hash_exp, (const char * )",");
> +    strcat(key_name, "_");
> +    strcat(hash_exp, "`");
> +    strcat(hash_exp, temp_colms->field_name.str);
> +    strcat(key_name, temp_colms->field_name.str);
> +    strcat(hash_exp, "`");
>
> 1. hash_exp is generated incorrectly, you forgot that a column
>    name itself can contain backticks. There are quoting functions
>    in sql_show.cc and as my_snprintf("%`s")
>
> Changed.
>
> 2. do you really need to create a true virtual column here, with the
>    hash expression and store it in the frm? you can store the key as a
>    normal key (with actual blobs, not uint for the hash value),
>    and generate the vcol in init_from_binary_frm_image().
>
> This is a big change. Took me 3-4 days , But anyway done.
>
> +  }
> +  strcat(hash_exp, (const char * )")");
> +  v->expr_str.str= hash_exp;
> +  v->expr_str.length= strlen(hash_exp);
> +  v->expr_item= NULL;
> +  v->set_stored_in_db_flag(true);
> +  cf->vcol_info= v;
> +  cf->charset= cs;
> +  cf->create_length_to_internal_length();
> +  cf->length= cf->char_length= cf->pack_length;
> +  prepare_create_field(cf, NULL, 0);
> +  if (!current_key_info->flags & HA_NULL_PART_KEY)
> +  {
> +    cf->pack_flag^= FIELDFLAG_MAYBE_NULL;
> +    cf->flags^= NOT_NULL_FLAG;
> +  }
> +  alter_info->create_list.push_front(cf,thd->mem_root);
> +  /* Update row offset because field is added in first position */
> +  int offset=0;
> +  it.rewind();
> +  while ((dup_field= it++))
> +  {
> +    dup_field->offset= offset;
> +    if (dup_field->stored_in_db())
> +      offset+= dup_field->pack_length;
> +  }
> +  it.rewind();
> +  while ((dup_field= it++))
> +  {
> +    if (!dup_field->stored_in_db())
> +    {
> +      dup_field->offset= offset;
> +      offset+= dup_field->pack_length;
> +    }
> +  }
> +  if(current_key->name.length==0)
> +  {
> +    current_key_info->name= key_name;
> +    current_key_info->name_length= strlen(key_name);
> +    key_name= make_unique_key_name(thd, key_name,
> +          key_info, current_key_info);
> +  }
> +  else
> +    current_key_info->name= current_key->name.str;
> +  if (check_if_keyname_exists(current_key_info->name, key_info,
> +                              current_key_info))
> +  {
> +    my_error(ER_DUP_KEYNAME, MYF(0), key_name);
> +    return 1;
> +  }
> +  current_key->type= Key::MULTIPLE;
> +  current_key_info->key_length= cf->pack_length; //length of mysql long
> column
> +  current_key_info->user_defined_key_parts= 1;
> +  current_key_info->flags= 0;
> +  current_key_info->key_part->fieldnr= 0;
> +  current_key_info->key_part->offset= 0;
> +  current_key_info->key_part->key_type= cf->pack_flag;
> +  current_key_info->key_part->length= cf->pack_length;
> +  /* As key is added in front so update update keyinfo field ref and
> offset*/
> +  KEY * t_key = key_info;
> +  KEY_PART_INFO *t_key_part;
> +  while (t_key != current_key_info)
> +  {
> +    t_key_part= t_key->key_part;
> +    for (int i= 0; i < t_key->user_defined_key_parts; i++,t_key_part++)
> +    {
> +      t_key_part->fieldnr+= 1;
> +      t_key_part->offset+= cf->pack_length;
> +    }
> +    t_key++;
> +  }
> +  return 0;
> +}
>
>  /*
>    Preparation for table creation
> @@ -3283,7 +3454,13 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO
> *create_info,
>        /* Fix for prepare statement */
>        thd->change_item_tree(&sql_field->default_value->expr_item, item);
>      }
> -
> +    if (sql_field->field_visibility == USER_DEFINED_HIDDEN &&
> +        sql_field->flags & NOT_NULL_FLAG &&
> +        sql_field->flags & NO_DEFAULT_VALUE_FLAG)
> +    {
> +      my_error(ER_HIDDEN_NOT_NULL_WOUT_DEFAULT, MYF(0),
> sql_field->field_name);
>
> say "WITHOUT", this "WOUT" looks weird
>
> Changed, I thought short form will work.
>
> +      DBUG_RETURN(TRUE);
> +    }
>      if (sql_field->sql_type == MYSQL_TYPE_SET ||
>          sql_field->sql_type == MYSQL_TYPE_ENUM)
>      {
> @@ -3884,10 +4070,24 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO
> *create_info,
>            if (f_is_geom(sql_field->pack_flag) && sql_field->geom_type ==
>                Field::GEOM_POINT)
>              column->length= MAX_LEN_GEOM_POINT_FIELD;
> -         if (!column->length)
> -         {
> -           my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0),
> column->field_name.str);
> -           DBUG_RETURN(TRUE);
> +    if (!column->length)
> +    {
> +      if (key->type == Key::PRIMARY)
> +      { //todo change error message
>
> agree, ER_TOO_LONG_KEY would be better here
>
> Changed
>
> +        my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0),
> column->field_name.str);
> +        DBUG_RETURN(TRUE);
> +      }
> +      if (!add_hash_field(thd, alter_info, key, key_info,
> +                          *key_info_buffer,
> create_info->default_table_charset))
> +      {
> +        key_part_info= key_info->key_part;
> +        key_part_info++;
> +        null_fields++;
> +        key_length= HA_HASH_KEY_LENGTH_WITHOUT_NULL;
> +        break;
> +      }
> +      else
> +        DBUG_RETURN(TRUE);
>           }
>         }
>  #ifdef HAVE_SPATIAL
> @@ -3974,9 +4174,9 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO
> *create_info,
>             }
>             else
>             {
> -             my_error(ER_TOO_LONG_KEY, MYF(0), key_part_length);
> -             DBUG_RETURN(TRUE);
> -           }
> +                               my_error(ER_TOO_LONG_KEY, MYF(0),
> key_part_length);
> +                               DBUG_RETURN(TRUE);
>
> why don't you call add_hash_field() here?
> if this place is now impossible, add a DBUG_ASSERT(0) there or remove the
> if() completely and replace it with an assert. I mean:
>
>   if (condition)
>   {
>      something;
>   }
>   else
>   {
>      something else;
>   }
>
> becomes
>
>   DBUG_ASSERT(condition);
>   something;
>
> +                       }
>           }
>         }
>          // Catch invalid use of partial keys
> @@ -4021,8 +4221,23 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO
> *create_info,
>         }
>         else
>         {
> -         my_error(ER_TOO_LONG_KEY, MYF(0), key_part_length);
> -         DBUG_RETURN(TRUE);
> +               if(key->type != Key::UNIQUE)
> +               {
> +                       my_error(ER_TOO_LONG_KEY, MYF(0), key_part_length);
> +                       DBUG_RETURN(TRUE);
> +               }
> +               //todo we does not respect length given by user in
> calculating hash
>
> oh. that's a bug. good that you have a comment about it,
> there're more urgent issues that this one, but it should be fixed eventually
>
> //TODO
>
> +               if(!add_hash_field(thd, alter_info, key, key_info,
> +
> *key_info_buffer, create_info->default_table_charset))
> +               {
> +                       key_part_info= key_info->key_part;
> +                       key_part_info++;
> +                       null_fields++;
> +                       key_length= HA_HASH_KEY_LENGTH_WITHOUT_NULL;
> +                       break;
> +               }
> +               else
> +                       DBUG_RETURN(TRUE);
>         }
>        }
>        key_part_info->length= (uint16) key_part_length;
> @@ -7502,6 +7717,8 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
>    */
>    for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++)
>    {
> +    if (field->field_visibility == FULL_HIDDEN)
> +      continue;
>
> ok, so you recreate DB_ROW_HASH_xxx columns every time
>
> Yes, BTW I changed this If condition to this one
> if  (field->is_long_unique_hash)
>     continue;
>
>      Alter_drop *drop;
>      if (field->type() == MYSQL_TYPE_VARCHAR)
>        create_info->varchar= TRUE;
> @@ -7818,7 +8057,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
>
>        if (key_info->flags & HA_SPATIAL)
>          key_type= Key::SPATIAL;
> -      else if (key_info->flags & HA_NOSAME)
> +      else if (key_info->flags & HA_NOSAME || key_info->flags &
> HA_UNIQUE_HASH)
>        {
>          if (! my_strcasecmp(system_charset_info, key_name,
> primary_key_name))
>            key_type= Key::PRIMARY;
>
> huh? I thought your HA_UNIQUE_HASH indexes cannot be Key::PRIMARY
>
> Sorry , I did not see this.
>
> Regards,
> Sergei
> Chief Architect MariaDB
> and security@xxxxxxxxxxx
>
>


Follow ups

References