1 /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. 2 3 This program is free software; you can redistribute it and/or modify 4 it under the terms of the GNU General Public License as published by 5 the Free Software Foundation; version 2 of the License. 6 7 This program is distributed in the hope that it will be useful, 8 but WITHOUT ANY WARRANTY; without even the implied warranty of 9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 GNU General Public License for more details. 11 12 You should have received a copy of the GNU General Public License 13 along with this program; if not, write to the Free Software 14 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ 15 16 #ifndef SQL_ERROR_H 17 #define SQL_ERROR_H 18 19 #include "sql_list.h" /* Sql_alloc, MEM_ROOT */ 20 #include "m_string.h" /* LEX_STRING */ 21 #include "sql_string.h" /* String */ 22 #include "mysql_com.h" /* MYSQL_ERRMSG_SIZE */ 23 24 class THD; 25 26 /** 27 Stores status of the currently executed statement. 28 Cleared at the beginning of the statement, and then 29 can hold either OK, ERROR, or EOF status. 30 Can not be assigned twice per statement. 31 */ 32 33 class Diagnostics_area 34 { 35 public: 36 enum enum_diagnostics_status 37 { 38 /** The area is cleared at start of a statement. */ 39 DA_EMPTY= 0, 40 /** Set whenever one calls my_ok(). */ 41 DA_OK, 42 /** Set whenever one calls my_eof(). */ 43 DA_EOF, 44 /** Set whenever one calls my_error() or my_message(). */ 45 DA_ERROR, 46 /** Set in case of a custom response, such as one from COM_STMT_PREPARE. */ 47 DA_DISABLED 48 }; 49 /** True if status information is sent to the client. */ 50 bool is_sent; 51 /** Set to make set_error_status after set_{ok,eof}_status possible. */ 52 bool can_overwrite_status; 53 54 void set_ok_status(THD *thd, ulonglong affected_rows_arg, 55 ulonglong last_insert_id_arg, 56 const char *message); 57 void set_eof_status(THD *thd); 58 void set_error_status(THD *thd, uint sql_errno_arg, const char *message_arg, 59 const char *sqlstate); 60 61 void disable_status(); 62 63 void reset_diagnostics_area(); 64 is_set()65 bool is_set() const { return m_status != DA_EMPTY; } is_error()66 bool is_error() const { return m_status == DA_ERROR; } is_eof()67 bool is_eof() const { return m_status == DA_EOF; } is_ok()68 bool is_ok() const { return m_status == DA_OK; } is_disabled()69 bool is_disabled() const { return m_status == DA_DISABLED; } status()70 enum_diagnostics_status status() const { return m_status; } 71 message()72 const char *message() const 73 { DBUG_ASSERT(m_status == DA_ERROR || m_status == DA_OK); return m_message; } 74 sql_errno()75 uint sql_errno() const 76 { DBUG_ASSERT(m_status == DA_ERROR); return m_sql_errno; } 77 get_sqlstate()78 const char* get_sqlstate() const 79 { DBUG_ASSERT(m_status == DA_ERROR); return m_sqlstate; } 80 affected_rows()81 ulonglong affected_rows() const 82 { DBUG_ASSERT(m_status == DA_OK); return m_affected_rows; } 83 last_insert_id()84 ulonglong last_insert_id() const 85 { DBUG_ASSERT(m_status == DA_OK); return m_last_insert_id; } 86 statement_warn_count()87 uint statement_warn_count() const 88 { 89 DBUG_ASSERT(m_status == DA_OK || m_status == DA_EOF); 90 return m_statement_warn_count; 91 } 92 Diagnostics_area()93 Diagnostics_area() { reset_diagnostics_area(); } 94 95 private: 96 /** Message buffer. Can be used by OK or ERROR status. */ 97 char m_message[MYSQL_ERRMSG_SIZE]; 98 /** 99 SQL error number. One of ER_ codes from share/errmsg.txt. 100 Set by set_error_status. 101 */ 102 uint m_sql_errno; 103 104 char m_sqlstate[SQLSTATE_LENGTH+1]; 105 106 /** 107 The number of rows affected by the last statement. This is 108 semantically close to thd->row_count_func, but has a different 109 life cycle. thd->row_count_func stores the value returned by 110 function ROW_COUNT() and is cleared only by statements that 111 update its value, such as INSERT, UPDATE, DELETE and few others. 112 This member is cleared at the beginning of the next statement. 113 114 We could possibly merge the two, but life cycle of thd->row_count_func 115 can not be changed. 116 */ 117 ulonglong m_affected_rows; 118 /** 119 Similarly to the previous member, this is a replacement of 120 thd->first_successful_insert_id_in_prev_stmt, which is used 121 to implement LAST_INSERT_ID(). 122 */ 123 ulonglong m_last_insert_id; 124 /** 125 Number of warnings of this last statement. May differ from 126 the number of warnings returned by SHOW WARNINGS e.g. in case 127 the statement doesn't clear the warnings, and doesn't generate 128 them. 129 */ 130 uint m_statement_warn_count; 131 enum_diagnostics_status m_status; 132 }; 133 134 /////////////////////////////////////////////////////////////////////////// 135 136 /** 137 Representation of a SQL condition. 138 A SQL condition can be a completion condition (note, warning), 139 or an exception condition (error, not found). 140 @note This class is named MYSQL_ERROR instead of SQL_condition for 141 historical reasons, to facilitate merging code with previous releases. 142 */ 143 class MYSQL_ERROR : public Sql_alloc 144 { 145 public: 146 /* 147 Enumeration value describing the severity of the error. 148 149 Note that these enumeration values must correspond to the indices 150 of the sql_print_message_handlers array. 151 */ 152 enum enum_warning_level 153 { WARN_LEVEL_NOTE, WARN_LEVEL_WARN, WARN_LEVEL_ERROR, WARN_LEVEL_END}; 154 /** 155 Get the MESSAGE_TEXT of this condition. 156 @return the message text. 157 */ 158 const char* get_message_text() const; 159 160 /** 161 Get the MESSAGE_OCTET_LENGTH of this condition. 162 @return the length in bytes of the message text. 163 */ 164 int get_message_octet_length() const; 165 166 /** 167 Get the SQLSTATE of this condition. 168 @return the sql state. 169 */ get_sqlstate()170 const char* get_sqlstate() const 171 { return m_returned_sqlstate; } 172 173 /** 174 Get the SQL_ERRNO of this condition. 175 @return the sql error number condition item. 176 */ get_sql_errno()177 uint get_sql_errno() const 178 { return m_sql_errno; } 179 180 /** 181 Get the error level of this condition. 182 @return the error level condition item. 183 */ get_level()184 MYSQL_ERROR::enum_warning_level get_level() const 185 { return m_level; } 186 187 private: 188 /* 189 The interface of MYSQL_ERROR is mostly private, by design, 190 so that only the following code: 191 - various raise_error() or raise_warning() methods in class THD, 192 - the implementation of SIGNAL / RESIGNAL 193 - catch / re-throw of SQL conditions in stored procedures (sp_rcontext) 194 is allowed to create / modify a SQL condition. 195 Enforcing this policy prevents confusion, since the only public 196 interface available to the rest of the server implementation 197 is the interface offered by the THD methods (THD::raise_error()), 198 which should be used. 199 */ 200 friend class THD; 201 friend class Warning_info; 202 friend class Signal_common; 203 friend class Signal_statement; 204 friend class Resignal_statement; 205 friend class sp_rcontext; 206 207 /** 208 Default constructor. 209 This constructor is usefull when allocating arrays. 210 Note that the init() method should be called to complete the MYSQL_ERROR. 211 */ 212 MYSQL_ERROR(); 213 214 /** 215 Complete the MYSQL_ERROR initialisation. 216 @param mem_root The memory root to use for the condition items 217 of this condition 218 */ 219 void init(MEM_ROOT *mem_root); 220 221 /** 222 Constructor. 223 @param mem_root The memory root to use for the condition items 224 of this condition 225 */ 226 MYSQL_ERROR(MEM_ROOT *mem_root); 227 228 /** Destructor. */ ~MYSQL_ERROR()229 ~MYSQL_ERROR() 230 {} 231 232 /** 233 Copy optional condition items attributes. 234 @param cond the condition to copy. 235 */ 236 void copy_opt_attributes(const MYSQL_ERROR *cond); 237 238 /** 239 Set this condition area with a fixed message text. 240 @param thd the current thread. 241 @param code the error number for this condition. 242 @param str the message text for this condition. 243 @param level the error level for this condition. 244 @param MyFlags additional flags. 245 */ 246 void set(uint sql_errno, const char* sqlstate, 247 MYSQL_ERROR::enum_warning_level level, 248 const char* msg); 249 250 /** 251 Set the condition message test. 252 @param str Message text, expressed in the character set derived from 253 the server --language option 254 */ 255 void set_builtin_message_text(const char* str); 256 257 /** Set the SQLSTATE of this condition. */ 258 void set_sqlstate(const char* sqlstate); 259 260 /** 261 Clear this SQL condition. 262 */ 263 void clear(); 264 265 private: 266 /** SQL CLASS_ORIGIN condition item. */ 267 String m_class_origin; 268 269 /** SQL SUBCLASS_ORIGIN condition item. */ 270 String m_subclass_origin; 271 272 /** SQL CONSTRAINT_CATALOG condition item. */ 273 String m_constraint_catalog; 274 275 /** SQL CONSTRAINT_SCHEMA condition item. */ 276 String m_constraint_schema; 277 278 /** SQL CONSTRAINT_NAME condition item. */ 279 String m_constraint_name; 280 281 /** SQL CATALOG_NAME condition item. */ 282 String m_catalog_name; 283 284 /** SQL SCHEMA_NAME condition item. */ 285 String m_schema_name; 286 287 /** SQL TABLE_NAME condition item. */ 288 String m_table_name; 289 290 /** SQL COLUMN_NAME condition item. */ 291 String m_column_name; 292 293 /** SQL CURSOR_NAME condition item. */ 294 String m_cursor_name; 295 296 /** Message text, expressed in the character set implied by --language. */ 297 String m_message_text; 298 299 /** MySQL extension, MYSQL_ERRNO condition item. */ 300 uint m_sql_errno; 301 302 /** 303 SQL RETURNED_SQLSTATE condition item. 304 This member is always NUL terminated. 305 */ 306 char m_returned_sqlstate[SQLSTATE_LENGTH+1]; 307 308 /** Severity (error, warning, note) of this condition. */ 309 MYSQL_ERROR::enum_warning_level m_level; 310 311 /** Memory root to use to hold condition item values. */ 312 MEM_ROOT *m_mem_root; 313 }; 314 315 /////////////////////////////////////////////////////////////////////////// 316 317 /** 318 Information about warnings of the current connection. 319 */ 320 321 class Warning_info 322 { 323 /** A memory root to allocate warnings and errors */ 324 MEM_ROOT m_warn_root; 325 326 /** List of warnings of all severities (levels). */ 327 List <MYSQL_ERROR> m_warn_list; 328 329 /** A break down of the number of warnings per severity (level). */ 330 uint m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END]; 331 332 /** 333 The number of warnings of the current statement. Warning_info 334 life cycle differs from statement life cycle -- it may span 335 multiple statements. In that case we get 336 m_statement_warn_count 0, whereas m_warn_list is not empty. 337 */ 338 uint m_statement_warn_count; 339 340 /* 341 Row counter, to print in errors and warnings. Not increased in 342 create_sort_index(); may differ from examined_row_count. 343 */ 344 ulong m_current_row_for_warning; 345 346 /** Used to optionally clear warnings only once per statement. */ 347 ulonglong m_warn_id; 348 349 /** Indicates if push_warning() allows unlimited number of warnings. */ 350 bool m_allow_unlimited_warnings; 351 352 private: 353 Warning_info(const Warning_info &rhs); /* Not implemented */ 354 Warning_info& operator=(const Warning_info &rhs); /* Not implemented */ 355 public: 356 357 Warning_info(ulonglong warn_id_arg, bool allow_unlimited_warnings); 358 ~Warning_info(); 359 360 /** 361 Reset the warning information. Clear all warnings, 362 the number of warnings, reset current row counter 363 to point to the first row. 364 */ 365 void clear_warning_info(ulonglong warn_id_arg); 366 /** 367 Only clear warning info if haven't yet done that already 368 for the current query. Allows to be issued at any time 369 during the query, without risk of clearing some warnings 370 that have been generated by the current statement. 371 372 @todo: This is a sign of sloppy coding. Instead we need to 373 designate one place in a statement life cycle where we call 374 clear_warning_info(). 375 */ opt_clear_warning_info(ulonglong query_id)376 void opt_clear_warning_info(ulonglong query_id) 377 { 378 if (query_id != m_warn_id) 379 clear_warning_info(query_id); 380 } 381 append_warning_info(THD * thd,Warning_info * source)382 void append_warning_info(THD *thd, Warning_info *source) 383 { 384 append_warnings(thd, & source->warn_list()); 385 } 386 387 /** 388 Concatenate the list of warnings. 389 It's considered tolerable to lose a warning. 390 */ append_warnings(THD * thd,List<MYSQL_ERROR> * src)391 void append_warnings(THD *thd, List<MYSQL_ERROR> *src) 392 { 393 MYSQL_ERROR *err; 394 List_iterator_fast<MYSQL_ERROR> it(*src); 395 /* 396 Don't use ::push_warning() to avoid invocation of condition 397 handlers or escalation of warnings to errors. 398 */ 399 while ((err= it++)) 400 Warning_info::push_warning(thd, err); 401 } 402 403 /** 404 Conditional merge of related warning information areas. 405 */ 406 void merge_with_routine_info(THD *thd, Warning_info *source); 407 408 /** 409 Reset between two COM_ commands. Warnings are preserved 410 between commands, but statement_warn_count indicates 411 the number of warnings of this particular statement only. 412 */ reset_for_next_command()413 void reset_for_next_command() { m_statement_warn_count= 0; } 414 415 /** 416 Used for @@warning_count system variable, which prints 417 the number of rows returned by SHOW WARNINGS. 418 */ warn_count()419 ulong warn_count() const 420 { 421 /* 422 This may be higher than warn_list.elements if we have 423 had more warnings than thd->variables.max_error_count. 424 */ 425 return (m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_NOTE] + 426 m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_ERROR] + 427 m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_WARN]); 428 } 429 430 /** 431 This is for iteration purposes. We return a non-constant reference 432 since List doesn't have constant iterators. 433 */ warn_list()434 List<MYSQL_ERROR> &warn_list() { return m_warn_list; } 435 436 /** 437 The number of errors, or number of rows returned by SHOW ERRORS, 438 also the value of session variable @@error_count. 439 */ error_count()440 ulong error_count() const 441 { 442 return m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_ERROR]; 443 } 444 445 /** Id of the warning information area. */ warn_id()446 ulonglong warn_id() const { return m_warn_id; } 447 448 /** Do we have any errors and warnings that we can *show*? */ is_empty()449 bool is_empty() const { return m_warn_list.elements == 0; } 450 451 /** Increment the current row counter to point at the next row. */ inc_current_row_for_warning()452 void inc_current_row_for_warning() { m_current_row_for_warning++; } 453 /** Reset the current row counter. Start counting from the first row. */ reset_current_row_for_warning()454 void reset_current_row_for_warning() { m_current_row_for_warning= 1; } 455 /** Return the current counter value. */ current_row_for_warning()456 ulong current_row_for_warning() const { return m_current_row_for_warning; } 457 statement_warn_count()458 ulong statement_warn_count() const { return m_statement_warn_count; } 459 460 /** Add a new condition to the current list. */ 461 MYSQL_ERROR *push_warning(THD *thd, 462 uint sql_errno, const char* sqlstate, 463 MYSQL_ERROR::enum_warning_level level, 464 const char* msg); 465 466 /** Add a new condition to the current list. */ 467 MYSQL_ERROR *push_warning(THD *thd, const MYSQL_ERROR *sql_condition); 468 469 /** 470 Set the read only status for this statement area. 471 This is a privileged operation, reserved for the implementation of 472 diagnostics related statements, to enforce that the statement area is 473 left untouched during execution. 474 The diagnostics statements are: 475 - SHOW WARNINGS 476 - SHOW ERRORS 477 - GET DIAGNOSTICS 478 @param read_only the read only property to set 479 */ set_read_only(bool read_only)480 void set_read_only(bool read_only) 481 { m_read_only= read_only; } 482 483 /** 484 Read only status. 485 @return the read only property 486 */ is_read_only()487 bool is_read_only() const 488 { return m_read_only; } 489 490 private: 491 /** Read only status. */ 492 bool m_read_only; 493 494 friend class Resignal_statement; 495 }; 496 497 extern char *err_conv(char *buff, uint to_length, const char *from, 498 uint from_length, CHARSET_INFO *from_cs); 499 500 class ErrConvString 501 { 502 char err_buffer[MYSQL_ERRMSG_SIZE]; 503 public: 504 ErrConvString(String * str)505 ErrConvString(String *str) 506 { 507 (void) err_conv(err_buffer, sizeof(err_buffer), str->ptr(), 508 str->length(), str->charset()); 509 } 510 ErrConvString(const char * str,CHARSET_INFO * cs)511 ErrConvString(const char *str, CHARSET_INFO* cs) 512 { 513 (void) err_conv(err_buffer, sizeof(err_buffer), 514 str, strlen(str), cs); 515 } 516 ErrConvString(const char * str,uint length,CHARSET_INFO * cs)517 ErrConvString(const char *str, uint length, CHARSET_INFO* cs) 518 { 519 (void) err_conv(err_buffer, sizeof(err_buffer), 520 str, length, cs); 521 } 522 ~ErrConvString()523 ~ErrConvString() { }; ptr()524 char *ptr() { return err_buffer; } 525 }; 526 527 528 void push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level, 529 uint code, const char *msg); 530 void push_warning_printf(THD *thd, MYSQL_ERROR::enum_warning_level level, 531 uint code, const char *format, ...); 532 bool mysqld_show_warnings(THD *thd, ulong levels_to_show); 533 uint32 convert_error_message(char *to, uint32 to_length, CHARSET_INFO *to_cs, 534 const char *from, uint32 from_length, 535 CHARSET_INFO *from_cs, uint *errors); 536 537 extern const LEX_STRING warning_level_names[]; 538 539 #endif // SQL_ERROR_H 540