summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mysql_com.h1
-rw-r--r--mysql-test/suite/vcol/r/index.result38
-rw-r--r--mysql-test/suite/vcol/t/index.test25
-rw-r--r--sql/sql_union.cc6
-rw-r--r--sql/table.cc75
-rw-r--r--sql/table.h2
6 files changed, 126 insertions, 21 deletions
diff --git a/include/mysql_com.h b/include/mysql_com.h
index 06c934bf9bd..17366e22da8 100644
--- a/include/mysql_com.h
+++ b/include/mysql_com.h
@@ -179,6 +179,7 @@ enum enum_indicator_type
#define BINCMP_FLAG 131072U /* Intern: Used by sql_yacc */
#define GET_FIXED_FIELDS_FLAG (1U << 18) /* Used to get fields in item tree */
#define FIELD_IN_PART_FUNC_FLAG (1U << 19)/* Field part of partition func */
+#define PART_INDIRECT_KEY_FLAG (1U << 20)
/**
Intern: Field in TABLE object for new version of altered table,
diff --git a/mysql-test/suite/vcol/r/index.result b/mysql-test/suite/vcol/r/index.result
new file mode 100644
index 00000000000..cd4ebc96024
--- /dev/null
+++ b/mysql-test/suite/vcol/r/index.result
@@ -0,0 +1,38 @@
+CREATE TABLE t1 (a int, b int as (a+1) virtual, c int as (b+1) virtual, index(c)) engine=myisam;
+insert into t1 (a) values (1),(2),(3);
+update t1 set a=5 where a=3;
+delete from t1 where a=1;
+select * from t1;
+a b c
+2 3 4
+5 6 7
+select * from t1 where c=7;
+a b c
+5 6 7
+check table t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+select * from t1;
+a b c
+2 3 4
+5 6 7
+drop table t1;
+CREATE TABLE t1 (a int, b int as (a+1) virtual, c int as (b+1) virtual, index(c)) engine=innodb;
+insert into t1 (a) values (1),(2),(3);
+update t1 set a=5 where a=3;
+delete from t1 where a=1;
+select * from t1;
+a b c
+2 3 4
+5 6 7
+select * from t1 where c=7;
+a b c
+5 6 7
+check table t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+select * from t1;
+a b c
+2 3 4
+5 6 7
+drop table t1;
diff --git a/mysql-test/suite/vcol/t/index.test b/mysql-test/suite/vcol/t/index.test
new file mode 100644
index 00000000000..55d5b68f26b
--- /dev/null
+++ b/mysql-test/suite/vcol/t/index.test
@@ -0,0 +1,25 @@
+--source include/have_innodb.inc
+
+#
+# Test creating table with a key that consists of indirect virtual fields
+#
+
+CREATE TABLE t1 (a int, b int as (a+1) virtual, c int as (b+1) virtual, index(c)) engine=myisam;
+insert into t1 (a) values (1),(2),(3);
+update t1 set a=5 where a=3;
+delete from t1 where a=1;
+select * from t1;
+select * from t1 where c=7;
+check table t1;
+select * from t1;
+drop table t1;
+
+CREATE TABLE t1 (a int, b int as (a+1) virtual, c int as (b+1) virtual, index(c)) engine=innodb;
+insert into t1 (a) values (1),(2),(3);
+update t1 set a=5 where a=3;
+delete from t1 where a=1;
+select * from t1;
+select * from t1 where c=7;
+check table t1;
+select * from t1;
+drop table t1;
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 178d7393878..b409790c044 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -185,7 +185,7 @@ select_union::create_result_table(THD *thd_arg, List<Item> *column_types,
table->keys_in_use_for_query.clear_all();
for (uint i=0; i < table->s->fields; i++)
- table->field[i]->flags &= ~PART_KEY_FLAG;
+ table->field[i]->flags &= ~(PART_KEY_FLAG | PART_INDIRECT_KEY_FLAG);
if (create_table)
{
@@ -219,7 +219,7 @@ select_union_recursive::create_result_table(THD *thd_arg,
incr_table->keys_in_use_for_query.clear_all();
for (uint i=0; i < table->s->fields; i++)
- incr_table->field[i]->flags &= ~PART_KEY_FLAG;
+ incr_table->field[i]->flags &= ~(PART_KEY_FLAG | PART_INDIRECT_KEY_FLAG);
TABLE *rec_table= 0;
if (! (rec_table= create_tmp_table(thd_arg, &tmp_table_param, *column_types,
@@ -230,7 +230,7 @@ select_union_recursive::create_result_table(THD *thd_arg,
rec_table->keys_in_use_for_query.clear_all();
for (uint i=0; i < table->s->fields; i++)
- rec_table->field[i]->flags &= ~PART_KEY_FLAG;
+ rec_table->field[i]->flags &= ~(PART_KEY_FLAG | PART_INDIRECT_KEY_FLAG);
if (rec_tables.push_back(rec_table))
return true;
diff --git a/sql/table.cc b/sql/table.cc
index 12fc10c3259..198e77f1872 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -3357,7 +3357,7 @@ partititon_err:
}
}
- outparam->mark_columns_used_by_check_constraints();
+ outparam->mark_columns_used_by_virtual_fields();
if (share->table_category == TABLE_CATEGORY_LOG)
{
@@ -6293,11 +6293,12 @@ void TABLE::mark_columns_needed_for_delete()
Field **reg_field;
for (reg_field= field ; *reg_field ; reg_field++)
{
- if ((*reg_field)->flags & PART_KEY_FLAG)
+ Field *cur_field= *reg_field;
+ if (cur_field->flags & (PART_KEY_FLAG | PART_INDIRECT_KEY_FLAG))
{
- bitmap_set_bit(read_set, (*reg_field)->field_index);
- if ((*reg_field)->vcol_info)
- mark_virtual_col(*reg_field);
+ bitmap_set_bit(read_set, cur_field->field_index);
+ if (cur_field->vcol_info)
+ bitmap_set_bit(vcol_set, cur_field->field_index);
}
}
need_signal= true;
@@ -6655,7 +6656,8 @@ bool TABLE::mark_virtual_columns_for_write(bool insert_fl
if (bitmap_is_set(write_set, tmp_vfield->field_index))
bitmap_updated|= mark_virtual_col(tmp_vfield);
else if (tmp_vfield->vcol_info->stored_in_db ||
- (tmp_vfield->flags & (PART_KEY_FLAG | FIELD_IN_PART_FUNC_FLAG)))
+ (tmp_vfield->flags & (PART_KEY_FLAG | FIELD_IN_PART_FUNC_FLAG |
+ PART_INDIRECT_KEY_FLAG)))
{
bitmap_set_bit(write_set, tmp_vfield->field_index);
mark_virtual_col(tmp_vfield);
@@ -6668,27 +6670,64 @@ bool TABLE::mark_virtual_columns_for_write(bool insert_fl
}
/*
- Mark fields used by check constraints.
+ Mark fields used by check constraints into s->check_set.
+ Mark all fields used in an expression that is part of an index
+ with PART_INDIRECT_KEY_FLAG
+
This is done once for the TABLE_SHARE the first time the table is opened.
The marking must be done non-destructively to handle the case when
this could be run in parallely by two threads
*/
-void TABLE::mark_columns_used_by_check_constraints(void)
+void TABLE::mark_columns_used_by_virtual_fields(void)
{
MY_BITMAP *save_read_set;
- /* If there is no check constraints or if check_set is already initialized */
- if (!s->check_set || s->check_set_initialized)
+ Field **vfield_ptr;
+
+ /* If there is virtual fields are already initialized */
+ if (s->check_set_initialized)
return;
- save_read_set= read_set;
- read_set= s->check_set;
+ if (s->tmp_table == NO_TMP_TABLE)
+ mysql_mutex_lock(&s->LOCK_share);
+ if (s->check_set)
+ {
+ /* Mark fields used by check constraint */
+ save_read_set= read_set;
+ read_set= s->check_set;
+
+ for (Virtual_column_info **chk= check_constraints ; *chk ; chk++)
+ (*chk)->expr->walk(&Item::register_field_in_read_map, 1, 0);
+ read_set= save_read_set;
+ }
- for (Virtual_column_info **chk= check_constraints ; *chk ; chk++)
- (*chk)->expr->walk(&Item::register_field_in_read_map, 1, 0);
+ /*
+ mark all fields that part of a virtual indexed field with
+ PART_INDIRECT_KEY_FLAG. This is used to ensure that all fields
+ that are part of an index exits before write/delete/update.
- read_set= save_read_set;
+ As this code is only executed once per open share, it's reusing
+ existing functionality instead of adding an extra argument to
+ add_field_to_set_processor or adding another processor.
+ */
+ if (vfield)
+ {
+ for (vfield_ptr= vfield; *vfield_ptr; vfield_ptr++)
+ {
+ if ((*vfield_ptr)->flags & PART_KEY_FLAG)
+ (*vfield_ptr)->vcol_info->expr->walk(&Item::add_field_to_set_processor,
+ 1, this);
+ }
+ for (uint i= 0 ; i < s->fields ; i++)
+ {
+ if (bitmap_is_set(&tmp_set, i))
+ field[i]->flags|= PART_INDIRECT_KEY_FLAG;
+ }
+ bitmap_clear_all(&tmp_set);
+ }
s->check_set_initialized= 1;
+ if (s->tmp_table == NO_TMP_TABLE)
+ mysql_mutex_unlock(&s->LOCK_share);
}
/* Add fields used by CHECK CONSTRAINT to read map */
@@ -7465,7 +7504,8 @@ int TABLE::update_virtual_fields(handler *h, enum_vcol_update_mode update_mode)
update= bitmap_is_set(vcol_set, vf->field_index);
break;
case VCOL_UPDATE_FOR_REPLACE:
- update= ((!vcol_info->stored_in_db && (vf->flags & PART_KEY_FLAG) &&
+ update= ((!vcol_info->stored_in_db &&
+ (vf->flags & (PART_KEY_FLAG | PART_INDIRECT_KEY_FLAG)) &&
bitmap_is_set(vcol_set, vf->field_index)) ||
update_all_columns);
if (update && (vf->flags & BLOB_FLAG))
@@ -7484,7 +7524,8 @@ int TABLE::update_virtual_fields(handler *h, enum_vcol_update_mode update_mode)
case VCOL_UPDATE_INDEXED:
case VCOL_UPDATE_INDEXED_FOR_UPDATE:
/* Read indexed fields that was not updated in VCOL_UPDATE_FOR_READ */
- update= (!vcol_info->stored_in_db && (vf->flags & PART_KEY_FLAG) &&
+ update= (!vcol_info->stored_in_db &&
+ (vf->flags & (PART_KEY_FLAG | PART_INDIRECT_KEY_FLAG)) &&
!bitmap_is_set(vcol_set, vf->field_index));
swap_values= 1;
break;
diff --git a/sql/table.h b/sql/table.h
index 6febeb555f9..4c409342c27 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -1323,7 +1323,7 @@ public:
bool mark_virtual_col(Field *field);
bool mark_virtual_columns_for_write(bool insert_fl);
void mark_default_fields_for_write(bool insert_fl);
- void mark_columns_used_by_check_constraints(void);
+ void mark_columns_used_by_virtual_fields(void);
void mark_check_constraint_columns_for_read(void);
int verify_constraints(bool ignore_failure);
inline void column_bitmaps_set(MY_BITMAP *read_set_arg)