summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSachin <sachin.setiya@mariadb.com>2019-01-08 19:42:02 +0530
committerSachin <sachin.setiya@mariadb.com>2019-01-08 19:42:02 +0530
commitab6393d13dfba93308569b934f579f82c6b9ff03 (patch)
treeefc19acfaef1ce9ff5374969b0ef1be7cccaa68e
parent292b2fd23bbdf0ef406c90036c166dbca793db4b (diff)
downloadmariadb-git-ab6393d13dfba93308569b934f579f82c6b9ff03.tar.gz
Final changes
-rw-r--r--mysql-test/main/long_unique.test1
-rw-r--r--mysql-test/main/long_unique_innodb.result121
-rw-r--r--mysql-test/main/long_unique_innodb.test131
-rw-r--r--mysql-test/main/mdev-504.test3
-rw-r--r--sql/handler.cc9
-rw-r--r--sql/sql_base.cc2
-rw-r--r--sql/sql_show.cc16
-rw-r--r--sql/sql_table.cc7
-rw-r--r--sql/sql_update.cc6
-rw-r--r--sql/table.cc69
-rw-r--r--sql/table.h17
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