← Back to team overview

maria-developers team mailing list archive

Re: bb2db687a05: 26 aug (MDEV-371 Unique indexes for blobs)

 

Hi, Sachin!

Could you please explain what you store in the frm file and how you modify
keyinfo/keypart structures in memory?

Needs to be tested with partitioned tables. Particularly with MDEV-14005.

Tests were great and thourough, good job.

It'd be useful to have at least some tests for innodb too, though.

See other comments below.

On Oct 08, Sachin Setiya wrote:

> diff --git a/mysql-test/main/long_unique.result b/mysql-test/main/long_unique.result
> new file mode 100644
> index 00000000000..1a06c230c72
> --- /dev/null
> +++ b/mysql-test/main/long_unique.result
> @@ -0,0 +1,1391 @@
> +#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 
> +set @allowed_packet= @@max_allowed_packet;
> +#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;
> +Table  t1
> +Non_unique     0
> +Key_name       a
> +Seq_in_index   1
> +Column_name    a
> +Collation      A
> +Cardinality    NULL
> +Sub_part       NULL
> +Packed NULL
> +Null   YES
> +Index_type     HASH_INDEX

I'm not sure about it. One cannot write UNIQUE (a) USING HASH_INDEX
in CREATE TABLE, right?

May be just report HASH here? (and fix the parser to behave accordingly)

> +Comment        
> +Index_comment  
> +
> +MyISAM file:         DATADIR/test/t1
> +Record format:       Packed
> +Character set:       latin1_swedish_ci (8)
> +Data records:                   10  Deleted blocks:                 0
> +Recordlength:                   20
> +
> +table description:
> +Key Start Len Index   Type
> +1   12    8   multip. ulonglong NULL       

good idea

> +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  IS_GENERATED    GENERATION_EXPRESSION
> +def    test    t1      a       1       NULL    YES     blob    65535   65535   NULL    NULL    NULL    NULL    NULL    blob    UNI             select,insert,update,references         NEVER   NULL
> +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      0       test    a       1       a       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +select   * from information_schema.key_column_usage where table_schema= 'test' and table_name= 't1';
> +CONSTRAINT_CATALOG     def
> +CONSTRAINT_SCHEMA      test
> +CONSTRAINT_NAME        a
> +TABLE_CATALOG  def
> +TABLE_SCHEMA   test
> +TABLE_NAME     t1
> +COLUMN_NAME    a
> +ORDINAL_POSITION       1
> +POSITION_IN_UNIQUE_CONSTRAINT  NULL
> +REFERENCED_TABLE_SCHEMA        NULL
> +REFERENCED_TABLE_NAME  NULL
> +REFERENCED_COLUMN_NAME NULL
> +# table select we should not be able to see db_row_hash_column;
> +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 'sachin' for key 'a'
> +insert into t1 values(123456789034567891);
> +ERROR 23000: Duplicate entry '123456789034567891' for key 'a'

looks great :)

> +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 'mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm' 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);
> +
> +MyISAM file:         DATADIR/test/t1
> +Record format:       Packed
> +Character set:       latin1_swedish_ci (8)
> +Data records:                    7  Deleted blocks:                 0
> +Recordlength:                   20
> +
> +table description:
> +Key Start Len Index   Type
> +1   12    8   multip. ulonglong NULL       
> +#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`(65535))

I think there shouldn't be (65535) here

> +) 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`(65535))
> +) 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 `a` (`a`(65535)),
> +  UNIQUE KEY `db_row_hash_1` (`db_row_hash_1`)
> +) 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     0       clm     1       clm_changed     A       NULL    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           
> +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     0       a       1       a       A       NULL    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 ('Ä');

this should've failed, shouldn't it?

> +drop table t1;
> +create table t1 (a int primary key, b blob unique);
> +desc t1;
> +Field  Type    Null    Key     Default Extra
> +a      int(11) NO      PRI     NULL    
> +b      blob    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     0       PRIMARY 1       a       A       0       NULL    NULL            BTREE           
> +t1     0       b       1       b       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +insert into t1 values(1,1),(2,2),(3,3);
> +insert into t1 values(1,1);
> +ERROR 23000: Duplicate entry '1' for key 'b'
> +insert into t1 values(7,1);
> +ERROR 23000: Duplicate entry '1' for key 'b'
> +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',341,'fdf','gfgfgfg','hghgr'),('maria',345,'frter','dasd','utyuty'),
> +(123456789034567891,353534,53453453453456,64565464564564,45435345345345),
> +(123456789034567890,43545,657567567567,78967657567567,657567567567567676);
> +#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     0       a       1       a       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +t1     0       c       1       c       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +t1     0       d       1       d       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +t1     0       e       1       e       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +
> +MyISAM file:         DATADIR/test/t1
> +Record format:       Packed
> +Character set:       latin1_swedish_ci (8)
> +Data records:                    8  Deleted blocks:                 0
> +Recordlength:                 3072
> +
> +table description:
> +Key Start Len Index   Type
> +1   3063  8   multip. ulonglong NULL       
> +2   3055  8   multip. ulonglong NULL       
> +3   3047  8   multip. ulonglong NULL       
> +4   3039  8   multip. ulonglong prefix NULL

why "prefix" here? how is it different from others?

> +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  IS_GENERATED    GENERATION_EXPRESSION
> +def    test    t1      a       1       NULL    YES     blob    65535   65535   NULL    NULL    NULL    NULL    NULL    blob    UNI             select,insert,update,references         NEVER   NULL
> +def    test    t1      b       2       NULL    YES     int     NULL    NULL    10      0       NULL    NULL    NULL    int(11)                 select,insert,update,references         NEVER   NULL
> +def    test    t1      c       3       NULL    YES     blob    65535   65535   NULL    NULL    NULL    NULL    NULL    blob    UNI             select,insert,update,references         NEVER   NULL
> +def    test    t1      d       4       NULL    YES     text    65535   65535   NULL    NULL    NULL    latin1  latin1_swedish_ci       text    UNI             select,insert,update,references         NEVER   NULL
> +def    test    t1      e       5       NULL    YES     varchar 3000    3000    NULL    NULL    NULL    latin1  latin1_swedish_ci       varchar(3000)   UNI             select,insert,update,references         NEVER   NULL
> +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      0       test    a       1       a       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +def    test    t1      0       test    c       1       c       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +def    test    t1      0       test    d       1       d       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +def    test    t1      0       test    e       1       e       A       NULL    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_1 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 341     fdf     gfgfgfg hghgr
> +maria  345     frter   dasd    utyuty
> +123456789034567891     353534  53453453453456  64565464564564  45435345345345
> +123456789034567890     43545   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 'sachin' for key 'a'
> +insert into t1 values(1234567890345671890,4353451,6575675675617,789676575675617,657567567567567676);
> +ERROR 23000: Duplicate entry '657567567567567676' 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 341     fdf     gfgfgfg hghgr
> +maria  345     frter   dasd    utyuty
> +123456789034567891     353534  53453453453456  64565464564564  45435345345345
> +123456789034567890     43545   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',2995));
> +insert into t1 values(repeat('m',4000*11),10,repeat('s',4000*11),repeat('s',4000*11),repeat('s',2995));
> +ERROR 23000: Duplicate entry 'ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss' for key 'e'
> +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`(65535)),
> +  UNIQUE KEY `c` (`c`(65535)),
> +  UNIQUE KEY `d` (`d`(65535)),
> +  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`(65535)),
> +  UNIQUE KEY `c` (`c`(65535)),
> +  UNIQUE KEY `d` (`d`(65535)),
> +  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 `a` (`a`(65535)),
> +  UNIQUE KEY `c` (`c`(65535)),
> +  UNIQUE KEY `d` (`d`(65535)),
> +  UNIQUE KEY `e` (`e`),
> +  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`)
> +) 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;

"this should not" ?

> +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 `d` (`d`(65535)),
> +  UNIQUE KEY `e` (`e`),
> +  UNIQUE KEY `db_row_hash_1` (`db_row_hash_1`),
> +  UNIQUE KEY `db_row_hash_2` (`db_row_hash_2`)
> +) 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       d       1       d       A       NULL    65535   NULL    YES     HASH_INDEX              
> +t1     0       e       1       e       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +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           
> +#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 `d` (`d`(65535)),
> +  UNIQUE KEY `e` (`e`),
> +  UNIQUE KEY `db_row_hash_1` (`db_row_hash_1`),
> +  UNIQUE KEY `db_row_hash_2` (`db_row_hash_2`),
> +  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       d       1       d       A       NULL    65535   NULL    YES     HASH_INDEX              
> +t1     0       e       1       e       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +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       a       1       a       A       NULL    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 `d` (`d`(65535)),
> +  UNIQUE KEY `e` (`e`),
> +  UNIQUE KEY `db_row_hash_1` (`db_row_hash_1`),
> +  UNIQUE KEY `db_row_hash_2` (`db_row_hash_2`),
> +  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       d       1       d       A       NULL    65535   NULL    YES     HASH_INDEX              
> +t1     0       e       1       e       A       NULL    NULL    NULL    YES     BTREE           
> +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       a       1       a       A       NULL    NULL    NULL    YES     BTREE           
> +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 `d` (`d`(65535)),
> +  UNIQUE KEY `e` (`e`),
> +  UNIQUE KEY `db_row_hash_1` (`db_row_hash_1`),
> +  UNIQUE KEY `db_row_hash_2` (`db_row_hash_2`),
> +  UNIQUE KEY `a` (`a`),
> +  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       d       1       d       A       NULL    65535   NULL    YES     HASH_INDEX              
> +t1     0       e       1       e       A       NULL    NULL    NULL    YES     BTREE           
> +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       a       1       a       A       NULL    NULL    NULL    YES     BTREE           
> +t1     0       clm1    1       clm_changed1    A       NULL    NULL    NULL    YES     HASH_INDEX              
> +t1     0       clm2    1       clm_changed2    A       NULL    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 `d` (`d`(65535)),
> +  UNIQUE KEY `e` (`e`),
> +  UNIQUE KEY `db_row_hash_1` (`db_row_hash_1`),
> +  UNIQUE KEY `db_row_hash_2` (`db_row_hash_2`),
> +  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       d       1       d       A       NULL    65535   NULL    YES     HASH_INDEX              
> +t1     0       e       1       e       A       NULL    NULL    NULL    YES     BTREE           
> +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       a       1       a       A       NULL    NULL    NULL    YES     BTREE           
> +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(b,d,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')
> +,(null,null,null,null,null,null,null,null),(null,null,null,null,null,null,null,null);
> +#table structure;
> +desc t1;
> +Field  Type    Null    Key     Default Extra
> +a      blob    YES     MUL     NULL    
> +b      int(11) YES     MUL     NULL    
> +c      varchar(2000)   YES     MUL     NULL    
> +d      text    YES             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` (`a`,`b`,`c`),
> +  UNIQUE KEY `c` (`c`,`d`,`e`),
> +  UNIQUE KEY `e` (`e`,`f`,`g`,`h`),
> +  UNIQUE KEY `b` (`b`,`d`,`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       1       a       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +t1     0       a       2       b       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +t1     0       a       3       c       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +t1     0       c       1       c       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +t1     0       c       2       d       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       c       3       e       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       e       1       e       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       e       2       f       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       e       3       g       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       e       4       h       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       b       1       b       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       b       2       d       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       b       3       g       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       b       4       h       A       0       NULL    NULL    YES     HASH_INDEX              
> +
> +MyISAM file:         DATADIR/test/t1
> +Record format:       Packed
> +Character set:       latin1_swedish_ci (8)
> +Data records:                    9  Deleted blocks:                 0
> +Recordlength:                 5092
> +
> +table description:
> +Key Start Len Index   Type
> +1   5081  8   multip. ulonglong prefix NULL
> +2   5073  8   multip. ulonglong prefix NULL
> +3   5065  8   multip. ulonglong prefix NULL
> +4   5057  8   multip. ulonglong NULL       
> +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  IS_GENERATED    GENERATION_EXPRESSION
> +def    test    t1      a       1       NULL    YES     blob    65535   65535   NULL    NULL    NULL    NULL    NULL    blob    MUL             select,insert,update,references         NEVER   NULL
> +def    test    t1      b       2       NULL    YES     int     NULL    NULL    10      0       NULL    NULL    NULL    int(11) MUL             select,insert,update,references         NEVER   NULL
> +def    test    t1      c       3       NULL    YES     varchar 2000    2000    NULL    NULL    NULL    latin1  latin1_swedish_ci       varchar(2000)   MUL             select,insert,update,references         NEVER   NULL
> +def    test    t1      d       4       NULL    YES     text    65535   65535   NULL    NULL    NULL    latin1  latin1_swedish_ci       text                    select,insert,update,references         NEVER   NULL
> +def    test    t1      e       5       NULL    YES     varchar 3000    3000    NULL    NULL    NULL    latin1  latin1_swedish_ci       varchar(3000)   MUL             select,insert,update,references         NEVER   NULL
> +def    test    t1      f       6       NULL    YES     longblob        4294967295      4294967295      NULL    NULL    NULL    NULL    NULL    longblob                        select,insert,update,references         NEVER   NULL
> +def    test    t1      g       7       NULL    YES     int     NULL    NULL    10      0       NULL    NULL    NULL    int(11)                 select,insert,update,references         NEVER   NULL
> +def    test    t1      h       8       NULL    YES     text    65535   65535   NULL    NULL    NULL    latin1  latin1_swedish_ci       text                    select,insert,update,references         NEVER   NULL
> +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      0       test    a       1       a       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +def    test    t1      0       test    a       2       b       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +def    test    t1      0       test    a       3       c       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +def    test    t1      0       test    c       1       c       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +def    test    t1      0       test    c       2       d       A       0       NULL    NULL    YES     HASH_INDEX              
> +def    test    t1      0       test    c       3       e       A       0       NULL    NULL    YES     HASH_INDEX              
> +def    test    t1      0       test    e       1       e       A       0       NULL    NULL    YES     HASH_INDEX              
> +def    test    t1      0       test    e       2       f       A       0       NULL    NULL    YES     HASH_INDEX              
> +def    test    t1      0       test    e       3       g       A       0       NULL    NULL    YES     HASH_INDEX              
> +def    test    t1      0       test    e       4       h       A       0       NULL    NULL    YES     HASH_INDEX              
> +def    test    t1      0       test    b       1       b       A       0       NULL    NULL    YES     HASH_INDEX              
> +def    test    t1      0       test    b       2       d       A       0       NULL    NULL    YES     HASH_INDEX              
> +def    test    t1      0       test    b       3       g       A       0       NULL    NULL    YES     HASH_INDEX              
> +def    test    t1      0       test    b       4       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       def     test    t1      a       1       NULL    NULL    NULL    NULL
> +def    test    a       def     test    t1      b       2       NULL    NULL    NULL    NULL
> +def    test    a       def     test    t1      c       3       NULL    NULL    NULL    NULL
> +def    test    c       def     test    t1      c       1       NULL    NULL    NULL    NULL
> +def    test    c       def     test    t1      d       2       NULL    NULL    NULL    NULL
> +def    test    c       def     test    t1      e       3       NULL    NULL    NULL    NULL
> +def    test    e       def     test    t1      e       1       NULL    NULL    NULL    NULL
> +def    test    e       def     test    t1      f       2       NULL    NULL    NULL    NULL
> +def    test    e       def     test    t1      g       3       NULL    NULL    NULL    NULL
> +def    test    e       def     test    t1      h       4       NULL    NULL    NULL    NULL
> +def    test    b       def     test    t1      b       1       NULL    NULL    NULL    NULL
> +def    test    b       def     test    t1      d       2       NULL    NULL    NULL    NULL
> +def    test    b       def     test    t1      g       3       NULL    NULL    NULL    NULL
> +def    test    b       def     test    t1      h       4       NULL    NULL    NULL    NULL
> +# table select we should not be able to see db_row_hash_1 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
> +NULL   NULL    NULL    NULL    NULL    NULL    NULL    NULL
> +NULL   NULL    NULL    NULL    NULL    NULL    NULL    NULL
> +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'
> +insert into t1 values(0,0,1,1,1,0,0,0);
> +ERROR 23000: Duplicate entry '1-1-1' for key 'c'
> +insert into t1 values(0,0,0,0,1,1,1,1);
> +ERROR 23000: Duplicate entry '1-1-1-1' for key 'e'
> +insert into t1 values(1,1,1,1,1,0,0,0);
> +ERROR 23000: Duplicate entry '1-1-1' for key 'a'
> +insert into t1 values(0,0,0,0,1,1,1,1);
> +ERROR 23000: Duplicate entry '1-1-1-1' for key 'e'
> +insert into t1 values(1,1,1,1,1,1,1,1);
> +ERROR 23000: Duplicate entry '1-1-1' for key 'a'
> +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` (`a`,`b`,`c`),
> +  UNIQUE KEY `c` (`c`,`d`,`e`),
> +  UNIQUE KEY `e` (`e`,`f`,`g`,`h`),
> +  UNIQUE KEY `b` (`b`,`d`,`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` (`a`(65535),`b`,`c`),
> +  UNIQUE KEY `c` (`c`,`d`(65535),`e`),
> +  UNIQUE KEY `e` (`e`,`f`,`g`,`h`(65535)),
> +  UNIQUE KEY `b` (`b`,`d`(65535),`g`,`h`(65535))
> +) 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       1       a       A       NULL    65535   NULL    YES     HASH_INDEX              
> +t1     0       a       2       b       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +t1     0       a       3       c       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +t1     0       c       1       c       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +t1     0       c       2       d       A       0       65535   NULL    YES     HASH_INDEX              
> +t1     0       c       3       e       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       e       1       e       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       e       2       f       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       e       3       g       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       e       4       h       A       0       65535   NULL    YES     HASH_INDEX              
> +t1     0       b       1       b       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       b       2       d       A       0       65535   NULL    YES     HASH_INDEX              
> +t1     0       b       3       g       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       b       4       h       A       0       65535   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` (`a`(65535),`b`,`c`),
> +  UNIQUE KEY `c` (`c`,`d`(65535),`e`),
> +  UNIQUE KEY `e` (`e`,`f`,`g`,`h`(65535)),
> +  UNIQUE KEY `b` (`b`,`d`(65535),`g`,`h`(65535))
> +) 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       1       a       A       NULL    65535   NULL    YES     HASH_INDEX              
> +t1     0       a       2       b       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +t1     0       a       3       c       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +t1     0       c       1       c       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +t1     0       c       2       d       A       0       65535   NULL    YES     HASH_INDEX              
> +t1     0       c       3       e       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       e       1       e       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       e       2       f       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       e       3       g       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       e       4       h       A       0       65535   NULL    YES     HASH_INDEX              
> +t1     0       b       1       b       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       b       2       d       A       0       65535   NULL    YES     HASH_INDEX              
> +t1     0       b       3       g       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       b       4       h       A       0       65535   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 `e` (`e`,`f`,`g`,`h`(65535)),
> +  UNIQUE KEY `a` (`aa`(65535),`bb`,`c`),
> +  UNIQUE KEY `c` (`c`,`dd`(65535),`e`),
> +  UNIQUE KEY `b` (`bb`,`dd`(65535),`g`,`h`(65535))
> +) 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       e       1       e       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +t1     0       e       2       f       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +t1     0       e       3       g       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +t1     0       e       4       h       A       NULL    65535   NULL    YES     HASH_INDEX              
> +t1     0       a       1       aa      A       0       65535   NULL    YES     HASH_INDEX              
> +t1     0       a       2       bb      A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       a       3       c       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       c       1       c       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       c       2       dd      A       0       65535   NULL    YES     HASH_INDEX              
> +t1     0       c       3       e       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       b       1       bb      A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       b       2       dd      A       0       65535   NULL    YES     HASH_INDEX              
> +t1     0       b       3       g       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       b       4       h       A       0       65535   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 `e` (`e`,`f`,`g`,`h`(65535)),
> +  UNIQUE KEY `a` (`a`(65535),`b`,`c`),
> +  UNIQUE KEY `c` (`c`,`d`(65535),`e`),
> +  UNIQUE KEY `b` (`b`,`d`(65535),`g`,`h`(65535))
> +) 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       e       1       e       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +t1     0       e       2       f       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +t1     0       e       3       g       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +t1     0       e       4       h       A       NULL    65535   NULL    YES     HASH_INDEX              
> +t1     0       a       1       a       A       0       65535   NULL    YES     HASH_INDEX              
> +t1     0       a       2       b       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       a       3       c       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       c       1       c       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       c       2       d       A       0       65535   NULL    YES     HASH_INDEX              
> +t1     0       c       3       e       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       b       1       b       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       b       2       d       A       0       65535   NULL    YES     HASH_INDEX              
> +t1     0       b       3       g       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       b       4       h       A       0       65535   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 varchar(20) , modify column b varchar(20) , modify column c varchar(20);
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `a` varchar(20) DEFAULT NULL,
> +  `b` varchar(20) DEFAULT NULL,
> +  `c` varchar(20) 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 `e` (`e`,`f`,`g`,`h`(65535)),
> +  UNIQUE KEY `a` (`a`,`b`,`c`),
> +  UNIQUE KEY `c` (`c`,`d`(65535),`e`),
> +  UNIQUE KEY `b` (`b`,`d`(65535),`g`,`h`(65535))
> +) 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       e       1       e       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +t1     0       e       2       f       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +t1     0       e       3       g       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +t1     0       e       4       h       A       NULL    65535   NULL    YES     HASH_INDEX              
> +t1     0       a       1       a       A       NULL    NULL    NULL    YES     BTREE           
> +t1     0       a       2       b       A       NULL    NULL    NULL    YES     BTREE           
> +t1     0       a       3       c       A       0       NULL    NULL    YES     BTREE           
> +t1     0       c       1       c       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       c       2       d       A       0       65535   NULL    YES     HASH_INDEX              
> +t1     0       c       3       e       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       b       1       b       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       b       2       d       A       0       65535   NULL    YES     HASH_INDEX              
> +t1     0       b       3       g       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       b       4       h       A       0       65535   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 `e` (`e`,`f`,`g`,`h`(65535)),
> +  UNIQUE KEY `a` (`a`,`b`,`c`),
> +  UNIQUE KEY `c` (`c`,`d`(65535),`e`),
> +  UNIQUE KEY `b` (`b`,`d`(65535),`g`,`h`(65535))
> +) 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       e       1       e       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +t1     0       e       2       f       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +t1     0       e       3       g       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +t1     0       e       4       h       A       NULL    65535   NULL    YES     HASH_INDEX              
> +t1     0       a       1       a       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       a       2       b       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       a       3       c       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       c       1       c       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       c       2       d       A       0       65535   NULL    YES     HASH_INDEX              
> +t1     0       c       3       e       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       b       1       b       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       b       2       d       A       0       65535   NULL    YES     HASH_INDEX              
> +t1     0       b       3       g       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       b       4       h       A       0       65535   NULL    YES     HASH_INDEX              
> +#try to delete blob column in unique;
> +truncate table t1;
> +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 `e` (`e`,`f`,`g`,`h`(65535)),
> +  UNIQUE KEY `a` (`a`,`b`,`c`),
> +  UNIQUE KEY `c` (`c`,`d`(65535),`e`),
> +  UNIQUE KEY `b` (`b`,`d`(65535),`g`,`h`(65535))
> +) 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       e       1       e       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +t1     0       e       2       f       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +t1     0       e       3       g       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +t1     0       e       4       h       A       NULL    65535   NULL    YES     HASH_INDEX              
> +t1     0       a       1       a       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       a       2       b       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       a       3       c       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       c       1       c       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       c       2       d       A       0       65535   NULL    YES     HASH_INDEX              
> +t1     0       c       3       e       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       b       1       b       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       b       2       d       A       0       65535   NULL    YES     HASH_INDEX              
> +t1     0       b       3       g       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       b       4       h       A       0       65535   NULL    YES     HASH_INDEX              
> +#now try to delete keys;
> +alter table t1 drop key c, drop key e;
> +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` (`a`(65535),`b`(65535),`c`(65535)),
> +  UNIQUE KEY `b` (`b`(65535),`d`(65535),`g`,`h`(65535))
> +) 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       1       a       A       NULL    65535   NULL    YES     HASH_INDEX              
> +t1     0       a       2       b       A       NULL    65535   NULL    YES     HASH_INDEX              
> +t1     0       a       3       c       A       0       65535   NULL    YES     HASH_INDEX              
> +t1     0       b       1       b       A       0       65535   NULL    YES     HASH_INDEX              
> +t1     0       b       2       d       A       0       65535   NULL    YES     HASH_INDEX              
> +t1     0       b       3       g       A       0       NULL    NULL    YES     HASH_INDEX              
> +t1     0       b       4       h       A       0       65535   NULL    YES     HASH_INDEX              
> +drop table t1;
> +#now alter table containing some data basically some tests with ignore;
> +create table t1 (a blob);
> +insert into t1 values(1),(2),(3);
> +#normal alter table;
> +alter table t1 add unique key(a);
> +alter table t1 drop key a;
> +truncate table t1;
> +insert into t1 values(1),(1),(2),(2),(3);
> +alter table t1 add unique key(a);
> +ERROR 23000: Duplicate entry '1' for key 'a'
> +alter ignore table t1 add unique key(a);
> +select * from t1;
> +a
> +1
> +2
> +3
> +insert into t1 values(1);
> +ERROR 23000: Duplicate entry '1' for key 'a'
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `a` blob DEFAULT NULL,
> +  UNIQUE KEY `a` (`a`(65535))
> +) 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       1       a       A       NULL    65535   NULL    YES     HASH_INDEX              
> +drop table t1;
> +#Now with multiple keys;
> +create table t1(a blob , b blob, c blob , d blob , e int);
> +insert into t1 values (1,1,1,1,1);
> +insert into t1 values (1,1,1,1,1);
> +insert into t1 values (2,1,1,1,1);
> +insert into t1 values (2,2,2,2,2);
> +insert into t1 values (3,3,4,4,4);
> +insert into t1 values (4,4,4,4,4);
> +alter table t1 add unique key(a,c), add unique key(b,d), add unique key(e);
> +ERROR 23000: Duplicate entry '1-1' for key 'a'
> +alter ignore  table t1 add unique key(a,c), add unique key(b,d), add unique key(e);
> +select * from t1;
> +a      b       c       d       e
> +1      1       1       1       1
> +2      2       2       2       2
> +3      3       4       4       4
> +insert into t1 values (1,12,1,13,14);
> +ERROR 23000: Duplicate entry '1-1' for key 'a'
> +insert into t1 values (12,1,14,1,14);
> +ERROR 23000: Duplicate entry '1-1' for key 'b'
> +insert into t1 values (13,12,13,14,4);
> +ERROR 23000: Duplicate entry '4' for key 'e'
> +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` int(11) DEFAULT NULL,
> +  UNIQUE KEY `a` (`a`(65535),`c`(65535)),
> +  UNIQUE KEY `b` (`b`(65535),`d`(65535)),
> +  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       a       1       a       A       NULL    65535   NULL    YES     HASH_INDEX              
> +t1     0       a       2       c       A       NULL    65535   NULL    YES     HASH_INDEX              
> +t1     0       b       1       b       A       NULL    65535   NULL    YES     HASH_INDEX              
> +t1     0       b       2       d       A       0       65535   NULL    YES     HASH_INDEX              
> +t1     0       e       1       e       A       0       NULL    NULL    YES     BTREE           
> +drop table t1;
> +#visibility of db_row_hash 
> +create table t1 (a blob unique , b blob unique);
> +desc t1;
> +Field  Type    Null    Key     Default Extra
> +a      blob    YES     UNI     NULL    
> +b      blob    YES     UNI     NULL    
> +insert into t1 values(1,19);
> +insert into t1 values(2,29);
> +insert into t1 values(3,39);
> +insert into t1 values(4,49);
> +create table t2 (DB_ROW_HASH_1 int, DB_ROW_HASH_2 int);
> +insert into t2 values(11,1);
> +insert into t2 values(22,2);
> +insert into t2 values(33,3);
> +insert into t2 values(44,4);
> +select * from t1;
> +a      b
> +1      19
> +2      29
> +3      39
> +4      49
> +select * from t2;
> +DB_ROW_HASH_1  DB_ROW_HASH_2
> +11     1
> +22     2
> +33     3
> +44     4
> +select DB_ROW_HASH_1, DB_ROW_HASH_2 from t1;
> +ERROR 42S22: Unknown column 'DB_ROW_HASH_1' in 'field list'
> +#bug
> +select DB_ROW_HASH_1, DB_ROW_HASH_2 from t1,t2;
> +DB_ROW_HASH_1  DB_ROW_HASH_2
> +11     1
> +11     1
> +11     1
> +11     1
> +22     2
> +22     2
> +22     2
> +22     2
> +33     3
> +33     3
> +33     3
> +33     3
> +44     4
> +44     4
> +44     4
> +44     4
> +select * from t1 where DB_ROW_HASH_1 in (select DB_ROW_HASH_1 from t2);
> +ERROR 42S22: Unknown column 'DB_ROW_HASH_1' in 'IN/ALL/ANY subquery'
> +select DB_ROW_HASH_1, DB_ROW_HASH_2 from t1,t2 where DB_ROW_HASH_1 in (select DB_ROW_HASH_1 from t2);
> +DB_ROW_HASH_1  DB_ROW_HASH_2
> +11     1
> +22     2
> +33     3
> +44     4
> +11     1
> +22     2
> +33     3
> +44     4
> +11     1
> +22     2
> +33     3
> +44     4
> +11     1
> +22     2
> +33     3
> +44     4
> +select * from t2 where DB_ROW_HASH_1 in (select DB_ROW_HASH_1 from t1);
> +DB_ROW_HASH_1  DB_ROW_HASH_2
> +11     1
> +22     2
> +33     3
> +44     4
> +select DB_ROW_HASH_1 from t1,t2 where t1.DB_ROW_HASH_1 = t2.DB_ROW_HASH_2;
> +ERROR 42S22: Unknown column 't1.DB_ROW_HASH_1' in 'where clause'
> +select DB_ROW_HASH_1 from t1 inner join t2 on t1.a = t2.DB_ROW_HASH_2;
> +DB_ROW_HASH_1
> +11
> +22
> +33
> +44
> +drop table t1,t2;
> +#very long blob entry;
> +SET @@GLOBAL.max_allowed_packet=67108864;
> +connect  'newcon', localhost, root,,;
> +connection newcon;
> +show variables like 'max_allowed_packet';
> +Variable_name  Value
> +max_allowed_packet     67108864
> +create table t1(a longblob unique, b longblob , c longblob , unique(b,c));
> +desc t1;
> +Field  Type    Null    Key     Default Extra
> +a      longblob        YES     UNI     NULL    
> +b      longblob        YES     MUL     NULL    
> +c      longblob        YES             NULL    
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `a` longblob DEFAULT NULL,
> +  `b` longblob DEFAULT NULL,
> +  `c` longblob DEFAULT NULL,
> +  UNIQUE KEY `a` (`a`),
> +  UNIQUE KEY `b` (`b`,`c`)
> +) 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       1       a       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +t1     0       b       1       b       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +t1     0       b       2       c       A       0       NULL    NULL    YES     HASH_INDEX              
> +insert into t1 values(concat(repeat('sachin',10000000),'1'),concat(repeat('sachin',10000000),'1'),
> +concat(repeat('sachin',10000000),'1'));
> +insert into t1 values(concat(repeat('sachin',10000000),'2'),concat(repeat('sachin',10000000),'2'),
> +concat(repeat('sachin',10000000),'1'));
> +insert into t1 values(concat(repeat('sachin',10000000),'2'),concat(repeat('sachin',10000000),'2'),
> +concat(repeat('sachin',10000000),'4'));
> +ERROR 23000: Duplicate entry 'sachinsachinsachinsachinsachinsachinsachinsachinsachinsachinsach' for key 'a'
> +insert into t1 values(concat(repeat('sachin',10000000),'3'),concat(repeat('sachin',10000000),'1'),
> +concat(repeat('sachin',10000000),'1'));
> +ERROR 23000: Duplicate entry 'sachinsachinsachinsachinsachinsachinsachinsachinsachinsachinsach' for key 'b'
> +drop table t1;
> +#long key unique with different key length
> +create table t1(a blob, unique(a(3000)));
> +desc t1;
> +Field  Type    Null    Key     Default Extra
> +a      blob    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     0       a       1       a       A       NULL    3000    NULL    YES     HASH_INDEX              
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `a` blob DEFAULT NULL,
> +  UNIQUE KEY `a` (`a`(3000))
> +) ENGINE=MyISAM DEFAULT CHARSET=latin1
> +insert into t1 value(concat(repeat('s',3000),'1'));
> +insert into t1 value(concat(repeat('s',3000),'2'));
> +ERROR 23000: Duplicate entry 'ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss' for key 'a'
> +insert into t1 value(concat(repeat('a',3000),'2'));
> +drop table t1;
> +create table t1(a varchar(4000), b longblob , c varchar(5000), d longblob, 
> +unique(a(3500), b(1000000)), unique(c(4500), d(10000000)));
> +desc t1;
> +Field  Type    Null    Key     Default Extra
> +a      varchar(4000)   YES     MUL     NULL    
> +b      longblob        YES             NULL    
> +c      varchar(5000)   YES     MUL     NULL    
> +d      longblob        YES             NULL    
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `a` varchar(4000) DEFAULT NULL,
> +  `b` longblob DEFAULT NULL,
> +  `c` varchar(5000) DEFAULT NULL,
> +  `d` longblob DEFAULT NULL,
> +  UNIQUE KEY `a` (`a`(3500),`b`),
> +  UNIQUE KEY `c` (`c`(4500),`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       a       1       a       A       NULL    3500    NULL    YES     HASH_INDEX              
> +t1     0       a       2       b       A       NULL    NULL    NULL    YES     HASH_INDEX              
> +t1     0       c       1       c       A       0       4500    NULL    YES     HASH_INDEX              
> +t1     0       c       2       d       A       0       NULL    NULL    YES     HASH_INDEX              
> +drop table t1;
> +disconnect newcon;
> +connection default;
> +SET @@GLOBAL.max_allowed_packet=4194304;
> +#ext bug
> +create table t1(a int primary key, b blob unique, c int, d blob , index(c));
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `a` int(11) NOT NULL,
> +  `b` blob DEFAULT NULL,
> +  `c` int(11) DEFAULT NULL,
> +  `d` blob DEFAULT NULL,
> +  PRIMARY KEY (`a`),
> +  UNIQUE KEY `b` (`b`),
> +  KEY `c` (`c`)
> +) ENGINE=MyISAM DEFAULT CHARSET=latin1
> +insert into t1 values(1,23,1,33);
> +insert into t1 values(2,23,1,33);
> +ERROR 23000: Duplicate entry '23' for key 'b'
> +drop table t1;
> +create table t2 (a blob unique , c int , index(c));
> +show create table t2;
> +Table  Create Table
> +t2     CREATE TABLE `t2` (
> +  `a` blob DEFAULT NULL,
> +  `c` int(11) DEFAULT NULL,
> +  UNIQUE KEY `a` (`a`),
> +  KEY `c` (`c`)
> +) ENGINE=MyISAM DEFAULT CHARSET=latin1
> +insert into t2 values(1,1);
> +insert into t2 values(2,1);
> +drop table t2;
> +#not null test //todo solve warnings
> +create table t1(a blob unique not null);
> +desc t1;
> +Field  Type    Null    Key     Default Extra
> +a      blob    NO      PRI     NULL    
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `a` blob NOT NULL,
> +  UNIQUE KEY `a` (`a`)
> +) ENGINE=MyISAM DEFAULT CHARSET=latin1
> +insert into t1 values(1);
> +insert into t1 values(3);
> +insert into t1 values(1);
> +ERROR 23000: Duplicate entry '1' for key 'a'
> +drop table t1;
> +create table t1(a int primary key, b blob unique , c blob unique not null);
> +insert into t1 values(1,1,1);
> +insert into t1 values(2,1,2);
> +ERROR 23000: Duplicate entry '1' for key 'b'
> +insert into t1 values(3,3,1);
> +ERROR 23000: Duplicate entry '1' for key 'c'
> +drop table t1;
> +create table t1 (a blob unique not null, b blob not null, c blob not null, unique(b,c));
> +desc t1;
> +Field  Type    Null    Key     Default Extra
> +a      blob    NO      PRI     NULL    
> +b      blob    NO      MUL     NULL    
> +c      blob    NO              NULL    
> +show create table t1;
> +Table  Create Table
> +t1     CREATE TABLE `t1` (
> +  `a` blob NOT NULL,
> +  `b` blob NOT NULL,
> +  `c` blob NOT NULL,
> +  UNIQUE KEY `a` (`a`),
> +  UNIQUE KEY `b` (`b`,`c`)
> +) ENGINE=MyISAM DEFAULT CHARSET=latin1
> +insert into t1 values (1, 2, 3);
> +insert into t1 values (2, 1, 3);
> +insert into t1 values (2, 1, 3);
> +ERROR 23000: Duplicate entry '2' for key 'a'
> +drop table t1;
> +set @@GLOBAL.max_allowed_packet= @allowed_packet;
> diff --git a/sql/field.h b/sql/field.h
> index b6f28808e2e..13eea28fe8a 100644
> --- a/sql/field.h
> +++ b/sql/field.h
> @@ -539,6 +539,7 @@ class Virtual_column_info: public Sql_alloc
>    Item *expr;
>    LEX_CSTRING name;                             /* Name of constraint */
>    uint flags;
> +  LEX_CSTRING hash_expr;

It is not a good idea to put your hash-unique-constraint specific
data into a common Virtual_column_info.

Luckily, you don't need it. Just like "current_timestamp()" expression
is generated on the fly as needed in parse_vcol_defs(), you can
generate the hash expression there too, no need to do it
in TABLE_SHARE::init_from_binary_frm_image().

So, just remove hash_expr.

>  
>    Virtual_column_info()
>    : vcol_type((enum_vcol_info_type)VCOL_TYPE_NONE),
> @@ -681,7 +688,7 @@ class Field: public Value_source
>      GEOM_MULTIPOINT = 4, GEOM_MULTILINESTRING = 5, GEOM_MULTIPOLYGON = 6,
>      GEOM_GEOMETRYCOLLECTION = 7
>    };
> -  enum imagetype { itRAW, itMBR};
> +  enum imagetype { itRAW, itMBR, itHASH};

itHASH isn't used anywhere in your patch :)

>  
>    utype                unireg_check;
>    uint32       field_length;           // Length of field
> diff --git a/sql/field.cc b/sql/field.cc
> index dc854826ed6..f75f52141e3 100644
> --- a/sql/field.cc
> +++ b/sql/field.cc
> @@ -9822,7 +9822,7 @@ int Field_bit::key_cmp(const uchar *str, uint length)
>  }
>  
>  
> -int Field_bit::cmp_offset(uint row_offset)
> +int Field_bit::cmp_offset(long row_offset)

may be my_ptrdiff_t ?

>  {
>    if (bit_len)
>    {
> diff --git a/sql/item_func.h b/sql/item_func.h
> index 3b6cb4ceeac..0391de0c5ad 100644
> --- a/sql/item_func.h
> +++ b/sql/item_func.h
> @@ -803,6 +803,19 @@ class Item_long_func: public Item_int_func
>  };
>  
>  
> +class Item_func_hash: public Item_int_func
> +{
> +public:
> +  Item_func_hash(THD *thd, List<Item> &item): Item_int_func(thd, item)
> +  {}
> +  longlong val_int();
> +  void fix_length_and_dec();
> +  const Type_handler *type_handler() const { return &type_handler_long; }
> +  Item *get_copy(THD *thd)
> +  { return get_item_copy<Item_func_hash>(thd, this); }
> +  const char *func_name() const { return "HASH"; }

is it a user visible function? Can one write

    SELECT HASH(a) FROM t1 ?

looks like yes, so
1. please add tests for it
2. we need to document what hash function, exactly, is used.
3. May be better to call it MARIADB_HASH? to highlight its internal-use
   nature and a home-baked hash function? And to reduce a chance for
   a collision with user defined functions.
4. An even better approach would be not to create any user visible function
   at all. Currently unpack_vcol_info_from_frm() calls the parser and
   then initializes vcol_info and calls fix_fields. If you split it in two
   you can do `new Item_func_hash` manually and skip the first part
   of unpack_vcol_info_from_frm(). And you won't need HASH to be user-visible.
   As a minor optimization, the same can be done for "current_timestamp()"

> +};
> +
>  class Item_longlong_func: public Item_int_func
>  {
>  public:
> diff --git a/sql/sql_show.cc b/sql/sql_show.cc
> index 4923c628bf9..c620ea23165 100644
> --- a/sql/sql_show.cc
> +++ b/sql/sql_show.cc
> @@ -2300,7 +2300,7 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet,
>        */
>        packet->append(STRING_WITH_LEN("PRIMARY KEY"));
>      }
> -    else if (key_info->flags & HA_NOSAME)
> +    else if (key_info->flags & HA_NOSAME || key_info->flags & HA_LONG_UNIQUE_HASH)

Is it needed? As far as I can see, you always set HA_NOSAME
whenever you set HA_LONG_UNIQUE_HASH.

>        packet->append(STRING_WITH_LEN("UNIQUE KEY "));
>      else if (key_info->flags & HA_FULLTEXT)
>        packet->append(STRING_WITH_LEN("FULLTEXT KEY "));
> diff --git a/include/my_base.h b/include/my_base.h
> index c36072c0bfa..ba17f8d80dc 100644
> --- a/include/my_base.h
> +++ b/include/my_base.h
> @@ -290,6 +291,11 @@ enum ha_base_keytype {
>  #define HA_KEY_HAS_PART_KEY_SEG 65536
>  /* Internal Flag Can be calcaluted */
>  #define HA_INVISIBLE_KEY 2<<18
> +/*
> +   Some more flags for keys  these are not stored in
> +   frm it is calculated on the fly in init_from_binary_frm_image
> +*/

1. I don't think you need to make the same comment more verbose every time
you repeat it :) Just say, like

 #define HA_INVISIBLE_KEY      2<<18  /* this is calculated too */
 #define HA_LONG_UNIQUE_HASH   2<<19  /* this is calculated too */

2. Do you need a separate flag for that, just HA_INVISIBLE_KEY isn't enough?

> +#define HA_LONG_UNIQUE_HASH   2<<19
>         /* Automatic bits in key-flag */
>  
>  #define HA_SPACE_PACK_USED      4      /* Test for if SPACE_PACK used */
> @@ -317,6 +323,13 @@ enum ha_base_keytype {
>  #define HA_BIT_PART            1024
>  #define HA_CAN_MEMCMP           2048 /* internal, never stored in frm */
>  
> +/*
> +  Used for key parts whole length is greater then > file->max_key_part_length
> +  Only used for HA_LONG_UNIQUE_HASH keys
> +*/ //TODO a better name ??
> +#define HA_HASH_KEY_PART_FLAG   4096
> +/* Field need to be frees externally */
> +#define HA_FIELD_EX_FREED       8192

Okay, this is a weird name, agree. But it is not used anywere, so
there's an easy solution :)

>         /* optionbits for database */
>  #define HA_OPTION_PACK_RECORD          1U
>  #define HA_OPTION_PACK_KEYS            2U
> diff --git a/sql/table.h b/sql/table.h
> index 785fd9f3427..9ed7fcd7beb 100644
> --- a/sql/table.h
> +++ b/sql/table.h
> @@ -346,9 +346,39 @@ enum field_visibility_t {
>    INVISIBLE_FULL
>  };
>  
> -#define INVISIBLE_MAX_BITS 3
> +#define INVISIBLE_MAX_BITS              3
> +/* We will store the info into 3rd bit if field is hash field */
> +#define HASH_FIELD_MASK                 15
> +#define HASH_FIELD_MASK_SHIFT           4
> +#define HA_HASH_FIELD_LENGTH            8
> +#define HA_HASH_KEY_LENGTH_WITHOUT_NULL 8
> +#define HA_HASH_KEY_LENGTH_WITH_NULL    9
> +//TODO is this correct ? how about size of char ptr on 32/16 bit machine?

I don't understand that, sorry

> +#define HA_HASH_KEY_PART_LENGTH         4 + 8 // 4 for length , 8 for portable size of char ptr

you almost always should use parentheses in macro expressions

>  
> +const LEX_CSTRING ha_hash_str           {STRING_WITH_LEN("HASH")};

???
you create a copy of ha_hash_str symbol in every .o file that
included table.h?

>  
> +
> +int find_field_pos_in_hash(Item *hash_item, const char * field_name);
> +
> +int fields_in_hash_str(Item *hash_item);
> +
> +Field * field_ptr_in_hash_str(Item *hash_item, int index);
> +
> +int get_key_part_length(KEY *keyinfo, int index);
> +
> +void calc_hash_for_unique(ulong &nr1, ulong &nr2, String *str);
> +
> +void create_update_handler(THD *thd, TABLE *table);
> +
> +void delete_update_handler(THD *thd, TABLE *table);
> +
> +void setup_table_hash(TABLE *table);
> +
> +void re_setup_table(TABLE *table);
> +
> +int get_hash_key(THD *thd, TABLE *table, handler *h, uint key_index, uchar *rec_buf,
> +              uchar *key_buff);
>  /**
>    Category of table found in the table share.
>  */
> @@ -1094,6 +1124,17 @@ struct TABLE
>    THD  *in_use;                        /* Which thread uses this */
>  
>    uchar *record[3];                    /* Pointer to records */
> +  /* record buf to resolve hash collisions for long UNIQUE constraints */
> +  uchar *check_unique_buf;
> +  handler *update_handler;  /* Handler used in case of update */
> +  /*
> +     In the case of write row for long unique we are unable of find
> +     Whick key is voilated. Because we in case of duplicate hash 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

typos :)
"unable to find", "which", "violated"

> +   */
> +  int dupp_hash_key;
>    uchar *write_row_record;             /* Used as optimisation in
>                                            THD::write_row */
>    uchar *insert_values;                  /* used by INSERT ... UPDATE */
> @@ -2898,6 +2939,7 @@ void append_unescaped(String *res, const char *pos, size_t length);
>  void prepare_frm_header(THD *thd, uint reclength, uchar *fileinfo,
>                          HA_CREATE_INFO *create_info, uint keys, KEY *key_info);
>  const char *fn_frm_ext(const char *name);
> +void calc_hash_for_unique(ulong &nr1, ulong &nr2, String *str);

you have this prototype twice in table.h

>  
>  /* Check that the integer is in the internal */
>  static inline int set_zone(int nr,int min_zone,int max_zone)
> diff --git a/sql/table.cc b/sql/table.cc
> index 73b1a6bd9b2..8cd4db2844d 100644
> --- a/sql/table.cc
> +++ b/sql/table.cc
> @@ -747,7 +748,13 @@ static bool create_key_infos(const uchar *strpos, const uchar *frm_image_end,
>      if (i == 0)
>      {
>        ext_key_parts+= (share->use_ext_keys ? first_keyinfo->user_defined_key_parts*(keys-1) : 0); 
> +      /*
> +        Some keys can be HA_LONG_UNIQUE_HASH , but we do not know at this point ,
> +        how many ?, but will always be less than or equal to total num of
> +        keys. Each HA_LONG_UNIQUE_HASH key require one extra key_part in which
> +        it stored hash. On safe side we will allocate memory for each key.
> +       */
> -      n_length=keys * sizeof(KEY) + ext_key_parts * sizeof(KEY_PART_INFO);
> +      n_length=keys * sizeof(KEY) + (ext_key_parts +keys) * sizeof(KEY_PART_INFO);

Hmm, why wouldn't you store the number of HA_KEY_ALG_LONG_HASH keys in
EXTRA2_LONG_UNIQUES ? Then you'll know it here.

>        if (!(keyinfo= (KEY*) alloc_root(&share->mem_root,
>                                        n_length + len)))
>          return 1;
> @@ -798,6 +805,14 @@ static bool create_key_infos(const uchar *strpos, const uchar *frm_image_end,
>        }
>        key_part->store_length=key_part->length;
>      }
> +    if (keyinfo->algorithm == HA_KEY_ALG_LONG_HASH)
> +    {
> +      keyinfo->flags|= HA_LONG_UNIQUE_HASH | HA_NOSAME;
> +      keyinfo->key_length= 0;
> +      share->ext_key_parts++;
> +      // This empty key_part for storing Hash
> +      key_part++;
> +    }

so, you write keyinfo's for HA_LONG_UNIQUE_HASH keys into the frm?
why don't you write keysegs for them? I mean, it is not very logical.
I'd thought you won't write either keyinfos or keysegs. Or, okay, you could
write both. But only keyinfos and no keysegs? That's strange

>  
>      /*
>        Add primary key to end of extended keys for non unique keys for
> @@ -1143,13 +1159,21 @@ bool parse_vcol_defs(THD *thd, MEM_ROOT *mem_root, TABLE *table,
>      pos+= expr_length;
>    }
>  
> -  /* Now, initialize CURRENT_TIMESTAMP fields */
> +  /* Now, initialize CURRENT_TIMESTAMP and UNIQUE_INDEX_HASH_FIELD fields */
>    for (field_ptr= table->field; *field_ptr; field_ptr++)
>    {
>      Field *field= *field_ptr;
> -    if (field->has_default_now_unireg_check())
> +    if (field->vcol_info && (length = field->vcol_info->hash_expr.length))
>      {
>        expr_str.length(parse_vcol_keyword.length);
> +      expr_str.append((char*)field->vcol_info->hash_expr.str, length);
> +      vcol= unpack_vcol_info_from_frm(thd, mem_root, table, &expr_str,
> +                                    &(field->vcol_info), error_reported);

see above about not going through the parser for hash keys.

> +      *(vfield_ptr++)= *field_ptr;
> +
> +    }
> +    if (field->has_default_now_unireg_check())
> +    {
>        expr_str.append(STRING_WITH_LEN("current_timestamp("));
>        expr_str.append_ulonglong(field->decimals());
>        expr_str.append(')');
> @@ -2106,7 +2132,8 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
>        uchar flags= *extra2_field_flags++;
>        if (flags & VERS_OPTIMIZED_UPDATE)
>          reg_field->flags|= VERS_UPDATE_UNVERSIONED_FLAG;
> -
> +      if (flags & EXTRA2_LONG_UNIQUE_HASH_FIELD)
> +        reg_field->flags|= LONG_UNIQUE_HASH_FIELD;

so, you write LONG_UNIQUE_HASH_FIELD fields to frm too. Why?

>        reg_field->invisible= f_visibility(flags);
>      }
>      if (reg_field->invisible == INVISIBLE_USER)
> @@ -2350,6 +2438,8 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
>        key_part= keyinfo->key_part;
>        uint key_parts= share->use_ext_keys ? keyinfo->ext_key_parts :
>                                              keyinfo->user_defined_key_parts;
> +      if (keyinfo->flags & HA_LONG_UNIQUE_HASH)
> +        key_parts++;

key_parts++ ? Doesn't your HA_LONG_UNIQUE_HASH key have only one part, always?

>        for (i=0; i < key_parts; key_part++, i++)
>        {
>          Field *field;
> @@ -2363,7 +2453,16 @@ 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();
> +        if (keyinfo->flags & HA_LONG_UNIQUE_HASH
> +            &&(key_part->length > handler_file->max_key_part_length()
> +             || key_part->length == 0))

1. fix the spacing and the indentation here, please
2. what should happen if HA_LONG_UNIQUE_HASH flag is set,
   but the key_part->length is small ?

> +        {
> +          key_part->key_part_flag= HA_HASH_KEY_PART_FLAG;
> +          key_part->store_length= HA_HASH_KEY_PART_LENGTH;
> +        }
> +        /* Invisible Full is currently used by long uniques */
> -        if (field->invisible > INVISIBLE_USER && !field->vers_sys_field())
> +        if ((field->invisible ==  INVISIBLE_USER ||
> +                field->invisible == INVISIBLE_SYSTEM )&& !field->vers_sys_field())

why is this change?

>            keyinfo->flags |= HA_INVISIBLE_KEY;
>          if (field->null_ptr)
>          {
> @@ -2428,7 +2527,8 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
>                field->part_of_sortkey= share->keys_in_use;
>            }
>          }
> -        if (field->key_length() != key_part->length)
> +        if (field->key_length() != key_part->length &&
> +             !(keyinfo->flags & HA_LONG_UNIQUE_HASH))

why is  that?

>          {
>  #ifndef TO_BE_DELETED_ON_PRODUCTION
>            if (field->type() == MYSQL_TYPE_NEWDECIMAL)
> @@ -2470,7 +2570,8 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
>          if (!(key_part->key_part_flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART |
>                                           HA_BIT_PART)) &&
>              key_part->type != HA_KEYTYPE_FLOAT &&
> -            key_part->type == HA_KEYTYPE_DOUBLE)
> +            key_part->type == HA_KEYTYPE_DOUBLE &&
> +            !(keyinfo->flags & HA_LONG_UNIQUE_HASH))

why is that?

>            key_part->key_part_flag|= HA_CAN_MEMCMP;
>        }
>        keyinfo->usable_key_parts= usable_parts; // Filesort
> @@ -8346,6 +8454,377 @@ double KEY::actual_rec_per_key(uint i)
>  }
>  
>  
> +/*
> +   find out the field positoin in hash_str()
> +   position starts from 0
> +   else return -1;
> +*/
> +int find_field_pos_in_hash(Item *hash_item, const  char * field_name)
> +{
> +  Item_func_or_sum * temp= static_cast<Item_func_or_sum *>(hash_item);
> +  Item_args * t_item= static_cast<Item_args *>(temp);
> +  uint arg_count= t_item->argument_count();
> +  Item ** arguments= t_item->arguments();
> +  Field * t_field;
> +
> +  for (uint j=0; j < arg_count; j++)
> +  {
> +    DBUG_ASSERT(arguments[j]->type() == Item::FIELD_ITEM ||
> +                arguments[j]->type() == Item::FUNC_ITEM);
> +    if (arguments[j]->type() == Item::FIELD_ITEM)
> +    {
> +      t_field= static_cast<Item_field *>(arguments[j])->field;
> +    }
> +    else
> +    {
> +      Item_func_left *fnc= static_cast<Item_func_left *>(arguments[j]);
> +      t_field= static_cast<Item_field *>(fnc->arguments()[0])->field;
> +    }
> +    if (!my_strcasecmp(system_charset_info, t_field->field_name.str, field_name))
> +      return j;
> +  }
> +  return -1;
> +}
> +
> +/*
> +   find total number of field in hash_str
> +*/
> +int fields_in_hash_str(Item * hash_item)

can be static

> +{
> +  Item_func_or_sum * temp= static_cast<Item_func_or_sum *>(hash_item);
> +  Item_args * t_item= static_cast<Item_args *>(temp);
> +  return t_item->argument_count();
> +}
> +
> +/*
> +   Returns fields ptr given by hash_str index
> +   Index starts from 0
> +*/
> +Field * field_ptr_in_hash_str(Item *hash_item, int index)
> +{
> +  Item_func_or_sum * temp= static_cast<Item_func_or_sum *>(hash_item);
> +  Item_args * t_item= static_cast<Item_args *>(temp);
> +  return static_cast<Item_field *>(t_item->arguments()[index])->field;
> +}
> +
> +//NO longer Needed

remove it, then :)

> +int get_key_part_length(KEY *keyinfo, int index)
> +{
> +  DBUG_ASSERT(keyinfo->flags & HA_LONG_UNIQUE_HASH);
> +  TABLE *tbl= keyinfo->table;
> +  Item *h_item= keyinfo->key_part->field->vcol_info->expr;
> +  Field *fld= field_ptr_in_hash_str(h_item, index);
> +  if (!index)
> +    return fld->pack_length()+HA_HASH_KEY_LENGTH_WITH_NULL+1;
> +  return fld->pack_length()+1;
> +}
> +/**
> +  @brief clone of current handler.
> +  Creates a clone of handler used in update for
> +  unique hash key.
> +  @param thd            Thread Object
> +  @param table          Table Object
> +  @return    handler object
> +*/
> +void create_update_handler(THD *thd, TABLE *table)

better, clone_handler_for_update

> +{
> +  handler *update_handler= NULL;
> +    for (uint i= 0; i < table->s->keys; i++)

indentation

> +    {
> +      if (table->key_info[i].flags & HA_LONG_UNIQUE_HASH)
> +      {
> +        update_handler= table->file->clone(table->s->normalized_path.str,
> +                                           thd->mem_root);
> +        update_handler->ha_external_lock(thd, F_RDLCK);
> +        table->update_handler= update_handler;

why do you store it in TABLE? you can just keep it in a local variable
in mysql_update, you don't need it outside of mysql_update anyway.
(and multi-update)

also, you shouldn't need to scan all table keys here. use some
flag or property in TABLE_SCHEMA to check quickly whether the table
has these lock unique keys.

> +        return;
> +      }
> +    }
> +    return;
> +}
> +
> +/**
> + @brief Deletes update handler object
> + @param thd   Thread Object
> + @param table Table Object
> +*/
> +void delete_update_handler(THD *thd, TABLE *table)
> +{
> +  if (table->update_handler)
> +  {
> +    table->update_handler->ha_external_lock(thd, F_UNLCK);
> +    table->update_handler->ha_close();
> +    delete table->update_handler;
> +    table->update_handler= NULL;
> +  }
> +}
> +/**
> + @brief This function makes table object with
> +        long unique keys ready for storage engine.
> +        It makes key_part of HA_LONG_UNIQUE_HASH point to
> +        hash key_part.
> + @param table Table object
> + */
> +void setup_table_hash(TABLE *table)

this and other functions could be methods in TABLE

> +{
> +  /*
> +     Extra parts of long unique key which are used only at server level
> +     for example in key  unique(a, b, c)   //a b c are blob
> +     extra_key_part_hash is 3
> +  */
> +  uint extra_key_part_hash= 0;
> +  uint hash_parts= 0;
> +  KEY *s_keyinfo= table->s->key_info;
> +  KEY *keyinfo= table->key_info;
> +  /*
> +     Sometime s_keyinfo or key_info can be null. So
> +     two different loop for keyinfo and s_keyinfo
> +     reference test case:- main.subselect_sj2

how they could be null here?

> +   */
> +
> +  if (keyinfo)
> +  {
> +    for (uint i= 0; i < table->s->keys; i++, keyinfo++)
> +    {
> +      if (keyinfo->flags & HA_LONG_UNIQUE_HASH)
> +      {
> +        DBUG_ASSERT(keyinfo->user_defined_key_parts ==
> +                    keyinfo->ext_key_parts);
> +        keyinfo->flags&= ~(HA_NOSAME | HA_LONG_UNIQUE_HASH);
> +        keyinfo->algorithm= HA_KEY_ALG_UNDEF;
> +        extra_key_part_hash+= keyinfo->ext_key_parts;
> +        hash_parts++;
> +        keyinfo->key_part= keyinfo->key_part+ keyinfo->ext_key_parts;
> +        keyinfo->user_defined_key_parts= keyinfo->usable_key_parts=
> +            keyinfo->ext_key_parts= 1;
> +        keyinfo->key_length= keyinfo->key_part->store_length;
> +      }
> +    }
> +    table->s->key_parts-= extra_key_part_hash;
> +    table->s->key_parts+= hash_parts;
> +    table->s->ext_key_parts-= extra_key_part_hash;

I don't understand what you're doing here. Could you add a comment, explaning
the resulting structure of keys and keysegs and what's where?

> +  }
> +  if (s_keyinfo)
> +  {
> +    for (uint i= 0; i < table->s->keys; i++, s_keyinfo++)
> +    {
> +      if (s_keyinfo->flags & HA_LONG_UNIQUE_HASH)
> +      {
> +        DBUG_ASSERT(s_keyinfo->user_defined_key_parts ==
> +                    s_keyinfo->ext_key_parts);
> +        s_keyinfo->flags&= ~(HA_NOSAME | HA_LONG_UNIQUE_HASH);
> +        s_keyinfo->algorithm= HA_KEY_ALG_BTREE;
> +        extra_key_part_hash+= s_keyinfo->ext_key_parts;
> +        s_keyinfo->key_part= s_keyinfo->key_part+ s_keyinfo->ext_key_parts;
> +        s_keyinfo->user_defined_key_parts= s_keyinfo->usable_key_parts=
> +            s_keyinfo->ext_key_parts= 1;
> +        s_keyinfo->key_length= s_keyinfo->key_part->store_length;
> +      }
> +    }
> +    if (!keyinfo)
> +    {
> +      table->s->key_parts-= extra_key_part_hash;
> +      table->s->key_parts+= hash_parts;
> +      table->s->ext_key_parts-= extra_key_part_hash;
> +    }
> +  }
> +}
> +
> +/**
> + @brief Revert the effect of setup_table_hash
> + @param table Table Object
> + */
> +void re_setup_table(TABLE *table)
> +{
> +  //extra key parts excluding hash , which needs to be added in keyparts
> +  uint extra_key_parts_ex_hash= 0;
> +  uint extra_hash_parts= 0; // this var for share->extra_hash_parts
> +  KEY *s_keyinfo= table->s->key_info;
> +  KEY *keyinfo= table->key_info;
> +  /*
> +     Sometime s_keyinfo can be null so
> +     two different loop for keyinfo and s_keyinfo
> +     ref test case:- main.subselect_sj2
> +   */
> +  if (keyinfo)
> +  {
> +    for (uint i= 0; i < table->s->keys; i++, keyinfo++)
> +    {
> +      if (keyinfo->user_defined_key_parts == 1 &&
> +          keyinfo->key_part->field->flags & LONG_UNIQUE_HASH_FIELD)
> +      {
> +        keyinfo->flags|= (HA_NOSAME | HA_LONG_UNIQUE_HASH);
> +        keyinfo->algorithm= HA_KEY_ALG_LONG_HASH;
> +        /* Sometimes it can happen, that we does not parsed hash_str.
> +           Like when this function is called in ha_create. So we will
> +           Use field from  table->field rather then share->field*/
> +        Item *h_item= table->field[keyinfo->key_part->fieldnr - 1]->
> +                                                   vcol_info->expr;
> +        uint hash_parts= fields_in_hash_str(h_item);
> +        keyinfo->key_part= keyinfo->key_part- hash_parts;
> +        keyinfo->user_defined_key_parts= keyinfo->usable_key_parts=
> +            keyinfo->ext_key_parts= hash_parts;
> +        extra_key_parts_ex_hash+= hash_parts;
> +        extra_hash_parts++;
> +        keyinfo->key_length= -1;
> +      }
> +    }
> +    table->s->key_parts-= extra_hash_parts;
> +    table->s->key_parts+= extra_key_parts_ex_hash;
> +    table->s->ext_key_parts+= extra_key_parts_ex_hash + extra_hash_parts;
> +  } 
> +  if (s_keyinfo)
> +  {
> +    for (uint i= 0; i < table->s->keys; i++, s_keyinfo++)
> +    {
> +      if (s_keyinfo->user_defined_key_parts == 1 &&
> +          s_keyinfo->key_part->field->flags & LONG_UNIQUE_HASH_FIELD)
> +      {
> +        s_keyinfo->flags|= (HA_NOSAME | HA_LONG_UNIQUE_HASH);
> +        s_keyinfo->algorithm= HA_KEY_ALG_LONG_HASH;
> +        extra_hash_parts++;
> +        /* Sometimes it can happen, that we does not parsed hash_str.
> +           Like when this function is called in ha_create. So we will
> +           Use field from  table->field rather then share->field*/
> +        Item *h_item= table->field[s_keyinfo->key_part->fieldnr - 1]->
> +                                                   vcol_info->expr;
> +        uint hash_parts= fields_in_hash_str(h_item);
> +        s_keyinfo->key_part= s_keyinfo->key_part- hash_parts;
> +        s_keyinfo->user_defined_key_parts= s_keyinfo->usable_key_parts=
> +            s_keyinfo->ext_key_parts= hash_parts;
> +        extra_key_parts_ex_hash+= hash_parts;
> +        s_keyinfo->key_length= -1;
> +      }
> +    }
> +    if (!keyinfo)
> +    {
> +      table->s->key_parts-= extra_hash_parts;
> +      table->s->key_parts+= extra_key_parts_ex_hash;
> +      table->s->ext_key_parts+= extra_key_parts_ex_hash + extra_hash_parts;
> +    }
> +  }
> +}
> +
> +/**
> + @brief set_hash
> + @param table
> + @param key_index
> + @param key_buff
> + 
> +int get_hash_key(THD *thd,TABLE *table, handler *h,  uint key_index,
> +                 uchar * rec_buff, uchar *key_buff)

unused?

> +{
> +  KEY *keyinfo= &table->key_info[key_index];
> +  DBUG_ASSERT(keyinfo->flags & HA_LONG_UNIQUE_HASH);
> +  KEY_PART_INFO *temp_key_part= table->key_info[key_index].key_part;
> +  Field *fld[keyinfo->user_defined_key_parts];
> +  Field *t_field;
> +  uchar hash_buff[9];
> +  ulong nr1= 1, nr2= 4;
> +  String *str1, temp1;
> +  String *str2, temp2;
> +  bool is_null= false;
> +  bool is_same= true;
> +  bool is_index_inited= h->inited;
> +  /* difference between field->ptr and start of rec_buff *
> +  long diff = rec_buff- table->record[0];
> +  int result= 0;
> +  for (uint i=0; i < keyinfo->user_defined_key_parts; i++, temp_key_part++)
> +  {
> +    uint maybe_null= MY_TEST(temp_key_part->null_bit);
> +    fld[i]= temp_key_part->field->new_key_field(thd->mem_root, table,
> +                                                key_buff + maybe_null, 12,
> +                                                maybe_null?key_buff:0, 1,
> +                                                temp_key_part->key_part_flag
> +                                                & HA_HASH_KEY_PART_FLAG);
> +    if (fld[i]->is_real_null())
> +    {
> +      is_null= true;
> +      break;
> +    }
> +    str1= fld[i]->val_str(&temp1);
> +    calc_hash_for_unique(nr1, nr2, str1);
> +    key_buff+= temp_key_part->store_length;
> +  }
> +  if (is_null && !(keyinfo->flags & HA_NULL_PART_KEY))
> +    return HA_ERR_KEY_NOT_FOUND;
> +  if (keyinfo->flags & HA_NULL_PART_KEY)
> +  {
> +    hash_buff[0]= is_null;
> +    int8store(hash_buff + 1, nr1);
> +  }
> +  else
> +    int8store(hash_buff, nr1);
> +  if (!is_index_inited)
> +    result= h->ha_index_init(key_index, 0);
> +  if (result)
> +    return result;
> +
> +  setup_table_hash(table);
> +  result= h->ha_index_read_map(rec_buff, hash_buff, HA_WHOLE_KEY,
> +                       HA_READ_KEY_EXACT);
> +  re_setup_table(table);
> +  if (!result)
> +  {
> +    for (uint i=0; i < keyinfo->user_defined_key_parts; i++)
> +    {
> +      t_field= keyinfo->key_part[i].field;
> +      t_field->move_field(t_field->ptr+diff,
> +                          t_field->null_ptr+diff, t_field->null_bit);
> +    }
> +    do
> +    {
> +      re_setup_table(table);
> +      is_same= true;
> +      for (uint i=0; i < keyinfo->user_defined_key_parts; i++)
> +      {
> +        t_field= keyinfo->key_part[i].field;
> +        if (fld[i]->is_real_null() && t_field->is_real_null())
> +          continue;
> +        if (!fld[i]->is_real_null() && !t_field->is_real_null())
> +        {
> +          str1= t_field->val_str(&temp1);
> +          str2= fld[i]->val_str(&temp2);
> +          if (my_strcasecmp(str1->charset(), str1->c_ptr_safe(),
> +                                 str2->c_ptr_safe()))
> +          {
> +            is_same= false;
> +            break;
> +          }
> +        }
> +        else
> +        {
> +          is_same= false;
> +          break;
> +        }
> +      }
> +      setup_table_hash(table);
> +    }
> +    while (!is_same && !(result= h->ha_index_next_same(rec_buff, hash_buff,
> +                                          keyinfo->key_length)));
> +    for (uint i=0; i < keyinfo->user_defined_key_parts; i++)
> +    {
> +      t_field= keyinfo->key_part[i].field;
> +      t_field->move_field(t_field->ptr-diff,
> +                          t_field->null_ptr-diff, t_field->null_bit);
> +    }
> +  }
> +  if (!is_index_inited)
> +    h->ha_index_end();
> +  re_setup_table(table);
> +  for (uint i=0; i < keyinfo->user_defined_key_parts; i++)
> +  {
> +    if (keyinfo->key_part[i].key_part_flag & HA_FIELD_EX_FREED)
> +    {
> +      Field_blob *blb= static_cast<Field_blob *>(fld[i]);
> +      uchar * addr;
> +      blb->get_ptr(&addr);
> +      my_free(addr);
> +    }
> +  }
> +  return result;
> +}
> +*/
>  LEX_CSTRING *fk_option_name(enum_fk_option opt)
>  {
>    static LEX_CSTRING names[]=
> @@ -8814,3 +9293,15 @@ bool TABLE::export_structure(THD *thd, Row_definition_list *defs)
>    }
>    return false;
>  }
> +
> +void calc_hash_for_unique(ulong &nr1, ulong &nr2, String *str)
> +{
> +  CHARSET_INFO *cs;
> +  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);
> +  sql_print_information("setiya %lu, %s", nr1, str->ptr());

really? :)

> +}
> diff --git a/sql/sql_table.cc b/sql/sql_table.cc
> index 4ac8b102d79..f42687c0377 100644
> --- a/sql/sql_table.cc
> +++ b/sql/sql_table.cc
> @@ -3343,6 +3343,87 @@ mysql_add_invisible_index(THD *thd, List<Key> *key_list,
>    key_list->push_back(key, thd->mem_root);
>    return key;
>  }
> +/**
> +  Add hidden level 3 hash field to table in case of long

s/hidden level 3/fully invisible/

> +  unique column
> +  @param  thd           Thread Context.
> +  @param  create_list   List of table fields.
> +  @param  cs            Field Charset
> +  @param  key_info      Whole Keys buffer
> +  @param  key_index     Index of current key

1. instead of key_info and key_index, you can just take a key_info of the current
   key here (that is key_info + key_index).
2. what is the "current key"? Is it the unique key over blobs that you create
   a hash field for? please clarify the comment.

> +*/
> +
> +static void add_hash_field(THD * thd, List<Create_field> *create_list,
> +                           CHARSET_INFO *cs, KEY *key_info, int key_index)
> +{
> +  List_iterator<Create_field> it(*create_list);
> +  Create_field *dup_field, *cf= new (thd->mem_root) Create_field();
> +  cf->flags|= UNSIGNED_FLAG | LONG_UNIQUE_HASH_FIELD;
> +  cf->charset= cs;
> +  cf->decimals= 0;
> +  cf->length= cf->char_length= cf->pack_length= HA_HASH_FIELD_LENGTH;
> +  cf->invisible= INVISIBLE_FULL;
> +  cf->pack_flag|= FIELDFLAG_MAYBE_NULL;
> +  uint num= 1;
> +  char *temp_name= (char *)thd->alloc(30);
> +  my_snprintf(temp_name, 30, "DB_ROW_HASH_%u", num);

please, give names for 30 and for the whole my_snprintf - macros, functions,
whatever. And better use a LEX_STRING for it, for example:

 #define LONG_HASH_FIELD_NAME_LENGTH 30
 static inline make_long_hash_field_name(LEX_STRING buf, uint num)
 {
   buf->length= my_snprintf(buf->str, LONG_HASH_FIELD_NAME_LENGTH, "DB_ROW_HASH_%u", num);
 }

> +  /*
> +    Check for collusions

collisions :)

> +   */
> +  while ((dup_field= it++))
> +  {
> +    if (!my_strcasecmp(system_charset_info, temp_name, dup_field->field_name.str))
> +    {
> +      num++;
> +      my_snprintf(temp_name, 30, "DB_ROW_HASH_%u", num);
> +      it.rewind();
> +    }
> +  }
> +  it.rewind();
> +  cf->field_name.str= temp_name;
> +  cf->field_name.length= strlen(temp_name);

you won't need strlen here, if you use LEX_STRING above

> +  cf->set_handler(&type_handler_longlong);
> +  /*
> +    We have added db_row_hash field in starting of
> +    fields array , So we have to change key_part
> +    field index
> +  for (int i= 0; i <= key_index; i++, key_info++)
> +  {
> +    KEY_PART_INFO *info= key_info->key_part;
> +    for (uint j= 0; j <  key_info->user_defined_key_parts; j++, info++)
> +    {
> +      info->fieldnr+= 1;
> +      info->offset+= HA_HASH_FIELD_LENGTH;
> +    }
> +  }*/

Forgot to remove it?

> +  key_info[key_index].flags|= HA_NOSAME;
> +  key_info[key_index].algorithm= HA_KEY_ALG_LONG_HASH;
> +  it.rewind();
> +  uint record_offset= 0;
> +  while ((dup_field= it++))
> +  {
> +    dup_field->offset= record_offset;
> +    if (dup_field->stored_in_db())
> +      record_offset+= dup_field->pack_length;

Why do you change all field offsets? You only need to put your field last,
that's all. Like

   while ((dup_field= it++))
     set_if_bigger(record_offset, dup_field->offset + dup_field->pack_length)

> +  }
> +  cf->offset= record_offset;
> +  /*
> +  it.rewind();
> +  while ((sql_field= it++))
> +  {
> +    if (!sql_field->stored_in_db())
> +    {
> +      sql_field->offset= record_offset;
> +      record_offset+= sql_field->pack_length;
> +    }
> +  }

why is that?

> +   */
> +  /* hash column should be fully hidden */
> +  //prepare_create_field(cf, NULL, 0);

Forgot to remove it?

> +  create_list->push_back(cf,thd->mem_root);
> +}
> +
> +
>  /*
>    Preparation for table creation
>  
> @@ -3868,6 +3951,8 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
>        }
>  
>        cols2.rewind();
> +      key_part_info->fieldnr= field;
> +      key_part_info->offset=  (uint16) sql_field->offset;

why did you need to move that?

>        if (key->type == Key::FULLTEXT)
>        {
>         if ((sql_field->real_field_type() != MYSQL_TYPE_STRING &&
> @@ -3922,8 +4007,19 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
>              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 (key->type == Key::PRIMARY)
> +        {
> +             my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name.str);
> +             DBUG_RETURN(TRUE);
> +        }
> +        else if (!is_hash_field_added)
> +        {
> +          add_hash_field(thd, &alter_info->create_list,
> +                       create_info->default_table_charset,
> +                       *key_info_buffer, key_number);
> +          column->length= 0;

why column->length= 0 ?

> +          is_hash_field_added= true;
> +        }
>           }
>         }
>  #ifdef HAVE_SPATIAL
> @@ -4062,11 +4159,29 @@ 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)
> +      {
> +        if (!is_hash_field_added)
> +        {
> +          add_hash_field(thd, &alter_info->create_list,
> +                        create_info->default_table_charset,
> +                       *key_info_buffer, key_number);
> +          is_hash_field_added= true;

instead of is_hash_field_added and many add_hash_field() here and there, I'd
rather rename the variable to hash_field_needed. And only do hash_field_needed= true.
And at the end if (hash_field_needed) add_hash_field(...)

> +        }
> +      }
> +      else
> +      {
> +           my_error(ER_TOO_LONG_KEY, MYF(0), key_part_length);

any test cases for this error?

> +           DBUG_RETURN(TRUE);
> +         }
> +    }
>        }
> -      key_part_info->length= (uint16) key_part_length;
> +      /* We can not store key_part_length more then 2^16 - 1 in frm
> +         So we will simply make it zero */

Not really. If someone explicitly asks for a long prefix, it should be an error.
Like CREATE TABLE (a blob, UNIQUE (a(65537)); -- this is an error

> +      if (is_hash_field_added && key_part_length > (2<<16) - 1)
> +        key_part_info->length= 0;
> +      else
> +        key_part_info->length= (uint16) key_part_length;
>        /* Use packed keys for long strings on the first column */
>        if (!((*db_options) & HA_OPTION_NO_PACK_KEYS) &&
>            !((create_info->table_options & HA_OPTION_NO_PACK_KEYS)) &&
> @@ -4122,12 +4237,37 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
>      if (key->type == Key::UNIQUE && !(key_info->flags & HA_NULL_PART_KEY))
>        unique_key=1;
>      key_info->key_length=(uint16) key_length;
> -    if (key_length > max_key_length && key->type != Key::FULLTEXT)
> +    if (key_length > max_key_length && key->type != Key::FULLTEXT &&
> +            !is_hash_field_added)
>      {
>        my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
>        DBUG_RETURN(TRUE);
>      }
>  
> +    if (is_hash_field_added)
> +    {
> +      if (key_info->flags & HA_NULL_PART_KEY)
> +         null_fields++;
> +      else
> +      {
> +        uint elements= alter_info->create_list.elements;
> +        Create_field *hash_fld= static_cast<Create_field *>(alter_info->
> +                                                     create_list.elem(elements -1 ));
> +        hash_fld->flags|= NOT_NULL_FLAG;
> +        hash_fld->pack_flag&= ~FIELDFLAG_MAYBE_NULL;
> +       /*
> +          Althought we do not need default value anywhere in code , but if we create
> +          table with non null long columns , then at the time of insert we get warning.
> +          So default value is used so solve this warning.
> +        Virtual_column_info *default_value= new (thd->mem_root) Virtual_column_info();
> +        char * def_str= (char *)alloc_root(thd->mem_root, 2);
> +        strncpy(def_str, "0", 1);
> +        default_value->expr_str.str= def_str;
> +        default_value->expr_str.length= 1;
> +        default_value->expr_item= new (thd->mem_root) Item_int(thd,0);
> +        hash_fld->default_value= default_value; */
> +      }

Forgot to remove it?

> +    }
>      if (validate_comment_length(thd, &key->key_create_info.comment,
>                                  INDEX_COMMENT_MAXLEN,
>                                  ER_TOO_LONG_INDEX_COMMENT,
> @@ -8328,6 +8468,11 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
>        enum Key::Keytype key_type;
>        LEX_CSTRING tmp_name;
>        bzero((char*) &key_create_info, sizeof(key_create_info));
> +      if (key_info->flags & HA_LONG_UNIQUE_HASH)
> +      {
> +        key_info->flags&= ~(HA_LONG_UNIQUE_HASH);
> +        key_info->algorithm= HA_KEY_ALG_UNDEF;
> +      }

Why?

>        key_create_info.algorithm= key_info->algorithm;
>        /*
>          We copy block size directly as some engines, like Area, sets this
> diff --git a/sql/handler.cc b/sql/handler.cc
> index b77b2a3fa2c..cda53dfdc87 100644
> --- a/sql/handler.cc
> +++ b/sql/handler.cc
> @@ -6179,6 +6185,185 @@ int handler::ha_reset()
>    DBUG_RETURN(reset());
>  }
>  
> +static int check_duplicate_long_entry_key(TABLE *table, handler *h, uchar *new_rec,
> +                                   uint key_no)
> +{
> +  Field *hash_field;
> +  int result, error= 0;
> +  if (!(table->key_info[key_no].user_defined_key_parts == 1
> +        && table->key_info[key_no].key_part->field->flags & LONG_UNIQUE_HASH_FIELD ))
> +    return 0;

What if LONG_UNIQUE_HASH_FIELD is set but user_defined_key_parts != 1?

> +  hash_field= table->key_info[key_no].key_part->field;
> +  DBUG_ASSERT((table->key_info[key_no].flags & HA_NULL_PART_KEY &&
> +      table->key_info[key_no].key_length == HA_HASH_KEY_LENGTH_WITH_NULL)
> +    || table->key_info[key_no].key_length == HA_HASH_KEY_LENGTH_WITHOUT_NULL);
> +  uchar ptr[HA_HASH_KEY_LENGTH_WITH_NULL];
> +
> +  if (hash_field->is_real_null())
> +    return 0;
> +
> +  key_copy(ptr, new_rec, &table->key_info[key_no],
> +              table->key_info[key_no].key_length, false);

good, use existing function, no need to reinvent the wheel

> +
> +  if (!table->check_unique_buf)
> +    table->check_unique_buf= (uchar *)alloc_root(&table->mem_root,
> +                                    table->s->reclength*sizeof(uchar));
> +
> +  result= h->ha_index_init(key_no, 0);
> +  if (result)
> +    return result;
> +  result= h->ha_index_read_map(table->check_unique_buf,
> +                               ptr, HA_WHOLE_KEY, HA_READ_KEY_EXACT);
> +  if (!result)
> +  {
> +    bool is_same;
> +    do
> +    {
> +      Item_func_or_sum * temp= static_cast<Item_func_or_sum *>(hash_field->
> +                                                               vcol_info->expr);
> +      Item_args * t_item= static_cast<Item_args *>(temp);
> +      uint arg_count= t_item->argument_count();
> +      Item ** arguments= t_item->arguments();
> +      long diff= table->check_unique_buf - new_rec;
> +      Field * t_field;
> +      is_same= true;
> +      for (uint j=0; j < arg_count; j++)
> +      {
> +        DBUG_ASSERT(arguments[j]->type() == Item::FIELD_ITEM ||
> +                    // this one for left(fld_name,length)
> +                    arguments[j]->type() == Item::FUNC_ITEM);
> +        if (arguments[j]->type() == Item::FIELD_ITEM)
> +        {
> +          t_field= static_cast<Item_field *>(arguments[j])->field;
> +          if (t_field->cmp_offset(diff))
> +            is_same= false;
> +        }
> +        else
> +        {
> +          Item_func_left *fnc= static_cast<Item_func_left *>(arguments[j]);
> +          DBUG_ASSERT(!my_strcasecmp(system_charset_info, "left", fnc->func_name()));
> +          //item_data= fnc->val_str(&tmp1);
> +          DBUG_ASSERT(fnc->arguments()[0]->type() == Item::FIELD_ITEM);
> +          t_field= static_cast<Item_field *>(fnc->arguments()[0])->field;
> +          //        field_data= t_field->val_str(&tmp2);
> +          //        if (my_strnncoll(t_field->charset(),(const uchar *)item_data->ptr(),
> +          //                         item_data->length(),
> +          //                         (const uchar *)field_data.ptr(),
> +          //                         item_data->length()))
> +          //          return 0;
> +          uint length= fnc->arguments()[1]->val_int();
> +          if (t_field->cmp_max(t_field->ptr, t_field->ptr + diff, length))
> +            is_same= false;
> +        }
> +      }

you don't need all that code, use key_cmp() or key_cmp_if_same() from key.cc

> +    }
> +    while (!is_same && !(result= table->file->ha_index_next_same(table->check_unique_buf,
> +                         ptr, table->key_info[key_no].key_length)));
> +    if (is_same)
> +    {
> +      table->dupp_hash_key= key_no;
> +      error= HA_ERR_FOUND_DUPP_KEY;
> +      goto exit;
> +    }
> +    else
> +      goto exit;
> +  }
> +  if (result == HA_ERR_LOCK_WAIT_TIMEOUT)
> +  {
> +    table->dupp_hash_key= key_no;
> +    //TODO check if this is the only case
> +    error= HA_ERR_FOUND_DUPP_KEY;

Why?

> +  }
> +  exit:
> +  h->ha_index_end();
> +  return error;
> +}
> +/** @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(x,y))
> +    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 x_y 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
> +   @returns 0 if no duplicate else returns error
> +  */
> +static int check_duplicate_long_entries(TABLE *table, handler *h, uchar *new_rec)
> +{
> +  table->dupp_hash_key= -1;
> +  int result;
> +  for (uint i= 0; i < table->s->keys; i++)
> +  {
> +    if ((result= check_duplicate_long_entry_key(table, h, new_rec, i)))
> +      return result;
> +  }
> +  return 0;
> +}
> +
> +/** @brief
> +    check whether updated records breaks the
> +    unique constraint on long columns.
> +   @returns 0 if no duplicate else returns error
> +  */
> +static int check_duplicate_long_entries_update(TABLE *table, handler *h, uchar *new_rec)
> +{
> +  Field **f, *field;
> +  Item *h_item;
> +  int error= 0;
> +  bool is_update_handler_null= false;
> +  /*
> +     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].user_defined_key_parts == 1 &&
> +          table->key_info[i].key_part->field->flags & LONG_UNIQUE_HASH_FIELD)
> +    {
> +      /*
> +         Currently mysql_update is pacthed so that it will automatically set the
> +         Update handler and then free it but ha_update_row is used in many function (
> +         like in case of reinsert) Instead of patching them all here we check is
> +         update_handler is null then set it  And then set it null again
> +       */
> +      if (!table->update_handler)
> +      {
> +        create_update_handler(current_thd, table);
> +        is_update_handler_null= true;
> +      }
> +      h_item= table->key_info[i].key_part->field->vcol_info->expr;
> +      for (f= table->field; f && (field= *f); f++)
> +      {
> +        if ( find_field_pos_in_hash(h_item, field->field_name.str) != -1)
> +        {
> +          /* Compare fields if they are different then check for duplicates*/
> +          if(field->cmp_binary_offset(reclength))
> +          {
> +            if((error= check_duplicate_long_entry_key(table, table->update_handler,
> +                                                   new_rec, i)))
> +              goto exit;
> +            /*
> +              break beacuse check_duplicate_long_entrie_key will
> +              take care of remaning fields
> +             */
> +            break;
> +          }
> +        }
> +      }
> +    }
> +  }
> +  exit:
> +  if (is_update_handler_null)
> +  {
> +    delete_update_handler(current_thd, table);
> +  }
> +  return error;
> +}
>  
>  int handler::ha_write_row(uchar *buf)
>  {
> @@ -6189,14 +6374,21 @@ int handler::ha_write_row(uchar *buf)
>    DBUG_ENTER("handler::ha_write_row");
>    DEBUG_SYNC_C("ha_write_row_start");
>  
> +  setup_table_hash(table);

No-no. You cannot modify table structure back and forth for *every inserted row*.
It's ok to do it once, when a table is opened. But not for every row,

>    MYSQL_INSERT_ROW_START(table_share->db.str, table_share->table_name.str);
>    mark_trx_read_write();
>    increment_statistics(&SSV::ha_write_count);
>  
> +  if ((error= check_duplicate_long_entries(table, table->file, buf)))
> +  {
> +    re_setup_table(table);
> +    DBUG_RETURN(error);
> +  }
>    TABLE_IO_WAIT(tracker, m_psi, PSI_TABLE_WRITE_ROW, MAX_KEY, 0,
>                        { error= write_row(buf); })
>  
>    MYSQL_INSERT_ROW_DONE(error);
> +  re_setup_table(table);
>    if (likely(!error) && !row_already_logged)
>    {
>      rows_changed++;

Regards,
Sergei
Chief Architect MariaDB
and security@xxxxxxxxxxx