Fixed the bug mdev-12845.
This patch fills in a serious flaw in the code that supports condition pushdown into materialized views / derived tables. If a predicate happened to contain a reference to a mergeable view / derived table and it does not depended directly on the target materialized view / derived table then the predicate was not considered as a subject to pusdown to this view / derived table.
This commit is contained in:
parent
a8131e71f9
commit
9f3622191d
@ -554,7 +554,7 @@ EXPLAIN SELECT * FROM (SELECT * FROM t1) AS table1,
|
|||||||
id select_type table type possible_keys key key_len ref rows Extra
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
1 PRIMARY t1 system NULL NULL NULL NULL 1
|
1 PRIMARY t1 system NULL NULL NULL NULL 1
|
||||||
1 PRIMARY <derived3> ref key0 key0 5 const 0
|
1 PRIMARY <derived3> ref key0 key0 5 const 0
|
||||||
3 DERIVED t2 ALL NULL NULL NULL NULL 2 Using temporary
|
3 DERIVED t2 ALL NULL NULL NULL NULL 2 Using where; Using temporary
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1249 Select 4 was reduced during optimization
|
Note 1249 Select 4 was reduced during optimization
|
||||||
DROP TABLE t1, t2;
|
DROP TABLE t1, t2;
|
||||||
|
@ -7234,6 +7234,7 @@ EXPLAIN
|
|||||||
"materialized": {
|
"materialized": {
|
||||||
"query_block": {
|
"query_block": {
|
||||||
"select_id": 5,
|
"select_id": 5,
|
||||||
|
"having_condition": "s > 2",
|
||||||
"filesort": {
|
"filesort": {
|
||||||
"sort_key": "t4.d",
|
"sort_key": "t4.d",
|
||||||
"temporary_table": {
|
"temporary_table": {
|
||||||
@ -7605,6 +7606,7 @@ EXPLAIN
|
|||||||
"materialized": {
|
"materialized": {
|
||||||
"query_block": {
|
"query_block": {
|
||||||
"select_id": 3,
|
"select_id": 3,
|
||||||
|
"having_condition": "s < 50",
|
||||||
"filesort": {
|
"filesort": {
|
||||||
"sort_key": "t3.a",
|
"sort_key": "t3.a",
|
||||||
"temporary_table": {
|
"temporary_table": {
|
||||||
@ -7755,9 +7757,14 @@ EXPLAIN
|
|||||||
"select_id": 4,
|
"select_id": 4,
|
||||||
"table": {
|
"table": {
|
||||||
"table_name": "t",
|
"table_name": "t",
|
||||||
"access_type": "ALL",
|
"access_type": "range",
|
||||||
|
"possible_keys": ["PRIMARY"],
|
||||||
|
"key": "PRIMARY",
|
||||||
|
"key_length": "4",
|
||||||
|
"used_key_parts": ["pk"],
|
||||||
"rows": 2,
|
"rows": 2,
|
||||||
"filtered": 100
|
"filtered": 100,
|
||||||
|
"index_condition": "t.pk > 2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -8447,3 +8454,221 @@ WHERE row <> order_number;
|
|||||||
row order_number
|
row order_number
|
||||||
14 51
|
14 51
|
||||||
DROP TABLE sales_documents;
|
DROP TABLE sales_documents;
|
||||||
|
#
|
||||||
|
# MDEV-12845: pushdown from merged derived using equalities
|
||||||
|
#
|
||||||
|
create table t1 (a int);
|
||||||
|
insert into t1 values
|
||||||
|
(4), (8), (5), (3), (10), (2), (7);
|
||||||
|
create table t2 (b int, c int);
|
||||||
|
insert into t2 values
|
||||||
|
(2,1), (5,2), (2,2), (4,1), (4,3),
|
||||||
|
(5,3), (2,4), (4,6), (2,1);
|
||||||
|
create view v1 as
|
||||||
|
select b, sum(c) as s from t2 group by b;
|
||||||
|
create view v2 as
|
||||||
|
select distinct b, c from t2;
|
||||||
|
create view v3 as
|
||||||
|
select b, max(c) as m from t2 group by b;
|
||||||
|
select b
|
||||||
|
from ( select t1.a, v1.b, v1.s from t1, v1 where t1.a = v1.b ) as t
|
||||||
|
where b > 2;
|
||||||
|
b
|
||||||
|
4
|
||||||
|
5
|
||||||
|
explain format=json select b
|
||||||
|
from ( select t1.a, v1.b, v1.s from t1, v1 where t1.a = v1.b ) as t
|
||||||
|
where b > 2;
|
||||||
|
EXPLAIN
|
||||||
|
{
|
||||||
|
"query_block": {
|
||||||
|
"select_id": 1,
|
||||||
|
"table": {
|
||||||
|
"table_name": "t1",
|
||||||
|
"access_type": "ALL",
|
||||||
|
"rows": 7,
|
||||||
|
"filtered": 100,
|
||||||
|
"attached_condition": "t1.a > 2 and t1.a is not null"
|
||||||
|
},
|
||||||
|
"table": {
|
||||||
|
"table_name": "<derived3>",
|
||||||
|
"access_type": "ref",
|
||||||
|
"possible_keys": ["key0"],
|
||||||
|
"key": "key0",
|
||||||
|
"key_length": "5",
|
||||||
|
"used_key_parts": ["b"],
|
||||||
|
"ref": ["test.t1.a"],
|
||||||
|
"rows": 2,
|
||||||
|
"filtered": 100,
|
||||||
|
"materialized": {
|
||||||
|
"query_block": {
|
||||||
|
"select_id": 3,
|
||||||
|
"filesort": {
|
||||||
|
"sort_key": "t2.b",
|
||||||
|
"temporary_table": {
|
||||||
|
"table": {
|
||||||
|
"table_name": "t2",
|
||||||
|
"access_type": "ALL",
|
||||||
|
"rows": 9,
|
||||||
|
"filtered": 100,
|
||||||
|
"attached_condition": "t2.b > 2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
select a
|
||||||
|
from ( select t1.a, v1.b, v1.s from t1, v1 where t1.a = v1.b ) as t
|
||||||
|
where a > 2;
|
||||||
|
a
|
||||||
|
4
|
||||||
|
5
|
||||||
|
explain format=json select a
|
||||||
|
from ( select t1.a, v1.b, v1.s from t1, v1 where t1.a = v1.b ) as t
|
||||||
|
where a > 2;
|
||||||
|
EXPLAIN
|
||||||
|
{
|
||||||
|
"query_block": {
|
||||||
|
"select_id": 1,
|
||||||
|
"table": {
|
||||||
|
"table_name": "t1",
|
||||||
|
"access_type": "ALL",
|
||||||
|
"rows": 7,
|
||||||
|
"filtered": 100,
|
||||||
|
"attached_condition": "t1.a > 2 and t1.a is not null"
|
||||||
|
},
|
||||||
|
"table": {
|
||||||
|
"table_name": "<derived3>",
|
||||||
|
"access_type": "ref",
|
||||||
|
"possible_keys": ["key0"],
|
||||||
|
"key": "key0",
|
||||||
|
"key_length": "5",
|
||||||
|
"used_key_parts": ["b"],
|
||||||
|
"ref": ["test.t1.a"],
|
||||||
|
"rows": 2,
|
||||||
|
"filtered": 100,
|
||||||
|
"materialized": {
|
||||||
|
"query_block": {
|
||||||
|
"select_id": 3,
|
||||||
|
"filesort": {
|
||||||
|
"sort_key": "t2.b",
|
||||||
|
"temporary_table": {
|
||||||
|
"table": {
|
||||||
|
"table_name": "t2",
|
||||||
|
"access_type": "ALL",
|
||||||
|
"rows": 9,
|
||||||
|
"filtered": 100,
|
||||||
|
"attached_condition": "t2.b > 2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
select a
|
||||||
|
from ( select t1.a, v2.b, v2.c from t1, v2 where t1.a = v2.b ) as t
|
||||||
|
where a > 2;
|
||||||
|
a
|
||||||
|
4
|
||||||
|
4
|
||||||
|
4
|
||||||
|
5
|
||||||
|
5
|
||||||
|
explain format=json select a
|
||||||
|
from ( select t1.a, v2.b, v2.c from t1, v2 where t1.a = v2.b ) as t
|
||||||
|
where a > 2;
|
||||||
|
EXPLAIN
|
||||||
|
{
|
||||||
|
"query_block": {
|
||||||
|
"select_id": 1,
|
||||||
|
"table": {
|
||||||
|
"table_name": "t1",
|
||||||
|
"access_type": "ALL",
|
||||||
|
"rows": 7,
|
||||||
|
"filtered": 100,
|
||||||
|
"attached_condition": "t1.a > 2 and t1.a is not null"
|
||||||
|
},
|
||||||
|
"table": {
|
||||||
|
"table_name": "<derived3>",
|
||||||
|
"access_type": "ref",
|
||||||
|
"possible_keys": ["key0"],
|
||||||
|
"key": "key0",
|
||||||
|
"key_length": "5",
|
||||||
|
"used_key_parts": ["b"],
|
||||||
|
"ref": ["test.t1.a"],
|
||||||
|
"rows": 2,
|
||||||
|
"filtered": 100,
|
||||||
|
"materialized": {
|
||||||
|
"query_block": {
|
||||||
|
"select_id": 3,
|
||||||
|
"temporary_table": {
|
||||||
|
"table": {
|
||||||
|
"table_name": "t2",
|
||||||
|
"access_type": "ALL",
|
||||||
|
"rows": 9,
|
||||||
|
"filtered": 100,
|
||||||
|
"attached_condition": "t2.b > 2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
select a
|
||||||
|
from ( select t1.a, v3.b, v3.m from t1, v3 where t1.a = v3.m ) as t
|
||||||
|
where a > 2;
|
||||||
|
a
|
||||||
|
4
|
||||||
|
3
|
||||||
|
explain format=json select a
|
||||||
|
from ( select t1.a, v3.b, v3.m from t1, v3 where t1.a = v3.m ) as t
|
||||||
|
where a > 2;
|
||||||
|
EXPLAIN
|
||||||
|
{
|
||||||
|
"query_block": {
|
||||||
|
"select_id": 1,
|
||||||
|
"table": {
|
||||||
|
"table_name": "t1",
|
||||||
|
"access_type": "ALL",
|
||||||
|
"rows": 7,
|
||||||
|
"filtered": 100,
|
||||||
|
"attached_condition": "t1.a > 2 and t1.a is not null"
|
||||||
|
},
|
||||||
|
"table": {
|
||||||
|
"table_name": "<derived3>",
|
||||||
|
"access_type": "ref",
|
||||||
|
"possible_keys": ["key0"],
|
||||||
|
"key": "key0",
|
||||||
|
"key_length": "5",
|
||||||
|
"used_key_parts": ["m"],
|
||||||
|
"ref": ["test.t1.a"],
|
||||||
|
"rows": 2,
|
||||||
|
"filtered": 100,
|
||||||
|
"materialized": {
|
||||||
|
"query_block": {
|
||||||
|
"select_id": 3,
|
||||||
|
"having_condition": "m > 2",
|
||||||
|
"filesort": {
|
||||||
|
"sort_key": "t2.b",
|
||||||
|
"temporary_table": {
|
||||||
|
"table": {
|
||||||
|
"table_name": "t2",
|
||||||
|
"access_type": "ALL",
|
||||||
|
"rows": 9,
|
||||||
|
"filtered": 100
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
drop view v1,v2,v3;
|
||||||
|
drop table t1,t2;
|
||||||
|
@ -900,7 +900,7 @@ EXPLAIN
|
|||||||
"access_type": "ALL",
|
"access_type": "ALL",
|
||||||
"rows": 11,
|
"rows": 11,
|
||||||
"filtered": 100,
|
"filtered": 100,
|
||||||
"attached_condition": "t1.f1 in (2,3)"
|
"attached_condition": "t1.f1 < 7 and t1.f1 in (2,3)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1107,7 +1107,7 @@ id select_type table type possible_keys key key_len ref rows Extra
|
|||||||
1 PRIMARY t1 system NULL NULL NULL NULL 1
|
1 PRIMARY t1 system NULL NULL NULL NULL 1
|
||||||
1 PRIMARY t2 ref a a 4 const 1 Using index
|
1 PRIMARY t2 ref a a 4 const 1 Using index
|
||||||
1 PRIMARY <derived2> ref key0 key0 8 const,const 1
|
1 PRIMARY <derived2> ref key0 key0 8 const,const 1
|
||||||
2 DERIVED t3 ALL NULL NULL NULL NULL 12 Using temporary; Using filesort
|
2 DERIVED t3 ALL NULL NULL NULL NULL 12 Using where; Using temporary; Using filesort
|
||||||
SELECT * FROM t1, t2, v1 WHERE t2.a=t1.a AND t2.a=v1.a AND t2.a=v1.b;
|
SELECT * FROM t1, t2, v1 WHERE t2.a=t1.a AND t2.a=v1.a AND t2.a=v1.b;
|
||||||
a a a b
|
a a a b
|
||||||
c c c c
|
c c c c
|
||||||
|
@ -1452,3 +1452,60 @@ SELECT * FROM
|
|||||||
WHERE row <> order_number;
|
WHERE row <> order_number;
|
||||||
|
|
||||||
DROP TABLE sales_documents;
|
DROP TABLE sales_documents;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-12845: pushdown from merged derived using equalities
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
create table t1 (a int);
|
||||||
|
insert into t1 values
|
||||||
|
(4), (8), (5), (3), (10), (2), (7);
|
||||||
|
|
||||||
|
create table t2 (b int, c int);
|
||||||
|
insert into t2 values
|
||||||
|
(2,1), (5,2), (2,2), (4,1), (4,3),
|
||||||
|
(5,3), (2,4), (4,6), (2,1);
|
||||||
|
|
||||||
|
create view v1 as
|
||||||
|
select b, sum(c) as s from t2 group by b;
|
||||||
|
|
||||||
|
create view v2 as
|
||||||
|
select distinct b, c from t2;
|
||||||
|
|
||||||
|
create view v3 as
|
||||||
|
select b, max(c) as m from t2 group by b;
|
||||||
|
|
||||||
|
let $q1=
|
||||||
|
select b
|
||||||
|
from ( select t1.a, v1.b, v1.s from t1, v1 where t1.a = v1.b ) as t
|
||||||
|
where b > 2;
|
||||||
|
|
||||||
|
eval $q1;
|
||||||
|
eval explain format=json $q1;
|
||||||
|
|
||||||
|
let $q2=
|
||||||
|
select a
|
||||||
|
from ( select t1.a, v1.b, v1.s from t1, v1 where t1.a = v1.b ) as t
|
||||||
|
where a > 2;
|
||||||
|
|
||||||
|
eval $q2;
|
||||||
|
eval explain format=json $q2;
|
||||||
|
|
||||||
|
let $q3=
|
||||||
|
select a
|
||||||
|
from ( select t1.a, v2.b, v2.c from t1, v2 where t1.a = v2.b ) as t
|
||||||
|
where a > 2;
|
||||||
|
|
||||||
|
eval $q3;
|
||||||
|
eval explain format=json $q3;
|
||||||
|
|
||||||
|
let $q4=
|
||||||
|
select a
|
||||||
|
from ( select t1.a, v3.b, v3.m from t1, v3 where t1.a = v3.m ) as t
|
||||||
|
where a > 2;
|
||||||
|
|
||||||
|
eval $q4;
|
||||||
|
eval explain format=json $q4;
|
||||||
|
|
||||||
|
drop view v1,v2,v3;
|
||||||
|
drop table t1,t2;
|
||||||
|
293
sql/item.cc
293
sql/item.cc
@ -7120,121 +7120,182 @@ Item *Item_field::update_value_transformer(THD *thd, uchar *select_arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Item *Item_field::derived_field_transformer_for_having(THD *thd, uchar *arg)
|
static
|
||||||
|
Item *get_field_item_for_having(THD *thd, Item *item, st_select_lex *sel)
|
||||||
{
|
{
|
||||||
st_select_lex *sl= (st_select_lex *)arg;
|
DBUG_ASSERT(item->type() == Item::FIELD_ITEM ||
|
||||||
table_map map= sl->master_unit()->derived->table->map;
|
(item->type() == Item::REF_ITEM &&
|
||||||
if (!((Item_field*)this)->item_equal)
|
((Item_ref *) item)->ref_type() == Item_ref::VIEW_REF));
|
||||||
{
|
Item_field *field_item= NULL;
|
||||||
if (used_tables() == map)
|
table_map map= sel->master_unit()->derived->table->map;
|
||||||
{
|
Item_equal *item_equal= item->get_item_equal();
|
||||||
Item_ref *rf=
|
if (!item_equal)
|
||||||
new (thd->mem_root) Item_ref(thd, &sl->context,
|
field_item= (Item_field *)(item->real_item());
|
||||||
NullS, NullS,
|
|
||||||
((Item_field*) this)->field_name);
|
|
||||||
if (!rf)
|
|
||||||
return 0;
|
|
||||||
return rf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Item_equal *cond= (Item_equal *) ((Item_field*)this)->item_equal;
|
Item_equal_fields_iterator li(*item_equal);
|
||||||
Item_equal_fields_iterator li(*cond);
|
Item *equal_item;
|
||||||
Item *item;
|
while ((equal_item= li++))
|
||||||
while ((item=li++))
|
|
||||||
{
|
{
|
||||||
if (item->used_tables() == map && item->real_item()->type() == FIELD_ITEM)
|
if (equal_item->used_tables() == map)
|
||||||
{
|
{
|
||||||
Item_ref *rf=
|
field_item= (Item_field *)(equal_item->real_item());
|
||||||
new (thd->mem_root) Item_ref(thd, &sl->context,
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (field_item)
|
||||||
|
{
|
||||||
|
Item_ref *ref= new (thd->mem_root) Item_ref(thd, &sel->context,
|
||||||
NullS, NullS,
|
NullS, NullS,
|
||||||
((Item_field*) (item->real_item()))->field_name);
|
field_item->field_name);
|
||||||
if (!rf)
|
return ref;
|
||||||
return 0;
|
|
||||||
return rf;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
DBUG_ASSERT(0);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Item *Item_field::derived_field_transformer_for_having(THD *thd, uchar *arg)
|
||||||
|
{
|
||||||
|
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))
|
||||||
return this;
|
return this;
|
||||||
|
if (!item_equal && used_tables() != tab_map)
|
||||||
|
return this;
|
||||||
|
return get_field_item_for_having(thd, this, sel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Item *Item_field::derived_field_transformer_for_where(THD *thd, uchar *arg)
|
Item *Item_direct_view_ref::derived_field_transformer_for_having(THD *thd,
|
||||||
|
uchar *arg)
|
||||||
{
|
{
|
||||||
|
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))
|
||||||
|
return this;
|
||||||
|
if (!item_equal && used_tables() != tab_map)
|
||||||
|
return this;
|
||||||
|
return get_field_item_for_having(thd, this, sel);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static
|
||||||
|
Item *find_producing_item(Item *item, st_select_lex *sel)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(item->type() == Item::FIELD_ITEM ||
|
||||||
|
(item->type() == Item::REF_ITEM &&
|
||||||
|
((Item_ref *) item)->ref_type() == Item_ref::VIEW_REF));
|
||||||
Item *producing_item;
|
Item *producing_item;
|
||||||
st_select_lex *sl= (st_select_lex *)arg;
|
Item_field *field_item= NULL;
|
||||||
List_iterator_fast<Item> li(sl->item_list);
|
Item_equal *item_equal= item->get_item_equal();
|
||||||
table_map map= sl->master_unit()->derived->table->map;
|
table_map tab_map= sel->master_unit()->derived->table->map;
|
||||||
if (used_tables() == map)
|
if (item->used_tables() == tab_map)
|
||||||
|
field_item= (Item_field *) (item->real_item());
|
||||||
|
if (!field_item && item_equal)
|
||||||
{
|
{
|
||||||
uint field_no= ((Item_field*) this)->field->field_index;
|
Item_equal_fields_iterator it(*item_equal);
|
||||||
for (uint i= 0; i <= field_no; i++)
|
Item *equal_item;
|
||||||
producing_item= li++;
|
while ((equal_item= it++))
|
||||||
return producing_item->build_clone(thd, thd->mem_root);
|
{
|
||||||
|
if (equal_item->used_tables() == tab_map)
|
||||||
|
{
|
||||||
|
field_item= (Item_field *) (equal_item->real_item());
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else if (((Item_field*)this)->item_equal)
|
}
|
||||||
|
}
|
||||||
|
List_iterator_fast<Item> li(sel->item_list);
|
||||||
|
if (field_item)
|
||||||
{
|
{
|
||||||
Item_equal *cond= (Item_equal *) ((Item_field*)this)->item_equal;
|
|
||||||
Item_equal_fields_iterator it(*cond);
|
|
||||||
Item *item;
|
|
||||||
while ((item=it++))
|
|
||||||
{
|
|
||||||
if (item->used_tables() == map && item->real_item()->type() == FIELD_ITEM)
|
|
||||||
{
|
|
||||||
Item_field *field_item= (Item_field *) (item->real_item());
|
|
||||||
li.rewind();
|
|
||||||
uint field_no= field_item->field->field_index;
|
uint field_no= field_item->field->field_index;
|
||||||
for (uint i= 0; i <= field_no; i++)
|
for (uint i= 0; i <= field_no; i++)
|
||||||
producing_item= li++;
|
producing_item= li++;
|
||||||
|
return producing_item;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Item *Item_direct_view_ref::derived_field_transformer_for_where(THD *thd,
|
||||||
|
uchar *arg)
|
||||||
|
{
|
||||||
|
if (item_equal)
|
||||||
|
{
|
||||||
|
st_select_lex *sel= (st_select_lex *)arg;
|
||||||
|
Item *producing_item= find_producing_item(this, sel);
|
||||||
|
DBUG_ASSERT (producing_item != NULL);
|
||||||
return producing_item->build_clone(thd, thd->mem_root);
|
return producing_item->build_clone(thd, thd->mem_root);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
Grouping_tmp_field *find_matching_grouping_field(Item *item,
|
||||||
|
st_select_lex *sel)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(item->type() == Item::FIELD_ITEM ||
|
||||||
|
(item->type() == Item::REF_ITEM &&
|
||||||
|
((Item_ref *) item)->ref_type() == Item_ref::VIEW_REF));
|
||||||
|
List_iterator<Grouping_tmp_field> li(sel->grouping_tmp_fields);
|
||||||
|
Grouping_tmp_field *gr_field;
|
||||||
|
Item_field *field_item= (Item_field *) (item->real_item());
|
||||||
|
while ((gr_field= li++))
|
||||||
|
{
|
||||||
|
if (field_item->field == gr_field->tmp_field)
|
||||||
|
return gr_field;
|
||||||
|
}
|
||||||
|
Item_equal *item_equal= item->get_item_equal();
|
||||||
|
if (item_equal)
|
||||||
|
{
|
||||||
|
Item_equal_fields_iterator it(*item_equal);
|
||||||
|
Item *equal_item;
|
||||||
|
while ((equal_item= it++))
|
||||||
|
{
|
||||||
|
field_item= (Item_field *) (equal_item->real_item());
|
||||||
|
li.rewind();
|
||||||
|
while ((gr_field= li++))
|
||||||
|
{
|
||||||
|
if (field_item->field == gr_field->tmp_field)
|
||||||
|
return gr_field;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Item *Item_field::derived_grouping_field_transformer_for_where(THD *thd,
|
Item *Item_field::derived_grouping_field_transformer_for_where(THD *thd,
|
||||||
uchar *arg)
|
uchar *arg)
|
||||||
{
|
{
|
||||||
st_select_lex *sl= (st_select_lex *)arg;
|
st_select_lex *sel= (st_select_lex *)arg;
|
||||||
List_iterator<Grouping_tmp_field> li(sl->grouping_tmp_fields);
|
Grouping_tmp_field *gr_field= find_matching_grouping_field(this, sel);
|
||||||
Grouping_tmp_field *field;
|
if (gr_field)
|
||||||
table_map map= sl->master_unit()->derived->table->map;
|
return gr_field->producing_item->build_clone(thd, thd->mem_root);
|
||||||
if (used_tables() == map)
|
|
||||||
{
|
|
||||||
while ((field=li++))
|
|
||||||
{
|
|
||||||
if (((Item_field*) this)->field == field->tmp_field)
|
|
||||||
return field->producing_item->build_clone(thd, thd->mem_root);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (((Item_field*)this)->item_equal)
|
|
||||||
{
|
|
||||||
Item_equal *cond= (Item_equal *) ((Item_field*)this)->item_equal;
|
|
||||||
Item_equal_fields_iterator it(*cond);
|
|
||||||
Item *item;
|
|
||||||
while ((item=it++))
|
|
||||||
{
|
|
||||||
if (item->used_tables() == map && item->real_item()->type() == FIELD_ITEM)
|
|
||||||
{
|
|
||||||
Item_field *field_item= (Item_field *) (item->real_item());
|
|
||||||
li.rewind();
|
|
||||||
while ((field=li++))
|
|
||||||
{
|
|
||||||
if (field_item->field == field->tmp_field)
|
|
||||||
{
|
|
||||||
return field->producing_item->build_clone(thd, thd->mem_root);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Item *
|
||||||
|
Item_direct_view_ref::derived_grouping_field_transformer_for_where(THD *thd,
|
||||||
|
uchar *arg)
|
||||||
|
{
|
||||||
|
if (!item_equal)
|
||||||
|
return this;
|
||||||
|
st_select_lex *sel= (st_select_lex *)arg;
|
||||||
|
Grouping_tmp_field *gr_field= find_matching_grouping_field(this, sel);
|
||||||
|
return gr_field->producing_item->build_clone(thd, thd->mem_root);
|
||||||
|
}
|
||||||
|
|
||||||
void Item_field::print(String *str, enum_query_type query_type)
|
void Item_field::print(String *str, enum_query_type query_type)
|
||||||
{
|
{
|
||||||
if (field && field->table->const_table &&
|
if (field && field->table->const_table &&
|
||||||
@ -8702,6 +8763,32 @@ Item *Item_direct_view_ref::replace_equal_field(THD *thd, uchar *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Item_direct_view_ref::excl_dep_on_table(table_map tab_map)
|
||||||
|
{
|
||||||
|
table_map used= used_tables();
|
||||||
|
if (used & OUTER_REF_TABLE_BIT)
|
||||||
|
return false;
|
||||||
|
if (!(used & ~tab_map))
|
||||||
|
return true;
|
||||||
|
if (item_equal)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(real_item()->type() == Item::FIELD_ITEM);
|
||||||
|
return item_equal->used_tables() & tab_map;
|
||||||
|
}
|
||||||
|
return (*ref)->excl_dep_on_table(tab_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Item_direct_view_ref::excl_dep_on_grouping_fields(st_select_lex *sel)
|
||||||
|
{
|
||||||
|
if (item_equal)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(real_item()->type() == Item::FIELD_ITEM);
|
||||||
|
return find_matching_grouping_field(this, sel) != NULL;
|
||||||
|
}
|
||||||
|
return (*ref)->excl_dep_on_grouping_fields(sel);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Item_default_value::eq(const Item *item, bool binary_cmp) const
|
bool Item_default_value::eq(const Item *item, bool binary_cmp) const
|
||||||
{
|
{
|
||||||
return item->type() == DEFAULT_VALUE_ITEM &&
|
return item->type() == DEFAULT_VALUE_ITEM &&
|
||||||
@ -10613,46 +10700,16 @@ const char *dbug_print_unit(SELECT_LEX_UNIT *un)
|
|||||||
|
|
||||||
#endif /*DBUG_OFF*/
|
#endif /*DBUG_OFF*/
|
||||||
|
|
||||||
bool Item_field::exclusive_dependence_on_table_processor(void *map)
|
bool Item_field::excl_dep_on_table(table_map tab_map)
|
||||||
{
|
{
|
||||||
table_map tab_map= *((table_map *) map);
|
return used_tables() == tab_map ||
|
||||||
return !((used_tables() == tab_map ||
|
(item_equal && (item_equal->used_tables() & tab_map));
|
||||||
(item_equal && item_equal->used_tables() & tab_map)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Item_field::exclusive_dependence_on_grouping_fields_processor(void *arg)
|
bool
|
||||||
|
Item_field::excl_dep_on_grouping_fields(st_select_lex *sel)
|
||||||
{
|
{
|
||||||
st_select_lex *sl= (st_select_lex *)arg;
|
return find_matching_grouping_field(this, sel) != NULL;
|
||||||
List_iterator<Grouping_tmp_field> li(sl->grouping_tmp_fields);
|
|
||||||
Grouping_tmp_field *field;
|
|
||||||
table_map map= sl->master_unit()->derived->table->map;
|
|
||||||
if (used_tables() == map)
|
|
||||||
{
|
|
||||||
while ((field=li++))
|
|
||||||
{
|
|
||||||
if (((Item_field*) this)->field == field->tmp_field)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (((Item_field*)this)->item_equal)
|
|
||||||
{
|
|
||||||
Item_equal *cond= (Item_equal *) ((Item_field*)this)->item_equal;
|
|
||||||
Item_equal_fields_iterator it(*cond);
|
|
||||||
Item *item;
|
|
||||||
while ((item=it++))
|
|
||||||
{
|
|
||||||
if (item->used_tables() == map && item->real_item()->type() == FIELD_ITEM)
|
|
||||||
{
|
|
||||||
li.rewind();
|
|
||||||
while ((field=li++))
|
|
||||||
{
|
|
||||||
if (((Item_field *)(item->real_item()))->field == field->tmp_field)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Item::register_in(THD *thd)
|
void Item::register_in(THD *thd)
|
||||||
|
64
sql/item.h
64
sql/item.h
@ -1580,8 +1580,20 @@ public:
|
|||||||
virtual bool limit_index_condition_pushdown_processor(void *arg) { return 0; }
|
virtual bool limit_index_condition_pushdown_processor(void *arg) { return 0; }
|
||||||
virtual bool exists2in_processor(void *arg) { return 0; }
|
virtual bool exists2in_processor(void *arg) { return 0; }
|
||||||
virtual bool find_selective_predicates_list_processor(void *arg) { return 0; }
|
virtual bool find_selective_predicates_list_processor(void *arg) { return 0; }
|
||||||
virtual bool exclusive_dependence_on_table_processor(void *arg) { return 0; }
|
|
||||||
virtual bool exclusive_dependence_on_grouping_fields_processor(void *arg) { return 0; }
|
/*
|
||||||
|
TRUE if the expression depends only on the table indicated by tab_map
|
||||||
|
or can be converted to such an exression using equalities.
|
||||||
|
Not to be used for AND/OR formulas.
|
||||||
|
*/
|
||||||
|
virtual bool excl_dep_on_table(table_map tab_map) { return false; }
|
||||||
|
/*
|
||||||
|
TRUE if the expression depends only on grouping fields of sel
|
||||||
|
or can be converted to such an exression using equalities.
|
||||||
|
Not to be used for AND/OR formulas.
|
||||||
|
*/
|
||||||
|
virtual bool excl_dep_on_grouping_fields(st_select_lex *sel) { return false; }
|
||||||
|
|
||||||
virtual bool switch_to_nullable_fields_processor(void *arg) { return 0; }
|
virtual bool switch_to_nullable_fields_processor(void *arg) { return 0; }
|
||||||
virtual bool find_function_processor (void *arg) { return 0; }
|
virtual bool find_function_processor (void *arg) { return 0; }
|
||||||
/*
|
/*
|
||||||
@ -2633,8 +2645,8 @@ public:
|
|||||||
Item *derived_field_transformer_for_where(THD *thd, uchar *arg);
|
Item *derived_field_transformer_for_where(THD *thd, uchar *arg);
|
||||||
Item *derived_grouping_field_transformer_for_where(THD *thd, uchar *arg);
|
Item *derived_grouping_field_transformer_for_where(THD *thd, uchar *arg);
|
||||||
virtual void print(String *str, enum_query_type query_type);
|
virtual void print(String *str, enum_query_type query_type);
|
||||||
bool exclusive_dependence_on_table_processor(void *map);
|
bool excl_dep_on_table(table_map tab_map);
|
||||||
bool exclusive_dependence_on_grouping_fields_processor(void *arg);
|
bool excl_dep_on_grouping_fields(st_select_lex *sel);
|
||||||
bool cleanup_excluding_fields_processor(void *arg)
|
bool cleanup_excluding_fields_processor(void *arg)
|
||||||
{ return field ? 0 : cleanup_processor(arg); }
|
{ return field ? 0 : cleanup_processor(arg); }
|
||||||
bool cleanup_excluding_const_fields_processor(void *arg)
|
bool cleanup_excluding_const_fields_processor(void *arg)
|
||||||
@ -3853,6 +3865,28 @@ protected:
|
|||||||
}
|
}
|
||||||
bool transform_args(THD *thd, Item_transformer transformer, uchar *arg);
|
bool transform_args(THD *thd, Item_transformer transformer, uchar *arg);
|
||||||
void propagate_equal_fields(THD *, const Item::Context &, COND_EQUAL *);
|
void propagate_equal_fields(THD *, const Item::Context &, COND_EQUAL *);
|
||||||
|
bool excl_dep_on_table(table_map tab_map)
|
||||||
|
{
|
||||||
|
for (uint i= 0; i < arg_count; i++)
|
||||||
|
{
|
||||||
|
if (args[i]->const_item())
|
||||||
|
continue;
|
||||||
|
if (!args[i]->excl_dep_on_table(tab_map))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool excl_dep_on_grouping_fields(st_select_lex *sel)
|
||||||
|
{
|
||||||
|
for (uint i= 0; i < arg_count; i++)
|
||||||
|
{
|
||||||
|
if (args[i]->const_item())
|
||||||
|
continue;
|
||||||
|
if (!args[i]->excl_dep_on_grouping_fields(sel))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
public:
|
public:
|
||||||
Item_args(void)
|
Item_args(void)
|
||||||
:args(NULL), arg_count(0)
|
:args(NULL), arg_count(0)
|
||||||
@ -4321,10 +4355,15 @@ public:
|
|||||||
}
|
}
|
||||||
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
|
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
|
||||||
{ return get_item_copy<Item_ref>(thd, mem_root, this); }
|
{ return get_item_copy<Item_ref>(thd, mem_root, this); }
|
||||||
bool exclusive_dependence_on_table_processor(void *map)
|
bool excl_dep_on_table(table_map tab_map)
|
||||||
{ return depended_from != NULL; }
|
{
|
||||||
bool exclusive_dependence_on_grouping_fields_processor(void *arg)
|
table_map used= used_tables();
|
||||||
{ return depended_from != NULL; }
|
if (used & OUTER_REF_TABLE_BIT)
|
||||||
|
return false;
|
||||||
|
return (used == tab_map) || (*ref)->excl_dep_on_table(tab_map);
|
||||||
|
}
|
||||||
|
bool excl_dep_on_grouping_fields(st_select_lex *sel)
|
||||||
|
{ return (*ref)->excl_dep_on_grouping_fields(sel); }
|
||||||
bool cleanup_excluding_fields_processor(void *arg)
|
bool cleanup_excluding_fields_processor(void *arg)
|
||||||
{
|
{
|
||||||
Item *item= real_item();
|
Item *item= real_item();
|
||||||
@ -4628,6 +4667,13 @@ public:
|
|||||||
view_arg->view_used_tables|= (*ref)->used_tables();
|
view_arg->view_used_tables|= (*ref)->used_tables();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
bool excl_dep_on_table(table_map tab_map);
|
||||||
|
bool excl_dep_on_grouping_fields(st_select_lex *sel);
|
||||||
|
Item *derived_field_transformer_for_having(THD *thd, uchar *arg);
|
||||||
|
Item *derived_field_transformer_for_where(THD *thd, uchar *arg);
|
||||||
|
Item *derived_grouping_field_transformer_for_where(THD *thd,
|
||||||
|
uchar *arg);
|
||||||
|
|
||||||
void save_val(Field *to)
|
void save_val(Field *to)
|
||||||
{
|
{
|
||||||
if (check_null_ref())
|
if (check_null_ref())
|
||||||
@ -4709,6 +4755,8 @@ public:
|
|||||||
item_equal= NULL;
|
item_equal= NULL;
|
||||||
Item_direct_ref::cleanup();
|
Item_direct_ref::cleanup();
|
||||||
}
|
}
|
||||||
|
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
|
||||||
|
{ return get_item_copy<Item_direct_view_ref>(thd, mem_root, this); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -2395,6 +2395,14 @@ public:
|
|||||||
void set_context_field(Item_field *ctx_field) { context_field= ctx_field; }
|
void set_context_field(Item_field *ctx_field) { context_field= ctx_field; }
|
||||||
void set_link_equal_fields(bool flag) { link_equal_fields= flag; }
|
void set_link_equal_fields(bool flag) { link_equal_fields= flag; }
|
||||||
Item* get_copy(THD *thd, MEM_ROOT *mem_root) { return 0; }
|
Item* get_copy(THD *thd, MEM_ROOT *mem_root) { return 0; }
|
||||||
|
/*
|
||||||
|
This does not comply with the specification of the virtual method,
|
||||||
|
but Item_equal items are processed distinguishly anyway
|
||||||
|
*/
|
||||||
|
bool excl_dep_on_table(table_map tab_map)
|
||||||
|
{
|
||||||
|
return used_tables() & tab_map;
|
||||||
|
}
|
||||||
friend class Item_equal_fields_iterator;
|
friend class Item_equal_fields_iterator;
|
||||||
bool count_sargable_conds(void *arg);
|
bool count_sargable_conds(void *arg);
|
||||||
friend class Item_equal_iterator<List_iterator_fast,Item>;
|
friend class Item_equal_iterator<List_iterator_fast,Item>;
|
||||||
|
@ -316,6 +316,19 @@ public:
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool excl_dep_on_table(table_map tab_map)
|
||||||
|
{
|
||||||
|
if (used_tables() & OUTER_REF_TABLE_BIT)
|
||||||
|
return false;
|
||||||
|
return !(used_tables() & ~tab_map) ||
|
||||||
|
Item_args::excl_dep_on_table(tab_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool excl_dep_on_grouping_fields(st_select_lex *sel)
|
||||||
|
{
|
||||||
|
return Item_args::excl_dep_on_grouping_fields(sel);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We assume the result of any function that has a TIMESTAMP argument to be
|
We assume the result of any function that has a TIMESTAMP argument to be
|
||||||
timezone-dependent, since a TIMESTAMP value in both numeric and string
|
timezone-dependent, since a TIMESTAMP value in both numeric and string
|
||||||
|
@ -126,6 +126,16 @@ public:
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool excl_dep_on_table(table_map tab_map)
|
||||||
|
{
|
||||||
|
return Item_args::excl_dep_on_table(tab_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool excl_dep_on_grouping_fields(st_select_lex *sel)
|
||||||
|
{
|
||||||
|
return Item_args::excl_dep_on_grouping_fields(sel);
|
||||||
|
}
|
||||||
|
|
||||||
bool check_vcol_func_processor(void *arg) {return FALSE; }
|
bool check_vcol_func_processor(void *arg) {return FALSE; }
|
||||||
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
|
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
|
||||||
{ return get_item_copy<Item_row>(thd, mem_root, this); }
|
{ return get_item_copy<Item_row>(thd, mem_root, this); }
|
||||||
|
@ -1246,7 +1246,7 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived)
|
|||||||
Item *cond_over_grouping_fields;
|
Item *cond_over_grouping_fields;
|
||||||
sl->collect_grouping_fields(thd);
|
sl->collect_grouping_fields(thd);
|
||||||
sl->check_cond_extraction_for_grouping_fields(extracted_cond_copy,
|
sl->check_cond_extraction_for_grouping_fields(extracted_cond_copy,
|
||||||
&Item::exclusive_dependence_on_grouping_fields_processor);
|
derived);
|
||||||
cond_over_grouping_fields=
|
cond_over_grouping_fields=
|
||||||
sl->build_cond_for_grouping_fields(thd, extracted_cond_copy, true);
|
sl->build_cond_for_grouping_fields(thd, extracted_cond_copy, true);
|
||||||
|
|
||||||
@ -1285,7 +1285,8 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived)
|
|||||||
if (!extracted_cond_copy)
|
if (!extracted_cond_copy)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
extracted_cond_copy->walk(&Item::cleanup_processor, 0, 0);
|
extracted_cond_copy->walk(&Item::cleanup_excluding_const_fields_processor,
|
||||||
|
0, 0);
|
||||||
sl->cond_pushed_into_having= extracted_cond_copy;
|
sl->cond_pushed_into_having= extracted_cond_copy;
|
||||||
}
|
}
|
||||||
thd->lex->current_select= save_curr_select;
|
thd->lex->current_select= save_curr_select;
|
||||||
|
@ -5006,8 +5006,9 @@ void st_select_lex::collect_grouping_fields(THD *thd)
|
|||||||
from cond.
|
from cond.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void st_select_lex::check_cond_extraction_for_grouping_fields(Item *cond,
|
void
|
||||||
Item_processor check_processor)
|
st_select_lex::check_cond_extraction_for_grouping_fields(Item *cond,
|
||||||
|
TABLE_LIST *derived)
|
||||||
{
|
{
|
||||||
cond->clear_extraction_flag();
|
cond->clear_extraction_flag();
|
||||||
if (cond->type() == Item::COND_ITEM)
|
if (cond->type() == Item::COND_ITEM)
|
||||||
@ -5020,7 +5021,7 @@ void st_select_lex::check_cond_extraction_for_grouping_fields(Item *cond,
|
|||||||
Item *item;
|
Item *item;
|
||||||
while ((item=li++))
|
while ((item=li++))
|
||||||
{
|
{
|
||||||
check_cond_extraction_for_grouping_fields(item, check_processor);
|
check_cond_extraction_for_grouping_fields(item, derived);
|
||||||
if (item->get_extraction_flag() != NO_EXTRACTION_FL)
|
if (item->get_extraction_flag() != NO_EXTRACTION_FL)
|
||||||
{
|
{
|
||||||
count++;
|
count++;
|
||||||
@ -5042,9 +5043,11 @@ void st_select_lex::check_cond_extraction_for_grouping_fields(Item *cond,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
cond->set_extraction_flag(cond->walk(check_processor,
|
{
|
||||||
0, (uchar *) this) ?
|
int fl= cond->excl_dep_on_grouping_fields(this) ?
|
||||||
NO_EXTRACTION_FL : FULL_EXTRACTION_FL);
|
FULL_EXTRACTION_FL : NO_EXTRACTION_FL;
|
||||||
|
cond->set_extraction_flag(fl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1139,7 +1139,7 @@ public:
|
|||||||
bool check_subqueries_with_recursive_references();
|
bool check_subqueries_with_recursive_references();
|
||||||
void collect_grouping_fields(THD *thd);
|
void collect_grouping_fields(THD *thd);
|
||||||
void check_cond_extraction_for_grouping_fields(Item *cond,
|
void check_cond_extraction_for_grouping_fields(Item *cond,
|
||||||
Item_processor processor);
|
TABLE_LIST *derived);
|
||||||
Item *build_cond_for_grouping_fields(THD *thd, Item *cond,
|
Item *build_cond_for_grouping_fields(THD *thd, Item *cond,
|
||||||
bool no_to_clones);
|
bool no_to_clones);
|
||||||
|
|
||||||
|
@ -8128,8 +8128,7 @@ void TABLE_LIST::check_pushable_cond_for_table(Item *cond)
|
|||||||
item->clear_extraction_flag();
|
item->clear_extraction_flag();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (cond->walk(&Item::exclusive_dependence_on_table_processor,
|
else if (!cond->excl_dep_on_table(tab_map))
|
||||||
0, (void *) &tab_map))
|
|
||||||
cond->set_extraction_flag(NO_EXTRACTION_FL);
|
cond->set_extraction_flag(NO_EXTRACTION_FL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user