summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/union.result6
-rw-r--r--mysql-test/t/union.test3
-rw-r--r--sql/sql_delete.cc14
-rw-r--r--sql/sql_parse.cc1
-rw-r--r--sql/sql_union.cc11
-rw-r--r--sql/sql_yacc.yy51
6 files changed, 42 insertions, 44 deletions
diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result
index 3d4b79ea78d..f2572321d61 100644
--- a/mysql-test/r/union.result
+++ b/mysql-test/r/union.result
@@ -68,6 +68,12 @@ t2 c 1
t2 d 1
t2 e 1
t2 f 1
+(select a,b from t1 limit 2) union all (select a,b from t2 order by a) limit 4;
+a b
+1 a
+2 b
+3 c
+4 d
explain select a,b from t1 union all select a,b from t2;
table type possible_keys key key_len ref rows Extra
t1 ALL NULL NULL NULL NULL 4
diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test
index 5c4a62d5c41..dc7e036e258 100644
--- a/mysql-test/t/union.test
+++ b/mysql-test/t/union.test
@@ -16,6 +16,9 @@ select 0,'#' union select a,b from t1 union all select a,b from t2 union select
select a,b from t1 union select a,b from t1;
select 't1',b,count(*) from t1 group by b UNION select 't2',b,count(*) from t2 group by b;
+#test alternate syntax for unions
+(select a,b from t1 limit 2) union all (select a,b from t2 order by a) limit 4;
+
# Test some error conditions with UNION
explain select a,b from t1 union all select a,b from t2;
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index b8d4f00533e..a712d4ca54c 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -455,11 +455,13 @@ int multi_delete::do_deletes (bool from_send_error)
bool multi_delete::send_eof()
{
thd->proc_info="deleting from reference tables"; /* out: 1 if error, 0 if success */
+
+ /* Does deletes for the last n - 1 tables, returns 0 if ok */
int error = do_deletes(false); /* do_deletes returns 0 if success */
/* reset used flags */
delete_tables->table->no_keyread=0;
-
+ if (error == -1) error = 0;
thd->proc_info="end";
if (error)
{
@@ -485,12 +487,10 @@ bool multi_delete::send_eof()
!some_table_is_not_transaction_safe(delete_tables))
error=1; /* Log write failed: roll back
the SQL statement */
- if (deleted)
- {
- /* If autocommit is on we do a commit, in an error case we
- roll back the current SQL statement */
- VOID(ha_autocommit_or_rollback(thd, error != 0));
- }
+
+ /* Commit or rollback the current SQL statement */
+
+ VOID(ha_autocommit_or_rollback(thd,error > 0));
}
::send_ok(&thd->net,deleted);
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 8d1835c7b90..f8bc02c9f19 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2406,6 +2406,7 @@ mysql_init_query(THD *thd)
thd->fatal_error=0; // Safety
thd->last_insert_id_used=thd->query_start_used=thd->insert_id_used=0;
thd->sent_row_count=thd->examined_row_count=0;
+ thd->lex.sql_command=SQLCOM_SELECT;
DBUG_VOID_RETURN;
}
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 0d8a6dc4ed1..a6ea88d9adc 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -27,7 +27,7 @@
int mysql_union(THD *thd, LEX *lex,select_result *result)
{
- SELECT_LEX *sl, *last_sl, lex_sl;
+ SELECT_LEX *sl, *last_sl=(SELECT_LEX *)NULL, lex_sl;
ORDER *order;
List<Item> item_list;
TABLE *table;
@@ -38,7 +38,7 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
DBUG_ENTER("mysql_union");
/* Fix tables 'to-be-unioned-from' list to point at opened tables */
- for (sl=&lex->select_lex; sl && sl->linkage != NOT_A_SELECT; sl=sl->next)
+ for (sl=&lex->select_lex; sl && sl->linkage != NOT_A_SELECT; last_sl=sl, sl=sl->next)
{
for (TABLE_LIST *cursor= (TABLE_LIST *)sl->table_list.first;
cursor;
@@ -50,6 +50,7 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
{
lex_sl=*sl;
sl=(SELECT_LEX *)NULL;
+ if (last_sl) last_sl->next=sl;
}
else
lex_sl.linkage=UNSPECIFIED_TYPE;
@@ -68,7 +69,7 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
sl->item_list,
sl->where,
sl->ftfunc_list,
- (sl->braces) ? (ORDER*) 0 : (ORDER *) sl->order_list.first,
+ (sl->braces) ? (ORDER *) sl->order_list.first : (ORDER *) 0,
(ORDER*) sl->group_list.first,
sl->having,
(ORDER*) NULL,
@@ -79,7 +80,7 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
DBUG_RETURN(0);
}
- order = (lex_sl.linkage == UNSPECIFIED_TYPE) ? (ORDER *) last_sl->order_list.first : (ORDER *) lex_sl.order_list.first;
+ order = (lex_sl.linkage == UNSPECIFIED_TYPE) ? ( (last_sl->braces) ? (ORDER *) 0 : (ORDER *) last_sl->order_list.first) : (ORDER *) lex_sl.order_list.first;
{
Item *item;
@@ -127,7 +128,7 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
sl->item_list,
sl->where,
sl->ftfunc_list,
- (sl->braces) ? (ORDER*) 0 : (ORDER *)sl->order_list.first,
+ (sl->braces) ? (ORDER *)sl->order_list.first : (ORDER *) 0,
(ORDER*) sl->group_list.first,
sl->having,
(ORDER*) NULL,
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 4174e6ba345..cc79ef3e7cd 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1335,18 +1335,9 @@ table_to_table:
select:
- SELECT_SYM
- {
- Lex->sql_command= SQLCOM_SELECT;
- }
- select_part2;
- |
- '(' SELECT_SYM
- {
- Lex->sql_command= SQLCOM_SELECT;
- }
- select_part3;
-
+ SELECT_SYM select_part2 {Select->braces=false;} union
+ |
+ '(' SELECT_SYM select_part2 ')' {Select->braces=true;} union_opt
select_part2:
{
@@ -1354,16 +1345,7 @@ select_part2:
lex->lock_option=TL_READ;
mysql_init_select(lex);
}
- select_options select_item_list select_into select_lock_type union
-
-select_part3:
- {
- LEX *lex=Lex;
- lex->lock_option=TL_READ;
- mysql_init_select(lex);
- Select->braces = true;
- }
- select_options select_item_list select_into select_lock_type ')' union
+ select_options select_item_list select_into select_lock_type
select_into:
limit_clause {}
@@ -3496,11 +3478,7 @@ rollback:
union:
- /* empty */
- {
- if (Lex->select->braces || Select->linkage == NOT_A_SELECT)
- YYABORT;
- }
+ /* empty */ {}
| union_list
union_list:
@@ -3513,20 +3491,29 @@ union_list:
net_printf(&lex->thd->net, ER_WRONG_USAGE,"UNION","INTO");
YYABORT;
}
+ if (lex->select->linkage==NOT_A_SELECT)
+ YYABORT;
mysql_new_select(lex);
lex->select->linkage=UNION_TYPE;
}
- SELECT_SYM select_part2
- | '(' SELECT_SYM select_part3 optional_order_or_limit
+ select
+
+union_opt:
+ union {}
+ | optional_order_or_limit {}
optional_order_or_limit:
/* emty */ {}
|
{
- mysql_new_select(Lex);
- Lex->select->linkage=NOT_A_SELECT;
+ LEX *lex=Lex;
+ if (!lex->select->braces)
+ YYABORT;
+ mysql_new_select(lex);
+ mysql_init_select(lex);
+ lex->select->linkage=NOT_A_SELECT;
}
- order_clause limit_clause
+ opt_order_clause limit_clause
union_option:
/* empty */ {}