diff options
-rw-r--r-- | mysql-test/r/subselect.result | 34 | ||||
-rw-r--r-- | mysql-test/t/subselect.test | 16 | ||||
-rw-r--r-- | sql/item.cc | 10 | ||||
-rw-r--r-- | sql/item_subselect.cc | 6 | ||||
-rw-r--r-- | sql/mysql_priv.h | 6 | ||||
-rw-r--r-- | sql/sql_derived.cc | 27 | ||||
-rw-r--r-- | sql/sql_lex.h | 2 | ||||
-rw-r--r-- | sql/sql_parse.cc | 2 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 2 | ||||
-rw-r--r-- | sql/sql_select.cc | 18 | ||||
-rw-r--r-- | sql/sql_select.h | 2 | ||||
-rw-r--r-- | sql/sql_union.cc | 64 | ||||
-rw-r--r-- | sql/sql_update.cc | 2 |
13 files changed, 132 insertions, 59 deletions
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 5cb17e124f6..656703c1999 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -951,3 +951,37 @@ select * from t1; mot topic date pseudo joce 1 0000-00-00 joce drop table t1, t2, t3; +SELECT * FROM (SELECT 1 as a,(SELECT a)) a; +a (SELECT a) +1 1 +CREATE TABLE t1 SELECT * FROM (SELECT 1 as a,(SELECT 1)) a; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` bigint(1) NOT NULL default '0', + `(SELECT 1)` bigint(1) NOT NULL default '0' +) TYPE=MyISAM CHARSET=latin1 +drop table t1; +CREATE TABLE t1 SELECT * FROM (SELECT 1 as a,(SELECT a)) a; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` bigint(1) NOT NULL default '0', + `(SELECT a)` bigint(1) NOT NULL default '0' +) TYPE=MyISAM CHARSET=latin1 +drop table t1; +CREATE TABLE t1 SELECT * FROM (SELECT 1 as a,(SELECT a+0)) a; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` bigint(1) NOT NULL default '0', + `(SELECT a+0)` bigint(17) NOT NULL default '0' +) TYPE=MyISAM CHARSET=latin1 +drop table t1; +CREATE TABLE t1 SELECT (SELECT 1 as a UNION SELECT 1+1 limit 1,1) as a; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` bigint(17) NOT NULL default '0' +) TYPE=MyISAM CHARSET=latin1 +drop table t1; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index da9d7330c46..9a4c5590cc1 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -558,4 +558,18 @@ DELETE FROM t1 WHERE topic IN (SELECT DISTINCT topic FROM t2 WHERE NOT EXISTS(SELECT * FROM t3 WHERE numeropost=topic)); select * from t1; -drop table t1, t2, t3;
\ No newline at end of file +drop table t1, t2, t3; + +SELECT * FROM (SELECT 1 as a,(SELECT a)) a; +CREATE TABLE t1 SELECT * FROM (SELECT 1 as a,(SELECT 1)) a; +SHOW CREATE TABLE t1; +drop table t1; +CREATE TABLE t1 SELECT * FROM (SELECT 1 as a,(SELECT a)) a; +SHOW CREATE TABLE t1; +drop table t1; +CREATE TABLE t1 SELECT * FROM (SELECT 1 as a,(SELECT a+0)) a; +SHOW CREATE TABLE t1; +drop table t1; +CREATE TABLE t1 SELECT (SELECT 1 as a UNION SELECT 1+1 limit 1,1) as a; +SHOW CREATE TABLE t1; +drop table t1; diff --git a/sql/item.cc b/sql/item.cc index 9f96ad0f0f5..09244d95806 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -633,7 +633,8 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) uint counter= 0; // Prevent using outer fields in subselects, that is not supported now SELECT_LEX *cursel=(SELECT_LEX *) thd->lex.current_select; - if (cursel->master_unit()->first_select()->linkage != DERIVED_TABLE_TYPE) + if (outer_resolving || + cursel->master_unit()->first_select()->linkage != DERIVED_TABLE_TYPE) for (SELECT_LEX *sl=(outer_resolving?cursel:cursel->outer_select()); sl; sl= sl->outer_select()) @@ -1184,10 +1185,6 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) } ref= thd->lex.current_select->ref_pointer_array + counter-1; } - - max_length= (*ref)->max_length; - maybe_null= (*ref)->maybe_null; - decimals= (*ref)->decimals; } if (((*ref)->with_sum_func && @@ -1202,6 +1199,9 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) "forward reference in item list")); return 1; } + max_length= (*ref)->max_length; + maybe_null= (*ref)->maybe_null; + decimals= (*ref)->decimals; fixed= 1; if (ref && (*ref)->check_cols(1)) return 1; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index ffb4d715159..9a3019ece12 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -161,7 +161,7 @@ void Item_singlerow_subselect::select_transformer(THD *thd, select_lex->item_list.elements == 1 && // TODO: mark subselect items from item list separately !(select_lex->item_list.head()->type() == FIELD_ITEM || - select_lex->item_list.head()->type() == REF_ITEM) + select_lex->item_list.head()->type() == REF_ITEM) ) { @@ -693,7 +693,7 @@ int subselect_single_select_engine::prepare() (ORDER*) select_lex->group_list.first, select_lex->having, (ORDER*) 0, select_lex, - select_lex->master_unit(), 0)) + select_lex->master_unit(), 0, 0)) return 1; thd->lex.current_select= save_select; return 0; @@ -701,7 +701,7 @@ int subselect_single_select_engine::prepare() int subselect_union_engine::prepare() { - return unit->prepare(thd, result); + return unit->prepare(thd, result, 0); } static Item_result set_row(SELECT_LEX *select_lex, Item * item, diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 978678fa975..026c521adb5 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -403,7 +403,8 @@ int mysql_select(THD *thd, Item ***rref_pointer_array, COND *conds, uint og_num, ORDER *order, ORDER *group, Item *having, ORDER *proc_param, ulong select_type, select_result *result, SELECT_LEX_UNIT *unit, - SELECT_LEX *select_lex, bool fake_select_lex); + SELECT_LEX *select_lex, bool fake_select_lex, + bool tables_OK); void free_ulderlayed_joins(THD *thd, SELECT_LEX *select); void fix_tables_pointers(SELECT_LEX *select_lex); void fix_tables_pointers(SELECT_LEX_UNIT *select_lex); @@ -411,7 +412,8 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result); int mysql_explain_select(THD *thd, SELECT_LEX *sl, char const *type, select_result *result); -int mysql_union(THD *thd, LEX *lex,select_result *result,SELECT_LEX_UNIT *unit); +int mysql_union(THD *thd, LEX *lex, select_result *result, + SELECT_LEX_UNIT *unit, bool tables_OK); int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t); Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, Item_result_field ***copy_func, Field **from_field, diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 8fc3314b69f..d1a232c35b6 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -106,17 +106,22 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t) fix_tables_pointers(unit); } - Item *item; - List_iterator<Item> it(sl->item_list); - - while ((item= it++)) - item_list.push_back(item); - - lex->current_select= sl; TABLE_LIST *first_table= (TABLE_LIST*) sl->table_list.first; - if (setup_wild(thd, first_table, item_list, 0, sl->with_wild) || - setup_fields(thd, 0, first_table, item_list, 0, 0, 1)) + if (setup_tables(first_table) || + setup_wild(thd, first_table, sl->item_list, 0, sl->with_wild)) + { + res= -1; + goto exit; + } + + item_list= sl->item_list; + sl->with_wild= 0; + if (setup_ref_array(thd, &sl->ref_pointer_array, + (item_list.elements + sl->with_sum_func + + sl->order_list.elements + sl->group_list.elements)) || + setup_fields(thd, sl->ref_pointer_array, first_table, item_list, + 0, 0, 1)) { res= -1; goto exit; @@ -145,7 +150,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t) sl->options&= ~OPTION_FOUND_ROWS; if (is_union) - res= mysql_union(thd, lex, derived_result, unit); + res= mysql_union(thd, lex, derived_result, unit, 1); else res= mysql_select(thd, &sl->ref_pointer_array, (TABLE_LIST*) sl->table_list.first, @@ -156,7 +161,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t) (ORDER *) sl->group_list.first, sl->having, (ORDER*) NULL, sl->options | thd->options | SELECT_NO_UNLOCK, - derived_result, unit, sl, 0); + derived_result, unit, sl, 0, 1); if (!res) { diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 1cd38cf9f67..7e858d13ccf 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -312,7 +312,7 @@ public: void exclude_level(); /* UNION methods */ - int prepare(THD *thd, select_result *result); + int prepare(THD *thd, select_result *result, bool tables_OK); int exec(); int cleanup(); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index eda2cbb69ce..430bfb35b3e 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2387,7 +2387,7 @@ mysql_execute_command(THD *thd) (ORDER *)NULL, select_lex->options | thd->options | SELECT_NO_JOIN_CACHE, - result, unit, select_lex, 0); + result, unit, select_lex, 0, 0); if (thd->net.report_error) res= -1; delete result; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 830848ce0c8..1d886949633 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -568,7 +568,7 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables, if (join->prepare(&select_lex->ref_pointer_array, tables, wild_num, conds, og_num, order, group, having, proc, - select_lex, unit, 0)) + select_lex, unit, 0, 0)) DBUG_RETURN(1); /* diff --git a/sql/sql_select.cc b/sql/sql_select.cc index e2568dda625..5417984977d 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -169,7 +169,7 @@ int handle_select(THD *thd, LEX *lex, select_result *result) register SELECT_LEX *select_lex = &lex->select_lex; fix_tables_pointers(lex->all_selects_list); if (select_lex->next_select()) - res=mysql_union(thd,lex,result,&lex->unit); + res=mysql_union(thd, lex, result, &lex->unit, 0); else res= mysql_select(thd, &select_lex->ref_pointer_array, (TABLE_LIST*) select_lex->table_list.first, @@ -182,7 +182,7 @@ int handle_select(THD *thd, LEX *lex, select_result *result) select_lex->having, (ORDER*) lex->proc_list.first, select_lex->options | thd->options, - result, &(lex->unit), &(lex->select_lex), 0); + result, &(lex->unit), &(lex->select_lex), 0, 0); if (res && result) result->abort(); @@ -267,7 +267,8 @@ JOIN::prepare(Item ***rref_pointer_array, ORDER *order_init, ORDER *group_init, Item *having_init, ORDER *proc_param_init, SELECT_LEX *select, - SELECT_LEX_UNIT *unit, bool fake_select_lex) + SELECT_LEX_UNIT *unit, + bool fake_select_lex, bool tables_OK) { DBUG_ENTER("JOIN::prepare"); @@ -284,8 +285,9 @@ JOIN::prepare(Item ***rref_pointer_array, /* Check that all tables, fields, conds and order are ok */ - if (setup_tables(tables_list) || - setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) || + if ((tables_OK?0:(setup_tables(tables_list) || + setup_wild(thd, tables_list, fields_list, + &all_fields, wild_num))) || setup_ref_array(thd, rref_pointer_array, (fields_list.elements + select_lex->with_sum_func + og_num)) || @@ -1296,7 +1298,7 @@ mysql_select(THD *thd, Item ***rref_pointer_array, COND *conds, uint og_num, ORDER *order, ORDER *group, Item *having, ORDER *proc_param, ulong select_options, select_result *result, SELECT_LEX_UNIT *unit, - SELECT_LEX *select_lex, bool fake_select_lex) + SELECT_LEX *select_lex, bool fake_select_lex, bool tables_OK) { int err; bool free_join= 1; @@ -1323,7 +1325,7 @@ mysql_select(THD *thd, Item ***rref_pointer_array, if (join->prepare(rref_pointer_array, tables, wild_num, conds, og_num, order, group, having, proc_param, - select_lex, unit, fake_select_lex)) + select_lex, unit, fake_select_lex, tables_OK)) { DBUG_RETURN(-1); } @@ -8065,7 +8067,7 @@ int mysql_explain_select(THD *thd, SELECT_LEX *select_lex, char const *type, select_lex->having, (ORDER*) thd->lex.proc_list.first, select_lex->options | thd->options | SELECT_DESCRIBE, - result, unit, select_lex, 0); + result, unit, select_lex, 0, 0); DBUG_RETURN(res); } diff --git a/sql/sql_select.h b/sql/sql_select.h index 934a3b72734..38e8a5d96f9 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -256,7 +256,7 @@ class JOIN :public Sql_alloc int prepare(Item ***rref_pointer_array, TABLE_LIST *tables, uint wind_num, COND *conds, uint og_num, ORDER *order, ORDER *group, Item *having, ORDER *proc_param, SELECT_LEX *select, - SELECT_LEX_UNIT *unit, bool fake_select_lex); + SELECT_LEX_UNIT *unit, bool fake_select_lex, bool tables_OK); int optimize(); int reinit(); void exec(); diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 259f6dbb4b5..dde0251d0c2 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -24,11 +24,12 @@ #include "mysql_priv.h" #include "sql_select.h" -int mysql_union(THD *thd, LEX *lex, select_result *result,SELECT_LEX_UNIT *unit) +int mysql_union(THD *thd, LEX *lex, select_result *result, + SELECT_LEX_UNIT *unit, bool tables_OK) { DBUG_ENTER("mysql_union"); int res= 0; - if (!(res= unit->prepare(thd, result))) + if (!(res= unit->prepare(thd, result, tables_OK))) res= unit->exec(); res|= unit->cleanup(); DBUG_RETURN(res); @@ -107,7 +108,8 @@ bool select_union::flush() return 0; } -int st_select_lex_unit::prepare(THD *thd, select_result *result) +int st_select_lex_unit::prepare(THD *thd, select_result *result, + bool tables_OK) { DBUG_ENTER("st_select_lex_unit::prepare"); @@ -121,7 +123,7 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result) SELECT_LEX_NODE *lex_select_save= thd->lex.current_select; SELECT_LEX *sl; - thd->lex.current_select=first_select(); + thd->lex.current_select= sl= first_select(); /* Global option */ if (((void*)(global_parameters)) == ((void*)this)) { @@ -130,20 +132,28 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result) if (found_rows_for_union) first_select()->options ^= OPTION_FOUND_ROWS; } - item_list.empty(); + if (tables_OK) { - Item *item; - List_iterator<Item> it(first_select()->item_list); + item_list= sl->item_list; + } + else + { + item_list.empty(); TABLE_LIST *first_table= (TABLE_LIST*) first_select()->table_list.first; - /* Create a list of items that will be in the result set */ - while ((item= it++)) - if (item_list.push_back(item)) - goto err; - if (setup_wild(thd, first_table, item_list, 0, - first_select()->with_wild) || - setup_fields(thd, 0, first_table, item_list, 0, 0, 1)) + if (setup_tables(first_table) || + setup_wild(thd, first_table, sl->item_list, 0, sl->with_wild)) + goto err; + + item_list= sl->item_list; + sl->with_wild= 0; + if (setup_ref_array(thd, &sl->ref_pointer_array, + (item_list.elements + sl->with_sum_func + + sl->order_list.elements + sl->group_list.elements)) || + setup_fields(thd, sl->ref_pointer_array, first_table, item_list, + 0, 0, 1)) goto err; + tables_OK= 1; } bzero((char*) &tmp_table_param,sizeof(tmp_table_param)); @@ -191,11 +201,25 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result) (ORDER*) sl->group_list.first, sl->having, (ORDER*) NULL, - sl, this, 0); + sl, this, 0, tables_OK); + tables_OK= 0; if (res | thd->fatal_error) goto err; } + item_list.empty(); thd->lex.current_select= lex_select_save; + { + List_iterator<Item> it(first_select()->item_list); + Field **field; + + for (field= table->field; *field; field++) + { + (void) it++; + if (item_list.push_back(new Item_field(*field))) + DBUG_RETURN(-1); + } + } + DBUG_RETURN(res | thd->fatal_error); err: thd->lex.current_select= lex_select_save; @@ -260,9 +284,6 @@ int st_select_lex_unit::exec() thd->lex.current_select = first_select(); res =-1; { - /* Create a list of fields in the temporary table */ - List_iterator<Item> it(item_list); - Field **field; #if 0 List<Item_func_match> ftfunc_list; ftfunc_list.empty(); @@ -272,11 +293,6 @@ int st_select_lex_unit::exec() thd->lex.select_lex.ftfunc_list= &empty_list; #endif - for (field=table->field ; *field ; field++) - { - (void) it++; - (void) it.replace(new Item_field(*field)); - } if (!thd->fatal_error) // Check if EOM { SELECT_LEX *sl=thd->lex.current_select->master_unit()->first_select(); @@ -292,7 +308,7 @@ int st_select_lex_unit::exec() global_parameters->order_list.elements, (ORDER*)global_parameters->order_list.first, (ORDER*) NULL, NULL, (ORDER*) NULL, - thd->options, result, this, first_select(), 1); + thd->options, result, this, first_select(), 1, 0); if (found_rows_for_union && !res) thd->limit_found_rows = (ulonglong)table->file->records; } diff --git a/sql/sql_update.cc b/sql/sql_update.cc index f2f1c0da0d9..8836564c6d4 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -428,7 +428,7 @@ int mysql_multi_update(THD *thd, conds, 0, (ORDER *) NULL, (ORDER *)NULL, (Item *) NULL, (ORDER *)NULL, options | SELECT_NO_JOIN_CACHE, - result, unit, select_lex, 0); + result, unit, select_lex, 0, 0); delete result; DBUG_RETURN(res); } |