← Back to team overview

maria-developers team mailing list archive

Re: Sachin weekly report

 

Hi Sergei!
Actually I implemented optimization on where with update and delete ,
with minimal changes on optimizer. Also now we can
use optimization in joins, select including subquery etc. I haven't
written much test case, but I will write it soon.
Please review it.
Regards
sachin

On Wed, Sep 7, 2016 at 11:06 PM, Sachin Setia <sachinsetia1001@xxxxxxxxx> wrote:
> 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
>>
>>


References