summaryrefslogtreecommitdiff
path: root/sql/item_subselect.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/item_subselect.cc')
-rw-r--r--sql/item_subselect.cc225
1 files changed, 120 insertions, 105 deletions
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index c615bcf7e0f..6d86d7d4b2d 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -63,12 +63,21 @@ void Item_subselect::init(st_select_lex *select_lex,
=> we do not copy old_engine here
*/
engine= unit->item->engine;
+ parsing_place= unit->item->parsing_place;
unit->item->engine= 0;
unit->item= this;
engine->change_item(this, result);
}
else
{
+ SELECT_LEX *outer_select= unit->outer_select();
+ /*
+ do not take into account expression inside aggregate functions because
+ they can access original table fields
+ */
+ parsing_place= (outer_select->in_sum_expr ?
+ NO_MATTER :
+ outer_select->parsing_place);
if (select_lex->next_select())
engine= new subselect_union_engine(unit, result, this);
else
@@ -76,7 +85,7 @@ void Item_subselect::init(st_select_lex *select_lex,
}
{
SELECT_LEX *upper= unit->outer_select();
- if (upper->parsing_place == SELECT_LEX_NODE::IN_HAVING)
+ if (upper->parsing_place == IN_HAVING)
upper->subquery_in_having= 1;
}
DBUG_VOID_RETURN;
@@ -123,13 +132,13 @@ Item_subselect::select_transformer(JOIN *join)
bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref)
{
+ char const *save_where= thd_param->where;
+ int res;
+
DBUG_ASSERT(fixed == 0);
engine->set_thd((thd= thd_param));
arena= thd->current_arena;
- char const *save_where= thd->where;
- int res;
-
if (check_stack_overrun(thd, (gptr)&res))
return 1;
@@ -306,7 +315,12 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
return RES_OK;
SELECT_LEX *select_lex= join->select_lex;
- Statement backup;
+
+ /* Juggle with current arena only if we're in prepared statement prepare */
+ Item_arena *arena= join->thd->current_arena;
+ Item_arena backup;
+ if (!arena->is_stmt_prepare())
+ arena= 0; // For easier test
if (!select_lex->master_unit()->first_select()->next_select() &&
!select_lex->table_list.elements &&
@@ -632,6 +646,7 @@ Item_subselect::trans_res
Item_in_subselect::single_value_transformer(JOIN *join,
Comp_creator *func)
{
+ Item_subselect::trans_res result= RES_ERROR;
DBUG_ENTER("Item_in_subselect::single_value_transformer");
if (changed)
@@ -640,10 +655,13 @@ Item_in_subselect::single_value_transformer(JOIN *join,
}
SELECT_LEX *select_lex= join->select_lex;
- Statement backup;
+ Item_arena *arena= join->thd->current_arena, backup;
thd->where= "scalar IN/ALL/ANY subquery";
- if (arena)
+
+ if (!arena->is_stmt_prepare())
+ arena= 0; // For easier test
+ else
thd->set_n_backup_item_arena(arena, &backup);
if (select_lex->item_list.elements > 1)
@@ -751,18 +769,17 @@ Item_in_subselect::single_value_transformer(JOIN *join,
}
select_lex->uncacheable|= UNCACHEABLE_DEPENDENT;
- Item *item;
-
- item= (Item*) select_lex->item_list.head();
if (join->having || select_lex->with_sum_func ||
select_lex->group_list.elements)
{
- item= func->create(expr,
- new Item_ref_null_helper(this,
- select_lex->ref_pointer_array,
- (char *)"<ref>",
- this->full_name()));
+ bool tmp;
+ Item *item= func->create(expr,
+ new Item_ref_null_helper(this,
+ select_lex->
+ ref_pointer_array,
+ (char *)"<ref>",
+ this->full_name()));
/*
AND and comparison functions can't be changed during fix_fields()
we can assign select_lex->having here, and pass 0 as last
@@ -770,21 +787,22 @@ Item_in_subselect::single_value_transformer(JOIN *join,
*/
select_lex->having= join->having= and_items(join->having, item);
select_lex->having_fix_field= 1;
- if (join->having->fix_fields(thd, join->tables_list, 0))
- {
- select_lex->having_fix_field= 0;
- goto err;
- }
+ tmp= join->having->fix_fields(thd, join->tables_list, 0);
select_lex->having_fix_field= 0;
+ if (tmp)
+ goto err;
}
else
{
+ Item *item= (Item*) select_lex->item_list.head();
+
select_lex->item_list.empty();
select_lex->item_list.push_back(new Item_int("Not_used",
(longlong) 1, 21));
select_lex->ref_pointer_array[0]= select_lex->item_list.head();
if (select_lex->table_list.elements)
{
+ bool tmp;
Item *having= item, *orig_item= item;
item= func->create(expr, item);
if (!abort_on_null && orig_item->maybe_null)
@@ -800,12 +818,10 @@ Item_in_subselect::single_value_transformer(JOIN *join,
new Item_cond_and(having, join->having) :
having);
select_lex->having_fix_field= 1;
- if (join->having->fix_fields(thd, join->tables_list, 0))
- {
- select_lex->having_fix_field= 0;
+ tmp= join->having->fix_fields(thd, join->tables_list, 0);
+ select_lex->having_fix_field= 0;
+ if (tmp)
goto err;
- }
- select_lex->having_fix_field= 0;
item= new Item_cond_or(item,
new Item_func_isnull(orig_item));
}
@@ -821,6 +837,7 @@ Item_in_subselect::single_value_transformer(JOIN *join,
}
else
{
+ bool tmp;
if (select_lex->master_unit()->first_select()->next_select())
{
/*
@@ -835,13 +852,10 @@ Item_in_subselect::single_value_transformer(JOIN *join,
(char *)"<no matter>",
(char *)"<result>"));
select_lex->having_fix_field= 1;
- if (join->having->fix_fields(thd, join->tables_list,
- 0))
- {
- select_lex->having_fix_field= 0;
+ tmp= join->having->fix_fields(thd, join->tables_list, 0);
+ select_lex->having_fix_field= 0;
+ if (tmp)
goto err;
- }
- select_lex->having_fix_field= 0;
}
else
{
@@ -857,42 +871,40 @@ Item_in_subselect::single_value_transformer(JOIN *join,
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_SELECT_REDUCED, warn_buff);
}
- if (arena)
- thd->restore_backup_item_arena(arena, &backup);
- DBUG_RETURN(RES_REDUCE);
+ result= RES_REDUCE;
+ goto end;
}
}
}
ok:
- if (arena)
- thd->restore_backup_item_arena(arena, &backup);
- DBUG_RETURN(RES_OK);
+ result= RES_OK;
err:
if (arena)
thd->restore_backup_item_arena(arena, &backup);
- DBUG_RETURN(RES_ERROR);
+ DBUG_RETURN(result);
}
Item_subselect::trans_res
Item_in_subselect::row_value_transformer(JOIN *join)
{
+ Item *item= 0;
+ SELECT_LEX *select_lex= join->select_lex;
DBUG_ENTER("Item_in_subselect::row_value_transformer");
if (changed)
{
DBUG_RETURN(RES_OK);
}
- Statement backup;
- Item *item= 0;
-
thd->where= "row IN/ALL/ANY subquery";
- if (arena)
- thd->set_n_backup_item_arena(arena, &backup);
- SELECT_LEX *select_lex= join->select_lex;
+ Item_arena *arena= join->thd->current_arena, backup;
+ if (!arena->is_stmt_prepare())
+ arena= 0;
+ else
+ thd->set_n_backup_item_arena(arena, &backup);
if (select_lex->item_list.elements != left_expr->cols())
{
@@ -1237,29 +1249,31 @@ int subselect_uniquesubquery_engine::exec()
DBUG_ENTER("subselect_uniquesubquery_engine::exec");
int error;
TABLE *table= tab->table;
- if ((tab->ref.key_err= (*tab->ref.key_copy)->copy()))
+ for (store_key **copy=tab->ref.key_copy ; *copy ; copy++)
{
- table->status= STATUS_NOT_FOUND;
- error= -1;
+ if (tab->ref.key_err= (*copy)->copy())
+ {
+ table->status= STATUS_NOT_FOUND;
+ DBUG_RETURN(1);
+ }
}
+
+ if (!table->file->inited)
+ table->file->ha_index_init(tab->ref.key);
+ error= table->file->index_read(table->record[0],
+ tab->ref.key_buff,
+ tab->ref.key_length,HA_READ_KEY_EXACT);
+ if (error && error != HA_ERR_KEY_NOT_FOUND)
+ error= report_error(table, error);
else
{
- if (!table->file->inited)
- table->file->ha_index_init(tab->ref.key);
- error= table->file->index_read(table->record[0],
- tab->ref.key_buff,
- tab->ref.key_length,HA_READ_KEY_EXACT);
- if (error && error != HA_ERR_KEY_NOT_FOUND)
- error= report_error(table, error);
- else
- {
- error= 0;
- table->null_row= 0;
- ((Item_in_subselect *) item)->value= (!table->status &&
- (!cond || cond->val_int()) ? 1 :
- 0);
- }
+ error= 0;
+ table->null_row= 0;
+ ((Item_in_subselect *) item)->value= (!table->status &&
+ (!cond || cond->val_int()) ? 1 :
+ 0);
}
+
DBUG_RETURN(error != 0);
}
@@ -1287,55 +1301,56 @@ int subselect_indexsubquery_engine::exec()
((Item_in_subselect *) item)->was_null= 0;
}
- if ((*tab->ref.key_copy) && (tab->ref.key_err= (*tab->ref.key_copy)->copy()))
+ for (store_key **copy=tab->ref.key_copy ; *copy ; copy++)
{
- table->status= STATUS_NOT_FOUND;
- error= -1;
+ if (tab->ref.key_err= (*copy)->copy())
+ {
+ table->status= STATUS_NOT_FOUND;
+ DBUG_RETURN(1);
+ }
}
+
+ if (!table->file->inited)
+ table->file->ha_index_init(tab->ref.key);
+ error= table->file->index_read(table->record[0],
+ tab->ref.key_buff,
+ tab->ref.key_length,HA_READ_KEY_EXACT);
+ if (error && error != HA_ERR_KEY_NOT_FOUND)
+ error= report_error(table, error);
else
{
- if (!table->file->inited)
- table->file->ha_index_init(tab->ref.key);
- error= table->file->index_read(table->record[0],
- tab->ref.key_buff,
- tab->ref.key_length,HA_READ_KEY_EXACT);
- if (error && error != HA_ERR_KEY_NOT_FOUND)
- error= report_error(table, error);
- else
+ for (;;)
{
- for (;;)
+ error= 0;
+ table->null_row= 0;
+ if (!table->status)
{
- error= 0;
- table->null_row= 0;
- if (!table->status)
- {
- if (!cond || cond->val_int())
- {
- if (null_finding)
- ((Item_in_subselect *) item)->was_null= 1;
- else
- ((Item_in_subselect *) item)->value= 1;
- break;
- }
- error= table->file->index_next_same(table->record[0],
- tab->ref.key_buff,
- tab->ref.key_length);
- if (error && error != HA_ERR_END_OF_FILE)
- {
- error= report_error(table, error);
- break;
- }
- }
- else
- {
- if (!check_null || null_finding)
- break; /* We don't need to check nulls */
- *tab->ref.null_ref_key= 1;
- null_finding= 1;
- /* Check if there exists a row with a null value in the index */
- if ((error= (safe_index_read(tab) == 1)))
- break;
- }
+ if (!cond || cond->val_int())
+ {
+ if (null_finding)
+ ((Item_in_subselect *) item)->was_null= 1;
+ else
+ ((Item_in_subselect *) item)->value= 1;
+ break;
+ }
+ error= table->file->index_next_same(table->record[0],
+ tab->ref.key_buff,
+ tab->ref.key_length);
+ if (error && error != HA_ERR_END_OF_FILE)
+ {
+ error= report_error(table, error);
+ break;
+ }
+ }
+ else
+ {
+ if (!check_null || null_finding)
+ break; /* We don't need to check nulls */
+ *tab->ref.null_ref_key= 1;
+ null_finding= 1;
+ /* Check if there exists a row with a null value in the index */
+ if ((error= (safe_index_read(tab) == 1)))
+ break;
}
}
}