Commit 20109712 authored by Oleksandr Byelkin's avatar Oleksandr Byelkin

MDEV-6892: WHERE does not apply

Taking into account implicit dependence of constant view field from nullable table of left join added.

Fixed finding real table to check if it turned to NULL (materialized view & derived taken into account)

Removed incorrect uninitialization.
parent 8cbaafd2
......@@ -568,3 +568,15 @@ update t1 set balance=(select sum(balance) from (SELECT balance FROM t1 where ac
set optimizer_switch=@save_derived_optimizer_switch_bug;
drop table t1;
set optimizer_switch=@save_derived_optimizer_switch;
#
# MDEV-6892: WHERE does not apply
#
create table t1 (id int);
create table t2 (id int);
insert into t1 values(1),(2),(3);
insert into t2 values(4),(5),(6);
select x.id, message from (select id from t1) x left join
(select id, 1 as message from t2) y on x.id=y.id
where coalesce(message,0) <> 0;
id message
drop table t1,t2;
......@@ -492,5 +492,17 @@ update t1 set balance=(select sum(balance) from (SELECT balance FROM t1 where ac
set optimizer_switch=@save_derived_optimizer_switch_bug;
drop table t1;
set optimizer_switch=@save_derived_optimizer_switch;
--echo #
--echo # MDEV-6892: WHERE does not apply
--echo #
create table t1 (id int);
create table t2 (id int);
insert into t1 values(1),(2),(3);
insert into t2 values(4),(5),(6);
#explain extended
select x.id, message from (select id from t1) x left join
(select id, 1 as message from t2) y on x.id=y.id
where coalesce(message,0) <> 0;
drop table t1,t2;
......@@ -7949,6 +7949,7 @@ bool Item_direct_view_ref::fix_fields(THD *thd, Item **reference)
return TRUE;
if (view->table && view->table->maybe_null)
maybe_null= TRUE;
set_null_ref_table();
return FALSE;
}
......@@ -9790,13 +9791,28 @@ void Item_ref::update_used_tables()
(*ref)->update_used_tables();
}
void Item_direct_view_ref::update_used_tables()
{
set_null_ref_table();
Item_direct_ref::update_used_tables();
}
table_map Item_direct_view_ref::used_tables() const
{
return get_depended_from() ?
OUTER_REF_TABLE_BIT :
((view->is_merged_derived() || view->merged || !view->table) ?
(*ref)->used_tables() :
view->table->map);
DBUG_ASSERT(null_ref_table);
if (get_depended_from())
return OUTER_REF_TABLE_BIT;
if (view->is_merged_derived() || view->merged || !view->table)
return ((*ref)->used_tables() ?
(*ref)->used_tables() :
((null_ref_table != NO_NULL_TABLE) ?
null_ref_table->map :
(table_map)0 ));
return view->table->map;
}
table_map Item_direct_view_ref::not_null_tables() const
......
......@@ -3315,13 +3315,16 @@ class Item_direct_view_ref :public Item_direct_ref
#define NO_NULL_TABLE (reinterpret_cast<TABLE *>(0x1))
void set_null_ref_table()
{
if (!view->is_inner_table_of_outer_join() ||
!(null_ref_table= view->get_real_join_table()))
null_ref_table= NO_NULL_TABLE;
}
bool check_null_ref()
{
if (null_ref_table == NULL)
{
if (!(null_ref_table= view->get_real_join_table()))
null_ref_table= NO_NULL_TABLE;
}
DBUG_ASSERT(null_ref_table);
if (null_ref_table != NO_NULL_TABLE && null_ref_table->null_row)
{
null_value= 1;
......@@ -3329,6 +3332,7 @@ class Item_direct_view_ref :public Item_direct_ref
}
return FALSE;
}
public:
Item_direct_view_ref(Name_resolution_context *context_arg, Item **item,
const char *table_name_arg,
......@@ -3336,7 +3340,11 @@ public:
TABLE_LIST *view_arg)
:Item_direct_ref(context_arg, item, table_name_arg, field_name_arg),
item_equal(0), view(view_arg),
null_ref_table(NULL) {}
null_ref_table(NULL)
{
if (fixed)
set_null_ref_table();
}
bool fix_fields(THD *, Item **);
bool eq(const Item *item, bool binary_cmp) const;
......@@ -3353,8 +3361,10 @@ public:
bool subst_argument_checker(uchar **arg);
Item *equal_fields_propagator(uchar *arg);
Item *replace_equal_field(uchar *arg);
table_map used_tables() const;
table_map used_tables() const;
void update_used_tables();
table_map not_null_tables() const;
bool const_item() const { return used_tables() == 0; }
bool walk(Item_processor processor, bool walk_subquery, uchar *arg)
{
return (*ref)->walk(processor, walk_subquery, arg) ||
......
......@@ -5034,7 +5034,8 @@ TABLE *TABLE_LIST::get_real_join_table()
TABLE_LIST *tbl= this;
while (tbl->table == NULL || tbl->table->reginfo.join_tab == NULL)
{
if (tbl->view == NULL && tbl->derived == NULL)
if ((tbl->view == NULL && tbl->derived == NULL) ||
tbl->is_materialized_derived())
break;
/* we do not support merging of union yet */
DBUG_ASSERT(tbl->view == NULL ||
......@@ -5043,28 +5044,25 @@ TABLE *TABLE_LIST::get_real_join_table()
tbl->derived->first_select()->next_select() == NULL);
{
List_iterator_fast<TABLE_LIST> ti;
List_iterator_fast<TABLE_LIST>
ti(tbl->view != NULL ?
tbl->view->select_lex.top_join_list :
tbl->derived->first_select()->top_join_list);
for (;;)
{
List_iterator_fast<TABLE_LIST>
ti(tbl->view != NULL ?
tbl->view->select_lex.top_join_list :
tbl->derived->first_select()->top_join_list);
for (;;)
{
tbl= NULL;
/*
Find left table in outer join on this level
(the list is reverted).
*/
for (TABLE_LIST *t= ti++; t; t= ti++)
tbl= t;
if (!tbl)
return NULL; // view/derived with no tables
if (!tbl->nested_join)
break;
/* go deeper if we've found nested join */
ti= tbl->nested_join->join_list;
}
tbl= NULL;
/*
Find left table in outer join on this level
(the list is reverted).
*/
for (TABLE_LIST *t= ti++; t; t= ti++)
tbl= t;
if (!tbl)
return NULL; // view/derived with no tables
if (!tbl->nested_join)
break;
/* go deeper if we've found nested join */
ti= tbl->nested_join->join_list;
}
}
}
......
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