1 /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
2    Copyright (c) 2017, MariaDB Corporation.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; version 2 of the License.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 
13    You should have received a copy of the GNU General Public License
14    along with this program; if not, write to the Free Software
15    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335  USA */
16 
17 #ifndef SQL_ERROR_H
18 #define SQL_ERROR_H
19 
20 #include "sql_list.h" 	/* Sql_alloc, MEM_ROOT, list */
21 #include "sql_type_int.h" // Longlong_hybrid
22 #include "sql_string.h"                        /* String */
23 #include "sql_plist.h" /* I_P_List */
24 #include "mysql_com.h" /* MYSQL_ERRMSG_SIZE */
25 #include "my_time.h"   /* MYSQL_TIME */
26 #include "decimal.h"
27 
28 class THD;
29 class my_decimal;
30 class sp_condition_value;
31 
32 ///////////////////////////////////////////////////////////////////////////
33 
34 class Sql_state
35 {
36 protected:
37   /**
38     This member is always NUL terminated.
39   */
40   char m_sqlstate[SQLSTATE_LENGTH + 1];
41 public:
Sql_state()42   Sql_state()
43   {
44     memset(m_sqlstate, 0, sizeof(m_sqlstate));
45   }
46 
Sql_state(const char * sqlstate)47   Sql_state(const char *sqlstate)
48   {
49     set_sqlstate(sqlstate);
50   }
51 
get_sqlstate()52   const char* get_sqlstate() const
53   { return m_sqlstate; }
54 
set_sqlstate(const Sql_state * other)55   void set_sqlstate(const Sql_state *other)
56   {
57     *this= *other;
58   }
set_sqlstate(const char * sqlstate)59   void set_sqlstate(const char *sqlstate)
60   {
61     memcpy(m_sqlstate, sqlstate, SQLSTATE_LENGTH);
62     m_sqlstate[SQLSTATE_LENGTH]= '\0';
63   }
eq(const Sql_state * other)64   bool eq(const Sql_state *other) const
65   {
66     return strcmp(m_sqlstate, other->m_sqlstate) == 0;
67   }
68 
has_sql_state()69   bool has_sql_state() const { return m_sqlstate[0] != '\0'; }
70 
71   /**
72     Checks if this SQL state defines a WARNING condition.
73     Note: m_sqlstate must contain a valid SQL-state.
74 
75     @retval true if this SQL state defines a WARNING condition.
76     @retval false otherwise.
77   */
is_warning()78   inline bool is_warning() const
79   { return m_sqlstate[0] == '0' && m_sqlstate[1] == '1'; }
80 
81 
82   /**
83     Checks if this SQL state defines a NOT FOUND condition.
84     Note: m_sqlstate must contain a valid SQL-state.
85 
86     @retval true if this SQL state defines a NOT FOUND condition.
87     @retval false otherwise.
88   */
is_not_found()89   inline bool is_not_found() const
90   { return m_sqlstate[0] == '0' && m_sqlstate[1] == '2'; }
91 
92 
93   /**
94     Checks if this SQL state defines an EXCEPTION condition.
95     Note: m_sqlstate must contain a valid SQL-state.
96 
97     @retval true if this SQL state defines an EXCEPTION condition.
98     @retval false otherwise.
99   */
is_exception()100   inline bool is_exception() const
101   { return m_sqlstate[0] != '0' || m_sqlstate[1] > '2'; }
102 
103 };
104 
105 
106 class Sql_state_errno: public Sql_state
107 {
108 protected:
109   /**
110     MySQL extension, MYSQL_ERRNO condition item.
111     SQL error number. One of ER_ codes from share/errmsg.txt.
112     Set by set_error_status.
113   */
114   uint m_sql_errno;
115 
116 public:
Sql_state_errno()117   Sql_state_errno()
118    :m_sql_errno(0)
119   { }
Sql_state_errno(uint sql_errno)120   Sql_state_errno(uint sql_errno)
121    :m_sql_errno(sql_errno)
122   { }
Sql_state_errno(uint sql_errno,const char * sql_state)123   Sql_state_errno(uint sql_errno, const char *sql_state)
124    :Sql_state(sql_state),
125     m_sql_errno(sql_errno)
126   { }
127   /**
128     Get the SQL_ERRNO of this condition.
129     @return the sql error number condition item.
130   */
get_sql_errno()131   uint get_sql_errno() const
132   { return m_sql_errno; }
133 
set(uint sql_errno,const char * sqlstate)134   void set(uint sql_errno, const char *sqlstate)
135   {
136     m_sql_errno= sql_errno;
137     set_sqlstate(sqlstate);
138   }
clear()139   void clear()
140   {
141     m_sql_errno= 0;
142   }
143 };
144 
145 
146 class Sql_state_errno_level: public Sql_state_errno
147 {
148 public:
149   /*
150     Enumeration value describing the severity of the error.
151 
152     Note that these enumeration values must correspond to the indices
153     of the sql_print_message_handlers array.
154   */
155   enum enum_warning_level
156   { WARN_LEVEL_NOTE, WARN_LEVEL_WARN, WARN_LEVEL_ERROR, WARN_LEVEL_END};
157 
158 protected:
159   /** Severity (error, warning, note) of this condition. */
160   enum_warning_level m_level;
161 
162   void assign_defaults(const Sql_state_errno *value);
163 
164 public:
165   /**
166     Get the error level of this condition.
167     @return the error level condition item.
168   */
get_level()169   enum_warning_level get_level() const
170   { return m_level; }
171 
Sql_state_errno_level()172    Sql_state_errno_level()
173     :m_level(WARN_LEVEL_ERROR)
174   { }
175 
Sql_state_errno_level(uint sqlerrno,const char * sqlstate,enum_warning_level level)176   Sql_state_errno_level(uint sqlerrno, const char* sqlstate,
177                          enum_warning_level level)
178    :Sql_state_errno(sqlerrno, sqlstate),
179     m_level(level)
180   { }
Sql_state_errno_level(const Sql_state_errno & state_errno,enum_warning_level level)181   Sql_state_errno_level(const Sql_state_errno &state_errno,
182                          enum_warning_level level)
183    :Sql_state_errno(state_errno),
184     m_level(level)
185   { }
clear()186   void clear()
187   {
188     m_level= WARN_LEVEL_ERROR;
189     Sql_state_errno::clear();
190   }
191 };
192 
193 
194 /*
195   class Sql_user_condition_identity.
196   Instances of this class uniquely idetify user defined conditions (EXCEPTION).
197 
198     SET sql_mode=ORACLE;
199     CREATE PROCEDURE p1
200     AS
201       a EXCEPTION;
202     BEGIN
203       RAISE a;
204     EXCEPTION
205       WHEN a THEN NULL;
206     END;
207 
208   Currently a user defined condition is identified by a pointer to
209   its parse time sp_condition_value instance. This can change when
210   we add packages. See MDEV-10591.
211 */
212 class Sql_user_condition_identity
213 {
214 protected:
215   const sp_condition_value *m_user_condition_value;
216 public:
Sql_user_condition_identity()217   Sql_user_condition_identity()
218    :m_user_condition_value(NULL)
219   { }
Sql_user_condition_identity(const sp_condition_value * value)220   Sql_user_condition_identity(const sp_condition_value *value)
221    :m_user_condition_value(value)
222   { }
get_user_condition_value()223   const sp_condition_value *get_user_condition_value() const
224   { return m_user_condition_value; }
225 
set(const Sql_user_condition_identity & identity)226   void set(const Sql_user_condition_identity &identity)
227   {
228     *this= identity;
229   }
clear()230   void clear()
231   {
232     m_user_condition_value= NULL;
233   }
234 };
235 
236 
237 /**
238   class Sql_condition_identity.
239   Instances of this class uniquely identify conditions
240   (including user-defined exceptions for sql_mode=ORACLE)
241   and store everything that is needed for handler search
242   purposes in sp_pcontext::find_handler().
243 */
244 class Sql_condition_identity: public Sql_state_errno_level,
245                               public Sql_user_condition_identity
246 {
247 public:
Sql_condition_identity()248   Sql_condition_identity()
249   { }
Sql_condition_identity(const Sql_state_errno_level & st,const Sql_user_condition_identity & ucid)250   Sql_condition_identity(const Sql_state_errno_level &st,
251                          const Sql_user_condition_identity &ucid)
252    :Sql_state_errno_level(st),
253     Sql_user_condition_identity(ucid)
254   { }
Sql_condition_identity(const Sql_state_errno & st,enum_warning_level level,const Sql_user_condition_identity & ucid)255   Sql_condition_identity(const Sql_state_errno &st,
256                          enum_warning_level level,
257                          const Sql_user_condition_identity &ucid)
258    :Sql_state_errno_level(st, level),
259     Sql_user_condition_identity(ucid)
260   { }
Sql_condition_identity(uint sqlerrno,const char * sqlstate,enum_warning_level level,const Sql_user_condition_identity & ucid)261   Sql_condition_identity(uint sqlerrno,
262                          const char* sqlstate,
263                          enum_warning_level level,
264                          const Sql_user_condition_identity &ucid)
265     :Sql_state_errno_level(sqlerrno, sqlstate, level),
266      Sql_user_condition_identity(ucid)
267   { }
clear()268   void clear()
269   {
270     Sql_state_errno_level::clear();
271     Sql_user_condition_identity::clear();
272   }
273 };
274 
275 
276 class Sql_condition_items
277 {
278 protected:
279   /** SQL CLASS_ORIGIN condition item. */
280   String m_class_origin;
281 
282   /** SQL SUBCLASS_ORIGIN condition item. */
283   String m_subclass_origin;
284 
285   /** SQL CONSTRAINT_CATALOG condition item. */
286   String m_constraint_catalog;
287 
288   /** SQL CONSTRAINT_SCHEMA condition item. */
289   String m_constraint_schema;
290 
291   /** SQL CONSTRAINT_NAME condition item. */
292   String m_constraint_name;
293 
294   /** SQL CATALOG_NAME condition item. */
295   String m_catalog_name;
296 
297   /** SQL SCHEMA_NAME condition item. */
298   String m_schema_name;
299 
300   /** SQL TABLE_NAME condition item. */
301   String m_table_name;
302 
303   /** SQL COLUMN_NAME condition item. */
304   String m_column_name;
305 
306   /** SQL CURSOR_NAME condition item. */
307   String m_cursor_name;
308 
Sql_condition_items()309   Sql_condition_items()
310    :m_class_origin((const char*) NULL, 0, & my_charset_utf8_bin),
311     m_subclass_origin((const char*) NULL, 0, & my_charset_utf8_bin),
312     m_constraint_catalog((const char*) NULL, 0, & my_charset_utf8_bin),
313     m_constraint_schema((const char*) NULL, 0, & my_charset_utf8_bin),
314     m_constraint_name((const char*) NULL, 0, & my_charset_utf8_bin),
315     m_catalog_name((const char*) NULL, 0, & my_charset_utf8_bin),
316     m_schema_name((const char*) NULL, 0, & my_charset_utf8_bin),
317     m_table_name((const char*) NULL, 0, & my_charset_utf8_bin),
318     m_column_name((const char*) NULL, 0, & my_charset_utf8_bin),
319     m_cursor_name((const char*) NULL, 0, & my_charset_utf8_bin)
320   { }
321 
clear()322   void clear()
323   {
324     m_class_origin.length(0);
325     m_subclass_origin.length(0);
326     m_constraint_catalog.length(0);
327     m_constraint_schema.length(0);
328     m_constraint_name.length(0);
329     m_catalog_name.length(0);
330     m_schema_name.length(0);
331     m_table_name.length(0);
332     m_column_name.length(0);
333     m_cursor_name.length(0);
334   }
335 };
336 
337 
338 /**
339   Representation of a SQL condition.
340   A SQL condition can be a completion condition (note, warning),
341   or an exception condition (error, not found).
342 */
343 class Sql_condition : public Sql_alloc,
344                       public Sql_condition_identity,
345                       public Sql_condition_items
346 {
347 public:
348 
349   /**
350     Convert a bitmask consisting of MYSQL_TIME_{NOTE|WARN}_XXX bits
351     to WARN_LEVEL_XXX
352   */
time_warn_level(uint warnings)353   static enum_warning_level time_warn_level(uint warnings)
354   {
355     return MYSQL_TIME_WARN_HAVE_WARNINGS(warnings) ?
356            WARN_LEVEL_WARN : WARN_LEVEL_NOTE;
357   }
358 
359   /**
360     Get the MESSAGE_TEXT of this condition.
361     @return the message text.
362   */
363   const char* get_message_text() const;
364 
365   /**
366     Get the MESSAGE_OCTET_LENGTH of this condition.
367     @return the length in bytes of the message text.
368   */
369   int get_message_octet_length() const;
370 
371 private:
372   /*
373     The interface of Sql_condition is mostly private, by design,
374     so that only the following code:
375     - various raise_error() or raise_warning() methods in class THD,
376     - the implementation of SIGNAL / RESIGNAL / GET DIAGNOSTICS
377     - catch / re-throw of SQL conditions in stored procedures (sp_rcontext)
378     is allowed to create / modify a SQL condition.
379     Enforcing this policy prevents confusion, since the only public
380     interface available to the rest of the server implementation
381     is the interface offered by the THD methods (THD::raise_error()),
382     which should be used.
383   */
384   friend class THD;
385   friend class Warning_info;
386   friend class Sql_cmd_common_signal;
387   friend class Sql_cmd_signal;
388   friend class Sql_cmd_resignal;
389   friend class sp_rcontext;
390   friend class Condition_information_item;
391 
392   /**
393     Default constructor.
394     This constructor is usefull when allocating arrays.
395     Note that the init() method should be called to complete the Sql_condition.
396   */
Sql_condition()397   Sql_condition()
398    :m_mem_root(NULL)
399   { }
400 
401   /**
402     Complete the Sql_condition initialisation.
403     @param mem_root The memory root to use for the condition items
404     of this condition
405   */
init(MEM_ROOT * mem_root)406   void init(MEM_ROOT *mem_root)
407   {
408     DBUG_ASSERT(mem_root != NULL);
409     DBUG_ASSERT(m_mem_root == NULL);
410     m_mem_root= mem_root;
411   }
412 
413   /**
414     Constructor.
415     @param mem_root The memory root to use for the condition items
416     of this condition
417   */
Sql_condition(MEM_ROOT * mem_root)418   Sql_condition(MEM_ROOT *mem_root)
419    :m_mem_root(mem_root)
420   {
421     DBUG_ASSERT(mem_root != NULL);
422   }
423 
Sql_condition(MEM_ROOT * mem_root,const Sql_user_condition_identity & ucid)424   Sql_condition(MEM_ROOT *mem_root, const Sql_user_condition_identity &ucid)
425    :Sql_condition_identity(Sql_state_errno_level(), ucid),
426     m_mem_root(mem_root)
427   {
428     DBUG_ASSERT(mem_root != NULL);
429   }
430   /**
431     Constructor for a fixed message text.
432     @param mem_root - memory root
433     @param value    - the error number and the sql state for this condition
434     @param level    - the error level for this condition
435     @param msg      - the message text for this condition
436   */
Sql_condition(MEM_ROOT * mem_root,const Sql_condition_identity & value,const char * msg)437   Sql_condition(MEM_ROOT *mem_root,
438                 const Sql_condition_identity &value,
439                 const char *msg)
440    :Sql_condition_identity(value),
441     m_mem_root(mem_root)
442   {
443     DBUG_ASSERT(mem_root != NULL);
444     DBUG_ASSERT(value.get_sql_errno() != 0);
445     DBUG_ASSERT(msg != NULL);
446     set_builtin_message_text(msg);
447   }
448 
449   /** Destructor. */
~Sql_condition()450   ~Sql_condition()
451   {}
452 
453   /**
454     Copy optional condition items attributes.
455     @param cond the condition to copy.
456   */
457   void copy_opt_attributes(const Sql_condition *cond);
458 
459   /**
460     Set the condition message test.
461     @param str Message text, expressed in the character set derived from
462     the server --language option
463   */
464   void set_builtin_message_text(const char* str);
465 
466   /** Set the CLASS_ORIGIN of this condition. */
467   void set_class_origin();
468 
469   /** Set the SUBCLASS_ORIGIN of this condition. */
470   void set_subclass_origin();
471 
472   /**
473     Assign the condition items 'MYSQL_ERRNO', 'level' and 'MESSAGE_TEXT'
474     default values of a condition.
475     @param thd   - current thread, to access to localized error messages
476     @param from  - copy condition items from here (can be NULL)
477   */
478   void assign_defaults(THD *thd, const Sql_state_errno *from);
479 
480   /**
481     Clear this SQL condition.
482   */
clear()483   void clear()
484   {
485     Sql_condition_identity::clear();
486     Sql_condition_items::clear();
487     m_message_text.length(0);
488   }
489 
490 private:
491   /** Message text, expressed in the character set implied by --language. */
492   String m_message_text;
493 
494   /** Pointers for participating in the list of conditions. */
495   Sql_condition *next_in_wi;
496   Sql_condition **prev_in_wi;
497 
498   /** Memory root to use to hold condition item values. */
499   MEM_ROOT *m_mem_root;
500 };
501 
502 ///////////////////////////////////////////////////////////////////////////
503 
504 /**
505   Information about warnings of the current connection.
506 */
507 class Warning_info
508 {
509   /** The type of the counted and doubly linked list of conditions. */
510   typedef I_P_List<Sql_condition,
511                    I_P_List_adapter<Sql_condition,
512                                     &Sql_condition::next_in_wi,
513                                     &Sql_condition::prev_in_wi>,
514                    I_P_List_counter,
515                    I_P_List_fast_push_back<Sql_condition> >
516           Sql_condition_list;
517 
518   /** A memory root to allocate warnings and errors */
519   MEM_ROOT           m_warn_root;
520 
521   /** List of warnings of all severities (levels). */
522   Sql_condition_list   m_warn_list;
523 
524   /** A break down of the number of warnings per severity (level). */
525   uint	             m_warn_count[(uint) Sql_condition::WARN_LEVEL_END];
526 
527   /**
528     The number of warnings of the current statement. Warning_info
529     life cycle differs from statement life cycle -- it may span
530     multiple statements. In that case we get
531     m_current_statement_warn_count 0, whereas m_warn_list is not empty.
532   */
533   uint	             m_current_statement_warn_count;
534 
535   /*
536     Row counter, to print in errors and warnings. Not increased in
537     create_sort_index(); may differ from examined_row_count.
538   */
539   ulong              m_current_row_for_warning;
540 
541   /** Used to optionally clear warnings only once per statement. */
542   ulonglong          m_warn_id;
543 
544   /**
545     A pointer to an element of m_warn_list. It determines SQL-condition
546     instance which corresponds to the error state in Diagnostics_area.
547 
548     This is needed for properly processing SQL-conditions in SQL-handlers.
549     When an SQL-handler is found for the current error state in Diagnostics_area,
550     this pointer is needed to remove the corresponding SQL-condition from the
551     Warning_info list.
552 
553     @note m_error_condition might be NULL in the following cases:
554        - Diagnostics_area set to fatal error state (like OOM);
555        - Max number of Warning_info elements has been reached (thus, there is
556          no corresponding SQL-condition object in Warning_info).
557   */
558   const Sql_condition *m_error_condition;
559 
560   /** Indicates if push_warning() allows unlimited number of warnings. */
561   bool               m_allow_unlimited_warnings;
562   bool		     initialized;    /* Set to 1 if init() has been called */
563 
564   /** Read only status. */
565   bool m_read_only;
566 
567   /** Pointers for participating in the stack of Warning_info objects. */
568   Warning_info *m_next_in_da;
569   Warning_info **m_prev_in_da;
570 
571   List<Sql_condition> m_marked_sql_conditions;
572 
573 public:
574   Warning_info(ulonglong warn_id_arg, bool allow_unlimited_warnings,
575                bool initialized);
576   ~Warning_info();
577   /* Allocate memory for structures */
578   void init();
579   void free_memory();
580 
581 private:
582   Warning_info(const Warning_info &rhs); /* Not implemented */
583   Warning_info& operator=(const Warning_info &rhs); /* Not implemented */
584 
585   /**
586     Checks if Warning_info contains SQL-condition with the given message.
587 
588     @param message_str    Message string.
589     @param message_length Length of message string.
590 
591     @return true if the Warning_info contains an SQL-condition with the given
592     message.
593   */
594   bool has_sql_condition(const char *message_str, size_t message_length) const;
595 
596   /**
597     Reset the warning information. Clear all warnings,
598     the number of warnings, reset current row counter
599     to point to the first row.
600 
601     @param new_id new Warning_info id.
602   */
603   void clear(ulonglong new_id);
604 
605   /**
606     Only clear warning info if haven't yet done that already
607     for the current query. Allows to be issued at any time
608     during the query, without risk of clearing some warnings
609     that have been generated by the current statement.
610 
611     @todo: This is a sign of sloppy coding. Instead we need to
612     designate one place in a statement life cycle where we call
613     Warning_info::clear().
614 
615     @param query_id Current query id.
616   */
opt_clear(ulonglong query_id)617   void opt_clear(ulonglong query_id)
618   {
619     if (query_id != m_warn_id)
620       clear(query_id);
621   }
622 
623   /**
624     Concatenate the list of warnings.
625 
626     It's considered tolerable to lose an SQL-condition in case of OOM-error,
627     or if the number of SQL-conditions in the Warning_info reached top limit.
628 
629     @param thd    Thread context.
630     @param source Warning_info object to copy SQL-conditions from.
631   */
632   void append_warning_info(THD *thd, const Warning_info *source);
633 
634   /**
635     Reset between two COM_ commands. Warnings are preserved
636     between commands, but statement_warn_count indicates
637     the number of warnings of this particular statement only.
638   */
reset_for_next_command()639   void reset_for_next_command()
640   { m_current_statement_warn_count= 0; }
641 
642   /**
643     Mark active SQL-conditions for later removal.
644     This is done to simulate stacked DAs for HANDLER statements.
645   */
646   void mark_sql_conditions_for_removal();
647 
648   /**
649     Unmark SQL-conditions, which were marked for later removal.
650     This is done to simulate stacked DAs for HANDLER statements.
651   */
unmark_sql_conditions_from_removal()652   void unmark_sql_conditions_from_removal()
653   { m_marked_sql_conditions.empty(); }
654 
655   /**
656     Remove SQL-conditions that are marked for deletion.
657     This is done to simulate stacked DAs for HANDLER statements.
658   */
659   void remove_marked_sql_conditions();
660 
661   /**
662     Check if the given SQL-condition is marked for removal in this Warning_info
663     instance.
664 
665     @param cond the SQL-condition.
666 
667     @retval true if the given SQL-condition is marked for removal in this
668                  Warning_info instance.
669     @retval false otherwise.
670   */
671   bool is_marked_for_removal(const Sql_condition *cond) const;
672 
673   /**
674     Mark a single SQL-condition for removal (add the given SQL-condition to the
675     removal list of this Warning_info instance).
676   */
mark_condition_for_removal(Sql_condition * cond)677   void mark_condition_for_removal(Sql_condition *cond)
678   { m_marked_sql_conditions.push_back(cond, &m_warn_root); }
679 
680   /**
681     Used for @@warning_count system variable, which prints
682     the number of rows returned by SHOW WARNINGS.
683   */
warn_count()684   ulong warn_count() const
685   {
686     /*
687       This may be higher than warn_list.elements() if we have
688       had more warnings than thd->variables.max_error_count.
689     */
690     return (m_warn_count[(uint) Sql_condition::WARN_LEVEL_NOTE] +
691             m_warn_count[(uint) Sql_condition::WARN_LEVEL_ERROR] +
692             m_warn_count[(uint) Sql_condition::WARN_LEVEL_WARN]);
693   }
694 
695   /**
696     The number of errors, or number of rows returned by SHOW ERRORS,
697     also the value of session variable @@error_count.
698   */
error_count()699   ulong error_count() const
700   { return m_warn_count[(uint) Sql_condition::WARN_LEVEL_ERROR]; }
701 
702   /**
703     The number of conditions (errors, warnings and notes) in the list.
704   */
cond_count()705   uint cond_count() const
706   {
707     return m_warn_list.elements();
708   }
709 
710   /** Id of the warning information area. */
id()711   ulonglong id() const { return m_warn_id; }
712 
713   /** Set id of the warning information area. */
id(ulonglong id_arg)714   void id(ulonglong id_arg) { m_warn_id= id_arg; }
715 
716   /** Do we have any errors and warnings that we can *show*? */
is_empty()717   bool is_empty() const { return m_warn_list.is_empty(); }
718 
719   /** Increment the current row counter to point at the next row. */
inc_current_row_for_warning()720   void inc_current_row_for_warning() { m_current_row_for_warning++; }
721 
722   /** Reset the current row counter. Start counting from the first row. */
reset_current_row_for_warning()723   void reset_current_row_for_warning() { m_current_row_for_warning= 1; }
724 
725   /** Return the current counter value. */
current_row_for_warning()726   ulong current_row_for_warning() const { return m_current_row_for_warning; }
727 
728   /** Return the number of warnings thrown by the current statement. */
current_statement_warn_count()729   ulong current_statement_warn_count() const
730   { return m_current_statement_warn_count; }
731 
732   /** Make sure there is room for the given number of conditions. */
733   void reserve_space(THD *thd, uint count);
734 
735   /**
736     Add a new SQL-condition to the current list and increment the respective
737     counters.
738 
739     @param thd        Thread context.
740     @param identity   SQL-condition identity
741     @param msg        SQL-condition message.
742 
743     @return a pointer to the added SQL-condition.
744   */
745   Sql_condition *push_warning(THD *thd,
746                               const Sql_condition_identity *identity,
747                               const char* msg);
748 
749   /**
750     Add a new SQL-condition to the current list and increment the respective
751     counters.
752 
753     @param thd            Thread context.
754     @param sql_condition  SQL-condition to copy values from.
755 
756     @return a pointer to the added SQL-condition.
757   */
758   Sql_condition *push_warning(THD *thd, const Sql_condition *sql_condition);
759 
760   /**
761     Set the read only status for this statement area.
762     This is a privileged operation, reserved for the implementation of
763     diagnostics related statements, to enforce that the statement area is
764     left untouched during execution.
765     The diagnostics statements are:
766     - SHOW WARNINGS
767     - SHOW ERRORS
768     - GET DIAGNOSTICS
769     @param read_only the read only property to set.
770   */
set_read_only(bool read_only_arg)771   void set_read_only(bool read_only_arg)
772   { m_read_only= read_only_arg; }
773 
774   /**
775     Read only status.
776     @return the read only property.
777   */
is_read_only()778   bool is_read_only() const
779   { return m_read_only; }
780 
781   /**
782     @return SQL-condition, which corresponds to the error state in
783     Diagnostics_area.
784 
785     @see m_error_condition.
786   */
get_error_condition()787   const Sql_condition *get_error_condition() const
788   { return m_error_condition; }
789 
790   /**
791     Set SQL-condition, which corresponds to the error state in Diagnostics_area.
792 
793     @see m_error_condition.
794   */
set_error_condition(const Sql_condition * error_condition)795   void set_error_condition(const Sql_condition *error_condition)
796   { m_error_condition= error_condition; }
797 
798   /**
799     Reset SQL-condition, which corresponds to the error state in
800     Diagnostics_area.
801 
802     @see m_error_condition.
803   */
clear_error_condition()804   void clear_error_condition()
805   { m_error_condition= NULL; }
806 
807   // for:
808   //   - m_next_in_da / m_prev_in_da
809   //   - is_marked_for_removal()
810   friend class Diagnostics_area;
811 };
812 
813 
814 extern char *err_conv(char *buff, uint to_length, const char *from,
815                       uint from_length, CHARSET_INFO *from_cs);
816 
817 class ErrConv
818 {
819 protected:
820   mutable char err_buffer[MYSQL_ERRMSG_SIZE];
821 public:
ErrConv()822   ErrConv() {}
~ErrConv()823   virtual ~ErrConv() {}
824   virtual const char *ptr() const = 0;
825 };
826 
827 class ErrConvString : public ErrConv
828 {
829   const char *str;
830   size_t len;
831   CHARSET_INFO *cs;
832 public:
ErrConvString(const char * str_arg,size_t len_arg,CHARSET_INFO * cs_arg)833   ErrConvString(const char *str_arg, size_t len_arg, CHARSET_INFO *cs_arg)
834     : ErrConv(), str(str_arg), len(len_arg), cs(cs_arg) {}
ErrConvString(const char * str_arg,CHARSET_INFO * cs_arg)835   ErrConvString(const char *str_arg, CHARSET_INFO *cs_arg)
836     : ErrConv(), str(str_arg), len(strlen(str_arg)), cs(cs_arg) {}
ErrConvString(const String * s)837   ErrConvString(const String *s)
838     : ErrConv(), str(s->ptr()), len(s->length()), cs(s->charset()) {}
ptr()839   const char *ptr() const
840   {
841     DBUG_ASSERT(len < UINT_MAX32);
842     return err_conv(err_buffer, (uint) sizeof(err_buffer), str, (uint) len, cs);
843   }
844 };
845 
846 class ErrConvInteger : public ErrConv, public Longlong_hybrid
847 {
848 public:
849   ErrConvInteger(longlong num_arg, bool unsigned_flag= false) :
ErrConv()850     ErrConv(), Longlong_hybrid(num_arg, unsigned_flag) {}
ptr()851   const char *ptr() const
852   {
853     return m_unsigned ? ullstr(m_value, err_buffer) :
854                          llstr(m_value, err_buffer);
855   }
856 };
857 
858 class ErrConvDouble: public ErrConv
859 {
860   double num;
861 public:
ErrConvDouble(double num_arg)862   ErrConvDouble(double num_arg) : ErrConv(), num(num_arg) {}
ptr()863   const char *ptr() const
864   {
865     my_gcvt(num, MY_GCVT_ARG_DOUBLE, sizeof(err_buffer), err_buffer, 0);
866     return err_buffer;
867   }
868 };
869 
870 class ErrConvTime : public ErrConv
871 {
872   const MYSQL_TIME *ltime;
873 public:
ErrConvTime(const MYSQL_TIME * ltime_arg)874   ErrConvTime(const MYSQL_TIME *ltime_arg) : ErrConv(), ltime(ltime_arg) {}
ptr()875   const char *ptr() const
876   {
877     my_TIME_to_str(ltime, err_buffer, AUTO_SEC_PART_DIGITS);
878     return err_buffer;
879   }
880 };
881 
882 class ErrConvDecimal : public ErrConv
883 {
884   const decimal_t *d;
885 public:
ErrConvDecimal(const decimal_t * d_arg)886   ErrConvDecimal(const decimal_t *d_arg) : ErrConv(), d(d_arg) {}
ptr()887   const char *ptr() const
888   {
889     int len= sizeof(err_buffer);
890     decimal2string(d, err_buffer, &len, 0, 0, ' ');
891     return err_buffer;
892   }
893 };
894 
895 ///////////////////////////////////////////////////////////////////////////
896 
897 /**
898   Stores status of the currently executed statement.
899   Cleared at the beginning of the statement, and then
900   can hold either OK, ERROR, or EOF status.
901   Can not be assigned twice per statement.
902 */
903 
904 class Diagnostics_area: public Sql_state_errno,
905                         public Sql_user_condition_identity
906 {
907 private:
908   /** The type of the counted and doubly linked list of conditions. */
909   typedef I_P_List<Warning_info,
910                    I_P_List_adapter<Warning_info,
911                                     &Warning_info::m_next_in_da,
912                                     &Warning_info::m_prev_in_da>,
913                    I_P_List_counter,
914                    I_P_List_fast_push_back<Warning_info> >
915           Warning_info_list;
916 
917 public:
918   /** Const iterator used to iterate through the warning list. */
919   typedef Warning_info::Sql_condition_list::Const_Iterator
920     Sql_condition_iterator;
921 
922   enum enum_diagnostics_status
923   {
924     /** The area is cleared at start of a statement. */
925     DA_EMPTY= 0,
926     /** Set whenever one calls my_ok(). */
927     DA_OK,
928     /** Set whenever one calls my_eof(). */
929     DA_EOF,
930     /** Set whenever one calls my_ok() in PS bulk mode. */
931     DA_OK_BULK,
932     /** Set whenever one calls my_error() or my_message(). */
933     DA_ERROR,
934     /** Set in case of a custom response, such as one from COM_STMT_PREPARE. */
935     DA_DISABLED
936   };
937 
set_overwrite_status(bool can_overwrite_status)938   void set_overwrite_status(bool can_overwrite_status)
939   { m_can_overwrite_status= can_overwrite_status; }
940 
941   /** True if status information is sent to the client. */
is_sent()942   bool is_sent() const { return m_is_sent; }
943 
set_is_sent(bool is_sent_arg)944   void set_is_sent(bool is_sent_arg) { m_is_sent= is_sent_arg; }
945 
946   void set_ok_status(ulonglong affected_rows,
947                      ulonglong last_insert_id,
948                      const char *message);
949 
950   void set_eof_status(THD *thd);
951 
952   void set_error_status(uint sql_errno);
953 
954   void set_error_status(uint sql_errno,
955                         const char *message,
956                         const char *sqlstate,
957                         const Sql_user_condition_identity &ucid,
958                         const Sql_condition *error_condition);
959 
set_error_status(uint sql_errno,const char * message,const char * sqlstate,const Sql_condition * error_condition)960   void set_error_status(uint sql_errno,
961                         const char *message,
962                         const char *sqlstate,
963                         const Sql_condition *error_condition)
964   {
965     set_error_status(sql_errno, message, sqlstate,
966                      Sql_user_condition_identity(),
967                      error_condition);
968   }
969 
970   void disable_status();
971 
972   void reset_diagnostics_area();
973 
is_set()974   bool is_set() const { return m_status != DA_EMPTY; }
975 
is_error()976   bool is_error() const { return m_status == DA_ERROR; }
977 
is_eof()978   bool is_eof() const { return m_status == DA_EOF; }
979 
is_ok()980   bool is_ok() const { return m_status == DA_OK; }
981 
is_disabled()982   bool is_disabled() const { return m_status == DA_DISABLED; }
983 
set_bulk_execution(bool bulk)984   void set_bulk_execution(bool bulk) { is_bulk_execution= bulk; }
985 
is_bulk_op()986   bool is_bulk_op() const { return is_bulk_execution; }
987 
status()988   enum_diagnostics_status status() const { return m_status; }
989 
message()990   const char *message() const
991   { DBUG_ASSERT(m_status == DA_ERROR || m_status == DA_OK ||
992                 m_status == DA_OK_BULK); return m_message; }
993 
skip_flush()994   bool skip_flush() const
995   {
996     DBUG_ASSERT(m_status == DA_OK || m_status == DA_OK_BULK);
997     return m_skip_flush;
998   }
999 
set_skip_flush()1000   void set_skip_flush()
1001   { m_skip_flush= TRUE; }
1002 
sql_errno()1003   uint sql_errno() const
1004   {
1005     DBUG_ASSERT(m_status == DA_ERROR);
1006     return Sql_state_errno::get_sql_errno();
1007   }
1008 
get_sqlstate()1009   const char* get_sqlstate() const
1010   { DBUG_ASSERT(m_status == DA_ERROR); return Sql_state::get_sqlstate(); }
1011 
affected_rows()1012   ulonglong affected_rows() const
1013   {
1014     DBUG_ASSERT(m_status == DA_OK || m_status == DA_OK_BULK);
1015     return m_affected_rows;
1016   }
1017 
last_insert_id()1018   ulonglong last_insert_id() const
1019   {
1020     DBUG_ASSERT(m_status == DA_OK || m_status == DA_OK_BULK);
1021     return m_last_insert_id;
1022   }
1023 
statement_warn_count()1024   uint statement_warn_count() const
1025   {
1026     DBUG_ASSERT(m_status == DA_OK || m_status == DA_OK_BULK ||
1027                 m_status == DA_EOF);
1028     return m_statement_warn_count;
1029   }
1030 
1031   /**
1032     Get the current errno, state and id of the user defined condition
1033     and return them as Sql_condition_identity.
1034   */
get_error_condition_identity()1035   Sql_condition_identity get_error_condition_identity() const
1036   {
1037     DBUG_ASSERT(m_status == DA_ERROR);
1038     return Sql_condition_identity(*this /*Sql_state_errno*/,
1039                                   Sql_condition::WARN_LEVEL_ERROR,
1040                                   *this /*Sql_user_condition_identity*/);
1041   }
1042 
1043   /* Used to count any warnings pushed after calling set_ok_status(). */
increment_warning()1044   void increment_warning()
1045   {
1046     if (m_status != DA_EMPTY)
1047       m_statement_warn_count++;
1048   }
1049 
1050   Diagnostics_area(bool initialize);
1051   Diagnostics_area(ulonglong warning_info_id, bool allow_unlimited_warnings,
1052                    bool initialize);
init()1053   void init() { m_main_wi.init() ; }
free_memory()1054   void free_memory() { m_main_wi.free_memory() ; }
1055 
push_warning_info(Warning_info * wi)1056   void push_warning_info(Warning_info *wi)
1057   { m_wi_stack.push_front(wi); }
1058 
pop_warning_info()1059   void pop_warning_info()
1060   {
1061     DBUG_ASSERT(m_wi_stack.elements() > 0);
1062     m_wi_stack.remove(m_wi_stack.front());
1063   }
1064 
set_warning_info_id(ulonglong id)1065   void set_warning_info_id(ulonglong id)
1066   { get_warning_info()->id(id); }
1067 
warning_info_id()1068   ulonglong warning_info_id() const
1069   { return get_warning_info()->id(); }
1070 
1071   /**
1072     Compare given current warning info and current warning info
1073     and see if they are different. They will be different if
1074     warnings have been generated or statements that use tables
1075     have been executed. This is checked by comparing m_warn_id.
1076 
1077     @param wi  Warning info to compare with current Warning info.
1078 
1079     @return    false if they are equal, true if they are not.
1080   */
warning_info_changed(const Warning_info * wi)1081   bool warning_info_changed(const Warning_info *wi) const
1082   { return get_warning_info()->id() != wi->id(); }
1083 
is_warning_info_empty()1084   bool is_warning_info_empty() const
1085   { return get_warning_info()->is_empty(); }
1086 
current_statement_warn_count()1087   ulong current_statement_warn_count() const
1088   { return get_warning_info()->current_statement_warn_count(); }
1089 
has_sql_condition(const char * message_str,size_t message_length)1090   bool has_sql_condition(const char *message_str, size_t message_length) const
1091   { return get_warning_info()->has_sql_condition(message_str, message_length); }
1092 
reset_for_next_command()1093   void reset_for_next_command()
1094   { get_warning_info()->reset_for_next_command(); }
1095 
clear_warning_info(ulonglong id)1096   void clear_warning_info(ulonglong id)
1097   { get_warning_info()->clear(id); }
1098 
opt_clear_warning_info(ulonglong query_id)1099   void opt_clear_warning_info(ulonglong query_id)
1100   { get_warning_info()->opt_clear(query_id); }
1101 
current_row_for_warning()1102   ulong current_row_for_warning() const
1103   { return get_warning_info()->current_row_for_warning(); }
1104 
inc_current_row_for_warning()1105   void inc_current_row_for_warning()
1106   { get_warning_info()->inc_current_row_for_warning(); }
1107 
reset_current_row_for_warning()1108   void reset_current_row_for_warning()
1109   { get_warning_info()->reset_current_row_for_warning(); }
1110 
is_warning_info_read_only()1111   bool is_warning_info_read_only() const
1112   { return get_warning_info()->is_read_only(); }
1113 
set_warning_info_read_only(bool read_only_arg)1114   void set_warning_info_read_only(bool read_only_arg)
1115   { get_warning_info()->set_read_only(read_only_arg); }
1116 
error_count()1117   ulong error_count() const
1118   { return get_warning_info()->error_count(); }
1119 
warn_count()1120   ulong warn_count() const
1121   { return get_warning_info()->warn_count(); }
1122 
cond_count()1123   uint cond_count() const
1124   { return get_warning_info()->cond_count(); }
1125 
sql_conditions()1126   Sql_condition_iterator sql_conditions() const
1127   { return get_warning_info()->m_warn_list; }
1128 
reserve_space(THD * thd,uint count)1129   void reserve_space(THD *thd, uint count)
1130   { get_warning_info()->reserve_space(thd, count); }
1131 
push_warning(THD * thd,const Sql_condition * sql_condition)1132   Sql_condition *push_warning(THD *thd, const Sql_condition *sql_condition)
1133   { return get_warning_info()->push_warning(thd, sql_condition); }
1134 
push_warning(THD * thd,uint sql_errno_arg,const char * sqlstate,Sql_condition::enum_warning_level level,const Sql_user_condition_identity & ucid,const char * msg)1135   Sql_condition *push_warning(THD *thd,
1136                               uint sql_errno_arg,
1137                               const char* sqlstate,
1138                               Sql_condition::enum_warning_level level,
1139                               const Sql_user_condition_identity &ucid,
1140                               const char* msg)
1141   {
1142     Sql_condition_identity tmp(sql_errno_arg, sqlstate, level, ucid);
1143     return get_warning_info()->push_warning(thd, &tmp, msg);
1144   }
1145 
push_warning(THD * thd,uint sqlerrno,const char * sqlstate,Sql_condition::enum_warning_level level,const char * msg)1146   Sql_condition *push_warning(THD *thd,
1147                               uint sqlerrno,
1148                               const char* sqlstate,
1149                               Sql_condition::enum_warning_level level,
1150                               const char* msg)
1151   {
1152     return push_warning(thd, sqlerrno, sqlstate, level,
1153                         Sql_user_condition_identity(), msg);
1154   }
mark_sql_conditions_for_removal()1155   void mark_sql_conditions_for_removal()
1156   { get_warning_info()->mark_sql_conditions_for_removal(); }
1157 
unmark_sql_conditions_from_removal()1158   void unmark_sql_conditions_from_removal()
1159   { get_warning_info()->unmark_sql_conditions_from_removal(); }
1160 
remove_marked_sql_conditions()1161   void remove_marked_sql_conditions()
1162   { get_warning_info()->remove_marked_sql_conditions(); }
1163 
get_error_condition()1164   const Sql_condition *get_error_condition() const
1165   { return get_warning_info()->get_error_condition(); }
1166 
copy_sql_conditions_to_wi(THD * thd,Warning_info * dst_wi)1167   void copy_sql_conditions_to_wi(THD *thd, Warning_info *dst_wi) const
1168   { dst_wi->append_warning_info(thd, get_warning_info()); }
1169 
copy_sql_conditions_from_wi(THD * thd,const Warning_info * src_wi)1170   void copy_sql_conditions_from_wi(THD *thd, const Warning_info *src_wi)
1171   { get_warning_info()->append_warning_info(thd, src_wi); }
1172 
1173   void copy_non_errors_from_wi(THD *thd, const Warning_info *src_wi);
1174 
1175 private:
get_warning_info()1176   Warning_info *get_warning_info() { return m_wi_stack.front(); }
1177 
get_warning_info()1178   const Warning_info *get_warning_info() const { return m_wi_stack.front(); }
1179 
1180 private:
1181   /** True if status information is sent to the client. */
1182   bool m_is_sent;
1183 
1184   /** Set to make set_error_status after set_{ok,eof}_status possible. */
1185   bool m_can_overwrite_status;
1186 
1187   /** Skip flushing network buffer after writing OK (for COM_MULTI) */
1188   bool m_skip_flush;
1189 
1190   /** Message buffer. Can be used by OK or ERROR status. */
1191   char m_message[MYSQL_ERRMSG_SIZE];
1192 
1193   /**
1194     The number of rows affected by the last statement. This is
1195     semantically close to thd->m_row_count_func, but has a different
1196     life cycle. thd->m_row_count_func stores the value returned by
1197     function ROW_COUNT() and is cleared only by statements that
1198     update its value, such as INSERT, UPDATE, DELETE and few others.
1199     This member is cleared at the beginning of the next statement.
1200 
1201     We could possibly merge the two, but life cycle of thd->m_row_count_func
1202     can not be changed.
1203   */
1204   ulonglong    m_affected_rows;
1205 
1206   /**
1207     Similarly to the previous member, this is a replacement of
1208     thd->first_successful_insert_id_in_prev_stmt, which is used
1209     to implement LAST_INSERT_ID().
1210   */
1211 
1212   ulonglong   m_last_insert_id;
1213   /**
1214     Number of warnings of this last statement. May differ from
1215     the number of warnings returned by SHOW WARNINGS e.g. in case
1216     the statement doesn't clear the warnings, and doesn't generate
1217     them.
1218   */
1219   uint	     m_statement_warn_count;
1220 
1221   enum_diagnostics_status m_status;
1222 
1223   my_bool is_bulk_execution;
1224 
1225   Warning_info m_main_wi;
1226 
1227   Warning_info_list m_wi_stack;
1228 };
1229 
1230 ///////////////////////////////////////////////////////////////////////////
1231 
1232 
1233 void push_warning(THD *thd, Sql_condition::enum_warning_level level,
1234                   uint code, const char *msg);
1235 
1236 void push_warning_printf(THD *thd, Sql_condition::enum_warning_level level,
1237                          uint code, const char *format, ...);
1238 
1239 bool mysqld_show_warnings(THD *thd, ulong levels_to_show);
1240 
1241 size_t convert_error_message(char *to, size_t to_length,
1242                              CHARSET_INFO *to_cs,
1243                              const char *from, size_t from_length,
1244                              CHARSET_INFO *from_cs, uint *errors);
1245 
1246 extern const LEX_CSTRING warning_level_names[];
1247 
1248 bool is_sqlstate_valid(const LEX_CSTRING *sqlstate);
1249 /**
1250   Checks if the specified SQL-state-string defines COMPLETION condition.
1251   This function assumes that the given string contains a valid SQL-state.
1252 
1253   @param s the condition SQLSTATE.
1254 
1255   @retval true if the given string defines COMPLETION condition.
1256   @retval false otherwise.
1257 */
is_sqlstate_completion(const char * s)1258 inline bool is_sqlstate_completion(const char *s)
1259 { return s[0] == '0' && s[1] == '0'; }
1260 
1261 
1262 #endif // SQL_ERROR_H
1263