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-1301, 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 "m_string.h" /* LEX_STRING */
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
28class THD;
29class my_decimal;
30class sp_condition_value;
31
32///////////////////////////////////////////////////////////////////////////
33
34class Sql_state
35{
36protected:
37 /**
38 This member is always NUL terminated.
39 */
40 char m_sqlstate[SQLSTATE_LENGTH + 1];
41public:
42 Sql_state()
43 {
44 memset(m_sqlstate, 0, sizeof(m_sqlstate));
45 }
46
47 Sql_state(const char *sqlstate)
48 {
49 set_sqlstate(sqlstate);
50 }
51
52 const char* get_sqlstate() const
53 { return m_sqlstate; }
54
55 void set_sqlstate(const Sql_state *other)
56 {
57 *this= *other;
58 }
59 void set_sqlstate(const char *sqlstate)
60 {
61 memcpy(m_sqlstate, sqlstate, SQLSTATE_LENGTH);
62 m_sqlstate[SQLSTATE_LENGTH]= '\0';
63 }
64 bool eq(const Sql_state *other) const
65 {
66 return strcmp(m_sqlstate, other->m_sqlstate) == 0;
67 }
68
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 */
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 */
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 */
100 inline bool is_exception() const
101 { return m_sqlstate[0] != '0' || m_sqlstate[1] > '2'; }
102
103};
104
105
106class Sql_state_errno: public Sql_state
107{
108protected:
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
116public:
117 Sql_state_errno()
118 :m_sql_errno(0)
119 { }
120 Sql_state_errno(uint sql_errno)
121 :m_sql_errno(sql_errno)
122 { }
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 */
131 uint get_sql_errno() const
132 { return m_sql_errno; }
133
134 void set(uint sql_errno, const char *sqlstate)
135 {
136 m_sql_errno= sql_errno;
137 set_sqlstate(sqlstate);
138 }
139 void clear()
140 {
141 m_sql_errno= 0;
142 }
143};
144
145
146class Sql_state_errno_level: public Sql_state_errno
147{
148public:
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
158protected:
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
164public:
165 /**
166 Get the error level of this condition.
167 @return the error level condition item.
168 */
169 enum_warning_level get_level() const
170 { return m_level; }
171
172 Sql_state_errno_level()
173 :m_level(WARN_LEVEL_ERROR)
174 { }
175
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 { }
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 { }
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*/
212class Sql_user_condition_identity
213{
214protected:
215 const sp_condition_value *m_user_condition_value;
216public:
217 Sql_user_condition_identity()
218 :m_user_condition_value(NULL)
219 { }
220 Sql_user_condition_identity(const sp_condition_value *value)
221 :m_user_condition_value(value)
222 { }
223 const sp_condition_value *get_user_condition_value() const
224 { return m_user_condition_value; }
225
226 void set(const Sql_user_condition_identity &identity)
227 {
228 *this= identity;
229 }
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*/
244class Sql_condition_identity: public Sql_state_errno_level,
245 public Sql_user_condition_identity
246{
247public:
248 Sql_condition_identity()
249 { }
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 { }
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 { }
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 { }
268 void clear()
269 {
270 Sql_state_errno_level::clear();
271 Sql_user_condition_identity::clear();
272 }
273};
274
275
276class Sql_condition_items
277{
278protected:
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
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
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*/
343class Sql_condition : public Sql_alloc,
344 public Sql_condition_identity,
345 public Sql_condition_items
346{
347public:
348
349 /**
350 Convert a bitmask consisting of MYSQL_TIME_{NOTE|WARN}_XXX bits
351 to WARN_LEVEL_XXX
352 */
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
371private:
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 */
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 */
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 */
418 Sql_condition(MEM_ROOT *mem_root)
419 :m_mem_root(mem_root)
420 {
421 DBUG_ASSERT(mem_root != NULL);
422 }
423
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 */
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. */
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 */
483 void clear()
484 {
485 Sql_condition_identity::clear();
486 Sql_condition_items::clear();
487 m_message_text.length(0);
488 }
489
490private:
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*/
507class 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
573public:
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
581private:
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 */
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 */
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 */
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 */
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 */
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 */
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 */
705 uint cond_count() const
706 {
707 return m_warn_list.elements();
708 }
709
710 /** Id of the warning information area. */
711 ulonglong id() const { return m_warn_id; }
712
713 /** Set id of the warning information area. */
714 void id(ulonglong id_arg) { m_warn_id= id_arg; }
715
716 /** Do we have any errors and warnings that we can *show*? */
717 bool is_empty() const { return m_warn_list.is_empty(); }
718
719 /** Increment the current row counter to point at the next row. */
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. */
723 void reset_current_row_for_warning() { m_current_row_for_warning= 1; }
724
725 /** Return the current counter value. */
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. */
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 */
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 */
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 */
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 */
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 */
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
814extern char *err_conv(char *buff, uint to_length, const char *from,
815 uint from_length, CHARSET_INFO *from_cs);
816
817class ErrConv
818{
819protected:
820 mutable char err_buffer[MYSQL_ERRMSG_SIZE];
821public:
822 ErrConv() {}
823 virtual ~ErrConv() {}
824 virtual const char *ptr() const = 0;
825};
826
827class ErrConvString : public ErrConv
828{
829 const char *str;
830 size_t len;
831 CHARSET_INFO *cs;
832public:
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) {}
835 ErrConvString(const char *str_arg, CHARSET_INFO *cs_arg)
836 : ErrConv(), str(str_arg), len(strlen(str_arg)), cs(cs_arg) {}
837 ErrConvString(const String *s)
838 : ErrConv(), str(s->ptr()), len(s->length()), cs(s->charset()) {}
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
846class ErrConvInteger : public ErrConv
847{
848 longlong m_value;
849 bool m_unsigned;
850public:
851 ErrConvInteger(longlong num_arg, bool unsigned_flag= false) :
852 ErrConv(), m_value(num_arg), m_unsigned(unsigned_flag) {}
853 const char *ptr() const
854 {
855 return m_unsigned ? ullstr(m_value, err_buffer) :
856 llstr(m_value, err_buffer);
857 }
858};
859
860class ErrConvDouble: public ErrConv
861{
862 double num;
863public:
864 ErrConvDouble(double num_arg) : ErrConv(), num(num_arg) {}
865 const char *ptr() const
866 {
867 my_gcvt(num, MY_GCVT_ARG_DOUBLE, sizeof(err_buffer), err_buffer, 0);
868 return err_buffer;
869 }
870};
871
872class ErrConvTime : public ErrConv
873{
874 const MYSQL_TIME *ltime;
875public:
876 ErrConvTime(const MYSQL_TIME *ltime_arg) : ErrConv(), ltime(ltime_arg) {}
877 const char *ptr() const
878 {
879 my_TIME_to_str(ltime, err_buffer, AUTO_SEC_PART_DIGITS);
880 return err_buffer;
881 }
882};
883
884class ErrConvDecimal : public ErrConv
885{
886 const decimal_t *d;
887public:
888 ErrConvDecimal(const decimal_t *d_arg) : ErrConv(), d(d_arg) {}
889 const char *ptr() const
890 {
891 int len= sizeof(err_buffer);
892 decimal2string(d, err_buffer, &len, 0, 0, ' ');
893 return err_buffer;
894 }
895};
896
897///////////////////////////////////////////////////////////////////////////
898
899/**
900 Stores status of the currently executed statement.
901 Cleared at the beginning of the statement, and then
902 can hold either OK, ERROR, or EOF status.
903 Can not be assigned twice per statement.
904*/
905
906class Diagnostics_area: public Sql_state_errno,
907 public Sql_user_condition_identity
908{
909private:
910 /** The type of the counted and doubly linked list of conditions. */
911 typedef I_P_List<Warning_info,
912 I_P_List_adapter<Warning_info,
913 &Warning_info::m_next_in_da,
914 &Warning_info::m_prev_in_da>,
915 I_P_List_counter,
916 I_P_List_fast_push_back<Warning_info> >
917 Warning_info_list;
918
919public:
920 /** Const iterator used to iterate through the warning list. */
921 typedef Warning_info::Sql_condition_list::Const_Iterator
922 Sql_condition_iterator;
923
924 enum enum_diagnostics_status
925 {
926 /** The area is cleared at start of a statement. */
927 DA_EMPTY= 0,
928 /** Set whenever one calls my_ok(). */
929 DA_OK,
930 /** Set whenever one calls my_eof(). */
931 DA_EOF,
932 /** Set whenever one calls my_ok() in PS bulk mode. */
933 DA_OK_BULK,
934 /** Set whenever one calls my_error() or my_message(). */
935 DA_ERROR,
936 /** Set in case of a custom response, such as one from COM_STMT_PREPARE. */
937 DA_DISABLED
938 };
939
940 void set_overwrite_status(bool can_overwrite_status)
941 { m_can_overwrite_status= can_overwrite_status; }
942
943 /** True if status information is sent to the client. */
944 bool is_sent() const { return m_is_sent; }
945
946 void set_is_sent(bool is_sent_arg) { m_is_sent= is_sent_arg; }
947
948 void set_ok_status(ulonglong affected_rows,
949 ulonglong last_insert_id,
950 const char *message);
951
952 void set_eof_status(THD *thd);
953
954 void set_error_status(uint sql_errno);
955
956 void set_error_status(uint sql_errno,
957 const char *message,
958 const char *sqlstate,
959 const Sql_user_condition_identity &ucid,
960 const Sql_condition *error_condition);
961
962 void set_error_status(uint sql_errno,
963 const char *message,
964 const char *sqlstate,
965 const Sql_condition *error_condition)
966 {
967 set_error_status(sql_errno, message, sqlstate,
968 Sql_user_condition_identity(),
969 error_condition);
970 }
971
972 void disable_status();
973
974 void reset_diagnostics_area();
975
976 bool is_set() const { return m_status != DA_EMPTY; }
977
978 bool is_error() const { return m_status == DA_ERROR; }
979
980 bool is_eof() const { return m_status == DA_EOF; }
981
982 bool is_ok() const { return m_status == DA_OK; }
983
984 bool is_disabled() const { return m_status == DA_DISABLED; }
985
986 void set_bulk_execution(bool bulk) { is_bulk_execution= bulk; }
987
988 bool is_bulk_op() const { return is_bulk_execution; }
989
990 enum_diagnostics_status status() const { return m_status; }
991
992 const char *message() const
993 { DBUG_ASSERT(m_status == DA_ERROR || m_status == DA_OK ||
994 m_status == DA_OK_BULK); return m_message; }
995
996 bool skip_flush() const
997 {
998 DBUG_ASSERT(m_status == DA_OK || m_status == DA_OK_BULK);
999 return m_skip_flush;
1000 }
1001
1002 void set_skip_flush()
1003 { m_skip_flush= TRUE; }
1004
1005 uint sql_errno() const
1006 {
1007 DBUG_ASSERT(m_status == DA_ERROR);
1008 return Sql_state_errno::get_sql_errno();
1009 }
1010
1011 const char* get_sqlstate() const
1012 { DBUG_ASSERT(m_status == DA_ERROR); return Sql_state::get_sqlstate(); }
1013
1014 ulonglong affected_rows() const
1015 {
1016 DBUG_ASSERT(m_status == DA_OK || m_status == DA_OK_BULK);
1017 return m_affected_rows;
1018 }
1019
1020 ulonglong last_insert_id() const
1021 {
1022 DBUG_ASSERT(m_status == DA_OK || m_status == DA_OK_BULK);
1023 return m_last_insert_id;
1024 }
1025
1026 uint statement_warn_count() const
1027 {
1028 DBUG_ASSERT(m_status == DA_OK || m_status == DA_OK_BULK ||
1029 m_status == DA_EOF);
1030 return m_statement_warn_count;
1031 }
1032
1033 /**
1034 Get the current errno, state and id of the user defined condition
1035 and return them as Sql_condition_identity.
1036 */
1037 Sql_condition_identity get_error_condition_identity() const
1038 {
1039 DBUG_ASSERT(m_status == DA_ERROR);
1040 return Sql_condition_identity(*this /*Sql_state_errno*/,
1041 Sql_condition::WARN_LEVEL_ERROR,
1042 *this /*Sql_user_condition_identity*/);
1043 }
1044
1045 /* Used to count any warnings pushed after calling set_ok_status(). */
1046 void increment_warning()
1047 {
1048 if (m_status != DA_EMPTY)
1049 m_statement_warn_count++;
1050 }
1051
1052 Diagnostics_area(bool initialize);
1053 Diagnostics_area(ulonglong warning_info_id, bool allow_unlimited_warnings,
1054 bool initialize);
1055 void init() { m_main_wi.init() ; }
1056 void free_memory() { m_main_wi.free_memory() ; }
1057
1058 void push_warning_info(Warning_info *wi)
1059 { m_wi_stack.push_front(wi); }
1060
1061 void pop_warning_info()
1062 {
1063 DBUG_ASSERT(m_wi_stack.elements() > 0);
1064 m_wi_stack.remove(m_wi_stack.front());
1065 }
1066
1067 void set_warning_info_id(ulonglong id)
1068 { get_warning_info()->id(id); }
1069
1070 ulonglong warning_info_id() const
1071 { return get_warning_info()->id(); }
1072
1073 /**
1074 Compare given current warning info and current warning info
1075 and see if they are different. They will be different if
1076 warnings have been generated or statements that use tables
1077 have been executed. This is checked by comparing m_warn_id.
1078
1079 @param wi Warning info to compare with current Warning info.
1080
1081 @return false if they are equal, true if they are not.
1082 */
1083 bool warning_info_changed(const Warning_info *wi) const
1084 { return get_warning_info()->id() != wi->id(); }
1085
1086 bool is_warning_info_empty() const
1087 { return get_warning_info()->is_empty(); }
1088
1089 ulong current_statement_warn_count() const
1090 { return get_warning_info()->current_statement_warn_count(); }
1091
1092 bool has_sql_condition(const char *message_str, size_t message_length) const
1093 { return get_warning_info()->has_sql_condition(message_str, message_length); }
1094
1095 void reset_for_next_command()
1096 { get_warning_info()->reset_for_next_command(); }
1097
1098 void clear_warning_info(ulonglong id)
1099 { get_warning_info()->clear(id); }
1100
1101 void opt_clear_warning_info(ulonglong query_id)
1102 { get_warning_info()->opt_clear(query_id); }
1103
1104 ulong current_row_for_warning() const
1105 { return get_warning_info()->current_row_for_warning(); }
1106
1107 void inc_current_row_for_warning()
1108 { get_warning_info()->inc_current_row_for_warning(); }
1109
1110 void reset_current_row_for_warning()
1111 { get_warning_info()->reset_current_row_for_warning(); }
1112
1113 bool is_warning_info_read_only() const
1114 { return get_warning_info()->is_read_only(); }
1115
1116 void set_warning_info_read_only(bool read_only_arg)
1117 { get_warning_info()->set_read_only(read_only_arg); }
1118
1119 ulong error_count() const
1120 { return get_warning_info()->error_count(); }
1121
1122 ulong warn_count() const
1123 { return get_warning_info()->warn_count(); }
1124
1125 uint cond_count() const
1126 { return get_warning_info()->cond_count(); }
1127
1128 Sql_condition_iterator sql_conditions() const
1129 { return get_warning_info()->m_warn_list; }
1130
1131 void reserve_space(THD *thd, uint count)
1132 { get_warning_info()->reserve_space(thd, count); }
1133
1134 Sql_condition *push_warning(THD *thd, const Sql_condition *sql_condition)
1135 { return get_warning_info()->push_warning(thd, sql_condition); }
1136
1137 Sql_condition *push_warning(THD *thd,
1138 uint sql_errno_arg,
1139 const char* sqlstate,
1140 Sql_condition::enum_warning_level level,
1141 const Sql_user_condition_identity &ucid,
1142 const char* msg)
1143 {
1144 Sql_condition_identity tmp(sql_errno_arg, sqlstate, level, ucid);
1145 return get_warning_info()->push_warning(thd, &tmp, msg);
1146 }
1147
1148 Sql_condition *push_warning(THD *thd,
1149 uint sqlerrno,
1150 const char* sqlstate,
1151 Sql_condition::enum_warning_level level,
1152 const char* msg)
1153 {
1154 return push_warning(thd, sqlerrno, sqlstate, level,
1155 Sql_user_condition_identity(), msg);
1156 }
1157 void mark_sql_conditions_for_removal()
1158 { get_warning_info()->mark_sql_conditions_for_removal(); }
1159
1160 void unmark_sql_conditions_from_removal()
1161 { get_warning_info()->unmark_sql_conditions_from_removal(); }
1162
1163 void remove_marked_sql_conditions()
1164 { get_warning_info()->remove_marked_sql_conditions(); }
1165
1166 const Sql_condition *get_error_condition() const
1167 { return get_warning_info()->get_error_condition(); }
1168
1169 void copy_sql_conditions_to_wi(THD *thd, Warning_info *dst_wi) const
1170 { dst_wi->append_warning_info(thd, get_warning_info()); }
1171
1172 void copy_sql_conditions_from_wi(THD *thd, const Warning_info *src_wi)
1173 { get_warning_info()->append_warning_info(thd, src_wi); }
1174
1175 void copy_non_errors_from_wi(THD *thd, const Warning_info *src_wi);
1176
1177private:
1178 Warning_info *get_warning_info() { return m_wi_stack.front(); }
1179
1180 const Warning_info *get_warning_info() const { return m_wi_stack.front(); }
1181
1182private:
1183 /** True if status information is sent to the client. */
1184 bool m_is_sent;
1185
1186 /** Set to make set_error_status after set_{ok,eof}_status possible. */
1187 bool m_can_overwrite_status;
1188
1189 /** Skip flushing network buffer after writing OK (for COM_MULTI) */
1190 bool m_skip_flush;
1191
1192 /** Message buffer. Can be used by OK or ERROR status. */
1193 char m_message[MYSQL_ERRMSG_SIZE];
1194
1195 /**
1196 The number of rows affected by the last statement. This is
1197 semantically close to thd->m_row_count_func, but has a different
1198 life cycle. thd->m_row_count_func stores the value returned by
1199 function ROW_COUNT() and is cleared only by statements that
1200 update its value, such as INSERT, UPDATE, DELETE and few others.
1201 This member is cleared at the beginning of the next statement.
1202
1203 We could possibly merge the two, but life cycle of thd->m_row_count_func
1204 can not be changed.
1205 */
1206 ulonglong m_affected_rows;
1207
1208 /**
1209 Similarly to the previous member, this is a replacement of
1210 thd->first_successful_insert_id_in_prev_stmt, which is used
1211 to implement LAST_INSERT_ID().
1212 */
1213
1214 ulonglong m_last_insert_id;
1215 /**
1216 Number of warnings of this last statement. May differ from
1217 the number of warnings returned by SHOW WARNINGS e.g. in case
1218 the statement doesn't clear the warnings, and doesn't generate
1219 them.
1220 */
1221 uint m_statement_warn_count;
1222
1223 enum_diagnostics_status m_status;
1224
1225 my_bool is_bulk_execution;
1226
1227 Warning_info m_main_wi;
1228
1229 Warning_info_list m_wi_stack;
1230};
1231
1232///////////////////////////////////////////////////////////////////////////
1233
1234
1235void push_warning(THD *thd, Sql_condition::enum_warning_level level,
1236 uint code, const char *msg);
1237
1238void push_warning_printf(THD *thd, Sql_condition::enum_warning_level level,
1239 uint code, const char *format, ...);
1240
1241bool mysqld_show_warnings(THD *thd, ulong levels_to_show);
1242
1243size_t convert_error_message(char *to, size_t to_length,
1244 CHARSET_INFO *to_cs,
1245 const char *from, size_t from_length,
1246 CHARSET_INFO *from_cs, uint *errors);
1247
1248extern const LEX_CSTRING warning_level_names[];
1249
1250bool is_sqlstate_valid(const LEX_CSTRING *sqlstate);
1251/**
1252 Checks if the specified SQL-state-string defines COMPLETION condition.
1253 This function assumes that the given string contains a valid SQL-state.
1254
1255 @param s the condition SQLSTATE.
1256
1257 @retval true if the given string defines COMPLETION condition.
1258 @retval false otherwise.
1259*/
1260inline bool is_sqlstate_completion(const char *s)
1261{ return s[0] == '0' && s[1] == '0'; }
1262
1263
1264#endif // SQL_ERROR_H
1265