Skip to content

Commit c9908eb

Browse files
author
Chaithra Gopalareddy
committed
Bug#34616553: SEGV (Item_subselect::print() at sql/item_subselect.cc:833)
reported by ASan For this problem to happen, it needs several conditions to be met: 1. A mergeable derived table having a subquery in select list which is referenced by ORDER BY through an alias. This makes the ORDER BY reference the select expression when it gets resolved. 2. Needs to have a subquery with the same name in the query block where the derived table gets merged. 3. Needs to have window function referencing the subquery through an alias in PARTITION BY or ORDER BY clause. This makes it take a special path while resolving the ordering item to point to the view reference (from the merged derived table) than the one in the select list. When the derived table having the order by referencing the subquery in select expression gets merged, order by is moved to the outer query block. This makes another call to resolve the order by item. This time, it cleans up the order by item since it resolves against the select list again. Later, window function's partition by clause resolves against the view reference pointing to the subquery which was deleted previously leading to problems later during optimization. Solution is to not do the resolving again for a merged order by expression. We now have a check for a non constant expression that is already resolved and for such a order by expression, we just add a hidden element to the merged query block instead of re-resolving it. Change-Id: Idf33bca4ae1db29bfc5fcdc7e768e3ca77109441
1 parent 1f55b72 commit c9908eb

File tree

1 file changed

+14
-1
lines changed

1 file changed

+14
-1
lines changed

sql/sql_resolver.cc

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4353,7 +4353,6 @@ bool find_order_in_list(THD *thd, Ref_item_array ref_item_array,
43534353
if ((*order->item)->real_item() != (*select_item)->real_item()) {
43544354
Item::Cleanup_after_removal_context ctx(
43554355
thd->lex->current_query_block());
4356-
43574356
(*order->item)
43584357
->walk(&Item::clean_up_after_removal, walk_options,
43594358
pointer_cast<uchar *>(&ctx));
@@ -4495,6 +4494,20 @@ bool setup_order(THD *thd, Ref_item_array ref_item_array, Table_ref *tables,
44954494
const bool is_aggregated = select->is_grouped();
44964495

44974496
for (uint number = 1; order; order = order->next, number++) {
4497+
Item *order_item = *order->item;
4498+
if (order_item->fixed && !order_item->const_item()) {
4499+
// If a non constant expression in order by is already
4500+
// resolved, it must have been merged from a derived table.
4501+
// So, we do not need to re-resolve in this query block. Add
4502+
// a hidden item instead.
4503+
uint size = fields->size();
4504+
order_item->hidden = true;
4505+
order->in_field_list = false;
4506+
fields->push_front(order_item);
4507+
ref_item_array[size] = order_item;
4508+
continue;
4509+
}
4510+
44984511
if (find_order_in_list(thd, ref_item_array, tables, order, fields, false,
44994512
false))
45004513
return true;

0 commit comments

Comments
 (0)