fix a bug in derived tables

UNION's bug fixes and code clean-up
parent c75fa953
...@@ -1000,7 +1000,7 @@ CREATE TABLE t1 SELECT (SELECT 1 as a UNION SELECT 1+1 limit 1,1) as a; ...@@ -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; SHOW CREATE TABLE t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`a` bigint(17) NOT NULL default '0' `a` bigint(1) NOT NULL default '0'
) TYPE=MyISAM CHARSET=latin1 ) TYPE=MyISAM CHARSET=latin1
drop table t1; drop table t1;
create table t1 (a int); create table t1 (a int);
......
#!/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;"
...@@ -189,7 +189,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, ...@@ -189,7 +189,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
tables->table_list->table=tables->table; tables->table_list->table=tables->table;
} }
else else
unit->exclude(); unit->exclude_level();
org_table_list->db= (char *)""; org_table_list->db= (char *)"";
#ifndef DBUG_OFF #ifndef DBUG_OFF
/* Try to catch errors if this is accessed */ /* Try to catch errors if this is accessed */
......
...@@ -289,7 +289,7 @@ class st_select_lex_unit: public st_select_lex_node { ...@@ -289,7 +289,7 @@ class st_select_lex_unit: public st_select_lex_node {
bool describe, found_rows_for_union, bool describe, found_rows_for_union,
prepared, // prepare phase already performed for UNION (unit) prepared, // prepare phase already performed for UNION (unit)
optimized, // optimize phase already performed for UNION (unit) optimized, // optimize phase already performed for UNION (unit)
executed; // already executed executed, t_and_f; // already executed
public: public:
/* /*
Pointer to 'last' select or pointer to unit where stored Pointer to 'last' select or pointer to unit where stored
......
...@@ -120,6 +120,7 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result, ...@@ -120,6 +120,7 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result,
found_rows_for_union= 0; found_rows_for_union= 0;
TMP_TABLE_PARAM tmp_table_param; TMP_TABLE_PARAM tmp_table_param;
this->result= result; this->result= result;
t_and_f=tables_and_fields_initied;
SELECT_LEX_NODE *lex_select_save= thd->lex.current_select; SELECT_LEX_NODE *lex_select_save= thd->lex.current_select;
SELECT_LEX *sl; SELECT_LEX *sl;
...@@ -132,7 +133,7 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result, ...@@ -132,7 +133,7 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result,
if (found_rows_for_union) if (found_rows_for_union)
first_select()->options ^= OPTION_FOUND_ROWS; 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 and tables will be initialized by mysql_derived
item_list= sl->item_list; item_list= sl->item_list;
...@@ -154,7 +155,7 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result, ...@@ -154,7 +155,7 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result,
setup_fields(thd, sl->ref_pointer_array, first_table, item_list, setup_fields(thd, sl->ref_pointer_array, first_table, item_list,
0, 0, 1)) 0, 0, 1))
goto err; goto err;
tables_and_fields_initied= 1; t_and_f= 1;
} }
bzero((char*) &tmp_table_param,sizeof(tmp_table_param)); bzero((char*) &tmp_table_param,sizeof(tmp_table_param));
...@@ -177,35 +178,36 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result, ...@@ -177,35 +178,36 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result,
union_result->not_describe=1; union_result->not_describe=1;
union_result->tmp_table_param=&tmp_table_param; union_result->tmp_table_param=&tmp_table_param;
if (thd->lex.describe)
// prepare selects
for (sl= first_select(); sl; sl= sl->next_select())
{ {
JOIN *join= new JOIN(thd, sl->item_list, for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
sl->options | thd->options | SELECT_NO_UNLOCK, {
union_result); JOIN *join= new JOIN(thd, sl->item_list,
thd->lex.current_select= sl; sl->options | thd->options | SELECT_NO_UNLOCK,
offset_limit_cnt= sl->offset_limit; union_result);
select_limit_cnt= sl->select_limit+sl->offset_limit; thd->lex.current_select= sl;
if (select_limit_cnt < sl->select_limit) offset_limit_cnt= sl->offset_limit;
select_limit_cnt= HA_POS_ERROR; // no limit select_limit_cnt= sl->select_limit+sl->offset_limit;
if (select_limit_cnt == HA_POS_ERROR) if (select_limit_cnt < sl->select_limit)
sl->options&= ~OPTION_FOUND_ROWS; select_limit_cnt= HA_POS_ERROR; // no limit
if (select_limit_cnt == HA_POS_ERROR)
res= join->prepare(&sl->ref_pointer_array, sl->options&= ~OPTION_FOUND_ROWS;
(TABLE_LIST*) sl->table_list.first, sl->with_wild,
sl->where, res= join->prepare(&sl->ref_pointer_array,
((sl->braces) ? sl->order_list.elements : 0) + (TABLE_LIST*) sl->table_list.first, sl->with_wild,
sl->group_list.elements, sl->where,
(sl->braces) ? ((sl->braces) ? sl->order_list.elements : 0) +
(ORDER *)sl->order_list.first : (ORDER *) 0, sl->group_list.elements,
(ORDER*) sl->group_list.first, (sl->braces) ?
sl->having, (ORDER *)sl->order_list.first : (ORDER *) 0,
(ORDER*) NULL, (ORDER*) sl->group_list.first,
sl, this, 0, tables_and_fields_initied); sl->having,
tables_and_fields_initied= 0; (ORDER*) NULL,
if (res | thd->is_fatal_error) sl, this, 0, t_and_f);
goto err; t_and_f=0;
if (res | thd->is_fatal_error)
goto err;
}
} }
item_list.empty(); item_list.empty();
thd->lex.current_select= lex_select_save; thd->lex.current_select= lex_select_save;
...@@ -246,23 +248,49 @@ int st_select_lex_unit::exec() ...@@ -246,23 +248,49 @@ int st_select_lex_unit::exec()
} }
for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select()) for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
{ {
thd->lex.current_select= sl; if (optimized)
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
res= sl->join->reinit(); 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) if (!res)
{ {
sl->join->exec(); sl->join->exec();
res= sl->join->error; res= sl->join->error;
if (!res && union_result->flush())
{
thd->lex.current_select= lex_select_save;
DBUG_RETURN(1);
}
} }
if (res) if (res)
{ {
...@@ -270,14 +298,8 @@ int st_select_lex_unit::exec() ...@@ -270,14 +298,8 @@ int st_select_lex_unit::exec()
DBUG_RETURN(res); 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' */ /* Send result to 'result' */
......
...@@ -1775,7 +1775,8 @@ select_part2: ...@@ -1775,7 +1775,8 @@ select_part2:
SELECT_LEX * sel= lex->current_select->select_lex(); SELECT_LEX * sel= lex->current_select->select_lex();
if (lex->current_select == &lex->select_lex) if (lex->current_select == &lex->select_lex)
lex->lock_option= TL_READ; /* Only for global SELECT */ 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; select_options select_item_list select_into select_lock_type;
...@@ -4656,6 +4657,7 @@ union_list: ...@@ -4656,6 +4657,7 @@ union_list:
} }
if (mysql_new_select(lex, 0)) if (mysql_new_select(lex, 0))
YYABORT; YYABORT;
mysql_init_select(lex);
lex->current_select->linkage=UNION_TYPE; lex->current_select->linkage=UNION_TYPE;
} }
select_init {} select_init {}
......
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