3970 Jon Olav Hauglid 2012-07-04
WL#6406 Stacked diagnostic areas
Patch 2: Refactoring:
- Combined Warning_info and Diagnostics_area and
removed Warning_info.
- Combined Sql_condition::init() and Sql_condition::set()
with constructor
modified:
sql/sp_rcontext.cc
sql/sql_error.cc
sql/sql_error.h
sql/sql_signal.cc
3969 Jon Olav Hauglid 2012-07-04
WL#6406 Stacked diagnostic areas
Patch 1:
- Added THD::push_diagnostics_area(), THD::pop_diagnostics_area()
and THD::get_stacked_da(). Related code added to sql_error.
- Removed push/pop of warning info, used push/pop da instead.
- Removed set_stmt_da(), used push/pop da instead.
modified:
sql/rpl_master.cc
sql/sp_head.cc
sql/sql_admin.cc
sql/sql_class.h
sql/sql_error.cc
sql/sql_error.h
sql/sql_get_diagnostics.cc
sql/sql_partition.cc
sql/sql_prepare.cc
sql/sql_show.cc
=== modified file 'sql/sp_rcontext.cc'
--- a/sql/sp_rcontext.cc 2012-06-06 12:12:51 +0000
+++ b/sql/sp_rcontext.cc 2012-07-04 14:06:47 +0000
@@ -262,11 +262,12 @@ bool sp_rcontext::handle_sql_condition(T
*/
if (!found_condition)
{
- Sql_condition *condition=
- new (callers_arena->mem_root) Sql_condition(callers_arena->mem_root);
- condition->set(da->sql_errno(), da->get_sqlstate(),
- Sql_condition::WARN_LEVEL_ERROR,
- da->message());
+ Sql_condition *condition= new (callers_arena->mem_root)
+ Sql_condition(callers_arena->mem_root,
+ da->sql_errno(),
+ da->get_sqlstate(),
+ Sql_condition::WARN_LEVEL_ERROR,
+ da->message());
found_condition= condition;
}
}
=== modified file 'sql/sql_error.cc'
--- a/sql/sql_error.cc 2012-07-04 13:47:16 +0000
+++ b/sql/sql_error.cc 2012-07-04 14:06:47 +0000
@@ -170,7 +170,26 @@ using std::max;
consequence of WL#751.
*/
-Sql_condition::Sql_condition()
+
+static void copy_string(MEM_ROOT *mem_root, String* dst, const String* src)
+{
+ size_t len= src->length();
+ if (len)
+ {
+ char* copy= (char*) alloc_root(mem_root, len + 1);
+ if (copy)
+ {
+ memcpy(copy, src->ptr(), len);
+ copy[len]= '\0';
+ dst->set(copy, len, src->charset());
+ }
+ }
+ else
+ dst->length(0);
+}
+
+
+Sql_condition::Sql_condition(MEM_ROOT *mem_root)
: Sql_alloc(),
m_class_origin((const char*) NULL, 0, & my_charset_utf8_bin),
m_subclass_origin((const char*) NULL, 0, & my_charset_utf8_bin),
@@ -185,36 +204,17 @@ Sql_condition::Sql_condition()
m_message_text(),
m_sql_errno(0),
m_level(Sql_condition::WARN_LEVEL_ERROR),
- m_mem_root(NULL)
+ m_mem_root(mem_root)
{
+ DBUG_ASSERT(mem_root != NULL);
memset(m_returned_sqlstate, 0, sizeof(m_returned_sqlstate));
}
-void Sql_condition::init(MEM_ROOT *mem_root)
-{
- DBUG_ASSERT(mem_root != NULL);
- DBUG_ASSERT(m_mem_root == NULL);
- m_mem_root= mem_root;
-}
-void Sql_condition::clear()
-{
- m_class_origin.length(0);
- m_subclass_origin.length(0);
- m_constraint_catalog.length(0);
- m_constraint_schema.length(0);
- m_constraint_name.length(0);
- m_catalog_name.length(0);
- m_schema_name.length(0);
- m_table_name.length(0);
- m_column_name.length(0);
- m_cursor_name.length(0);
- m_message_text.length(0);
- m_sql_errno= 0;
- m_level= Sql_condition::WARN_LEVEL_ERROR;
-}
-
-Sql_condition::Sql_condition(MEM_ROOT *mem_root)
+Sql_condition::Sql_condition(MEM_ROOT *mem_root, uint sql_errno,
+ const char* sqlstate,
+ Sql_condition::enum_warning_level level,
+ const char* msg)
: Sql_alloc(),
m_class_origin((const char*) NULL, 0, & my_charset_utf8_bin),
m_subclass_origin((const char*) NULL, 0, & my_charset_utf8_bin),
@@ -227,33 +227,25 @@ Sql_condition::Sql_condition(MEM_ROOT *m
m_column_name((const char*) NULL, 0, & my_charset_utf8_bin),
m_cursor_name((const char*) NULL, 0, & my_charset_utf8_bin),
m_message_text(),
- m_sql_errno(0),
- m_level(Sql_condition::WARN_LEVEL_ERROR),
+ m_sql_errno(sql_errno),
+ m_level(level),
m_mem_root(mem_root)
{
DBUG_ASSERT(mem_root != NULL);
+ DBUG_ASSERT(sql_errno != 0);
+ DBUG_ASSERT(sqlstate != NULL);
+ DBUG_ASSERT(msg != NULL);
+
memset(m_returned_sqlstate, 0, sizeof(m_returned_sqlstate));
-}
-static void copy_string(MEM_ROOT *mem_root, String* dst, const String* src)
-{
- size_t len= src->length();
- if (len)
- {
- char* copy= (char*) alloc_root(mem_root, len + 1);
- if (copy)
- {
- memcpy(copy, src->ptr(), len);
- copy[len]= '\0';
- dst->set(copy, len, src->charset());
- }
- }
- else
- dst->length(0);
+ set_builtin_message_text(msg);
+ set_sqlstate(sqlstate);
+ set_class_origin();
+ set_subclass_origin();
}
-void
-Sql_condition::copy_opt_attributes(const Sql_condition *cond)
+
+void Sql_condition::copy_opt_attributes(const Sql_condition *cond)
{
DBUG_ASSERT(this != cond);
copy_string(m_mem_root, & m_class_origin, & cond->m_class_origin);
@@ -268,26 +260,8 @@ Sql_condition::copy_opt_attributes(const
copy_string(m_mem_root, & m_cursor_name, & cond->m_cursor_name);
}
-void
-Sql_condition::set(uint sql_errno, const char* sqlstate,
- Sql_condition::enum_warning_level level, const char* msg)
-{
- DBUG_ASSERT(sql_errno != 0);
- DBUG_ASSERT(sqlstate != NULL);
- DBUG_ASSERT(msg != NULL);
- m_sql_errno= sql_errno;
- memcpy(m_returned_sqlstate, sqlstate, SQLSTATE_LENGTH);
- m_returned_sqlstate[SQLSTATE_LENGTH]= '\0';
-
- set_class_origin();
- set_subclass_origin();
- set_builtin_message_text(msg);
- m_level= level;
-}
-
-void
-Sql_condition::set_builtin_message_text(const char* str)
+void Sql_condition::set_builtin_message_text(const char* str)
{
/*
See the comments
@@ -300,32 +274,21 @@ Sql_condition::set_builtin_message_text(
DBUG_ASSERT(! m_message_text.is_alloced());
}
-const char*
-Sql_condition::get_message_text() const
-{
- return m_message_text.ptr();
-}
-int
-Sql_condition::get_message_octet_length() const
-{
- return m_message_text.length();
-}
-
-void
-Sql_condition::set_sqlstate(const char* sqlstate)
+void Sql_condition::set_sqlstate(const char* sqlstate)
{
memcpy(m_returned_sqlstate, sqlstate, SQLSTATE_LENGTH);
m_returned_sqlstate[SQLSTATE_LENGTH]= '\0';
}
+
static LEX_CSTRING sqlstate_origin[]= {
{ STRING_WITH_LEN("ISO 9075") },
{ STRING_WITH_LEN("MySQL") }
};
-void
-Sql_condition::set_class_origin()
+
+void Sql_condition::set_class_origin()
{
char cls[2];
LEX_CSTRING *origin;
@@ -356,8 +319,8 @@ Sql_condition::set_class_origin()
m_class_origin.set_ascii(origin->str, origin->length);
}
-void
-Sql_condition::set_subclass_origin()
+
+void Sql_condition::set_subclass_origin()
{
LEX_CSTRING *origin;
@@ -378,28 +341,67 @@ Sql_condition::set_subclass_origin()
m_subclass_origin.set_ascii(origin->str, origin->length);
}
+
+void Sql_condition::clear()
+{
+ m_class_origin.length(0);
+ m_subclass_origin.length(0);
+ m_constraint_catalog.length(0);
+ m_constraint_schema.length(0);
+ m_constraint_name.length(0);
+ m_catalog_name.length(0);
+ m_schema_name.length(0);
+ m_table_name.length(0);
+ m_column_name.length(0);
+ m_cursor_name.length(0);
+ m_message_text.length(0);
+ m_sql_errno= 0;
+ m_level= Sql_condition::WARN_LEVEL_ERROR;
+}
+
+
Diagnostics_area::Diagnostics_area()
- : m_main_wi(0, false), m_stacked_da(NULL)
+ : m_stacked_da(NULL),
+ m_error_condition(NULL),
+ m_allow_unlimited_warnings(false),
+ m_read_only(false),
+ m_current_statement_warn_count(0),
+ m_current_row_for_warning(1),
+ m_warn_id(0)
{
+ /* Initialize sub structures */
+ init_sql_alloc(&m_warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
+ m_warn_list.empty();
+ memset(m_warn_count, 0, sizeof(m_warn_count));
reset_diagnostics_area();
}
+
Diagnostics_area::Diagnostics_area(ulonglong warning_info_id,
bool allow_unlimited_warnings)
- : m_main_wi(warning_info_id, allow_unlimited_warnings),
- m_stacked_da(NULL)
+ : m_stacked_da(NULL),
+ m_error_condition(NULL),
+ m_allow_unlimited_warnings(allow_unlimited_warnings),
+ m_read_only(false),
+ m_current_statement_warn_count(0),
+ m_current_row_for_warning(1),
+ m_warn_id(warning_info_id)
{
+ /* Initialize sub structures */
+ init_sql_alloc(&m_warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
+ m_warn_list.empty();
+ memset(m_warn_count, 0, sizeof(m_warn_count));
reset_diagnostics_area();
}
-/**
- Clear this diagnostics area.
- Normally called at the end of a statement.
-*/
+Diagnostics_area::~Diagnostics_area()
+{
+ free_root(&m_warn_root,MYF(0));
+}
-void
-Diagnostics_area::reset_diagnostics_area()
+
+void Diagnostics_area::reset_diagnostics_area()
{
DBUG_ENTER("reset_diagnostics_area");
#ifdef DBUG_OFF
@@ -411,7 +413,7 @@ Diagnostics_area::reset_diagnostics_area
m_last_insert_id= 0;
m_statement_warn_count= 0;
#endif
- m_main_wi.clear_error_condition();
+ clear_error_condition();
set_is_sent(false);
/** Tiny reset in debug mode to see garbage right away */
m_status= DA_EMPTY;
@@ -419,15 +421,9 @@ Diagnostics_area::reset_diagnostics_area
}
-/**
- Set OK status -- ends commands that do not return a
- result set, e.g. INSERT/UPDATE/DELETE.
-*/
-
-void
-Diagnostics_area::set_ok_status(ulonglong affected_rows,
- ulonglong last_insert_id,
- const char *message)
+void Diagnostics_area::set_ok_status(ulonglong affected_rows,
+ ulonglong last_insert_id,
+ const char *message)
{
DBUG_ENTER("set_ok_status");
DBUG_ASSERT(! is_set());
@@ -450,12 +446,7 @@ Diagnostics_area::set_ok_status(ulonglon
}
-/**
- Set EOF status.
-*/
-
-void
-Diagnostics_area::set_eof_status(THD *thd)
+void Diagnostics_area::set_eof_status(THD *thd)
{
DBUG_ENTER("set_eof_status");
/* Only allowed to report eof if has not yet reported an error */
@@ -480,16 +471,8 @@ Diagnostics_area::set_eof_status(THD *th
DBUG_VOID_RETURN;
}
-/**
- Set ERROR status in the Diagnostics Area. This function should be used to
- report fatal errors (such as out-of-memory errors) when no further
- processing is possible.
-
- @param sql_errno SQL-condition error number
-*/
-void
-Diagnostics_area::set_error_status(uint sql_errno)
+void Diagnostics_area::set_error_status(uint sql_errno)
{
set_error_status(sql_errno,
ER(sql_errno),
@@ -497,23 +480,11 @@ Diagnostics_area::set_error_status(uint
NULL);
}
-/**
- Set ERROR status in the Diagnostics Area.
-
- @note error_condition may be NULL. It happens if a) OOM error is being
- reported; or b) when Warning_info is full.
- @param sql_errno SQL-condition error number
- @param message SQL-condition message
- @param sqlstate SQL-condition state
- @param error_condition SQL-condition object representing the error state
-*/
-
-void
-Diagnostics_area::set_error_status(uint sql_errno,
- const char *message,
- const char *sqlstate,
- const Sql_condition *error_condition)
+void Diagnostics_area::set_error_status(uint sql_errno,
+ const char *message,
+ const char *sqlstate,
+ const Sql_condition *error_condition)
{
DBUG_ENTER("set_error_status");
/*
@@ -543,50 +514,22 @@ Diagnostics_area::set_error_status(uint
m_sqlstate[SQLSTATE_LENGTH]= '\0';
strmake(m_message, message, sizeof(m_message)-1);
- m_main_wi.set_error_condition(error_condition);
+ set_error_condition(error_condition);
m_status= DA_ERROR;
DBUG_VOID_RETURN;
}
-/**
- Mark the diagnostics area as 'DISABLED'.
-
- This is used in rare cases when the COM_ command at hand sends a response
- in a custom format. One example is the query cache, another is
- COM_STMT_PREPARE.
-*/
-
-void
-Diagnostics_area::disable_status()
+void Diagnostics_area::disable_status()
{
DBUG_ASSERT(! is_set());
m_status= DA_DISABLED;
}
-Warning_info::Warning_info(ulonglong warn_id_arg, bool allow_unlimited_warnings)
- :m_current_statement_warn_count(0),
- m_current_row_for_warning(1),
- m_warn_id(warn_id_arg),
- m_error_condition(NULL),
- m_allow_unlimited_warnings(allow_unlimited_warnings),
- m_read_only(FALSE)
-{
- /* Initialize sub structures */
- init_sql_alloc(&m_warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
- m_warn_list.empty();
- memset(m_warn_count, 0, sizeof(m_warn_count));
-}
-
-Warning_info::~Warning_info()
-{
- free_root(&m_warn_root,MYF(0));
-}
-
-bool Warning_info::has_sql_condition(const char *message_str,
- ulong message_length) const
+bool Diagnostics_area::has_sql_condition(const char *message_str,
+ ulong message_length) const
{
Diagnostics_area::Sql_condition_iterator it(m_warn_list);
const Sql_condition *err;
@@ -601,9 +544,9 @@ bool Warning_info::has_sql_condition(con
}
-void Warning_info::clear(ulonglong new_id)
+void Diagnostics_area::clear_warning_info(ulonglong new_id)
{
- id(new_id);
+ set_warning_info_id(new_id);
m_warn_list.empty();
m_marked_sql_conditions.empty();
free_root(&m_warn_root, MYF(0));
@@ -614,7 +557,7 @@ void Warning_info::clear(ulonglong new_i
}
-void Warning_info::append_warning_info(THD *thd, const Warning_info *source)
+void Diagnostics_area::append_warning_info(THD *thd, const Diagnostics_area *source)
{
const Sql_condition *err;
Diagnostics_area::Sql_condition_iterator it(source->m_warn_list);
@@ -623,7 +566,7 @@ void Warning_info::append_warning_info(T
while ((err= it++))
{
// Do not use ::push_warning() to avoid invocation of THD-internal-handlers.
- Sql_condition *new_error= Warning_info::push_warning(thd, err);
+ Sql_condition *new_error= Diagnostics_area::push_warning(thd, err);
if (src_error_condition && src_error_condition == err)
set_error_condition(new_error);
@@ -637,7 +580,7 @@ void Warning_info::append_warning_info(T
void Diagnostics_area::copy_non_errors_from_da(THD *thd,
const Diagnostics_area *src_da)
{
- Sql_condition_iterator it(src_da->m_main_wi.m_warn_list);
+ Sql_condition_iterator it(src_da->m_warn_list);
const Sql_condition *cond;
while ((cond= it++))
@@ -645,15 +588,15 @@ void Diagnostics_area::copy_non_errors_f
if (cond->get_level() == Sql_condition::WARN_LEVEL_ERROR)
continue;
- Sql_condition *new_condition= m_main_wi.push_warning(thd, cond);
+ Sql_condition *new_condition= push_warning(thd, cond);
- if (src_da->m_main_wi.is_marked_for_removal(cond))
- m_main_wi.mark_condition_for_removal(new_condition);
+ if (src_da->is_marked_for_removal(cond))
+ mark_condition_for_removal(new_condition);
}
}
-void Warning_info::mark_sql_conditions_for_removal()
+void Diagnostics_area::mark_sql_conditions_for_removal()
{
Sql_condition_list::Iterator it(m_warn_list);
Sql_condition *cond;
@@ -663,7 +606,7 @@ void Warning_info::mark_sql_conditions_f
}
-void Warning_info::remove_marked_sql_conditions()
+void Diagnostics_area::remove_marked_sql_conditions()
{
List_iterator_fast<Sql_condition> it(m_marked_sql_conditions);
Sql_condition *cond;
@@ -681,7 +624,7 @@ void Warning_info::remove_marked_sql_con
}
-bool Warning_info::is_marked_for_removal(const Sql_condition *cond) const
+bool Diagnostics_area::is_marked_for_removal(const Sql_condition *cond) const
{
List_iterator_fast<Sql_condition> it(
const_cast<List<Sql_condition>&> (m_marked_sql_conditions));
@@ -697,16 +640,17 @@ bool Warning_info::is_marked_for_removal
}
-void Warning_info::reserve_space(THD *thd, uint count)
+void Diagnostics_area::reserve_space(THD *thd, uint count)
{
while ((m_warn_list.elements() + count) > thd->variables.max_error_count)
m_warn_list.remove(m_warn_list.front());
}
-Sql_condition *Warning_info::push_warning(THD *thd,
- uint sql_errno, const char* sqlstate,
- Sql_condition::enum_warning_level level,
- const char *msg)
+
+Sql_condition *Diagnostics_area::push_warning(THD *thd,
+ uint sql_errno, const char* sqlstate,
+ Sql_condition::enum_warning_level level,
+ const char *msg)
{
Sql_condition *cond= NULL;
@@ -715,10 +659,10 @@ Sql_condition *Warning_info::push_warnin
if (m_allow_unlimited_warnings ||
m_warn_list.elements() < thd->variables.max_error_count)
{
- cond= new (& m_warn_root) Sql_condition(& m_warn_root);
+ cond= new (& m_warn_root) Sql_condition(& m_warn_root, sql_errno,
+ sqlstate, level, msg);
if (cond)
{
- cond->set(sql_errno, sqlstate, level, msg);
m_warn_list.push_back(cond);
}
}
@@ -729,7 +673,8 @@ Sql_condition *Warning_info::push_warnin
return cond;
}
-Sql_condition *Warning_info::push_warning(THD *thd, const Sql_condition *sql_condition)
+
+Sql_condition *Diagnostics_area::push_warning(THD *thd, const Sql_condition *sql_condition)
{
Sql_condition *new_condition= push_warning(thd,
sql_condition->get_sql_errno(),
@@ -748,7 +693,7 @@ void Diagnostics_area::push_diagnostics_
{
DBUG_ASSERT(da->m_stacked_da == NULL);
da->m_stacked_da= this;
- da->m_main_wi.append_warning_info(thd, &m_main_wi);
+ da->append_warning_info(thd, this);
}
=== modified file 'sql/sql_error.h'
--- a/sql/sql_error.h 2012-07-04 13:47:16 +0000
+++ b/sql/sql_error.h 2012-07-04 14:06:47 +0000
@@ -48,13 +48,15 @@ public:
Get the MESSAGE_TEXT of this condition.
@return the message text.
*/
- const char* get_message_text() const;
+ const char* get_message_text() const
+ { return m_message_text.ptr(); }
/**
Get the MESSAGE_OCTET_LENGTH of this condition.
@return the length in bytes of the message text.
*/
- int get_message_octet_length() const;
+ int get_message_octet_length() const
+ { return m_message_text.length(); }
/**
Get the SQLSTATE of this condition.
@@ -91,7 +93,7 @@ private:
which should be used.
*/
friend class THD;
- friend class Warning_info;
+ friend class Diagnostics_area;
friend class Sql_cmd_common_signal;
friend class Sql_cmd_signal;
friend class Sql_cmd_resignal;
@@ -99,25 +101,26 @@ private:
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 Sql_condition.
- */
- Sql_condition();
+ Constructor.
- /**
- Complete the Sql_condition initialisation.
- @param mem_root The memory root to use for the condition items
- of this condition
+ @param mem_root Memory root to use for the condition items
+ of this condition.
*/
- void init(MEM_ROOT *mem_root);
+ Sql_condition(MEM_ROOT *mem_root);
/**
Constructor.
- @param mem_root The memory root to use for the condition items
- of this condition
- */
- Sql_condition(MEM_ROOT *mem_root);
+
+ @param mem_root Memory root to use for the condition items
+ of this condition.
+ @param sql_errno Error number.
+ @param sqlstate SQLSTATE.
+ @param level Condition level - error, warning or note.
+ @param msg Message text.
+ */
+ Sql_condition(MEM_ROOT *mem_root, uint sql_errno, const char* sqlstate,
+ Sql_condition::enum_warning_level level,
+ const char *msg);
/** Destructor. */
~Sql_condition()
@@ -130,18 +133,6 @@ private:
void copy_opt_attributes(const Sql_condition *cond);
/**
- Set this condition area with a fixed message text.
- @param thd the current thread.
- @param code the error number for this condition.
- @param str the message text for this condition.
- @param level the error level for this condition.
- @param MyFlags additional flags.
- */
- void set(uint sql_errno, const char* sqlstate,
- Sql_condition::enum_warning_level level,
- const char* msg);
-
- /**
Set the condition message test.
@param str Message text, expressed in the character set derived from
the server --language option
@@ -157,9 +148,7 @@ private:
/** Set the SUBCLASS_ORIGIN of this condition. */
void set_subclass_origin();
- /**
- Clear this SQL condition.
- */
+ /** Clear this SQL condition. */
void clear();
private:
@@ -218,307 +207,6 @@ private:
///////////////////////////////////////////////////////////////////////////
-/**
- 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). */
- Sql_condition_list m_warn_list;
-
- /** A break down of the number of warnings per severity (level). */
- 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_current_statement_warn_count 0, whereas m_warn_list is not empty.
- */
- uint m_current_statement_warn_count;
-
- /*
- Row counter, to print in errors and warnings. Not increased in
- create_sort_index(); may differ from examined_row_count.
- */
- ulong m_current_row_for_warning;
-
- /** 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;
-
- /** Read only status. */
- bool m_read_only;
-
- List<Sql_condition> m_marked_sql_conditions;
-
- Warning_info(ulonglong warn_id_arg, bool allow_unlimited_warnings);
- ~Warning_info();
-
- 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(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
- during the query, without risk of clearing some warnings
- that have been generated by the current statement.
-
- @todo: This is a sign of sloppy coding. Instead we need to
- designate one place in a statement life cycle where we call
- Warning_info::clear().
-
- @param query_id Current query id.
- */
- void opt_clear(ulonglong query_id)
- {
- if (query_id != m_warn_id)
- clear(query_id);
- }
-
- /**
- Concatenate the list of warnings.
-
- 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 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_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
- the number of rows returned by SHOW WARNINGS.
- */
- ulong warn_count() const
- {
- /*
- 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) Sql_condition::WARN_LEVEL_NOTE] +
- m_warn_count[(uint) Sql_condition::WARN_LEVEL_ERROR] +
- m_warn_count[(uint) Sql_condition::WARN_LEVEL_WARN]);
- }
-
- /**
- 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_list.elements();
- }
-
- /** Id of the warning information area. */
- 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.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; }
-
- /** 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.
-
- @param thd Thread context.
- @param sql_condition SQL-condition to copy values from.
-
- @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.
- This is a privileged operation, reserved for the implementation of
- diagnostics related statements, to enforce that the statement area is
- left untouched during execution.
- The diagnostics statements are:
- - SHOW WARNINGS
- - SHOW ERRORS
- - GET DIAGNOSTICS
- @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.
- */
- bool is_read_only() const
- { return m_read_only; }
-
- /**
- @return SQL-condition, which corresponds to the error state in
- Diagnostics_area.
-
- @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:
- // - is_marked_for_removal()
- friend class Diagnostics_area;
-};
-
uint err_conv(char *buff, size_t to_length, const char *from,
size_t from_length, const CHARSET_INFO *from_cs);
@@ -579,9 +267,18 @@ public:
*/
class Diagnostics_area
{
+ /** 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;
+
public:
/** Const iterator used to iterate through the warning list. */
- typedef Warning_info::Sql_condition_list::Const_Iterator
+ typedef Sql_condition_list::Const_Iterator
Sql_condition_iterator;
enum enum_diagnostics_status
@@ -598,6 +295,10 @@ public:
DA_DISABLED
};
+ Diagnostics_area();
+ Diagnostics_area(ulonglong warning_info_id, bool allow_unlimited_warnings);
+ ~Diagnostics_area();
+
void set_overwrite_status(bool can_overwrite_status)
{ m_can_overwrite_status= can_overwrite_status; }
@@ -605,21 +306,58 @@ public:
void set_is_sent(bool is_sent) { m_is_sent= is_sent; }
+ /**
+ Set OK status -- ends commands that do not return a
+ result set, e.g. INSERT/UPDATE/DELETE.
+ */
void set_ok_status(ulonglong affected_rows,
ulonglong last_insert_id,
const char *message);
+ /**
+ Set EOF status.
+ */
void set_eof_status(THD *thd);
- void set_error_status(uint sql_errno);
+ /**
+ Set ERROR status in the Diagnostics Area. This function should be used to
+ report fatal errors (such as out-of-memory errors) when no further
+ processing is possible.
+
+ @param sql_errno SQL-condition error number
+ */
+ void set_error_status(uint sql_errno);
+
+ /**
+ Set ERROR status in the Diagnostics Area.
+
+ @note error_condition may be NULL. It happens if a) OOM error is being
+ reported; or b) when Warning_info is full.
+ @param sql_errno SQL-condition error number
+ @param message SQL-condition message
+ @param sqlstate SQL-condition state
+ @param error_condition SQL-condition object representing the error state
+ */
void set_error_status(uint sql_errno,
const char *message,
const char *sqlstate,
const Sql_condition *error_condition);
+ /**
+ Mark the diagnostics area as 'DISABLED'.
+
+ This is used in rare cases when the COM_ command at hand sends a response
+ in a custom format. One example is the query cache, another is
+ COM_STMT_PREPARE.
+ */
void disable_status();
+ /**
+ Clear this diagnostics area.
+
+ Normally called at the end of a statement.
+ */
void reset_diagnostics_area();
bool is_set() const { return m_status != DA_EMPTY; }
@@ -655,14 +393,13 @@ public:
return m_statement_warn_count;
}
- Diagnostics_area();
- Diagnostics_area(ulonglong warning_info_id, bool allow_unlimited_warnings);
-
+ /** Set id of the warning information area. */
void set_warning_info_id(ulonglong id)
- { m_main_wi.id(id); }
+ { m_warn_id= id; }
+ /** Id of the warning information area. */
ulonglong warning_info_id() const
- { return m_main_wi.id(); }
+ { return m_warn_id; }
/**
Compare given current and given diagnostic area
@@ -675,82 +412,188 @@ public:
@return false if they are equal, true if they are not.
*/
bool diagnostics_area_changed(const Diagnostics_area *da) const
- { return m_main_wi.id() != da->m_main_wi.id(); }
+ { return warning_info_id() != da->warning_info_id(); }
+ /** Do we have any errors and warnings that we can *show*? */
bool is_warning_info_empty() const
- { return m_main_wi.is_empty(); }
+ { return m_warn_list.is_empty(); }
+ /** Return the number of warnings thrown by the current statement. */
ulong current_statement_warn_count() const
- { return m_main_wi.current_statement_warn_count(); }
-
- bool has_sql_condition(const char *message_str, ulong message_length) const
- { return m_main_wi.has_sql_condition(message_str, message_length); }
+ { return m_current_statement_warn_count; }
+ /**
+ 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_main_wi.reset_for_next_command(); }
+ { m_current_statement_warn_count= 0; }
+
+ /**
+ 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 id);
+
+ /**
+ Only clear warning info if haven't yet done that already
+ for the current query. Allows to be issued at any time
+ during the query, without risk of clearing some warnings
+ that have been generated by the current statement.
- void clear_warning_info(ulonglong id)
- { m_main_wi.clear(id); }
+ @todo: This is a sign of sloppy coding. Instead we need to
+ designate one place in a statement life cycle where we call
+ Warning_info::clear().
+ @param query_id Current query id.
+ */
void opt_clear_warning_info(ulonglong query_id)
- { m_main_wi.opt_clear(query_id); }
+ {
+ if (query_id != m_warn_id)
+ clear_warning_info(query_id);
+ }
+ /** Return the current counter value. */
ulong current_row_for_warning() const
- { return m_main_wi.current_row_for_warning(); }
+ { return m_current_row_for_warning; }
+ /** Increment the current row counter to point at the next row. */
void inc_current_row_for_warning()
- { m_main_wi.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_main_wi.reset_current_row_for_warning(); }
+ { m_current_row_for_warning= 1; }
+ /**
+ Read only status.
+ @return the read only property.
+ */
bool is_warning_info_read_only() const
- { return m_main_wi.is_read_only(); }
+ { return m_read_only; }
+ /**
+ Set the read only status for this statement area.
+ This is a privileged operation, reserved for the implementation of
+ diagnostics related statements, to enforce that the statement area is
+ left untouched during execution.
+ The diagnostics statements are:
+ - SHOW WARNINGS
+ - SHOW ERRORS
+ - GET DIAGNOSTICS
+ @param read_only the read only property to set.
+ */
void set_warning_info_read_only(bool read_only)
- { m_main_wi.set_read_only(read_only); }
+ { m_read_only= read_only; }
+ /**
+ 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_main_wi.error_count(); }
+ { return m_warn_count[(uint) Sql_condition::WARN_LEVEL_ERROR]; }
+ /**
+ Used for @@warning_count system variable, which prints
+ the number of rows returned by SHOW WARNINGS.
+ */
ulong warn_count() const
- { return m_main_wi.warn_count(); }
+ {
+ /*
+ 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) Sql_condition::WARN_LEVEL_NOTE] +
+ m_warn_count[(uint) Sql_condition::WARN_LEVEL_ERROR] +
+ m_warn_count[(uint) Sql_condition::WARN_LEVEL_WARN]);
+ }
+ /**
+ The number of conditions (errors, warnings and notes) in the list.
+ */
uint cond_count() const
- { return m_main_wi.cond_count(); }
+ { return m_warn_list.elements(); }
Sql_condition_iterator sql_conditions() const
- { return m_main_wi.m_warn_list; }
+ { return m_warn_list; }
+
+ /** 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_condition SQL-condition to copy values from.
+
+ @return a pointer to the added SQL-condition.
+ */
+ Sql_condition *push_warning(THD *thd, const Sql_condition *sql_condition);
- void reserve_space(THD *thd, uint count)
- { m_main_wi.reserve_space(thd, count); }
+ /**
+ Add a new SQL-condition to the current list and increment the respective
+ counters.
- Sql_condition *push_warning(THD *thd, const Sql_condition *sql_condition)
- { return m_main_wi.push_warning(thd, sql_condition); }
+ @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)
- {
- return m_main_wi.push_warning(thd, sql_errno, sqlstate, level, msg);
- }
+ const char* msg);
+
+ /**
+ @return SQL-condition, which corresponds to the error state in
+ Diagnostics_area.
- void mark_sql_conditions_for_removal()
- { m_main_wi.mark_sql_conditions_for_removal(); }
+ @see m_error_condition.
+ */
+ const Sql_condition *get_error_condition() const
+ { return m_error_condition; }
- void unmark_sql_conditions_from_removal()
- { m_main_wi.unmark_sql_conditions_from_removal(); }
+ /**
+ Mark active SQL-conditions for later removal.
+ This is done to simulate stacked DAs for HANDLER statements.
+ */
+ void mark_sql_conditions_for_removal();
- void remove_marked_sql_conditions()
- { m_main_wi.remove_marked_sql_conditions(); }
+ /**
+ 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(); }
- const Sql_condition *get_error_condition() const
- { return m_main_wi.get_error_condition(); }
+ /**
+ Remove SQL-conditions that are marked for deletion.
+ This is done to simulate stacked DAs for HANDLER statements.
+ */
+ void remove_marked_sql_conditions();
void copy_sql_conditions_from_da(THD *thd, const Diagnostics_area *src_da)
- { m_main_wi.append_warning_info(thd, &src_da->m_main_wi); }
+ { append_warning_info(thd, src_da); }
/**
Copy Sql_conditions that are not WARN_LEVEL_ERROR from the source
@@ -795,23 +638,106 @@ private:
{ return m_stacked_da; }
private:
+ /**
+ Concatenate the list of warnings.
+
+ 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 append_warning_info(THD *thd, const Diagnostics_area *source);
+
+ /**
+ 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); }
+
+ /**
+ 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; }
+
+private:
+ /** Pointer to the diagnostic area below on the stack. */
+ Diagnostics_area *m_stacked_da;
+
+ /** A memory root to allocate warnings and errors */
+ MEM_ROOT m_warn_root;
+
+ /** List of warnings of all severities (levels). */
+ Sql_condition_list m_warn_list;
+
+ /**
+ 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;
+
+ List<Sql_condition> m_marked_sql_conditions;
+
/** 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;
+ /** Indicates if push_warning() allows unlimited number of warnings. */
+ bool m_allow_unlimited_warnings;
+
+ /** Read only status. */
+ bool m_read_only;
+
/** Message buffer. Can be used by OK or ERROR status. */
char m_message[MYSQL_ERRMSG_SIZE];
+ char m_sqlstate[SQLSTATE_LENGTH+1];
+
+ enum_diagnostics_status m_status;
+
/**
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
@@ -840,12 +766,25 @@ private:
*/
uint m_statement_warn_count;
- enum_diagnostics_status m_status;
+ /**
+ 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_current_statement_warn_count 0, whereas m_warn_list is not empty.
+ */
+ uint m_current_statement_warn_count;
- Warning_info m_main_wi;
+ /** A break down of the number of warnings per severity (level). */
+ uint m_warn_count[(uint) Sql_condition::WARN_LEVEL_END];
- /** Pointer to the diagnostic area below on the stack. */
- Diagnostics_area *m_stacked_da;
+ /**
+ Row counter, to print in errors and warnings. Not increased in
+ create_sort_index(); may differ from examined_row_count.
+ */
+ ulong m_current_row_for_warning;
+
+ /** Used to optionally clear warnings only once per statement. */
+ ulonglong m_warn_id;
friend class THD;
};
=== modified file 'sql/sql_signal.cc'
--- a/sql/sql_signal.cc 2012-03-19 17:59:14 +0000
+++ b/sql/sql_signal.cc 2012-07-04 14:06:47 +0000
@@ -18,6 +18,7 @@
#include "sp_pcontext.h"
#include "sp_rcontext.h"
#include "sql_signal.h"
+#include "sql_error.h"
/*
The parser accepts any error code (desired)
@@ -123,15 +124,15 @@ void Sql_cmd_common_signal::eval_default
DBUG_ASSERT(sqlstate);
/* SQLSTATE class "00": illegal, rejected in the parser. */
- DBUG_ASSERT((sqlstate[0] != '0') || (sqlstate[1] != '0'));
+ DBUG_ASSERT(!is_sqlstate_completion(sqlstate));
- if ((sqlstate[0] == '0') && (sqlstate[1] == '1'))
+ if (is_sqlstate_warning(sqlstate))
{
/* SQLSTATE class "01": warning. */
assign_defaults(cond, set_defaults,
Sql_condition::WARN_LEVEL_WARN, ER_SIGNAL_WARN);
}
- else if ((sqlstate[0] == '0') && (sqlstate[1] == '2'))
+ else if (is_sqlstate_not_found(sqlstate))
{
/* SQLSTATE class "02": not found. */
assign_defaults(cond, set_defaults,
@@ -503,11 +504,11 @@ bool Sql_cmd_resignal::execute(THD *thd)
DBUG_RETURN(true);
}
- Sql_condition signaled_err(thd->mem_root);
- signaled_err.set(signaled->sql_errno,
- signaled->sql_state,
- signaled->level,
- signaled->message);
+ Sql_condition signaled_err(thd->mem_root,
+ signaled->sql_errno,
+ signaled->sql_state,
+ signaled->level,
+ signaled->message);
if (m_cond) // RESIGNAL with signal_value.
No bundle (reason: useless for push emails).
| Thread |
|---|
| • bzr push into mysql-trunk-wl6406 branch (jon.hauglid:3969 to 3970) WL#6406 | Jon Olav Hauglid | 4 Jul |