My Project
sql_error.h
00001 /* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
00002 
00003    This program is free software; you can redistribute it and/or modify
00004    it under the terms of the GNU General Public License as published by
00005    the Free Software Foundation; version 2 of the License.
00006 
00007    This program is distributed in the hope that it will be useful,
00008    but WITHOUT ANY WARRANTY; without even the implied warranty of
00009    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00010    GNU General Public License for more details.
00011 
00012    You should have received a copy of the GNU General Public License
00013    along with this program; if not, write to the Free Software
00014    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
00015 
00016 #ifndef SQL_ERROR_H
00017 #define SQL_ERROR_H
00018 
00019 #include "sql_list.h"
00020 #include "m_string.h" /* LEX_STRING */
00021 #include "sql_string.h"                        /* String */
00022 #include "sql_plist.h" /* I_P_List */
00023 #include "mysql_com.h" /* MYSQL_ERRMSG_SIZE */
00024 
00025 class THD;
00026 class my_decimal;
00027 
00029 
00035 class Sql_condition : public Sql_alloc
00036 {
00037 public:
00038   /*
00039     Enumeration value describing the severity of the error.
00040 
00041     Note that these enumeration values must correspond to the indices
00042     of the sql_print_message_handlers array.
00043   */
00044   enum enum_warning_level
00045   { WARN_LEVEL_NOTE, WARN_LEVEL_WARN, WARN_LEVEL_ERROR, WARN_LEVEL_END};
00046 
00051   const char* get_message_text() const;
00052 
00057   int get_message_octet_length() const;
00058 
00063   const char* get_sqlstate() const
00064   { return m_returned_sqlstate; }
00065 
00070   uint get_sql_errno() const
00071   { return m_sql_errno; }
00072 
00077   Sql_condition::enum_warning_level get_level() const
00078   { return m_level; }
00079 
00080 private:
00081   /*
00082     The interface of Sql_condition is mostly private, by design,
00083     so that only the following code:
00084     - various raise_error() or raise_warning() methods in class THD,
00085     - the implementation of SIGNAL / RESIGNAL / GET DIAGNOSTICS
00086     - catch / re-throw of SQL conditions in stored procedures (sp_rcontext)
00087     is allowed to create / modify a SQL condition.
00088     Enforcing this policy prevents confusion, since the only public
00089     interface available to the rest of the server implementation
00090     is the interface offered by the THD methods (THD::raise_error()),
00091     which should be used.
00092   */
00093   friend class THD;
00094   friend class Warning_info;
00095   friend class Sql_cmd_common_signal;
00096   friend class Sql_cmd_signal;
00097   friend class Sql_cmd_resignal;
00098   friend class sp_rcontext;
00099   friend class Condition_information_item;
00100 
00106   Sql_condition();
00107 
00113   void init(MEM_ROOT *mem_root);
00114 
00120   Sql_condition(MEM_ROOT *mem_root);
00121 
00123   ~Sql_condition()
00124   {}
00125 
00130   void copy_opt_attributes(const Sql_condition *cond);
00131 
00140   void set(uint sql_errno, const char* sqlstate,
00141            Sql_condition::enum_warning_level level,
00142            const char* msg);
00143 
00149   void set_builtin_message_text(const char* str);
00150 
00152   void set_sqlstate(const char* sqlstate);
00153 
00155   void set_class_origins();
00156 
00160   void clear();
00161 
00162 private:
00164   String m_class_origin;
00165 
00167   String m_subclass_origin;
00168 
00170   String m_constraint_catalog;
00171 
00173   String m_constraint_schema;
00174 
00176   String m_constraint_name;
00177 
00179   String m_catalog_name;
00180 
00182   String m_schema_name;
00183 
00185   String m_table_name;
00186 
00188   String m_column_name;
00189 
00191   String m_cursor_name;
00192 
00194   String m_message_text;
00195 
00197   uint m_sql_errno;
00198 
00203   char m_returned_sqlstate[SQLSTATE_LENGTH+1];
00204 
00206   Sql_condition::enum_warning_level m_level;
00207 
00209   Sql_condition *next_in_wi;
00210   Sql_condition **prev_in_wi;
00211 
00213   MEM_ROOT *m_mem_root;
00214 };
00215 
00217 
00221 class Warning_info
00222 {
00224   typedef I_P_List<Sql_condition,
00225                    I_P_List_adapter<Sql_condition,
00226                                     &Sql_condition::next_in_wi,
00227                                     &Sql_condition::prev_in_wi>,
00228                    I_P_List_counter,
00229                    I_P_List_fast_push_back<Sql_condition> >
00230           Sql_condition_list;
00231 
00233   MEM_ROOT           m_warn_root;
00234 
00236   Sql_condition_list   m_warn_list;
00237 
00239   uint               m_warn_count[(uint) Sql_condition::WARN_LEVEL_END];
00240 
00247   uint               m_current_statement_warn_count;
00248 
00249   /*
00250     Row counter, to print in errors and warnings. Not increased in
00251     create_sort_index(); may differ from examined_row_count.
00252   */
00253   ulong              m_current_row_for_warning;
00254 
00256   ulonglong          m_warn_id;
00257 
00272   const Sql_condition *m_error_condition;
00273 
00275   bool               m_allow_unlimited_warnings;
00276 
00278   bool m_read_only;
00279 
00281   Warning_info *m_next_in_da;
00282   Warning_info **m_prev_in_da;
00283 
00284   List<Sql_condition> m_marked_sql_conditions;
00285 
00286 public:
00287   Warning_info(ulonglong warn_id_arg, bool allow_unlimited_warnings);
00288   ~Warning_info();
00289 
00290 private:
00291   Warning_info(const Warning_info &rhs); /* Not implemented */
00292   Warning_info& operator=(const Warning_info &rhs); /* Not implemented */
00293 
00303   bool has_sql_condition(const char *message_str, ulong message_length) const;
00304 
00312   void clear(ulonglong new_id);
00313 
00326   void opt_clear(ulonglong query_id)
00327   {
00328     if (query_id != m_warn_id)
00329       clear(query_id);
00330   }
00331 
00341   void append_warning_info(THD *thd, const Warning_info *source);
00342 
00348   void reset_for_next_command()
00349   { m_current_statement_warn_count= 0; }
00350 
00355   void mark_sql_conditions_for_removal();
00356 
00361   void unmark_sql_conditions_from_removal()
00362   { m_marked_sql_conditions.empty(); }
00363 
00368   void remove_marked_sql_conditions();
00369 
00380   bool is_marked_for_removal(const Sql_condition *cond) const;
00381 
00386   void mark_condition_for_removal(Sql_condition *cond)
00387   { m_marked_sql_conditions.push_back(cond, &m_warn_root); }
00388 
00393   ulong warn_count() const
00394   {
00395     /*
00396       This may be higher than warn_list.elements() if we have
00397       had more warnings than thd->variables.max_error_count.
00398     */
00399     return (m_warn_count[(uint) Sql_condition::WARN_LEVEL_NOTE] +
00400             m_warn_count[(uint) Sql_condition::WARN_LEVEL_ERROR] +
00401             m_warn_count[(uint) Sql_condition::WARN_LEVEL_WARN]);
00402   }
00403 
00408   ulong error_count() const
00409   { return m_warn_count[(uint) Sql_condition::WARN_LEVEL_ERROR]; }
00410 
00414   uint cond_count() const
00415   {
00416     return m_warn_list.elements();
00417   }
00418 
00420   ulonglong id() const { return m_warn_id; }
00421 
00423   void id(ulonglong id) { m_warn_id= id; }
00424 
00426   bool is_empty() const { return m_warn_list.is_empty(); }
00427 
00429   void inc_current_row_for_warning() { m_current_row_for_warning++; }
00430 
00432   void reset_current_row_for_warning() { m_current_row_for_warning= 1; }
00433 
00435   ulong current_row_for_warning() const { return m_current_row_for_warning; }
00436 
00438   ulong current_statement_warn_count() const
00439   { return m_current_statement_warn_count; }
00440 
00442   void reserve_space(THD *thd, uint count);
00443 
00456   Sql_condition *push_warning(THD *thd,
00457                               uint sql_errno,
00458                               const char* sqlstate,
00459                               Sql_condition::enum_warning_level level,
00460                               const char* msg);
00461 
00471   Sql_condition *push_warning(THD *thd, const Sql_condition *sql_condition);
00472 
00484   void set_read_only(bool read_only)
00485   { m_read_only= read_only; }
00486 
00491   bool is_read_only() const
00492   { return m_read_only; }
00493 
00500   const Sql_condition *get_error_condition() const
00501   { return m_error_condition; }
00502 
00508   void set_error_condition(const Sql_condition *error_condition)
00509   { m_error_condition= error_condition; }
00510 
00517   void clear_error_condition()
00518   { m_error_condition= NULL; }
00519 
00520   // for:
00521   //   - m_next_in_da / m_prev_in_da
00522   //   - is_marked_for_removal()
00523   friend class Diagnostics_area;
00524 };
00525 
00526 uint err_conv(char *buff, size_t to_length, const char *from,
00527               size_t from_length, const CHARSET_INFO *from_cs);
00528 
00529 class ErrConvString
00530 {
00531   char err_buffer[MYSQL_ERRMSG_SIZE];
00532   size_t buf_length;
00533 public:
00534   ErrConvString(String *str)
00535   {
00536     buf_length= err_conv(err_buffer, sizeof(err_buffer), str->ptr(),
00537                          str->length(), str->charset());
00538   }
00539 
00540   ErrConvString(const char *str, const CHARSET_INFO* cs)
00541   {
00542     buf_length= err_conv(err_buffer, sizeof(err_buffer), str, strlen(str), cs);
00543   }
00544 
00545   ErrConvString(const char *str, uint length)
00546   {
00547     buf_length= err_conv(err_buffer, sizeof(err_buffer), str, length,
00548                          &my_charset_latin1);
00549   }
00550 
00551   ErrConvString(const char *str, uint length, const CHARSET_INFO* cs)
00552   {
00553     buf_length= err_conv(err_buffer, sizeof(err_buffer), str, length, cs);
00554   }
00555 
00556   ErrConvString(longlong nr)
00557   {
00558     buf_length= my_snprintf(err_buffer, sizeof(err_buffer), "%lld", nr);
00559   }
00560 
00561   ErrConvString(longlong nr, bool unsigned_flag)
00562   {
00563     buf_length= longlong10_to_str(nr, err_buffer, unsigned_flag ? 10 : -10) -
00564                 err_buffer;
00565   }
00566 
00567   ErrConvString(double nr);
00568   ErrConvString(const my_decimal *nr);
00569   ErrConvString(const struct st_mysql_time *ltime, uint dec);
00570  
00571   ~ErrConvString() { };
00572   char *ptr() { return err_buffer; }
00573   size_t length() const { return buf_length; }
00574 };
00575 
00577 
00584 class Diagnostics_area
00585 {
00586 private:
00588   typedef I_P_List<Warning_info,
00589                    I_P_List_adapter<Warning_info,
00590                                     &Warning_info::m_next_in_da,
00591                                     &Warning_info::m_prev_in_da>,
00592                    I_P_List_counter,
00593                    I_P_List_fast_push_back<Warning_info> >
00594           Warning_info_list;
00595 
00596 public:
00598   typedef Warning_info::Sql_condition_list::Const_Iterator
00599     Sql_condition_iterator;
00600 
00601   enum enum_diagnostics_status
00602   {
00604     DA_EMPTY= 0,
00606     DA_OK,
00608     DA_EOF,
00610     DA_ERROR,
00612     DA_DISABLED
00613   };
00614 
00615   void set_overwrite_status(bool can_overwrite_status)
00616   { m_can_overwrite_status= can_overwrite_status; }
00617 
00618   bool is_sent() const { return m_is_sent; }
00619 
00620   void set_is_sent(bool is_sent) { m_is_sent= is_sent; }
00621 
00622   void set_ok_status(ulonglong affected_rows,
00623                      ulonglong last_insert_id,
00624                      const char *message);
00625 
00626   void set_eof_status(THD *thd);
00627 
00628   void set_error_status(uint sql_errno);
00629 
00630   void set_error_status(uint sql_errno,
00631                         const char *message,
00632                         const char *sqlstate,
00633                         const Sql_condition *error_condition);
00634 
00635   void disable_status();
00636 
00637   void reset_diagnostics_area();
00638 
00639   bool is_set() const { return m_status != DA_EMPTY; }
00640 
00641   bool is_error() const { return m_status == DA_ERROR; }
00642 
00643   bool is_eof() const { return m_status == DA_EOF; }
00644 
00645   bool is_ok() const { return m_status == DA_OK; }
00646 
00647   bool is_disabled() const { return m_status == DA_DISABLED; }
00648 
00649   enum_diagnostics_status status() const { return m_status; }
00650 
00651   const char *message() const
00652   { DBUG_ASSERT(m_status == DA_ERROR || m_status == DA_OK); return m_message; }
00653 
00654   uint sql_errno() const
00655   { DBUG_ASSERT(m_status == DA_ERROR); return m_sql_errno; }
00656 
00657   const char* get_sqlstate() const
00658   { DBUG_ASSERT(m_status == DA_ERROR); return m_sqlstate; }
00659 
00660   ulonglong affected_rows() const
00661   { DBUG_ASSERT(m_status == DA_OK); return m_affected_rows; }
00662 
00663   ulonglong last_insert_id() const
00664   { DBUG_ASSERT(m_status == DA_OK); return m_last_insert_id; }
00665 
00666   uint statement_warn_count() const
00667   {
00668     DBUG_ASSERT(m_status == DA_OK || m_status == DA_EOF);
00669     return m_statement_warn_count;
00670   }
00671 
00672   Diagnostics_area();
00673   Diagnostics_area(ulonglong warning_info_id, bool allow_unlimited_warnings);
00674 
00675   void push_warning_info(Warning_info *wi)
00676   { m_wi_stack.push_front(wi); }
00677 
00678   void pop_warning_info()
00679   {
00680     DBUG_ASSERT(m_wi_stack.elements() > 0);
00681     m_wi_stack.remove(m_wi_stack.front());
00682   }
00683 
00684   void set_warning_info_id(ulonglong id)
00685   { get_warning_info()->id(id); }
00686 
00687   ulonglong warning_info_id() const
00688   { return get_warning_info()->id(); }
00689 
00700   bool warning_info_changed(const Warning_info *wi) const
00701   { return get_warning_info()->id() != wi->id(); }
00702 
00703   bool is_warning_info_empty() const
00704   { return get_warning_info()->is_empty(); }
00705 
00706   ulong current_statement_warn_count() const
00707   { return get_warning_info()->current_statement_warn_count(); }
00708 
00709   bool has_sql_condition(const char *message_str, ulong message_length) const
00710   { return get_warning_info()->has_sql_condition(message_str, message_length); }
00711 
00712   void reset_for_next_command()
00713   { get_warning_info()->reset_for_next_command(); }
00714 
00715   void clear_warning_info(ulonglong id)
00716   { get_warning_info()->clear(id); }
00717 
00718   void opt_clear_warning_info(ulonglong query_id)
00719   { get_warning_info()->opt_clear(query_id); }
00720 
00721   ulong current_row_for_warning() const
00722   { return get_warning_info()->current_row_for_warning(); }
00723 
00724   void inc_current_row_for_warning()
00725   { get_warning_info()->inc_current_row_for_warning(); }
00726 
00727   void reset_current_row_for_warning()
00728   { get_warning_info()->reset_current_row_for_warning(); }
00729 
00730   bool is_warning_info_read_only() const
00731   { return get_warning_info()->is_read_only(); }
00732 
00733   void set_warning_info_read_only(bool read_only)
00734   { get_warning_info()->set_read_only(read_only); }
00735 
00736   ulong error_count() const
00737   { return get_warning_info()->error_count(); }
00738 
00739   ulong warn_count() const
00740   { return get_warning_info()->warn_count(); }
00741 
00742   uint cond_count() const
00743   { return get_warning_info()->cond_count(); }
00744 
00745   Sql_condition_iterator sql_conditions() const
00746   { return get_warning_info()->m_warn_list; }
00747 
00748   void reserve_space(THD *thd, uint count)
00749   { get_warning_info()->reserve_space(thd, count); }
00750 
00751   Sql_condition *push_warning(THD *thd, const Sql_condition *sql_condition)
00752   { return get_warning_info()->push_warning(thd, sql_condition); }
00753 
00754   Sql_condition *push_warning(THD *thd,
00755                               uint sql_errno,
00756                               const char* sqlstate,
00757                               Sql_condition::enum_warning_level level,
00758                               const char* msg)
00759   {
00760     return get_warning_info()->push_warning(thd,
00761                                             sql_errno, sqlstate, level, msg);
00762   }
00763 
00764   void mark_sql_conditions_for_removal()
00765   { get_warning_info()->mark_sql_conditions_for_removal(); }
00766 
00767   void unmark_sql_conditions_from_removal()
00768   { get_warning_info()->unmark_sql_conditions_from_removal(); }
00769 
00770   void remove_marked_sql_conditions()
00771   { get_warning_info()->remove_marked_sql_conditions(); }
00772 
00773   const Sql_condition *get_error_condition() const
00774   { return get_warning_info()->get_error_condition(); }
00775 
00776   void copy_sql_conditions_to_wi(THD *thd, Warning_info *dst_wi) const
00777   { dst_wi->append_warning_info(thd, get_warning_info()); }
00778 
00779   void copy_sql_conditions_from_wi(THD *thd, const Warning_info *src_wi)
00780   { get_warning_info()->append_warning_info(thd, src_wi); }
00781 
00782   void copy_non_errors_from_wi(THD *thd, const Warning_info *src_wi);
00783 
00784 private:
00785   Warning_info *get_warning_info() { return m_wi_stack.front(); }
00786 
00787   const Warning_info *get_warning_info() const { return m_wi_stack.front(); }
00788 
00789 private:
00791   bool m_is_sent;
00792 
00794   bool m_can_overwrite_status;
00795 
00797   char m_message[MYSQL_ERRMSG_SIZE];
00798 
00803   uint m_sql_errno;
00804 
00805   char m_sqlstate[SQLSTATE_LENGTH+1];
00806 
00818   ulonglong    m_affected_rows;
00819 
00825   ulonglong   m_last_insert_id;
00826 
00833   uint       m_statement_warn_count;
00834 
00835   enum_diagnostics_status m_status;
00836 
00837   Warning_info m_main_wi;
00838 
00839   Warning_info_list m_wi_stack;
00840 };
00841 
00843 
00844 
00845 void push_warning(THD *thd, Sql_condition::enum_warning_level level,
00846                   uint code, const char *msg);
00847 
00848 void push_warning_printf(THD *thd, Sql_condition::enum_warning_level level,
00849                          uint code, const char *format, ...);
00850 
00851 bool mysqld_show_warnings(THD *thd, ulong levels_to_show);
00852 
00853 uint32 convert_error_message(char *to, uint32 to_length,
00854                              const CHARSET_INFO *to_cs,
00855                              const char *from, uint32 from_length,
00856                              const CHARSET_INFO *from_cs, uint *errors);
00857 
00858 extern const LEX_STRING warning_level_names[];
00859 
00860 bool is_sqlstate_valid(const LEX_STRING *sqlstate);
00861 
00862 
00872 inline bool is_sqlstate_completion(const char *s)
00873 { return s[0] == '0' && s[1] == '0'; }
00874 
00875 
00885 inline bool is_sqlstate_warning(const char *s)
00886 { return s[0] == '0' && s[1] == '1'; }
00887 
00888 
00898 inline bool is_sqlstate_not_found(const char *s)
00899 { return s[0] == '0' && s[1] == '2'; }
00900 
00901 
00911 inline bool is_sqlstate_exception(const char *s)
00912 { return s[0] != '0' || s[1] > '2'; }
00913 
00914 
00915 #endif // SQL_ERROR_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines