summaryrefslogtreecommitdiff
path: root/sql/sql_error.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_error.cc')
-rw-r--r--sql/sql_error.cc143
1 files changed, 72 insertions, 71 deletions
diff --git a/sql/sql_error.cc b/sql/sql_error.cc
index a11a0f454a2..80cdc0bc734 100644
--- a/sql/sql_error.cc
+++ b/sql/sql_error.cc
@@ -372,7 +372,7 @@ Diagnostics_area::set_eof_status(THD *thd)
{
DBUG_ENTER("set_eof_status");
/* Only allowed to report eof if has not yet reported an error */
- DBUG_ASSERT(! is_set());
+ DBUG_ASSERT(!is_set() || (m_status == DA_EOF_BULK && is_bulk_op()));
/*
In production, refuse to overwrite an error or a custom response
with an EOF packet.
@@ -385,11 +385,23 @@ Diagnostics_area::set_eof_status(THD *thd)
number of warnings, since they are not available to the client
anyway.
*/
- m_statement_warn_count= (thd->spcont ?
- 0 :
- current_statement_warn_count());
+ if (m_status == DA_EOF_BULK)
+ {
+ if (!thd->spcont)
+ m_statement_warn_count+= current_statement_warn_count();
+ }
+ else
+ {
+ if (thd->spcont)
+ {
+ m_statement_warn_count= 0;
+ m_affected_rows= 0;
+ }
+ else
+ m_statement_warn_count= current_statement_warn_count();
+ m_status= (is_bulk_op() ? DA_EOF_BULK : DA_EOF);
+ }
- m_status= DA_EOF;
DBUG_VOID_RETURN;
}
@@ -506,7 +518,7 @@ void Warning_info::init()
{
/* Initialize sub structures */
DBUG_ASSERT(initialized == 0);
- init_sql_alloc(&m_warn_root, "Warning_info", WARN_ALLOC_BLOCK_SIZE,
+ init_sql_alloc(PSI_INSTRUMENT_ME, &m_warn_root, WARN_ALLOC_BLOCK_SIZE,
WARN_ALLOC_PREALLOC_SIZE, MYF(MY_THREAD_SPECIFIC));
initialized= 1;
}
@@ -744,7 +756,7 @@ void push_warning_printf(THD *thd, Sql_condition::enum_warning_level level,
DBUG_ASSERT(format != NULL);
va_start(args,format);
- my_vsnprintf_ex(&my_charset_utf8_general_ci, warning,
+ my_vsnprintf_ex(&my_charset_utf8mb3_general_ci, warning,
sizeof(warning), format, args);
va_end(args);
push_warning(thd, level, code, warning);
@@ -783,7 +795,7 @@ bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
const Sql_condition *err;
SELECT_LEX *sel= thd->lex->first_select_lex();
SELECT_LEX_UNIT *unit= &thd->lex->unit;
- ulonglong idx= 0;
+ ha_rows idx;
Protocol *protocol=thd->protocol;
DBUG_ENTER("mysqld_show_warnings");
@@ -808,23 +820,22 @@ bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
Diagnostics_area::Sql_condition_iterator it=
thd->get_stmt_da()->sql_conditions();
- while ((err= it++))
+ for (idx= 0; (err= it++) ; idx++)
{
/* Skip levels that the user is not interested in */
if (!(levels_to_show & ((ulong) 1 << err->get_level())))
continue;
- if (++idx <= unit->offset_limit_cnt)
- continue;
- if (idx > unit->select_limit_cnt)
+ if (unit->lim.check_offset(idx))
+ continue; // using limit offset,count
+ if (idx >= unit->lim.get_select_limit())
break;
protocol->prepare_for_resend();
protocol->store(warning_level_names[err->get_level()].str,
warning_level_names[err->get_level()].length,
system_charset_info);
protocol->store((uint32) err->get_sql_errno());
- protocol->store(err->get_message_text(),
- err->get_message_octet_length(),
- system_charset_info);
+ protocol->store_warning(err->get_message_text(),
+ err->get_message_octet_length());
if (protocol->write())
DBUG_RETURN(TRUE);
}
@@ -837,6 +848,26 @@ bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
/**
+ This replaces U+0000 to '\0000', so the result error message string:
+ - is a good null-terminated string
+ - presents the entire data
+ For example:
+ SELECT CAST(_latin1 0x610062 AS SIGNED);
+ returns a warning:
+ Truncated incorrect INTEGER value: 'a\0000b'
+ Notice, the 0x00 byte is replaced to a 5-byte long string '\0000',
+ while 'a' and 'b' are printed as is.
+*/
+extern "C" int my_wc_mb_utf8_null_terminated(CHARSET_INFO *cs,
+ my_wc_t wc, uchar *r, uchar *e)
+{
+ return wc == '\0' ?
+ cs->wc_to_printable(wc, r, e) :
+ my_charset_utf8mb3_handler.wc_mb(cs, wc, r, e);
+}
+
+
+/**
Convert value for dispatch to error message(see WL#751).
@param to buffer for converted string
@@ -894,8 +925,11 @@ char *err_conv(char *buff, uint to_length, const char *from,
else
{
uint errors;
- res= copy_and_convert(to, to_length, system_charset_info,
- from, from_length, from_cs, &errors);
+ res= my_convert_using_func(to, to_length, system_charset_info,
+ my_wc_mb_utf8_null_terminated,
+ from, from_length, from_cs,
+ from_cs->cset->mb_wc,
+ &errors);
to[res]= 0;
}
return buff;
@@ -921,64 +955,21 @@ size_t convert_error_message(char *to, size_t to_length, CHARSET_INFO *to_cs,
const char *from, size_t from_length,
CHARSET_INFO *from_cs, uint *errors)
{
- int cnvres;
- my_wc_t wc;
- const uchar *from_end= (const uchar*) from+from_length;
- char *to_start= to;
- uchar *to_end;
- my_charset_conv_mb_wc mb_wc= from_cs->cset->mb_wc;
- my_charset_conv_wc_mb wc_mb;
- uint error_count= 0;
- size_t length;
-
DBUG_ASSERT(to_length > 0);
/* Make room for the null terminator. */
to_length--;
- to_end= (uchar*) (to + to_length);
-
- if (!to_cs || from_cs == to_cs || to_cs == &my_charset_bin)
- {
- length= MY_MIN(to_length, from_length);
- memmove(to, from, length);
- to[length]= 0;
- return length;
- }
- wc_mb= to_cs->cset->wc_mb;
- while (1)
- {
- if ((cnvres= (*mb_wc)(from_cs, &wc, (uchar*) from, from_end)) > 0)
- {
- if (!wc)
- break;
- from+= cnvres;
- }
- else if (cnvres == MY_CS_ILSEQ)
- {
- wc= (ulong) (uchar) *from;
- from+=1;
- }
- else
- break;
-
- if ((cnvres= (*wc_mb)(to_cs, wc, (uchar*) to, to_end)) > 0)
- to+= cnvres;
- else if (cnvres == MY_CS_ILUNI)
- {
- length= (wc <= 0xFFFF) ? 6/* '\1234' format*/ : 9 /* '\+123456' format*/;
- if ((uchar*)(to + length) >= to_end)
- break;
- cnvres= (int)my_snprintf(to, 9,
- (wc <= 0xFFFF) ? "\\%04X" : "\\+%06X", (uint) wc);
- to+= cnvres;
- }
- else
- break;
- }
-
- *to= 0;
- *errors= error_count;
- return (size_t) (to - to_start);
+ if (!to_cs || to_cs == &my_charset_bin)
+ to_cs= system_charset_info;
+ uint32 cnv_length= my_convert_using_func(to, to_length,
+ to_cs,
+ to_cs->cset->wc_to_printable,
+ from, from_length,
+ from_cs, from_cs->cset->mb_wc,
+ errors);
+ DBUG_ASSERT(to_length >= cnv_length);
+ to[cnv_length]= '\0';
+ return cnv_length;
}
@@ -1009,3 +1000,13 @@ bool is_sqlstate_valid(const LEX_CSTRING *sqlstate)
return true;
}
+
+
+void convert_error_to_warning(THD *thd)
+{
+ DBUG_ASSERT(thd->is_error());
+ push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
+ thd->get_stmt_da()->sql_errno(),
+ thd->get_stmt_da()->message());
+ thd->clear_error();
+}