1
/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
18
#include "sp_pcontext.h"
19
#include "sp_rcontext.h"
20
#include "sql_signal.h"
23
The parser accepts any error code (desired)
24
The runtime internally supports any error code (desired)
25
The client server protocol is limited to 16 bits error codes (restriction)
26
Enforcing the 65535 limit in the runtime until the protocol can change.
28
#define MAX_MYSQL_ERRNO UINT_MAX16
30
const LEX_STRING Diag_condition_item_names[]=
32
{ C_STRING_WITH_LEN("CLASS_ORIGIN") },
33
{ C_STRING_WITH_LEN("SUBCLASS_ORIGIN") },
34
{ C_STRING_WITH_LEN("CONSTRAINT_CATALOG") },
35
{ C_STRING_WITH_LEN("CONSTRAINT_SCHEMA") },
36
{ C_STRING_WITH_LEN("CONSTRAINT_NAME") },
37
{ C_STRING_WITH_LEN("CATALOG_NAME") },
38
{ C_STRING_WITH_LEN("SCHEMA_NAME") },
39
{ C_STRING_WITH_LEN("TABLE_NAME") },
40
{ C_STRING_WITH_LEN("COLUMN_NAME") },
41
{ C_STRING_WITH_LEN("CURSOR_NAME") },
42
{ C_STRING_WITH_LEN("MESSAGE_TEXT") },
43
{ C_STRING_WITH_LEN("MYSQL_ERRNO") },
45
{ C_STRING_WITH_LEN("CONDITION_IDENTIFIER") },
46
{ C_STRING_WITH_LEN("CONDITION_NUMBER") },
47
{ C_STRING_WITH_LEN("CONNECTION_NAME") },
48
{ C_STRING_WITH_LEN("MESSAGE_LENGTH") },
49
{ C_STRING_WITH_LEN("MESSAGE_OCTET_LENGTH") },
50
{ C_STRING_WITH_LEN("PARAMETER_MODE") },
51
{ C_STRING_WITH_LEN("PARAMETER_NAME") },
52
{ C_STRING_WITH_LEN("PARAMETER_ORDINAL_POSITION") },
53
{ C_STRING_WITH_LEN("RETURNED_SQLSTATE") },
54
{ C_STRING_WITH_LEN("ROUTINE_CATALOG") },
55
{ C_STRING_WITH_LEN("ROUTINE_NAME") },
56
{ C_STRING_WITH_LEN("ROUTINE_SCHEMA") },
57
{ C_STRING_WITH_LEN("SERVER_NAME") },
58
{ C_STRING_WITH_LEN("SPECIFIC_NAME") },
59
{ C_STRING_WITH_LEN("TRIGGER_CATALOG") },
60
{ C_STRING_WITH_LEN("TRIGGER_NAME") },
61
{ C_STRING_WITH_LEN("TRIGGER_SCHEMA") }
64
const LEX_STRING Diag_statement_item_names[]=
66
{ C_STRING_WITH_LEN("NUMBER") },
67
{ C_STRING_WITH_LEN("MORE") },
68
{ C_STRING_WITH_LEN("COMMAND_FUNCTION") },
69
{ C_STRING_WITH_LEN("COMMAND_FUNCTION_CODE") },
70
{ C_STRING_WITH_LEN("DYNAMIC_FUNCTION") },
71
{ C_STRING_WITH_LEN("DYNAMIC_FUNCTION_CODE") },
72
{ C_STRING_WITH_LEN("ROW_COUNT") },
73
{ C_STRING_WITH_LEN("TRANSACTIONS_COMMITTED") },
74
{ C_STRING_WITH_LEN("TRANSACTIONS_ROLLED_BACK") },
75
{ C_STRING_WITH_LEN("TRANSACTION_ACTIVE") }
79
Set_signal_information::Set_signal_information(
80
const Set_signal_information& set)
82
memcpy(m_item, set.m_item, sizeof(m_item));
85
void Set_signal_information::clear()
87
memset(m_item, 0, sizeof(m_item));
90
void Signal_common::assign_defaults(MYSQL_ERROR *cond,
92
MYSQL_ERROR::enum_warning_level level,
98
cond->m_sql_errno= sqlcode;
100
if (! cond->get_message_text())
101
cond->set_builtin_message_text(ER(sqlcode));
104
void Signal_common::eval_defaults(THD *thd, MYSQL_ERROR *cond)
108
const char* sqlstate;
109
bool set_defaults= (m_cond != 0);
114
SIGNAL is restricted in sql_yacc.yy to only signal SQLSTATE conditions.
116
DBUG_ASSERT(m_cond->type == sp_cond_type::state);
117
sqlstate= m_cond->sqlstate;
118
cond->set_sqlstate(sqlstate);
121
sqlstate= cond->get_sqlstate();
123
DBUG_ASSERT(sqlstate);
124
/* SQLSTATE class "00": illegal, rejected in the parser. */
125
DBUG_ASSERT((sqlstate[0] != '0') || (sqlstate[1] != '0'));
127
if ((sqlstate[0] == '0') && (sqlstate[1] == '1'))
129
/* SQLSTATE class "01": warning. */
130
assign_defaults(cond, set_defaults,
131
MYSQL_ERROR::WARN_LEVEL_WARN, ER_SIGNAL_WARN);
133
else if ((sqlstate[0] == '0') && (sqlstate[1] == '2'))
135
/* SQLSTATE class "02": not found. */
136
assign_defaults(cond, set_defaults,
137
MYSQL_ERROR::WARN_LEVEL_ERROR, ER_SIGNAL_NOT_FOUND);
141
/* other SQLSTATE classes : error. */
142
assign_defaults(cond, set_defaults,
143
MYSQL_ERROR::WARN_LEVEL_ERROR, ER_SIGNAL_EXCEPTION);
147
static bool assign_fixed_string(MEM_ROOT *mem_root,
148
CHARSET_INFO *dst_cs,
155
CHARSET_INFO *src_cs;
168
dst->set((const char*) NULL, 0, dst_cs);
172
src_cs= src->charset();
173
src_len= src->length();
174
src_end= src_str + src_len;
175
numchars= src_cs->cset->numchars(src_cs, src_str, src_end);
177
if (numchars <= max_char)
179
to_copy= src->length();
185
to_copy= dst_cs->cset->charpos(dst_cs, src_str, src_end, numchars);
189
if (String::needs_conversion(to_copy, src_cs, dst_cs, & dummy_offset))
191
dst_len= numchars * dst_cs->mbmaxlen;
192
dst_str= (char*) alloc_root(mem_root, dst_len + 1);
195
const char* well_formed_error_pos;
196
const char* cannot_convert_error_pos;
197
const char* from_end_pos;
199
dst_copied= well_formed_copy_nchars(dst_cs, dst_str, dst_len,
200
src_cs, src_str, src_len,
202
& well_formed_error_pos,
203
& cannot_convert_error_pos,
205
DBUG_ASSERT(dst_copied <= dst_len);
206
dst_len= dst_copied; /* In case the copy truncated the data */
207
dst_str[dst_copied]= '\0';
213
dst_str= (char*) alloc_root(mem_root, dst_len + 1);
216
memcpy(dst_str, src_str, to_copy);
217
dst_str[to_copy]= '\0';
220
dst->set(dst_str, dst_len, dst_cs);
225
static int assign_condition_item(MEM_ROOT *mem_root, const char* name, THD *thd,
226
Item *set, String *ci)
228
char str_buff[(64+1)*4]; /* Room for a null terminated UTF8 String 64 */
229
String str_value(str_buff, sizeof(str_buff), & my_charset_utf8_bin);
233
DBUG_ENTER("assign_condition_item");
237
thd->raise_error_printf(ER_WRONG_VALUE_FOR_VAR, name, "NULL");
241
str= set->val_str(& str_value);
242
truncated= assign_fixed_string(mem_root, & my_charset_utf8_bin, 64, ci, str);
245
if (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES |
246
MODE_STRICT_ALL_TABLES))
248
thd->raise_error_printf(ER_COND_ITEM_TOO_LONG, name);
252
thd->raise_warning_printf(WARN_COND_ITEM_TRUNCATED, name);
259
int Signal_common::eval_signal_informations(THD *thd, MYSQL_ERROR *cond)
263
enum enum_diag_condition_item_name m_item;
264
String MYSQL_ERROR::*m_member;
267
static cond_item_map map[]=
269
{ DIAG_CLASS_ORIGIN, & MYSQL_ERROR::m_class_origin },
270
{ DIAG_SUBCLASS_ORIGIN, & MYSQL_ERROR::m_subclass_origin },
271
{ DIAG_CONSTRAINT_CATALOG, & MYSQL_ERROR::m_constraint_catalog },
272
{ DIAG_CONSTRAINT_SCHEMA, & MYSQL_ERROR::m_constraint_schema },
273
{ DIAG_CONSTRAINT_NAME, & MYSQL_ERROR::m_constraint_name },
274
{ DIAG_CATALOG_NAME, & MYSQL_ERROR::m_catalog_name },
275
{ DIAG_SCHEMA_NAME, & MYSQL_ERROR::m_schema_name },
276
{ DIAG_TABLE_NAME, & MYSQL_ERROR::m_table_name },
277
{ DIAG_COLUMN_NAME, & MYSQL_ERROR::m_column_name },
278
{ DIAG_CURSOR_NAME, & MYSQL_ERROR::m_cursor_name }
287
enum enum_diag_condition_item_name item_enum;
289
const LEX_STRING *name;
291
DBUG_ENTER("Signal_common::eval_signal_informations");
293
for (i= FIRST_DIAG_SET_PROPERTY;
294
i <= LAST_DIAG_SET_PROPERTY;
297
set= m_set_signal_information.m_item[i];
302
if (set->fix_fields(thd, & set))
304
m_set_signal_information.m_item[i]= set;
310
Generically assign all the UTF8 String 64 condition items
311
described in the map.
313
for (j= 0; j < array_elements(map); j++)
315
item_enum= map[j].m_item;
316
set= m_set_signal_information.m_item[item_enum];
319
member= & (cond->* map[j].m_member);
320
name= & Diag_condition_item_names[item_enum];
321
if (assign_condition_item(cond->m_mem_root, name->str, thd, set, member))
327
Assign the remaining attributes.
330
set= m_set_signal_information.m_item[DIAG_MESSAGE_TEXT];
335
thd->raise_error_printf(ER_WRONG_VALUE_FOR_VAR,
336
"MESSAGE_TEXT", "NULL");
340
Enforce that SET MESSAGE_TEXT = <value> evaluates the value
341
as VARCHAR(128) CHARACTER SET UTF8.
345
str= set->val_str(& str_value);
346
truncated= assign_fixed_string(thd->mem_root, & my_charset_utf8_bin, 128,
350
if (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES |
351
MODE_STRICT_ALL_TABLES))
353
thd->raise_error_printf(ER_COND_ITEM_TOO_LONG,
358
thd->raise_warning_printf(WARN_COND_ITEM_TRUNCATED,
364
"Design notes about MYSQL_ERROR::m_message_text."
367
String converted_text;
368
converted_text.set_charset(error_message_charset_info);
369
converted_text.append(utf8_text.ptr(), utf8_text.length(),
370
utf8_text.charset());
371
cond->set_builtin_message_text(converted_text.c_ptr_safe());
374
set= m_set_signal_information.m_item[DIAG_MYSQL_ERRNO];
379
thd->raise_error_printf(ER_WRONG_VALUE_FOR_VAR,
380
"MYSQL_ERRNO", "NULL");
383
longlong code= set->val_int();
384
if ((code <= 0) || (code > MAX_MYSQL_ERRNO))
386
str= set->val_str(& str_value);
387
thd->raise_error_printf(ER_WRONG_VALUE_FOR_VAR,
388
"MYSQL_ERRNO", str->c_ptr_safe());
391
cond->m_sql_errno= (int) code;
395
The various item->val_xxx() methods don't return an error code,
396
but flag thd in case of failure.
398
if (! thd->is_error())
402
for (i= FIRST_DIAG_SET_PROPERTY;
403
i <= LAST_DIAG_SET_PROPERTY;
406
set= m_set_signal_information.m_item[i];
417
bool Signal_common::raise_condition(THD *thd, MYSQL_ERROR *cond)
421
DBUG_ENTER("Signal_common::raise_condition");
423
DBUG_ASSERT(m_lex->query_tables == NULL);
425
eval_defaults(thd, cond);
426
if (eval_signal_informations(thd, cond))
429
/* SIGNAL should not signal WARN_LEVEL_NOTE */
430
DBUG_ASSERT((cond->m_level == MYSQL_ERROR::WARN_LEVEL_WARN) ||
431
(cond->m_level == MYSQL_ERROR::WARN_LEVEL_ERROR));
433
MYSQL_ERROR *raised= NULL;
434
raised= thd->raise_condition(cond->get_sql_errno(),
435
cond->get_sqlstate(),
437
cond->get_message_text());
439
raised->copy_opt_attributes(cond);
441
if (cond->m_level == MYSQL_ERROR::WARN_LEVEL_WARN)
450
bool Signal_statement::execute(THD *thd)
453
MYSQL_ERROR cond(thd->mem_root);
455
DBUG_ENTER("Signal_statement::execute");
458
WL#2110 SIGNAL specification says:
460
When SIGNAL is executed, it has five effects, in the following order:
462
(1) First, the diagnostics area is completely cleared. So if the
463
SIGNAL is in a DECLARE HANDLER then any pending errors or warnings
464
are gone. So is 'row count'.
466
This has roots in the SQL standard specification for SIGNAL.
469
thd->stmt_da->reset_diagnostics_area();
470
thd->set_row_count_func(0);
471
thd->warning_info->clear_warning_info(thd->query_id);
473
result= raise_condition(thd, &cond);
479
bool Resignal_statement::execute(THD *thd)
481
MYSQL_ERROR *signaled;
484
DBUG_ENTER("Resignal_statement::execute");
486
thd->warning_info->m_warn_id= thd->query_id;
488
if (! thd->spcont || ! (signaled= thd->spcont->raised_condition()))
490
thd->raise_error(ER_RESIGNAL_WITHOUT_ACTIVE_HANDLER);
496
/* RESIGNAL without signal_value */
497
result= raise_condition(thd, signaled);
501
/* RESIGNAL with signal_value */
502
result= raise_condition(thd, signaled);