diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index 3d4b79ea78dfee69deefc6cad5277d0c6027a4b3..f2572321d613c71dda29d3f6083916f14a89162f 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 5c4a62d5c41fd62ef64acb4ba6c6af08ad6c894d..dc7e036e258297c6bf05f7368889b9c317a43aec 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 b8d4f00533e56429587ccd8da66fe629dd616b59..a712d4ca54c49e92d78b926c08912ac5bad7e241 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 8d1835c7b90f7e898582941680ff92675e0fbd4d..f8bc02c9f19484aaad41883c81822f5ba6f458a9 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 0d8a6dc4ed1107953004b7436bbcd7d3f5a95118..a6ea88d9adc2df3f4d6f286f8b6216a7640081be 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 4174e6ba34502d37be900f538a4979e4b1debaa8..cc79ef3e7cd6ad1fe672d434784124f58da26a0b 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 */ {}