Skip to content

Commit 1c12125

Browse files
roylysengdahlerlend
authored andcommitted
Bug#35889583: Server fails when we execute set of queries Bug#35996409: Failure in Query_expression::is_set_operation() Bug#36404149: Failing the server
Problem is that we attempt to inspect a query expression object that has been abandoned due to condition elimination. The problem is with equality operations that are transformed into semi-join conditions, where we store the left and right parts of the equality in sj_inner_exprs and sj_outer_exprs. The fix is to remove the references in the semi-join expression arrays when removing the corresponding equality condition. A dive within all join nests of the query block is necessary, due to the fact that we may have seen multiple transformations that add join nests so far. Change-Id: I7ae6aca62564486d0261a65afdf54ba057c9687d
1 parent 4c8e540 commit 1c12125

File tree

5 files changed

+57
-0
lines changed

5 files changed

+57
-0
lines changed

sql/item.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2910,6 +2910,7 @@ class Item : public Parse_tree_node {
29102910
Query_block *const m_root;
29112911

29122912
friend class Item;
2913+
friend class Item_func_eq;
29132914
friend class Item_sum;
29142915
friend class Item_subselect;
29152916
friend class Item_ref;

sql/item_cmpfunc.cc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2610,6 +2610,22 @@ void Item_in_optimizer::update_used_tables() {
26102610
}
26112611
}
26122612

2613+
bool Item_func_eq::clean_up_after_removal(uchar *arg) {
2614+
Cleanup_after_removal_context *const ctx =
2615+
pointer_cast<Cleanup_after_removal_context *>(arg);
2616+
2617+
if (ctx->is_stopped(this)) return false;
2618+
2619+
if (reference_count() > 1) {
2620+
(void)decrement_ref_count();
2621+
ctx->stop_at(this);
2622+
}
2623+
2624+
ctx->m_root->prune_sj_exprs(this, nullptr);
2625+
2626+
return false;
2627+
}
2628+
26132629
longlong Item_func_eq::val_int() {
26142630
assert(fixed);
26152631
const int value = cmp.compare();

sql/item_cmpfunc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,6 +1091,7 @@ class Item_func_eq final : public Item_eq_base {
10911091
Item_func_comparison *negate_item() override;
10921092
bool equality_substitution_analyzer(uchar **) override { return true; }
10931093
Item *equality_substitution_transformer(uchar *arg) override;
1094+
bool clean_up_after_removal(uchar *arg) override;
10941095

10951096
float get_filtering_effect(THD *thd, table_map filter_for_table,
10961097
table_map read_tables,

sql/sql_lex.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1777,6 +1777,8 @@ class Query_block : public Query_term {
17771777
*/
17781778
bool accept(Select_lex_visitor *visitor);
17791779

1780+
void prune_sj_exprs(Item_func_eq *item, mem_root_deque<Table_ref *> *nest);
1781+
17801782
/**
17811783
Cleanup this subtree (this Query_block and all nested Query_blockes and
17821784
Query_expressions).

sql/sql_resolver.cc

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5263,6 +5263,43 @@ bool validate_gc_assignment(const mem_root_deque<Item *> &fields,
52635263
return false;
52645264
}
52655265

5266+
/// Minion of prune_sj_exprs, q.v.
5267+
static void prune_sj_exprs_from_nest(Item_func_eq *item, Table_ref *nest) {
5268+
auto it1 = nest->nested_join->sj_outer_exprs.begin();
5269+
auto it2 = nest->nested_join->sj_inner_exprs.begin();
5270+
while (it1 != nest->nested_join->sj_outer_exprs.end() &&
5271+
it2 != nest->nested_join->sj_inner_exprs.end()) {
5272+
Item *outer = *it1;
5273+
Item *inner = *it2;
5274+
if ((outer == item->arguments()[0] && inner == item->arguments()[1]) ||
5275+
(outer == item->arguments()[1] && inner == item->arguments()[0])) {
5276+
nest->nested_join->sj_outer_exprs.erase(it1);
5277+
nest->nested_join->sj_inner_exprs.erase(it2);
5278+
break;
5279+
}
5280+
it1++;
5281+
it2++;
5282+
}
5283+
}
5284+
5285+
/**
5286+
Recursively look for removed item inside any nested joins'
5287+
sj_{inner,outer}_exprs. If target for removal is found, remove such entries
5288+
because the corresponding equality condition has been eliminated.
5289+
5290+
@param item the equality which is being removed.
5291+
@param nest the table nest (nullptr means top nest)
5292+
*/
5293+
void Query_block::prune_sj_exprs(Item_func_eq *item,
5294+
mem_root_deque<Table_ref *> *nest) {
5295+
if (nest == nullptr) nest = &m_table_nest;
5296+
for (Table_ref *table : *nest) {
5297+
if (table->nested_join == nullptr) continue;
5298+
prune_sj_exprs_from_nest(item, table);
5299+
prune_sj_exprs(item, &table->nested_join->m_tables);
5300+
}
5301+
}
5302+
52665303
/**
52675304
Delete unused columns from merged tables.
52685305

0 commit comments

Comments
 (0)