1
0
mirror of https://github.com/MariaDB/server.git synced 2026-10-23 18:49:29 +03:00

MDEV-28610 : Assertion marked_for_read() failed upon range select with virtual column in index.

Problem:
Executing a range select using an index that includes virtual/generated columns
(e.g. SELECT ... WHERE c BETWEEN ... ORDER BY d) could trigger:

Assertion 'marked_for_read()' failed in Field access during execution.

Cause:
The keyread initialization path was populating table->read_set using
mark_index_columns(), which follows the non-recursive index marking path.
This only marks direct index fields and does not resolve dependencies of
virtual/generated columns.

As a result, when an index contained virtual columns, their dependent base
columns were not included in read_set, leading to invalid access during
later evaluation of virtual columns.

Fix:
Replace mark_index_columns() with mark_index_columns_for_read() in the
keyread initialization path. This ensures the recursive read-marking logic is
used, so virtual/generated column dependencies are correctly propagated into
read_set before execution.
This commit is contained in:
PranavKTiwari
2026-05-25 15:43:44 +05:30
committed by Pranav Tiwari
parent 209c510d9e
commit 885587d369
5 changed files with 47 additions and 6 deletions

View File

@@ -618,4 +618,22 @@ NULL
NULL
NULL
DROP TABLE t1;
#
# MDEV-28610 Assertion `marked_for_read()' failed upon range select with virtual column in index
#
CREATE TABLE t (
a INT UNSIGNED NOT NULL DEFAULT 0,
b INT AS (a) VIRTUAL,
c TIME,
d INT,
e DATE,
f VARCHAR(1024),
PRIMARY KEY(c),
KEY(c,b,d,f(64))
);
INSERT INTO t (c) VALUES ('00:00:00'),('00:00:04');
SELECT c FROM t WHERE c BETWEEN '00:00:00' AND '00:00:00' ORDER BY d;
c
00:00:00
DROP TABLE t;
# End of 10.11 tests

View File

@@ -592,4 +592,24 @@ SELECT VALUE( vid ) FROM (select * from t1)dt;
DROP TABLE t1;
--echo #
--echo # MDEV-28610 Assertion `marked_for_read()' failed upon range select with virtual column in index
--echo #
CREATE TABLE t (
a INT UNSIGNED NOT NULL DEFAULT 0,
b INT AS (a) VIRTUAL,
c TIME,
d INT,
e DATE,
f VARCHAR(1024),
PRIMARY KEY(c),
KEY(c,b,d,f(64))
);
INSERT INTO t (c) VALUES ('00:00:00'),('00:00:04');
SELECT c FROM t WHERE c BETWEEN '00:00:00' AND '00:00:00' ORDER BY d;
# Cleanup
DROP TABLE t;
--echo # End of 10.11 tests

View File

@@ -11699,7 +11699,7 @@ bool Field::save_in_field_ignore_value(bool view_error_processing)
void Field::register_field_in_read_map()
{
if (vcol_info)
if (!stored_in_db())
{
Item *vcol_item= vcol_info->expr;
vcol_item->walk(&Item::register_field_in_read_map, 1, 0);

View File

@@ -33052,9 +33052,9 @@ void JOIN::init_join_cache_and_keyread()
depends on are automatically added to the read_set - because they're
needed to calculate the vcol.
But if we're doing keyread, vcol is taken
from the index, not calculated, and base columns do not need to be
in the read set. To ensure this we try to set the read_set to only
the key-parts of the indexes.
from the index, not calculated. The below call adds the key-parts
to the read_set, and for virtual columns also adds any base columns
they depend on.
Another side effect of this is
Lets say you have a query
@@ -33066,7 +33066,10 @@ void JOIN::init_join_cache_and_keyread()
tuple.
*/
if (!(table->file->index_flags(table->file->keyread, 0, 1) & HA_CLUSTERED_INDEX))
table->mark_index_columns(table->file->keyread, table->read_set);
{
bitmap_clear_all(table->read_set);
table->mark_index_columns_for_read(table->file->keyread);
}
}
bool init_for_explain= false;

View File

@@ -7819,7 +7819,7 @@ inline void TABLE::mark_index_columns_no_reset(uint index, MY_BITMAP *bitmap)
}
inline void TABLE::mark_index_columns_for_read(uint index)
void TABLE::mark_index_columns_for_read(uint index)
{
do_mark_index_columns(this, index, read_set, true);
}