mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
Merge mysql.com:/home/psergey/mysql-5.0-bug8804-r12
into mysql.com:/home/psergey/mysql-5.1-bug8804-r12-merge sql/item_cmpfunc.cc: Auto merged sql/item_cmpfunc.h: Auto merged sql/item_subselect.h: Auto merged sql/mysql_priv.h: Auto merged sql/mysqld.cc: Auto merged sql/sql_lex.h: Auto merged sql/sql_select.cc: Auto merged sql/sql_select.h: Auto merged mysql-test/r/ndb_subquery.result: Manual merge mysql-test/r/subselect.result: Manual merge mysql-test/r/subselect3.result: Manual merge sql/item_subselect.cc: Manual merge
This commit is contained in:
@@ -234,16 +234,16 @@ bool Item_subselect::walk(Item_processor processor, bool walk_subquery,
|
||||
}
|
||||
|
||||
|
||||
bool Item_subselect::exec(bool full_scan)
|
||||
bool Item_subselect::exec()
|
||||
{
|
||||
int res;
|
||||
|
||||
res= engine->exec(full_scan);
|
||||
res= engine->exec();
|
||||
|
||||
if (engine_changed)
|
||||
{
|
||||
engine_changed= 0;
|
||||
return exec(full_scan);
|
||||
return exec();
|
||||
}
|
||||
return (res);
|
||||
}
|
||||
@@ -491,13 +491,13 @@ bool Item_singlerow_subselect::null_inside()
|
||||
|
||||
void Item_singlerow_subselect::bring_value()
|
||||
{
|
||||
exec(FALSE);
|
||||
exec();
|
||||
}
|
||||
|
||||
double Item_singlerow_subselect::val_real()
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
if (!exec(FALSE) && !value->null_value)
|
||||
if (!exec() && !value->null_value)
|
||||
{
|
||||
null_value= 0;
|
||||
return value->val_real();
|
||||
@@ -512,7 +512,7 @@ double Item_singlerow_subselect::val_real()
|
||||
longlong Item_singlerow_subselect::val_int()
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
if (!exec(FALSE) && !value->null_value)
|
||||
if (!exec() && !value->null_value)
|
||||
{
|
||||
null_value= 0;
|
||||
return value->val_int();
|
||||
@@ -526,7 +526,7 @@ longlong Item_singlerow_subselect::val_int()
|
||||
|
||||
String *Item_singlerow_subselect::val_str(String *str)
|
||||
{
|
||||
if (!exec(FALSE) && !value->null_value)
|
||||
if (!exec() && !value->null_value)
|
||||
{
|
||||
null_value= 0;
|
||||
return value->val_str(str);
|
||||
@@ -541,7 +541,7 @@ String *Item_singlerow_subselect::val_str(String *str)
|
||||
|
||||
my_decimal *Item_singlerow_subselect::val_decimal(my_decimal *decimal_value)
|
||||
{
|
||||
if (!exec(FALSE) && !value->null_value)
|
||||
if (!exec() && !value->null_value)
|
||||
{
|
||||
null_value= 0;
|
||||
return value->val_decimal(decimal_value);
|
||||
@@ -556,7 +556,7 @@ my_decimal *Item_singlerow_subselect::val_decimal(my_decimal *decimal_value)
|
||||
|
||||
bool Item_singlerow_subselect::val_bool()
|
||||
{
|
||||
if (!exec(FALSE) && !value->null_value)
|
||||
if (!exec() && !value->null_value)
|
||||
{
|
||||
null_value= 0;
|
||||
return value->val_bool();
|
||||
@@ -608,7 +608,7 @@ bool Item_in_subselect::test_limit(SELECT_LEX_UNIT *unit)
|
||||
Item_in_subselect::Item_in_subselect(Item * left_exp,
|
||||
st_select_lex *select_lex):
|
||||
Item_exists_subselect(), optimizer(0), transformed(0),
|
||||
enable_pushed_conds(TRUE), upper_item(0)
|
||||
pushed_cond_guards(NULL), upper_item(0)
|
||||
{
|
||||
DBUG_ENTER("Item_in_subselect::Item_in_subselect");
|
||||
left_expr= left_exp;
|
||||
@@ -653,7 +653,7 @@ void Item_exists_subselect::fix_length_and_dec()
|
||||
double Item_exists_subselect::val_real()
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
if (exec(FALSE))
|
||||
if (exec())
|
||||
{
|
||||
reset();
|
||||
return 0;
|
||||
@@ -664,7 +664,7 @@ double Item_exists_subselect::val_real()
|
||||
longlong Item_exists_subselect::val_int()
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
if (exec(FALSE))
|
||||
if (exec())
|
||||
{
|
||||
reset();
|
||||
return 0;
|
||||
@@ -675,7 +675,7 @@ longlong Item_exists_subselect::val_int()
|
||||
String *Item_exists_subselect::val_str(String *str)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
if (exec(FALSE))
|
||||
if (exec())
|
||||
{
|
||||
reset();
|
||||
return 0;
|
||||
@@ -688,7 +688,7 @@ String *Item_exists_subselect::val_str(String *str)
|
||||
my_decimal *Item_exists_subselect::val_decimal(my_decimal *decimal_value)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
if (exec(FALSE))
|
||||
if (exec())
|
||||
{
|
||||
reset();
|
||||
return 0;
|
||||
@@ -701,7 +701,7 @@ my_decimal *Item_exists_subselect::val_decimal(my_decimal *decimal_value)
|
||||
bool Item_exists_subselect::val_bool()
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
if (exec(FALSE))
|
||||
if (exec())
|
||||
{
|
||||
reset();
|
||||
return 0;
|
||||
@@ -719,7 +719,7 @@ double Item_in_subselect::val_real()
|
||||
DBUG_ASSERT(0);
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
null_value= 0;
|
||||
if (exec(!enable_pushed_conds))
|
||||
if (exec())
|
||||
{
|
||||
reset();
|
||||
null_value= 1;
|
||||
@@ -740,7 +740,7 @@ longlong Item_in_subselect::val_int()
|
||||
DBUG_ASSERT(0);
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
null_value= 0;
|
||||
if (exec(!enable_pushed_conds))
|
||||
if (exec())
|
||||
{
|
||||
reset();
|
||||
null_value= 1;
|
||||
@@ -761,7 +761,7 @@ String *Item_in_subselect::val_str(String *str)
|
||||
DBUG_ASSERT(0);
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
null_value= 0;
|
||||
if (exec(!enable_pushed_conds))
|
||||
if (exec())
|
||||
{
|
||||
reset();
|
||||
null_value= 1;
|
||||
@@ -781,7 +781,7 @@ bool Item_in_subselect::val_bool()
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
null_value= 0;
|
||||
if (exec(!enable_pushed_conds))
|
||||
if (exec())
|
||||
{
|
||||
reset();
|
||||
null_value= 1;
|
||||
@@ -801,7 +801,7 @@ my_decimal *Item_in_subselect::val_decimal(my_decimal *decimal_value)
|
||||
DBUG_ASSERT(0);
|
||||
null_value= 0;
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
if (exec(!enable_pushed_conds))
|
||||
if (exec())
|
||||
{
|
||||
reset();
|
||||
null_value= 1;
|
||||
@@ -965,7 +965,7 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
||||
|
||||
if (!substitution)
|
||||
{
|
||||
//first call for this unit
|
||||
/* We're invoked for the 1st (or the only) SELECT in the subquery UNION */
|
||||
SELECT_LEX_UNIT *unit= select_lex->master_unit();
|
||||
substitution= optimizer;
|
||||
|
||||
@@ -991,19 +991,14 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
||||
|
||||
unit->uncacheable|= UNCACHEABLE_DEPENDENT;
|
||||
}
|
||||
if (!abort_on_null && left_expr->maybe_null && !pushed_cond_guards)
|
||||
{
|
||||
if (!(pushed_cond_guards= (bool*)join->thd->alloc(sizeof(bool))))
|
||||
DBUG_RETURN(RES_ERROR);
|
||||
pushed_cond_guards[0]= TRUE;
|
||||
}
|
||||
|
||||
select_lex->uncacheable|= UNCACHEABLE_DEPENDENT;
|
||||
/*
|
||||
Add the left part of a subselect to a WHERE or HAVING clause of
|
||||
the right part, e.g.
|
||||
|
||||
SELECT 1 IN (SELECT a FROM t1) =>
|
||||
|
||||
SELECT Item_in_optimizer(1, SELECT a FROM t1 WHERE a=1)
|
||||
|
||||
HAVING is used only if the right part contains a SUM function, a GROUP
|
||||
BY or a HAVING clause.
|
||||
*/
|
||||
if (join->having || select_lex->with_sum_func ||
|
||||
select_lex->group_list.elements)
|
||||
{
|
||||
@@ -1015,13 +1010,13 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
||||
ref_pointer_array,
|
||||
(char *)"<ref>",
|
||||
this->full_name()));
|
||||
if (!abort_on_null && ((Item*)select_lex->item_list.head())->maybe_null)
|
||||
if (!abort_on_null && left_expr->maybe_null)
|
||||
{
|
||||
/*
|
||||
We can encounter "NULL IN (SELECT ...)". Wrap the added condition
|
||||
within a trigger.
|
||||
within a trig_cond.
|
||||
*/
|
||||
item= new Item_func_trig_cond(item, &enable_pushed_conds);
|
||||
item= new Item_func_trig_cond(item, get_cond_guard(0));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1030,6 +1025,8 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
||||
argument (reference) to fix_fields()
|
||||
*/
|
||||
select_lex->having= join->having= and_items(join->having, item);
|
||||
if (join->having == item)
|
||||
item->name= (char*)in_having_cond;
|
||||
select_lex->having_fix_field= 1;
|
||||
/*
|
||||
we do not check join->having->fixed, because Item_and (from and_items)
|
||||
@@ -1056,14 +1053,19 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
||||
item= func->create(expr, item);
|
||||
if (!abort_on_null && orig_item->maybe_null)
|
||||
{
|
||||
having=
|
||||
new Item_func_trig_cond(new Item_is_not_null_test(this, having),
|
||||
&enable_pushed_conds);
|
||||
having= new Item_is_not_null_test(this, having);
|
||||
if (left_expr->maybe_null)
|
||||
{
|
||||
if (!(having= new Item_func_trig_cond(having,
|
||||
get_cond_guard(0))))
|
||||
DBUG_RETURN(RES_ERROR);
|
||||
}
|
||||
/*
|
||||
Item_is_not_null_test can't be changed during fix_fields()
|
||||
we can assign select_lex->having here, and pass 0 as last
|
||||
argument (reference) to fix_fields()
|
||||
*/
|
||||
having->name= (char*)in_having_cond;
|
||||
select_lex->having= join->having= having;
|
||||
select_lex->having_fix_field= 1;
|
||||
/*
|
||||
@@ -1075,17 +1077,25 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
||||
select_lex->having_fix_field= 0;
|
||||
if (tmp)
|
||||
DBUG_RETURN(RES_ERROR);
|
||||
/*
|
||||
NOTE: It is important that we add this "IS NULL" here, even when
|
||||
orig_item can't be NULL. This is needed so that this predicate is
|
||||
only used by ref[_or_null] analyzer (and, e.g. is not used by const
|
||||
propagation).
|
||||
*/
|
||||
item= new Item_cond_or(item,
|
||||
new Item_func_isnull(orig_item));
|
||||
item= new Item_func_trig_cond(item, &enable_pushed_conds);
|
||||
}
|
||||
/*
|
||||
If we may encounter NULL IN (SELECT ...) and care whether subquery
|
||||
result is NULL or FALSE, wrap condition in a trig_cond.
|
||||
*/
|
||||
if (!abort_on_null && left_expr->maybe_null)
|
||||
{
|
||||
if (!(item= new Item_func_trig_cond(item, get_cond_guard(0))))
|
||||
DBUG_RETURN(RES_ERROR);
|
||||
}
|
||||
/*
|
||||
TODO: figure out why the following is done here in
|
||||
single_value_transformer but there is no corresponding action in
|
||||
row_value_transformer?
|
||||
*/
|
||||
item->name= (char *)in_additional_cond;
|
||||
|
||||
/*
|
||||
AND can't be changed during fix_fields()
|
||||
we can assign select_lex->having here, and pass 0 as last
|
||||
@@ -1116,10 +1126,16 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
||||
select_lex->ref_pointer_array,
|
||||
(char *)"<no matter>",
|
||||
(char *)"<result>"));
|
||||
new_having= new Item_func_trig_cond(new_having, &enable_pushed_conds);
|
||||
if (!abort_on_null && left_expr->maybe_null)
|
||||
{
|
||||
if (!(new_having= new Item_func_trig_cond(new_having,
|
||||
get_cond_guard(0))))
|
||||
DBUG_RETURN(RES_ERROR);
|
||||
}
|
||||
new_having->name= (char*)in_having_cond;
|
||||
select_lex->having= join->having= new_having;
|
||||
|
||||
select_lex->having_fix_field= 1;
|
||||
|
||||
/*
|
||||
we do not check join->having->fixed, because comparison function
|
||||
(from func->create) can't be fixed after creation
|
||||
@@ -1189,6 +1205,15 @@ Item_in_subselect::row_value_transformer(JOIN *join)
|
||||
|
||||
thd->lex->current_select= current;
|
||||
unit->uncacheable|= UNCACHEABLE_DEPENDENT;
|
||||
|
||||
if (!abort_on_null && left_expr->maybe_null && !pushed_cond_guards)
|
||||
{
|
||||
if (!(pushed_cond_guards= (bool*)join->thd->alloc(sizeof(bool) *
|
||||
left_expr->cols())))
|
||||
DBUG_RETURN(RES_ERROR);
|
||||
for (uint i= 0; i < cols_num; i++)
|
||||
pushed_cond_guards[i]= TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
select_lex->uncacheable|= UNCACHEABLE_DEPENDENT;
|
||||
@@ -1205,6 +1230,7 @@ Item_in_subselect::row_value_transformer(JOIN *join)
|
||||
is_not_null_test(v3))
|
||||
where is_not_null_test used to register nulls in case if we have
|
||||
not found matching to return correct NULL value
|
||||
TODO: say here explicitly if the order of AND parts matters or not.
|
||||
*/
|
||||
Item *item_having_part2= 0;
|
||||
for (uint i= 0; i < cols_num; i++)
|
||||
@@ -1233,21 +1259,28 @@ Item_in_subselect::row_value_transformer(JOIN *join)
|
||||
(char *)"<no matter>",
|
||||
(char *)"<list ref>")
|
||||
);
|
||||
having_item=
|
||||
and_items(having_item,
|
||||
new Item_cond_or(item_eq, item_isnull));
|
||||
item_having_part2=
|
||||
and_items(item_having_part2,
|
||||
new
|
||||
Item_is_not_null_test(this,
|
||||
new
|
||||
Item_ref(&select_lex->context,
|
||||
select_lex->
|
||||
ref_pointer_array + i,
|
||||
(char *)"<no matter>",
|
||||
(char *)"<list ref>")
|
||||
)
|
||||
);
|
||||
Item *col_item= new Item_cond_or(item_eq, item_isnull);
|
||||
if (!abort_on_null && left_expr->el(i)->maybe_null)
|
||||
{
|
||||
if (!(col_item= new Item_func_trig_cond(col_item, get_cond_guard(i))))
|
||||
DBUG_RETURN(RES_ERROR);
|
||||
}
|
||||
having_item= and_items(having_item, col_item);
|
||||
|
||||
Item *item_nnull_test=
|
||||
new Item_is_not_null_test(this,
|
||||
new Item_ref(&select_lex->context,
|
||||
select_lex->
|
||||
ref_pointer_array + i,
|
||||
(char *)"<no matter>",
|
||||
(char *)"<list ref>"));
|
||||
if (!abort_on_null && left_expr->el(i)->maybe_null)
|
||||
{
|
||||
if (!(item_nnull_test=
|
||||
new Item_func_trig_cond(item_nnull_test, get_cond_guard(i))))
|
||||
DBUG_RETURN(RES_ERROR);
|
||||
}
|
||||
item_having_part2= and_items(item_having_part2, item_nnull_test);
|
||||
item_having_part2->top_level_item();
|
||||
}
|
||||
having_item= and_items(having_item, item_having_part2);
|
||||
@@ -1296,18 +1329,15 @@ Item_in_subselect::row_value_transformer(JOIN *join)
|
||||
);
|
||||
if (!abort_on_null)
|
||||
{
|
||||
having_item=
|
||||
and_items(having_item,
|
||||
new
|
||||
Item_is_not_null_test(this,
|
||||
new
|
||||
Item_ref(&select_lex->context,
|
||||
select_lex->
|
||||
ref_pointer_array + i,
|
||||
(char *)"<no matter>",
|
||||
(char *)"<list ref>")
|
||||
)
|
||||
);
|
||||
Item *having_col_item=
|
||||
new Item_is_not_null_test(this,
|
||||
new
|
||||
Item_ref(&select_lex->context,
|
||||
select_lex->ref_pointer_array + i,
|
||||
(char *)"<no matter>",
|
||||
(char *)"<list ref>"));
|
||||
|
||||
|
||||
item_isnull= new
|
||||
Item_func_isnull(new
|
||||
Item_direct_ref(&select_lex->context,
|
||||
@@ -1316,14 +1346,23 @@ Item_in_subselect::row_value_transformer(JOIN *join)
|
||||
(char *)"<no matter>",
|
||||
(char *)"<list ref>")
|
||||
);
|
||||
|
||||
item= new Item_cond_or(item, item_isnull);
|
||||
/*
|
||||
TODO: why we create the above for cases where the right part
|
||||
cant be NULL?
|
||||
*/
|
||||
if (left_expr->el(i)->maybe_null)
|
||||
{
|
||||
if (!(item= new Item_func_trig_cond(item, get_cond_guard(i))))
|
||||
DBUG_RETURN(RES_ERROR);
|
||||
if (!(having_col_item=
|
||||
new Item_func_trig_cond(having_col_item, get_cond_guard(i))))
|
||||
DBUG_RETURN(RES_ERROR);
|
||||
}
|
||||
having_item= and_items(having_item, having_col_item);
|
||||
}
|
||||
|
||||
where_item= and_items(where_item, item);
|
||||
}
|
||||
if (where_item)
|
||||
where_item= new Item_func_trig_cond(where_item, &enable_pushed_conds);
|
||||
/*
|
||||
AND can't be changed during fix_fields()
|
||||
we can assign select_lex->where here, and pass 0 as last
|
||||
@@ -1337,9 +1376,9 @@ Item_in_subselect::row_value_transformer(JOIN *join)
|
||||
if (having_item)
|
||||
{
|
||||
bool res;
|
||||
having_item= new Item_func_trig_cond(having_item, &enable_pushed_conds);
|
||||
|
||||
select_lex->having= join->having= and_items(join->having, having_item);
|
||||
if (having_item == select_lex->having)
|
||||
having_item->name= (char*)in_having_cond;
|
||||
select_lex->having->top_level_item();
|
||||
/*
|
||||
AND can't be changed during fix_fields()
|
||||
@@ -1725,7 +1764,7 @@ int init_read_record_seq(JOIN_TAB *tab);
|
||||
int join_read_always_key_or_null(JOIN_TAB *tab);
|
||||
int join_read_next_same_or_null(READ_RECORD *info);
|
||||
|
||||
int subselect_single_select_engine::exec(bool full_scan)
|
||||
int subselect_single_select_engine::exec()
|
||||
{
|
||||
DBUG_ENTER("subselect_single_select_engine::exec");
|
||||
char const *save_where= thd->where;
|
||||
@@ -1763,9 +1802,13 @@ int subselect_single_select_engine::exec(bool full_scan)
|
||||
if (!executed)
|
||||
{
|
||||
item->reset_value_registration();
|
||||
if (full_scan)
|
||||
bool have_changed_access= FALSE;
|
||||
JOIN_TAB *changed_tabs[MAX_TABLES];
|
||||
JOIN_TAB **last_changed_tab= changed_tabs;
|
||||
if (item->have_guarded_conds())
|
||||
{
|
||||
/*
|
||||
For at least one of the pushed predicates the following is true:
|
||||
We should not apply optimizations based on the condition that was
|
||||
pushed down into the subquery. Those optimizations are ref[_or_null]
|
||||
acceses. Change them to be full table scans.
|
||||
@@ -1773,32 +1816,36 @@ int subselect_single_select_engine::exec(bool full_scan)
|
||||
for (uint i=join->const_tables ; i < join->tables ; i++)
|
||||
{
|
||||
JOIN_TAB *tab=join->join_tab+i;
|
||||
if (tab->keyuse && tab->keyuse->outer_ref)
|
||||
if (tab && tab->keyuse)
|
||||
{
|
||||
tab->read_first_record= init_read_record_seq;
|
||||
tab->read_record.record= tab->table->record[0];
|
||||
tab->read_record.thd= join->thd;
|
||||
tab->read_record.ref_length= tab->table->file->ref_length;
|
||||
for (uint i= 0; i < tab->ref.key_parts; i++)
|
||||
{
|
||||
bool *cond_guard= tab->ref.cond_guards[i];
|
||||
if (cond_guard && !*cond_guard)
|
||||
{
|
||||
/* Change the access method to full table scan */
|
||||
tab->read_first_record= init_read_record_seq;
|
||||
tab->read_record.record= tab->table->record[0];
|
||||
tab->read_record.thd= join->thd;
|
||||
tab->read_record.ref_length= tab->table->file->ref_length;
|
||||
*(last_changed_tab++)= tab;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
join->exec();
|
||||
|
||||
if (full_scan)
|
||||
/* Enable the optimizations back */
|
||||
for (JOIN_TAB **ptab= changed_tabs; ptab != last_changed_tab; ptab++)
|
||||
{
|
||||
/* Enable the optimizations back */
|
||||
for (uint i=join->const_tables ; i < join->tables ; i++)
|
||||
{
|
||||
JOIN_TAB *tab=join->join_tab+i;
|
||||
if (tab->keyuse && tab->keyuse->outer_ref)
|
||||
{
|
||||
tab->read_record.record= 0;
|
||||
tab->read_record.ref_length= 0;
|
||||
tab->read_first_record= join_read_always_key_or_null;
|
||||
tab->read_record.read_record= join_read_next_same_or_null;
|
||||
}
|
||||
}
|
||||
JOIN_TAB *tab= *ptab;
|
||||
tab->read_record.record= 0;
|
||||
tab->read_record.ref_length= 0;
|
||||
tab->read_first_record= join_read_always_key_or_null;
|
||||
tab->read_record.read_record= join_read_next_same_or_null;
|
||||
}
|
||||
executed= 1;
|
||||
thd->where= save_where;
|
||||
@@ -1810,13 +1857,9 @@ int subselect_single_select_engine::exec(bool full_scan)
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
int subselect_union_engine::exec(bool full_scan)
|
||||
int subselect_union_engine::exec()
|
||||
{
|
||||
char const *save_where= thd->where;
|
||||
/*
|
||||
Ignore the full_scan parameter: the pushed down predicates are only used
|
||||
for filtering, and the caller has disabled them if necessary.
|
||||
*/
|
||||
int res= unit->exec();
|
||||
thd->where= save_where;
|
||||
return res;
|
||||
@@ -1824,7 +1867,7 @@ int subselect_union_engine::exec(bool full_scan)
|
||||
|
||||
|
||||
/*
|
||||
Search for at least on row satisfying select condition
|
||||
Search for at least one row satisfying select condition
|
||||
|
||||
SYNOPSIS
|
||||
subselect_uniquesubquery_engine::scan_table()
|
||||
@@ -1833,8 +1876,8 @@ int subselect_union_engine::exec(bool full_scan)
|
||||
Scan the table using sequential access until we find at least one row
|
||||
satisfying select condition.
|
||||
|
||||
The result of this function (info about whether a row was found) is
|
||||
stored in this->empty_result_set.
|
||||
The caller must set this->empty_result_set=FALSE before calling this
|
||||
function. This function will set it to TRUE if it finds a matching row.
|
||||
|
||||
RETURN
|
||||
FALSE - OK
|
||||
@@ -1846,7 +1889,6 @@ int subselect_uniquesubquery_engine::scan_table()
|
||||
int error;
|
||||
TABLE *table= tab->table;
|
||||
DBUG_ENTER("subselect_uniquesubquery_engine::scan_table");
|
||||
empty_result_set= TRUE;
|
||||
|
||||
if (table->file->inited)
|
||||
table->file->ha_index_end();
|
||||
@@ -1939,10 +1981,13 @@ bool subselect_uniquesubquery_engine::copy_ref_key()
|
||||
- FALSE otherwise.
|
||||
|
||||
In some cases (IN subselect is a top level item, i.e. abort_on_null==TRUE)
|
||||
the caller doesn't distinguish between NULL and FALSE result and we just
|
||||
the caller doesn't distinguish between NULL and FALSE result and we just
|
||||
return FALSE.
|
||||
Otherwise we make a full table scan to see if there is at least one matching row.
|
||||
|
||||
Otherwise we make a full table scan to see if there is at least one
|
||||
matching row.
|
||||
|
||||
The result of this function (info about whether a row was found) is
|
||||
stored in this->empty_result_set.
|
||||
NOTE
|
||||
|
||||
RETURN
|
||||
@@ -1950,11 +1995,12 @@ bool subselect_uniquesubquery_engine::copy_ref_key()
|
||||
TRUE - an error occured while scanning
|
||||
*/
|
||||
|
||||
int subselect_uniquesubquery_engine::exec(bool full_scan)
|
||||
int subselect_uniquesubquery_engine::exec()
|
||||
{
|
||||
DBUG_ENTER("subselect_uniquesubquery_engine::exec");
|
||||
int error;
|
||||
TABLE *table= tab->table;
|
||||
empty_result_set= TRUE;
|
||||
|
||||
/* TODO: change to use of 'full_scan' here? */
|
||||
if (copy_ref_key())
|
||||
@@ -1975,9 +2021,13 @@ int subselect_uniquesubquery_engine::exec(bool full_scan)
|
||||
{
|
||||
error= 0;
|
||||
table->null_row= 0;
|
||||
((Item_in_subselect *) item)->value= (!table->status &&
|
||||
(!cond || cond->val_int()) ? 1 :
|
||||
0);
|
||||
if (!table->status && (!cond || cond->val_int()))
|
||||
{
|
||||
((Item_in_subselect *) item)->value= 1;
|
||||
empty_result_set= FALSE;
|
||||
}
|
||||
else
|
||||
((Item_in_subselect *) item)->value= 0;
|
||||
}
|
||||
|
||||
DBUG_RETURN(error != 0);
|
||||
@@ -2043,7 +2093,7 @@ subselect_uniquesubquery_engine::~subselect_uniquesubquery_engine()
|
||||
1
|
||||
*/
|
||||
|
||||
int subselect_indexsubquery_engine::exec(bool full_scan)
|
||||
int subselect_indexsubquery_engine::exec()
|
||||
{
|
||||
DBUG_ENTER("subselect_indexsubquery_engine::exec");
|
||||
int error;
|
||||
@@ -2084,8 +2134,9 @@ int subselect_indexsubquery_engine::exec(bool full_scan)
|
||||
table->null_row= 0;
|
||||
if (!table->status)
|
||||
{
|
||||
if (!cond || cond->val_int())
|
||||
if ((!cond || cond->val_int()) && (!having || having->val_int()))
|
||||
{
|
||||
empty_result_set= FALSE;
|
||||
if (null_finding)
|
||||
((Item_in_subselect *) item)->was_null= 1;
|
||||
else
|
||||
@@ -2228,11 +2279,16 @@ void subselect_indexsubquery_engine::print(String *str)
|
||||
str->append(key_info->name);
|
||||
if (check_null)
|
||||
str->append(STRING_WITH_LEN(" checking NULL"));
|
||||
if (cond)
|
||||
if (cond)
|
||||
{
|
||||
str->append(STRING_WITH_LEN(" where "));
|
||||
cond->print(str);
|
||||
}
|
||||
if (having)
|
||||
{
|
||||
str->append(STRING_WITH_LEN(" having "));
|
||||
having->print(str);
|
||||
}
|
||||
str->append(')');
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user