summaryrefslogtreecommitdiff
path: root/sql/item_subselect.cc
diff options
context:
space:
mode:
authorunknown <pem@mysql.com>2004-04-07 19:07:44 +0200
committerunknown <pem@mysql.com>2004-04-07 19:07:44 +0200
commitc635d37479fbf8aa0da03d47f264ab9907cfe72b (patch)
treee5ac1517ff3dccc42352b7bac39ecd1c093d0ae6 /sql/item_subselect.cc
parent8468cde4f1e028b380c24d0bac28402678568d81 (diff)
parent0948f9769b3e3da2e064e65015b86644af4acd78 (diff)
downloadmariadb-git-c635d37479fbf8aa0da03d47f264ab9907cfe72b.tar.gz
Merge 4.1 -> 5.0.
BitKeeper/etc/ignore: auto-union BitKeeper/etc/logging_ok: auto-union VC++Files/sql/mysqld.dsp: Auto merged client/Makefile.am: Auto merged client/mysql.cc: Auto merged client/mysqltest.c: Auto merged configure.in: Auto merged include/my_global.h: Auto merged include/my_pthread.h: Auto merged include/my_sys.h: Auto merged include/mysql_com.h: Auto merged libmysqld/Makefile.am: Auto merged libmysqld/lib_sql.cc: Auto merged myisam/mi_check.c: Auto merged myisam/myisamchk.c: Auto merged myisam/myisamdef.h: Auto merged mysql-test/install_test_db.sh: Auto merged mysql-test/r/insert_select.result: Auto merged mysql-test/r/join_outer.result: Auto merged mysql-test/r/null.result: Auto merged mysql-test/r/connect.result: Auto merged mysql-test/r/func_sapdb.result: Auto merged mysql-test/r/mix_innodb_myisam_binlog.result: Auto merged mysql-test/r/mysqldump.result: Auto merged mysql-test/r/rpl_change_master.result: Auto merged mysql-test/r/rpl_log.result: Auto merged mysql-test/r/show_check.result: Auto merged mysql-test/r/symlink.result: Auto merged mysql-test/r/rpl_flush_log_loop.result: Auto merged mysql-test/r/rpl_flush_tables.result: Auto merged mysql-test/r/rpl_loaddata.result: Auto merged mysql-test/r/rpl_loaddata_rule_m.result: Auto merged mysql-test/r/rpl_loaddata_rule_s.result: Auto merged mysql-test/r/rpl_max_relay_size.result: Auto merged mysql-test/r/rpl_reset_slave.result: Auto merged mysql-test/r/rpl_temporary.result: Auto merged mysql-test/r/rpl_until.result: Auto merged mysql-test/r/rpl_user_variables.result: Auto merged mysql-test/r/subselect.result: Auto merged mysql-test/r/union.result: Auto merged mysql-test/r/variables.result: Auto merged mysql-test/t/func_sapdb.test: Auto merged mysql-test/t/mix_innodb_myisam_binlog.test: Auto merged mysql-test/t/mysqlbinlog.test: Auto merged mysql-test/t/rpl_change_master.test: Auto merged mysql-test/t/rpl_log.test: Auto merged mysql-test/t/variables.test: Auto merged netware/BUILD/compile-linux-tools: Auto merged netware/BUILD/compile-netware-END: Auto merged netware/BUILD/compile-netware-all: Auto merged netware/BUILD/compile-netware-standard: Auto merged mysql-test/t/rpl_empty_master_crash.test: Auto merged mysql-test/t/rpl_error_ignored_table.test: Auto merged mysql-test/t/rpl_flush_log_loop.test: Auto merged mysql-test/t/rpl_loaddata.test: Auto merged mysql-test/t/rpl_loaddata_rule_m.test: Auto merged mysql-test/t/rpl_loaddata_rule_s.test: Auto merged mysql-test/t/rpl_max_relay_size.test: Auto merged mysql-test/t/rpl_openssl.test: Auto merged mysql-test/t/rpl_relayrotate-slave.opt: Auto merged mysql-test/t/rpl_reset_slave.test: Auto merged mysql-test/t/rpl_trunc_binlog.test: Auto merged mysql-test/t/rpl_until.test: Auto merged mysql-test/t/rpl_user_variables.test: Auto merged mysql-test/t/subselect.test: Auto merged scripts/make_binary_distribution.sh: Auto merged scripts/mysql_create_system_tables.sh: Auto merged scripts/mysql_fix_privilege_tables.sql: Auto merged scripts/mysql_install_db.sh: Auto merged sql/filesort.cc: Auto merged sql/ha_berkeley.cc: Auto merged sql/ha_berkeley.h: Auto merged sql/ha_innodb.h: Auto merged sql/ha_myisam.cc: Auto merged sql/handler.cc: Auto merged sql/handler.h: Auto merged sql/item.cc: Auto merged sql/item.h: Auto merged sql/item_cmpfunc.cc: Auto merged sql/item_cmpfunc.h: Auto merged sql/item_create.cc: Auto merged sql/item_create.h: Auto merged sql/item_subselect.cc: Auto merged sql/item_sum.cc: Auto merged sql/item_sum.h: Auto merged sql/item_timefunc.h: Auto merged sql/lock.cc: Auto merged sql/log_event.h: Auto merged sql/mysqld.cc: Auto merged sql/net_serv.cc: Auto merged sql/protocol.cc: Auto merged sql/protocol.h: Auto merged sql/repl_failsafe.cc: Auto merged sql/sql_acl.cc: Auto merged sql/sql_acl.h: Auto merged sql/sql_base.cc: Auto merged sql/sql_cache.cc: Auto merged sql/sql_class.h: Auto merged sql/sql_db.cc: Auto merged sql/sql_delete.cc: Auto merged sql/sql_derived.cc: Auto merged sql/sql_lex.h: Auto merged sql/sql_list.h: Auto merged sql/sql_load.cc: Auto merged sql/sql_rename.cc: Auto merged sql/sql_repl.cc: Auto merged sql/sql_repl.h: Auto merged sql/sql_select.cc: Auto merged sql/sql_select.h: Auto merged sql/sql_show.cc: Auto merged sql/sql_table.cc: Auto merged sql/sql_test.cc: Auto merged sql/sql_update.cc: Auto merged sql-common/client.c: Auto merged tests/client_test.c: Auto merged
Diffstat (limited to 'sql/item_subselect.cc')
-rw-r--r--sql/item_subselect.cc329
1 files changed, 236 insertions, 93 deletions
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index d4d9f832a3d..390c734a87a 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -35,9 +35,9 @@ inline Item * and_items(Item* cond, Item *item)
}
Item_subselect::Item_subselect():
- Item_result_field(), value_assigned(0), substitution(0),
- engine(0), used_tables_cache(0), have_to_be_excluded(0),
- const_item_cache(1), engine_changed(0)
+ Item_result_field(), value_assigned(0), thd(0), substitution(0),
+ engine(0), old_engine(0), used_tables_cache(0), have_to_be_excluded(0),
+ const_item_cache(1), engine_changed(0), changed(0)
{
reset();
/*
@@ -54,10 +54,10 @@ void Item_subselect::init(st_select_lex *select_lex,
DBUG_ENTER("Item_subselect::init");
DBUG_PRINT("subs", ("select_lex 0x%xl", (ulong) select_lex));
+ unit= select_lex->master_unit();
if (select_lex->next_select())
- engine= new subselect_union_engine(select_lex->master_unit(), result,
- this);
+ engine= new subselect_union_engine(unit, result, this);
else
engine= new subselect_single_select_engine(select_lex, result, this);
DBUG_VOID_RETURN;
@@ -65,8 +65,26 @@ void Item_subselect::init(st_select_lex *select_lex,
void Item_subselect::cleanup()
{
+ DBUG_ENTER("Item_subselect::cleanup");
Item_result_field::cleanup();
- engine->cleanup();
+ if (old_engine)
+ {
+ engine->cleanup();
+ engine= old_engine;
+ old_engine= 0;
+ }
+ engine->cleanup();
+ reset();
+ value_assigned= 0;
+ DBUG_VOID_RETURN;
+}
+
+void Item_singlerow_subselect::cleanup()
+{
+ DBUG_ENTER("Item_singlerow_subselect::cleanup");
+ value= 0; row= 0;
+ Item_subselect::cleanup();
+ DBUG_VOID_RETURN;
}
Item_subselect::~Item_subselect()
@@ -84,22 +102,35 @@ Item_subselect::select_transformer(JOIN *join)
bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref)
{
+ DBUG_ASSERT(fixed == 0);
engine->set_thd((thd= thd_param));
+ stmt= thd->current_statement;
char const *save_where= thd->where;
int res= engine->prepare();
+
+ // all transformetion is done (used by prepared statements)
+ changed= 1;
+
if (!res)
{
if (substitution)
{
+ int ret= 0;
+
+ // did we changed top item of WHERE condition
+ if (unit->outer_select()->where == (*ref))
+ unit->outer_select()->where= substitution; // correct WHERE for PS
+
(*ref)= substitution;
substitution->name= name;
if (have_to_be_excluded)
engine->exclude();
substitution= 0;
fixed= 1;
- thd->where= "checking transformed subquery";
- int ret= (*ref)->fix_fields(thd, tables, ref);
+ thd->where= "checking transformed subquery";
+ if (!(*ref)->fixed)
+ ret= (*ref)->fix_fields(thd, tables, ref);
// We can't substitute aggregate functions (like (SELECT (max(i)))
if ((*ref)->with_sum_func)
{
@@ -171,6 +202,12 @@ bool Item_subselect::const_item() const
return const_item_cache;
}
+Item *Item_subselect::get_tmp_table_item(THD *thd)
+{
+ if (!with_sum_func && !const_item())
+ return new Item_field(result_field);
+ return copy_or_same(thd);
+}
void Item_subselect::update_used_tables()
{
@@ -240,8 +277,12 @@ void Item_singlerow_subselect::reset()
Item_subselect::trans_res
Item_singlerow_subselect::select_transformer(JOIN *join)
{
+ if (changed)
+ return RES_OK;
+
SELECT_LEX *select_lex= join->select_lex;
-
+ Statement backup;
+
if (!select_lex->master_unit()->first_select()->next_select() &&
!select_lex->table_list.elements &&
select_lex->item_list.elements == 1 &&
@@ -275,20 +316,30 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
if (join->conds || join->having)
{
Item *cond;
+ if (stmt)
+ thd->set_n_backup_item_arena(stmt, &backup);
+
if (!join->having)
cond= join->conds;
else if (!join->conds)
cond= join->having;
else
if (!(cond= new Item_cond_and(join->conds, join->having)))
- return RES_ERROR;
+ goto err;
if (!(substitution= new Item_func_if(cond, substitution,
new Item_null())))
- return RES_ERROR;
+ goto err;
}
+ if (stmt)
+ thd->restore_backup_item_arena(stmt, &backup);
return RES_REDUCE;
}
return RES_OK;
+
+err:
+ if (stmt)
+ thd->restore_backup_item_arena(stmt, &backup);
+ return RES_ERROR;
}
void Item_singlerow_subselect::store(uint i, Item *item)
@@ -349,6 +400,7 @@ void Item_singlerow_subselect::bring_value()
double Item_singlerow_subselect::val()
{
+ DBUG_ASSERT(fixed == 1);
if (!exec() && !value->null_value)
{
null_value= 0;
@@ -363,6 +415,7 @@ double Item_singlerow_subselect::val()
longlong Item_singlerow_subselect::val_int()
{
+ DBUG_ASSERT(fixed == 1);
if (!exec() && !value->null_value)
{
null_value= 0;
@@ -471,6 +524,7 @@ void Item_exists_subselect::fix_length_and_dec()
double Item_exists_subselect::val()
{
+ DBUG_ASSERT(fixed == 1);
if (exec())
{
reset();
@@ -481,6 +535,7 @@ double Item_exists_subselect::val()
longlong Item_exists_subselect::val_int()
{
+ DBUG_ASSERT(fixed == 1);
if (exec())
{
reset();
@@ -491,6 +546,7 @@ longlong Item_exists_subselect::val_int()
String *Item_exists_subselect::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
if (exec())
{
reset();
@@ -502,6 +558,7 @@ String *Item_exists_subselect::val_str(String *str)
double Item_in_subselect::val()
{
+ DBUG_ASSERT(fixed == 1);
if (exec())
{
reset();
@@ -515,6 +572,7 @@ double Item_in_subselect::val()
longlong Item_in_subselect::val_int()
{
+ DBUG_ASSERT(fixed == 1);
if (exec())
{
reset();
@@ -528,6 +586,7 @@ longlong Item_in_subselect::val_int()
String *Item_in_subselect::val_str(String *str)
{
+ DBUG_ASSERT(fixed == 1);
if (exec())
{
reset();
@@ -550,15 +609,22 @@ Item_in_subselect::single_value_transformer(JOIN *join,
{
DBUG_ENTER("Item_in_subselect::single_value_transformer");
+ if (changed)
+ {
+ DBUG_RETURN(RES_OK);
+ }
+
SELECT_LEX *select_lex= join->select_lex;
+ Statement backup;
- THD *thd_tmp= join->thd;
- thd_tmp->where= "scalar IN/ALL/ANY subquery";
+ thd->where= "scalar IN/ALL/ANY subquery";
+ if (stmt)
+ thd->set_n_backup_item_arena(stmt, &backup);
if (select_lex->item_list.elements > 1)
{
my_error(ER_OPERAND_COLUMNS, MYF(0), 1);
- DBUG_RETURN(RES_ERROR);
+ goto err;
}
if ((abort_on_null || (upper_not && upper_not->top_level())) &&
@@ -567,7 +633,7 @@ Item_in_subselect::single_value_transformer(JOIN *join,
if (substitution)
{
// It is second (third, ...) SELECT of UNION => All is done
- DBUG_RETURN(RES_OK);
+ goto ok;
}
Item *subs;
@@ -596,11 +662,9 @@ Item_in_subselect::single_value_transformer(JOIN *join,
*select_lex->ref_pointer_array= item;
select_lex->item_list.empty();
select_lex->item_list.push_back(item);
-
- if (item->fix_fields(thd_tmp, join->tables_list, &item))
- {
- DBUG_RETURN(RES_ERROR);
- }
+
+ // fix_fields call for 'item' will be made during new subquery fix_fields
+
subs= new Item_singlerow_subselect(select_lex);
}
else
@@ -611,16 +675,16 @@ Item_in_subselect::single_value_transformer(JOIN *join,
subs= new Item_maxmin_subselect(this, select_lex, func->l_op());
}
// left expression belong to outer select
- SELECT_LEX *current= thd_tmp->lex->current_select, *up;
- thd_tmp->lex->current_select= up= current->return_after_parsing();
- if (left_expr->fix_fields(thd_tmp, up->get_table_list(), &left_expr))
+ SELECT_LEX *current= thd->lex->current_select, *up;
+ thd->lex->current_select= up= current->return_after_parsing();
+ if (left_expr->fix_fields(thd, up->get_table_list(), &left_expr))
{
- thd_tmp->lex->current_select= current;
- DBUG_RETURN(RES_ERROR);
+ thd->lex->current_select= current;
+ goto err;
}
- thd_tmp->lex->current_select= current;
+ thd->lex->current_select= current;
substitution= func->create(left_expr, subs);
- DBUG_RETURN(RES_OK);
+ goto ok;
}
if (!substitution)
@@ -629,16 +693,16 @@ Item_in_subselect::single_value_transformer(JOIN *join,
SELECT_LEX_UNIT *unit= select_lex->master_unit();
substitution= optimizer= new Item_in_optimizer(left_expr, this);
- SELECT_LEX *current= thd_tmp->lex->current_select, *up;
+ SELECT_LEX *current= thd->lex->current_select, *up;
- thd_tmp->lex->current_select= up= current->return_after_parsing();
+ 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_tmp, up->get_table_list(), 0))
+ if (!optimizer || optimizer->fix_left(thd, up->get_table_list(), 0))
{
- thd_tmp->lex->current_select= current;
- DBUG_RETURN(RES_ERROR);
+ thd->lex->current_select= current;
+ goto err;
}
- thd_tmp->lex->current_select= current;
+ thd->lex->current_select= current;
/*
As far as Item_ref_in_optimizer do not substitude itself on fix_fields
@@ -665,12 +729,17 @@ Item_in_subselect::single_value_transformer(JOIN *join,
select_lex->ref_pointer_array,
(char *)"<ref>",
this->full_name()));
- join->having= and_items(join->having, item);
+ /*
+ AND and comparison functions can't be changed during fix_fields()
+ we can assign select_lex->having here, and pass 0 as last
+ argument (reference) to fix_fields()
+ */
+ select_lex->having= join->having= and_items(join->having, item);
select_lex->having_fix_field= 1;
- if (join->having->fix_fields(thd_tmp, join->tables_list, &join->having))
+ if (join->having->fix_fields(thd, join->tables_list, 0))
{
select_lex->having_fix_field= 0;
- DBUG_RETURN(RES_ERROR);
+ goto err;
}
select_lex->having_fix_field= 0;
}
@@ -682,44 +751,61 @@ Item_in_subselect::single_value_transformer(JOIN *join,
select_lex->ref_pointer_array[0]= select_lex->item_list.head();
if (select_lex->table_list.elements)
{
- Item *having= item, *isnull= item;
+ Item *having= item, *orig_item= item;
item= func->create(expr, item);
- if (!abort_on_null)
+ if (!abort_on_null && orig_item->maybe_null)
{
having= new Item_is_not_null_test(this, having);
- join->having= (join->having ?
- new Item_cond_and(having, join->having) :
- having);
+ /*
+ 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()
+ */
+ select_lex->having=
+ join->having= (join->having ?
+ new Item_cond_and(having, join->having) :
+ having);
select_lex->having_fix_field= 1;
- if (join->having->fix_fields(thd_tmp, join->tables_list,
- &join->having))
+ if (join->having->fix_fields(thd, join->tables_list, 0))
{
select_lex->having_fix_field= 0;
- DBUG_RETURN(RES_ERROR);
+ goto err;
}
select_lex->having_fix_field= 0;
item= new Item_cond_or(item,
- new Item_func_isnull(isnull));
+ new Item_func_isnull(orig_item));
}
item->name= (char *)in_additional_cond;
- join->conds= and_items(join->conds, item);
- if (join->conds->fix_fields(thd_tmp, join->tables_list, &join->conds))
- DBUG_RETURN(RES_ERROR);
+ /*
+ AND can't be changed during fix_fields()
+ we can assign select_lex->having here, and pass 0 as last
+ argument (reference) to fix_fields()
+ */
+ select_lex->where= join->conds= and_items(join->conds, item);
+ if (join->conds->fix_fields(thd, join->tables_list, 0))
+ goto err;
}
else
{
if (select_lex->master_unit()->first_select()->next_select())
{
- join->having= func->create(expr,
- new Item_null_helper(this, item,
- (char *)"<no matter>",
- (char *)"<result>"));
+ /*
+ comparison functions can't be changed during fix_fields()
+ we can assign select_lex->having here, and pass 0 as last
+ argument (reference) to fix_fields()
+ */
+ select_lex->having=
+ join->having=
+ func->create(expr,
+ new Item_null_helper(this, item,
+ (char *)"<no matter>",
+ (char *)"<result>"));
select_lex->having_fix_field= 1;
- if (join->having->fix_fields(thd_tmp, join->tables_list,
- &join->having))
+ if (join->having->fix_fields(thd, join->tables_list,
+ 0))
{
select_lex->having_fix_field= 0;
- DBUG_RETURN(RES_ERROR);
+ goto err;
}
select_lex->having_fix_field= 0;
}
@@ -730,18 +816,29 @@ Item_in_subselect::single_value_transformer(JOIN *join,
// fix_field of item will be done in time of substituting
substitution= item;
have_to_be_excluded= 1;
- if (thd_tmp->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(thd_tmp, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_SELECT_REDUCED, warn_buff);
}
+ if (stmt)
+ thd->restore_backup_item_arena(stmt, &backup);
DBUG_RETURN(RES_REDUCE);
}
}
}
+
+ok:
+ if (stmt)
+ thd->restore_backup_item_arena(stmt, &backup);
DBUG_RETURN(RES_OK);
+
+err:
+ if (stmt)
+ thd->restore_backup_item_arena(stmt, &backup);
+ DBUG_RETURN(RES_ERROR);
}
@@ -750,15 +847,23 @@ Item_in_subselect::row_value_transformer(JOIN *join)
{
DBUG_ENTER("Item_in_subselect::row_value_transformer");
- THD *thd_tmp= join->thd;
- thd_tmp->where= "row IN/ALL/ANY subquery";
+ if (changed)
+ {
+ DBUG_RETURN(RES_OK);
+ }
+ Statement backup;
+ Item *item= 0;
+
+ thd->where= "row IN/ALL/ANY subquery";
+ if (stmt)
+ thd->set_n_backup_item_arena(stmt, &backup);
SELECT_LEX *select_lex= join->select_lex;
if (select_lex->item_list.elements != left_expr->cols())
{
my_error(ER_OPERAND_COLUMNS, MYF(0), left_expr->cols());
- DBUG_RETURN(RES_ERROR);
+ goto err;
}
if (!substitution)
@@ -767,62 +872,82 @@ Item_in_subselect::row_value_transformer(JOIN *join)
SELECT_LEX_UNIT *unit= select_lex->master_unit();
substitution= optimizer= new Item_in_optimizer(left_expr, this);
- SELECT_LEX *current= thd_tmp->lex->current_select, *up;
- thd_tmp->lex->current_select= up= current->return_after_parsing();
+ 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_tmp, up->get_table_list(), 0))
+ if (!optimizer || optimizer->fix_left(thd, up->get_table_list(), 0))
{
- thd_tmp->lex->current_select= current;
- DBUG_RETURN(RES_ERROR);
+ thd->lex->current_select= current;
+ goto err;
}
- thd_tmp->lex->current_select= current;
+
+ // we will refer to apper level cache array => we have to save it in PS
+ optimizer->keep_top_level_cache();
+
+ thd->lex->current_select= current;
unit->uncacheable|= UNCACHEABLE_DEPENDENT;
}
- uint n= left_expr->cols();
-
select_lex->uncacheable|= UNCACHEABLE_DEPENDENT;
- select_lex->setup_ref_array(thd_tmp,
+ select_lex->setup_ref_array(thd,
select_lex->order_list.elements +
select_lex->group_list.elements);
- Item *item= 0;
- List_iterator_fast<Item> li(select_lex->item_list);
- for (uint i= 0; i < n; i++)
{
- Item *func= new Item_ref_null_helper(this,
- select_lex->ref_pointer_array+i,
- (char *) "<no matter>",
- (char *) "<list ref>");
- func=
- eq_creator.create(new Item_ref((*optimizer->get_cache())->
- addr(i),
- NULL,
- (char *)"<no matter>",
+ uint n= left_expr->cols();
+ List_iterator_fast<Item> li(select_lex->item_list);
+ for (uint i= 0; i < n; i++)
+ {
+ Item *func= new Item_ref_null_helper(this,
+ select_lex->ref_pointer_array+i,
+ (char *) "<no matter>",
+ (char *) "<list ref>");
+ func=
+ eq_creator.create(new Item_ref((*optimizer->get_cache())->
+ addr(i),
+ NULL,
+ (char *)"<no matter>",
(char *)in_left_expr_name),
- func);
- item= and_items(item, func);
+ func);
+ item= and_items(item, func);
+ }
}
-
if (join->having || select_lex->with_sum_func ||
select_lex->group_list.first ||
!select_lex->table_list.elements)
{
- join->having= and_items(join->having, item);
+ /*
+ AND can't be changed during fix_fields()
+ we can assign select_lex->having here, and pass 0 as last
+ argument (reference) to fix_fields()
+ */
+ select_lex->having= join->having= and_items(join->having, item);
select_lex->having_fix_field= 1;
- if (join->having->fix_fields(thd_tmp, join->tables_list, &join->having))
+ if (join->having->fix_fields(thd, join->tables_list, 0))
{
select_lex->having_fix_field= 0;
- DBUG_RETURN(RES_ERROR);
+ goto err;
}
select_lex->having_fix_field= 0;
}
else
{
- join->conds= and_items(join->conds, item);
- if (join->conds->fix_fields(thd_tmp, join->tables_list, &join->having))
- DBUG_RETURN(RES_ERROR);
+ /*
+ AND can't be changed during fix_fields()
+ we can assign select_lex->having here, and pass 0 as last
+ argument (reference) to fix_fields()
+ */
+ select_lex->where= join->conds= and_items(join->conds, item);
+ if (join->conds->fix_fields(thd, join->tables_list, 0))
+ goto err;
}
+ if (stmt)
+ thd->restore_backup_item_arena(stmt, &backup);
DBUG_RETURN(RES_OK);
+
+err:
+ if (stmt)
+ thd->restore_backup_item_arena(stmt, &backup);
+ DBUG_RETURN(RES_ERROR);
}
@@ -888,13 +1013,31 @@ subselect_single_select_engine(st_select_lex *select,
this->select_lex= select_lex;
}
+
void subselect_single_select_engine::cleanup()
{
- prepared= 0;
- optimized= 0;
- executed= 0;
+ DBUG_ENTER("subselect_single_select_engine::cleanup");
+ prepared= optimized= executed= 0;
+ join= 0;
+ DBUG_VOID_RETURN;
}
+
+void subselect_union_engine::cleanup()
+{
+ DBUG_ENTER("subselect_union_engine::cleanup");
+ unit->reinit_exec_mechanism();
+ DBUG_VOID_RETURN;
+}
+
+
+void subselect_uniquesubquery_engine::cleanup()
+{
+ DBUG_ENTER("subselect_uniquesubquery_engine::cleanup");
+ DBUG_VOID_RETURN;
+}
+
+
subselect_union_engine::subselect_union_engine(st_select_lex_unit *u,
select_subselect *result_arg,
Item_subselect *item_arg)