Skip to content

Commit

Permalink
Bug#35284734: mysqld crash from (m_ref_item != nullptr ?
Browse files Browse the repository at this point in the history
          ref_item()->walk(processor, walk, arg

If a subquery gets transformed into an EXISTS subquery
resulting in conditions being added involving the left
side of the comparison operator and if the left side
of the operator has a view reference, we are currently
not incrementing the reference count for underlying
field of the view reference correctly. This results
in the deletion of the field even though it is accessed
in the query which leads to problems later.
A view reference expects that every reference to it
increments the reference count of the underlying field
correctly because all view references share the same
underlying field. For a query like this one:
SELECT  f2 , MAX(t1.f1)
FROM (WITH cte1 AS (SELECT * FROM t1)
                   SELECT * FROM cte1) AS t1
WHERE FALSE
 AND (t1.f1+1 <> SOME (WITH cte2 AS (SELECT 1)
                                    SELECT * FROM cte2))
GROUP BY f2;

the view reference (t1.f1) post transformation is
referenced in 5 places (2 in cte1, 1 in the outer query
block, (1 in the where clause but through another view
reference) and 2 additionally in the trigger conditions
added by the transformation) where as the reference count
is 3. When the always false condition gets deleted,
reference count is decremented twice and because cte1
gets merged, it reduces the reference count further to
0 resulting in deletion of the field.
Solution is to increment the reference count correctly
for every condition added by IN to EXISTS transformation.

Change-Id: If39216cbfec4928d60c7be9ccbfb6d017c9605ef
  • Loading branch information
Chaithra Gopalareddy authored and dahlerlend committed May 31, 2023
1 parent bfc42f4 commit e9b5041
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 1 deletion.
15 changes: 15 additions & 0 deletions sql/item_cmpfunc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2056,6 +2056,21 @@ bool Arg_comparator::compare_null_values() {
return result;
}

void Item_bool_func::set_created_by_in2exists() {
m_created_by_in2exists = true;
// When a condition is created by IN to EXISTS transformation,
// it re-uses the expressions that are part of the query. As a
// result we need to increment the reference count
// for these expressions.
WalkItem(this, enum_walk::PREFIX | enum_walk::SUBQUERY, [](Item *inner_item) {
// Reference counting matters only for referenced items.
if (inner_item->type() == REF_ITEM) {
down_cast<Item_ref *>(inner_item)->ref_item()->increment_ref_count();
}
return false;
});
}

const char *Item_bool_func::bool_transform_names[10] = {"is true",
"is false",
"is null",
Expand Down
2 changes: 1 addition & 1 deletion sql/item_cmpfunc.h
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ class Item_bool_func : public Item_int_func {
}
uint decimal_precision() const override { return 1; }
bool created_by_in2exists() const override { return m_created_by_in2exists; }
void set_created_by_in2exists() { m_created_by_in2exists = true; }
void set_created_by_in2exists();

static const char *bool_transform_names[10];
/**
Expand Down

0 comments on commit e9b5041

Please sign in to comment.