Bug#23924 general_log truncates queries with character set introducers.
Problem: logging of utf8-incompatible binary strings didn't work Fix: hex-encoding of incompatible sequences.
This commit is contained in:
parent
ef9579619d
commit
f83cc8e6db
@ -107,6 +107,17 @@ Database Table In_use Name_locked
|
||||
SET GLOBAL GENERAL_LOG=ON;
|
||||
SET GLOBAL SLOW_QUERY_LOG=ON;
|
||||
truncate table mysql.general_log;
|
||||
set names binary;
|
||||
select _koi8r'ÔÅÓÔ' as test;
|
||||
test
|
||||
ÔÅÓÔ
|
||||
select * from mysql.general_log;
|
||||
event_time user_host thread_id server_id command_type argument
|
||||
TIMESTAMP USER_HOST THREAD_ID 1 Query set names binary
|
||||
TIMESTAMP USER_HOST THREAD_ID 1 Query select _koi8r'\xD4\xC5\xD3\xD4' as test
|
||||
TIMESTAMP USER_HOST THREAD_ID 1 Query select * from mysql.general_log
|
||||
set names utf8;
|
||||
truncate table mysql.general_log;
|
||||
set names utf8;
|
||||
create table bug16905 (s char(15) character set utf8 default 'пусто');
|
||||
insert into bug16905 values ('новое');
|
||||
|
@ -130,6 +130,16 @@ show open tables;
|
||||
SET GLOBAL GENERAL_LOG=ON;
|
||||
SET GLOBAL SLOW_QUERY_LOG=ON;
|
||||
|
||||
#
|
||||
# Bug#23924 general_log truncates queries with character set introducers.
|
||||
#
|
||||
truncate table mysql.general_log;
|
||||
set names binary;
|
||||
select _koi8r'ÔÅÓÔ' as test;
|
||||
--replace_column 1 TIMESTAMP 2 USER_HOST 3 THREAD_ID
|
||||
select * from mysql.general_log;
|
||||
set names utf8;
|
||||
|
||||
#
|
||||
# Bug #16905 Log tables: unicode statements are logged incorrectly
|
||||
#
|
||||
|
11
sql/field.cc
11
sql/field.cc
@ -7644,6 +7644,17 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
|
||||
if (value.alloc(new_length))
|
||||
goto oom_error;
|
||||
|
||||
|
||||
if (f_is_hex_escape(flags))
|
||||
{
|
||||
copy_length= my_copy_with_hex_escaping(field_charset,
|
||||
(char*) value.ptr(), new_length,
|
||||
from, length);
|
||||
Field_blob::store_length(copy_length);
|
||||
tmp= value.ptr();
|
||||
bmove(ptr + packlength, (uchar*) &tmp, sizeof(char*));
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
"length" is OK as "nchars" argument to well_formed_copy_nchars as this
|
||||
is never used to limit the length of the data. The cut of long data
|
||||
|
@ -2069,6 +2069,7 @@ int set_field_to_null_with_conversions(Field *field, bool no_conversions);
|
||||
#define FIELDFLAG_NO_DEFAULT 16384 /* sql */
|
||||
#define FIELDFLAG_SUM ((uint) 32768)// predit: +#fieldflag
|
||||
#define FIELDFLAG_MAYBE_NULL ((uint) 32768)// sql
|
||||
#define FIELDFLAG_HEX_ESCAPE ((uint) 0x10000)
|
||||
#define FIELDFLAG_PACK_SHIFT 3
|
||||
#define FIELDFLAG_DEC_SHIFT 8
|
||||
#define FIELDFLAG_MAX_DEC 31
|
||||
@ -2094,3 +2095,4 @@ int set_field_to_null_with_conversions(Field *field, bool no_conversions);
|
||||
#define f_maybe_null(x) (x & FIELDFLAG_MAYBE_NULL)
|
||||
#define f_no_default(x) (x & FIELDFLAG_NO_DEFAULT)
|
||||
#define f_bit_as_char(x) ((x) & FIELDFLAG_TREAT_BIT_AS_CHAR)
|
||||
#define f_is_hex_escape(x) ((x) & FIELDFLAG_HEX_ESCAPE)
|
||||
|
@ -418,6 +418,7 @@ bool Log_to_csv_event_handler::
|
||||
A positive return value in store() means truncation.
|
||||
Still logging a message in the log in this case.
|
||||
*/
|
||||
table->field[5]->flags|= FIELDFLAG_HEX_ESCAPE;
|
||||
if (table->field[5]->store(sql_text, sql_text_len, client_cs) < 0)
|
||||
goto err;
|
||||
|
||||
|
@ -840,6 +840,68 @@ outp:
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Copy string with HEX-encoding of "bad" characters.
|
||||
|
||||
@details This functions copies the string pointed by "src"
|
||||
to the string pointed by "dst". Not more than "srclen" bytes
|
||||
are read from "src". Any sequences of bytes representing
|
||||
a not-well-formed substring (according to cs) are hex-encoded,
|
||||
and all well-formed substrings (according to cs) are copied as is.
|
||||
Not more than "dstlen" bytes are written to "dst". The number
|
||||
of bytes written to "dst" is returned.
|
||||
|
||||
@param cs character set pointer of the destination string
|
||||
@param[out] dst destination string
|
||||
@param dstlen size of dst
|
||||
@param src source string
|
||||
@param srclen length of src
|
||||
|
||||
@retval result length
|
||||
*/
|
||||
|
||||
size_t
|
||||
my_copy_with_hex_escaping(CHARSET_INFO *cs,
|
||||
char *dst, size_t dstlen,
|
||||
const char *src, size_t srclen)
|
||||
{
|
||||
const char *srcend= src + srclen;
|
||||
char *dst0= dst;
|
||||
|
||||
for ( ; src < srcend ; )
|
||||
{
|
||||
size_t chlen;
|
||||
if ((chlen= my_ismbchar(cs, src, srcend)))
|
||||
{
|
||||
if (dstlen < chlen)
|
||||
break; /* purecov: inspected */
|
||||
memcpy(dst, src, chlen);
|
||||
src+= chlen;
|
||||
dst+= chlen;
|
||||
dstlen-= chlen;
|
||||
}
|
||||
else if (*src & 0x80)
|
||||
{
|
||||
if (dstlen < 4)
|
||||
break; /* purecov: inspected */
|
||||
*dst++= '\\';
|
||||
*dst++= 'x';
|
||||
*dst++= _dig_vec_upper[((unsigned char) *src) >> 4];
|
||||
*dst++= _dig_vec_upper[((unsigned char) *src) & 15];
|
||||
src++;
|
||||
dstlen-= 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dstlen < 1)
|
||||
break; /* purecov: inspected */
|
||||
*dst++= *src++;
|
||||
dstlen--;
|
||||
}
|
||||
}
|
||||
return dst - dst0;
|
||||
}
|
||||
|
||||
/*
|
||||
copy a string,
|
||||
with optional character set conversion,
|
||||
|
@ -37,6 +37,9 @@ uint32 well_formed_copy_nchars(CHARSET_INFO *to_cs,
|
||||
const char **well_formed_error_pos,
|
||||
const char **cannot_convert_error_pos,
|
||||
const char **from_end_pos);
|
||||
size_t my_copy_with_hex_escaping(CHARSET_INFO *cs,
|
||||
char *dst, size_t dstlen,
|
||||
const char *src, size_t srclen);
|
||||
|
||||
class String
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user