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 GENERAL_LOG=ON;
|
||||||
SET GLOBAL SLOW_QUERY_LOG=ON;
|
SET GLOBAL SLOW_QUERY_LOG=ON;
|
||||||
truncate table mysql.general_log;
|
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;
|
set names utf8;
|
||||||
create table bug16905 (s char(15) character set utf8 default 'пусто');
|
create table bug16905 (s char(15) character set utf8 default 'пусто');
|
||||||
insert into bug16905 values ('новое');
|
insert into bug16905 values ('новое');
|
||||||
|
@ -130,6 +130,16 @@ show open tables;
|
|||||||
SET GLOBAL GENERAL_LOG=ON;
|
SET GLOBAL GENERAL_LOG=ON;
|
||||||
SET GLOBAL SLOW_QUERY_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
|
# 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))
|
if (value.alloc(new_length))
|
||||||
goto oom_error;
|
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
|
"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
|
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_NO_DEFAULT 16384 /* sql */
|
||||||
#define FIELDFLAG_SUM ((uint) 32768)// predit: +#fieldflag
|
#define FIELDFLAG_SUM ((uint) 32768)// predit: +#fieldflag
|
||||||
#define FIELDFLAG_MAYBE_NULL ((uint) 32768)// sql
|
#define FIELDFLAG_MAYBE_NULL ((uint) 32768)// sql
|
||||||
|
#define FIELDFLAG_HEX_ESCAPE ((uint) 0x10000)
|
||||||
#define FIELDFLAG_PACK_SHIFT 3
|
#define FIELDFLAG_PACK_SHIFT 3
|
||||||
#define FIELDFLAG_DEC_SHIFT 8
|
#define FIELDFLAG_DEC_SHIFT 8
|
||||||
#define FIELDFLAG_MAX_DEC 31
|
#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_maybe_null(x) (x & FIELDFLAG_MAYBE_NULL)
|
||||||
#define f_no_default(x) (x & FIELDFLAG_NO_DEFAULT)
|
#define f_no_default(x) (x & FIELDFLAG_NO_DEFAULT)
|
||||||
#define f_bit_as_char(x) ((x) & FIELDFLAG_TREAT_BIT_AS_CHAR)
|
#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.
|
A positive return value in store() means truncation.
|
||||||
Still logging a message in the log in this case.
|
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)
|
if (table->field[5]->store(sql_text, sql_text_len, client_cs) < 0)
|
||||||
goto err;
|
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,
|
copy a string,
|
||||||
with optional character set conversion,
|
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 **well_formed_error_pos,
|
||||||
const char **cannot_convert_error_pos,
|
const char **cannot_convert_error_pos,
|
||||||
const char **from_end_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
|
class String
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user