1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

Fixed LP bug #729039.

If join condition is of the form <t2.key>=<t1.no_key> then the server
performs no index look-ups when looking for matching rows of t2 for
the rows from t1 with t1.no_key=NULL. It happens because the function
add_not_null_conds() injects an additional condition of the form 
IS NOT NULL(<t1.no_key>) into the WHERE condition.
However if the join condition was of the form <t.key>=<outer_ref> no
additional null rejecting predicate was generated. This could lead
to extra records in the result set if the value of <outer_ref> happened
to be NULL.
The new code injects null rejecting predicates of the form 
IS NOT NULL(<outer_ref>) and evaluates them before the first row
the subquery is constructed.
This commit is contained in:
Igor Babaev
2011-03-07 22:09:21 -08:00
parent 0d5d68f684
commit 3d3d5f1d43
7 changed files with 158 additions and 4 deletions

View File

@ -6891,7 +6891,7 @@ static void add_not_null_conds(JOIN *join)
UPDATE t1 SET t1.f2=(SELECT MAX(t2.f4) FROM t2 WHERE t2.f3=t1.f1);
not_null_item is the t1.f1, but it's referred_tab is 0.
*/
if (!referred_tab || referred_tab->join != join)
if (!referred_tab)
continue;
if (!(notnull= new Item_func_isnotnull(not_null_item)))
DBUG_VOID_RETURN;
@ -6908,9 +6908,14 @@ static void add_not_null_conds(JOIN *join)
QT_ORDINARY););
if (!tab->first_inner)
{
COND *new_cond= referred_tab->select_cond;
COND *new_cond= referred_tab->join == join ?
referred_tab->select_cond :
join->outer_ref_cond;
add_cond_and_fix(&new_cond, notnull);
referred_tab->set_select_cond(new_cond, __LINE__);
if (referred_tab->join == join)
referred_tab->set_select_cond(new_cond, __LINE__);
else
join->outer_ref_cond= new_cond;
}
else
add_cond_and_fix(tab->first_inner->on_expr_ref, notnull);
@ -7127,6 +7132,15 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
DBUG_PRINT("info",("Found impossible WHERE condition"));
DBUG_RETURN(1); // Impossible const condition
}
COND *outer_ref_cond= make_cond_for_table(cond,
OUTER_REF_TABLE_BIT,
(table_map) 0, FALSE, FALSE);
if (outer_ref_cond)
{
add_cond_and_fix(&outer_ref_cond, join->outer_ref_cond);
join->outer_ref_cond= outer_ref_cond;
}
}
}
@ -13393,7 +13407,10 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
else
{
DBUG_ASSERT(join->tables);
error= join->first_select(join,join_tab,0);
if (join->outer_ref_cond && !join->outer_ref_cond->val_int())
error= NESTED_LOOP_NO_MORE_ROWS;
else
error= join->first_select(join,join_tab,0);
if (error == NESTED_LOOP_OK || error == NESTED_LOOP_NO_MORE_ROWS)
error= join->first_select(join,join_tab,1);
if (error == NESTED_LOOP_QUERY_LIMIT)