mirror of
https://github.com/MariaDB/server.git
synced 2025-08-31 22:22:30 +03:00
Bug#12713 "Error in a stored function called from a SELECT doesn't
cause ROLLBACK of statement", part 1. Review fixes. Do not send OK/EOF packets to the client until we reached the end of the current statement. This is a consolidation, to keep the functionality that is shared by all SQL statements in one place in the server. Currently this functionality includes: - close_thread_tables() - log_slow_statement(). After this patch and the subsequent patch for Bug#12713, it shall also include: - ha_autocommit_or_rollback() - net_end_statement() - query_cache_end_of_result(). In future it may also include: - mysql_reset_thd_for_next_command().
This commit is contained in:
159
sql/sql_class.h
159
sql/sql_class.h
@@ -913,7 +913,6 @@ public:
|
||||
uint in_sub_stmt;
|
||||
bool enable_slow_log;
|
||||
bool last_insert_id_used;
|
||||
my_bool no_send_ok;
|
||||
SAVEPOINT *savepoints;
|
||||
};
|
||||
|
||||
@@ -975,6 +974,123 @@ public:
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Stores status of the currently executed statement.
|
||||
Cleared at the beginning of the statement, and then
|
||||
can hold either OK, ERROR, or EOF status.
|
||||
Can not be assigned twice per statement.
|
||||
*/
|
||||
|
||||
class Diagnostics_area
|
||||
{
|
||||
public:
|
||||
enum enum_diagnostics_status
|
||||
{
|
||||
/** The area is cleared at start of a statement. */
|
||||
DA_EMPTY= 0,
|
||||
/** Set whenever one calls send_ok(). */
|
||||
DA_OK,
|
||||
/** Set whenever one calls send_eof(). */
|
||||
DA_EOF,
|
||||
/** Set whenever one calls my_error() or my_message(). */
|
||||
DA_ERROR,
|
||||
/** Set in case of a custom response, such as one from COM_STMT_PREPARE. */
|
||||
DA_DISABLED
|
||||
};
|
||||
/** True if status information is sent to the client. */
|
||||
bool is_sent;
|
||||
/** Set to make set_error_status after set_{ok,eof}_status possible. */
|
||||
bool can_overwrite_status;
|
||||
|
||||
void set_ok_status(THD *thd, ha_rows affected_rows_arg,
|
||||
ulong last_insert_id_arg,
|
||||
const char *message);
|
||||
void set_eof_status(THD *thd);
|
||||
void set_error_status(THD *thd, uint sql_errno_arg, const char *message_arg);
|
||||
|
||||
void disable_status();
|
||||
|
||||
void reset_diagnostics_area();
|
||||
|
||||
bool is_set() const { return m_status != DA_EMPTY; }
|
||||
bool is_error() const { return m_status == DA_ERROR; }
|
||||
bool is_eof() const { return m_status == DA_EOF; }
|
||||
bool is_ok() const { return m_status == DA_OK; }
|
||||
bool is_disabled() const { return m_status == DA_DISABLED; }
|
||||
enum_diagnostics_status status() const { return m_status; }
|
||||
|
||||
const char *message() const
|
||||
{ DBUG_ASSERT(m_status == DA_ERROR || m_status == DA_OK); return m_message; }
|
||||
|
||||
uint sql_errno() const
|
||||
{ DBUG_ASSERT(m_status == DA_ERROR); return m_sql_errno; }
|
||||
|
||||
uint server_status() const
|
||||
{
|
||||
DBUG_ASSERT(m_status == DA_OK || m_status == DA_EOF);
|
||||
return m_server_status;
|
||||
}
|
||||
|
||||
ha_rows affected_rows() const
|
||||
{ DBUG_ASSERT(m_status == DA_OK); return m_affected_rows; }
|
||||
|
||||
ulong last_insert_id() const
|
||||
{ DBUG_ASSERT(m_status == DA_OK); return m_last_insert_id; }
|
||||
|
||||
uint total_warn_count() const
|
||||
{
|
||||
DBUG_ASSERT(m_status == DA_OK || m_status == DA_EOF);
|
||||
return m_total_warn_count;
|
||||
}
|
||||
|
||||
Diagnostics_area() { reset_diagnostics_area(); }
|
||||
|
||||
private:
|
||||
/** Message buffer. Can be used by OK or ERROR status. */
|
||||
char m_message[MYSQL_ERRMSG_SIZE];
|
||||
/**
|
||||
SQL error number. One of ER_ codes from share/errmsg.txt.
|
||||
Set by set_error_status.
|
||||
*/
|
||||
uint m_sql_errno;
|
||||
|
||||
/**
|
||||
Copied from thd->server_status when the diagnostics area is assigned.
|
||||
We need this member as some places in the code use the following pattern:
|
||||
thd->server_status|= ...
|
||||
send_eof(thd);
|
||||
thd->server_status&= ~...
|
||||
Assigned by OK, EOF or ERROR.
|
||||
*/
|
||||
uint m_server_status;
|
||||
/**
|
||||
The number of rows affected by the last statement. This is
|
||||
semantically close to thd->row_count_func, but has a different
|
||||
life cycle. thd->row_count_func stores the value returned by
|
||||
function ROW_COUNT() and is cleared only by statements that
|
||||
update its value, such as INSERT, UPDATE, DELETE and few others.
|
||||
This member is cleared at the beginning of the next statement.
|
||||
|
||||
We could possibly merge the two, but life cycle of thd->row_count_func
|
||||
can not be changed.
|
||||
*/
|
||||
ha_rows m_affected_rows;
|
||||
/**
|
||||
Similarly to the previous member, this is a replacement of
|
||||
thd->first_successful_insert_id_in_prev_stmt, which is used
|
||||
to implement LAST_INSERT_ID().
|
||||
*/
|
||||
ulong m_last_insert_id;
|
||||
/** The total number of warnings. */
|
||||
uint m_total_warn_count;
|
||||
enum_diagnostics_status m_status;
|
||||
/**
|
||||
@todo: the following THD members belong here:
|
||||
- warn_list, warn_count,
|
||||
*/
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
@class THD
|
||||
For each client connection we create a separate thread with THD serving as
|
||||
@@ -1400,6 +1516,7 @@ public:
|
||||
List <MYSQL_ERROR> warn_list;
|
||||
uint warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END];
|
||||
uint total_warn_count;
|
||||
Diagnostics_area main_da;
|
||||
/*
|
||||
Id of current query. Statement can be reused to execute several queries
|
||||
query_id is global in context of the whole MySQL server.
|
||||
@@ -1714,12 +1831,18 @@ public:
|
||||
CHANGED_TABLE_LIST * changed_table_dup(const char *key, long key_length);
|
||||
int send_explain_fields(select_result *result);
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
/**
|
||||
Clear the current error, if any.
|
||||
We do not clear is_fatal_error or is_fatal_sub_stmt_error since we
|
||||
assume this is never called if the fatal error is set.
|
||||
@todo: To silence an error, one should use Internal_error_handler
|
||||
mechanism. In future this function will be removed.
|
||||
*/
|
||||
inline void clear_error()
|
||||
{
|
||||
DBUG_ENTER("clear_error");
|
||||
net.last_error[0]= 0;
|
||||
net.last_errno= 0;
|
||||
net.report_error= 0;
|
||||
if (main_da.is_error())
|
||||
main_da.reset_diagnostics_area();
|
||||
is_slave_error= 0;
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
@@ -1728,10 +1851,14 @@ public:
|
||||
void clear_error();
|
||||
inline bool vio_ok() const { return true; }
|
||||
#endif
|
||||
/**
|
||||
Mark the current error as fatal. Warning: this does not
|
||||
set any error, it sets a property of the error, so must be
|
||||
followed or prefixed with my_error().
|
||||
*/
|
||||
inline void fatal_error()
|
||||
{
|
||||
is_fatal_error= 1;
|
||||
net.report_error= 1;
|
||||
DBUG_PRINT("error",("Fatal error set"));
|
||||
}
|
||||
/**
|
||||
@@ -1747,7 +1874,7 @@ public:
|
||||
|
||||
To raise this flag, use my_error().
|
||||
*/
|
||||
inline bool is_error() const { return net.report_error; }
|
||||
inline bool is_error() const { return main_da.is_error(); }
|
||||
inline CHARSET_INFO *charset() { return variables.character_set_client; }
|
||||
void update_charset();
|
||||
|
||||
@@ -1971,6 +2098,24 @@ private:
|
||||
};
|
||||
|
||||
|
||||
/** A short cut for thd->main_da.set_ok_status(). */
|
||||
|
||||
inline void
|
||||
send_ok(THD *thd, ha_rows affected_rows= 0, ulonglong id= 0,
|
||||
const char *message= NULL)
|
||||
{
|
||||
thd->main_da.set_ok_status(thd, affected_rows, id, message);
|
||||
}
|
||||
|
||||
|
||||
/** A short cut for thd->main_da.set_eof_status(). */
|
||||
|
||||
inline void
|
||||
send_eof(THD *thd)
|
||||
{
|
||||
thd->main_da.set_eof_status(thd);
|
||||
}
|
||||
|
||||
#define tmp_disable_binlog(A) \
|
||||
{ulonglong tmp_disable_binlog__save_options= (A)->options; \
|
||||
(A)->options&= ~OPTION_BIN_LOG
|
||||
@@ -2508,6 +2653,7 @@ public:
|
||||
void send_error(uint errcode,const char *err);
|
||||
int do_deletes();
|
||||
bool send_eof();
|
||||
virtual void abort();
|
||||
};
|
||||
|
||||
|
||||
@@ -2550,6 +2696,7 @@ public:
|
||||
void send_error(uint errcode,const char *err);
|
||||
int do_updates (bool from_send_error);
|
||||
bool send_eof();
|
||||
virtual void abort();
|
||||
};
|
||||
|
||||
class my_var : public Sql_alloc {
|
||||
|
Reference in New Issue
Block a user