Commit 2d7d19a3 authored by Igor Babaev's avatar Igor Babaev

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.
parent 3fbee664
......@@ -10387,4 +10387,97 @@ f
3
DROP VIEW v1;
DROP TABLE t1;
#
# MDEV-17574: pushdown into derived from mergeable view
# used in multi-table UPDATE
# pushdown into materialized derived from mergeable view
# used in SELECT
#
CREATE TABLE t1 (f1 text, f2 int);
INSERT INTO t1 VALUES ('x',1), ('y',2);
CREATE VIEW v1 AS SELECT f2 FROM ( SELECT f2 FROM t1 ) AS t;
UPDATE v1, t1 SET t1.f1 = 'z' WHERE v1.f2 < 2 AND t1.f2 = v1.f2;
EXPLAIN FORMAT=JSON UPDATE v1, t1 SET t1.f1 = 'z' WHERE v1.f2 < 2 AND t1.f2 = v1.f2;
EXPLAIN
{
"query_block": {
"select_id": 1,
"table": {
"table_name": "<derived3>",
"access_type": "ALL",
"rows": 2,
"filtered": 100,
"attached_condition": "t.f2 < 2",
"materialized": {
"query_block": {
"select_id": 3,
"table": {
"table_name": "t1",
"access_type": "ALL",
"rows": 2,
"filtered": 100,
"attached_condition": "t1.f2 < 2"
}
}
}
},
"table": {
"table_name": "t1",
"access_type": "ALL",
"rows": 2,
"filtered": 100,
"attached_condition": "t1.f2 = t.f2"
}
}
}
SELECT * FROM t1;
f1 f2
z 1
y 2
CREATE VIEW v2 AS SELECT f2 FROM ( SELECT DISTINCT f2 FROM t1 ) AS t;
SELECT * FROM v2, t1 WHERE v2.f2 < 2 AND t1.f2 = v2.f2;
f2 f1 f2
1 z 1
EXPLAIN FORMAT=JSON SELECT * FROM v2, t1 WHERE v2.f2 < 2 AND t1.f2 = v2.f2;
EXPLAIN
{
"query_block": {
"select_id": 1,
"table": {
"table_name": "<derived3>",
"access_type": "ALL",
"rows": 2,
"filtered": 100,
"attached_condition": "t.f2 < 2",
"materialized": {
"query_block": {
"select_id": 3,
"temporary_table": {
"table": {
"table_name": "t1",
"access_type": "ALL",
"rows": 2,
"filtered": 100,
"attached_condition": "t1.f2 < 2"
}
}
}
}
},
"block-nl-join": {
"table": {
"table_name": "t1",
"access_type": "ALL",
"rows": 2,
"filtered": 100
},
"buffer_type": "flat",
"buffer_size": "256Kb",
"join_type": "BNL",
"attached_condition": "t1.f2 = t.f2"
}
}
}
DROP VIEW v1,v2;
DROP TABLE t1;
# End of 10.2 tests
......@@ -2075,4 +2075,31 @@ SELECT * FROM t1;
DROP VIEW v1;
DROP TABLE t1;
--echo #
--echo # MDEV-17574: pushdown into derived from mergeable view
--echo # used in multi-table UPDATE
--echo # pushdown into materialized derived from mergeable view
--echo # used in SELECT
--echo #
CREATE TABLE t1 (f1 text, f2 int);
INSERT INTO t1 VALUES ('x',1), ('y',2);
CREATE VIEW v1 AS SELECT f2 FROM ( SELECT f2 FROM t1 ) AS t;
let $q1 =
UPDATE v1, t1 SET t1.f1 = 'z' WHERE v1.f2 < 2 AND t1.f2 = v1.f2;
eval $q1;
eval EXPLAIN FORMAT=JSON $q1;
SELECT * FROM t1;
CREATE VIEW v2 AS SELECT f2 FROM ( SELECT DISTINCT f2 FROM t1 ) AS t;
let $q2 =
SELECT * FROM v2, t1 WHERE v2.f2 < 2 AND t1.f2 = v2.f2;
eval $q2;
eval EXPLAIN FORMAT=JSON $q2;
DROP VIEW v1,v2;
DROP TABLE t1;
--echo # End of 10.2 tests
......@@ -7143,13 +7143,21 @@ Item *Item_field::derived_field_transformer_for_having(THD *thd, uchar *arg)
return this;
if (!item_equal && used_tables() != tab_map)
return this;
return get_field_item_for_having(thd, this, sel);
Item *item= get_field_item_for_having(thd, this, sel);
if (item)
item->marker|= SUBSTITUTION_FL;
return item;
}
Item *Item_direct_view_ref::derived_field_transformer_for_having(THD *thd,
uchar *arg)
{
if ((*ref)->marker & SUBSTITUTION_FL)
{
this->marker|= SUBSTITUTION_FL;
return this;
}
st_select_lex *sel= (st_select_lex *)arg;
table_map tab_map= sel->master_unit()->derived->table->map;
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)
st_select_lex *sel= (st_select_lex *)arg;
Item *producing_item= find_producing_item(this, sel);
if (producing_item)
return producing_item->build_clone(thd, thd->mem_root);
{
Item *producing_clone= producing_item->build_clone(thd, thd->mem_root);
if (producing_clone)
producing_clone->marker|= SUBSTITUTION_FL;
return producing_clone;
}
return this;
}
Item *Item_direct_view_ref::derived_field_transformer_for_where(THD *thd,
uchar *arg)
{
if ((*ref)->marker & SUBSTITUTION_FL)
return (*ref);
if (item_equal)
{
st_select_lex *sel= (st_select_lex *)arg;
......@@ -7258,7 +7273,13 @@ Item *Item_field::derived_grouping_field_transformer_for_where(THD *thd,
st_select_lex *sel= (st_select_lex *)arg;
Grouping_tmp_field *gr_field= find_matching_grouping_field(this, sel);
if (gr_field)
return gr_field->producing_item->build_clone(thd, thd->mem_root);
{
Item *producing_clone=
gr_field->producing_item->build_clone(thd, thd->mem_root);
if (producing_clone)
producing_clone->marker|= SUBSTITUTION_FL;
return producing_clone;
}
return this;
}
......@@ -7267,6 +7288,11 @@ Item *
Item_direct_view_ref::derived_grouping_field_transformer_for_where(THD *thd,
uchar *arg)
{
if ((*ref)->marker & SUBSTITUTION_FL)
{
this->marker|= SUBSTITUTION_FL;
return this;
}
if (!item_equal)
return this;
st_select_lex *sel= (st_select_lex *)arg;
......
......@@ -147,6 +147,7 @@ bool mark_unsupported_function(const char *w1, const char *w2,
#define NO_EXTRACTION_FL (1 << 6)
#define FULL_EXTRACTION_FL (1 << 7)
#define SUBSTITUTION_FL (1 << 8)
#define EXTRACTION_MASK (NO_EXTRACTION_FL | FULL_EXTRACTION_FL)
class DTCollation {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment