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