MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:bar Date:February 29 2008 12:41pm
Subject:bk commit into 5.1 tree (bar:1.2530) BUG#23924
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of bar.  When bar does a push these changes
will be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2008-02-29 16:41:02+04:00, bar@stripped +7 -0
  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.

  mysql-test/r/log_tables.result@stripped, 2008-02-29 16:40:59+04:00, bar@stripped +11 -0
    Adding test

  mysql-test/t/log_tables.test@stripped, 2008-02-29 16:40:59+04:00, bar@stripped +10 -0
    Adding test

  sql/field.cc@stripped, 2008-02-29 16:40:59+04:00, bar@stripped +11 -0
    Copying with hex escaping

  sql/field.h@stripped, 2008-02-29 16:40:59+04:00, bar@stripped +2 -0
    New field flag

  sql/log.cc@stripped, 2008-02-29 16:40:59+04:00, bar@stripped +1 -0
    Marking the column "general_log.argument" as hex-escaping field.

  sql/sql_string.cc@stripped, 2008-02-29 16:40:59+04:00, bar@stripped +62 -0
    New function to copy strings with hex-encoding of incompatible characters.

  sql/sql_string.h@stripped, 2008-02-29 16:40:59+04:00, bar@stripped +3 -0
    Prototype for the new function

diff -Nrup a/mysql-test/r/log_tables.result b/mysql-test/r/log_tables.result
--- a/mysql-test/r/log_tables.result	2007-12-05 15:48:11 +04:00
+++ b/mysql-test/r/log_tables.result	2008-02-29 16:40:59 +04:00
@@ -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;
+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 ('новое');
diff -Nrup a/mysql-test/t/log_tables.test b/mysql-test/t/log_tables.test
--- a/mysql-test/t/log_tables.test	2007-12-05 15:48:11 +04:00
+++ b/mysql-test/t/log_tables.test	2008-02-29 16:40:59 +04:00
@@ -131,6 +131,16 @@ 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;
+--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
 #
 
diff -Nrup a/sql/field.cc b/sql/field.cc
--- a/sql/field.cc	2008-02-07 15:28:36 +04:00
+++ b/sql/field.cc	2008-02-29 16:40:59 +04:00
@@ -7644,6 +7644,17 @@ int Field_blob::store(const char *from,u
   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
diff -Nrup a/sql/field.h b/sql/field.h
--- a/sql/field.h	2008-02-07 15:28:36 +04:00
+++ b/sql/field.h	2008-02-29 16:40:59 +04:00
@@ -2069,6 +2069,7 @@ int set_field_to_null_with_conversions(F
 #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(F
 #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)
diff -Nrup a/sql/log.cc b/sql/log.cc
--- a/sql/log.cc	2008-02-09 06:37:53 +04:00
+++ b/sql/log.cc	2008-02-29 16:40:59 +04:00
@@ -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;
 
diff -Nrup a/sql/sql_string.cc b/sql/sql_string.cc
--- a/sql/sql_string.cc	2007-12-19 22:04:21 +04:00
+++ b/sql/sql_string.cc	2008-02-29 16:40:59 +04:00
@@ -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;
+      memcpy(dst, src, chlen);
+      src+= chlen;
+      dst+= chlen;
+      dstlen-= chlen;
+    }
+    else if (*src & 0x80)
+    {
+      if (dstlen < 4)
+        break;
+      *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;
+      *dst++= *src++;
+      dstlen--;
+    }
+  }
+  return dst - dst0;
+}
+
 /*
   copy a string,
   with optional character set conversion,
diff -Nrup a/sql/sql_string.h b/sql/sql_string.h
--- a/sql/sql_string.h	2007-01-24 21:57:01 +04:00
+++ b/sql/sql_string.h	2008-02-29 16:40:59 +04:00
@@ -37,6 +37,9 @@ uint32 well_formed_copy_nchars(CHARSET_I
                                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
 {
Thread
bk commit into 5.1 tree (bar:1.2530) BUG#23924bar29 Feb