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 ErrBuff
818 {
819 protected:
820 mutable char err_buffer[MYSQL_ERRMSG_SIZE];
821 public:
ErrBuff()822 ErrBuff()
823 {
824 err_buffer[0]= '\0';
825 }
ptr()826 const char *ptr() const { return err_buffer; }
set_longlong(const Longlong_hybrid & nr)827 const char *set_longlong(const Longlong_hybrid &nr) const
828 {
829 return nr.is_unsigned() ? ullstr(nr.value(), err_buffer) :
830 llstr(nr.value(), err_buffer);
831 }
set_double(double nr)832 const char *set_double(double nr) const
833 {
834 my_gcvt(nr, MY_GCVT_ARG_DOUBLE, sizeof(err_buffer), err_buffer, 0);
835 return err_buffer;
836 }
set_decimal(const decimal_t * d)837 const char *set_decimal(const decimal_t *d) const
838 {
839 int len= sizeof(err_buffer);
840 decimal2string(d, err_buffer, &len, 0, 0, ' ');
841 return err_buffer;
842 }
set_str(const char * str,size_t len,CHARSET_INFO * cs)843 const char *set_str(const char *str, size_t len, CHARSET_INFO *cs) const
844 {
845 DBUG_ASSERT(len < UINT_MAX32);
846 return err_conv(err_buffer, (uint) sizeof(err_buffer), str, (uint) len, cs);
847 }
set_mysql_time(const MYSQL_TIME * ltime)848 const char *set_mysql_time(const MYSQL_TIME *ltime) const
849 {
850 my_TIME_to_str(ltime, err_buffer, AUTO_SEC_PART_DIGITS);
851 return err_buffer;
852 }
853 };
854
855
856 class ErrConv: public ErrBuff
857 {
858 public:
ErrConv()859 ErrConv() {}
~ErrConv()860 virtual ~ErrConv() {}
861 virtual const char *ptr() const = 0;
862 };
863
864 class ErrConvString : public ErrConv
865 {
866 const char *str;
867 size_t len;
868 CHARSET_INFO *cs;
869 public:
ErrConvString(const char * str_arg,size_t len_arg,CHARSET_INFO * cs_arg)870 ErrConvString(const char *str_arg, size_t len_arg, CHARSET_INFO *cs_arg)
871 : ErrConv(), str(str_arg), len(len_arg), cs(cs_arg) {}
ErrConvString(const char * str_arg,CHARSET_INFO * cs_arg)872 ErrConvString(const char *str_arg, CHARSET_INFO *cs_arg)
873 : ErrConv(), str(str_arg), len(strlen(str_arg)), cs(cs_arg) {}
ErrConvString(const String * s)874 ErrConvString(const String *s)
875 : ErrConv(), str(s->ptr()), len(s->length()), cs(s->charset()) {}
ptr()876 const char *ptr() const
877 {
878 return set_str(str, len, cs);
879 }
880 };
881
882 class ErrConvInteger : public ErrConv, public Longlong_hybrid
883 {
884 public:
ErrConvInteger(const Longlong_hybrid & nr)885 ErrConvInteger(const Longlong_hybrid &nr)
886 : ErrConv(), Longlong_hybrid(nr) { }
ptr()887 const char *ptr() const
888 {
889 return set_longlong(static_cast<Longlong_hybrid>(*this));
890 }
891 };
892
893 class ErrConvDouble: public ErrConv
894 {
895 double num;
896 public:
ErrConvDouble(double num_arg)897 ErrConvDouble(double num_arg) : ErrConv(), num(num_arg) {}
ptr()898 const char *ptr() const
899 {
900 return set_double(num);
901 }
902 };
903
904 class ErrConvTime : public ErrConv
905 {
906 const MYSQL_TIME *ltime;
907 public:
ErrConvTime(const MYSQL_TIME * ltime_arg)908 ErrConvTime(const MYSQL_TIME *ltime_arg) : ErrConv(), ltime(ltime_arg) {}
ptr()909 const char *ptr() const
910 {
911 return set_mysql_time(ltime);
912 }
913 };
914
915 class ErrConvDecimal : public ErrConv
916 {
917 const decimal_t *d;
918 public:
ErrConvDecimal(const decimal_t * d_arg)919 ErrConvDecimal(const decimal_t *d_arg) : ErrConv(), d(d_arg) {}
ptr()920 const char *ptr() const
921 {
922 return set_decimal(d);
923 }
924 };
925
926 ///////////////////////////////////////////////////////////////////////////
927
928 /**
929 Stores status of the currently executed statement.
930 Cleared at the beginning of the statement, and then
931 can hold either OK, ERROR, or EOF status.
932 Can not be assigned twice per statement.
933 */
934
935 class Diagnostics_area: public Sql_state_errno,
936 public Sql_user_condition_identity
937 {
938 private:
939 /** The type of the counted and doubly linked list of conditions. */
940 typedef I_P_List<Warning_info,
941 I_P_List_adapter<Warning_info,
942 &Warning_info::m_next_in_da,
943 &Warning_info::m_prev_in_da>,
944 I_P_List_counter,
945 I_P_List_fast_push_back<Warning_info> >
946 Warning_info_list;
947
948 public:
949 /** Const iterator used to iterate through the warning list. */
950 typedef Warning_info::Sql_condition_list::Const_Iterator
951 Sql_condition_iterator;
952
953 enum enum_diagnostics_status
954 {
955 /** The area is cleared at start of a statement. */
956 DA_EMPTY= 0,
957 /** Set whenever one calls my_ok(). */
958 DA_OK,
959 /** Set whenever one calls my_eof(). */
960 DA_EOF,
961 /** Set whenever one calls my_ok() in PS bulk mode. */
962 DA_OK_BULK,
963 /** Set whenever one calls my_error() or my_message(). */
964 DA_ERROR,
965 /** Set in case of a custom response, such as one from COM_STMT_PREPARE. */
966 DA_DISABLED
967 };
968
set_overwrite_status(bool can_overwrite_status)969 void set_overwrite_status(bool can_overwrite_status)
970 { m_can_overwrite_status= can_overwrite_status; }
971
972 /** True if status information is sent to the client. */
is_sent()973 bool is_sent() const { return m_is_sent; }
974
set_is_sent(bool is_sent_arg)975 void set_is_sent(bool is_sent_arg) { m_is_sent= is_sent_arg; }
976
977 void set_ok_status(ulonglong affected_rows,
978 ulonglong last_insert_id,
979 const char *message);
980
981 void set_eof_status(THD *thd);
982
983 void set_error_status(uint sql_errno);
984
985 void set_error_status(uint sql_errno,
986 const char *message,
987 const char *sqlstate,
988 const Sql_user_condition_identity &ucid,
989 const Sql_condition *error_condition);
990
set_error_status(uint sql_errno,const char * message,const char * sqlstate,const Sql_condition * error_condition)991 void set_error_status(uint sql_errno,
992 const char *message,
993 const char *sqlstate,
994 const Sql_condition *error_condition)
995 {
996 set_error_status(sql_errno, message, sqlstate,
997 Sql_user_condition_identity(),
998 error_condition);
999 }
1000
1001 void disable_status();
1002
1003 void reset_diagnostics_area();
1004
is_set()1005 bool is_set() const { return m_status != DA_EMPTY; }
1006
is_error()1007 bool is_error() const { return m_status == DA_ERROR; }
1008
is_eof()1009 bool is_eof() const { return m_status == DA_EOF; }
1010
is_ok()1011 bool is_ok() const { return m_status == DA_OK; }
1012
is_disabled()1013 bool is_disabled() const { return m_status == DA_DISABLED; }
1014
set_bulk_execution(bool bulk)1015 void set_bulk_execution(bool bulk) { is_bulk_execution= bulk; }
1016
is_bulk_op()1017 bool is_bulk_op() const { return is_bulk_execution; }
1018
status()1019 enum_diagnostics_status status() const { return m_status; }
1020
message()1021 const char *message() const
1022 { DBUG_ASSERT(m_status == DA_ERROR || m_status == DA_OK ||
1023 m_status == DA_OK_BULK); return m_message; }
1024
skip_flush()1025 bool skip_flush() const
1026 {
1027 DBUG_ASSERT(m_status == DA_OK || m_status == DA_OK_BULK);
1028 return m_skip_flush;
1029 }
1030
set_skip_flush()1031 void set_skip_flush()
1032 { m_skip_flush= TRUE; }
1033
sql_errno()1034 uint sql_errno() const
1035 {
1036 DBUG_ASSERT(m_status == DA_ERROR);
1037 return Sql_state_errno::get_sql_errno();
1038 }
1039
get_sqlstate()1040 const char* get_sqlstate() const
1041 { DBUG_ASSERT(m_status == DA_ERROR); return Sql_state::get_sqlstate(); }
1042
affected_rows()1043 ulonglong affected_rows() const
1044 {
1045 DBUG_ASSERT(m_status == DA_OK || m_status == DA_OK_BULK);
1046 return m_affected_rows;
1047 }
1048
last_insert_id()1049 ulonglong last_insert_id() const
1050 {
1051 DBUG_ASSERT(m_status == DA_OK || m_status == DA_OK_BULK);
1052 return m_last_insert_id;
1053 }
1054
statement_warn_count()1055 uint statement_warn_count() const
1056 {
1057 DBUG_ASSERT(m_status == DA_OK || m_status == DA_OK_BULK ||
1058 m_status == DA_EOF);
1059 return m_statement_warn_count;
1060 }
1061
1062 /**
1063 Get the current errno, state and id of the user defined condition
1064 and return them as Sql_condition_identity.
1065 */
get_error_condition_identity()1066 Sql_condition_identity get_error_condition_identity() const
1067 {
1068 DBUG_ASSERT(m_status == DA_ERROR);
1069 return Sql_condition_identity(*this /*Sql_state_errno*/,
1070 Sql_condition::WARN_LEVEL_ERROR,
1071 *this /*Sql_user_condition_identity*/);
1072 }
1073
1074 /* Used to count any warnings pushed after calling set_ok_status(). */
increment_warning()1075 void increment_warning()
1076 {
1077 if (m_status != DA_EMPTY)
1078 m_statement_warn_count++;
1079 }
1080
1081 Diagnostics_area(bool initialize);
1082 Diagnostics_area(ulonglong warning_info_id, bool allow_unlimited_warnings,
1083 bool initialize);
init()1084 void init() { m_main_wi.init() ; }
free_memory()1085 void free_memory() { m_main_wi.free_memory() ; }
1086
push_warning_info(Warning_info * wi)1087 void push_warning_info(Warning_info *wi)
1088 { m_wi_stack.push_front(wi); }
1089
pop_warning_info()1090 void pop_warning_info()
1091 {
1092 DBUG_ASSERT(m_wi_stack.elements() > 0);
1093 m_wi_stack.remove(m_wi_stack.front());
1094 }
1095
set_warning_info_id(ulonglong id)1096 void set_warning_info_id(ulonglong id)
1097 { get_warning_info()->id(id); }
1098
warning_info_id()1099 ulonglong warning_info_id() const
1100 { return get_warning_info()->id(); }
1101
1102 /**
1103 Compare given current warning info and current warning info
1104 and see if they are different. They will be different if
1105 warnings have been generated or statements that use tables
1106 have been executed. This is checked by comparing m_warn_id.
1107
1108 @param wi Warning info to compare with current Warning info.
1109
1110 @return false if they are equal, true if they are not.
1111 */
warning_info_changed(const Warning_info * wi)1112 bool warning_info_changed(const Warning_info *wi) const
1113 { return get_warning_info()->id() != wi->id(); }
1114
is_warning_info_empty()1115 bool is_warning_info_empty() const
1116 { return get_warning_info()->is_empty(); }
1117
current_statement_warn_count()1118 ulong current_statement_warn_count() const
1119 { return get_warning_info()->current_statement_warn_count(); }
1120
has_sql_condition(const char * message_str,size_t message_length)1121 bool has_sql_condition(const char *message_str, size_t message_length) const
1122 { return get_warning_info()->has_sql_condition(message_str, message_length); }
1123
reset_for_next_command()1124 void reset_for_next_command()
1125 { get_warning_info()->reset_for_next_command(); }
1126
clear_warning_info(ulonglong id)1127 void clear_warning_info(ulonglong id)
1128 { get_warning_info()->clear(id); }
1129
opt_clear_warning_info(ulonglong query_id)1130 void opt_clear_warning_info(ulonglong query_id)
1131 { get_warning_info()->opt_clear(query_id); }
1132
current_row_for_warning()1133 ulong current_row_for_warning() const
1134 { return get_warning_info()->current_row_for_warning(); }
1135
inc_current_row_for_warning()1136 void inc_current_row_for_warning()
1137 { get_warning_info()->inc_current_row_for_warning(); }
1138
reset_current_row_for_warning()1139 void reset_current_row_for_warning()
1140 { get_warning_info()->reset_current_row_for_warning(); }
1141
is_warning_info_read_only()1142 bool is_warning_info_read_only() const
1143 { return get_warning_info()->is_read_only(); }
1144
set_warning_info_read_only(bool read_only_arg)1145 void set_warning_info_read_only(bool read_only_arg)
1146 { get_warning_info()->set_read_only(read_only_arg); }
1147
error_count()1148 ulong error_count() const
1149 { return get_warning_info()->error_count(); }
1150
warn_count()1151 ulong warn_count() const
1152 { return get_warning_info()->warn_count(); }
1153
cond_count()1154 uint cond_count() const
1155 { return get_warning_info()->cond_count(); }
1156
sql_conditions()1157 Sql_condition_iterator sql_conditions() const
1158 { return get_warning_info()->m_warn_list; }
1159
reserve_space(THD * thd,uint count)1160 void reserve_space(THD *thd, uint count)
1161 { get_warning_info()->reserve_space(thd, count); }
1162
push_warning(THD * thd,const Sql_condition * sql_condition)1163 Sql_condition *push_warning(THD *thd, const Sql_condition *sql_condition)
1164 { return get_warning_info()->push_warning(thd, sql_condition); }
1165
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)1166 Sql_condition *push_warning(THD *thd,
1167 uint sql_errno_arg,
1168 const char* sqlstate,
1169 Sql_condition::enum_warning_level level,
1170 const Sql_user_condition_identity &ucid,
1171 const char* msg)
1172 {
1173 Sql_condition_identity tmp(sql_errno_arg, sqlstate, level, ucid);
1174 return get_warning_info()->push_warning(thd, &tmp, msg);
1175 }
1176
push_warning(THD * thd,uint sqlerrno,const char * sqlstate,Sql_condition::enum_warning_level level,const char * msg)1177 Sql_condition *push_warning(THD *thd,
1178 uint sqlerrno,
1179 const char* sqlstate,
1180 Sql_condition::enum_warning_level level,
1181 const char* msg)
1182 {
1183 return push_warning(thd, sqlerrno, sqlstate, level,
1184 Sql_user_condition_identity(), msg);
1185 }
mark_sql_conditions_for_removal()1186 void mark_sql_conditions_for_removal()
1187 { get_warning_info()->mark_sql_conditions_for_removal(); }
1188
unmark_sql_conditions_from_removal()1189 void unmark_sql_conditions_from_removal()
1190 { get_warning_info()->unmark_sql_conditions_from_removal(); }
1191
remove_marked_sql_conditions()1192 void remove_marked_sql_conditions()
1193 { get_warning_info()->remove_marked_sql_conditions(); }
1194
get_error_condition()1195 const Sql_condition *get_error_condition() const
1196 { return get_warning_info()->get_error_condition(); }
1197
copy_sql_conditions_to_wi(THD * thd,Warning_info * dst_wi)1198 void copy_sql_conditions_to_wi(THD *thd, Warning_info *dst_wi) const
1199 { dst_wi->append_warning_info(thd, get_warning_info()); }
1200
copy_sql_conditions_from_wi(THD * thd,const Warning_info * src_wi)1201 void copy_sql_conditions_from_wi(THD *thd, const Warning_info *src_wi)
1202 { get_warning_info()->append_warning_info(thd, src_wi); }
1203
1204 void copy_non_errors_from_wi(THD *thd, const Warning_info *src_wi);
1205
1206 private:
get_warning_info()1207 Warning_info *get_warning_info() { return m_wi_stack.front(); }
1208
get_warning_info()1209 const Warning_info *get_warning_info() const { return m_wi_stack.front(); }
1210
1211 private:
1212 /** True if status information is sent to the client. */
1213 bool m_is_sent;
1214
1215 /** Set to make set_error_status after set_{ok,eof}_status possible. */
1216 bool m_can_overwrite_status;
1217
1218 /** Skip flushing network buffer after writing OK (for COM_MULTI) */
1219 bool m_skip_flush;
1220
1221 /** Message buffer. Can be used by OK or ERROR status. */
1222 char m_message[MYSQL_ERRMSG_SIZE];
1223
1224 /**
1225 The number of rows affected by the last statement. This is
1226 semantically close to thd->m_row_count_func, but has a different
1227 life cycle. thd->m_row_count_func stores the value returned by
1228 function ROW_COUNT() and is cleared only by statements that
1229 update its value, such as INSERT, UPDATE, DELETE and few others.
1230 This member is cleared at the beginning of the next statement.
1231
1232 We could possibly merge the two, but life cycle of thd->m_row_count_func
1233 can not be changed.
1234 */
1235 ulonglong m_affected_rows;
1236
1237 /**
1238 Similarly to the previous member, this is a replacement of
1239 thd->first_successful_insert_id_in_prev_stmt, which is used
1240 to implement LAST_INSERT_ID().
1241 */
1242
1243 ulonglong m_last_insert_id;
1244 /**
1245 Number of warnings of this last statement. May differ from
1246 the number of warnings returned by SHOW WARNINGS e.g. in case
1247 the statement doesn't clear the warnings, and doesn't generate
1248 them.
1249 */
1250 uint m_statement_warn_count;
1251
1252 enum_diagnostics_status m_status;
1253
1254 my_bool is_bulk_execution;
1255
1256 Warning_info m_main_wi;
1257
1258 Warning_info_list m_wi_stack;
1259 };
1260
1261 ///////////////////////////////////////////////////////////////////////////
1262
1263
1264 void push_warning(THD *thd, Sql_condition::enum_warning_level level,
1265 uint code, const char *msg);
1266
1267 void push_warning_printf(THD *thd, Sql_condition::enum_warning_level level,
1268 uint code, const char *format, ...);
1269
1270 bool mysqld_show_warnings(THD *thd, ulong levels_to_show);
1271
1272 size_t convert_error_message(char *to, size_t to_length,
1273 CHARSET_INFO *to_cs,
1274 const char *from, size_t from_length,
1275 CHARSET_INFO *from_cs, uint *errors);
1276
1277 extern const LEX_CSTRING warning_level_names[];
1278
1279 bool is_sqlstate_valid(const LEX_CSTRING *sqlstate);
1280 /**
1281 Checks if the specified SQL-state-string defines COMPLETION condition.
1282 This function assumes that the given string contains a valid SQL-state.
1283
1284 @param s the condition SQLSTATE.
1285
1286 @retval true if the given string defines COMPLETION condition.
1287 @retval false otherwise.
1288 */
is_sqlstate_completion(const char * s)1289 inline bool is_sqlstate_completion(const char *s)
1290 { return s[0] == '0' && s[1] == '0'; }
1291
1292
1293 #endif // SQL_ERROR_H
1294