summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client/mysql.cc2
-rw-r--r--libmysql/libmysql.c3
-rw-r--r--mysql-test/r/subselect.result2
-rw-r--r--mysql-test/r/union.result27
-rw-r--r--mysql-test/t/union.test17
-rwxr-xr-xscripts/fill_func_tables.sh234
-rw-r--r--sql/sql_derived.cc67
-rw-r--r--sql/sql_lex.h3
-rw-r--r--sql/sql_union.cc125
-rw-r--r--sql/sql_yacc.yy4
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 {}