diff options
author | Sachin <sachin.setiya@mariadb.com> | 2018-08-28 11:05:57 +0530 |
---|---|---|
committer | Sachin <sachin.setiya@mariadb.com> | 2018-12-31 20:35:37 +0530 |
commit | a6968054057b39d19be83c5fc961817c6a94ea65 (patch) | |
tree | da7dc3e566c6f7e6d4d73154906a57d67259ef03 | |
parent | 3bdd93c10ae8601fa74da9de01b406d2901bfcfc (diff) | |
download | mariadb-git-a6968054057b39d19be83c5fc961817c6a94ea65.tar.gz |
commit a
-rw-r--r-- | include/my_base.h | 8 | ||||
-rw-r--r-- | include/mysql_com.h | 2 | ||||
-rw-r--r-- | mysql-test/main/long_unique.result | 1379 | ||||
-rw-r--r-- | mysql-test/main/long_unique.test | 468 | ||||
-rw-r--r-- | mysql-test/main/long_unique_update.result | 316 | ||||
-rw-r--r-- | mysql-test/main/long_unique_update.test | 137 | ||||
-rw-r--r-- | sql/field.cc | 2 | ||||
-rw-r--r-- | sql/field.h | 15 | ||||
-rw-r--r-- | sql/handler.cc | 199 | ||||
-rw-r--r-- | sql/item_func.cc | 30 | ||||
-rw-r--r-- | sql/item_func.h | 13 | ||||
-rw-r--r-- | sql/sql_select.cc | 3 | ||||
-rw-r--r-- | sql/sql_show.cc | 11 | ||||
-rw-r--r-- | sql/sql_table.cc | 180 | ||||
-rw-r--r-- | sql/sql_update.cc | 6 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 6 | ||||
-rw-r--r-- | sql/table.cc | 366 | ||||
-rw-r--r-- | sql/table.h | 38 | ||||
-rw-r--r-- | sql/unireg.cc | 2 | ||||
-rw-r--r-- | sql/unireg.h | 3 |
20 files changed, 3145 insertions, 39 deletions
diff --git a/include/my_base.h b/include/my_base.h index c36072c0bfa..9a16d4b624b 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -99,7 +99,8 @@ enum ha_key_alg { HA_KEY_ALG_BTREE= 1, /* B-tree, default one */ HA_KEY_ALG_RTREE= 2, /* R-tree, for spatial searches */ HA_KEY_ALG_HASH= 3, /* HASH keys (HEAP tables) */ - HA_KEY_ALG_FULLTEXT= 4 /* FULLTEXT (MyISAM tables) */ + HA_KEY_ALG_FULLTEXT= 4, /* FULLTEXT (MyISAM tables) */ + HA_KEY_ALG_LONG_HASH= 5 /* long BLOB keys */ }; /* Storage media types */ @@ -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 +/* + Flag for long unique hash key + calculated in the init_from_binary_frm_image +*/ +#define HA_LONG_UNIQUE_HASH 2<<19 /* Automatic bits in key-flag */ #define HA_SPACE_PACK_USED 4 /* Test for if SPACE_PACK used */ diff --git a/include/mysql_com.h b/include/mysql_com.h index 8b0847ab399..09491ee81c8 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -203,6 +203,8 @@ enum enum_indicator_type #define VERS_UPDATE_UNVERSIONED_FLAG (1 << 29) /* column that doesn't support system versioning when table itself supports it*/ +#define LONG_UNIQUE_HASH_FIELD (1<< 30) /* This field will store hash for unique + column */ #define REFRESH_GRANT (1ULL << 0) /* Refresh grant tables */ #define REFRESH_LOG (1ULL << 1) /* Start on new log file */ diff --git a/mysql-test/main/long_unique.result b/mysql-test/main/long_unique.result new file mode 100644 index 00000000000..29d5a6b8a04 --- /dev/null +++ b/mysql-test/main/long_unique.result @@ -0,0 +1,1379 @@ +#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 +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 +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 order by a; +a +NULL +NULL +1 +123456789034567890 +123456789034567891 +2 +3 +56 +maria +sachin +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' +select * from t1 order by a; +a +NULL +NULL +1 +123456789034567890 +123456789034567891 +2 +3 +56 +maria +sachin +insert into t1 values(11),(22),(33); +insert into t1 values(12),(22); +ERROR 23000: Duplicate entry '22' for key 'a' +select * from t1 order by a; +a +NULL +NULL +1 +11 +12 +123456789034567890 +123456789034567891 +2 +22 +3 +33 +56 +maria +sachin +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)) +) 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' +insert into t1 values(45,1,55),(45,1,55); +ERROR 23000: Duplicate entry '45' for key 'a' +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 name; +#this will change index to b tree; +alter table t1 change column a aa 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, + `aa` blob DEFAULT NULL, + UNIQUE KEY `db_row_hash_1` (`db_row_hash_1`), + UNIQUE KEY `a` (`aa`) +) 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 aa A NULL NULL NULL YES HASH_INDEX +# try to change the blob unique datatype; +#this will change index to b tree; +alter table t1 modify column aa 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, + `aa` int(11) DEFAULT NULL, + UNIQUE KEY `db_row_hash_1` (`db_row_hash_1`), + UNIQUE KEY `a` (`aa`) +) 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 aa 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, + `aa` int(11) DEFAULT NULL, + `clm_changed` blob DEFAULT NULL, + UNIQUE KEY `db_row_hash_1` (`db_row_hash_1`), + UNIQUE KEY `a` (`aa`), + 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 aa 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, + `aa` int(11) DEFAULT NULL, + `clm_changed` blob DEFAULT NULL, + UNIQUE KEY `db_row_hash_1` (`db_row_hash_1`), + UNIQUE KEY `a` (`aa`) +) 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 aa 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 ('Ä'); +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 +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 order by a; +a b c d e +1 2 3 4 5 +123456789034567890 43545 657567567567 78967657567567 657567567567567676 +123456789034567891 353534 53453453453456 64565464564564 45435345345345 +2 11 22 33 44 +3111 222 333 444 555 +5611 2222 3333 4444 5555 +maria 345 frter dasd utyuty +sachin 341 fdf gfgfgfg hghgr +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 order by a; +a b c d e +1 2 3 4 5 +123456789034567890 43545 657567567567 78967657567567 657567567567567676 +123456789034567891 353534 53453453453456 64565464564564 45435345345345 +2 11 22 33 44 +3111 222 333 444 555 +5611 2222 3333 4444 5555 +maria 345 frter dasd utyuty +sachin 341 fdf gfgfgfg hghgr +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; +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 order by a; +a b c d e f g h +NULL NULL NULL NULL NULL NULL NULL NULL +NULL NULL NULL NULL NULL NULL NULL NULL +1 1 1 1 1 1 1 1 +2 2 2 2 2 2 2 2 +3 3 3 3 3 3 3 3 +4 4 4 4 4 4 4 4 +5 5 5 5 5 5 5 5 +maria 6 maria maria maria maria 6 maria +mariadb 7 mariadb mariadb mariadb mariadb 8 mariadb +select db_row_hash_1 from t1; +ERROR 42S22: Unknown column 'db_row_hash_1' in 'field list' +select db_row_hash_2 from t1; +ERROR 42S22: Unknown column 'db_row_hash_2' in 'field list' +select db_row_hash_3 from t1; +ERROR 42S22: Unknown column 'db_row_hash_3' in 'field list' +#duplicate entry test; +#duplicate keys entry; +insert into t1 values(1,1,1,0,0,0,0,0); +ERROR 23000: Duplicate entry '1-1-1' for key 'a' +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; +#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 order by a; +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 order by a; +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 order by a; +a b +1 19 +2 29 +3 39 +4 49 +select * from t2 order by DB_ROW_HASH_1; +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/mysql-test/main/long_unique.test b/mysql-test/main/long_unique.test new file mode 100644 index 00000000000..e70a38e0928 --- /dev/null +++ b/mysql-test/main/long_unique.test @@ -0,0 +1,468 @@ +let datadir=`select @@datadir`; +--echo #Structure of tests +--echo #First we will check all option for +--echo #table containing single unique column +--echo #table containing keys like unique(a,b,c,d) etc +--echo #then table containing 2 blob unique etc +set @allowed_packet= @@max_allowed_packet; + +--echo #table with single long blob column; +create table t1(a blob unique); +insert into t1 values(1),(2),(3),(56),('sachin'),('maria'),(123456789034567891),(null),(null),(123456789034567890); + +--echo #table structure; +desc t1; +show create table t1; +query_vertical show keys from t1; +replace_result $datadir DATADIR; +exec $MYISAMCHK -d $datadir/test/t1; +select * from information_schema.columns where table_schema = 'test' and table_name = 't1'; +select * from information_schema.statistics where table_schema = 'test' and table_name = 't1'; +query_vertical select * from information_schema.key_column_usage where table_schema= 'test' and table_name= 't1'; +--echo # table select we should not be able to see db_row_hash_column; +select * from t1 order by a; +--error ER_BAD_FIELD_ERROR +select db_row_hash_1 from t1; +--echo #duplicate entry test; +--error ER_DUP_ENTRY +insert into t1 values(2); +--error ER_DUP_ENTRY +insert into t1 values('sachin'); +--error ER_DUP_ENTRY +insert into t1 values(123456789034567891); +select * from t1 order by a; +insert into t1 values(11),(22),(33); +--error ER_DUP_ENTRY +insert into t1 values(12),(22); +select * from t1 order by a; +insert into t1 values(repeat('s',4000*10)),(repeat('s',4001*10)); +--error ER_DUP_ENTRY +insert into t1 values(repeat('m',4000*10)),(repeat('m',4000*10)); +insert into t1 values(repeat('m',4001)),(repeat('m',4002)); +truncate table t1; +insert into t1 values(1),(2),(3),(4),(5),(8),(7); +replace_result $datadir DATADIR; +exec $MYISAMCHK -d $datadir/test/t1; +--echo #now some alter commands; +alter table t1 add column b int; +desc t1; +show create table t1; +--error ER_DUP_ENTRY +insert into t1 values(1,2); +--error ER_DUP_ENTRY +insert into t1 values(2,2); +--error ER_BAD_FIELD_ERROR +select db_row_hash_1 from t1; +--echo #now try to change db_row_hash_1 column; +--error ER_CANT_DROP_FIELD_OR_KEY +alter table t1 drop column db_row_hash_1; +--error ER_CANT_DROP_FIELD_OR_KEY +alter table t1 add column d int , add column e int , drop column db_row_hash_1; +--error ER_BAD_FIELD_ERROR +alter table t1 modify column db_row_hash_1 int ; +--error ER_BAD_FIELD_ERROR +alter table t1 add column a int , add column b int, modify column db_row_hash_1 int ; +--error ER_BAD_FIELD_ERROR +alter table t1 change column db_row_hash_1 dsds int; +--error ER_BAD_FIELD_ERROR +alter table t1 add column asd int, change column db_row_hash_1 dsds int; +alter table t1 drop column b , add column c int; +show create table t1; + +--echo #now add some column with name db_row_hash; +alter table t1 add column db_row_hash_1 int unique; +show create table t1; +--error ER_DUP_ENTRY +insert into t1 values(45,1,55),(46,1,55); +--error ER_DUP_ENTRY +insert into t1 values(45,1,55),(45,1,55); +alter table t1 add column db_row_hash_2 int, add column db_row_hash_3 int; +desc t1; +--echo #this should also drop the unique index ; +alter table t1 drop column a; +show create table t1; +show keys from t1; +--echo #add column with unique index on blob ; +alter table t1 add column a blob unique; +show create table t1; +--echo # try to change the blob unique name; +--echo #this will change index to b tree; +alter table t1 change column a aa blob ; +show create table t1; +show keys from t1; +--echo # try to change the blob unique datatype; +--echo #this will change index to b tree; +alter table t1 modify column aa int ; +show create table t1; +show keys from t1; +alter table t1 add column clm blob unique; +--echo #try changing the name ; +alter table t1 change column clm clm_changed blob; +show create table t1; +show keys from t1; +--echo #now drop the unique key; +alter table t1 drop key clm; +show create table t1; +show keys from t1; +drop table t1; + +create table t1 (a TEXT CHARSET latin1 COLLATE latin1_german2_ci unique); +desc t1; +show keys from t1; + insert into t1 values ('ae'); +--error ER_DUP_ENTRY +insert into t1 values ('AE'); +insert into t1 values ('Ä'); +drop table t1; +create table t1 (a int primary key, b blob unique); +desc t1; +show keys from t1; +insert into t1 values(1,1),(2,2),(3,3); +--error ER_DUP_ENTRY +insert into t1 values(1,1); +--error ER_DUP_ENTRY +insert into t1 values(7,1); +drop table t1; + +--echo #table with multiple long blob column and varchar text column ; +create table t1(a blob unique, b int , c blob unique , d text unique , e varchar(3000) unique); +insert into t1 values(1,2,3,4,5),(2,11,22,33,44),(3111,222,333,444,555),(5611,2222,3333,4444,5555), +('sachin',341,'fdf','gfgfgfg','hghgr'),('maria',345,'frter','dasd','utyuty'), +(123456789034567891,353534,53453453453456,64565464564564,45435345345345), +(123456789034567890,43545,657567567567,78967657567567,657567567567567676); + +--echo #table structure; +desc t1; +show create table t1; +show keys from t1; +replace_result $datadir DATADIR; +exec $MYISAMCHK -d $datadir/test/t1; +select * from information_schema.columns where table_schema = 'test' and table_name = 't1'; +select * from information_schema.statistics where table_schema = 'test' and table_name = 't1'; +select * from information_schema.key_column_usage where table_schema= 'test' and table_name= 't1'; +--echo #table select we should not be able to see db_row_hash_1 column; +select * from t1 order by a; +--error ER_BAD_FIELD_ERROR +select db_row_hash_1 from t1; +--error ER_BAD_FIELD_ERROR +select db_row_hash_2 from t1; +--error ER_BAD_FIELD_ERROR +select db_row_hash_3 from t1; +--echo #duplicate entry test; +--error ER_DUP_ENTRY +insert into t1 values(21,2,3,42,51); +--error ER_DUP_ENTRY +insert into t1 values('sachin',null,null,null,null); +--error ER_DUP_ENTRY +insert into t1 values(1234567890345671890,4353451,6575675675617,789676575675617,657567567567567676); +select * from t1 order by a; +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)); +--error ER_DUP_ENTRY +insert into t1 values(repeat('m',4000*11),10,repeat('s',4000*11),repeat('s',4000*11),repeat('s',2995)); +truncate table t1; +insert into t1 values(1,2,3,4,5),(2,11,22,33,44),(3111,222,333,444,555),(5611,2222,3333,4444,5555); + +--echo #now some alter commands; +alter table t1 add column f int; +desc t1; +show create table t1; +--echo #unique key should not break; +--error ER_DUP_ENTRY +insert into t1 values(1,2,3,4,5,6); +--error ER_BAD_FIELD_ERROR +select db_row_hash_1 , db_row_hash_2, db_row_hash_3 from t1; +--echo #now try to change db_row_hash_1 column; +--error ER_CANT_DROP_FIELD_OR_KEY +alter table t1 drop column db_row_hash_1, drop column db_row_hash_2, drop column db_row_hash_3; +--error ER_CANT_DROP_FIELD_OR_KEY +alter table t1 add column dg int , add column ef int , drop column db_row_hash_1; +--error ER_BAD_FIELD_ERROR +alter table t1 modify column db_row_hash_1 int , modify column db_row_hash_2 int, modify column db_row_hash_3 int; +--error ER_BAD_FIELD_ERROR +alter table t1 add column ar int , add column rb int, modify column db_row_hash_1 int , modify column db_row_hash_3 int; +--error ER_BAD_FIELD_ERROR +alter table t1 change column db_row_hash_1 dsds int , change column db_row_hash_2 dfdf int , change column db_row_hash_3 gdfg int ; +--error ER_BAD_FIELD_ERROR +alter table t1 add column asd int, drop column a, change column db_row_hash_1 dsds int, change db_row_hash_3 fdfdfd int; +alter table t1 drop column b , add column g int; +show create table t1; + +--echo #now add some column with name db_row_hash; +alter table t1 add column db_row_hash_1 int unique; +alter table t1 add column db_row_hash_2 int unique; +alter table t1 add column db_row_hash_3 int unique; +show create table t1; + +alter table t1 add column db_row_hash_7 int, add column db_row_hash_5 int , add column db_row_hash_4 int ; +alter table t1 drop column db_row_hash_7,drop column db_row_hash_3, drop column db_row_hash_4; +desc t1; +--echo #this show now break anything; +--error ER_DUP_ENTRY +insert into t1 values(1,2,3,4,5,6,23,5,6); +--echo #this should also drop the unique index; +alter table t1 drop column a, drop column c; +show create table t1; +show keys from t1; +--echo #add column with unique index on blob; +alter table t1 add column a blob unique; +show create table t1; +show keys from t1; +--echo #try to change the blob unique column name; +--echo #this will change index to b tree; +alter table t1 modify column a int , modify column e int; +show create table t1; +show keys from t1; +alter table t1 add column clm1 blob unique,add column clm2 blob unique; +--echo #try changing the name; +alter table t1 change column clm1 clm_changed1 blob, change column clm2 clm_changed2 blob; +show create table t1; +show keys from t1; +--echo #now drop the unique key; +alter table t1 drop key clm1, drop key clm2; +show create table t1; +show keys from t1; +drop table t1; + +--echo #now the table with key on multiple columns; the ultimate test; +create table t1(a blob, b int , c varchar(2000) , d text , e varchar(3000) , f longblob , g int , h text , + unique(a,b,c), unique(c,d,e),unique(e,f,g,h), unique(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); + +--echo #table structure; +desc t1; +show create table t1; +show keys from t1; +replace_result $datadir DATADIR; +exec $MYISAMCHK -d $datadir/test/t1; +select * from information_schema.columns where table_schema = 'test' and table_name = 't1'; +select * from information_schema.statistics where table_schema = 'test' and table_name = 't1'; +select * from information_schema.key_column_usage where table_schema= 'test' and table_name= 't1'; +--echo # table select we should not be able to see db_row_hash_1 column; +select * from t1 order by a; +--error ER_BAD_FIELD_ERROR +select db_row_hash_1 from t1; +--error ER_BAD_FIELD_ERROR +select db_row_hash_2 from t1; +--error ER_BAD_FIELD_ERROR +select db_row_hash_3 from t1; +--echo #duplicate entry test; +--echo #duplicate keys entry; +--error ER_DUP_ENTRY +insert into t1 values(1,1,1,0,0,0,0,0); +--error ER_DUP_ENTRY +insert into t1 values(0,0,1,1,1,0,0,0); +--error ER_DUP_ENTRY +insert into t1 values(0,0,0,0,1,1,1,1); +--error ER_DUP_ENTRY +insert into t1 values(1,1,1,1,1,0,0,0); +--error ER_DUP_ENTRY +insert into t1 values(0,0,0,0,1,1,1,1); +--error ER_DUP_ENTRY +insert into t1 values(1,1,1,1,1,1,1,1); +--error ER_BAD_FIELD_ERROR +select db_row_hash_1,db_row_hash_2,db_row_hash_3,db_row_hash_4,db_row_hash_5 from t1; +--error ER_CANT_DROP_FIELD_OR_KEY +alter table t1 drop column db_row_hash_1, drop column db_row_hash_2, drop column db_row_hash_3; +--error ER_CANT_DROP_FIELD_OR_KEY +alter table t1 add column dg int , add column ef int , drop column db_row_hash_1; +--error ER_BAD_FIELD_ERROR +alter table t1 modify column db_row_hash_1 int , modify column db_row_hash_2 int, modify column db_row_hash_3 int; +--error ER_BAD_FIELD_ERROR +alter table t1 add column ar int , add column rb int, modify column db_row_hash_1 int , modify column db_row_hash_3 int; +--error ER_BAD_FIELD_ERROR +alter table t1 change column db_row_hash_1 dsds int , change column db_row_hash_2 dfdf int , change column db_row_hash_3 gdfg int ; +--error ER_BAD_FIELD_ERROR +alter table t1 add column asd int, drop column a, change column db_row_hash_1 dsds int, change db_row_hash_3 fdfdfd int; + +show create table t1; +--echo # add column named db_row_hash_*; +alter table t1 add column db_row_hash_7 int , add column db_row_hash_5 int, + add column db_row_hash_1 int, add column db_row_hash_2 int; +show create table t1; +show keys from t1; +alter table t1 drop column db_row_hash_7 , drop column db_row_hash_5 , + drop column db_row_hash_1, drop column db_row_hash_2 ; +show create table t1; +show keys from t1; + +--echo #try to change column names; +alter table t1 change column a aa blob , change column b bb blob , change column d dd blob; +show create table t1; +show keys from t1; +alter table t1 change column aa a blob , change column bb b blob , change column dd d blob; +show create table t1; +show keys from t1; + +--echo #now we will change the data type to int and varchar limit so that we no longer require hash_index; +--echo #on key a_b_c; +alter table t1 modify column a varchar(20) , modify column b varchar(20) , modify column c varchar(20); +show create table t1; +show keys from t1; +--echo #change it back; +alter table t1 modify column a blob , modify column b blob , modify column c blob; +show create table t1; +show keys from t1; + +--echo #try to delete blob column in unique; +truncate table t1; +## this feature removed in 10.2 +#alter table t1 drop column a, drop column b, drop column c; +#show create table t1; +#show keys from t1; +--echo #now try to delete keys; +alter table t1 drop key c, drop key e; +show create table t1; +show keys from t1; +drop table t1; + +--echo #now alter table containing some data basically some tests with ignore; +create table t1 (a blob); +insert into t1 values(1),(2),(3); +--echo #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); +--error ER_DUP_ENTRY +alter table t1 add unique key(a); +alter ignore table t1 add unique key(a); +select * from t1 order by a; +--error ER_DUP_ENTRY +insert into t1 values(1); +show create table t1; +show keys from t1; +drop table t1; + +--echo #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); +--error ER_DUP_ENTRY +alter table t1 add unique key(a,c), add unique key(b,d), add unique key(e); +alter ignore table t1 add unique key(a,c), add unique key(b,d), add unique key(e); +select * from t1 order by a; +--error ER_DUP_ENTRY +insert into t1 values (1,12,1,13,14); +--error ER_DUP_ENTRY +insert into t1 values (12,1,14,1,14); +--error ER_DUP_ENTRY +insert into t1 values (13,12,13,14,4); +show create table t1; +show keys from t1; +drop table t1; + +--echo #visibility of db_row_hash +create table t1 (a blob unique , b blob unique); +desc t1; +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 order by a; +select * from t2 order by DB_ROW_HASH_1; +--error ER_BAD_FIELD_ERROR +select DB_ROW_HASH_1, DB_ROW_HASH_2 from t1; +--echo #bug +select DB_ROW_HASH_1, DB_ROW_HASH_2 from t1,t2; +--error ER_BAD_FIELD_ERROR +select * from t1 where DB_ROW_HASH_1 in (select DB_ROW_HASH_1 from t2); +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); +select * from t2 where DB_ROW_HASH_1 in (select DB_ROW_HASH_1 from t1); +--error ER_BAD_FIELD_ERROR +select DB_ROW_HASH_1 from t1,t2 where t1.DB_ROW_HASH_1 = t2.DB_ROW_HASH_2; +select DB_ROW_HASH_1 from t1 inner join t2 on t1.a = t2.DB_ROW_HASH_2; +drop table t1,t2; + +--echo #very long blob entry; +SET @@GLOBAL.max_allowed_packet=67108864; + +connect ('newcon', localhost, root,,); +--connection newcon +show variables like 'max_allowed_packet'; +create table t1(a longblob unique, b longblob , c longblob , unique(b,c)); +desc t1; +show create table t1; +show keys from t1; +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')); +--error ER_DUP_ENTRY +insert into t1 values(concat(repeat('sachin',10000000),'2'),concat(repeat('sachin',10000000),'2'), +concat(repeat('sachin',10000000),'4')); +--error ER_DUP_ENTRY +insert into t1 values(concat(repeat('sachin',10000000),'3'),concat(repeat('sachin',10000000),'1'), +concat(repeat('sachin',10000000),'1')); +drop table t1; + +--echo #long key unique with different key length +create table t1(a blob, unique(a(3000))); +desc t1; +show keys from t1; +show create table t1; +insert into t1 value(concat(repeat('s',3000),'1')); +--error ER_DUP_ENTRY +insert into t1 value(concat(repeat('s',3000),'2')); +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; +show create table t1; +show keys from t1; +drop table t1; +disconnect newcon; +--connection default +SET @@GLOBAL.max_allowed_packet=4194304; +--echo #ext bug +create table t1(a int primary key, b blob unique, c int, d blob , index(c)); +show create table t1; +insert into t1 values(1,23,1,33); +--error ER_DUP_ENTRY +insert into t1 values(2,23,1,33); +drop table t1; +create table t2 (a blob unique , c int , index(c)); +show create table t2; +insert into t2 values(1,1); +insert into t2 values(2,1); +drop table t2; +--echo #not null test //todo solve warnings +create table t1(a blob unique not null); +desc t1; +show create table t1; +insert into t1 values(1); +insert into t1 values(3); +--error ER_DUP_ENTRY +insert into t1 values(1); +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); +--error ER_DUP_ENTRY +insert into t1 values(2,1,2); +--error ER_DUP_ENTRY +insert into t1 values(3,3,1); +drop table t1; +create table t1 (a blob unique not null, b blob not null, c blob not null, unique(b,c)); +desc t1; +show create table t1; +insert into t1 values (1, 2, 3); +insert into t1 values (2, 1, 3); +--error ER_DUP_ENTRY +insert into t1 values (2, 1, 3); +drop table t1; +set @@GLOBAL.max_allowed_packet= @allowed_packet; diff --git a/mysql-test/main/long_unique_update.result b/mysql-test/main/long_unique_update.result new file mode 100644 index 00000000000..6e887ba2e5f --- /dev/null +++ b/mysql-test/main/long_unique_update.result @@ -0,0 +1,316 @@ +#structure of tests; +#1 test of table containing single unique blob column; +#2 test of table containing another unique int/ varchar etc column; +#3 test of table containing multiple unique blob column like unique(a),unique(b); +#4 test of table containing multiple multiple unique blob column like unique(a,b...),unique(c,d....); +#structure of each test; +#test if update works; +#test update for duplicate entry; +#test update for no change keys; +#test update for ignore ; +#test 1 +create table t1 (a blob unique); +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 +Comment +Index_comment +insert into t1 values(1),(2),(3),(4),(5); +select * from t1; +a +1 +2 +3 +4 +5 +update t1 set a=11 where a=5; +update t1 set a=a+20 where a=1; +select * from t1; +a +21 +2 +3 +4 +11 +update t1 set a=3 where a=2; +ERROR 23000: Duplicate entry '3' for key 'a' +update t1 set a=4 where a=3; +ERROR 23000: Duplicate entry '4' for key 'a' +#no change in blob key +update t1 set a=3 where a=3; +update t1 set a=2 where a=2; +select* from t1; +a +21 +2 +3 +4 +11 +#IGNORE; +update ignore t1 set a=3 where a=2; +update ignore t1 set a=4 where a=3; +select * from t1; +a +21 +2 +3 +4 +11 +drop table t1; +#test 2; +create table t1 (a int primary key, b blob unique , c int unique ); +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 +t1 0 c 1 c A NULL NULL NULL YES BTREE +insert into t1 values(1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5),(6,6,6),(7,7,7); +select * from t1 limit 3; +a b c +1 1 1 +2 2 2 +3 3 3 +update t1 set b=34 where a=1; +update t1 set b=a+c+b+34 where b=2; +update t1 set b=a+10+b where c=3; +select * from t1; +a b c +1 34 1 +2 40 2 +3 16 3 +4 4 4 +5 5 5 +6 6 6 +7 7 7 +truncate table t1; +insert into t1 values(1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5),(6,6,6),(7,7,7); +update t1 set b=4 where a=3; +ERROR 23000: Duplicate entry '4' for key 'b' +update t1 set b=a+1 where b=3; +ERROR 23000: Duplicate entry '4' for key 'b' +update t1 set b=a+1 where c=3; +ERROR 23000: Duplicate entry '4' for key 'b' +#no change in blob key +update t1 set b=3 where a=3; +update t1 set b=2 where b=2; +update t1 set b=5 where c=5; +select* from t1; +a b c +1 1 1 +2 2 2 +3 3 3 +4 4 4 +5 5 5 +6 6 6 +7 7 7 +#IGNORE; +update ignore t1 set b=3 where a=2; +update ignore t1 set b=4 where b=3; +update ignore t1 set b=5 where c=3; +select * from t1; +a b c +1 1 1 +2 2 2 +3 3 3 +4 4 4 +5 5 5 +6 6 6 +7 7 7 +drop table t1; +#test 3; +create table t1 (a blob unique, b blob unique , c blob unique); +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 c 1 c A NULL NULL NULL YES HASH_INDEX +insert into t1 values(1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5),(6,6,6),(7,7,7); +select * from t1 limit 3; +a b c +1 1 1 +2 2 2 +3 3 3 +update t1 set b=34 where a=1; +update t1 set b=a+c+b+34 where b=2; +update t1 set b=a+10+b where c=3; +select * from t1; +a b c +1 34 1 +2 40 2 +3 16 3 +4 4 4 +5 5 5 +6 6 6 +7 7 7 +truncate table t1; +insert into t1 values(1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5),(6,6,6),(7,7,7); +update t1 set b=4 where a=3; +ERROR 23000: Duplicate entry '4' for key 'b' +update t1 set b=a+1 where b=3; +ERROR 23000: Duplicate entry '4' for key 'b' +update t1 set b=a+1 where c=3; +ERROR 23000: Duplicate entry '4' for key 'b' +#no change in blob key +update t1 set b=3 where a=3; +update t1 set b=2 where b=2; +update t1 set b=5 where c=5; +select* from t1; +a b c +1 1 1 +2 2 2 +3 3 3 +4 4 4 +5 5 5 +6 6 6 +7 7 7 +#IGNORE; +update ignore t1 set b=3 where a=2; +update ignore t1 set b=4 where b=3; +update ignore t1 set b=5 where c=3; +update ignore t1 set b=b+3 where a>1 or b>1 or c>1; +select * from t1; +a b c +1 1 1 +2 2 2 +3 3 3 +4 4 4 +5 8 5 +6 9 6 +7 10 7 +update ignore t1 set b=b+5 where a>1 and b<5 and c<a+b; +select * from t1; +a b c +1 1 1 +2 7 2 +3 3 3 +4 4 4 +5 8 5 +6 9 6 +7 10 7 +drop table t1; +#test 4 ultimate test; +create table t1 (a int primary key , b int, c blob , d blob , e varchar(2000), f int , g text, +unique (b,c), unique (b,f),unique(e,g),unique(a,b,c,d,e,f,g)); +desc t1; +Field Type Null Key Default Extra +a int(11) NO PRI NULL +b int(11) YES MUL NULL +c blob YES NULL +d blob YES NULL +e varchar(2000) YES MUL NULL +f int(11) YES NULL +g text YES NULL +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) NOT NULL, + `b` int(11) DEFAULT NULL, + `c` blob DEFAULT NULL, + `d` blob DEFAULT NULL, + `e` varchar(2000) DEFAULT NULL, + `f` int(11) DEFAULT NULL, + `g` text DEFAULT NULL, + PRIMARY KEY (`a`), + UNIQUE KEY `b` (`b`,`c`), + UNIQUE KEY `b_2` (`b`,`f`), + UNIQUE KEY `e` (`e`,`g`), + UNIQUE KEY `a` (`a`,`b`,`c`,`d`,`e`,`f`,`g`) +) 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 PRIMARY 1 a A 0 NULL NULL BTREE +t1 0 b 1 b A NULL NULL NULL YES HASH_INDEX +t1 0 b 2 c A NULL NULL NULL YES HASH_INDEX +t1 0 b_2 1 b A NULL NULL NULL YES BTREE +t1 0 b_2 2 f A NULL NULL NULL YES BTREE +t1 0 e 1 e A NULL NULL NULL YES HASH_INDEX +t1 0 e 2 g A 0 NULL NULL YES HASH_INDEX +t1 0 a 1 a A 0 NULL NULL 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 a 4 d A 0 NULL NULL YES HASH_INDEX +t1 0 a 5 e A 0 NULL NULL YES HASH_INDEX +t1 0 a 6 f A 0 NULL NULL YES HASH_INDEX +t1 0 a 7 g A 0 NULL NULL YES HASH_INDEX +insert into t1 values(1,1,1,1,1,1,1),(2,2,2,2,2,2,2),(3,3,3,3,3,3,3),(4,4,4,4,4,4,4), +(5,5,5,5,5,5,5),(6,6,6,6,6,6,6),(7,7,7,7,7,7,7),(8,8,8,8,8,8,8),(9,9,9,9,9,9,9); +select * from t1 limit 3; +a b c d e f g +1 1 1 1 1 1 1 +2 2 2 2 2 2 2 +3 3 3 3 3 3 3 +#key b_c +update t1 set b=2 ,c=2 where a=1; +ERROR 23000: Duplicate entry '2-2' for key 'b' +update t1 set b=b+34, c=c+34 where e=1 and g=1 ; +update t1 set b=35, c=35 where e=1 and g=1 ; +update t1 set b=b+1, c=c+1 where a>0; +update ignore t1 set b=b+1, c=c+1 where a>0; +select * from t1 ; +a b c d e f g +1 35 35 1 1 1 1 +2 2 2 2 2 2 2 +3 3 3 3 3 3 3 +4 4 4 4 4 4 4 +5 5 5 5 5 5 5 +6 6 6 6 6 6 6 +7 7 7 7 7 7 7 +8 8 8 8 8 8 8 +9 9 9 9 9 9 9 +truncate table t1; +insert into t1 values(1,1,1,1,1,1,1),(2,2,2,2,2,2,2),(3,3,3,3,3,3,3),(4,4,4,4,4,4,4), +(5,5,5,5,5,5,5),(6,6,6,6,6,6,6),(7,7,7,7,7,7,7),(8,8,8,8,8,8,8),(9,9,9,9,9,9,9); +#key b_f no hash key +update t1 set b=2 , f=2 where a=1; +ERROR 23000: Duplicate entry '2-2' for key 'b_2' +update t1 set b=b+33, f=f+33 where e=1 and g=1; +update t1 set b=34, f=34 where e=1 and g=1 ; +update t1 set b=b+1, f=f+1 where a>0; +ERROR 23000: Duplicate entry '3-3' for key 'b_2' +update ignore t1 set b=b+1, f=f+1 where a>0; +select * from t1 ; +a b c d e f g +1 36 1 1 1 36 1 +2 2 2 2 2 2 2 +3 3 3 3 3 3 3 +4 4 4 4 4 4 4 +5 5 5 5 5 5 5 +6 6 6 6 6 6 6 +7 7 7 7 7 7 7 +8 8 8 8 8 8 8 +9 10 9 9 9 10 9 +truncate table t1; +insert into t1 values(1,1,1,1,1,1,1),(2,2,2,2,2,2,2),(3,3,3,3,3,3,3),(4,4,4,4,4,4,4), +(5,5,5,5,5,5,5),(6,6,6,6,6,6,6),(7,7,7,7,7,7,7),(8,8,8,8,8,8,8),(9,9,9,9,9,9,9); +#key e_g +update t1 set e=2 , g=2 where a=1; +ERROR 23000: Duplicate entry '2-2' for key 'e' +update t1 set e=e+34, g=g+34 where a=1; +update t1 set e=34, g=34 where e=1 and g=1 ; +select * from t1 where a=1; +a b c d e f g +1 1 1 1 35 1 35 +update t1 set e=e+1, g=g+1 where a>0; +ERROR 23000: Duplicate entry '3-3' for key 'e' +update ignore t1 set e=e+1, g=g+1 where a>0; +select * from t1 ; +a b c d e f g +1 1 1 1 36 1 36 +2 2 2 2 2 2 2 +3 3 3 3 3 3 3 +4 4 4 4 4 4 4 +5 5 5 5 5 5 5 +6 6 6 6 6 6 6 +7 7 7 7 7 7 7 +8 8 8 8 8 8 8 +9 9 9 9 9 9 9 +drop table t1; diff --git a/mysql-test/main/long_unique_update.test b/mysql-test/main/long_unique_update.test new file mode 100644 index 00000000000..79cca079fe6 --- /dev/null +++ b/mysql-test/main/long_unique_update.test @@ -0,0 +1,137 @@ +--echo #structure of tests; +--echo #1 test of table containing single unique blob column; +--echo #2 test of table containing another unique int/ varchar etc column; +--echo #3 test of table containing multiple unique blob column like unique(a),unique(b); +--echo #4 test of table containing multiple multiple unique blob column like unique(a,b...),unique(c,d....); +--echo #structure of each test; +--echo #test if update works; +--echo #test update for duplicate entry; +--echo #test update for no change keys; +--echo #test update for ignore ; + +--echo #test 1 +create table t1 (a blob unique); +query_vertical show keys from t1; +insert into t1 values(1),(2),(3),(4),(5); +select * from t1; +update t1 set a=11 where a=5; +update t1 set a=a+20 where a=1; +select * from t1; +--error ER_DUP_ENTRY +update t1 set a=3 where a=2; +--error ER_DUP_ENTRY +update t1 set a=4 where a=3; +--echo #no change in blob key +update t1 set a=3 where a=3; +update t1 set a=2 where a=2; +select* from t1; +--echo #IGNORE; +update ignore t1 set a=3 where a=2; +update ignore t1 set a=4 where a=3; +select * from t1; +drop table t1; + +--echo #test 2; +create table t1 (a int primary key, b blob unique , c int unique ); +show keys from t1; +insert into t1 values(1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5),(6,6,6),(7,7,7); +select * from t1 limit 3; +update t1 set b=34 where a=1; +update t1 set b=a+c+b+34 where b=2; +update t1 set b=a+10+b where c=3; +select * from t1; +truncate table t1; +insert into t1 values(1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5),(6,6,6),(7,7,7); +--error ER_DUP_ENTRY +update t1 set b=4 where a=3; +--error ER_DUP_ENTRY +update t1 set b=a+1 where b=3; +--error ER_DUP_ENTRY +update t1 set b=a+1 where c=3; +--echo #no change in blob key +update t1 set b=3 where a=3; +update t1 set b=2 where b=2; +update t1 set b=5 where c=5; +select* from t1; +--echo #IGNORE; +update ignore t1 set b=3 where a=2; +update ignore t1 set b=4 where b=3; +update ignore t1 set b=5 where c=3; +select * from t1; +drop table t1; + +--echo #test 3; +create table t1 (a blob unique, b blob unique , c blob unique); +show keys from t1; +insert into t1 values(1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5),(6,6,6),(7,7,7); +select * from t1 limit 3; +update t1 set b=34 where a=1; +update t1 set b=a+c+b+34 where b=2; +update t1 set b=a+10+b where c=3; +select * from t1; +truncate table t1; +insert into t1 values(1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5),(6,6,6),(7,7,7); +--error ER_DUP_ENTRY +update t1 set b=4 where a=3; +--error ER_DUP_ENTRY +update t1 set b=a+1 where b=3; +--error ER_DUP_ENTRY +update t1 set b=a+1 where c=3; +--echo #no change in blob key +update t1 set b=3 where a=3; +update t1 set b=2 where b=2; +update t1 set b=5 where c=5; +select* from t1; +--echo #IGNORE; +update ignore t1 set b=3 where a=2; +update ignore t1 set b=4 where b=3; +update ignore t1 set b=5 where c=3; +update ignore t1 set b=b+3 where a>1 or b>1 or c>1; +select * from t1; +update ignore t1 set b=b+5 where a>1 and b<5 and c<a+b; +select * from t1; +drop table t1; + +--echo #test 4 ultimate test; +create table t1 (a int primary key , b int, c blob , d blob , e varchar(2000), f int , g text, +unique (b,c), unique (b,f),unique(e,g),unique(a,b,c,d,e,f,g)); +desc t1; +show create table t1; +show keys from t1; +insert into t1 values(1,1,1,1,1,1,1),(2,2,2,2,2,2,2),(3,3,3,3,3,3,3),(4,4,4,4,4,4,4), +(5,5,5,5,5,5,5),(6,6,6,6,6,6,6),(7,7,7,7,7,7,7),(8,8,8,8,8,8,8),(9,9,9,9,9,9,9); +select * from t1 limit 3; +--echo #key b_c +--error ER_DUP_ENTRY +update t1 set b=2 ,c=2 where a=1; +update t1 set b=b+34, c=c+34 where e=1 and g=1 ; +update t1 set b=35, c=35 where e=1 and g=1 ; +update t1 set b=b+1, c=c+1 where a>0; +update ignore t1 set b=b+1, c=c+1 where a>0; +select * from t1 ; +truncate table t1; +insert into t1 values(1,1,1,1,1,1,1),(2,2,2,2,2,2,2),(3,3,3,3,3,3,3),(4,4,4,4,4,4,4), +(5,5,5,5,5,5,5),(6,6,6,6,6,6,6),(7,7,7,7,7,7,7),(8,8,8,8,8,8,8),(9,9,9,9,9,9,9); +--echo #key b_f no hash key +--error ER_DUP_ENTRY +update t1 set b=2 , f=2 where a=1; +update t1 set b=b+33, f=f+33 where e=1 and g=1; +update t1 set b=34, f=34 where e=1 and g=1 ; +--error ER_DUP_ENTRY +update t1 set b=b+1, f=f+1 where a>0; +update ignore t1 set b=b+1, f=f+1 where a>0; +select * from t1 ; +truncate table t1; +insert into t1 values(1,1,1,1,1,1,1),(2,2,2,2,2,2,2),(3,3,3,3,3,3,3),(4,4,4,4,4,4,4), +(5,5,5,5,5,5,5),(6,6,6,6,6,6,6),(7,7,7,7,7,7,7),(8,8,8,8,8,8,8),(9,9,9,9,9,9,9); +--echo #key e_g +--error ER_DUP_ENTRY +update t1 set e=2 , g=2 where a=1; +update t1 set e=e+34, g=g+34 where a=1; +update t1 set e=34, g=34 where e=1 and g=1 ; +select * from t1 where a=1; +--error ER_DUP_ENTRY +update t1 set e=e+1, g=g+1 where a>0; +update ignore t1 set e=e+1, g=g+1 where a>0; +select * from t1 ; +drop table t1; diff --git a/sql/field.cc b/sql/field.cc index dd125a06bad..dd0efc75e4b 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -9811,7 +9811,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) { if (bit_len) { diff --git a/sql/field.h b/sql/field.h index e762e45c024..bd7cdd1e60d 100644 --- a/sql/field.h +++ b/sql/field.h @@ -543,6 +543,7 @@ public: LEX_CSTRING name; /* Name of constraint */ /* see VCOL_* (VCOL_FIELD_REF, ...) */ uint flags; + LEX_CSTRING hash_expr; Virtual_column_info() : vcol_type((enum_vcol_info_type)VCOL_TYPE_NONE), @@ -552,8 +553,14 @@ public: { name.str= NULL; name.length= 0; + hash_expr.str= NULL; + hash_expr.length= 0; }; - ~Virtual_column_info() {} + ~Virtual_column_info() + { + if (!hash_expr.length) + my_free((void *)hash_expr.str); + } enum_vcol_info_type get_vcol_type() const { return vcol_type; @@ -687,7 +694,7 @@ public: GEOM_MULTIPOINT = 4, GEOM_MULTILINESTRING = 5, GEOM_MULTIPOLYGON = 6, GEOM_GEOMETRYCOLLECTION = 7 }; - enum imagetype { itRAW, itMBR}; + enum imagetype { itRAW, itMBR, itHASH}; utype unireg_check; uint32 field_length; // Length of field @@ -1083,7 +1090,7 @@ public: virtual int cmp(const uchar *,const uchar *)=0; virtual int cmp_binary(const uchar *a,const uchar *b, uint32 max_length=~0U) { return memcmp(a,b,pack_length()); } - virtual int cmp_offset(uint row_offset) + virtual int cmp_offset(long row_offset) { return cmp(ptr,ptr+row_offset); } virtual int cmp_binary_offset(uint row_offset) { return cmp_binary(ptr, ptr+row_offset); }; @@ -4311,7 +4318,7 @@ public: int key_cmp(const uchar *a, const uchar *b) { return cmp_binary((uchar *) a, (uchar *) b); } int key_cmp(const uchar *str, uint length); - int cmp_offset(uint row_offset); + int cmp_offset(long row_offset); bool update_min(Field *min_val, bool force_update) { longlong val= val_int(); diff --git a/sql/handler.cc b/sql/handler.cc index 001055cd475..3dbb21d39c5 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -2710,6 +2710,7 @@ int handler::ha_open(TABLE *table_arg, const char *name, int mode, test_if_locked)); table= table_arg; + setup_table_hash(table); DBUG_ASSERT(table->s == table_share); DBUG_ASSERT(m_lock_type == F_UNLCK); DBUG_PRINT("info", ("old m_lock_type: %d F_UNLCK %d", m_lock_type, F_UNLCK)); @@ -2726,6 +2727,7 @@ int handler::ha_open(TABLE *table_arg, const char *name, int mode, error=open(name,O_RDONLY,test_if_locked); } } + re_setup_table(table); if (unlikely(error)) { my_errno= error; /* Safeguard */ @@ -4108,6 +4110,8 @@ uint handler::get_dup_key(int error) m_lock_type != F_UNLCK); DBUG_ENTER("handler::get_dup_key"); table->file->errkey = (uint) -1; + if (table->dupp_hash_key != -1) + DBUG_RETURN(table->dupp_hash_key); if (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOREIGN_DUPLICATE_KEY || error == HA_ERR_FOUND_DUPP_UNIQUE || error == HA_ERR_NULL_IN_SPATIAL || @@ -4627,7 +4631,9 @@ handler::ha_create(const char *name, TABLE *form, HA_CREATE_INFO *info_arg) { DBUG_ASSERT(m_lock_type == F_UNLCK); mark_trx_read_write(); + setup_table_hash(form); int error= create(name, form, info_arg); + re_setup_table(form); if (!error && !(info_arg->options & (HA_LEX_CREATE_TMP_TABLE | HA_CREATE_TMP_ALTER))) mysql_audit_create_table(form); @@ -6256,6 +6262,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; + 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); + + 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; + } + } + } + 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; + } + 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) { @@ -6266,14 +6451,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); 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++; @@ -6298,9 +6490,15 @@ int handler::ha_update_row(const uchar *old_data, const uchar *new_data) DBUG_ASSERT(new_data == table->record[0]); DBUG_ASSERT(old_data == table->record[1]); + setup_table_hash(table); MYSQL_UPDATE_ROW_START(table_share->db.str, table_share->table_name.str); mark_trx_read_write(); increment_statistics(&SSV::ha_update_count); + if ((error= check_duplicate_long_entries_update(table, table->file, (uchar *)new_data))) + { + re_setup_table(table); + return error; + } TABLE_IO_WAIT(tracker, m_psi, PSI_TABLE_UPDATE_ROW, active_index, 0, { error= update_row(old_data, new_data);}) @@ -6311,6 +6509,7 @@ int handler::ha_update_row(const uchar *old_data, const uchar *new_data) rows_changed++; error= binlog_log_row(table, old_data, new_data, log_func); } + re_setup_table(table); return error; } diff --git a/sql/item_func.cc b/sql/item_func.cc index 1f949a4445b..24bb3d19cc5 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1719,6 +1719,36 @@ bool Item_func_mod::fix_length_and_dec() } +longlong Item_func_hash::val_int() +{ + unsigned_flag= true; + ulong nr1= 1,nr2= 4; + CHARSET_INFO *cs; + String * str; + for(uint i= 0;i<arg_count;i++) + { + str = args[i]->val_str(); + if(args[i]->null_value) + { + null_value= 1; + return 0; + } + calc_hash_for_unique(nr1, nr2, str); + } + null_value= 0; + return (longlong)nr1; +} + + +void Item_func_hash::fix_length_and_dec() +{ + maybe_null= 1; + decimals= 0; + max_length= 8; +} + + + double Item_func_neg::real_op() { double value= args[0]->val_real(); diff --git a/sql/item_func.h b/sql/item_func.h index 1081f2919c8..c80f48f15b1 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1019,6 +1019,19 @@ public: }; +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"; } +}; + class Item_longlong_func: public Item_int_func { public: diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 04baf5737c6..c660af38118 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -17296,6 +17296,9 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, table->intersect_keys.init(); table->keys_in_use_for_query.init(); table->no_rows_with_nulls= param->force_not_null_cols; + table->update_handler= NULL; + table->dupp_hash_key= -1; + table->check_unique_buf= NULL; table->s= share; init_tmp_table_share(thd, share, "", 0, tmpname, tmpname); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 5adee6731b5..885c989e197 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2306,7 +2306,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) packet->append(STRING_WITH_LEN("UNIQUE KEY ")); else if (key_info->flags & HA_FULLTEXT) packet->append(STRING_WITH_LEN("FULLTEXT KEY ")); @@ -6593,8 +6593,13 @@ static int get_schema_stat_record(THD *thd, TABLE_LIST *tables, table->field[9]->store((longlong) records, TRUE); table->field[9]->set_notnull(); } - const char *tmp= show_table->file->index_type(i); - table->field[13]->store(tmp, strlen(tmp), cs); + if (key->flags & HA_LONG_UNIQUE_HASH) + table->field[13]->store(STRING_WITH_LEN("HASH_INDEX"), cs); + else + { + const char *tmp= show_table->file->index_type(i); + table->field[13]->store(tmp, strlen(tmp), cs); + } } if (!(key_info->flags & HA_FULLTEXT) && (key_part->field && diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 666c6fb325a..0389dc970a3 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3323,6 +3323,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 + 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 +*/ + +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); + /* + Check for collusions + */ + 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); + 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; + } + }*/ + 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; + } + 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; + } + } + */ + /* hash column should be fully hidden */ + //prepare_create_field(cf, NULL, 0); + create_list->push_back(cf,thd->mem_root); +} + + /* Preparation for table creation @@ -3368,6 +3449,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, uint total_uneven_bit_length= 0; int select_field_count= C_CREATE_SELECT(create_table_mode); bool tmp_table= create_table_mode == C_ALTER_TABLE; + bool is_hash_field_added= false; DBUG_ENTER("mysql_prepare_create_table"); DBUG_EXECUTE_IF("test_pseudo_invisible",{ @@ -3685,6 +3767,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, uint key_length=0; Key_part_spec *column; + is_hash_field_added= false; if (key->name.str == ignore_key) { /* ignore redundant keys */ @@ -3852,6 +3935,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; if (key->type == Key::FULLTEXT) { if ((sql_field->real_field_type() != MYSQL_TYPE_STRING && @@ -3906,8 +3991,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; + is_hash_field_added= true; + } } } #ifdef HAVE_SPATIAL @@ -3971,8 +4067,6 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, } } - key_part_info->fieldnr= field; - key_part_info->offset= (uint16) sql_field->offset; key_part_info->key_type=sql_field->pack_flag; uint key_part_length= sql_field->key_length; @@ -3986,9 +4080,9 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, if (key_part_length > max_key_length || key_part_length > file->max_key_part_length()) { - key_part_length= MY_MIN(max_key_length, file->max_key_part_length()); if (key->type == Key::MULTIPLE) { + key_part_length= MY_MIN(max_key_length, file->max_key_part_length()); /* not a critical problem */ push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, ER_TOO_LONG_KEY, @@ -3997,11 +4091,13 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, /* Align key length to multibyte char boundary */ key_part_length-= key_part_length % sql_field->charset->mbmaxlen; } - else - { - my_error(ER_TOO_LONG_KEY, MYF(0), key_part_length); - 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); + is_hash_field_added= true; + } } } // Catch invalid use of partial keys @@ -4025,7 +4121,8 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, else if (!(file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS)) key_part_length= column->length; } - else if (key_part_length == 0 && (sql_field->flags & NOT_NULL_FLAG)) + else if (key_part_length == 0 && (sql_field->flags & NOT_NULL_FLAG) && + !is_hash_field_added) { my_error(ER_WRONG_KEY_COLUMN, MYF(0), file->table_type(), column->field_name.str); @@ -4034,9 +4131,9 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, if (key_part_length > file->max_key_part_length() && key->type != Key::FULLTEXT) { - key_part_length= file->max_key_part_length(); if (key->type == Key::MULTIPLE) { + key_part_length= file->max_key_part_length(); /* not a critical problem */ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_TOO_LONG_KEY, ER_THD(thd, ER_TOO_LONG_KEY), @@ -4046,11 +4143,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; + } + } + else + { + my_error(ER_TOO_LONG_KEY, MYF(0), key_part_length); + 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 */ + 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)) && @@ -4106,12 +4221,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; */ + } + } if (validate_comment_length(thd, &key->key_create_info.comment, INDEX_COMMENT_MAXLEN, ER_TOO_LONG_INDEX_COMMENT, @@ -8319,6 +8459,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; + } key_create_info.algorithm= key_info->algorithm; /* We copy block size directly as some engines, like Area, sets this @@ -8358,6 +8503,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, tmp_name.str= key_name; tmp_name.length= strlen(key_name); + /* We dont need LONG_UNIQUE_HASH_FIELD flag because it will be autogenerated */ key= new Key(key_type, &tmp_name, &key_create_info, MY_TEST(key_info->flags & HA_GENERATED_KEY), &key_parts, key_info->option_list, DDL_options()); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index d74da408dfc..b5395c1afa9 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -861,6 +861,7 @@ update_begin: */ can_compare_record= records_are_comparable(table); explain->tracker.on_scan_init(); + create_update_handler(thd, table); THD_STAGE_INFO(thd, stage_updating); while (!(error=info.read_record()) && !thd->killed) @@ -1055,6 +1056,7 @@ update_begin: break; } } + delete_update_handler(thd, table); ANALYZE_STOP_TRACKING(&explain->command_tracker); table->auto_increment_field_not_null= FALSE; dup_key_found= 0; @@ -2092,6 +2094,7 @@ multi_update::initialize_tables(JOIN *join) if (ignore) table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); + create_update_handler(join->thd, table); if (table == main_table) // First table in join { if (safe_update_on_fly(thd, join->join_tab, table_ref, all_tables)) @@ -2268,7 +2271,8 @@ multi_update::~multi_update() TABLE_LIST *table; for (table= update_tables ; table; table= table->next_local) { - table->table->no_keyread= 0; + table->table->no_keyread= table->table->no_cache= 0; + delete_update_handler(thd, table->table); if (ignore) table->table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index f628ef098a1..2177ec22351 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -10820,6 +10820,12 @@ function_call_conflict: if (unlikely($$ == NULL)) MYSQL_YYABORT; } + | HASH_SYM '(' expr_list ')' + { + $$= new (thd->mem_root)Item_func_hash(thd,*$3); + if (unlikely($$ == NULL)) + MYSQL_YYABORT; + } /* LAST_VALUE here conflicts with the definition for window functions. We have these 2 separate rules to remove the shift/reduce conflict. */ diff --git a/sql/table.cc b/sql/table.cc index 0a40c5fb341..bf13b6aca2d 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -44,6 +44,7 @@ #include "sql_cte.h" #include "ha_sequence.h" #include "sql_show.h" +#include "my_base.h" /* For MySQL 5.7 virtual fields */ #define MYSQL57_GENERATED_FIELD 128 @@ -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); - n_length=keys * sizeof(KEY) + ext_key_parts * sizeof(KEY_PART_INFO); + /* + 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 +keys) * sizeof(KEY_PART_INFO); 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++; + } /* Add primary key to end of extended keys for non unique keys for @@ -1048,6 +1063,7 @@ bool parse_vcol_defs(THD *thd, MEM_ROOT *mem_root, TABLE *table, Query_arena backup_arena; Virtual_column_info *vcol= 0; StringBuffer<MAX_FIELD_WIDTH> expr_str; + uint length= 0; bool res= 1; DBUG_ENTER("parse_vcol_defs"); @@ -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); + *(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(')'); @@ -1251,12 +1275,14 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, uint db_create_options, keys, key_parts, n_length; uint com_length, null_bit_pos, UNINIT_VAR(mysql57_vcol_null_bit_pos), bitmap_count; uint i; + uint field_additional_property_length= 0; bool use_hash, mysql57_null_bits= 0; char *keynames, *names, *comment_pos; const uchar *forminfo, *extra2; const uchar *frm_image_end = frm_image + frm_length; uchar *record, *null_flags, *null_pos, *UNINIT_VAR(mysql57_vcol_null_pos); const uchar *disk_buff, *strpos; + const uchar * field_properties=NULL; ulong pos, record_offset; ulong rec_buff_length; handler *handler_file= 0; @@ -2107,7 +2133,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; reg_field->invisible= f_visibility(flags); } if (reg_field->invisible == INVISIBLE_USER) @@ -2178,6 +2205,66 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, /* Fix key->name and key_part->field */ if (key_parts) { + keyinfo= share->key_info; + uint hash_field_used_no= share->fields -1 ; + KEY_PART_INFO *hash_keypart, *temp_key_part; + Field *hash_fld, *temp_fld; + for (uint i= 0; i < share->keys; i++, keyinfo++) + { + /* + 1. We need set value in hash key_part + 2. Set vcol_info in corresponding db_row_hash_ field + */ + if (keyinfo->flags & HA_LONG_UNIQUE_HASH) + { + DBUG_ASSERT(share->field[hash_field_used_no]->flags & LONG_UNIQUE_HASH_FIELD); + hash_keypart= keyinfo->key_part + keyinfo->user_defined_key_parts; + /* Last n fields are unique_index_hash fields*/ + hash_keypart->fieldnr= hash_field_used_no + 1; + hash_keypart->length= HA_HASH_KEY_LENGTH_WITHOUT_NULL; + hash_keypart->store_length= hash_keypart->length; + hash_keypart->type= HA_KEYTYPE_ULONGLONG; + hash_keypart->key_part_flag= 0; + hash_keypart->key_type= 32834; + hash_keypart->offset= share->reclength + - HA_HASH_FIELD_LENGTH*(share->fields - hash_field_used_no); + hash_fld= share->field[hash_field_used_no]; + temp_key_part= keyinfo->key_part; + Virtual_column_info *v= new (&share->mem_root) Virtual_column_info(); + String hash_str; + hash_str.append(ha_hash_str.str,ha_hash_str.length); + hash_str.append(STRING_WITH_LEN("(")); + for (uint j= 0; j < keyinfo->user_defined_key_parts; j++, + temp_key_part++) + { + if (j) + hash_str.append(STRING_WITH_LEN(" , ")); + temp_fld= share->field[temp_key_part->fieldnr-1]; + DBUG_ASSERT(temp_fld); + if (!temp_key_part->length || + temp_key_part->length == temp_fld->max_display_length()) + append_identifier(thd, &hash_str, temp_fld->field_name.str, + strlen(temp_fld->field_name.str)); + else + { + hash_str.append(STRING_WITH_LEN(" LEFT(")); + append_identifier(thd, &hash_str, temp_fld->field_name.str, + strlen(temp_fld->field_name.str)); + char temp[20]; + my_snprintf((char *)temp, 20, ", %u )", temp_key_part->length); + hash_str.append((char *)temp); + } + } + hash_str.append(STRING_WITH_LEN(")")); + char * expr_str= (char *)alloc_root(&share->mem_root, hash_str.length()+1); + strncpy(expr_str, hash_str.ptr(), hash_str.length()); + v->hash_expr.str= expr_str; + v->hash_expr.length= hash_str.length(); + hash_fld->vcol_info= v; + share->virtual_fields++; + hash_field_used_no--; + } + } uint add_first_key_parts= 0; longlong ha_option= handler_file->ha_table_flags(); keyinfo= share->key_info; @@ -2284,9 +2371,10 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, if (field->null_ptr) len_null_byte= HA_KEY_NULL_LENGTH; - if (field->type() == MYSQL_TYPE_BLOB || + if ((field->type() == MYSQL_TYPE_BLOB || field->real_type() == MYSQL_TYPE_VARCHAR || - field->type() == MYSQL_TYPE_GEOMETRY) + field->type() == MYSQL_TYPE_GEOMETRY) && + !(keyinfo->flags & HA_LONG_UNIQUE_HASH)) { length_bytes= HA_KEY_BLOB_LENGTH; } @@ -2351,6 +2439,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++; for (i=0; i < key_parts; key_part++, i++) { Field *field; @@ -2364,7 +2454,13 @@ 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 (field->invisible > INVISIBLE_USER && !field->vers_sys_field()) + if (keyinfo->flags & HA_LONG_UNIQUE_HASH + &&(key_part->length > handler_file->max_key_part_length() + || key_part->length == 0)) + key_part->store_length= HA_HASH_KEY_PART_LENGTH; + /* Invisible Full is currently used by long uniques */ + if ((field->invisible == INVISIBLE_USER || + field->invisible == INVISIBLE_SYSTEM )&& !field->vers_sys_field()) keyinfo->flags |= HA_INVISIBLE_KEY; if (field->null_ptr) { @@ -2429,7 +2525,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)) { #ifndef TO_BE_DELETED_ON_PRODUCTION if (field->type() == MYSQL_TYPE_NEWDECIMAL) @@ -2471,7 +2568,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)) key_part->key_part_flag|= HA_CAN_MEMCMP; } keyinfo->usable_key_parts= usable_parts; // Filesort @@ -3165,7 +3263,8 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share, const char *tmp_alias; bool error_reported= FALSE; uchar *record, *bitmaps; - Field **field_ptr; + Field **field_ptr, *field; + KEY *key_info; uint8 save_context_analysis_only= thd->lex->context_analysis_only; TABLE_SHARE::enum_v_keys check_set_initialized= share->check_set_initialized; DBUG_ENTER("open_table_from_share"); @@ -3180,6 +3279,7 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share, outparam->s= share; outparam->db_stat= db_stat; outparam->write_row_record= NULL; + outparam->dupp_hash_key= -1; if (share->incompatible_version && !(ha_open_flags & (HA_OPEN_FOR_ALTER | HA_OPEN_FOR_REPAIR))) @@ -3322,6 +3422,8 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share, key_part_end= key_part + (share->use_ext_keys ? key_info->ext_key_parts : key_info->user_defined_key_parts) ; + if (key_info->flags & HA_LONG_UNIQUE_HASH) + key_part_end++; for ( ; key_part < key_part_end; key_part++) { Field *field= key_part->field= outparam->field[key_part->fieldnr - 1]; @@ -4656,6 +4758,9 @@ void TABLE::init(THD *thd, TABLE_LIST *tl) created= TRUE; cond_selectivity= 1.0; cond_selectivity_sampling_explain= NULL; + update_handler= NULL; + dupp_hash_key= -1; + check_unique_buf= NULL; #ifdef HAVE_REPLICATION /* used in RBR Triggers */ master_had_triggers= 0; @@ -8498,6 +8603,235 @@ 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) +{ + 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(); +} + +/** + @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) +{ + handler *update_handler= NULL; + for (uint i= 0; i < table->s->keys; i++) + { + 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; + 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) +{ + /* + 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 + */ + + 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; + } + 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; + } + } +} + LEX_CSTRING *fk_option_name(enum_fk_option opt) { static LEX_CSTRING names[]= @@ -8967,3 +9301,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()); +} diff --git a/sql/table.h b/sql/table.h index 1720a212a1f..c8d7decd8e4 100644 --- a/sql/table.h +++ b/sql/table.h @@ -346,8 +346,32 @@ 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_PART_LENGTH 4 + 8 // 4 for length , 8 for portable size of char ptr +const LEX_CSTRING ha_hash_str {STRING_WITH_LEN("HASH")}; + + +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); + +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); /** Category of table found in the table share. @@ -1105,6 +1129,17 @@ public: 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 + */ + int dupp_hash_key; uchar *write_row_record; /* Used as optimisation in THD::write_row */ uchar *insert_values; /* used by INSERT ... UPDATE */ @@ -2929,6 +2964,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); /* 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/unireg.cc b/sql/unireg.cc index 4692b2d74d1..44e24554691 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -101,6 +101,8 @@ static uchar *extra2_write_field_properties(uchar *pos, uchar flags= cf->invisible; if (cf->flags & VERS_UPDATE_UNVERSIONED_FLAG) flags|= VERS_OPTIMIZED_UPDATE; + if (cf->flags & LONG_UNIQUE_HASH_FIELD) + flags|= EXTRA2_LONG_UNIQUE_HASH_FIELD; *pos++= flags; } return pos; diff --git a/sql/unireg.h b/sql/unireg.h index 6f224ab4894..1e360d61e36 100644 --- a/sql/unireg.h +++ b/sql/unireg.h @@ -179,7 +179,8 @@ enum extra2_frm_value_type { }; enum extra2_field_flags { - VERS_OPTIMIZED_UPDATE= 1 << INVISIBLE_MAX_BITS + VERS_OPTIMIZED_UPDATE= 1 << INVISIBLE_MAX_BITS, + EXTRA2_LONG_UNIQUE_HASH_FIELD= 1 << HASH_FIELD_MASK_SHIFT }; int rea_create_table(THD *thd, LEX_CUSTRING *frm, |