Skip to content

Commit 2d7d19a

Browse files
committed
MDEV-17574 SIGSEGV or Assertion `producing_item != __null' in
Item_direct_view_ref::derived_field_transformer_for_where upon updating a view The condition pushed into a materialized derived / view mast be adjusted for the new context: its column references must be substituted for references to the columns of the underlying tables if the condition is pushed into WHERE. The substitution is performed by the 'transform' method. If the materialized derived is used in a mergeable view then the references to the columns of the view are represented by Item_direct_view_ref objects. The transform method first processes the item wrapped in such an object and only after this it transforms the object itself. The transformation procedure of an Item_direct_view_ref object has to know whether the item it wraps has been substituted. If so the procedure does not have to do anything. In the code before this patch it was not possible for the transformation procedure used by an Item_direct_view_ref object to find out whether a substitution for the wrapped item had happened.
1 parent 3fbee66 commit 2d7d19a

File tree

4 files changed

+150
-3
lines changed

4 files changed

+150
-3
lines changed

mysql-test/r/derived_cond_pushdown.result

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10387,4 +10387,97 @@ f
1038710387
3
1038810388
DROP VIEW v1;
1038910389
DROP TABLE t1;
10390+
#
10391+
# MDEV-17574: pushdown into derived from mergeable view
10392+
# used in multi-table UPDATE
10393+
# pushdown into materialized derived from mergeable view
10394+
# used in SELECT
10395+
#
10396+
CREATE TABLE t1 (f1 text, f2 int);
10397+
INSERT INTO t1 VALUES ('x',1), ('y',2);
10398+
CREATE VIEW v1 AS SELECT f2 FROM ( SELECT f2 FROM t1 ) AS t;
10399+
UPDATE v1, t1 SET t1.f1 = 'z' WHERE v1.f2 < 2 AND t1.f2 = v1.f2;
10400+
EXPLAIN FORMAT=JSON UPDATE v1, t1 SET t1.f1 = 'z' WHERE v1.f2 < 2 AND t1.f2 = v1.f2;
10401+
EXPLAIN
10402+
{
10403+
"query_block": {
10404+
"select_id": 1,
10405+
"table": {
10406+
"table_name": "<derived3>",
10407+
"access_type": "ALL",
10408+
"rows": 2,
10409+
"filtered": 100,
10410+
"attached_condition": "t.f2 < 2",
10411+
"materialized": {
10412+
"query_block": {
10413+
"select_id": 3,
10414+
"table": {
10415+
"table_name": "t1",
10416+
"access_type": "ALL",
10417+
"rows": 2,
10418+
"filtered": 100,
10419+
"attached_condition": "t1.f2 < 2"
10420+
}
10421+
}
10422+
}
10423+
},
10424+
"table": {
10425+
"table_name": "t1",
10426+
"access_type": "ALL",
10427+
"rows": 2,
10428+
"filtered": 100,
10429+
"attached_condition": "t1.f2 = t.f2"
10430+
}
10431+
}
10432+
}
10433+
SELECT * FROM t1;
10434+
f1 f2
10435+
z 1
10436+
y 2
10437+
CREATE VIEW v2 AS SELECT f2 FROM ( SELECT DISTINCT f2 FROM t1 ) AS t;
10438+
SELECT * FROM v2, t1 WHERE v2.f2 < 2 AND t1.f2 = v2.f2;
10439+
f2 f1 f2
10440+
1 z 1
10441+
EXPLAIN FORMAT=JSON SELECT * FROM v2, t1 WHERE v2.f2 < 2 AND t1.f2 = v2.f2;
10442+
EXPLAIN
10443+
{
10444+
"query_block": {
10445+
"select_id": 1,
10446+
"table": {
10447+
"table_name": "<derived3>",
10448+
"access_type": "ALL",
10449+
"rows": 2,
10450+
"filtered": 100,
10451+
"attached_condition": "t.f2 < 2",
10452+
"materialized": {
10453+
"query_block": {
10454+
"select_id": 3,
10455+
"temporary_table": {
10456+
"table": {
10457+
"table_name": "t1",
10458+
"access_type": "ALL",
10459+
"rows": 2,
10460+
"filtered": 100,
10461+
"attached_condition": "t1.f2 < 2"
10462+
}
10463+
}
10464+
}
10465+
}
10466+
},
10467+
"block-nl-join": {
10468+
"table": {
10469+
"table_name": "t1",
10470+
"access_type": "ALL",
10471+
"rows": 2,
10472+
"filtered": 100
10473+
},
10474+
"buffer_type": "flat",
10475+
"buffer_size": "256Kb",
10476+
"join_type": "BNL",
10477+
"attached_condition": "t1.f2 = t.f2"
10478+
}
10479+
}
10480+
}
10481+
DROP VIEW v1,v2;
10482+
DROP TABLE t1;
1039010483
# End of 10.2 tests

mysql-test/t/derived_cond_pushdown.test

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2075,4 +2075,31 @@ SELECT * FROM t1;
20752075
DROP VIEW v1;
20762076
DROP TABLE t1;
20772077

2078+
--echo #
2079+
--echo # MDEV-17574: pushdown into derived from mergeable view
2080+
--echo # used in multi-table UPDATE
2081+
--echo # pushdown into materialized derived from mergeable view
2082+
--echo # used in SELECT
2083+
--echo #
2084+
2085+
CREATE TABLE t1 (f1 text, f2 int);
2086+
INSERT INTO t1 VALUES ('x',1), ('y',2);
2087+
2088+
CREATE VIEW v1 AS SELECT f2 FROM ( SELECT f2 FROM t1 ) AS t;
2089+
let $q1 =
2090+
UPDATE v1, t1 SET t1.f1 = 'z' WHERE v1.f2 < 2 AND t1.f2 = v1.f2;
2091+
eval $q1;
2092+
eval EXPLAIN FORMAT=JSON $q1;
2093+
2094+
SELECT * FROM t1;
2095+
2096+
CREATE VIEW v2 AS SELECT f2 FROM ( SELECT DISTINCT f2 FROM t1 ) AS t;
2097+
let $q2 =
2098+
SELECT * FROM v2, t1 WHERE v2.f2 < 2 AND t1.f2 = v2.f2;
2099+
eval $q2;
2100+
eval EXPLAIN FORMAT=JSON $q2;
2101+
2102+
DROP VIEW v1,v2;
2103+
DROP TABLE t1;
2104+
20782105
--echo # End of 10.2 tests

sql/item.cc

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7143,13 +7143,21 @@ Item *Item_field::derived_field_transformer_for_having(THD *thd, uchar *arg)
71437143
return this;
71447144
if (!item_equal && used_tables() != tab_map)
71457145
return this;
7146-
return get_field_item_for_having(thd, this, sel);
7146+
Item *item= get_field_item_for_having(thd, this, sel);
7147+
if (item)
7148+
item->marker|= SUBSTITUTION_FL;
7149+
return item;
71477150
}
71487151

71497152

71507153
Item *Item_direct_view_ref::derived_field_transformer_for_having(THD *thd,
71517154
uchar *arg)
71527155
{
7156+
if ((*ref)->marker & SUBSTITUTION_FL)
7157+
{
7158+
this->marker|= SUBSTITUTION_FL;
7159+
return this;
7160+
}
71537161
st_select_lex *sel= (st_select_lex *)arg;
71547162
table_map tab_map= sel->master_unit()->derived->table->map;
71557163
if ((item_equal && !(item_equal->used_tables() & tab_map)) ||
@@ -7200,13 +7208,20 @@ Item *Item_field::derived_field_transformer_for_where(THD *thd, uchar *arg)
72007208
st_select_lex *sel= (st_select_lex *)arg;
72017209
Item *producing_item= find_producing_item(this, sel);
72027210
if (producing_item)
7203-
return producing_item->build_clone(thd, thd->mem_root);
7211+
{
7212+
Item *producing_clone= producing_item->build_clone(thd, thd->mem_root);
7213+
if (producing_clone)
7214+
producing_clone->marker|= SUBSTITUTION_FL;
7215+
return producing_clone;
7216+
}
72047217
return this;
72057218
}
72067219

72077220
Item *Item_direct_view_ref::derived_field_transformer_for_where(THD *thd,
72087221
uchar *arg)
72097222
{
7223+
if ((*ref)->marker & SUBSTITUTION_FL)
7224+
return (*ref);
72107225
if (item_equal)
72117226
{
72127227
st_select_lex *sel= (st_select_lex *)arg;
@@ -7258,7 +7273,13 @@ Item *Item_field::derived_grouping_field_transformer_for_where(THD *thd,
72587273
st_select_lex *sel= (st_select_lex *)arg;
72597274
Grouping_tmp_field *gr_field= find_matching_grouping_field(this, sel);
72607275
if (gr_field)
7261-
return gr_field->producing_item->build_clone(thd, thd->mem_root);
7276+
{
7277+
Item *producing_clone=
7278+
gr_field->producing_item->build_clone(thd, thd->mem_root);
7279+
if (producing_clone)
7280+
producing_clone->marker|= SUBSTITUTION_FL;
7281+
return producing_clone;
7282+
}
72627283
return this;
72637284
}
72647285

@@ -7267,6 +7288,11 @@ Item *
72677288
Item_direct_view_ref::derived_grouping_field_transformer_for_where(THD *thd,
72687289
uchar *arg)
72697290
{
7291+
if ((*ref)->marker & SUBSTITUTION_FL)
7292+
{
7293+
this->marker|= SUBSTITUTION_FL;
7294+
return this;
7295+
}
72707296
if (!item_equal)
72717297
return this;
72727298
st_select_lex *sel= (st_select_lex *)arg;

sql/item.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ bool mark_unsupported_function(const char *w1, const char *w2,
147147

148148
#define NO_EXTRACTION_FL (1 << 6)
149149
#define FULL_EXTRACTION_FL (1 << 7)
150+
#define SUBSTITUTION_FL (1 << 8)
150151
#define EXTRACTION_MASK (NO_EXTRACTION_FL | FULL_EXTRACTION_FL)
151152

152153
class DTCollation {

0 commit comments

Comments
 (0)