summaryrefslogtreecommitdiff
path: root/sql/sql_error.h
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2013-07-21 16:39:19 +0200
committerSergei Golubchik <sergii@pisem.net>2013-07-21 16:39:19 +0200
commitb7b5f6f1ab49948b0e15b762266d4640b3d6b7fb (patch)
tree7c302c2025184dbd053aa6135f0ff28c8ce6f359 /sql/sql_error.h
parent5f6380adde2dac3f32b40339b9b702c0135eb7d6 (diff)
parentc1d6a2d7e194225ccc19a68ea5d0f368632620d0 (diff)
downloadmariadb-git-b7b5f6f1ab49948b0e15b762266d4640b3d6b7fb.tar.gz
10.0-monty merge
includes: * remove some remnants of "Bug#14521864: MYSQL 5.1 TO 5.5 BUGS PARTITIONING" * introduce LOCK_share, now LOCK_ha_data is strictly for engines * rea_create_table() always creates .par file (even in "frm-only" mode) * fix a 5.6 bug, temp file leak on dummy ALTER TABLE
Diffstat (limited to 'sql/sql_error.h')
-rw-r--r--sql/sql_error.h791
1 files changed, 565 insertions, 226 deletions
diff --git a/sql/sql_error.h b/sql/sql_error.h
index cd1b92a2bcc..0a75d7a392d 100644
--- a/sql/sql_error.h
+++ b/sql/sql_error.h
@@ -19,126 +19,13 @@
#include "sql_list.h" /* Sql_alloc, MEM_ROOT */
#include "m_string.h" /* LEX_STRING */
#include "sql_string.h" /* String */
+#include "sql_plist.h" /* I_P_List */
#include "mysql_com.h" /* MYSQL_ERRMSG_SIZE */
#include "my_time.h" /* MYSQL_TIME */
#include "decimal.h"
class THD;
-
-/**
- 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 my_ok(). */
- DA_OK,
- /** Set whenever one calls my_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, ulonglong affected_rows_arg,
- ulonglong 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,
- const char *sqlstate);
-
- 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; }
-
- const char* get_sqlstate() const
- { DBUG_ASSERT(m_status == DA_ERROR); return m_sqlstate; }
-
- ulonglong affected_rows() const
- { DBUG_ASSERT(m_status == DA_OK); return m_affected_rows; }
-
- ulonglong last_insert_id() const
- { DBUG_ASSERT(m_status == DA_OK); return m_last_insert_id; }
-
- uint statement_warn_count() const
- {
- DBUG_ASSERT(m_status == DA_OK || m_status == DA_EOF);
- return m_statement_warn_count;
- }
-
- /* Used to count any warnings pushed after calling set_ok_status(). */
- void increment_warning()
- {
- if (m_status != DA_EMPTY)
- m_statement_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;
-
- char m_sqlstate[SQLSTATE_LENGTH+1];
-
- /**
- 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.
- */
- ulonglong 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().
- */
- ulonglong m_last_insert_id;
- /**
- Number of warnings of this last statement. May differ from
- the number of warnings returned by SHOW WARNINGS e.g. in case
- the statement doesn't clear the warnings, and doesn't generate
- them.
- */
- uint m_statement_warn_count;
- enum_diagnostics_status m_status;
-};
+class my_decimal;
///////////////////////////////////////////////////////////////////////////
@@ -146,10 +33,8 @@ private:
Representation of a SQL condition.
A SQL condition can be a completion condition (note, warning),
or an exception condition (error, not found).
- @note This class is named MYSQL_ERROR instead of SQL_condition for
- historical reasons, to facilitate merging code with previous releases.
*/
-class MYSQL_ERROR : public Sql_alloc
+class Sql_condition : public Sql_alloc
{
public:
/*
@@ -160,6 +45,7 @@ public:
*/
enum enum_warning_level
{ WARN_LEVEL_NOTE, WARN_LEVEL_WARN, WARN_LEVEL_ERROR, WARN_LEVEL_END};
+
/**
Get the MESSAGE_TEXT of this condition.
@return the message text.
@@ -190,30 +76,15 @@ public:
Get the error level of this condition.
@return the error level condition item.
*/
- MYSQL_ERROR::enum_warning_level get_level() const
+ Sql_condition::enum_warning_level get_level() const
{ return m_level; }
- /** Destructor. */
- ~MYSQL_ERROR()
- {}
-
- /** check if condition was handled by a condition handler */
- bool handled() const
- {
- return m_handled;
- }
- /** mark that condition was handled */
- void mark_handled()
- {
- m_handled= 1;
- }
-
private:
/*
- The interface of MYSQL_ERROR is mostly private, by design,
+ The interface of Sql_condition is mostly private, by design,
so that only the following code:
- various raise_error() or raise_warning() methods in class THD,
- - the implementation of SIGNAL / RESIGNAL
+ - the implementation of SIGNAL / RESIGNAL / GET DIAGNOSTICS
- catch / re-throw of SQL conditions in stored procedures (sp_rcontext)
is allowed to create / modify a SQL condition.
Enforcing this policy prevents confusion, since the only public
@@ -223,20 +94,21 @@ private:
*/
friend class THD;
friend class Warning_info;
- friend class Signal_common;
- friend class Signal_statement;
- friend class Resignal_statement;
+ friend class Sql_cmd_common_signal;
+ friend class Sql_cmd_signal;
+ friend class Sql_cmd_resignal;
friend class sp_rcontext;
+ friend class Condition_information_item;
/**
Default constructor.
This constructor is usefull when allocating arrays.
- Note that the init() method should be called to complete the MYSQL_ERROR.
+ Note that the init() method should be called to complete the Sql_condition.
*/
- MYSQL_ERROR();
+ Sql_condition();
/**
- Complete the MYSQL_ERROR initialisation.
+ Complete the Sql_condition initialisation.
@param mem_root The memory root to use for the condition items
of this condition
*/
@@ -247,15 +119,17 @@ private:
@param mem_root The memory root to use for the condition items
of this condition
*/
- MYSQL_ERROR(MEM_ROOT *mem_root);
-
+ Sql_condition(MEM_ROOT *mem_root);
+ /** Destructor. */
+ ~Sql_condition()
+ {}
/**
Copy optional condition items attributes.
@param cond the condition to copy.
*/
- void copy_opt_attributes(const MYSQL_ERROR *cond);
+ void copy_opt_attributes(const Sql_condition *cond);
/**
Set this condition area with a fixed message text.
@@ -266,7 +140,7 @@ private:
@param MyFlags additional flags.
*/
void set(uint sql_errno, const char* sqlstate,
- MYSQL_ERROR::enum_warning_level level,
+ Sql_condition::enum_warning_level level,
const char* msg);
/**
@@ -279,6 +153,12 @@ private:
/** Set the SQLSTATE of this condition. */
void set_sqlstate(const char* sqlstate);
+ /** Set the CLASS_ORIGIN of this condition. */
+ void set_class_origin();
+
+ /** Set the SUBCLASS_ORIGIN of this condition. */
+ void set_subclass_origin();
+
/**
Clear this SQL condition.
*/
@@ -321,9 +201,6 @@ private:
/** MySQL extension, MYSQL_ERRNO condition item. */
uint m_sql_errno;
- /** Marker if error/warning was handled by a continue handler */
- bool m_handled;
-
/**
SQL RETURNED_SQLSTATE condition item.
This member is always NUL terminated.
@@ -331,44 +208,48 @@ private:
char m_returned_sqlstate[SQLSTATE_LENGTH+1];
/** Severity (error, warning, note) of this condition. */
- MYSQL_ERROR::enum_warning_level m_level;
+ Sql_condition::enum_warning_level m_level;
+
+ /** Pointers for participating in the list of conditions. */
+ Sql_condition *next_in_wi;
+ Sql_condition **prev_in_wi;
/** Memory root to use to hold condition item values. */
MEM_ROOT *m_mem_root;
};
-class Sql_condition : public MYSQL_ERROR
-{
- /*
- Wrapper class to allow one to use Sql_condition in handlers instead of
- MYSQL_ERROR
- */
-};
-
///////////////////////////////////////////////////////////////////////////
/**
Information about warnings of the current connection.
*/
-
class Warning_info
{
+ /** The type of the counted and doubly linked list of conditions. */
+ typedef I_P_List<Sql_condition,
+ I_P_List_adapter<Sql_condition,
+ &Sql_condition::next_in_wi,
+ &Sql_condition::prev_in_wi>,
+ I_P_List_counter,
+ I_P_List_fast_push_back<Sql_condition> >
+ Sql_condition_list;
+
/** A memory root to allocate warnings and errors */
MEM_ROOT m_warn_root;
/** List of warnings of all severities (levels). */
- List <MYSQL_ERROR> m_warn_list;
+ Sql_condition_list m_warn_list;
/** A break down of the number of warnings per severity (level). */
- uint m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END];
+ uint m_warn_count[(uint) Sql_condition::WARN_LEVEL_END];
/**
The number of warnings of the current statement. Warning_info
life cycle differs from statement life cycle -- it may span
multiple statements. In that case we get
- m_statement_warn_count 0, whereas m_warn_list is not empty.
+ m_current_statement_warn_count 0, whereas m_warn_list is not empty.
*/
- uint m_statement_warn_count;
+ uint m_current_statement_warn_count;
/*
Row counter, to print in errors and warnings. Not increased in
@@ -379,29 +260,67 @@ class Warning_info
/** Used to optionally clear warnings only once per statement. */
ulonglong m_warn_id;
+ /**
+ A pointer to an element of m_warn_list. It determines SQL-condition
+ instance which corresponds to the error state in Diagnostics_area.
+
+ This is needed for properly processing SQL-conditions in SQL-handlers.
+ When an SQL-handler is found for the current error state in Diagnostics_area,
+ this pointer is needed to remove the corresponding SQL-condition from the
+ Warning_info list.
+
+ @note m_error_condition might be NULL in the following cases:
+ - Diagnostics_area set to fatal error state (like OOM);
+ - Max number of Warning_info elements has been reached (thus, there is
+ no corresponding SQL-condition object in Warning_info).
+ */
+ const Sql_condition *m_error_condition;
+
/** Indicates if push_warning() allows unlimited number of warnings. */
bool m_allow_unlimited_warnings;
bool initialized; /* Set to 1 if init() has been called */
-private:
- Warning_info(const Warning_info &rhs); /* Not implemented */
- Warning_info& operator=(const Warning_info &rhs); /* Not implemented */
-public:
+ /** Read only status. */
+ bool m_read_only;
+
+ /** Pointers for participating in the stack of Warning_info objects. */
+ Warning_info *m_next_in_da;
+ Warning_info **m_prev_in_da;
+ List<Sql_condition> m_marked_sql_conditions;
+
+public:
Warning_info(ulonglong warn_id_arg, bool allow_unlimited_warnings,
- bool initialize=true);
+ bool initialized);
~Warning_info();
-
/* Allocate memory for structures */
void init();
void free_memory();
+private:
+ Warning_info(const Warning_info &rhs); /* Not implemented */
+ Warning_info& operator=(const Warning_info &rhs); /* Not implemented */
+
+ /**
+ Checks if Warning_info contains SQL-condition with the given message.
+
+ @param message_str Message string.
+ @param message_length Length of message string.
+
+ @return true if the Warning_info contains an SQL-condition with the given
+ message.
+ */
+ bool has_sql_condition(const char *message_str, ulong message_length) const;
+
/**
Reset the warning information. Clear all warnings,
the number of warnings, reset current row counter
to point to the first row.
+
+ @param new_id new Warning_info id.
*/
- void clear_warning_info(ulonglong warn_id_arg);
+ void clear(ulonglong new_id);
+
/**
Only clear warning info if haven't yet done that already
for the current query. Allows to be issued at any time
@@ -410,46 +329,72 @@ public:
@todo: This is a sign of sloppy coding. Instead we need to
designate one place in a statement life cycle where we call
- clear_warning_info().
+ Warning_info::clear().
+
+ @param query_id Current query id.
*/
- void opt_clear_warning_info(ulonglong query_id)
+ void opt_clear(ulonglong query_id)
{
if (query_id != m_warn_id)
- clear_warning_info(query_id);
- }
-
- void append_warning_info(THD *thd, Warning_info *source)
- {
- append_warnings(thd, & source->warn_list());
+ clear(query_id);
}
/**
Concatenate the list of warnings.
- It's considered tolerable to lose a warning.
- */
- void append_warnings(THD *thd, List<MYSQL_ERROR> *src)
- {
- MYSQL_ERROR *err;
- List_iterator_fast<MYSQL_ERROR> it(*src);
- /*
- Don't use ::push_warning() to avoid invocation of condition
- handlers or escalation of warnings to errors.
- */
- while ((err= it++))
- Warning_info::push_warning(thd, err);
- }
- /**
- Conditional merge of related warning information areas.
+ It's considered tolerable to lose an SQL-condition in case of OOM-error,
+ or if the number of SQL-conditions in the Warning_info reached top limit.
+
+ @param thd Thread context.
+ @param source Warning_info object to copy SQL-conditions from.
*/
- void merge_with_routine_info(THD *thd, Warning_info *source);
+ void append_warning_info(THD *thd, const Warning_info *source);
/**
Reset between two COM_ commands. Warnings are preserved
between commands, but statement_warn_count indicates
the number of warnings of this particular statement only.
*/
- void reset_for_next_command() { m_statement_warn_count= 0; }
+ void reset_for_next_command()
+ { m_current_statement_warn_count= 0; }
+
+ /**
+ Mark active SQL-conditions for later removal.
+ This is done to simulate stacked DAs for HANDLER statements.
+ */
+ void mark_sql_conditions_for_removal();
+
+ /**
+ Unmark SQL-conditions, which were marked for later removal.
+ This is done to simulate stacked DAs for HANDLER statements.
+ */
+ void unmark_sql_conditions_from_removal()
+ { m_marked_sql_conditions.empty(); }
+
+ /**
+ Remove SQL-conditions that are marked for deletion.
+ This is done to simulate stacked DAs for HANDLER statements.
+ */
+ void remove_marked_sql_conditions();
+
+ /**
+ Check if the given SQL-condition is marked for removal in this Warning_info
+ instance.
+
+ @param cond the SQL-condition.
+
+ @retval true if the given SQL-condition is marked for removal in this
+ Warning_info instance.
+ @retval false otherwise.
+ */
+ bool is_marked_for_removal(const Sql_condition *cond) const;
+
+ /**
+ Mark a single SQL-condition for removal (add the given SQL-condition to the
+ removal list of this Warning_info instance).
+ */
+ void mark_condition_for_removal(Sql_condition *cond)
+ { m_marked_sql_conditions.push_back(cond, &m_warn_root); }
/**
Used for @@warning_count system variable, which prints
@@ -458,52 +403,82 @@ public:
ulong warn_count() const
{
/*
- This may be higher than warn_list.elements if we have
+ This may be higher than warn_list.elements() if we have
had more warnings than thd->variables.max_error_count.
*/
- return (m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_NOTE] +
- m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_ERROR] +
- m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_WARN]);
+ return (m_warn_count[(uint) Sql_condition::WARN_LEVEL_NOTE] +
+ m_warn_count[(uint) Sql_condition::WARN_LEVEL_ERROR] +
+ m_warn_count[(uint) Sql_condition::WARN_LEVEL_WARN]);
}
/**
- This is for iteration purposes. We return a non-constant reference
- since List doesn't have constant iterators.
- */
- List<MYSQL_ERROR> &warn_list() { return m_warn_list; }
-
- /**
The number of errors, or number of rows returned by SHOW ERRORS,
also the value of session variable @@error_count.
*/
ulong error_count() const
+ { return m_warn_count[(uint) Sql_condition::WARN_LEVEL_ERROR]; }
+
+ /**
+ The number of conditions (errors, warnings and notes) in the list.
+ */
+ uint cond_count() const
{
- return m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_ERROR];
+ return m_warn_list.elements();
}
/** Id of the warning information area. */
- ulonglong warn_id() const { return m_warn_id; }
+ ulonglong id() const { return m_warn_id; }
+
+ /** Set id of the warning information area. */
+ void id(ulonglong id) { m_warn_id= id; }
/** Do we have any errors and warnings that we can *show*? */
- bool is_empty() const { return m_warn_list.elements == 0; }
+ bool is_empty() const { return m_warn_list.is_empty(); }
/** Increment the current row counter to point at the next row. */
void inc_current_row_for_warning() { m_current_row_for_warning++; }
+
/** Reset the current row counter. Start counting from the first row. */
void reset_current_row_for_warning() { m_current_row_for_warning= 1; }
+
/** Return the current counter value. */
ulong current_row_for_warning() const { return m_current_row_for_warning; }
- ulong statement_warn_count() const { return m_statement_warn_count; }
+ /** Return the number of warnings thrown by the current statement. */
+ ulong current_statement_warn_count() const
+ { return m_current_statement_warn_count; }
+
+ /** Make sure there is room for the given number of conditions. */
+ void reserve_space(THD *thd, uint count);
+
+ /**
+ Add a new SQL-condition to the current list and increment the respective
+ counters.
+
+ @param thd Thread context.
+ @param sql_errno SQL-condition error number.
+ @param sqlstate SQL-condition state.
+ @param level SQL-condition level.
+ @param msg SQL-condition message.
+
+ @return a pointer to the added SQL-condition.
+ */
+ Sql_condition *push_warning(THD *thd,
+ uint sql_errno,
+ const char* sqlstate,
+ Sql_condition::enum_warning_level level,
+ const char* msg);
+
+ /**
+ Add a new SQL-condition to the current list and increment the respective
+ counters.
- /** Add a new condition to the current list. */
- MYSQL_ERROR *push_warning(THD *thd,
- uint sql_errno, const char* sqlstate,
- MYSQL_ERROR::enum_warning_level level,
- const char* msg);
+ @param thd Thread context.
+ @param sql_condition SQL-condition to copy values from.
- /** Add a new condition to the current list. */
- MYSQL_ERROR *push_warning(THD *thd, const MYSQL_ERROR *sql_condition);
+ @return a pointer to the added SQL-condition.
+ */
+ Sql_condition *push_warning(THD *thd, const Sql_condition *sql_condition);
/**
Set the read only status for this statement area.
@@ -514,25 +489,51 @@ public:
- SHOW WARNINGS
- SHOW ERRORS
- GET DIAGNOSTICS
- @param read_only the read only property to set
+ @param read_only the read only property to set.
*/
void set_read_only(bool read_only)
{ m_read_only= read_only; }
/**
Read only status.
- @return the read only property
+ @return the read only property.
*/
bool is_read_only() const
{ return m_read_only; }
-private:
- /** Read only status. */
- bool m_read_only;
+ /**
+ @return SQL-condition, which corresponds to the error state in
+ Diagnostics_area.
- friend class Resignal_statement;
+ @see m_error_condition.
+ */
+ const Sql_condition *get_error_condition() const
+ { return m_error_condition; }
+
+ /**
+ Set SQL-condition, which corresponds to the error state in Diagnostics_area.
+
+ @see m_error_condition.
+ */
+ void set_error_condition(const Sql_condition *error_condition)
+ { m_error_condition= error_condition; }
+
+ /**
+ Reset SQL-condition, which corresponds to the error state in
+ Diagnostics_area.
+
+ @see m_error_condition.
+ */
+ void clear_error_condition()
+ { m_error_condition= NULL; }
+
+ // for:
+ // - m_next_in_da / m_prev_in_da
+ // - is_marked_for_removal()
+ friend class Diagnostics_area;
};
+
extern char *err_conv(char *buff, uint to_length, const char *from,
uint from_length, CHARSET_INFO *from_cs);
@@ -606,15 +607,353 @@ public:
}
};
-void push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level,
+///////////////////////////////////////////////////////////////////////////
+
+/**
+ 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
+{
+private:
+ /** The type of the counted and doubly linked list of conditions. */
+ typedef I_P_List<Warning_info,
+ I_P_List_adapter<Warning_info,
+ &Warning_info::m_next_in_da,
+ &Warning_info::m_prev_in_da>,
+ I_P_List_counter,
+ I_P_List_fast_push_back<Warning_info> >
+ Warning_info_list;
+
+public:
+ /** Const iterator used to iterate through the warning list. */
+ typedef Warning_info::Sql_condition_list::Const_Iterator
+ Sql_condition_iterator;
+
+ enum enum_diagnostics_status
+ {
+ /** The area is cleared at start of a statement. */
+ DA_EMPTY= 0,
+ /** Set whenever one calls my_ok(). */
+ DA_OK,
+ /** Set whenever one calls my_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
+ };
+
+ void set_overwrite_status(bool can_overwrite_status)
+ { m_can_overwrite_status= can_overwrite_status; }
+
+ /** True if status information is sent to the client. */
+ bool is_sent() const { return m_is_sent; }
+
+ void set_is_sent(bool is_sent) { m_is_sent= is_sent; }
+
+ void set_ok_status(ulonglong affected_rows,
+ ulonglong last_insert_id,
+ const char *message);
+
+ void set_eof_status(THD *thd);
+
+ void set_error_status(uint sql_errno);
+
+ void set_error_status(uint sql_errno,
+ const char *message,
+ const char *sqlstate,
+ const Sql_condition *error_condition);
+
+ 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; }
+
+ const char* get_sqlstate() const
+ { DBUG_ASSERT(m_status == DA_ERROR); return m_sqlstate; }
+
+ ulonglong affected_rows() const
+ { DBUG_ASSERT(m_status == DA_OK); return m_affected_rows; }
+
+ ulonglong last_insert_id() const
+ { DBUG_ASSERT(m_status == DA_OK); return m_last_insert_id; }
+
+ uint statement_warn_count() const
+ {
+ DBUG_ASSERT(m_status == DA_OK || m_status == DA_EOF);
+ return m_statement_warn_count;
+ }
+
+ /* Used to count any warnings pushed after calling set_ok_status(). */
+ void increment_warning()
+ {
+ if (m_status != DA_EMPTY)
+ m_statement_warn_count++;
+ }
+
+ Diagnostics_area(bool initialize);
+ Diagnostics_area(ulonglong warning_info_id, bool allow_unlimited_warnings,
+ bool initialize);
+ void init() { m_main_wi.init() ; }
+ void free_memory() { m_main_wi.free_memory() ; }
+
+ void push_warning_info(Warning_info *wi)
+ { m_wi_stack.push_front(wi); }
+
+ void pop_warning_info()
+ {
+ DBUG_ASSERT(m_wi_stack.elements() > 0);
+ m_wi_stack.remove(m_wi_stack.front());
+ }
+
+ void set_warning_info_id(ulonglong id)
+ { get_warning_info()->id(id); }
+
+ ulonglong warning_info_id() const
+ { return get_warning_info()->id(); }
+
+ /**
+ Compare given current warning info and current warning info
+ and see if they are different. They will be different if
+ warnings have been generated or statements that use tables
+ have been executed. This is checked by comparing m_warn_id.
+
+ @param wi Warning info to compare with current Warning info.
+
+ @return false if they are equal, true if they are not.
+ */
+ bool warning_info_changed(const Warning_info *wi) const
+ { return get_warning_info()->id() != wi->id(); }
+
+ bool is_warning_info_empty() const
+ { return get_warning_info()->is_empty(); }
+
+ ulong current_statement_warn_count() const
+ { return get_warning_info()->current_statement_warn_count(); }
+
+ bool has_sql_condition(const char *message_str, ulong message_length) const
+ { return get_warning_info()->has_sql_condition(message_str, message_length); }
+
+ void reset_for_next_command()
+ { get_warning_info()->reset_for_next_command(); }
+
+ void clear_warning_info(ulonglong id)
+ { get_warning_info()->clear(id); }
+
+ void opt_clear_warning_info(ulonglong query_id)
+ { get_warning_info()->opt_clear(query_id); }
+
+ ulong current_row_for_warning() const
+ { return get_warning_info()->current_row_for_warning(); }
+
+ void inc_current_row_for_warning()
+ { get_warning_info()->inc_current_row_for_warning(); }
+
+ void reset_current_row_for_warning()
+ { get_warning_info()->reset_current_row_for_warning(); }
+
+ bool is_warning_info_read_only() const
+ { return get_warning_info()->is_read_only(); }
+
+ void set_warning_info_read_only(bool read_only)
+ { get_warning_info()->set_read_only(read_only); }
+
+ ulong error_count() const
+ { return get_warning_info()->error_count(); }
+
+ ulong warn_count() const
+ { return get_warning_info()->warn_count(); }
+
+ uint cond_count() const
+ { return get_warning_info()->cond_count(); }
+
+ Sql_condition_iterator sql_conditions() const
+ { return get_warning_info()->m_warn_list; }
+
+ void reserve_space(THD *thd, uint count)
+ { get_warning_info()->reserve_space(thd, count); }
+
+ Sql_condition *push_warning(THD *thd, const Sql_condition *sql_condition)
+ { return get_warning_info()->push_warning(thd, sql_condition); }
+
+ Sql_condition *push_warning(THD *thd,
+ uint sql_errno,
+ const char* sqlstate,
+ Sql_condition::enum_warning_level level,
+ const char* msg)
+ {
+ return get_warning_info()->push_warning(thd,
+ sql_errno, sqlstate, level, msg);
+ }
+
+ void mark_sql_conditions_for_removal()
+ { get_warning_info()->mark_sql_conditions_for_removal(); }
+
+ void unmark_sql_conditions_from_removal()
+ { get_warning_info()->unmark_sql_conditions_from_removal(); }
+
+ void remove_marked_sql_conditions()
+ { get_warning_info()->remove_marked_sql_conditions(); }
+
+ const Sql_condition *get_error_condition() const
+ { return get_warning_info()->get_error_condition(); }
+
+ void copy_sql_conditions_to_wi(THD *thd, Warning_info *dst_wi) const
+ { dst_wi->append_warning_info(thd, get_warning_info()); }
+
+ void copy_sql_conditions_from_wi(THD *thd, const Warning_info *src_wi)
+ { get_warning_info()->append_warning_info(thd, src_wi); }
+
+ void copy_non_errors_from_wi(THD *thd, const Warning_info *src_wi);
+
+private:
+ Warning_info *get_warning_info() { return m_wi_stack.front(); }
+
+ const Warning_info *get_warning_info() const { return m_wi_stack.front(); }
+
+private:
+ /** True if status information is sent to the client. */
+ bool m_is_sent;
+
+ /** Set to make set_error_status after set_{ok,eof}_status possible. */
+ bool m_can_overwrite_status;
+
+ /** 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;
+
+ char m_sqlstate[SQLSTATE_LENGTH+1];
+
+ /**
+ 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.
+ */
+ ulonglong 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().
+ */
+
+ ulonglong m_last_insert_id;
+ /**
+ Number of warnings of this last statement. May differ from
+ the number of warnings returned by SHOW WARNINGS e.g. in case
+ the statement doesn't clear the warnings, and doesn't generate
+ them.
+ */
+ uint m_statement_warn_count;
+
+ enum_diagnostics_status m_status;
+
+ Warning_info m_main_wi;
+
+ Warning_info_list m_wi_stack;
+};
+
+///////////////////////////////////////////////////////////////////////////
+
+
+void push_warning(THD *thd, Sql_condition::enum_warning_level level,
uint code, const char *msg);
-void push_warning_printf(THD *thd, MYSQL_ERROR::enum_warning_level level,
- uint code, const char *format, ...);
+
+void push_warning_printf(THD *thd, Sql_condition::enum_warning_level level,
+ uint code, const char *format, ...);
+
bool mysqld_show_warnings(THD *thd, ulong levels_to_show);
-uint32 convert_error_message(char *to, uint32 to_length, CHARSET_INFO *to_cs,
+
+uint32 convert_error_message(char *to, uint32 to_length,
+ CHARSET_INFO *to_cs,
const char *from, uint32 from_length,
CHARSET_INFO *from_cs, uint *errors);
extern const LEX_STRING warning_level_names[];
+bool is_sqlstate_valid(const LEX_STRING *sqlstate);
+/**
+ Checks if the specified SQL-state-string defines COMPLETION condition.
+ This function assumes that the given string contains a valid SQL-state.
+
+ @param s the condition SQLSTATE.
+
+ @retval true if the given string defines COMPLETION condition.
+ @retval false otherwise.
+*/
+inline bool is_sqlstate_completion(const char *s)
+{ return s[0] == '0' && s[1] == '0'; }
+
+
+/**
+ Checks if the specified SQL-state-string defines WARNING condition.
+ This function assumes that the given string contains a valid SQL-state.
+
+ @param s the condition SQLSTATE.
+
+ @retval true if the given string defines WARNING condition.
+ @retval false otherwise.
+*/
+inline bool is_sqlstate_warning(const char *s)
+{ return s[0] == '0' && s[1] == '1'; }
+
+
+/**
+ Checks if the specified SQL-state-string defines NOT FOUND condition.
+ This function assumes that the given string contains a valid SQL-state.
+
+ @param s the condition SQLSTATE.
+
+ @retval true if the given string defines NOT FOUND condition.
+ @retval false otherwise.
+*/
+inline bool is_sqlstate_not_found(const char *s)
+{ return s[0] == '0' && s[1] == '2'; }
+
+
+/**
+ Checks if the specified SQL-state-string defines EXCEPTION condition.
+ This function assumes that the given string contains a valid SQL-state.
+
+ @param s the condition SQLSTATE.
+
+ @retval true if the given string defines EXCEPTION condition.
+ @retval false otherwise.
+*/
+inline bool is_sqlstate_exception(const char *s)
+{ return s[0] != '0' || s[1] > '2'; }
+
+
#endif // SQL_ERROR_H