Commit c0a9df1a authored by unknown's avatar unknown

correct support for a mix of UNION/UNION ALL in the same query.

Bug#1428

parent 78b4ba74
......@@ -36,8 +36,6 @@ a b
1 a
2 b
3 c
3 c
3 c
4 d
5 f
6 e
......@@ -48,8 +46,6 @@ select 0,'#' union select a,b from t1 union all select a,b from t2 union select
1 a
2 b
3 c
3 c
3 c
4 d
5 f
6 e
......@@ -920,5 +916,9 @@ select * from t1 UNION select * from t1 UNION ALL select * from t1;
i
1
1
1
drop table t1;
select 1 as a union all select 1 union all select 2 union select 1 union all select 2;
a
1
2
2
......@@ -493,6 +493,7 @@ create table t1 (i int);
insert into t1 values (1);
select * from t1 UNION select * from t1;
select * from t1 UNION ALL select * from t1;
# The following should return 2 lines
select * from t1 UNION select * from t1 UNION ALL select * from t1;
drop table t1;
select 1 as a union all select 1 union all select 2 union select 1 union all select 2;
......@@ -210,9 +210,6 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset;
#define OPTION_RELAXED_UNIQUE_CHECKS (1L << 27)
#define SELECT_NO_UNLOCK (1L << 28)
/* options for UNION set by the yacc parser (stored in unit->union_option) */
#define UNION_ALL 1
/* Bits for different SQL modes modes (including ANSI mode) */
#define MODE_REAL_AS_FLOAT 1
#define MODE_PIPES_AS_CONCAT 2
......
......@@ -138,7 +138,7 @@ static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
*/
if (!(table= create_tmp_table(thd, &derived_result->tmp_table_param,
unit->types, (ORDER*) 0,
is_union && !unit->union_option, 1,
is_union && unit->union_distinct, 1,
(first_select->options | thd->options |
TMP_TABLE_ALL_COLUMNS),
HA_POS_ERROR,
......
......@@ -997,7 +997,7 @@ void st_select_lex_unit::init_query()
global_parameters= first_select();
select_limit_cnt= HA_POS_ERROR;
offset_limit_cnt= 0;
union_option= 0;
union_distinct= 0;
prepared= optimized= executed= 0;
item= 0;
union_result= 0;
......@@ -1572,7 +1572,7 @@ void st_select_lex_unit::print(String *str)
if (sl != first_select())
{
str->append(" union ", 7);
if (union_option & UNION_ALL)
if (!union_distinct)
str->append("all ", 4);
}
if (sl->braces)
......
......@@ -335,7 +335,7 @@ class st_select_lex_unit: public st_select_lex_node {
/* fake SELECT_LEX for union processing */
st_select_lex *fake_select_lex;
uint union_option;
st_select_lex *union_distinct; /* pointer to the last UNION DISTINCT */
void init_query();
bool create_total_list(THD *thd, st_lex *lex, TABLE_LIST **result);
......
......@@ -210,7 +210,7 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
union_result->tmp_table_param.field_count= types.elements;
if (!(table= create_tmp_table(thd_arg,
&union_result->tmp_table_param, types,
(ORDER*) 0, !union_option, 1,
(ORDER*) 0, union_distinct, 1,
(first_select_in_union()->options |
thd_arg->options |
TMP_TABLE_ALL_COLUMNS),
......@@ -267,6 +267,8 @@ int st_select_lex_unit::exec()
item->reset();
table->file->delete_all_rows();
}
if (union_distinct) // for subselects
table->file->extra(HA_EXTRA_CHANGE_KEY_TO_UNIQUE);
for (SELECT_LEX *sl= select_cursor; sl; sl= sl->next_select())
{
ha_rows records_at_start= 0;
......@@ -317,6 +319,8 @@ int st_select_lex_unit::exec()
{
records_at_start= table->file->records;
sl->join->exec();
if (sl == union_distinct)
table->file->extra(HA_EXTRA_CHANGE_KEY_TO_DUP);
res= sl->join->error;
offset_limit_cnt= sl->offset_limit;
if (!res && union_result->flush())
......
......@@ -611,7 +611,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
udf_type if_exists opt_local opt_table_options table_options
table_option opt_if_not_exists opt_no_write_to_binlog opt_var_type
opt_var_ident_type delete_option opt_temporary all_or_any opt_distinct
opt_ignore_leaves fulltext_options spatial_type
opt_ignore_leaves fulltext_options spatial_type union_option
%type <ulong_num>
ULONG_NUM raid_types merge_insert_types
......@@ -718,7 +718,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
table_to_table_list table_to_table opt_table_list opt_as
handler_rkey_function handler_read_or_scan
single_multi table_wild_list table_wild_one opt_wild
union_clause union_list union_option
union_clause union_list
precision subselect_start opt_and charset
subselect_end select_var_list select_var_list_init help opt_len
opt_extended_describe
......@@ -5571,7 +5571,7 @@ union_clause:
;
union_list:
UNION_SYM union_option
UNION_SYM union_option
{
LEX *lex=Lex;
if (lex->exchange)
......@@ -5589,6 +5589,9 @@ union_list:
YYABORT;
mysql_init_select(lex);
lex->current_select->linkage=UNION_TYPE;
if ($2) /* UNION DISTINCT - remember position */
lex->current_select->master_unit()->union_distinct=
lex->current_select;
}
select_init {}
;
......@@ -5630,9 +5633,10 @@ order_or_limit:
;
union_option:
/* empty */ {}
| DISTINCT {}
| ALL {Select->master_unit()->union_option|= UNION_ALL;};
/* empty */ { $$=1; }
| DISTINCT { $$=1; }
| ALL { $$=0; }
;
singlerow_subselect:
subselect_start singlerow_subselect_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