Commit 1c8e92c6 authored by unknown's avatar unknown

aggregate functions check during substitution made only for single row subselects (BUG#4400)

restoring current senect pointer before PS rexecution (backport from 5.0)
removed spaces at  lines ends


mysql-test/r/subselect.result:
  Aggregate function comparation with ALL/ANY/SOME subselect test
mysql-test/t/subselect.test:
  Aggregate function comparation with ALL/ANY/SOME subselect test
sql/item_subselect.cc:
  removed spaces at  lines ends
  aggregate functions check during substitution made only for single row subselects
sql/item_subselect.h:
  removed spaces at  lines ends
sql/sql_prepare.cc:
  restoring current senect pointer before PS rexecution (backport from 5.0)
parent 88684077
...@@ -1891,3 +1891,11 @@ abc b ...@@ -1891,3 +1891,11 @@ abc b
3 4 3 4
deallocate prepare stmt1; deallocate prepare stmt1;
DROP TABLE t1, t2, t3; DROP TABLE t1, t2, t3;
CREATE TABLE `t1` ( `a` int(11) default NULL) ENGINE=MyISAM DEFAULT CHARSET=latin1;
insert into t1 values (1);
CREATE TABLE `t2` ( `b` int(11) default NULL, `a` int(11) default NULL) ENGINE=MyISAM DEFAULT CHARSET=latin1;
insert into t2 values (1,2);
select t000.a, count(*) `C` FROM t1 t000 GROUP BY t000.a HAVING count(*) > ALL (SELECT count(*) FROM t2 t001 WHERE t001.a=1);
a C
1 1
drop table t1,t2;
...@@ -1212,3 +1212,13 @@ execute stmt1; ...@@ -1212,3 +1212,13 @@ execute stmt1;
select * from t3; select * from t3;
deallocate prepare stmt1; deallocate prepare stmt1;
DROP TABLE t1, t2, t3; DROP TABLE t1, t2, t3;
#
# Aggregate function comparation with ALL/ANY/SOME subselect
#
CREATE TABLE `t1` ( `a` int(11) default NULL) ENGINE=MyISAM DEFAULT CHARSET=latin1;
insert into t1 values (1);
CREATE TABLE `t2` ( `b` int(11) default NULL, `a` int(11) default NULL) ENGINE=MyISAM DEFAULT CHARSET=latin1;
insert into t2 values (1,2);
select t000.a, count(*) `C` FROM t1 t000 GROUP BY t000.a HAVING count(*) > ALL (SELECT count(*) FROM t2 t001 WHERE t001.a=1);
drop table t1,t2;
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* /*
subselect Item subselect Item
SUBSELECT TODO: SUBSELECT TODO:
...@@ -41,7 +41,7 @@ Item_subselect::Item_subselect(): ...@@ -41,7 +41,7 @@ Item_subselect::Item_subselect():
{ {
reset(); reset();
/* /*
item value is NULL if select_subselect not changed this value item value is NULL if select_subselect not changed this value
(i.e. some rows will be found returned) (i.e. some rows will be found returned)
*/ */
null_value= 1; null_value= 1;
...@@ -114,7 +114,7 @@ Item_subselect::~Item_subselect() ...@@ -114,7 +114,7 @@ Item_subselect::~Item_subselect()
} }
Item_subselect::trans_res Item_subselect::trans_res
Item_subselect::select_transformer(JOIN *join) Item_subselect::select_transformer(JOIN *join)
{ {
DBUG_ENTER("Item_subselect::select_transformer"); DBUG_ENTER("Item_subselect::select_transformer");
DBUG_RETURN(RES_OK); DBUG_RETURN(RES_OK);
...@@ -148,11 +148,11 @@ bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref) ...@@ -148,11 +148,11 @@ bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref)
if (have_to_be_excluded) if (have_to_be_excluded)
engine->exclude(); engine->exclude();
substitution= 0; substitution= 0;
thd->where= "checking transformed subquery"; thd->where= "checking transformed subquery";
if (!(*ref)->fixed) if (!(*ref)->fixed)
ret= (*ref)->fix_fields(thd, tables, ref); ret= (*ref)->fix_fields(thd, tables, ref);
// We can't substitute aggregate functions (like (SELECT (max(i))) // We can't substitute aggregate functions like "SELECT (max(i))"
if ((*ref)->with_sum_func) if (substype() == SINGLEROW_SUBS && (*ref)->with_sum_func)
{ {
my_error(ER_INVALID_GROUP_FUNC_USE, MYF(0)); my_error(ER_INVALID_GROUP_FUNC_USE, MYF(0));
return 1; return 1;
...@@ -161,7 +161,7 @@ bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref) ...@@ -161,7 +161,7 @@ bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref)
} }
// Is it one field subselect? // Is it one field subselect?
if (engine->cols() > max_columns) if (engine->cols() > max_columns)
{ {
my_error(ER_OPERAND_COLUMNS, MYF(0), 1); my_error(ER_OPERAND_COLUMNS, MYF(0), 1);
return 1; return 1;
} }
...@@ -199,7 +199,7 @@ bool Item_subselect::exec() ...@@ -199,7 +199,7 @@ bool Item_subselect::exec()
return (res); return (res);
} }
Item::Type Item_subselect::type() const Item::Type Item_subselect::type() const
{ {
return SUBSELECT_ITEM; return SUBSELECT_ITEM;
} }
...@@ -277,7 +277,7 @@ Item_maxmin_subselect::Item_maxmin_subselect(Item_subselect *parent, ...@@ -277,7 +277,7 @@ Item_maxmin_subselect::Item_maxmin_subselect(Item_subselect *parent,
*/ */
used_tables_cache= parent->get_used_tables_cache(); used_tables_cache= parent->get_used_tables_cache();
const_item_cache= parent->get_const_item_cache(); const_item_cache= parent->get_const_item_cache();
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -299,7 +299,7 @@ Item_singlerow_subselect::select_transformer(JOIN *join) ...@@ -299,7 +299,7 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
{ {
if (changed) if (changed)
return RES_OK; return RES_OK;
SELECT_LEX *select_lex= join->select_lex; SELECT_LEX *select_lex= join->select_lex;
Statement backup; Statement backup;
...@@ -314,10 +314,10 @@ Item_singlerow_subselect::select_transformer(JOIN *join) ...@@ -314,10 +314,10 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
TODO: solve above problem TODO: solve above problem
*/ */
!(select_lex->item_list.head()->type() == FIELD_ITEM || !(select_lex->item_list.head()->type() == FIELD_ITEM ||
select_lex->item_list.head()->type() == REF_ITEM) select_lex->item_list.head()->type() == REF_ITEM)
) )
{ {
have_to_be_excluded= 1; have_to_be_excluded= 1;
if (join->thd->lex->describe) if (join->thd->lex->describe)
{ {
...@@ -355,7 +355,7 @@ Item_singlerow_subselect::select_transformer(JOIN *join) ...@@ -355,7 +355,7 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
return RES_REDUCE; return RES_REDUCE;
} }
return RES_OK; return RES_OK;
err: err:
if (stmt) if (stmt)
thd->restore_backup_item_arena(stmt, &backup); thd->restore_backup_item_arena(stmt, &backup);
...@@ -418,7 +418,7 @@ void Item_singlerow_subselect::bring_value() ...@@ -418,7 +418,7 @@ void Item_singlerow_subselect::bring_value()
exec(); exec();
} }
double Item_singlerow_subselect::val() double Item_singlerow_subselect::val()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
if (!exec() && !value->null_value) if (!exec() && !value->null_value)
...@@ -433,7 +433,7 @@ double Item_singlerow_subselect::val() ...@@ -433,7 +433,7 @@ double Item_singlerow_subselect::val()
} }
} }
longlong Item_singlerow_subselect::val_int() longlong Item_singlerow_subselect::val_int()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
if (!exec() && !value->null_value) if (!exec() && !value->null_value)
...@@ -448,7 +448,7 @@ longlong Item_singlerow_subselect::val_int() ...@@ -448,7 +448,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) if (!exec() && !value->null_value)
{ {
...@@ -553,7 +553,7 @@ double Item_exists_subselect::val() ...@@ -553,7 +553,7 @@ double Item_exists_subselect::val()
return (double) value; return (double) value;
} }
longlong Item_exists_subselect::val_int() longlong Item_exists_subselect::val_int()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
if (exec()) if (exec())
...@@ -590,7 +590,7 @@ double Item_in_subselect::val() ...@@ -590,7 +590,7 @@ double Item_in_subselect::val()
return (double) value; return (double) value;
} }
longlong Item_in_subselect::val_int() longlong Item_in_subselect::val_int()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
if (exec()) if (exec())
...@@ -842,7 +842,7 @@ Item_in_subselect::single_value_transformer(JOIN *join, ...@@ -842,7 +842,7 @@ Item_in_subselect::single_value_transformer(JOIN *join,
{ {
// it is single select without tables => possible optimization // it is single select without tables => possible optimization
item= func->create(left_expr, item); 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; substitution= item;
have_to_be_excluded= 1; have_to_be_excluded= 1;
if (thd->lex->describe) if (thd->lex->describe)
...@@ -885,7 +885,7 @@ Item_in_subselect::row_value_transformer(JOIN *join) ...@@ -885,7 +885,7 @@ Item_in_subselect::row_value_transformer(JOIN *join)
thd->where= "row IN/ALL/ANY subquery"; thd->where= "row IN/ALL/ANY subquery";
if (stmt) if (stmt)
thd->set_n_backup_item_arena(stmt, &backup); thd->set_n_backup_item_arena(stmt, &backup);
SELECT_LEX *select_lex= join->select_lex; SELECT_LEX *select_lex= join->select_lex;
...@@ -926,7 +926,7 @@ Item_in_subselect::row_value_transformer(JOIN *join) ...@@ -926,7 +926,7 @@ Item_in_subselect::row_value_transformer(JOIN *join)
List_iterator_fast<Item> li(select_lex->item_list); List_iterator_fast<Item> li(select_lex->item_list);
for (uint i= 0; i < n; i++) for (uint i= 0; i < n; i++)
{ {
Item *func= new Item_ref_null_helper(this, Item *func= new Item_ref_null_helper(this,
select_lex->ref_pointer_array+i, select_lex->ref_pointer_array+i,
(char *) "<no matter>", (char *) "<no matter>",
(char *) "<list ref>"); (char *) "<list ref>");
...@@ -1108,7 +1108,7 @@ int subselect_single_select_engine::prepare() ...@@ -1108,7 +1108,7 @@ int subselect_single_select_engine::prepare()
(ORDER*) select_lex->order_list.first, (ORDER*) select_lex->order_list.first,
(ORDER*) select_lex->group_list.first, (ORDER*) select_lex->group_list.first,
select_lex->having, select_lex->having,
(ORDER*) 0, select_lex, (ORDER*) 0, select_lex,
select_lex->master_unit())) select_lex->master_unit()))
return 1; return 1;
thd->lex->current_select= save_select; thd->lex->current_select= save_select;
......
...@@ -47,7 +47,7 @@ class Item_subselect :public Item_result_field ...@@ -47,7 +47,7 @@ class Item_subselect :public Item_result_field
/* old engine if engine was changed */ /* old engine if engine was changed */
subselect_engine *old_engine; subselect_engine *old_engine;
/* cache of used external tables */ /* cache of used external tables */
table_map used_tables_cache; table_map used_tables_cache;
/* allowed number of columns (1 for single value subqueries) */ /* allowed number of columns (1 for single value subqueries) */
uint max_columns; uint max_columns;
/* work with 'substitution' */ /* work with 'substitution' */
...@@ -69,17 +69,17 @@ class Item_subselect :public Item_result_field ...@@ -69,17 +69,17 @@ class Item_subselect :public Item_result_field
virtual subs_type substype() { return UNKNOWN_SUBS; } virtual subs_type substype() { return UNKNOWN_SUBS; }
/* /*
We need this method, because some compilers do not allow 'this' We need this method, because some compilers do not allow 'this'
pointer in constructor initialization list, but we need pass pointer pointer in constructor initialization list, but we need pass pointer
to subselect Item class to select_subselect classes constructor. to subselect Item class to select_subselect classes constructor.
*/ */
virtual void init (st_select_lex *select_lex, virtual void init (st_select_lex *select_lex,
select_subselect *result); select_subselect *result);
~Item_subselect(); ~Item_subselect();
void cleanup(); void cleanup();
virtual void reset() virtual void reset()
{ {
null_value= 1; null_value= 1;
} }
...@@ -275,7 +275,7 @@ class subselect_engine: public Sql_alloc ...@@ -275,7 +275,7 @@ class subselect_engine: public Sql_alloc
} }
virtual ~subselect_engine() {}; // to satisfy compiler virtual ~subselect_engine() {}; // to satisfy compiler
virtual void cleanup()= 0; virtual void cleanup()= 0;
// set_thd should be called before prepare() // set_thd should be called before prepare()
void set_thd(THD *thd_arg) { thd= thd_arg; } void set_thd(THD *thd_arg) { thd= thd_arg; }
THD * get_thd() { return thd; } THD * get_thd() { return thd; }
......
...@@ -1706,6 +1706,7 @@ static void reset_stmt_for_execute(Prepared_statement *stmt) ...@@ -1706,6 +1706,7 @@ static void reset_stmt_for_execute(Prepared_statement *stmt)
unit->reinit_exec_mechanism(); unit->reinit_exec_mechanism();
} }
} }
stmt->lex->current_select= &stmt->lex->select_lex;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment