diff options
author | Sachin <sachin.setiya@mariadb.com> | 2019-01-08 19:42:02 +0530 |
---|---|---|
committer | Sachin <sachin.setiya@mariadb.com> | 2019-01-08 19:42:02 +0530 |
commit | ab6393d13dfba93308569b934f579f82c6b9ff03 (patch) | |
tree | efc19acfaef1ce9ff5374969b0ef1be7cccaa68e | |
parent | 292b2fd23bbdf0ef406c90036c166dbca793db4b (diff) | |
download | mariadb-git-ab6393d13dfba93308569b934f579f82c6b9ff03.tar.gz |
Final changes
-rw-r--r-- | mysql-test/main/long_unique.test | 1 | ||||
-rw-r--r-- | mysql-test/main/long_unique_innodb.result | 121 | ||||
-rw-r--r-- | mysql-test/main/long_unique_innodb.test | 131 | ||||
-rw-r--r-- | mysql-test/main/mdev-504.test | 3 | ||||
-rw-r--r-- | sql/handler.cc | 9 | ||||
-rw-r--r-- | sql/sql_base.cc | 2 | ||||
-rw-r--r-- | sql/sql_show.cc | 16 | ||||
-rw-r--r-- | sql/sql_table.cc | 7 | ||||
-rw-r--r-- | sql/sql_update.cc | 6 | ||||
-rw-r--r-- | sql/table.cc | 69 | ||||
-rw-r--r-- | sql/table.h | 17 |
11 files changed, 310 insertions, 72 deletions
diff --git a/mysql-test/main/long_unique.test b/mysql-test/main/long_unique.test index 41c18178ae5..93c70eac80e 100644 --- a/mysql-test/main/long_unique.test +++ b/mysql-test/main/long_unique.test @@ -1,4 +1,5 @@ let datadir=`select @@datadir`; +--source include/have_partition.inc --echo #Structure of tests --echo #First we will check all option for diff --git a/mysql-test/main/long_unique_innodb.result b/mysql-test/main/long_unique_innodb.result new file mode 100644 index 00000000000..e5863401e38 --- /dev/null +++ b/mysql-test/main/long_unique_innodb.result @@ -0,0 +1,121 @@ +create table t1(a blob unique) engine= InnoDB; +insert into t1 values('RUC'); +insert into t1 values ('RUC'); +ERROR 23000: Duplicate entry 'RUC' for key 'a' +drop table t1; +#test for concurrent insert of long unique in innodb +create table t1(a blob unique) engine= InnoDB; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` blob DEFAULT NULL, + UNIQUE KEY `a` (`a`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +connect 'con1', localhost, root,,; +connect 'con2', localhost, root,,; +connection con1; +set transaction isolation level READ UNCOMMITTED; +start transaction; +insert into t1 values('RUC'); +connection con2; +set transaction isolation level READ UNCOMMITTED; +start transaction; +insert into t1 values ('RUC'); +ERROR 23000: Duplicate entry 'RUC' for key 'a' +connection con1; +commit; +set transaction isolation level READ COMMITTED; +start transaction; +insert into t1 values('RC'); +connection con2; +commit; +set transaction isolation level READ COMMITTED; +start transaction; +insert into t1 values ('RC'); +ERROR 23000: Duplicate entry 'RC' for key 'a' +commit; +connection con1; +commit; +set transaction isolation level REPEATABLE READ; +start transaction; +insert into t1 values('RR'); +connection con2; +commit; +set transaction isolation level REPEATABLE READ; +start transaction; +insert into t1 values ('RR'); +ERROR 23000: Duplicate entry 'RR' for key 'a' +connection con1; +commit; +set transaction isolation level SERIALIZABLE; +start transaction; +insert into t1 values('S'); +connection con2; +commit; +set transaction isolation level SERIALIZABLE; +start transaction; +insert into t1 values ('S'); +ERROR 23000: Duplicate entry 'S' for key 'a' +commit; +connection con1; +commit; +select * from t1; +a +RUC +RC +RR +S +drop table t1; +create table t1(a blob unique) engine=Innodb; +connection con1; +set transaction isolation level READ UNCOMMITTED; +start transaction; +insert into t1 values('RUC'); +connection con2; +set transaction isolation level READ UNCOMMITTED; +start transaction; +insert into t1 values ('RUC');; +connection con1; +rollback; +connection con2; +commit; +connection con1; +set transaction isolation level READ COMMITTED; +start transaction; +insert into t1 values('RC'); +connection con2; +set transaction isolation level READ COMMITTED; +start transaction; +insert into t1 values ('RC');; +connection con1; +rollback; +connection con2; +commit; +connection con1; +set transaction isolation level REPEATABLE READ; +start transaction; +insert into t1 values('RR'); +connection con2; +set transaction isolation level REPEATABLE READ; +start transaction; +insert into t1 values ('RR');; +connection con1; +rollback; +connection con2; +commit; +connection con1; +set transaction isolation level SERIALIZABLE; +start transaction; +insert into t1 values('S'); +connection con2; +set transaction isolation level SERIALIZABLE; +start transaction; +insert into t1 values ('S');; +connection con1; +rollback; +connection con2; +commit; +connection default; +drop table t1; +disconnect con1; +disconnect con2; diff --git a/mysql-test/main/long_unique_innodb.test b/mysql-test/main/long_unique_innodb.test new file mode 100644 index 00000000000..0918d1e0c68 --- /dev/null +++ b/mysql-test/main/long_unique_innodb.test @@ -0,0 +1,131 @@ +--source include/have_innodb.inc +--source include/big_test.inc + +create table t1(a blob unique) engine= InnoDB; +insert into t1 values('RUC'); +--error ER_DUP_ENTRY +insert into t1 values ('RUC'); +drop table t1; + +--echo #test for concurrent insert of long unique in innodb +create table t1(a blob unique) engine= InnoDB; +show create table t1; +connect ('con1', localhost, root,,); +connect ('con2', localhost, root,,); + +--connection con1 +set transaction isolation level READ UNCOMMITTED; +start transaction; +insert into t1 values('RUC'); +--connection con2 +set transaction isolation level READ UNCOMMITTED; +start transaction; +--error ER_DUP_ENTRY +insert into t1 values ('RUC'); + +--connection con1 +commit; +set transaction isolation level READ COMMITTED; +start transaction; +insert into t1 values('RC'); +--connection con2 +commit; +set transaction isolation level READ COMMITTED; +start transaction; +--error ER_DUP_ENTRY +insert into t1 values ('RC'); +commit; + +--connection con1 +commit; +set transaction isolation level REPEATABLE READ; +start transaction; +insert into t1 values('RR'); +--connection con2 +commit; +set transaction isolation level REPEATABLE READ; +start transaction; +--error ER_DUP_ENTRY +insert into t1 values ('RR'); + +--connection con1 +commit; +set transaction isolation level SERIALIZABLE; +start transaction; +insert into t1 values('S'); +--connection con2 +commit; +set transaction isolation level SERIALIZABLE; +start transaction; +--error ER_DUP_ENTRY +insert into t1 values ('S'); +commit; + +--connection con1 +commit; + +select * from t1; +drop table t1; + +create table t1(a blob unique) engine=Innodb; + +--connection con1 +set transaction isolation level READ UNCOMMITTED; +start transaction; +insert into t1 values('RUC'); +--connection con2 +set transaction isolation level READ UNCOMMITTED; +start transaction; +--send insert into t1 values ('RUC'); +--connection con1 +rollback; +--connection con2 +--reap +commit; + +--connection con1 +set transaction isolation level READ COMMITTED; +start transaction; +insert into t1 values('RC'); +--connection con2 +set transaction isolation level READ COMMITTED; +start transaction; +--send insert into t1 values ('RC'); +--connection con1 +rollback; +--connection con2 +--reap +commit; + +--connection con1 +set transaction isolation level REPEATABLE READ; +start transaction; +insert into t1 values('RR'); +--connection con2 +set transaction isolation level REPEATABLE READ; +start transaction; +--send insert into t1 values ('RR'); +--connection con1 +rollback; +--connection con2 +--reap +commit; + +--connection con1 +set transaction isolation level SERIALIZABLE; +start transaction; +insert into t1 values('S'); +--connection con2 +set transaction isolation level SERIALIZABLE; +start transaction; +--send insert into t1 values ('S'); +--connection con1 +rollback; +--connection con2 +--reap +commit; + +connection default; +drop table t1; +disconnect con1; +disconnect con2; diff --git a/mysql-test/main/mdev-504.test b/mysql-test/main/mdev-504.test index 277b5a038a0..75b84f576db 100644 --- a/mysql-test/main/mdev-504.test +++ b/mysql-test/main/mdev-504.test @@ -1,4 +1,3 @@ ---source include/not_valgrind.inc --source include/no_protocol.inc set @save_use_stat_tables=@@global.use_stat_tables; @@ -44,7 +43,7 @@ while ($trial) --connect (con2,localhost,root,,) --send CALL p_analyze() - --let $run = 100 + --let $run = 1 while ($run) { diff --git a/sql/handler.cc b/sql/handler.cc index 22e9a38f268..e1569c894da 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -3698,7 +3698,7 @@ void handler::print_error(int error, myf errflag) setup_keyinfo_hash(long_key); DBUG_VOID_RETURN; } - setup_table_hash(table); + table->re_setup_table(); } textno=ER_DUP_KEY; break; @@ -6384,19 +6384,18 @@ static int check_duplicate_long_entries(TABLE *table, handler *h, uchar *new_rec */ static int check_duplicate_long_entries_update(TABLE *table, handler *h, uchar *new_rec) { - Field **f, *field; - int key_parts; + Field *field; + uint key_parts; int error= 0; KEY *keyinfo; KEY_PART_INFO *keypart; - 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]; if (!table->update_handler) - clone_handler_for_update(current_thd, table); + table->clone_handler_for_update(); for (uint i= 0; i < table->s->keys; i++) { keyinfo= table->key_info + i; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 1b4ffd0c61e..4af078e84cd 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -994,6 +994,8 @@ void close_thread_table(THD *thd, TABLE **table_ptr) table->file->update_global_table_stats(); table->file->update_global_index_stats(); } + if (table->update_handler) + table->delete_update_handler(); /* This look is needed to allow THD::notify_shared_lock() to diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 05b17a476ec..b13a7de6339 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2083,7 +2083,7 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, uint primary_key; KEY *key_info; TABLE *table= table_list->table; - re_setup_table(table); + table->setup_table_hash(); TABLE_SHARE *share= table->s; sql_mode_t sql_mode= thd->variables.sql_mode; bool explicit_fields= false; @@ -2442,7 +2442,7 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, } #endif tmp_restore_column_map(table->read_set, old_map); - setup_table_hash(table); + table->re_setup_table(); DBUG_RETURN(error); } @@ -6556,7 +6556,7 @@ static int get_schema_stat_record(THD *thd, TABLE_LIST *tables, HA_STATUS_TIME); set_statistics_for_table(thd, show_table); } - re_setup_table(show_table); + show_table->setup_table_hash(); for (uint i=0 ; i < show_table->s->keys ; i++,key_info++) { if ((key_info->flags & HA_INVISIBLE_KEY) && @@ -6630,7 +6630,7 @@ static int get_schema_stat_record(THD *thd, TABLE_LIST *tables, DBUG_RETURN(1); } } - setup_table_hash(show_table); + show_table->re_setup_table(); } DBUG_RETURN(res); } @@ -6859,7 +6859,7 @@ static int get_schema_constraints_record(THD *thd, TABLE_LIST *tables, show_table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME); - re_setup_table(show_table); + show_table->setup_table_hash(); for (uint i=0 ; i < show_table->s->keys ; i++, key_info++) { if (i != primary_key && !(key_info->flags & HA_NOSAME)) @@ -6880,7 +6880,7 @@ static int get_schema_constraints_record(THD *thd, TABLE_LIST *tables, DBUG_RETURN(1); } } - setup_table_hash(show_table); + show_table->re_setup_table(); // Table check constraints for ( uint i = 0; i < show_table->s->table_check_constraints; i++ ) @@ -7059,7 +7059,7 @@ static int get_schema_key_column_usage_record(THD *thd, show_table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME); - re_setup_table(show_table); + show_table->setup_table_hash(); for (uint i=0 ; i < show_table->s->keys ; i++, key_info++) { if (i != primary_key && !(key_info->flags & HA_NOSAME)) @@ -7082,7 +7082,7 @@ static int get_schema_key_column_usage_record(THD *thd, } } } - setup_table_hash(show_table); + show_table->re_setup_table(); show_table->file->get_foreign_key_list(thd, &f_key_list); FOREIGN_KEY_INFO *f_key_info; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index a546e1aaa4e..97817ece33b 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3906,8 +3906,6 @@ 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 && @@ -3968,10 +3966,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, DBUG_RETURN(TRUE); } else - { is_hash_field_needed= true; - column->length= 0; - } } } #ifdef HAVE_SPATIAL @@ -4035,6 +4030,8 @@ 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; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 2bce61903ca..79e8bd5ea8c 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -1055,7 +1055,8 @@ update_begin: break; } } - delete_update_handler(thd, table); + if (table->update_handler) + table->delete_update_handler(); ANALYZE_STOP_TRACKING(&explain->command_tracker); table->auto_increment_field_not_null= FALSE; dup_key_found= 0; @@ -2270,7 +2271,8 @@ multi_update::~multi_update() for (table= update_tables ; table; table= table->next_local) { table->table->no_keyread= table->table->no_cache= 0; - delete_update_handler(thd, table->table); + if (table->table->update_handler) + table->table->delete_update_handler(); if (ignore) table->table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); } diff --git a/sql/table.cc b/sql/table.cc index e2167d5a8c4..d748ed23644 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -8769,78 +8769,67 @@ int find_field_pos_in_hash(Item *hash_item, const char * field_name) /* find total number of field in hash expr */ -inline int fields_in_hash_keyinfo(KEY *keyinfo) +int fields_in_hash_keyinfo(KEY *keyinfo) { Item_func_hash * temp= (Item_func_hash *) keyinfo->key_part->field->vcol_info->expr; return temp->argument_count(); } -inline void setup_keyinfo_hash(KEY *key_info) +void setup_keyinfo_hash(KEY *key_info) { - while(!(key_info->key_part->field->flags & LONG_UNIQUE_HASH_FIELD)) - key_info->key_part++; + uint no_of_keyparts= fields_in_hash_keyinfo(key_info); + key_info->key_part-= no_of_keyparts; key_info->user_defined_key_parts= key_info->usable_key_parts= - key_info->ext_key_parts= 1; + key_info->ext_key_parts= no_of_keyparts; } -inline void re_setup_keyinfo_hash(KEY *key_info) +void re_setup_keyinfo_hash(KEY *key_info) { - - uint no_of_keyparts= fields_in_hash_keyinfo(key_info); - key_info->key_part-= no_of_keyparts; + while(!(key_info->key_part->field->flags & LONG_UNIQUE_HASH_FIELD)) + key_info->key_part++; key_info->user_defined_key_parts= key_info->usable_key_parts= - key_info->ext_key_parts= no_of_keyparts; + key_info->ext_key_parts= 1; } /** @brief clone of current handler. Creates a clone of handler used in update for unique hash key. - @param thd Thread Object - @param table Table Object - @return handler object */ -void clone_handler_for_update(THD *thd, TABLE *table) +void TABLE::clone_handler_for_update() { handler *update_handler= NULL; - if (!table->s->long_unique_table) + if (!s->long_unique_table) return; - 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; + update_handler= file->clone(s->normalized_path.str, + in_use->mem_root); + update_handler->ha_external_lock(in_use, F_RDLCK); + this->update_handler= update_handler; return; } /** @brief Deletes update handler object - @param thd Thread Object - @param table Table Object */ -void delete_update_handler(THD *thd, TABLE *table) +void TABLE::delete_update_handler() { - 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; - } + update_handler->ha_external_lock(in_use, F_UNLCK); + update_handler->ha_close(); + delete update_handler; + this->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. + long unique keys ready for optimizer and alter table @param table Table object */ -void setup_table_hash(TABLE *table) +void TABLE::setup_table_hash() { - if (!table->s->long_unique_table) + if (!this->s->long_unique_table) return; - KEY *keyinfo= table->key_info; - for (uint i= 0; i < table->s->keys; i++, keyinfo++) + KEY *keyinfo= key_info; + for (uint i= 0; i < this->s->keys; i++, keyinfo++) if (keyinfo->algorithm == HA_KEY_ALG_LONG_HASH) setup_keyinfo_hash(keyinfo); } @@ -8849,12 +8838,12 @@ void setup_table_hash(TABLE *table) @brief Revert the effect of setup_table_hash @param table Table Object */ -void re_setup_table(TABLE *table) +void TABLE::re_setup_table() { - if (!table->s->long_unique_table) + if (!s->long_unique_table) return; - KEY *keyinfo= table->key_info; - for (uint i= 0; i < table->s->keys; i++, keyinfo++) + KEY *keyinfo= key_info; + for (uint i= 0; i < s->keys; i++, keyinfo++) if (keyinfo->algorithm == HA_KEY_ALG_LONG_HASH) re_setup_keyinfo_hash(keyinfo); } diff --git a/sql/table.h b/sql/table.h index 7de6e113613..945438c2829 100644 --- a/sql/table.h +++ b/sql/table.h @@ -354,21 +354,14 @@ enum field_visibility_t { int find_field_pos_in_hash(Item *hash_item, const char * field_name); -inline int fields_in_hash_keyinfo(KEY *keyinfo); +int fields_in_hash_keyinfo(KEY *keyinfo); -inline void setup_keyinfo_hash(KEY *key_info); +void setup_keyinfo_hash(KEY *key_info); -inline void re_setup_keyinfo_hash(KEY *key_info); +void re_setup_keyinfo_hash(KEY *key_info); Field * field_ptr_in_hash_str(Item *hash_item, int index); -void clone_handler_for_update(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. @@ -1575,6 +1568,10 @@ public: int delete_row(); void vers_update_fields(); void vers_update_end(); + void clone_handler_for_update(); + void delete_update_handler(); + void setup_table_hash(); + void re_setup_table(); /** Number of additional fields used in versioned tables */ #define VERSIONING_FIELDS 2 |