My Project
|
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