diff options
-rw-r--r-- | client/mysql.cc | 2 | ||||
-rw-r--r-- | libmysql/libmysql.c | 3 | ||||
-rw-r--r-- | mysql-test/r/subselect.result | 2 | ||||
-rw-r--r-- | mysql-test/r/union.result | 27 | ||||
-rw-r--r-- | mysql-test/t/union.test | 17 | ||||
-rwxr-xr-x | scripts/fill_func_tables.sh | 234 | ||||
-rw-r--r-- | sql/sql_derived.cc | 67 | ||||
-rw-r--r-- | sql/sql_lex.h | 3 | ||||
-rw-r--r-- | sql/sql_union.cc | 125 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 4 |
10 files changed, 400 insertions, 84 deletions
diff --git a/client/mysql.cc b/client/mysql.cc index 75d67afab3f..2ca1afdb93a 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1036,7 +1036,7 @@ static bool add_line(String &buffer,char *line,char *in_string, inchar == '-' && pos[1] == '-' && my_isspace(system_charset_info,pos[2])))) break; // comment to end of line - else if (!*in_string && inchar == '/' && *(pos+1) == '*') + else if (!*in_string && inchar == '/' && *(pos+1) == '*' && *(pos+2) != '!') { pos++; *ml_comment= 1; diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 25da7d48ad7..9f113f4c1b6 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -1225,6 +1225,9 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields, field->def=strdup_root(alloc,(char*) row->data[6]); field->def_length= lengths[6]; } + else + field->def=0; + field->max_length= 0; } } #ifndef DELETE_SUPPORT_OF_4_0_PROTOCOL diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 0d8c96fea85..47f24a340cd 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -1000,7 +1000,7 @@ 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' + `a` bigint(1) NOT NULL default '0' ) TYPE=MyISAM CHARSET=latin1 drop table t1; create table t1 (a int); diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index cb3a8029a87..cf166f47f35 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -203,3 +203,30 @@ No tables used select 1 as a,(select a union select a); a (select a union select a) 1 1 +drop table if exists t1,t2; +CREATE TABLE t1 ( id int(3) unsigned default '0') TYPE=MyISAM; +INSERT INTO t1 (id) VALUES("1"); +CREATE TABLE t2 ( id int(3) unsigned default '0', id_master int(5) default '0', text1 varchar(5) default NULL, text2 varchar(5) default NULL) TYPE=MyISAM; +INSERT INTO t2 (id, id_master, text1, text2) VALUES("1", "1", +"foo1", "bar1"); +INSERT INTO t2 (id, id_master, text1, text2) VALUES("2", "1", +"foo2", "bar2"); +INSERT INTO t2 (id, id_master, text1, text2) VALUES("3", "1", NULL, +"bar3"); +INSERT INTO t2 (id, id_master, text1, text2) VALUES("4", "1", +"foo4", "bar4"); +SELECT 1 AS id_master, 1 AS id, NULL AS text1, 'ABCDE' AS text2 UNION SELECT id_master, t2.id, text1, text2 FROM t1 LEFT JOIN t2 ON t1.id = t2.id_master; +id_master id text1 text2 +1 1 NULL ABCDE +1 1 bar1 +1 2 bar2 +1 3 NULL bar3 +1 4 bar4 +SELECT 1 AS id_master, 1 AS id, 'ABCDE' AS text1, 'ABCDE' AS text2 UNION SELECT id_master, t2.id, text1, text2 FROM t1 LEFT JOIN t2 ON t1.id = t2.id_master; +id_master id text1 text2 +1 1 ABCDE ABCDE +1 1 foo1 bar1 +1 2 foo2 bar2 +1 3 NULL bar3 +1 4 foo4 bar4 +drop table if exists t1,t2; diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test index b46f54c5c41..af2dd154974 100644 --- a/mysql-test/t/union.test +++ b/mysql-test/t/union.test @@ -107,3 +107,20 @@ drop table t1,t2; --error 1096 select * union select 1; select 1 as a,(select a union select a); +--disable_warnings +drop table if exists t1,t2; +--enable_warnings +CREATE TABLE t1 ( id int(3) unsigned default '0') TYPE=MyISAM; +INSERT INTO t1 (id) VALUES("1"); +CREATE TABLE t2 ( id int(3) unsigned default '0', id_master int(5) default '0', text1 varchar(5) default NULL, text2 varchar(5) default NULL) TYPE=MyISAM; +INSERT INTO t2 (id, id_master, text1, text2) VALUES("1", "1", +"foo1", "bar1"); +INSERT INTO t2 (id, id_master, text1, text2) VALUES("2", "1", +"foo2", "bar2"); +INSERT INTO t2 (id, id_master, text1, text2) VALUES("3", "1", NULL, +"bar3"); +INSERT INTO t2 (id, id_master, text1, text2) VALUES("4", "1", +"foo4", "bar4"); +SELECT 1 AS id_master, 1 AS id, NULL AS text1, 'ABCDE' AS text2 UNION SELECT id_master, t2.id, text1, text2 FROM t1 LEFT JOIN t2 ON t1.id = t2.id_master; +SELECT 1 AS id_master, 1 AS id, 'ABCDE' AS text1, 'ABCDE' AS text2 UNION SELECT id_master, t2.id, text1, text2 FROM t1 LEFT JOIN t2 ON t1.id = t2.id_master; +drop table if exists t1,t2; diff --git a/scripts/fill_func_tables.sh b/scripts/fill_func_tables.sh new file mode 100755 index 00000000000..459afee2fe1 --- /dev/null +++ b/scripts/fill_func_tables.sh @@ -0,0 +1,234 @@ +#!/usr/bin/perl +# fill_func_tables - parse ../Docs/manual.texi + +# Original version by vva + +my $cat_name= ""; +my $func_name= ""; +my $text= ""; +my $example= ""; + +local $mode= ""; + +sub prepare_name +{ + my ($a)= @_; + + $a =~ s/(\@itemize \@bullet)/ /g; + $a =~ s/(\@end itemize)/ /g; + $a =~ s/(\@end multitable)/ /g; + $a =~ s/(\@end table)/ /g; + $a =~ s/(\@cindex(.*?)\n)/ /g; + $a =~ s/(\@multitable \@columnfractions(.*?)\n)/ /g; + $a =~ s/(\@node(.*?)\n)/ /g; + $a =~ s/(\@tab)/\t/g; + $a =~ s/\@item/ /g; + $a =~ s/\@code\{((.|\n)+?)\}/$1/go; + $a =~ s/\@strong\{(.+?)\}/$1/go; + $a =~ s/\@samp\{(.+?)\}/$1/go; + $a =~ s/\@emph\{((.|\n)+?)\}/\/$1\//go; + $a =~ s/\@xref\{((.|\n)+?)\}/See also : [$1]/go; + $a =~ s/\@ref\{((.|\n)+?)\}/[$1]/go; + $a =~ s/\'/\'\'/g; + $a =~ s/\\/\\\\/g; + $a =~ s/\`/\`\`/g; + + $a =~ s/\@table \@code/ /g; + + $a =~ s/\(\)//g; + + $a =~ s/((\w|\s)+)\(([\+-=><\/%*!<>\s]+)\)/$3/gxs; #$a =~ s/((\w|\s)+)\(([\+-=><\/%*!<>\s]+)\)/$3 $1/gxs; + $a =~ s/([\+-=><\/%*!<>\s]+)\(((\w|\s)+)\)/$1/gxs;#$a =~ s/([\+-=><\/%*!<>\s]+)\(((\w|\s)+)\)/$1 $2/gxs; + $a =~ s/((\w|\s)+)\((.+)\)/$1/gxs; + + return $a; +} + +sub prepare_text +{ + my ($a)= @_; + + $a =~ s/(\@itemize \@bullet)/ /g; + $a =~ s/(\@end itemize)/ /g; + $a =~ s/(\@end multitable)/ /g; + $a =~ s/(\@end table)/ /g; + $a =~ s/(\@cindex(.*?)\n)/ /g; + $a =~ s/(\@multitable \@columnfractions(.*?)\n)/ /g; + $a =~ s/(\@node(.*?)\n)/ /g; + $a =~ s/(\@tab)/\t/g; + $a =~ s/\@itemx/ /g; + $a =~ s/\@item/ /g; + $a =~ s/\@code\{((.|\n)+?)\}/$1/go; + $a =~ s/\@strong\{(.+?)\}/$1/go; + $a =~ s/\@samp\{(.+?)\}/$1/go; + $a =~ s/\@emph\{((.|\n)+?)\}/\/$1\//go; + $a =~ s/\@xref\{((.|\n)+?)\}/See also : [$1]/go; + $a =~ s/\@ref\{((.|\n)+?)\}/[$1]/go; + $a =~ s/\'/\'\'/g; + $a =~ s/\\/\\\\/g; + $a =~ s/\`/\`\`/g; + $a =~ s/(\n*?)$//g; + $a =~ s/\n/\\n/g; + + $a =~ s/\@table \@code/ /g; + + return $a; +} + +sub prepare_example +{ + my ($a)= @_; + + $a =~ s/\'/\'\'/g; + $a =~ s/\\/\\\\/g; + $a =~ s/\`/\`\`/g; + $a =~ s/(\n*?)$//g; + $a =~ s/\n/\\n/g; + + return $a; +} + +sub flush_all +{ + my ($mode) = @_; + + if ($mode eq ""){return;} + + $func_name= prepare_name($func_name); + $text= prepare_text($text); + $example= prepare_example($example); + + if ($func_name ne "" && $text ne "" && !($func_name =~ /[abcdefghikjlmnopqrstuvwxyz]/)){ + print "INSERT INTO function (name,description,example) VALUES ("; + print "'$func_name',"; + print "'$text',"; + print "'$example'"; + print ");\n"; + print "INSERT INTO function_category (cat_id,func_id) VALUES (\@cur_category,LAST_INSERT_ID());\n"; + } + + $func_name= ""; + $text= ""; + $example= ""; + $mode= ""; +} + +sub new_category +{ + my ($category)= @_; + + $category= prepare_text($category); + + print "INSERT INTO function_category_name (name) VALUES (\'$category\');\n"; + print "SELECT \@cur_category:=LAST_INSERT_ID();\n"; +} + +print "INSERT INTO db (Host,DB,User,Select_priv) VALUES ('%','mysql_help','','Y');\n"; +print "CREATE DATABASE mysql_help;\n"; + +print "USE mysql_help;\n"; + +print "DROP TABLE IF EXISTS function;\n"; +print "CREATE TABLE function ("; +print " func_id int unsigned not null auto_increment,"; +print " name varchar(64) not null,"; +print " url varchar(128) not null,"; +print " description text not null,"; +print " example text not null,"; +print " min_args tinyint not null,"; +print " max_args tinyint,"; +print " date_created datetime not null,"; +print " last_modified timestamp not null,"; +print " primary key (func_id)"; +print ") type=myisam;\n\n"; + +print "DROP TABLE IF EXISTS function_category_name;\n"; +print "CREATE TABLE function_category_name ("; +print " cat_id smallint unsigned not null auto_increment,"; +print " name varchar(64) not null,"; +print " url varchar(128) not null,"; +print " date_created datetime not null,"; +print " last_modified timestamp not null,"; +print " primary key (cat_id)"; +print ") type=myisam;\n\n"; + +print "DROP TABLE IF EXISTS function_category;\n"; +print "CREATE TABLE function_category ("; +print " cat_id smallint unsigned not null references function_category_name,"; +print " func_id int unsigned not null references function,"; +print " primary key (cat_id, func_id)"; +print ") type=myisam;\n\n"; + +print "DELETE FROM function_category_name;\n"; +print "DELETE FROM function_category;\n"; +print "DELETE FROM function;\n"; +print "SELECT \@cur_category:=null;\n\n"; + +my $in_section_6_3= 0; + +for(<>) +{ + if ($_=~/\@section Functions for Use in \@code{SELECT} and \@code{WHERE} Clauses/ && + !$in_section_6_3){ + $in_section_6_3= 1; + next; + } + + if ($_=~/\@section/ && $in_section_6_3){ + $in_section_6_3= 0; + next; + } + + if (!$in_section_6_3) { next; } + + my $c_name= ""; + + ($c_name)=m|\@c for_mysql_help,(.+?)$|; + if (!($c_name eq "") && ! ($c_name =~ m/$cat_name/i)){ + ($cat_name)= $c_name; + new_category($cat_name); + next; + } + + ($c_name)=m|\@subsubsection (.+?)$|; + if (!($c_name eq "") && ! ($c_name =~ m/$cat_name/i)){ + ($cat_name)= $c_name; + new_category($cat_name); + next; + } + + ($c_name)=m|\@subsection (.+?)$|; + if (!($c_name eq "") && ! ($c_name =~ m/$cat_name/i)){ + ($cat_name)= $c_name; + new_category($cat_name); + next; + } + + ($f_name)=m|\@findex (.+?)$|; + if (!($f_name eq "")){ + flush_all($mode); + ($func_name)= ($f_name); + $mode= "text"; + next; + } + + if ($_=~/\@example/ && ($mode eq "text")){ + $mode= "example"; + next; + } + + if ($_=~/\@end example/ && ($mode eq "example")){ + flush_all($mode); + next; + } + + if ($mode eq "text") { $text .= $_; } + if ($mode eq "example") { $example .= $_; } +} + + +print "DELETE function_category_name "; +print "FROM function_category_name "; +print "LEFT JOIN function_category ON function_category.cat_id=function_category_name.cat_id "; +print "WHERE function_category.cat_id is null;" + diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 406a534daea..c0a4436a059 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -64,15 +64,16 @@ extern const char *any_db; // Special symbol for check_access int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *org_table_list) { - SELECT_LEX *sl= unit->first_select(); + SELECT_LEX *select_cursor= unit->first_select(); List<Item> item_list; TABLE *table; int res; select_union *derived_result; - TABLE_LIST *tables= (TABLE_LIST *)sl->table_list.first; + TABLE_LIST *tables= (TABLE_LIST *)select_cursor->table_list.first; TMP_TABLE_PARAM tmp_table_param; - bool is_union= sl->next_select() ? 1 : 0; - bool is_subsel= sl->first_inner_unit() ? 1: 0; + bool is_union= select_cursor->next_select() && + select_cursor->next_select()->linkage == UNION_TYPE; + bool is_subsel= select_cursor->first_inner_unit() ? 1: 0; SELECT_LEX_NODE *save_current_select= lex->current_select; DBUG_ENTER("mysql_derived"); @@ -111,21 +112,23 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, fix_tables_pointers(unit); } - lex->current_select= sl; - TABLE_LIST *first_table= (TABLE_LIST*) sl->table_list.first; + lex->current_select= select_cursor; + TABLE_LIST *first_table= (TABLE_LIST*) select_cursor->table_list.first; + /* Setting up. A must if a join or IGNORE, USE or similar are utilised */ if (setup_tables(first_table) || - setup_wild(thd, first_table, sl->item_list, 0, sl->with_wild)) + setup_wild(thd, first_table, select_cursor->item_list, 0, select_cursor->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, + item_list= select_cursor->item_list; + select_cursor->with_wild= 0; + if (setup_ref_array(thd, &select_cursor->ref_pointer_array, + (item_list.elements + select_cursor->with_sum_func + + select_cursor->order_list.elements + + select_cursor->group_list.elements)) || + setup_fields(thd, select_cursor->ref_pointer_array, first_table, item_list, 0, 0, 1)) { res= -1; @@ -133,10 +136,12 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, } bzero((char*) &tmp_table_param,sizeof(tmp_table_param)); tmp_table_param.field_count= item_list.elements; + /* temp table is created so that it hounours if UNION without ALL is to be + processed */ if (!(table= create_tmp_table(thd, &tmp_table_param, item_list, (ORDER*) 0, is_union && !unit->union_option, 1, - (sl->options | thd->options | + (select_cursor->options | thd->options | TMP_TABLE_ALL_COLUMNS), HA_POS_ERROR))) { @@ -147,26 +152,27 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, if ((derived_result=new select_union(table))) { derived_result->tmp_table_param=&tmp_table_param; - unit->offset_limit_cnt= sl->offset_limit; - unit->select_limit_cnt= sl->select_limit+sl->offset_limit; - if (unit->select_limit_cnt < sl->select_limit) + unit->offset_limit_cnt= select_cursor->offset_limit; + unit->select_limit_cnt= select_cursor->select_limit+ + select_cursor->offset_limit; + if (unit->select_limit_cnt < select_cursor->select_limit) unit->select_limit_cnt= HA_POS_ERROR; if (unit->select_limit_cnt == HA_POS_ERROR) - sl->options&= ~OPTION_FOUND_ROWS; + select_cursor->options&= ~OPTION_FOUND_ROWS; if (is_union) res= mysql_union(thd, lex, derived_result, unit, 1); else - res= mysql_select(thd, &sl->ref_pointer_array, - (TABLE_LIST*) sl->table_list.first, - sl->with_wild, - sl->item_list, sl->where, - sl->order_list.elements+sl->group_list.elements, - (ORDER *) sl->order_list.first, - (ORDER *) sl->group_list.first, - sl->having, (ORDER*) NULL, - sl->options | thd->options | SELECT_NO_UNLOCK, - derived_result, unit, sl, 0, 1); + res= mysql_select(thd, &select_cursor->ref_pointer_array, + (TABLE_LIST*) select_cursor->table_list.first, + select_cursor->with_wild, + select_cursor->item_list, select_cursor->where, + select_cursor->order_list.elements+select_cursor->group_list.elements, + (ORDER *) select_cursor->order_list.first, + (ORDER *) select_cursor->group_list.first, + select_cursor->having, (ORDER*) NULL, + select_cursor->options | thd->options | SELECT_NO_UNLOCK, + derived_result, unit, select_cursor, 0, 1); if (!res) { @@ -180,7 +186,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, { org_table_list->real_name=table->real_name; org_table_list->table=table; - table->derived_select_number= sl->select_number; + table->derived_select_number= select_cursor->select_number; table->tmp_table= TMP_TABLE; if (lex->describe) { @@ -189,12 +195,13 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, tables->table_list->table=tables->table; } else - unit->exclude(); + unit->exclude_level(); org_table_list->db= (char *)""; #ifndef DBUG_OFF /* Try to catch errors if this is accessed */ org_table_list->derived=(SELECT_LEX_UNIT *) 1; #endif +// This line is required to force read of table stats in the optimizer table->file->info(HA_STATUS_VARIABLE); } } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 60f48f293e4..aff3485dbe4 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -289,7 +289,8 @@ protected: bool describe, found_rows_for_union, prepared, // prepare phase already performed for UNION (unit) optimized, // optimize phase already performed for UNION (unit) - executed; // already executed + executed, // already executed + t_and_f; // used for transferring tables_and_fields_initied UNIT:: methods public: /* Pointer to 'last' select or pointer to unit where stored diff --git a/sql/sql_union.cc b/sql/sql_union.cc index bc1449aeda0..feaa8371acb 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -120,6 +120,7 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result, found_rows_for_union= 0; TMP_TABLE_PARAM tmp_table_param; this->result= result; + t_and_f= tables_and_fields_initied; SELECT_LEX_NODE *lex_select_save= thd->lex.current_select; SELECT_LEX *sl; @@ -132,7 +133,7 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result, if (found_rows_for_union) first_select()->options ^= OPTION_FOUND_ROWS; } - if (tables_and_fields_initied) + if (t_and_f) { // Item list and tables will be initialized by mysql_derived item_list= sl->item_list; @@ -145,7 +146,10 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result, if (setup_tables(first_table) || setup_wild(thd, first_table, sl->item_list, 0, sl->with_wild)) goto err; - + List_iterator<Item> it(sl->item_list); + Item *item; + while((item=it++)) + item->maybe_null=1; item_list= sl->item_list; sl->with_wild= 0; if (setup_ref_array(thd, &sl->ref_pointer_array, @@ -154,7 +158,7 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result, setup_fields(thd, sl->ref_pointer_array, first_table, item_list, 0, 0, 1)) goto err; - tables_and_fields_initied= 1; + t_and_f= 1; } bzero((char*) &tmp_table_param,sizeof(tmp_table_param)); @@ -177,35 +181,36 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result, union_result->not_describe=1; union_result->tmp_table_param=&tmp_table_param; - - // prepare selects - for (sl= first_select(); sl; sl= sl->next_select()) + if (thd->lex.describe) { - JOIN *join= new JOIN(thd, sl->item_list, - sl->options | thd->options | SELECT_NO_UNLOCK, - union_result); - thd->lex.current_select= sl; - offset_limit_cnt= sl->offset_limit; - select_limit_cnt= sl->select_limit+sl->offset_limit; - if (select_limit_cnt < sl->select_limit) - select_limit_cnt= HA_POS_ERROR; // no limit - if (select_limit_cnt == HA_POS_ERROR) - sl->options&= ~OPTION_FOUND_ROWS; - - res= join->prepare(&sl->ref_pointer_array, - (TABLE_LIST*) sl->table_list.first, sl->with_wild, - sl->where, - ((sl->braces) ? sl->order_list.elements : 0) + - sl->group_list.elements, - (sl->braces) ? - (ORDER *)sl->order_list.first : (ORDER *) 0, - (ORDER*) sl->group_list.first, - sl->having, - (ORDER*) NULL, - sl, this, 0, tables_and_fields_initied); - tables_and_fields_initied= 0; - if (res | thd->is_fatal_error) - goto err; + for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select()) + { + JOIN *join= new JOIN(thd, sl->item_list, + sl->options | thd->options | SELECT_NO_UNLOCK, + union_result); + thd->lex.current_select= sl; + offset_limit_cnt= sl->offset_limit; + select_limit_cnt= sl->select_limit+sl->offset_limit; + if (select_limit_cnt < sl->select_limit) + select_limit_cnt= HA_POS_ERROR; // no limit + if (select_limit_cnt == HA_POS_ERROR) + sl->options&= ~OPTION_FOUND_ROWS; + + res= join->prepare(&sl->ref_pointer_array, + (TABLE_LIST*) sl->table_list.first, sl->with_wild, + sl->where, + ((sl->braces) ? sl->order_list.elements : 0) + + sl->group_list.elements, + (sl->braces) ? + (ORDER *)sl->order_list.first : (ORDER *) 0, + (ORDER*) sl->group_list.first, + sl->having, + (ORDER*) NULL, + sl, this, 0, t_and_f); + t_and_f= 0; + if (res | thd->is_fatal_error) + goto err; + } } item_list.empty(); thd->lex.current_select= lex_select_save; @@ -246,23 +251,49 @@ int st_select_lex_unit::exec() } for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select()) { - thd->lex.current_select= sl; - offset_limit_cnt= sl->offset_limit; - select_limit_cnt= sl->select_limit+sl->offset_limit; - if (select_limit_cnt < sl->select_limit) - select_limit_cnt= HA_POS_ERROR; // no limit - if (select_limit_cnt == HA_POS_ERROR) - sl->options&= ~OPTION_FOUND_ROWS; - - if (!optimized) - res= sl->join->optimize(); - else + if (optimized) res= sl->join->reinit(); - + else + { + JOIN *join= new JOIN(thd, sl->item_list, + sl->options | thd->options | SELECT_NO_UNLOCK, + union_result); + thd->lex.current_select= sl; + offset_limit_cnt= sl->offset_limit; + select_limit_cnt= sl->select_limit+sl->offset_limit; + if (select_limit_cnt < sl->select_limit) + select_limit_cnt= HA_POS_ERROR; // no limit + if (select_limit_cnt == HA_POS_ERROR) + sl->options&= ~OPTION_FOUND_ROWS; + + res= join->prepare(&sl->ref_pointer_array, + (TABLE_LIST*) sl->table_list.first, sl->with_wild, + sl->where, + ((sl->braces) ? sl->order_list.elements : 0) + + sl->group_list.elements, + (sl->braces) ? + (ORDER *)sl->order_list.first : (ORDER *) 0, + (ORDER*) sl->group_list.first, + sl->having, + (ORDER*) NULL, + sl, this, 0, t_and_f); + t_and_f=0; + if (res | thd->is_fatal_error) + { + thd->lex.current_select= lex_select_save; + DBUG_RETURN(res); + } + res= sl->join->optimize(); + } if (!res) { sl->join->exec(); res= sl->join->error; + if (!res && union_result->flush()) + { + thd->lex.current_select= lex_select_save; + DBUG_RETURN(1); + } } if (res) { @@ -270,14 +301,8 @@ int st_select_lex_unit::exec() DBUG_RETURN(res); } } - optimized= 1; - } - - if (union_result->flush()) - { - thd->lex.current_select= lex_select_save; - DBUG_RETURN(1); } + optimized= 1; /* Send result to 'result' */ diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 739e3dd2685..b207d429bd2 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1775,7 +1775,8 @@ select_part2: SELECT_LEX * sel= lex->current_select->select_lex(); if (lex->current_select == &lex->select_lex) lex->lock_option= TL_READ; /* Only for global SELECT */ - mysql_init_select(lex); + if (sel->linkage != UNION_TYPE) + mysql_init_select(lex); } select_options select_item_list select_into select_lock_type; @@ -4656,6 +4657,7 @@ union_list: } if (mysql_new_select(lex, 0)) YYABORT; + mysql_init_select(lex); lex->current_select->linkage=UNION_TYPE; } select_init {} |