diff --git a/mysql-test/suite/vcol/r/vcol_keys_innodb.result b/mysql-test/suite/vcol/r/vcol_keys_innodb.result index 51e97864a2517..f6a2cb68ab7d8 100644 --- a/mysql-test/suite/vcol/r/vcol_keys_innodb.result +++ b/mysql-test/suite/vcol/r/vcol_keys_innodb.result @@ -303,3 +303,31 @@ IF(@@innodb_sort_buffer_size < count(*)*200, 'GOOD', 'WRONG SIZE') GOOD alter table t1 drop column va; drop table t1; +# +# MDEV-36896 Assertion `marked_for_read()' failed in virtual String *Field_varstring::val_str(String *, String *) +# +SET @old_isolation_level= @@session.tx_isolation; +SET @@session.tx_isolation= 'READ-UNCOMMITTED'; +CREATE TABLE t (a VARCHAR(10),b INT,c CHAR(10) GENERATED ALWAYS AS (a) VIRTUAL,KEY(b,c)) ENGINE=InnoDB; +INSERT INTO t (a) VALUES ('A'); +SELECT * FROM t WHERE b IS NULL ORDER BY a; +a b c +A NULL A +DROP TABLE t; +CREATE TABLE t ( +a VARCHAR(10), +b INT, +c CHAR(10) GENERATED ALWAYS AS (a) VIRTUAL, +d INT GENERATED ALWAYS AS (IF(a = c, 1, 0)) VIRTUAL, +KEY(b, c) +) ENGINE=InnoDB; +INSERT INTO t (a) VALUES ('A'); +INSERT INTO t (a, b) VALUES ('B', 1); +SELECT * FROM t WHERE b IS NULL ORDER BY a; +a b c d +A NULL A 1 +DROP TABLE t; +SET @@session.tx_isolation= @old_isolation_level; +# +# End of 10.11 tests +# diff --git a/mysql-test/suite/vcol/t/vcol_keys_innodb.test b/mysql-test/suite/vcol/t/vcol_keys_innodb.test index 488a2b936d084..cb4ff8b231578 100644 --- a/mysql-test/suite/vcol/t/vcol_keys_innodb.test +++ b/mysql-test/suite/vcol/t/vcol_keys_innodb.test @@ -135,3 +135,36 @@ insert t1 (id,a,c) select seq,seq,seq from seq_1_to_330; select IF(@@innodb_sort_buffer_size < count(*)*200, 'GOOD', 'WRONG SIZE') from t1; alter table t1 drop column va; drop table t1; + + +--echo # +--echo # MDEV-36896 Assertion `marked_for_read()' failed in virtual String *Field_varstring::val_str(String *, String *) +--echo # + +SET @old_isolation_level= @@session.tx_isolation; + +SET @@session.tx_isolation= 'READ-UNCOMMITTED'; +CREATE TABLE t (a VARCHAR(10),b INT,c CHAR(10) GENERATED ALWAYS AS (a) VIRTUAL,KEY(b,c)) ENGINE=InnoDB; +INSERT INTO t (a) VALUES ('A'); +SELECT * FROM t WHERE b IS NULL ORDER BY a; + +DROP TABLE t; + +CREATE TABLE t ( + a VARCHAR(10), + b INT, + c CHAR(10) GENERATED ALWAYS AS (a) VIRTUAL, + d INT GENERATED ALWAYS AS (IF(a = c, 1, 0)) VIRTUAL, + KEY(b, c) +) ENGINE=InnoDB; + +INSERT INTO t (a) VALUES ('A'); +INSERT INTO t (a, b) VALUES ('B', 1); +SELECT * FROM t WHERE b IS NULL ORDER BY a; +DROP TABLE t; + +SET @@session.tx_isolation= @old_isolation_level; + +--echo # +--echo # End of 10.11 tests +--echo # diff --git a/sql/item.cc b/sql/item.cc index d14a8da53da47..e5ecfcbef93de 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -980,12 +980,13 @@ bool Item_field::check_field_expression_processor(void *arg) bool Item_field::update_vcol_processor(void *arg) { MY_BITMAP *map= (MY_BITMAP *) arg; - if (field->vcol_info && - !bitmap_fast_test_and_set(map, field->field_index)) + + if (!bitmap_fast_test_and_set(map, field->field_index) && field->vcol_info) { field->vcol_info->expr->walk(&Item::update_vcol_processor, 0, arg); field->vcol_info->expr->save_in_field(field, 0); } + return 0; } diff --git a/sql/table.cc b/sql/table.cc index 2b283fd93e1b8..8907e2f117f62 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -9187,8 +9187,11 @@ int TABLE::update_virtual_field(Field *vf, bool ignore_warnings) TABLE::update_virtual_fields(handler *, enum_vcol_update_mode). */ in_use->set_n_backup_active_arena(expr_arena, &backup_arena); - bitmap_clear_all(&tmp_set); - vf->vcol_info->expr->walk(&Item::update_vcol_processor, 0, &tmp_set); + + MY_BITMAP local_set; + my_bitmap_init(&local_set, NULL, s->fields); + bitmap_set_bit(&local_set, vf->field_index); + vf->vcol_info->expr->walk(&Item::update_vcol_processor, 0, &local_set); DBUG_FIX_WRITE_SET(vf); vf->vcol_info->expr->save_in_field(vf, 0); DBUG_RESTORE_WRITE_SET(vf); @@ -9201,6 +9204,7 @@ int TABLE::update_virtual_field(Field *vf, bool ignore_warnings) // This is an internal calculation, we expect it to always succeed DBUG_ASSERT(count_errors.errors == 0); } + my_bitmap_free(&local_set); DBUG_RETURN(count_errors.errors); }