summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <Sinisa@sinisa.nasamreza.org>2001-10-19 17:46:51 +0300
committerunknown <Sinisa@sinisa.nasamreza.org>2001-10-19 17:46:51 +0300
commitf9b331ff8a647dbb689061ec1cc0a03d73b53446 (patch)
treeffa740e9e5f57bb711a2e6efb4a1928e20b968ea
parent61b7f807ad961ed24976757b1bf25ad74cec8d29 (diff)
parent7b440a7326886fdd35bcf59ae048194f87cb7cdf (diff)
downloadmariadb-git-f9b331ff8a647dbb689061ec1cc0a03d73b53446.tar.gz
Merge sinisa@work.mysql.com:/home/bk/mysql-4.0
into sinisa.nasamreza.org:/mnt/hdc/Sinisa/mysql-4.0 BitKeeper/etc/ignore: auto-union
-rw-r--r--.bzrignore3
-rw-r--r--sql/sql_delete.cc32
-rw-r--r--sql/sql_lex.h4
-rw-r--r--sql/sql_parse.cc2
-rw-r--r--sql/sql_union.cc30
-rw-r--r--sql/sql_yacc.yy32
6 files changed, 85 insertions, 18 deletions
diff --git a/.bzrignore b/.bzrignore
index ca408bae677..0703a1d2f25 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -57,6 +57,7 @@ Docs/manual_letter.ps
Docs/manual_toc.html
Docs/my_sys.doc
Docs/mysql.info
+Docs/tex.fmt
Docs/texi2dvi.out
INSTALL-SOURCE
Logs/*
@@ -210,6 +211,7 @@ libmysqld/derror.cc
libmysqld/errmsg.c
libmysqld/examples/completion_hash.cc
libmysqld/examples/completion_hash.h
+libmysqld/examples/link_sources
libmysqld/examples/my_readline.h
libmysqld/examples/mysql
libmysqld/examples/mysql.cc
@@ -422,4 +424,3 @@ vio/test-ssl
vio/test-sslclient
vio/test-sslserver
vio/viotest-ssl
-Docs/tex.fmt
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 8ba293c82f9..b8d4f00533e 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -375,7 +375,7 @@ void multi_delete::send_error(uint errcode,const char *err)
if ((table_being_deleted->table->file->has_transactions() &&
table_being_deleted == delete_tables) ||
!some_table_is_not_transaction_safe(delete_tables->next))
- ha_rollback(thd);
+ ha_rollback_stmt(thd);
else if (do_delete)
VOID(do_deletes(true));
}
@@ -454,29 +454,45 @@ int multi_delete::do_deletes (bool from_send_error)
bool multi_delete::send_eof()
{
- thd->proc_info="deleting from reference tables";
- int error = do_deletes(false);
+ thd->proc_info="deleting from reference tables"; /* out: 1 if error, 0 if success */
+ int error = do_deletes(false); /* do_deletes returns 0 if success */
/* reset used flags */
delete_tables->table->no_keyread=0;
thd->proc_info="end";
- if (error && error != -1)
+ if (error)
{
::send_error(&thd->net);
return 1;
}
+ /* Write the SQL statement to the binlog if we deleted
+ rows and we succeeded, or also in an error case when there
+ was a non-transaction-safe table involved, since
+ modifications in it cannot be rolled back. */
+
if (deleted &&
- (error <= 0 || some_table_is_not_transaction_safe(delete_tables)))
+ (!error || some_table_is_not_transaction_safe(delete_tables)))
{
mysql_update_log.write(thd,thd->query,thd->query_length);
Query_log_event qinfo(thd, thd->query);
- if (mysql_bin_log.write(&qinfo) &&
+
+ /* mysql_bin_log is not open if binlogging or replication
+ is not used */
+
+ if (mysql_bin_log.is_open() && mysql_bin_log.write(&qinfo) &&
!some_table_is_not_transaction_safe(delete_tables))
- error=1; // Rollback
- VOID(ha_autocommit_or_rollback(thd,error >= 0));
+ 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));
+ }
}
+
::send_ok(&thd->net,deleted);
return 0;
}
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 83652d1f818..9f9fe6c79b3 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -100,7 +100,7 @@ typedef struct st_lex_master_info
} LEX_MASTER_INFO;
-enum sub_select_type {UNSPECIFIED_TYPE,UNION_TYPE, INTERSECT_TYPE, EXCEPT_TYPE};
+enum sub_select_type {UNSPECIFIED_TYPE,UNION_TYPE, INTERSECT_TYPE, EXCEPT_TYPE, NOT_A_SELECT};
/* The state of the lex parsing for selects */
@@ -118,7 +118,7 @@ typedef struct st_select_lex {
ignore_index, *ignore_index_ptr;
List<Item_func_match> ftfunc_list;
uint in_sum_expr, sort_default;
- bool create_refs;
+ bool create_refs, braces;
st_select_lex *next;
} SELECT_LEX;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index e10214bc895..8d1835c7b90 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2888,7 +2888,7 @@ static bool create_total_list(THD *thd, LEX *lex, TABLE_LIST **result)
*new_table_list=0; // end result list
for (sl= &lex->select_lex; sl; sl=sl->next)
{
- if (sl->order_list.first && sl->next)
+ if (sl->order_list.first && sl->next && !sl->braces)
{
net_printf(&thd->net,ER_WRONG_USAGE,"UNION","ORDER BY");
return 1;
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index c0ec6c81575..0d8a6dc4ed1 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;
+ SELECT_LEX *sl, *last_sl, 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=sl->next)
+ for (sl=&lex->select_lex; sl && sl->linkage != NOT_A_SELECT; sl=sl->next)
{
for (TABLE_LIST *cursor= (TABLE_LIST *)sl->table_list.first;
cursor;
@@ -46,6 +46,14 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
cursor->table= ((TABLE_LIST*) cursor->table)->table;
}
+ if (sl)
+ {
+ lex_sl=*sl;
+ sl=(SELECT_LEX *)NULL;
+ }
+ else
+ lex_sl.linkage=UNSPECIFIED_TYPE;
+
/* Find last select part as it's here ORDER BY and GROUP BY is stored */
for (last_sl= &lex->select_lex;
last_sl->next;
@@ -60,7 +68,7 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
sl->item_list,
sl->where,
sl->ftfunc_list,
- (ORDER*) 0,
+ (sl->braces) ? (ORDER*) 0 : (ORDER *) sl->order_list.first,
(ORDER*) sl->group_list.first,
sl->having,
(ORDER*) NULL,
@@ -71,7 +79,8 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
DBUG_RETURN(0);
}
- order = (ORDER *) last_sl->order_list.first;
+ order = (lex_sl.linkage == UNSPECIFIED_TYPE) ? (ORDER *) last_sl->order_list.first : (ORDER *) lex_sl.order_list.first;
+
{
Item *item;
List_iterator<Item> it(lex->select_lex.item_list);
@@ -118,7 +127,7 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
sl->item_list,
sl->where,
sl->ftfunc_list,
- (ORDER*) 0,
+ (sl->braces) ? (ORDER*) 0 : (ORDER *)sl->order_list.first,
(ORDER*) sl->group_list.first,
sl->having,
(ORDER*) NULL,
@@ -149,10 +158,21 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
(void) it.replace(new Item_field(*field));
}
if (!thd->fatal_error) // Check if EOM
+ {
+ if (lex_sl.linkage == NOT_A_SELECT && ( lex_sl.select_limit || lex_sl.offset_limit))
+ {
+ thd->offset_limit=lex_sl.offset_limit;
+ thd->select_limit=lex_sl.select_limit+lex_sl.offset_limit;
+ if (thd->select_limit < lex_sl.select_limit)
+ thd->select_limit= HA_POS_ERROR; // no limit
+ if (thd->select_limit == HA_POS_ERROR)
+ thd->options&= ~OPTION_FOUND_ROWS;
+ }
res=mysql_select(thd,&result_table_list,
item_list, NULL, ftfunc_list, order,
(ORDER*) NULL, NULL, (ORDER*) NULL,
thd->options, result);
+ }
}
exit:
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 5dae9eeb3cb..4174e6ba345 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1340,6 +1340,13 @@ select:
Lex->sql_command= SQLCOM_SELECT;
}
select_part2;
+ |
+ '(' SELECT_SYM
+ {
+ Lex->sql_command= SQLCOM_SELECT;
+ }
+ select_part3;
+
select_part2:
{
@@ -1349,6 +1356,15 @@ select_part2:
}
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_into:
limit_clause {}
| select_from
@@ -3480,7 +3496,11 @@ rollback:
union:
- /* empty */ {}
+ /* empty */
+ {
+ if (Lex->select->braces || Select->linkage == NOT_A_SELECT)
+ YYABORT;
+ }
| union_list
union_list:
@@ -3497,6 +3517,16 @@ union_list:
lex->select->linkage=UNION_TYPE;
}
SELECT_SYM select_part2
+ | '(' SELECT_SYM select_part3 optional_order_or_limit
+
+optional_order_or_limit:
+ /* emty */ {}
+ |
+ {
+ mysql_new_select(Lex);
+ Lex->select->linkage=NOT_A_SELECT;
+ }
+ order_clause limit_clause
union_option:
/* empty */ {}