mirror of
https://github.com/MariaDB/server.git
synced 2026-05-05 22:55:32 +02:00
Add PART_INDIRECT_KEY_FLAG
This is to mark that a field is indirectly part of a key, which simplifes
checking if we need to have this field up to date to evaluate a key.
For example:
CREATE TABLE t1 (a int, b int as (a) virtual,
c int as (b) virtual, index(c))
would mark a and b with PART_INDIRECT_KEY_FLAG.
c is marked with PART_KEY_FLAG as before.
This commit is contained in:
parent
5ba6cee012
commit
831df10981
6 changed files with 126 additions and 21 deletions
|
|
@ -179,6 +179,7 @@ enum enum_indicator_type
|
||||||
#define BINCMP_FLAG 131072U /* Intern: Used by sql_yacc */
|
#define BINCMP_FLAG 131072U /* Intern: Used by sql_yacc */
|
||||||
#define GET_FIXED_FIELDS_FLAG (1U << 18) /* Used to get fields in item tree */
|
#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 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,
|
Intern: Field in TABLE object for new version of altered table,
|
||||||
|
|
|
||||||
38
mysql-test/suite/vcol/r/index.result
Normal file
38
mysql-test/suite/vcol/r/index.result
Normal file
|
|
@ -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;
|
||||||
25
mysql-test/suite/vcol/t/index.test
Normal file
25
mysql-test/suite/vcol/t/index.test
Normal file
|
|
@ -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;
|
||||||
|
|
@ -185,7 +185,7 @@ select_union::create_result_table(THD *thd_arg, List<Item> *column_types,
|
||||||
|
|
||||||
table->keys_in_use_for_query.clear_all();
|
table->keys_in_use_for_query.clear_all();
|
||||||
for (uint i=0; i < table->s->fields; i++)
|
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)
|
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();
|
incr_table->keys_in_use_for_query.clear_all();
|
||||||
for (uint i=0; i < table->s->fields; i++)
|
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;
|
TABLE *rec_table= 0;
|
||||||
if (! (rec_table= create_tmp_table(thd_arg, &tmp_table_param, *column_types,
|
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();
|
rec_table->keys_in_use_for_query.clear_all();
|
||||||
for (uint i=0; i < table->s->fields; i++)
|
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))
|
if (rec_tables.push_back(rec_table))
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
75
sql/table.cc
75
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)
|
if (share->table_category == TABLE_CATEGORY_LOG)
|
||||||
{
|
{
|
||||||
|
|
@ -6293,11 +6293,12 @@ void TABLE::mark_columns_needed_for_delete()
|
||||||
Field **reg_field;
|
Field **reg_field;
|
||||||
for (reg_field= field ; *reg_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);
|
bitmap_set_bit(read_set, cur_field->field_index);
|
||||||
if ((*reg_field)->vcol_info)
|
if (cur_field->vcol_info)
|
||||||
mark_virtual_col(*reg_field);
|
bitmap_set_bit(vcol_set, cur_field->field_index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
need_signal= true;
|
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))
|
if (bitmap_is_set(write_set, tmp_vfield->field_index))
|
||||||
bitmap_updated|= mark_virtual_col(tmp_vfield);
|
bitmap_updated|= mark_virtual_col(tmp_vfield);
|
||||||
else if (tmp_vfield->vcol_info->stored_in_db ||
|
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);
|
bitmap_set_bit(write_set, tmp_vfield->field_index);
|
||||||
mark_virtual_col(tmp_vfield);
|
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.
|
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
|
The marking must be done non-destructively to handle the case when
|
||||||
this could be run in parallely by two threads
|
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;
|
MY_BITMAP *save_read_set;
|
||||||
/* If there is no check constraints or if check_set is already initialized */
|
Field **vfield_ptr;
|
||||||
if (!s->check_set || s->check_set_initialized)
|
|
||||||
|
/* If there is virtual fields are already initialized */
|
||||||
|
if (s->check_set_initialized)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
save_read_set= read_set;
|
if (s->tmp_table == NO_TMP_TABLE)
|
||||||
read_set= s->check_set;
|
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++)
|
for (Virtual_column_info **chk= check_constraints ; *chk ; chk++)
|
||||||
(*chk)->expr->walk(&Item::register_field_in_read_map, 1, 0);
|
(*chk)->expr->walk(&Item::register_field_in_read_map, 1, 0);
|
||||||
|
read_set= save_read_set;
|
||||||
|
}
|
||||||
|
|
||||||
read_set= save_read_set;
|
/*
|
||||||
|
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.
|
||||||
|
|
||||||
|
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;
|
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 */
|
/* 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);
|
update= bitmap_is_set(vcol_set, vf->field_index);
|
||||||
break;
|
break;
|
||||||
case VCOL_UPDATE_FOR_REPLACE:
|
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)) ||
|
bitmap_is_set(vcol_set, vf->field_index)) ||
|
||||||
update_all_columns);
|
update_all_columns);
|
||||||
if (update && (vf->flags & BLOB_FLAG))
|
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:
|
||||||
case VCOL_UPDATE_INDEXED_FOR_UPDATE:
|
case VCOL_UPDATE_INDEXED_FOR_UPDATE:
|
||||||
/* Read indexed fields that was not updated in VCOL_UPDATE_FOR_READ */
|
/* 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));
|
!bitmap_is_set(vcol_set, vf->field_index));
|
||||||
swap_values= 1;
|
swap_values= 1;
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -1323,7 +1323,7 @@ public:
|
||||||
bool mark_virtual_col(Field *field);
|
bool mark_virtual_col(Field *field);
|
||||||
bool mark_virtual_columns_for_write(bool insert_fl);
|
bool mark_virtual_columns_for_write(bool insert_fl);
|
||||||
void mark_default_fields_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);
|
void mark_check_constraint_columns_for_read(void);
|
||||||
int verify_constraints(bool ignore_failure);
|
int verify_constraints(bool ignore_failure);
|
||||||
inline void column_bitmaps_set(MY_BITMAP *read_set_arg)
|
inline void column_bitmaps_set(MY_BITMAP *read_set_arg)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue