summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql-common/client.c1
-rw-r--r--sql/sql_class.cc30
-rw-r--r--sql/sql_class.h10
3 files changed, 30 insertions, 11 deletions
diff --git a/sql-common/client.c b/sql-common/client.c
index a6e02376a40..e92a9bd0cdc 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -1714,7 +1714,6 @@ static MYSQL_METHODS client_methods=
C_MODE_START
int mysql_init_character_set(MYSQL *mysql)
{
- NET *net= &mysql->net;
const char *default_collation_name;
/* Set character set */
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index b5a29783044..a904023cbff 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -1305,23 +1305,26 @@ bool select_send::send_fields(List<Item> &list, uint flags)
{
bool res;
if (!(res= thd->protocol->send_fields(&list, flags)))
- status= 1;
+ is_result_set_started= 1;
return res;
}
void select_send::abort()
{
DBUG_ENTER("select_send::abort");
- if (status && thd->spcont &&
+ if (is_result_set_started && thd->spcont &&
thd->spcont->find_handler(thd, thd->net.last_errno,
MYSQL_ERROR::WARN_LEVEL_ERROR))
{
/*
- Executing stored procedure without a handler.
- Here we should actually send an error to the client,
- but as an error will break a multiple result set, the only thing we
- can do for now is to nicely end the current data set and remembering
- the error so that the calling routine will abort
+ We're executing a stored procedure, have an open result
+ set, an SQL exception conditiona and a handler for it.
+ In this situation we must abort the current statement,
+ silence the error and start executing the continue/exit
+ handler.
+ Before aborting the statement, let's end the open result set, as
+ otherwise the client will hang due to the violation of the
+ client/server protocol.
*/
thd->net.report_error= 0;
send_eof();
@@ -1331,6 +1334,17 @@ void select_send::abort()
}
+/**
+ Cleanup an instance of this class for re-use
+ at next execution of a prepared statement/
+ stored procedure statement.
+*/
+
+void select_send::cleanup()
+{
+ is_result_set_started= FALSE;
+}
+
/* Send data to client. Returns 0 if ok */
bool select_send::send_data(List<Item> &items)
@@ -1392,7 +1406,7 @@ bool select_send::send_eof()
if (! thd->is_error())
{
::send_eof(thd);
- status= 0;
+ is_result_set_started= 0;
return 0;
}
else
diff --git a/sql/sql_class.h b/sql/sql_class.h
index db847c814a0..632c440266f 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -2051,14 +2051,20 @@ public:
class select_send :public select_result {
- int status;
+ /**
+ True if we have sent result set metadata to the client.
+ In this case the client always expects us to end the result
+ set with an eof or error packet
+ */
+ bool is_result_set_started;
public:
- select_send() :status(0) {}
+ select_send() :is_result_set_started(FALSE) {}
bool send_fields(List<Item> &list, uint flags);
bool send_data(List<Item> &items);
bool send_eof();
virtual bool check_simple_select() const { return FALSE; }
void abort();
+ virtual void cleanup();
};