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.cc509
1 files changed, 329 insertions, 180 deletions
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 1ab81d1862d..78dae0aaa1e 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -39,6 +39,7 @@ Item_subselect::Item_subselect():
engine(0), old_engine(0), used_tables_cache(0), have_to_be_excluded(0),
const_item_cache(1), engine_changed(0), changed(0)
{
+ with_subselect= 1;
reset();
/*
item value is NULL if select_subselect not changed this value
@@ -53,7 +54,7 @@ void Item_subselect::init(st_select_lex *select_lex,
{
DBUG_ENTER("Item_subselect::init");
- DBUG_PRINT("subs", ("select_lex 0x%xl", (ulong) select_lex));
+ DBUG_PRINT("enter", ("select_lex: 0x%x", (ulong) select_lex));
unit= select_lex->master_unit();
if (unit->item)
@@ -66,7 +67,7 @@ void Item_subselect::init(st_select_lex *select_lex,
parsing_place= unit->item->parsing_place;
unit->item->engine= 0;
unit->item= this;
- engine->change_item(this, result);
+ engine->change_result(this, result);
}
else
{
@@ -130,20 +131,20 @@ Item_subselect::select_transformer(JOIN *join)
}
-bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref)
+bool Item_subselect::fix_fields(THD *thd_param, Item **ref)
{
+ char const *save_where= thd_param->where;
+ bool res;
+
DBUG_ASSERT(fixed == 0);
engine->set_thd((thd= thd_param));
- char const *save_where= thd->where;
- int res;
-
- if (check_stack_overrun(thd, (gptr)&res))
- return 1;
+ if (check_stack_overrun(thd, STACK_MIN_SIZE, (gptr)&res))
+ return TRUE;
res= engine->prepare();
- // all transformetion is done (used by prepared statements)
+ // all transformation is done (used by prepared statements)
changed= 1;
if (!res)
@@ -165,7 +166,7 @@ bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref)
substitution= 0;
thd->where= "checking transformed subquery";
if (!(*ref)->fixed)
- ret= (*ref)->fix_fields(thd, tables, ref);
+ ret= (*ref)->fix_fields(thd, ref);
thd->where= save_where;
return ret;
}
@@ -173,7 +174,7 @@ bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref)
if (engine->cols() > max_columns)
{
my_error(ER_OPERAND_COLUMNS, MYF(0), 1);
- return 1;
+ return TRUE;
}
fix_length_and_dec();
}
@@ -194,15 +195,8 @@ bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref)
bool Item_subselect::exec()
{
int res;
- MEM_ROOT *old_root= thd->mem_root;
- /*
- As this is execution, all objects should be allocated through the main
- mem root
- */
- thd->mem_root= &thd->main_mem_root;
res= engine->exec();
- thd->mem_root= old_root;
if (engine_changed)
{
@@ -246,7 +240,7 @@ void Item_subselect::update_used_tables()
{
if (!engine->uncacheable())
{
- // did all used tables become ststic?
+ // did all used tables become static?
if (!(used_tables_cache & ~engine->upper_select_const_tables()))
const_item_cache= 1;
}
@@ -271,7 +265,8 @@ Item_singlerow_subselect::Item_singlerow_subselect(st_select_lex *select_lex)
DBUG_VOID_RETURN;
}
-Item_maxmin_subselect::Item_maxmin_subselect(Item_subselect *parent,
+Item_maxmin_subselect::Item_maxmin_subselect(THD *thd_param,
+ Item_subselect *parent,
st_select_lex *select_lex,
bool max_arg)
:Item_singlerow_subselect(), was_values(TRUE)
@@ -290,6 +285,12 @@ Item_maxmin_subselect::Item_maxmin_subselect(Item_subselect *parent,
used_tables_cache= parent->get_used_tables_cache();
const_item_cache= parent->get_const_item_cache();
+ /*
+ this subquery always creates during preparation, so we can assign
+ thd here
+ */
+ thd= thd_param;
+
DBUG_VOID_RETURN;
}
@@ -333,10 +334,8 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
return RES_OK;
SELECT_LEX *select_lex= join->select_lex;
-
- /* Juggle with current arena only if we're in prepared statement prepare */
- Item_arena *arena= join->thd->current_arena;
-
+ Query_arena *arena= thd->stmt_arena;
+
if (!select_lex->master_unit()->first_select()->next_select() &&
!select_lex->table_list.elements &&
select_lex->item_list.elements == 1 &&
@@ -351,20 +350,20 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
!(select_lex->item_list.head()->type() == FIELD_ITEM ||
select_lex->item_list.head()->type() == REF_ITEM) &&
/*
- switch off this optimisation for prepare statement,
+ switch off this optimization for prepare statement,
because we do not rollback this changes
TODO: make rollback for it, or special name resolving mode in 5.0.
*/
- !arena->is_stmt_prepare()
+ !arena->is_stmt_prepare_or_first_sp_execute()
)
{
have_to_be_excluded= 1;
- if (join->thd->lex->describe)
+ if (thd->lex->describe)
{
char warn_buff[MYSQL_ERRMSG_SIZE];
sprintf(warn_buff, ER(ER_SELECT_REDUCED), select_lex->select_number);
- push_warning(join->thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_SELECT_REDUCED, warn_buff);
}
substitution= select_lex->item_list.head();
@@ -381,6 +380,7 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
return RES_OK;
}
+
void Item_singlerow_subselect::store(uint i, Item *item)
{
row[i]->store(item);
@@ -404,6 +404,7 @@ void Item_singlerow_subselect::fix_length_and_dec()
engine->fix_length_and_dec(row);
value= *row;
}
+ unsigned_flag= value->unsigned_flag;
/*
If there are not tables in subquery then ability to have NULL value
depends on SELECT list (if single row subquery have tables then it
@@ -443,13 +444,13 @@ void Item_singlerow_subselect::bring_value()
exec();
}
-double Item_singlerow_subselect::val()
+double Item_singlerow_subselect::val_real()
{
DBUG_ASSERT(fixed == 1);
if (!exec() && !value->null_value)
{
null_value= 0;
- return value->val();
+ return value->val_real();
}
else
{
@@ -473,7 +474,7 @@ longlong Item_singlerow_subselect::val_int()
}
}
-String *Item_singlerow_subselect::val_str (String *str)
+String *Item_singlerow_subselect::val_str(String *str)
{
if (!exec() && !value->null_value)
{
@@ -488,24 +489,53 @@ String *Item_singlerow_subselect::val_str (String *str)
}
+my_decimal *Item_singlerow_subselect::val_decimal(my_decimal *decimal_value)
+{
+ if (!exec() && !value->null_value)
+ {
+ null_value= 0;
+ return value->val_decimal(decimal_value);
+ }
+ else
+ {
+ reset();
+ return 0;
+ }
+}
+
+
+bool Item_singlerow_subselect::val_bool()
+{
+ if (!exec() && !value->null_value)
+ {
+ null_value= 0;
+ return value->val_bool();
+ }
+ else
+ {
+ reset();
+ return 0;
+ }
+}
+
+
Item_exists_subselect::Item_exists_subselect(st_select_lex *select_lex):
Item_subselect()
{
DBUG_ENTER("Item_exists_subselect::Item_exists_subselect");
+ bool val_bool();
init(select_lex, new select_exists_subselect(this));
max_columns= UINT_MAX;
null_value= 0; //can't be NULL
maybe_null= 0; //can't be NULL
value= 0;
- // We need only 1 row to determinate existence
- select_lex->master_unit()->global_parameters->select_limit= 1;
DBUG_VOID_RETURN;
}
void Item_exists_subselect::print(String *str)
{
- str->append("exists", 6);
+ str->append(STRING_WITH_LEN("exists"));
Item_subselect::print(str);
}
@@ -565,9 +595,11 @@ void Item_exists_subselect::fix_length_and_dec()
decimals= 0;
max_length= 1;
max_columns= engine->cols();
+ /* We need only 1 row to determine existence */
+ unit->global_parameters->select_limit= new Item_int((int32) 1);
}
-double Item_exists_subselect::val()
+double Item_exists_subselect::val_real()
{
DBUG_ASSERT(fixed == 1);
if (exec())
@@ -597,12 +629,37 @@ String *Item_exists_subselect::val_str(String *str)
reset();
return 0;
}
- str->set(value,&my_charset_bin);
+ str->set((ulonglong)value,&my_charset_bin);
return str;
}
-double Item_in_subselect::val()
+my_decimal *Item_exists_subselect::val_decimal(my_decimal *decimal_value)
+{
+ DBUG_ASSERT(fixed == 1);
+ if (exec())
+ {
+ reset();
+ return 0;
+ }
+ int2my_decimal(E_DEC_FATAL_ERROR, value, 0, decimal_value);
+ return decimal_value;
+}
+
+
+bool Item_exists_subselect::val_bool()
+{
+ DBUG_ASSERT(fixed == 1);
+ if (exec())
+ {
+ reset();
+ return 0;
+ }
+ return value != 0;
+}
+
+
+double Item_in_subselect::val_real()
{
/*
As far as Item_in_subselect called only from Item_in_optimizer this
@@ -625,6 +682,11 @@ double Item_in_subselect::val()
longlong Item_in_subselect::val_int()
{
+ /*
+ As far as Item_in_subselect called only from Item_in_optimizer this
+ method should not be used
+ */
+ DBUG_ASSERT(0);
DBUG_ASSERT(fixed == 1);
null_value= 0;
if (exec())
@@ -659,20 +721,55 @@ String *Item_in_subselect::val_str(String *str)
null_value= 1;
return 0;
}
- str->set(value, &my_charset_bin);
+ str->set((ulonglong)value, &my_charset_bin);
return str;
}
+bool Item_in_subselect::val_bool()
+{
+ DBUG_ASSERT(fixed == 1);
+ if (exec())
+ {
+ reset();
+ null_value= 1;
+ return 0;
+ }
+ if (was_null && !value)
+ null_value= 1;
+ return value;
+}
+
+my_decimal *Item_in_subselect::val_decimal(my_decimal *decimal_value)
+{
+ /*
+ As far as Item_in_subselect called only from Item_in_optimizer this
+ method should not be used
+ */
+ DBUG_ASSERT(0);
+ DBUG_ASSERT(fixed == 1);
+ if (exec())
+ {
+ reset();
+ null_value= 1;
+ return 0;
+ }
+ if (was_null && !value)
+ null_value= 1;
+ int2my_decimal(E_DEC_FATAL_ERROR, value, 0, decimal_value);
+ return decimal_value;
+}
+
+
/* Rewrite a single-column IN/ALL/ANY subselect. */
Item_subselect::trans_res
Item_in_subselect::single_value_transformer(JOIN *join,
Comp_creator *func)
{
- DBUG_ENTER("Item_in_subselect::single_value_transformer");
-
+ Item_subselect::trans_res result= RES_ERROR;
SELECT_LEX *select_lex= join->select_lex;
+ DBUG_ENTER("Item_in_subselect::single_value_transformer");
/*
Check that the right part of the subselect contains no more than one
@@ -712,6 +809,7 @@ Item_in_subselect::single_value_transformer(JOIN *join,
select_lex->table_list.elements)
{
Item_sum_hybrid *item;
+ nesting_map save_allow_sum_func;
if (func->l_op())
{
/*
@@ -737,12 +835,16 @@ Item_in_subselect::single_value_transformer(JOIN *join,
it.replace(item);
}
+ save_allow_sum_func= thd->lex->allow_sum_func;
+ thd->lex->allow_sum_func|= 1 << thd->lex->current_select->nest_level;
/*
Item_sum_(max|min) can't substitute other item => we can use 0 as
- reference
+ reference, also Item_sum_(max|min) can't be fixed after creation, so
+ we do not check item->fixed
*/
- if (item->fix_fields(thd, join->tables_list, 0))
+ if (item->fix_fields(thd, 0))
DBUG_RETURN(RES_ERROR);
+ thd->lex->allow_sum_func= save_allow_sum_func;
/* we added aggregate function => we have to change statistic */
count_field_types(&join->tmp_table_param, join->all_fields, 0);
@@ -751,10 +853,7 @@ Item_in_subselect::single_value_transformer(JOIN *join,
else
{
Item_maxmin_subselect *item;
- // remove LIMIT placed by ALL/ANY subquery
- select_lex->master_unit()->global_parameters->select_limit=
- HA_POS_ERROR;
- subs= item= new Item_maxmin_subselect(this, select_lex, func->l_op());
+ subs= item= new Item_maxmin_subselect(thd, this, select_lex, func->l_op());
if (upper_item)
upper_item->set_sub_test(item);
}
@@ -773,7 +872,7 @@ Item_in_subselect::single_value_transformer(JOIN *join,
thd->lex->current_select= up= current->return_after_parsing();
//optimizer never use Item **ref => we can pass 0 as parameter
- if (!optimizer || optimizer->fix_left(thd, up->get_table_list(), 0))
+ if (!optimizer || optimizer->fix_left(thd, 0))
{
thd->lex->current_select= current;
DBUG_RETURN(RES_ERROR);
@@ -781,10 +880,11 @@ Item_in_subselect::single_value_transformer(JOIN *join,
thd->lex->current_select= current;
/*
- As far as Item_ref_in_optimizer do not substitude itself on fix_fields
+ As far as Item_ref_in_optimizer do not substitute itself on fix_fields
we can use same item for all selects.
*/
- expr= new Item_direct_ref((Item**)optimizer->get_cache(),
+ expr= new Item_direct_ref(&select_lex->context,
+ (Item**)optimizer->get_cache(),
(char *)"<no matter>",
(char *)in_left_expr_name);
@@ -792,9 +892,6 @@ Item_in_subselect::single_value_transformer(JOIN *join,
}
select_lex->uncacheable|= UNCACHEABLE_DEPENDENT;
- Item *item;
-
- item= (Item*) select_lex->item_list.head();
/*
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) =>
@@ -805,11 +902,18 @@ Item_in_subselect::single_value_transformer(JOIN *join,
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(&select_lex->context,
+ this,
+ select_lex->
+ ref_pointer_array,
+ (char *)"<ref>",
+ this->full_name()));
+#ifdef CORRECT_BUT_TOO_SLOW_TO_BE_USABLE
+ if (!abort_on_null && left_expr->maybe_null)
+ item= new Item_cond_or(new Item_func_isnull(left_expr), item);
+#endif
/*
AND and comparison functions can't be changed during fix_fields()
we can assign select_lex->having here, and pass 0 as last
@@ -817,17 +921,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;
- DBUG_RETURN(RES_ERROR);
- }
+ /*
+ we do not check join->having->fixed, because Item_and (from and_items)
+ or comparison function (from func->create) can't be fixed after creation
+ */
+ tmp= join->having->fix_fields(thd, 0);
select_lex->having_fix_field= 0;
+ if (tmp)
+ DBUG_RETURN(RES_ERROR);
}
else
{
+ Item *item= (Item*) select_lex->item_list.head();
+
if (select_lex->table_list.elements)
{
+ bool tmp;
Item *having= item, *orig_item= item;
select_lex->item_list.empty();
select_lex->item_list.push_back(new Item_int("Not_used",
@@ -847,14 +956,21 @@ 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;
+ /*
+ we do not check join->having->fixed, because Item_and (from
+ and_items) or comparison function (from func->create) can't be
+ fixed after creation
+ */
+ tmp= join->having->fix_fields(thd, 0);
+ select_lex->having_fix_field= 0;
+ if (tmp)
DBUG_RETURN(RES_ERROR);
- }
- select_lex->having_fix_field= 0;
item= new Item_cond_or(item,
new Item_func_isnull(orig_item));
+#ifdef CORRECT_BUT_TOO_SLOW_TO_BE_USABLE
+ if (left_expr->maybe_null)
+ item= new Item_cond_or(new Item_func_isnull(left_expr), item);
+#endif
}
item->name= (char *)in_additional_cond;
/*
@@ -864,11 +980,16 @@ Item_in_subselect::single_value_transformer(JOIN *join,
*/
select_lex->where= join->conds= and_items(join->conds, item);
select_lex->where->top_level_item();
- if (join->conds->fix_fields(thd, join->tables_list, 0))
+ /*
+ we do not check join->conds->fixed, because Item_and can't be fixed
+ after creation
+ */
+ if (join->conds->fix_fields(thd, 0))
DBUG_RETURN(RES_ERROR);
}
else
{
+ bool tmp;
if (select_lex->master_unit()->first_select()->next_select())
{
/*
@@ -879,25 +1000,26 @@ Item_in_subselect::single_value_transformer(JOIN *join,
select_lex->having=
join->having=
func->create(expr,
- new Item_ref_null_helper(this,
+ new Item_ref_null_helper(&select_lex->context, this,
select_lex->ref_pointer_array,
(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;
+ /*
+ we do not check join->having->fixed, because comparison function
+ (from func->create) can't be fixed after creation
+ */
+ tmp= join->having->fix_fields(thd, 0);
+ select_lex->having_fix_field= 0;
+ if (tmp)
DBUG_RETURN(RES_ERROR);
- }
- select_lex->having_fix_field= 0;
}
else
{
// it is single select without tables => possible optimization
item= func->create(left_expr, item);
- // fix_field of item will be done in time of substituting
+ // fix_field of item will be done in time of substituting
substitution= item;
have_to_be_excluded= 1;
if (thd->lex->describe)
@@ -942,13 +1064,13 @@ Item_in_subselect::row_value_transformer(JOIN *join)
SELECT_LEX *current= thd->lex->current_select, *up;
thd->lex->current_select= up= current->return_after_parsing();
//optimizer never use Item **ref => we can pass 0 as parameter
- if (!optimizer || optimizer->fix_left(thd, up->get_table_list(), 0))
+ if (!optimizer || optimizer->fix_left(thd, 0))
{
thd->lex->current_select= current;
DBUG_RETURN(RES_ERROR);
}
- // we will refer to apper level cache array => we have to save it in PS
+ // we will refer to upper level cache array => we have to save it in PS
optimizer->keep_top_level_cache();
thd->lex->current_select= current;
@@ -979,21 +1101,23 @@ Item_in_subselect::row_value_transformer(JOIN *join)
DBUG_RETURN(RES_ERROR);
Item *item_eq=
new Item_func_eq(new
- Item_ref((*optimizer->get_cache())->
- addr(i),
- (char *)"<no matter>",
- (char *)in_left_expr_name),
+ Item_ref(&select_lex->context,
+ (*optimizer->get_cache())->
+ addr(i),
+ (char *)"<no matter>",
+ (char *)in_left_expr_name),
new
- Item_ref(select_lex->ref_pointer_array + i,
- (char *)"<no matter>",
- (char *)"<list ref>")
+ Item_ref(&select_lex->context,
+ select_lex->ref_pointer_array + i,
+ (char *)"<no matter>",
+ (char *)"<list ref>")
);
Item *item_isnull=
new Item_func_isnull(new
- Item_ref( select_lex->
- ref_pointer_array+i,
- (char *)"<no matter>",
- (char *)"<list ref>")
+ Item_ref(&select_lex->context,
+ select_lex->ref_pointer_array+i,
+ (char *)"<no matter>",
+ (char *)"<list ref>")
);
having_item=
and_items(having_item,
@@ -1003,10 +1127,11 @@ Item_in_subselect::row_value_transformer(JOIN *join)
new
Item_is_not_null_test(this,
new
- Item_ref(select_lex->
- ref_pointer_array + i,
- (char *)"<no matter>",
- (char *)"<list ref>")
+ Item_ref(&select_lex->context,
+ select_lex->
+ ref_pointer_array + i,
+ (char *)"<no matter>",
+ (char *)"<list ref>")
)
);
item_having_part2->top_level_item();
@@ -1043,15 +1168,17 @@ Item_in_subselect::row_value_transformer(JOIN *join)
DBUG_RETURN(RES_ERROR);
item=
new Item_func_eq(new
- Item_direct_ref((*optimizer->get_cache())->
+ Item_direct_ref(&select_lex->context,
+ (*optimizer->get_cache())->
addr(i),
(char *)"<no matter>",
(char *)in_left_expr_name),
new
- Item_direct_ref( select_lex->
- ref_pointer_array+i,
- (char *)"<no matter>",
- (char *)"<list ref>")
+ Item_direct_ref(&select_lex->context,
+ select_lex->
+ ref_pointer_array+i,
+ (char *)"<no matter>",
+ (char *)"<list ref>")
);
if (!abort_on_null)
{
@@ -1060,18 +1187,20 @@ Item_in_subselect::row_value_transformer(JOIN *join)
new
Item_is_not_null_test(this,
new
- Item_ref(select_lex->
- ref_pointer_array + i,
- (char *)"<no matter>",
- (char *)"<list ref>")
+ 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->
- ref_pointer_array+i,
- (char *)"<no matter>",
- (char *)"<list ref>")
+ Item_direct_ref(&select_lex->context,
+ select_lex->
+ ref_pointer_array+i,
+ (char *)"<no matter>",
+ (char *)"<list ref>")
);
item= new Item_cond_or(item, item_isnull);
@@ -1086,7 +1215,7 @@ Item_in_subselect::row_value_transformer(JOIN *join)
*/
select_lex->where= join->conds= and_items(join->conds, where_item);
select_lex->where->top_level_item();
- if (join->conds->fix_fields(thd, join->tables_list, 0))
+ if (join->conds->fix_fields(thd, 0))
DBUG_RETURN(RES_ERROR);
}
if (having_item)
@@ -1100,13 +1229,14 @@ Item_in_subselect::row_value_transformer(JOIN *join)
argument (reference) to fix_fields()
*/
select_lex->having_fix_field= 1;
- res= join->having->fix_fields(thd, join->tables_list, 0);
+ res= join->having->fix_fields(thd, 0);
select_lex->having_fix_field= 0;
if (res)
{
DBUG_RETURN(RES_ERROR);
}
}
+
DBUG_RETURN(RES_OK);
}
@@ -1142,7 +1272,7 @@ Item_in_subselect::select_transformer(JOIN *join)
Item_subselect::trans_res
Item_in_subselect::select_in_like_transformer(JOIN *join, Comp_creator *func)
{
- Item_arena *arena, backup;
+ Query_arena *arena, backup;
SELECT_LEX *current= thd->lex->current_select, *up;
const char *save_where= thd->where;
Item_subselect::trans_res res= RES_ERROR;
@@ -1164,18 +1294,17 @@ Item_in_subselect::select_in_like_transformer(JOIN *join, Comp_creator *func)
*/
if (!optimizer)
{
- arena= thd->change_arena_if_needed(&backup);
+ arena= thd->activate_stmt_arena_if_needed(&backup);
result= (!(optimizer= new Item_in_optimizer(left_expr, this)));
if (arena)
- thd->restore_backup_item_arena(arena, &backup);
+ thd->restore_active_arena(arena, &backup);
if (result)
goto err;
}
thd->lex->current_select= up= current->return_after_parsing();
result= (!left_expr->fixed &&
- left_expr->fix_fields(thd, up->get_table_list(),
- optimizer->arguments()));
+ left_expr->fix_fields(thd, optimizer->arguments()));
/* fix_fields can change reference to left_expr, we need reassign it */
left_expr= optimizer->arguments()[0];
@@ -1184,7 +1313,7 @@ Item_in_subselect::select_in_like_transformer(JOIN *join, Comp_creator *func)
goto err;
transformed= 1;
- arena= thd->change_arena_if_needed(&backup);
+ arena= thd->activate_stmt_arena_if_needed(&backup);
/*
Both transformers call fix_fields() only for Items created inside them,
and all that items do not make permanent changes in current item arena
@@ -1200,14 +1329,14 @@ Item_in_subselect::select_in_like_transformer(JOIN *join, Comp_creator *func)
if (func != &eq_creator)
{
if (arena)
- thd->restore_backup_item_arena(arena, &backup);
+ thd->restore_active_arena(arena, &backup);
my_error(ER_OPERAND_COLUMNS, MYF(0), 1);
DBUG_RETURN(RES_ERROR);
}
res= row_value_transformer(join);
}
if (arena)
- thd->restore_backup_item_arena(arena, &backup);
+ thd->restore_active_arena(arena, &backup);
err:
thd->where= save_where;
DBUG_RETURN(res);
@@ -1217,16 +1346,27 @@ err:
void Item_in_subselect::print(String *str)
{
if (transformed)
- str->append("<exists>", 8);
+ str->append(STRING_WITH_LEN("<exists>"));
else
{
left_expr->print(str);
- str->append(" in ", 4);
+ str->append(STRING_WITH_LEN(" in "));
}
Item_subselect::print(str);
}
+bool Item_in_subselect::fix_fields(THD *thd, Item **ref)
+{
+ bool result = 0;
+
+ if(thd->lex->view_prepare_mode && left_expr && !left_expr->fixed)
+ result = left_expr->fix_fields(thd, &left_expr);
+
+ return result || Item_subselect::fix_fields(thd, ref);
+}
+
+
Item_subselect::trans_res
Item_allany_subselect::select_transformer(JOIN *join)
{
@@ -1240,7 +1380,7 @@ Item_allany_subselect::select_transformer(JOIN *join)
void Item_allany_subselect::print(String *str)
{
if (transformed)
- str->append("<exists>", 8);
+ str->append(STRING_WITH_LEN("<exists>"));
else
{
left_expr->print(str);
@@ -1252,24 +1392,23 @@ void Item_allany_subselect::print(String *str)
}
+void subselect_engine::set_thd(THD *thd_arg)
+{
+ thd= thd_arg;
+ if (result)
+ result->set_thd(thd_arg);
+}
+
+
subselect_single_select_engine::
subselect_single_select_engine(st_select_lex *select,
select_subselect *result,
Item_subselect *item)
:subselect_engine(item, result),
- prepared(0), optimized(0), executed(0), join(0)
+ prepared(0), optimized(0), executed(0),
+ select_lex(select), join(0)
{
- select_lex= select;
- SELECT_LEX_UNIT *unit= select_lex->master_unit();
- unit->offset_limit_cnt= unit->global_parameters->offset_limit;
- unit->select_limit_cnt= unit->global_parameters->select_limit+
- unit->global_parameters ->offset_limit;
- if (unit->select_limit_cnt < unit->global_parameters->select_limit)
- unit->select_limit_cnt= HA_POS_ERROR; // no limit
- if (unit->select_limit_cnt == HA_POS_ERROR)
- select_lex->options&= ~OPTION_FOUND_ROWS;
- unit->item= item;
- this->select_lex= select_lex;
+ select_lex->master_unit()->item= item;
}
@@ -1292,6 +1431,12 @@ void subselect_union_engine::cleanup()
}
+bool subselect_union_engine::is_executed() const
+{
+ return unit->executed;
+}
+
+
void subselect_uniquesubquery_engine::cleanup()
{
DBUG_ENTER("subselect_uniquesubquery_engine::cleanup");
@@ -1347,7 +1492,7 @@ int subselect_single_select_engine::prepare()
int subselect_union_engine::prepare()
{
- return unit->prepare(thd, result, SELECT_NO_UNLOCK, "");
+ return unit->prepare(thd, result, SELECT_NO_UNLOCK);
}
int subselect_uniquesubquery_engine::prepare()
@@ -1368,6 +1513,7 @@ static Item_result set_row(List<Item> &item_list, Item *item,
item->max_length= sel_item->max_length;
res_type= sel_item->result_type();
item->decimals= sel_item->decimals;
+ item->unsigned_flag= sel_item->unsigned_flag;
*maybe_null= sel_item->maybe_null;
if (!(row[i]= Item_cache::get_cache(res_type)))
return STRING_RESULT; // we should return something
@@ -1412,17 +1558,20 @@ void subselect_uniquesubquery_engine::fix_length_and_dec(Item_cache **row)
int subselect_single_select_engine::exec()
{
DBUG_ENTER("subselect_single_select_engine::exec");
- char const *save_where= join->thd->where;
- SELECT_LEX *save_select= join->thd->lex->current_select;
- join->thd->lex->current_select= select_lex;
+ char const *save_where= thd->where;
+ SELECT_LEX *save_select= thd->lex->current_select;
+ thd->lex->current_select= select_lex;
if (!optimized)
{
- optimized=1;
+ SELECT_LEX_UNIT *unit= select_lex->master_unit();
+
+ optimized= 1;
+ unit->set_limit(unit->global_parameters);
if (join->optimize())
{
- join->thd->where= save_where;
+ thd->where= save_where;
executed= 1;
- join->thd->lex->current_select= save_select;
+ thd->lex->current_select= save_select;
DBUG_RETURN(join->error ? join->error : 1);
}
if (item->engine_changed)
@@ -1434,8 +1583,8 @@ int subselect_single_select_engine::exec()
{
if (join->reinit())
{
- join->thd->where= save_where;
- join->thd->lex->current_select= save_select;
+ thd->where= save_where;
+ thd->lex->current_select= save_select;
DBUG_RETURN(1);
}
item->reset();
@@ -1446,20 +1595,20 @@ int subselect_single_select_engine::exec()
item->reset_value_registration();
join->exec();
executed= 1;
- join->thd->where= save_where;
- join->thd->lex->current_select= save_select;
+ thd->where= save_where;
+ thd->lex->current_select= save_select;
DBUG_RETURN(join->error||thd->is_fatal_error);
}
- join->thd->where= save_where;
- join->thd->lex->current_select= save_select;
+ thd->where= save_where;
+ thd->lex->current_select= save_select;
DBUG_RETURN(0);
}
int subselect_union_engine::exec()
{
- char const *save_where= unit->thd->where;
+ char const *save_where= thd->where;
int res= unit->exec();
- unit->thd->where= save_where;
+ thd->where= save_where;
return res;
}
@@ -1582,7 +1731,7 @@ int subselect_indexsubquery_engine::exec()
uint subselect_single_select_engine::cols()
{
- DBUG_ASSERT(select_lex->join); // should be called after fix_fields()
+ DBUG_ASSERT(select_lex->join != 0); // should be called after fix_fields()
return select_lex->join->fields_list.elements;
}
@@ -1627,7 +1776,7 @@ void subselect_uniquesubquery_engine::exclude()
table_map subselect_engine::calc_const_tables(TABLE_LIST *table)
{
table_map map= 0;
- for (; table; table= table->next)
+ for (; table; table= table->next_leaf)
{
TABLE *tbl= table->table;
if (tbl && tbl->const_table)
@@ -1640,14 +1789,13 @@ table_map subselect_engine::calc_const_tables(TABLE_LIST *table)
table_map subselect_single_select_engine::upper_select_const_tables()
{
return calc_const_tables((TABLE_LIST *) select_lex->outer_select()->
- table_list.first);
+ leaf_tables);
}
table_map subselect_union_engine::upper_select_const_tables()
{
- return calc_const_tables((TABLE_LIST *) unit->outer_select()->
- table_list.first);
+ return calc_const_tables((TABLE_LIST *) unit->outer_select()->leaf_tables);
}
@@ -1665,16 +1813,16 @@ void subselect_union_engine::print(String *str)
void subselect_uniquesubquery_engine::print(String *str)
{
- str->append("<primary_index_lookup>(", 23);
+ str->append(STRING_WITH_LEN("<primary_index_lookup>("));
tab->ref.items[0]->print(str);
- str->append(" in ", 4);
- str->append(tab->table->real_name);
+ str->append(STRING_WITH_LEN(" in "));
+ str->append(tab->table->s->table_name);
KEY *key_info= tab->table->key_info+ tab->ref.key;
- str->append(" on ", 4);
+ str->append(STRING_WITH_LEN(" on "));
str->append(key_info->name);
if (cond)
{
- str->append(" where ", 7);
+ str->append(STRING_WITH_LEN(" where "));
cond->print(str);
}
str->append(')');
@@ -1683,18 +1831,18 @@ void subselect_uniquesubquery_engine::print(String *str)
void subselect_indexsubquery_engine::print(String *str)
{
- str->append("<index_lookup>(", 15);
+ str->append(STRING_WITH_LEN("<index_lookup>("));
tab->ref.items[0]->print(str);
- str->append(" in ", 4);
- str->append(tab->table->real_name);
+ str->append(STRING_WITH_LEN(" in "));
+ str->append(tab->table->s->table_name);
KEY *key_info= tab->table->key_info+ tab->ref.key;
- str->append(" on ", 4);
+ str->append(STRING_WITH_LEN(" on "));
str->append(key_info->name);
if (check_null)
- str->append(" chicking NULL", 14);
+ str->append(STRING_WITH_LEN(" checking NULL"));
if (cond)
{
- str->append(" where ", 7);
+ str->append(STRING_WITH_LEN(" where "));
cond->print(str);
}
str->append(')');
@@ -1703,18 +1851,18 @@ void subselect_indexsubquery_engine::print(String *str)
/*
change select_result object of engine
- SINOPSYS
+ SYNOPSIS
subselect_single_select_engine::change_result()
si new subselect Item
res new select_result object
RETURN
- 0 OK
- -1 error
+ FALSE OK
+ TRUE error
*/
-int subselect_single_select_engine::change_item(Item_subselect *si,
- select_subselect *res)
+bool subselect_single_select_engine::change_result(Item_subselect *si,
+ select_subselect *res)
{
item= si;
result= res;
@@ -1725,18 +1873,18 @@ int subselect_single_select_engine::change_item(Item_subselect *si,
/*
change select_result object of engine
- SINOPSYS
+ SYNOPSIS
subselect_single_select_engine::change_result()
si new subselect Item
res new select_result object
RETURN
- 0 OK
- -1 error
+ FALSE OK
+ TRUE error
*/
-int subselect_union_engine::change_item(Item_subselect *si,
- select_subselect *res)
+bool subselect_union_engine::change_result(Item_subselect *si,
+ select_subselect *res)
{
item= si;
int rc= unit->change_result(res, result);
@@ -1748,27 +1896,28 @@ int subselect_union_engine::change_item(Item_subselect *si,
/*
change select_result emulation, never should be called
- SINOPSYS
+ SYNOPSIS
subselect_single_select_engine::change_result()
si new subselect Item
res new select_result object
RETURN
- -1 error
+ FALSE OK
+ TRUE error
*/
-int subselect_uniquesubquery_engine::change_item(Item_subselect *si,
- select_subselect *res)
+bool subselect_uniquesubquery_engine::change_result(Item_subselect *si,
+ select_subselect *res)
{
DBUG_ASSERT(0);
- return -1;
+ return TRUE;
}
/*
Report about presence of tables in subquery
- SINOPSYS
+ SYNOPSIS
subselect_single_select_engine::no_tables()
RETURN
@@ -1784,7 +1933,7 @@ bool subselect_single_select_engine::no_tables()
/*
Report about presence of tables in subquery
- SINOPSYS
+ SYNOPSIS
subselect_union_engine::no_tables()
RETURN
@@ -1805,7 +1954,7 @@ bool subselect_union_engine::no_tables()
/*
Report about presence of tables in subquery
- SINOPSYS
+ SYNOPSIS
subselect_uniquesubquery_engine::no_tables()
RETURN