MDEV-37435 Make new vcols created in vcol index substitution inherit name resolution from the select_lex
Some checks failed
Build on Windows ARM64 / build (push) Has been cancelled

When a column or alias is the GROUP BY item, and a HAVING conjunct
depends on this column/alias only, the HAVING conjunct could contain
an Item_ref pointing to the GROUP BY Item_field.

If the column/alias happens to the be the expression of a vcol, the
GROUP BY item would be substituted with a newly created vcol
Item_field (MDEV-36132). This causes the Item_ref in HAVING to point
to the new vcol Item_field as well.

Subsequently in the HAVING to WHERE pushdown optimization, the
conjunct is moved to WHERE and fix_fields is called on it, where it
expects the vcol Item_field to have a name resolution context. So we
let the vcol Item_field inherit the context from the select_lex.
This commit is contained in:
Yuchen Pei 2025-10-16 10:38:51 +11:00
parent d29fb34b83
commit 0316c6e4f2
No known key found for this signature in database
GPG Key ID: 3DD1B35105743563
3 changed files with 52 additions and 0 deletions

View File

@ -193,3 +193,32 @@ explain select vc1, vc2 from t group by c + 1, 1 - c;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t index NULL vc1 10 NULL 10000 Using index
drop table t;
#
# MDEV-37435 Assertion `field' failed in virtual bool Item_field::fix_fields(THD *, Item **)
#
CREATE TABLE t1 (a INT,a1 INT AS (a) VIRTUAL,INDEX (a1));
SELECT a FROM t1 GROUP BY a HAVING a>2;
a
SELECT a FROM t1 WHERE a=(SELECT a FROM t1 GROUP BY a HAVING a>2);
a
drop table t1;
create table t1 (a int, a1 int as (a+1) virtual, index(a1));
select a+1 as g from t1 group by g having g>2;
g
drop table t1;
CREATE TABLE t1 (a INT,a1 INT AS (a) VIRTUAL,INDEX (a1));
CREATE TABLE t2 (b INT,b1 INT AS (b) VIRTUAL,INDEX (b1));
insert into t1 (a) select seq from seq_1_to_5;
insert into t2 (b) select seq from seq_1_to_5;
SELECT a, b FROM t1, t2 GROUP BY a, b HAVING a>2 and b>2;
a b
3 3
3 4
3 5
4 3
4 4
4 5
5 3
5 4
5 5
drop table t1, t2;

View File

@ -149,3 +149,22 @@ alter table t
add index(vc1, vc2);
explain select vc1, vc2 from t group by c + 1, 1 - c;
drop table t;
--echo #
--echo # MDEV-37435 Assertion `field' failed in virtual bool Item_field::fix_fields(THD *, Item **)
--echo #
CREATE TABLE t1 (a INT,a1 INT AS (a) VIRTUAL,INDEX (a1));
SELECT a FROM t1 GROUP BY a HAVING a>2;
SELECT a FROM t1 WHERE a=(SELECT a FROM t1 GROUP BY a HAVING a>2);
drop table t1;
create table t1 (a int, a1 int as (a+1) virtual, index(a1));
select a+1 as g from t1 group by g having g>2;
drop table t1;
CREATE TABLE t1 (a INT,a1 INT AS (a) VIRTUAL,INDEX (a1));
CREATE TABLE t2 (b INT,b1 INT AS (b) VIRTUAL,INDEX (b1));
insert into t1 (a) select seq from seq_1_to_5;
insert into t2 (b) select seq from seq_1_to_5;
SELECT a, b FROM t1, t2 GROUP BY a, b HAVING a>2 and b>2;
drop table t1, t2;

View File

@ -105,6 +105,8 @@ class Vcol_subst_context
THD *thd;
/* Indexed virtual columns that we can try substituting */
List<Field> vcol_fields;
/* Name resolution context for new vcol Item_field's */
Name_resolution_context *context;
/*
How many times substitution was done. Used to determine whether to print
@ -293,6 +295,7 @@ bool substitute_indexed_vcols_for_join(JOIN *join)
if (!ctx.vcol_fields.elements)
return false; // Ok, nothing to do
ctx.context= &join->select_lex->context;
if (join->conds)
subst_vcols_in_item(&ctx, join->conds, "WHERE");
if (join->join_list)
@ -463,6 +466,7 @@ void subst_vcol_if_compatible(Vcol_subst_context *ctx,
Item_field *itf= new (thd->mem_root) Item_field(thd, vcol_field);
if (!itf)
return; // Out of memory, caller will know from thd->is_error()
itf->context= ctx->context;
bitmap_set_bit(vcol_field->table->read_set, vcol_field->field_index);
DBUG_ASSERT(itf->fixed());
thd->change_item_tree(vcol_expr_ref, itf);