diff options
-rw-r--r-- | include/mysql_com.h | 1 | ||||
-rw-r--r-- | mysql-test/suite/vcol/r/index.result | 38 | ||||
-rw-r--r-- | mysql-test/suite/vcol/t/index.test | 25 | ||||
-rw-r--r-- | sql/sql_union.cc | 6 | ||||
-rw-r--r-- | sql/table.cc | 75 | ||||
-rw-r--r-- | sql/table.h | 2 |
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) |