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