diff options
-rw-r--r-- | mysql-test/r/func_system.result | 2 | ||||
-rw-r--r-- | mysql-test/r/subselect.result | 8 | ||||
-rw-r--r-- | mysql-test/t/subselect.test | 10 | ||||
-rw-r--r-- | sql/item_subselect.cc | 44 | ||||
-rw-r--r-- | sql/item_subselect.h | 10 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 1 |
6 files changed, 47 insertions, 28 deletions
diff --git a/mysql-test/r/func_system.result b/mysql-test/r/func_system.result index 671132428c5..d3db2cc5151 100644 --- a/mysql-test/r/func_system.result +++ b/mysql-test/r/func_system.result @@ -46,7 +46,7 @@ create table t1 (version char(40)) select database(), user(), version() as 'vers show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `database()` char(34) character set utf8 NOT NULL default '', + `database()` char(34) character set utf8 default NULL, `user()` char(77) character set utf8 NOT NULL default '', `version` char(40) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 5ab36dacaaf..77339473142 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -1891,3 +1891,11 @@ abc b 3 4 deallocate prepare stmt1; 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; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 0c093c4ae3e..eb4b1f33b14 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1212,3 +1212,13 @@ execute stmt1; select * from t3; deallocate prepare stmt1; 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; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 3d5a11a26bc..8c4dae92ddc 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -14,7 +14,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* +/* subselect Item SUBSELECT TODO: @@ -41,7 +41,7 @@ Item_subselect::Item_subselect(): { 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) */ null_value= 1; @@ -114,7 +114,7 @@ Item_subselect::~Item_subselect() } Item_subselect::trans_res -Item_subselect::select_transformer(JOIN *join) +Item_subselect::select_transformer(JOIN *join) { DBUG_ENTER("Item_subselect::select_transformer"); DBUG_RETURN(RES_OK); @@ -153,11 +153,11 @@ bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref) if (have_to_be_excluded) engine->exclude(); substitution= 0; - thd->where= "checking transformed subquery"; + 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) + // We can't substitute aggregate functions like "SELECT (max(i))" + if (substype() == SINGLEROW_SUBS && (*ref)->with_sum_func) { my_error(ER_INVALID_GROUP_FUNC_USE, MYF(0)); return 1; @@ -166,7 +166,7 @@ bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref) } // Is it one field subselect? if (engine->cols() > max_columns) - { + { my_error(ER_OPERAND_COLUMNS, MYF(0), 1); return 1; } @@ -204,7 +204,7 @@ bool Item_subselect::exec() return (res); } -Item::Type Item_subselect::type() const +Item::Type Item_subselect::type() const { return SUBSELECT_ITEM; } @@ -282,7 +282,7 @@ 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(); - + DBUG_VOID_RETURN; } @@ -304,7 +304,7 @@ Item_singlerow_subselect::select_transformer(JOIN *join) { if (changed) return RES_OK; - + SELECT_LEX *select_lex= join->select_lex; Statement backup; @@ -319,10 +319,10 @@ Item_singlerow_subselect::select_transformer(JOIN *join) TODO: solve above problem */ !(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; if (join->thd->lex->describe) { @@ -360,7 +360,7 @@ Item_singlerow_subselect::select_transformer(JOIN *join) return RES_REDUCE; } return RES_OK; - + err: if (stmt) thd->restore_backup_item_arena(stmt, &backup); @@ -423,7 +423,7 @@ void Item_singlerow_subselect::bring_value() exec(); } -double Item_singlerow_subselect::val() +double Item_singlerow_subselect::val() { DBUG_ASSERT(fixed == 1); if (!exec() && !value->null_value) @@ -438,7 +438,7 @@ double Item_singlerow_subselect::val() } } -longlong Item_singlerow_subselect::val_int() +longlong Item_singlerow_subselect::val_int() { DBUG_ASSERT(fixed == 1); if (!exec() && !value->null_value) @@ -453,7 +453,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) { @@ -558,7 +558,7 @@ double Item_exists_subselect::val() return (double) value; } -longlong Item_exists_subselect::val_int() +longlong Item_exists_subselect::val_int() { DBUG_ASSERT(fixed == 1); if (exec()) @@ -595,7 +595,7 @@ double Item_in_subselect::val() return (double) value; } -longlong Item_in_subselect::val_int() +longlong Item_in_subselect::val_int() { DBUG_ASSERT(fixed == 1); if (exec()) @@ -847,7 +847,7 @@ Item_in_subselect::single_value_transformer(JOIN *join, { // 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) @@ -890,7 +890,7 @@ Item_in_subselect::row_value_transformer(JOIN *join) thd->where= "row IN/ALL/ANY subquery"; 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; @@ -931,7 +931,7 @@ Item_in_subselect::row_value_transformer(JOIN *join) List_iterator_fast<Item> li(select_lex->item_list); 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, (char *) "<no matter>", (char *) "<list ref>"); @@ -1113,7 +1113,7 @@ int subselect_single_select_engine::prepare() (ORDER*) select_lex->order_list.first, (ORDER*) select_lex->group_list.first, select_lex->having, - (ORDER*) 0, select_lex, + (ORDER*) 0, select_lex, select_lex->master_unit())) return 1; thd->lex->current_select= save_select; diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 364781de362..6b8b8b0b3a7 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -47,7 +47,7 @@ protected: /* old engine if engine was changed */ subselect_engine *old_engine; /* cache of used external tables */ - table_map used_tables_cache; + table_map used_tables_cache; /* allowed number of columns (1 for single value subqueries) */ uint max_columns; /* work with 'substitution' */ @@ -69,17 +69,17 @@ public: virtual subs_type substype() { return UNKNOWN_SUBS; } - /* + /* We need this method, because some compilers do not allow 'this' pointer in constructor initialization list, but we need pass pointer 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); ~Item_subselect(); void cleanup(); - virtual void reset() + virtual void reset() { null_value= 1; } @@ -275,7 +275,7 @@ public: } virtual ~subselect_engine() {}; // to satisfy compiler virtual void cleanup()= 0; - + // set_thd should be called before prepare() void set_thd(THD *thd_arg) { thd= thd_arg; } THD * get_thd() { return thd; } diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 91df364e531..4305bee42a2 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1706,6 +1706,7 @@ static void reset_stmt_for_execute(Prepared_statement *stmt) unit->reinit_exec_mechanism(); } } + stmt->lex->current_select= &stmt->lex->select_lex; } |