Commit 6010662c authored by Alexander Barkov's avatar Alexander Barkov

MDEV-11037 Diagnostics_area refactoring for user defined exceptions

parent ffca1e48
...@@ -36,10 +36,10 @@ bool sp_condition_value::equals(const sp_condition_value *cv) const ...@@ -36,10 +36,10 @@ bool sp_condition_value::equals(const sp_condition_value *cv) const
switch (type) switch (type)
{ {
case sp_condition_value::ERROR_CODE: case sp_condition_value::ERROR_CODE:
return (mysqlerr == cv->mysqlerr); return (get_sql_errno() == cv->get_sql_errno());
case sp_condition_value::SQLSTATE: case sp_condition_value::SQLSTATE:
return (strcmp(sql_state, cv->sql_state) == 0); return Sql_state::eq(cv);
default: default:
return true; return true;
...@@ -354,8 +354,7 @@ bool sp_pcontext::check_duplicate_handler( ...@@ -354,8 +354,7 @@ bool sp_pcontext::check_duplicate_handler(
sp_handler* sp_handler*
sp_pcontext::find_handler(const char *sql_state, sp_pcontext::find_handler(const Sql_state_errno *value,
uint sql_errno,
Sql_condition::enum_warning_level level) const Sql_condition::enum_warning_level level) const
{ {
sp_handler *found_handler= NULL; sp_handler *found_handler= NULL;
...@@ -373,7 +372,7 @@ sp_pcontext::find_handler(const char *sql_state, ...@@ -373,7 +372,7 @@ sp_pcontext::find_handler(const char *sql_state,
switch (cv->type) switch (cv->type)
{ {
case sp_condition_value::ERROR_CODE: case sp_condition_value::ERROR_CODE:
if (sql_errno == cv->mysqlerr && if (value->get_sql_errno() == cv->get_sql_errno() &&
(!found_cv || (!found_cv ||
found_cv->type > sp_condition_value::ERROR_CODE)) found_cv->type > sp_condition_value::ERROR_CODE))
{ {
...@@ -383,7 +382,7 @@ sp_pcontext::find_handler(const char *sql_state, ...@@ -383,7 +382,7 @@ sp_pcontext::find_handler(const char *sql_state,
break; break;
case sp_condition_value::SQLSTATE: case sp_condition_value::SQLSTATE:
if (strcmp(sql_state, cv->sql_state) == 0 && if (cv->Sql_state::eq(value) &&
(!found_cv || (!found_cv ||
found_cv->type > sp_condition_value::SQLSTATE)) found_cv->type > sp_condition_value::SQLSTATE))
{ {
...@@ -393,7 +392,7 @@ sp_pcontext::find_handler(const char *sql_state, ...@@ -393,7 +392,7 @@ sp_pcontext::find_handler(const char *sql_state,
break; break;
case sp_condition_value::WARNING: case sp_condition_value::WARNING:
if ((is_sqlstate_warning(sql_state) || if ((value->Sql_state::is_warning() ||
level == Sql_condition::WARN_LEVEL_WARN) && !found_cv) level == Sql_condition::WARN_LEVEL_WARN) && !found_cv)
{ {
found_cv= cv; found_cv= cv;
...@@ -402,7 +401,7 @@ sp_pcontext::find_handler(const char *sql_state, ...@@ -402,7 +401,7 @@ sp_pcontext::find_handler(const char *sql_state,
break; break;
case sp_condition_value::NOT_FOUND: case sp_condition_value::NOT_FOUND:
if (is_sqlstate_not_found(sql_state) && !found_cv) if (value->Sql_state::is_not_found() && !found_cv)
{ {
found_cv= cv; found_cv= cv;
found_handler= h; found_handler= h;
...@@ -418,7 +417,7 @@ sp_pcontext::find_handler(const char *sql_state, ...@@ -418,7 +417,7 @@ sp_pcontext::find_handler(const char *sql_state,
and it should be caught. and it should be caught.
*/ */
if (((current_thd->variables.sql_mode & MODE_ORACLE) || if (((current_thd->variables.sql_mode & MODE_ORACLE) ||
(is_sqlstate_exception(sql_state) && (value->Sql_state::is_exception() &&
level == Sql_condition::WARN_LEVEL_ERROR)) && !found_cv) level == Sql_condition::WARN_LEVEL_ERROR)) && !found_cv)
{ {
found_cv= cv; found_cv= cv;
...@@ -467,7 +466,7 @@ sp_pcontext::find_handler(const char *sql_state, ...@@ -467,7 +466,7 @@ sp_pcontext::find_handler(const char *sql_state,
if (!p || !p->m_parent) if (!p || !p->m_parent)
return NULL; return NULL;
return p->m_parent->find_handler(sql_state, sql_errno, level); return p->m_parent->find_handler(value, level);
} }
......
...@@ -127,12 +127,8 @@ class sp_label : public Sql_alloc ...@@ -127,12 +127,8 @@ class sp_label : public Sql_alloc
/// In some sense, this class is a union -- a set of filled attributes /// In some sense, this class is a union -- a set of filled attributes
/// depends on the sp_condition_value::type value. /// depends on the sp_condition_value::type value.
class sp_condition_value : public Sql_alloc class sp_condition_value : public Sql_alloc, public Sql_state_errno
{ {
void init_sql_state()
{
sql_state[0]= '\0';
}
public: public:
enum enum_type enum enum_type
{ {
...@@ -146,44 +142,30 @@ class sp_condition_value : public Sql_alloc ...@@ -146,44 +142,30 @@ class sp_condition_value : public Sql_alloc
/// Type of the condition value. /// Type of the condition value.
enum_type type; enum_type type;
/// SQLSTATE of the condition value.
char sql_state[SQLSTATE_LENGTH+1];
/// MySQL error code of the condition value.
uint mysqlerr;
public: public:
sp_condition_value(uint _mysqlerr) sp_condition_value(uint _mysqlerr)
:Sql_alloc(), :Sql_alloc(),
type(ERROR_CODE), Sql_state_errno(_mysqlerr),
mysqlerr(_mysqlerr) type(ERROR_CODE)
{ init_sql_state(); } { }
sp_condition_value(uint _mysqlerr, const char *_sql_state) sp_condition_value(uint _mysqlerr, const char *_sql_state)
:Sql_alloc(), :Sql_alloc(),
type(ERROR_CODE), Sql_state_errno(_mysqlerr, _sql_state),
mysqlerr(_mysqlerr) type(ERROR_CODE)
{ { }
memcpy(sql_state, _sql_state, SQLSTATE_LENGTH);
sql_state[SQLSTATE_LENGTH]= 0;
}
sp_condition_value(const char *_sql_state) sp_condition_value(const char *_sql_state)
:Sql_alloc(), :Sql_alloc(),
type(SQLSTATE), Sql_state_errno(0, _sql_state),
mysqlerr(0) type(SQLSTATE)
{ { }
memcpy(sql_state, _sql_state, SQLSTATE_LENGTH);
sql_state[SQLSTATE_LENGTH]= 0;
}
sp_condition_value(enum_type _type) sp_condition_value(enum_type _type)
:Sql_alloc(), :Sql_alloc(),
type(_type), type(_type)
mysqlerr(0)
{ {
DBUG_ASSERT(type != ERROR_CODE && type != SQLSTATE); DBUG_ASSERT(type != ERROR_CODE && type != SQLSTATE);
init_sql_state();
} }
/// Check if two instances of sp_condition_value are equal or not. /// Check if two instances of sp_condition_value are equal or not.
...@@ -192,8 +174,6 @@ class sp_condition_value : public Sql_alloc ...@@ -192,8 +174,6 @@ class sp_condition_value : public Sql_alloc
/// ///
/// @return true if the instances are equal, false otherwise. /// @return true if the instances are equal, false otherwise.
bool equals(const sp_condition_value *cv) const; bool equals(const sp_condition_value *cv) const;
bool has_sql_state() const { return sql_state[0] != '\0'; }
}; };
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
...@@ -532,13 +512,11 @@ class sp_pcontext : public Sql_alloc ...@@ -532,13 +512,11 @@ class sp_pcontext : public Sql_alloc
/// Find an SQL handler for the given SQL condition according to the /// Find an SQL handler for the given SQL condition according to the
/// SQL-handler resolution rules. This function is used at runtime. /// SQL-handler resolution rules. This function is used at runtime.
/// ///
/// @param sql_state The SQL condition state /// @param value The error code and the SQL state
/// @param sql_errno The error code
/// @param level The SQL condition level /// @param level The SQL condition level
/// ///
/// @return a pointer to the found SQL-handler or NULL. /// @return a pointer to the found SQL-handler or NULL.
sp_handler *find_handler(const char *sql_state, sp_handler *find_handler(const Sql_state_errno *value,
uint sql_errno,
Sql_condition::enum_warning_level level) const; Sql_condition::enum_warning_level level) const;
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
......
...@@ -228,9 +228,7 @@ bool sp_rcontext::handle_sql_condition(THD *thd, ...@@ -228,9 +228,7 @@ bool sp_rcontext::handle_sql_condition(THD *thd,
if (thd->is_error()) if (thd->is_error())
{ {
found_handler= found_handler=
cur_spi->m_ctx->find_handler(da->get_sqlstate(), cur_spi->m_ctx->find_handler(da, Sql_condition::WARN_LEVEL_ERROR);
da->sql_errno(),
Sql_condition::WARN_LEVEL_ERROR);
if (found_handler) if (found_handler)
found_condition= da->get_error_condition(); found_condition= da->get_error_condition();
...@@ -246,9 +244,7 @@ bool sp_rcontext::handle_sql_condition(THD *thd, ...@@ -246,9 +244,7 @@ bool sp_rcontext::handle_sql_condition(THD *thd,
{ {
Sql_condition *condition= Sql_condition *condition=
new (callers_arena->mem_root) Sql_condition(callers_arena->mem_root); new (callers_arena->mem_root) Sql_condition(callers_arena->mem_root);
condition->set(da->sql_errno(), da->get_sqlstate(), condition->set(da, Sql_condition::WARN_LEVEL_ERROR, da->message());
Sql_condition::WARN_LEVEL_ERROR,
da->message());
found_condition= condition; found_condition= condition;
} }
} }
...@@ -267,9 +263,7 @@ bool sp_rcontext::handle_sql_condition(THD *thd, ...@@ -267,9 +263,7 @@ bool sp_rcontext::handle_sql_condition(THD *thd,
c->get_level() == Sql_condition::WARN_LEVEL_NOTE) c->get_level() == Sql_condition::WARN_LEVEL_NOTE)
{ {
const sp_handler *handler= const sp_handler *handler=
cur_spi->m_ctx->find_handler(c->get_sqlstate(), cur_spi->m_ctx->find_handler(c, c->get_level());
c->get_sql_errno(),
c->get_level());
if (handler) if (handler)
{ {
found_handler= handler; found_handler= handler;
......
...@@ -120,18 +120,9 @@ class sp_rcontext : public Sql_alloc ...@@ -120,18 +120,9 @@ class sp_rcontext : public Sql_alloc
/// standard SQL-condition processing (Diagnostics_area should contain an /// standard SQL-condition processing (Diagnostics_area should contain an
/// object for active SQL-condition, not just information stored in DA's /// object for active SQL-condition, not just information stored in DA's
/// fields). /// fields).
class Sql_condition_info : public Sql_alloc class Sql_condition_info : public Sql_alloc, public Sql_state_errno_level
{ {
public: public:
/// SQL error code.
uint sql_errno;
/// Error level.
Sql_condition::enum_warning_level level;
/// SQLSTATE.
char sql_state[SQLSTATE_LENGTH + 1];
/// Text message. /// Text message.
char *message; char *message;
...@@ -141,12 +132,8 @@ class sp_rcontext : public Sql_alloc ...@@ -141,12 +132,8 @@ class sp_rcontext : public Sql_alloc
/// @param arena Query arena for SP /// @param arena Query arena for SP
Sql_condition_info(const Sql_condition *_sql_condition, Sql_condition_info(const Sql_condition *_sql_condition,
Query_arena *arena) Query_arena *arena)
:sql_errno(_sql_condition->get_sql_errno()), :Sql_state_errno_level(*_sql_condition)
level(_sql_condition->get_level())
{ {
memcpy(sql_state, _sql_condition->get_sqlstate(), SQLSTATE_LENGTH);
sql_state[SQLSTATE_LENGTH]= '\0';
message= strdup_root(arena->mem_root, _sql_condition->get_message_text()); message= strdup_root(arena->mem_root, _sql_condition->get_message_text());
} }
}; };
......
...@@ -185,11 +185,8 @@ Sql_condition::Sql_condition() ...@@ -185,11 +185,8 @@ Sql_condition::Sql_condition()
m_column_name((const char*) NULL, 0, & my_charset_utf8_bin), m_column_name((const char*) NULL, 0, & my_charset_utf8_bin),
m_cursor_name((const char*) NULL, 0, & my_charset_utf8_bin), m_cursor_name((const char*) NULL, 0, & my_charset_utf8_bin),
m_message_text(), m_message_text(),
m_sql_errno(0),
m_level(Sql_condition::WARN_LEVEL_ERROR),
m_mem_root(NULL) m_mem_root(NULL)
{ {
memset(m_returned_sqlstate, 0, sizeof(m_returned_sqlstate));
} }
void Sql_condition::init(MEM_ROOT *mem_root) void Sql_condition::init(MEM_ROOT *mem_root)
...@@ -229,12 +226,9 @@ Sql_condition::Sql_condition(MEM_ROOT *mem_root) ...@@ -229,12 +226,9 @@ Sql_condition::Sql_condition(MEM_ROOT *mem_root)
m_column_name((const char*) NULL, 0, & my_charset_utf8_bin), m_column_name((const char*) NULL, 0, & my_charset_utf8_bin),
m_cursor_name((const char*) NULL, 0, & my_charset_utf8_bin), m_cursor_name((const char*) NULL, 0, & my_charset_utf8_bin),
m_message_text(), m_message_text(),
m_sql_errno(0),
m_level(Sql_condition::WARN_LEVEL_ERROR),
m_mem_root(mem_root) m_mem_root(mem_root)
{ {
DBUG_ASSERT(mem_root != NULL); DBUG_ASSERT(mem_root != NULL);
memset(m_returned_sqlstate, 0, sizeof(m_returned_sqlstate));
} }
static void copy_string(MEM_ROOT *mem_root, String* dst, const String* src) static void copy_string(MEM_ROOT *mem_root, String* dst, const String* src)
...@@ -270,21 +264,6 @@ Sql_condition::copy_opt_attributes(const Sql_condition *cond) ...@@ -270,21 +264,6 @@ Sql_condition::copy_opt_attributes(const Sql_condition *cond)
copy_string(m_mem_root, & m_cursor_name, & cond->m_cursor_name); 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_builtin_message_text(msg);
m_level= level;
}
void void
Sql_condition::set_builtin_message_text(const char* str) Sql_condition::set_builtin_message_text(const char* str)
...@@ -312,13 +291,46 @@ Sql_condition::get_message_octet_length() const ...@@ -312,13 +291,46 @@ Sql_condition::get_message_octet_length() const
return m_message_text.length(); return m_message_text.length();
} }
void
Sql_condition::set_sqlstate(const char* sqlstate) void Sql_state_errno_level::assign_defaults(const Sql_state_errno *from)
{
DBUG_ASSERT(from);
int sqlerrno= from->get_sql_errno();
/*
SIGNAL is restricted in sql_yacc.yy to only signal SQLSTATE conditions.
*/
DBUG_ASSERT(from->has_sql_state());
set_sqlstate(from);
/* SQLSTATE class "00": illegal, rejected in the parser. */
DBUG_ASSERT(m_sqlstate[0] != '0' || get_sqlstate()[1] != '0');
if (Sql_state::is_warning()) /* SQLSTATE class "01": warning. */
{
m_level= Sql_condition::WARN_LEVEL_WARN;
m_sql_errno= sqlerrno ? sqlerrno : ER_SIGNAL_WARN;
}
else if (Sql_state::is_not_found()) /* SQLSTATE class "02": not found. */
{
m_level= Sql_condition::WARN_LEVEL_ERROR;
m_sql_errno= sqlerrno ? sqlerrno : ER_SIGNAL_NOT_FOUND;
}
else /* other SQLSTATE classes : error. */
{
m_level= Sql_condition::WARN_LEVEL_ERROR;
m_sql_errno= sqlerrno ? sqlerrno : ER_SIGNAL_EXCEPTION;
}
}
void Sql_condition::assign_defaults(THD *thd, const Sql_state_errno *from)
{ {
memcpy(m_returned_sqlstate, sqlstate, SQLSTATE_LENGTH); if (from)
m_returned_sqlstate[SQLSTATE_LENGTH]= '\0'; Sql_state_errno_level::assign_defaults(from);
if (!get_message_text())
set_builtin_message_text(ER(get_sql_errno()));
} }
Diagnostics_area::Diagnostics_area(bool initialize) Diagnostics_area::Diagnostics_area(bool initialize)
: is_bulk_execution(0), m_main_wi(0, false, initialize) : is_bulk_execution(0), m_main_wi(0, false, initialize)
{ {
...@@ -501,9 +513,7 @@ Diagnostics_area::set_error_status(uint sql_errno, ...@@ -501,9 +513,7 @@ Diagnostics_area::set_error_status(uint sql_errno,
return; return;
#endif #endif
m_sql_errno= sql_errno; set_condition_value(sql_errno, sqlstate);
memcpy(m_sqlstate, sqlstate, SQLSTATE_LENGTH);
m_sqlstate[SQLSTATE_LENGTH]= '\0';
strmake_buf(m_message, message); strmake_buf(m_message, message);
get_warning_info()->set_error_condition(error_condition); get_warning_info()->set_error_condition(error_condition);
...@@ -695,8 +705,7 @@ void Warning_info::reserve_space(THD *thd, uint count) ...@@ -695,8 +705,7 @@ void Warning_info::reserve_space(THD *thd, uint count)
} }
Sql_condition *Warning_info::push_warning(THD *thd, Sql_condition *Warning_info::push_warning(THD *thd,
uint sql_errno, const char* sqlstate, const Sql_state_errno_level *value,
Sql_condition::enum_warning_level level,
const char *msg) const char *msg)
{ {
Sql_condition *cond= NULL; Sql_condition *cond= NULL;
...@@ -709,11 +718,11 @@ Sql_condition *Warning_info::push_warning(THD *thd, ...@@ -709,11 +718,11 @@ Sql_condition *Warning_info::push_warning(THD *thd,
cond= new (& m_warn_root) Sql_condition(& m_warn_root); cond= new (& m_warn_root) Sql_condition(& m_warn_root);
if (cond) if (cond)
{ {
cond->set(sql_errno, sqlstate, level, msg); cond->set(value, msg);
m_warn_list.push_back(cond); m_warn_list.push_back(cond);
} }
} }
m_warn_count[(uint) level]++; m_warn_count[(uint) value->get_level()]++;
} }
m_current_statement_warn_count++; m_current_statement_warn_count++;
...@@ -721,12 +730,10 @@ Sql_condition *Warning_info::push_warning(THD *thd, ...@@ -721,12 +730,10 @@ Sql_condition *Warning_info::push_warning(THD *thd,
} }
Sql_condition *Warning_info::push_warning(THD *thd, const Sql_condition *sql_condition) Sql_condition *Warning_info::push_warning(THD *thd,
const Sql_condition *sql_condition)
{ {
Sql_condition *new_condition= push_warning(thd, Sql_condition *new_condition= push_warning(thd, sql_condition,
sql_condition->get_sql_errno(),
sql_condition->get_sqlstate(),
sql_condition->get_level(),
sql_condition->get_message_text()); sql_condition->get_message_text());
if (new_condition) if (new_condition)
......
...@@ -30,12 +30,119 @@ class my_decimal; ...@@ -30,12 +30,119 @@ class my_decimal;
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
/** class Sql_state
Representation of a SQL condition. {
A SQL condition can be a completion condition (note, warning), protected:
or an exception condition (error, not found). /**
*/ This member is always NUL terminated.
class Sql_condition : public Sql_alloc */
char m_sqlstate[SQLSTATE_LENGTH + 1];
public:
Sql_state()
{
memset(m_sqlstate, 0, sizeof(m_sqlstate));
}
Sql_state(const char *sqlstate)
{
set_sqlstate(sqlstate);
}
const char* get_sqlstate() const
{ return m_sqlstate; }
void set_sqlstate(const Sql_state *other)
{
*this= *other;
}
void set_sqlstate(const char *sqlstate)
{
memcpy(m_sqlstate, sqlstate, SQLSTATE_LENGTH);
m_sqlstate[SQLSTATE_LENGTH]= '\0';
}
bool eq(const Sql_state *other) const
{
return strcmp(m_sqlstate, other->m_sqlstate) == 0;
}
bool has_sql_state() const { return m_sqlstate[0] != '\0'; }
/**
Checks if this SQL state defines a WARNING condition.
Note: m_sqlstate must contain a valid SQL-state.
@retval true if this SQL state defines a WARNING condition.
@retval false otherwise.
*/
inline bool is_warning() const
{ return m_sqlstate[0] == '0' && m_sqlstate[1] == '1'; }
/**
Checks if this SQL state defines a NOT FOUND condition.
Note: m_sqlstate must contain a valid SQL-state.
@retval true if this SQL state defines a NOT FOUND condition.
@retval false otherwise.
*/
inline bool is_not_found() const
{ return m_sqlstate[0] == '0' && m_sqlstate[1] == '2'; }
/**
Checks if this SQL state defines an EXCEPTION condition.
Note: m_sqlstate must contain a valid SQL-state.
@retval true if this SQL state defines an EXCEPTION condition.
@retval false otherwise.
*/
inline bool is_exception() const
{ return m_sqlstate[0] != '0' || m_sqlstate[1] > '2'; }
};
class Sql_state_errno: public Sql_state
{
protected:
/**
MySQL extension, MYSQL_ERRNO condition item.
SQL error number. One of ER_ codes from share/errmsg.txt.
Set by set_error_status.
*/
uint m_sql_errno;
public:
Sql_state_errno()
:m_sql_errno(0)
{ }
Sql_state_errno(uint sql_errno)
:m_sql_errno(sql_errno)
{ }
Sql_state_errno(uint sql_errno, const char *sql_state)
:Sql_state(sql_state),
m_sql_errno(sql_errno)
{ }
/**
Get the SQL_ERRNO of this condition.
@return the sql error number condition item.
*/
uint get_sql_errno() const
{ return m_sql_errno; }
void set_condition_value(uint sql_errno, const char *sqlstate)
{
m_sql_errno= sql_errno;
set_sqlstate(sqlstate);
}
void set_condition_value(const Sql_state_errno *other)
{
*this= *other;
}
};
class Sql_state_errno_level: public Sql_state_errno
{ {
public: public:
/* /*
...@@ -47,6 +154,41 @@ class Sql_condition : public Sql_alloc ...@@ -47,6 +154,41 @@ class Sql_condition : public Sql_alloc
enum enum_warning_level enum enum_warning_level
{ WARN_LEVEL_NOTE, WARN_LEVEL_WARN, WARN_LEVEL_ERROR, WARN_LEVEL_END}; { WARN_LEVEL_NOTE, WARN_LEVEL_WARN, WARN_LEVEL_ERROR, WARN_LEVEL_END};
protected:
/** Severity (error, warning, note) of this condition. */
enum_warning_level m_level;
void assign_defaults(const Sql_state_errno *value);
public:
/**
Get the error level of this condition.
@return the error level condition item.
*/
enum_warning_level get_level() const
{ return m_level; }
Sql_state_errno_level()
:m_level(WARN_LEVEL_ERROR)
{ }
Sql_state_errno_level(uint sqlerrno, const char* sqlstate,
enum_warning_level level)
:Sql_state_errno(sqlerrno, sqlstate),
m_level(level)
{ }
};
/**
Representation of a SQL condition.
A SQL condition can be a completion condition (note, warning),
or an exception condition (error, not found).
*/
class Sql_condition : public Sql_alloc, public Sql_state_errno_level
{
public:
/** /**
Convert a bitmask consisting of MYSQL_TIME_{NOTE|WARN}_XXX bits Convert a bitmask consisting of MYSQL_TIME_{NOTE|WARN}_XXX bits
to WARN_LEVEL_XXX to WARN_LEVEL_XXX
...@@ -69,27 +211,6 @@ class Sql_condition : public Sql_alloc ...@@ -69,27 +211,6 @@ class Sql_condition : public Sql_alloc
*/ */
int get_message_octet_length() const; int get_message_octet_length() const;
/**
Get the SQLSTATE of this condition.
@return the sql state.
*/
const char* get_sqlstate() const
{ return m_returned_sqlstate; }
/**
Get the SQL_ERRNO of this condition.
@return the sql error number condition item.
*/
uint get_sql_errno() const
{ return m_sql_errno; }
/**
Get the error level of this condition.
@return the error level condition item.
*/
Sql_condition::enum_warning_level get_level() const
{ return m_level; }
private: private:
/* /*
The interface of Sql_condition is mostly private, by design, The interface of Sql_condition is mostly private, by design,
...@@ -144,15 +265,26 @@ class Sql_condition : public Sql_alloc ...@@ -144,15 +265,26 @@ class Sql_condition : public Sql_alloc
/** /**
Set this condition area with a fixed message text. Set this condition area with a fixed message text.
@param thd the current thread. @param value - the error number and the sql state for this condition.
@param code the error number for this condition. @param level - the error level for this condition.
@param str the message text for this condition. @param msg - 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, void set(const Sql_state_errno *value,
Sql_condition::enum_warning_level level, Sql_condition::enum_warning_level level,
const char* msg); const char* msg)
{
DBUG_ASSERT(value->get_sql_errno() != 0);
DBUG_ASSERT(value->get_sqlstate() != NULL);
DBUG_ASSERT(msg != NULL);
set_condition_value(value);
set_builtin_message_text(msg);
m_level= level;
}
void set(const Sql_state_errno_level *cond, const char* msg)
{
set(cond, cond->get_level(), msg);
}
/** /**
Set the condition message test. Set the condition message test.
...@@ -161,15 +293,20 @@ class Sql_condition : public Sql_alloc ...@@ -161,15 +293,20 @@ class Sql_condition : public Sql_alloc
*/ */
void set_builtin_message_text(const char* str); void set_builtin_message_text(const char* str);
/** Set the SQLSTATE of this condition. */
void set_sqlstate(const char* sqlstate);
/** Set the CLASS_ORIGIN of this condition. */ /** Set the CLASS_ORIGIN of this condition. */
void set_class_origin(); void set_class_origin();
/** Set the SUBCLASS_ORIGIN of this condition. */ /** Set the SUBCLASS_ORIGIN of this condition. */
void set_subclass_origin(); void set_subclass_origin();
/**
Assign the condition items 'MYSQL_ERRNO', 'level' and 'MESSAGE_TEXT'
default values of a condition.
@param thd - current thread, to access to localized error messages
@param from - copy condition items from here (can be NULL)
*/
void assign_defaults(THD *thd, const Sql_state_errno *from);
/** /**
Clear this SQL condition. Clear this SQL condition.
*/ */
...@@ -209,18 +346,6 @@ class Sql_condition : public Sql_alloc ...@@ -209,18 +346,6 @@ class Sql_condition : public Sql_alloc
/** Message text, expressed in the character set implied by --language. */ /** Message text, expressed in the character set implied by --language. */
String m_message_text; String m_message_text;
/** MySQL extension, MYSQL_ERRNO condition item. */
uint m_sql_errno;
/**
SQL RETURNED_SQLSTATE condition item.
This member is always NUL terminated.
*/
char m_returned_sqlstate[SQLSTATE_LENGTH+1];
/** Severity (error, warning, note) of this condition. */
Sql_condition::enum_warning_level m_level;
/** Pointers for participating in the list of conditions. */ /** Pointers for participating in the list of conditions. */
Sql_condition *next_in_wi; Sql_condition *next_in_wi;
Sql_condition **prev_in_wi; Sql_condition **prev_in_wi;
...@@ -475,9 +600,7 @@ class Warning_info ...@@ -475,9 +600,7 @@ class Warning_info
@return a pointer to the added SQL-condition. @return a pointer to the added SQL-condition.
*/ */
Sql_condition *push_warning(THD *thd, Sql_condition *push_warning(THD *thd,
uint sql_errno, const Sql_state_errno_level *value,
const char* sqlstate,
Sql_condition::enum_warning_level level,
const char* msg); const char* msg);
/** /**
...@@ -634,7 +757,7 @@ class ErrConvDecimal : public ErrConv ...@@ -634,7 +757,7 @@ class ErrConvDecimal : public ErrConv
Can not be assigned twice per statement. Can not be assigned twice per statement.
*/ */
class Diagnostics_area class Diagnostics_area: public Sql_state_errno
{ {
private: private:
/** The type of the counted and doubly linked list of conditions. */ /** The type of the counted and doubly linked list of conditions. */
...@@ -722,10 +845,13 @@ class Diagnostics_area ...@@ -722,10 +845,13 @@ class Diagnostics_area
{ m_skip_flush= TRUE; } { m_skip_flush= TRUE; }
uint sql_errno() const uint sql_errno() const
{ DBUG_ASSERT(m_status == DA_ERROR); return m_sql_errno; } {
DBUG_ASSERT(m_status == DA_ERROR);
return Sql_state_errno::get_sql_errno();
}
const char* get_sqlstate() const const char* get_sqlstate() const
{ DBUG_ASSERT(m_status == DA_ERROR); return m_sqlstate; } { DBUG_ASSERT(m_status == DA_ERROR); return Sql_state::get_sqlstate(); }
ulonglong affected_rows() const ulonglong affected_rows() const
{ {
...@@ -844,9 +970,8 @@ class Diagnostics_area ...@@ -844,9 +970,8 @@ class Diagnostics_area
Sql_condition::enum_warning_level level, Sql_condition::enum_warning_level level,
const char* msg) const char* msg)
{ {
return get_warning_info()->push_warning(thd, Sql_state_errno_level tmp(sql_errno_arg, sqlstate, level);
sql_errno_arg, sqlstate, level, return get_warning_info()->push_warning(thd, &tmp, msg);
msg);
} }
void mark_sql_conditions_for_removal() void mark_sql_conditions_for_removal()
...@@ -887,14 +1012,6 @@ class Diagnostics_area ...@@ -887,14 +1012,6 @@ class Diagnostics_area
/** Message buffer. Can be used by OK or ERROR status. */ /** Message buffer. Can be used by OK or ERROR status. */
char m_message[MYSQL_ERRMSG_SIZE]; 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 The number of rows affected by the last statement. This is
semantically close to thd->m_row_count_func, but has a different semantically close to thd->m_row_count_func, but has a different
...@@ -964,43 +1081,4 @@ inline bool is_sqlstate_completion(const char *s) ...@@ -964,43 +1081,4 @@ inline bool is_sqlstate_completion(const char *s)
{ return s[0] == '0' && s[1] == '0'; } { 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 #endif // SQL_ERROR_H
...@@ -75,69 +75,6 @@ void Set_signal_information::clear() ...@@ -75,69 +75,6 @@ void Set_signal_information::clear()
memset(m_item, 0, sizeof(m_item)); memset(m_item, 0, sizeof(m_item));
} }
void
Sql_cmd_common_signal::assign_defaults(Sql_condition *cond,
bool set_level_code,
Sql_condition::enum_warning_level level,
int sqlcode)
{
if (set_level_code)
{
cond->m_level= level;
cond->m_sql_errno= sqlcode;
}
if (! cond->get_message_text())
cond->set_builtin_message_text(ER(sqlcode));
}
void Sql_cmd_common_signal::eval_defaults(THD *thd, Sql_condition *cond)
{
DBUG_ASSERT(cond);
const char* sqlstate;
bool set_defaults= (m_cond != 0);
if (set_defaults)
{
/*
SIGNAL is restricted in sql_yacc.yy to only signal SQLSTATE conditions.
*/
DBUG_ASSERT(m_cond->has_sql_state());
sqlstate= m_cond->sql_state;
cond->set_sqlstate(sqlstate);
}
else
sqlstate= cond->get_sqlstate();
DBUG_ASSERT(sqlstate);
/* SQLSTATE class "00": illegal, rejected in the parser. */
DBUG_ASSERT((sqlstate[0] != '0') || (sqlstate[1] != '0'));
if ((sqlstate[0] == '0') && (sqlstate[1] == '1'))
{
/* SQLSTATE class "01": warning. */
assign_defaults(cond, set_defaults,
Sql_condition::WARN_LEVEL_WARN,
m_cond && m_cond->mysqlerr ? m_cond->mysqlerr :
ER_SIGNAL_WARN);
}
else if ((sqlstate[0] == '0') && (sqlstate[1] == '2'))
{
/* SQLSTATE class "02": not found. */
assign_defaults(cond, set_defaults,
Sql_condition::WARN_LEVEL_ERROR,
m_cond && m_cond->mysqlerr ? m_cond->mysqlerr :
ER_SIGNAL_NOT_FOUND);
}
else
{
/* other SQLSTATE classes : error. */
assign_defaults(cond, set_defaults,
Sql_condition::WARN_LEVEL_ERROR,
m_cond && m_cond->mysqlerr ? m_cond->mysqlerr :
ER_SIGNAL_EXCEPTION);
}
}
static bool assign_fixed_string(MEM_ROOT *mem_root, static bool assign_fixed_string(MEM_ROOT *mem_root,
CHARSET_INFO *dst_cs, CHARSET_INFO *dst_cs,
...@@ -408,7 +345,7 @@ bool Sql_cmd_common_signal::raise_condition(THD *thd, Sql_condition *cond) ...@@ -408,7 +345,7 @@ bool Sql_cmd_common_signal::raise_condition(THD *thd, Sql_condition *cond)
DBUG_ASSERT(thd->lex->query_tables == NULL); DBUG_ASSERT(thd->lex->query_tables == NULL);
eval_defaults(thd, cond); cond->assign_defaults(thd, m_cond);
if (eval_signal_informations(thd, cond)) if (eval_signal_informations(thd, cond))
DBUG_RETURN(result); DBUG_RETURN(result);
...@@ -491,10 +428,7 @@ bool Sql_cmd_resignal::execute(THD *thd) ...@@ -491,10 +428,7 @@ bool Sql_cmd_resignal::execute(THD *thd)
} }
Sql_condition signaled_err(thd->mem_root); Sql_condition signaled_err(thd->mem_root);
signaled_err.set(signaled->sql_errno, signaled_err.set(signaled, signaled->message);
signaled->sql_state,
signaled->level,
signaled->message);
if (m_cond) if (m_cond)
{ {
......
...@@ -39,27 +39,6 @@ class Sql_cmd_common_signal : public Sql_cmd ...@@ -39,27 +39,6 @@ class Sql_cmd_common_signal : public Sql_cmd
virtual ~Sql_cmd_common_signal() virtual ~Sql_cmd_common_signal()
{} {}
/**
Assign the condition items 'MYSQL_ERRNO', 'level' and 'MESSAGE_TEXT'
default values of a condition.
@param cond the condition to update.
@param set_level_code true if 'level' and 'MYSQL_ERRNO' needs to be overwritten
@param level the level to assign
@param sqlcode the sql code to assign
*/
static void assign_defaults(Sql_condition *cond,
bool set_level_code,
Sql_condition::enum_warning_level level,
int sqlcode);
/**
Evaluate the condition items 'SQLSTATE', 'MYSQL_ERRNO', 'level' and 'MESSAGE_TEXT'
default values for this statement.
@param thd the current thread.
@param cond the condition to update.
*/
void eval_defaults(THD *thd, Sql_condition *cond);
/** /**
Evaluate each signal condition items for this statement. Evaluate each signal condition items for this statement.
@param thd the current thread. @param thd the current thread.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment