Skip to content

Commit 18f05ef

Browse files
Chaithra GopalareddyErlend Dahl
authored andcommitted
Bug#32905044: CRASH AT CONDITION_PUSHDOWN::REPLACE_COLUMNS_IN_COND DURIN
RQG CONCURRENCY RUNS An earlier fix (Bug#32324234) made sure that a view reference needs to be cloned before a condition is pushed down to the derived table. To resolve the expression that was cloned, merged derived table's context (query_block->first_context) was used. However, an Item_view_ref object could also be created when a natural join column is created. For this case, while resolving, we cannot be using the merged derived table's context. Also, query_block->first_context is updated when natural join is present in the query. As a result, we can no more rely on first_context to give the correct context for the merged derived table. Solution: While creating field translations for the table that is getting merged, we capture the merged derived table's context. This context is then saved to each of the Item_view_ref object created. We then use it when view ref object is cloned. Change-Id: Ia60c49bf7e8393f2cda5b3ff9be223178e0f7f4a
1 parent 28ec5fd commit 18f05ef

7 files changed

Lines changed: 57 additions & 13 deletions

File tree

‎mysql-test/r/derived_condition_pushdown.result‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1176,3 +1176,12 @@ FROM (SELECT MAX(f1) AS a1 FROM t) as dt1,
11761176
WHERE dt1.a1 <= dt2.a2;
11771177
a1 a2
11781178
DROP TABLE t;
1179+
#
1180+
# Bug#32905044: CRASH AT CONDITION_PUSHDOWN::REPLACE_COLUMNS_IN_COND
1181+
# DURIN RQG CONCURRENCY RUNS
1182+
CREATE TABLE t(f1 INTEGER);
1183+
CREATE ALGORITHM=temptable VIEW v AS SELECT f1 FROM t;
1184+
SELECT f1 FROM (SELECT f1 FROM v) AS dt1 NATURAL JOIN v dt2 WHERE f1 > 5;
1185+
f1
1186+
DROP TABLE t;
1187+
DROP VIEW v;

‎mysql-test/t/derived_condition_pushdown.test‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,3 +699,16 @@ SELECT a1, a2
699699
WHERE dt1.a1 <= dt2.a2;
700700

701701
DROP TABLE t;
702+
703+
--echo #
704+
--echo # Bug#32905044: CRASH AT CONDITION_PUSHDOWN::REPLACE_COLUMNS_IN_COND
705+
--echo # DURIN RQG CONCURRENCY RUNS
706+
707+
CREATE TABLE t(f1 INTEGER);
708+
CREATE ALGORITHM=temptable VIEW v AS SELECT f1 FROM t;
709+
710+
#Query should not crash
711+
SELECT f1 FROM (SELECT f1 FROM v) AS dt1 NATURAL JOIN v dt2 WHERE f1 > 5;
712+
713+
DROP TABLE t;
714+
DROP VIEW v;

‎sql/item.cc‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8313,9 +8313,9 @@ Item *Item_view_ref::replace_view_refs_with_clone(uchar *arg) {
83138313
// Since the query block having dt2 is merged with the outer query
83148314
// block, the context to resolve the field will be different than
83158315
// the derived table context (dt1).
8316-
return dt->get_clone_for_derived_expr(
8317-
current_thd, *ref,
8318-
dt->derived_query_expression()->outer_query_block()->first_context);
8316+
Name_resolution_context *context_to_use =
8317+
m_merged_derived_context ? m_merged_derived_context : context;
8318+
return dt->get_clone_for_derived_expr(current_thd, *ref, context_to_use);
83198319
}
83208320

83218321
bool Item_default_value::itemize(Parse_context *pc, Item **res) {

‎sql/item.h‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5699,10 +5699,11 @@ class Item_view_ref final : public Item_ref {
56995699
Item_view_ref(Name_resolution_context *context_arg, Item **item,
57005700
const char *db_name_arg, const char *alias_name_arg,
57015701
const char *table_name_arg, const char *field_name_arg,
5702-
TABLE_LIST *tl)
5702+
TABLE_LIST *tl, Name_resolution_context *merged_derived_context)
57035703
: Item_ref(context_arg, item, db_name_arg, alias_name_arg,
57045704
field_name_arg),
5705-
first_inner_table(nullptr) {
5705+
first_inner_table(nullptr),
5706+
m_merged_derived_context(merged_derived_context) {
57065707
if (tl->is_view()) {
57075708
m_orig_db_name = db_name_arg;
57085709
m_orig_table_name = table_name_arg;
@@ -5806,6 +5807,11 @@ class Item_view_ref final : public Item_ref {
58065807
then this field points to the first leaf table of the view, otherwise NULL.
58075808
*/
58085809
TABLE_LIST *first_inner_table;
5810+
/**
5811+
Original Context of the underlying field in case of a merged derived
5812+
table.
5813+
*/
5814+
Name_resolution_context *m_merged_derived_context;
58095815
};
58105816

58115817
/*

‎sql/sql_derived.cc‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,6 +1154,7 @@ bool Condition_pushdown::replace_columns_in_cond(Item **cond, bool is_having) {
11541154
if (view_ref) {
11551155
(*cond) = (*cond)->transform(&Item::replace_view_refs_with_clone,
11561156
pointer_cast<uchar *>(m_derived_table));
1157+
if (cond == nullptr) return true;
11571158
}
11581159
Item *new_cond =
11591160
is_having ? (*cond)->transform(&Item::replace_with_derived_expr_ref,

‎sql/table.cc‎

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,8 @@ LEX_CSTRING PARSE_GCOL_KEYWORD = {STRING_WITH_LEN("parse_gcol_expr")};
157157

158158
static Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref,
159159
const char *name,
160-
Name_resolution_context *context);
160+
Name_resolution_context *context,
161+
Name_resolution_context *merged_derived_context);
161162
static void open_table_error(THD *thd, TABLE_SHARE *share, int error,
162163
int db_errno);
163164

@@ -4578,6 +4579,10 @@ bool TABLE_LIST::create_field_translation(THD *thd) {
45784579
field_translation = transl;
45794580
field_translation_end = transl + field_count;
45804581

4582+
// We capture the context used to resolve the fields of the merged
4583+
// derived table. This context is used when the field needs to be cloned
4584+
// to facilitate condition pushdown (replace_view_refs_with_clone()).
4585+
m_merged_derived_context = &select->context;
45814586
return false;
45824587
}
45834588

@@ -5027,7 +5032,8 @@ Item *Natural_join_column::create_item(THD *thd) {
50275032
assert(table_field == nullptr);
50285033
Query_block *select = thd->lex->current_query_block();
50295034
return create_view_field(thd, table_ref, &view_field->item,
5030-
view_field->name, &select->context);
5035+
view_field->name, &select->context,
5036+
/*merged_derived_context=*/nullptr);
50315037
}
50325038
return table_field;
50335039
}
@@ -5090,12 +5096,14 @@ const char *Field_iterator_view::name() { return ptr->name; }
50905096

50915097
Item *Field_iterator_view::create_item(THD *thd) {
50925098
Query_block *select = thd->lex->current_query_block();
5093-
return create_view_field(thd, view, &ptr->item, ptr->name, &select->context);
5099+
return create_view_field(thd, view, &ptr->item, ptr->name, &select->context,
5100+
view->m_merged_derived_context);
50945101
}
50955102

5096-
static Item *create_view_field(THD *, TABLE_LIST *view, Item **field_ref,
5097-
const char *name,
5098-
Name_resolution_context *context) {
5103+
static Item *create_view_field(
5104+
THD *, TABLE_LIST *view, Item **field_ref, const char *name,
5105+
Name_resolution_context *context,
5106+
Name_resolution_context *merged_derived_context) {
50995107
DBUG_TRACE;
51005108

51015109
Item *field = *field_ref;
@@ -5140,8 +5148,9 @@ static Item *create_view_field(THD *, TABLE_LIST *view, Item **field_ref,
51405148
mistakes, such as forgetting to mark the use of a field in both
51415149
read_set and write_set (may happen e.g in an UPDATE statement).
51425150
*/
5143-
Item *item = new Item_view_ref(context, field_ref, db_name, view->alias,
5144-
table_name, name, view);
5151+
Item *item =
5152+
new Item_view_ref(context, field_ref, db_name, view->alias, table_name,
5153+
name, view, merged_derived_context);
51455154
return item;
51465155
}
51475156

‎sql/table.h‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3521,6 +3521,12 @@ struct TABLE_LIST {
35213521
ulonglong algorithm{0};
35223522
ulonglong view_suid{0}; ///< view is suid (true by default)
35233523
ulonglong with_check{0}; ///< WITH CHECK OPTION
3524+
/**
3525+
Context that is used to resolve a merged derived table's
3526+
fields. Needed when a field from a merged derived table
3527+
is cloned. Used during condition pushdown to derived tables.
3528+
*/
3529+
Name_resolution_context *m_merged_derived_context{nullptr};
35243530

35253531
private:
35263532
/// The view algorithm that is actually used, if this is a view.

0 commit comments

Comments
 (0)