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