List:Commits« Previous MessageNext Message »
From:Christopher Powers Date:March 29 2012 3:24am
Subject:bzr push into mysql-trunk branch (chris.powers:3862 to 3863) Bug#13809293
View as plain text  
 3863 Christopher Powers	2012-03-28
      Bug#13809293 - PERFSCHEMA.DML_ESMS_BY_DIGEST FAILS ON DAILY-TRUNK SPORADICALLY
      
      The error was triggered by mb character strings being stored as UTF8 without
      conversion. PFS now converts digest identifier to UTF8 before storing in table.

    modified:
      include/mysql/psi/mysql_statement.h
      include/mysql/psi/psi.h
      sql/mysqld.cc
      sql/sql_parse.cc
      storage/perfschema/pfs.cc
      storage/perfschema/pfs_digest.cc
      storage/perfschema/pfs_digest.h
      storage/perfschema/table_helper.cc
 3862 Christopher Powers	2012-03-27 [merge]
      local merge

    added:
      mysql-test/suite/rpl/r/rpl_gtid_sql_until_before_after.result
      mysql-test/suite/rpl/t/rpl_gtid_sql_until_before_after.test
    modified:
      include/my_md5.h
      mysql-test/collections/default.experimental
      mysql-test/r/sp-bugs.result
      mysql-test/suite/binlog/r/binlog_row_mysqlbinlog_verbose.result
      mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_verbose.test
      mysql-test/suite/innodb/r/innodb-index-online.result
      mysql-test/suite/innodb/t/innodb-index-online.test
      mysql-test/t/sp-bugs.test
      sql/log_event.cc
      sql/rpl_gtid.h
      sql/rpl_gtid_set.cc
      sql/rpl_rli.cc
      sql/rpl_rli.h
      sql/rpl_slave.cc
      sql/sql_lex.h
      sql/sql_show.cc
      sql/sql_yacc.yy
      storage/innobase/api/api0api.cc
      storage/innobase/api/api0misc.cc
      storage/innobase/include/api0api.h
=== modified file 'include/mysql/psi/mysql_statement.h'
--- a/include/mysql/psi/mysql_statement.h	2012-02-10 23:14:57 +0000
+++ b/include/mysql/psi/mysql_statement.h	2012-03-29 03:22:29 +0000
@@ -63,10 +63,10 @@
 #endif
 
 #ifdef HAVE_PSI_STATEMENT_INTERFACE
-  #define MYSQL_START_STATEMENT(STATE, K, DB, DB_LEN) \
-    inline_mysql_start_statement(STATE, K, DB, DB_LEN, __FILE__, __LINE__)
+  #define MYSQL_START_STATEMENT(STATE, K, DB, DB_LEN, CS) \
+    inline_mysql_start_statement(STATE, K, DB, DB_LEN, CS, __FILE__, __LINE__)
 #else
-  #define MYSQL_START_STATEMENT(STATE, K, DB, DB_LEN) \
+  #define MYSQL_START_STATEMENT(STATE, K, DB, DB_LEN, CS) \
     NULL
 #endif
 
@@ -152,11 +152,11 @@ inline_mysql_add_token(PSI_digest_locker
 static inline struct PSI_statement_locker *
 inline_mysql_start_statement(PSI_statement_locker_state *state,
                              PSI_statement_key key,
-                             const char *db, uint db_len,
+                             const char *db, uint db_len, uint csid,
                              const char *src_file, int src_line)
 {
   PSI_statement_locker *locker;
-  locker= PSI_CALL(get_thread_statement_locker)(state, key);
+  locker= PSI_CALL(get_thread_statement_locker)(state, key, csid);
   if (likely(locker != NULL))
     PSI_CALL(start_statement)(locker, db, db_len, src_file, src_line);
   return locker;

=== modified file 'include/mysql/psi/psi.h'
--- a/include/mysql/psi/psi.h	2012-03-05 10:57:53 +0000
+++ b/include/mysql/psi/psi.h	2012-03-29 03:22:29 +0000
@@ -958,6 +958,8 @@ struct PSI_digest_storage
 {
   my_bool m_full;
   int m_byte_count;
+  /** Character set identifier. */
+  uint m_csid;
   unsigned char m_token_array[PSI_MAX_DIGEST_STORAGE_SIZE];
 };
 typedef struct PSI_digest_storage PSI_digest_storage;
@@ -1632,11 +1634,12 @@ typedef void (*end_stage_v1_t) (void);
   Get a statement instrumentation locker.
   @param state data storage for the locker
   @param key the statement instrumentation key
+  @param csid client character set id
   @return a statement locker, or NULL
 */
 typedef struct PSI_statement_locker* (*get_thread_statement_locker_v1_t)
   (struct PSI_statement_locker_state_v1 *state,
-   PSI_statement_key key);
+   PSI_statement_key key, uint csid);
 
 /**
   Refine a statement locker to a more specific key.

=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc	2012-03-22 06:25:38 +0000
+++ b/sql/mysqld.cc	2012-03-29 03:22:29 +0000
@@ -797,7 +797,8 @@ void net_after_header_psi(struct st_net
     {
       thd->m_statement_psi= MYSQL_START_STATEMENT(& thd->m_statement_state,
                                                   stmt_info_new_packet.m_key,
-                                                  thd->db, thd->db_length);
+                                                  thd->db, thd->db_length,
+                                                  thd->charset()->number);
 
       THD_STAGE_INFO(thd, stage_init);
     }

=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc	2012-03-14 09:52:49 +0000
+++ b/sql/sql_parse.cc	2012-03-29 03:22:29 +0000
@@ -1316,9 +1316,10 @@ bool dispatch_command(enum enum_server_c
                         (char *) thd->security_ctx->host_or_ip);
 
 /* PSI begin */
-      thd->m_statement_psi= MYSQL_START_STATEMENT(& thd->m_statement_state,
+      thd->m_statement_psi= MYSQL_START_STATEMENT(&thd->m_statement_state,
                                                   com_statement_info[command].m_key,
-                                                  thd->db, thd->db_length);
+                                                  thd->db, thd->db_length,
+                                                  thd->charset()->number);
       THD_STAGE_INFO(thd, stage_init);
       MYSQL_SET_STATEMENT_TEXT(thd->m_statement_psi, beginning_of_next_stmt, length);
 

=== modified file 'storage/perfschema/pfs.cc'
--- a/storage/perfschema/pfs.cc	2012-03-19 19:29:28 +0000
+++ b/storage/perfschema/pfs.cc	2012-03-29 03:22:29 +0000
@@ -4169,7 +4169,8 @@ static void end_stage_v1()
 
 static PSI_statement_locker*
 get_thread_statement_locker_v1(PSI_statement_locker_state *state,
-                               PSI_statement_key key)
+                               PSI_statement_key key,
+                               uint csid)
 {
   DBUG_ASSERT(state != NULL);
   if (! flag_global_instrumentation)
@@ -4269,6 +4270,7 @@ get_thread_statement_locker_v1(PSI_state
     flags|= STATE_FLAG_DIGEST;
     state->m_digest_state.m_last_id_index= 0;
     digest_reset(& state->m_digest_state.m_digest_storage);
+    state->m_digest_state.m_digest_storage.m_csid= csid;
   }
 
   state->m_discarded= false;
@@ -4567,10 +4569,7 @@ static void end_statement_v1(PSI_stateme
     if (flags & STATE_FLAG_DIGEST)
     {
       digest_storage= &state->m_digest_state.m_digest_storage;
-
-      /* 
-        Populate PFS_statements_digest_stat with computed digest information.
-      */
+      /* Populate PFS_statements_digest_stat with computed digest information.*/
       digest_stat= find_or_create_digest(thread, digest_storage);
     }
 
@@ -4637,10 +4636,7 @@ static void end_statement_v1(PSI_stateme
       {
         /* Set digest stat. */
         digest_storage= &state->m_digest_state.m_digest_storage;
-
-        /* 
-          Populate PFS_statements_digest_stat with computed digest information.
-        */
+        /* Populate statements_digest_stat with computed digest information. */
         digest_stat= find_or_create_digest(thread, digest_storage);
       }
     }

=== modified file 'storage/perfschema/pfs_digest.cc'
--- a/storage/perfschema/pfs_digest.cc	2012-02-28 15:57:52 +0000
+++ b/storage/perfschema/pfs_digest.cc	2012-03-29 03:22:29 +0000
@@ -31,6 +31,7 @@
 #include "my_md5.h"
 #include "sql_lex.h"
 #include "sql_get_diagnostics.h"
+#include "sql_string.h"
 #include <string.h>
 
 /* Generated code */
@@ -168,8 +169,8 @@ static LF_PINS* get_digest_hash_pins(PFS
 }
 
 PFS_statement_stat*
-find_or_create_digest(PFS_thread* thread,
-                      PSI_digest_storage* digest_storage)
+find_or_create_digest(PFS_thread *thread,
+                      PSI_digest_storage *digest_storage)
 {
   if (statements_digest_stat_array == NULL)
     return NULL;
@@ -348,98 +349,145 @@ void reset_esms_by_digest()
 */
 void get_digest_text(char* digest_text, PSI_digest_storage* digest_storage)
 {
+  DBUG_ASSERT(digest_storage != NULL);
   bool truncated= false;
   int byte_count= digest_storage->m_byte_count;
-  int need_bytes;
+  int bytes_needed= 0;
   uint tok= 0;
-  char *id_string;
-  int id_length;
   int current_byte= 0;
   lex_token_string *tok_data;
   /* -4 is to make sure extra space for '...' and a '\0' at the end. */
-  int available_bytes_to_write= COL_DIGEST_TEXT_SIZE - 4;
+  int bytes_available= COL_DIGEST_TEXT_SIZE - 4;
+  
+  /* Convert text to utf8 if necessary */
+  uint csid= digest_storage->m_csid;
+  const CHARSET_INFO *from_cs=get_charset(csid, 0);
+  const CHARSET_INFO *to_cs=get_charset_by_name("utf8_bin", 0);
+  /* Max number of characters * max mb len of target character set */
+  const uint max_converted_size= PSI_MAX_DIGEST_STORAGE_SIZE * 3;
+  char id_string[max_converted_size];
 
   DBUG_ASSERT(byte_count <= PSI_MAX_DIGEST_STORAGE_SIZE);
 
-  while ((current_byte < byte_count) &&
-         (available_bytes_to_write > 0) &&
-         (! truncated))
+  while (current_byte < byte_count &&
+         bytes_available > 0 &&
+         !truncated)
   {
     current_byte= read_token(digest_storage, current_byte, &tok);
-    tok_data= & lex_token_array[tok];
+    tok_data= &lex_token_array[tok];
     
     switch (tok)
     {
     /* All identifiers are printed with their name. */
     case IDENT:
-      current_byte= read_identifier(digest_storage, current_byte,
-                                    & id_string, & id_length);
-      need_bytes= id_length + 1; /* <id> space */
-      if (need_bytes <= available_bytes_to_write)
       {
-        if (id_length > 0)
+        char *id_ptr;
+        int id_len;
+        uint err_cs;
+
+        /* Get the next identifier in the storage buffer. */
+        current_byte= read_identifier(digest_storage, current_byte,
+                                      &id_ptr, &id_len);
+        /* Verify that the converted text will fit. */
+        if (to_cs->mbmaxlen*id_len > max_converted_size)
         {
-          strncpy(digest_text, id_string, id_length);
-          digest_text+= id_length;
+          truncated= true;
+          break;
+        }
+        /* Convert identifier string into the storage character set. */
+        int id_length= my_convert(id_string, max_converted_size, to_cs, id_ptr,
+                                  id_len, from_cs, &err_cs);
+        
+        if (id_length == 0 || err_cs != 0)
+        {
+          truncated= true;
+          break;
+        }
+        /* Copy the converted identifier into the digest string. */
+        bytes_needed= id_length + 1; /* <id> space */
+        if (bytes_needed <= bytes_available)
+        {
+          if (id_length > 0)
+          {
+            memcpy(digest_text, id_string, id_length);
+            digest_text+= id_length;
+          }
+          *digest_text++= ' ';
+          bytes_available-= bytes_needed;
+        }
+        else
+        {
+          truncated= true;
         }
-        *digest_text= ' ';
-        digest_text++;
-        available_bytes_to_write-= need_bytes;
-      }
-      else
-      {
-        truncated= true;
       }
       break;
+
     case IDENT_QUOTED:
-      current_byte= read_identifier(digest_storage, current_byte,
-                                    & id_string, & id_length);
-      need_bytes= id_length + 3; /* quote <id> quote space  */
-      if (need_bytes <= available_bytes_to_write)
       {
-        *digest_text= '`';
-        digest_text++;
-        if (id_length > 0)
+        char *id_ptr;
+        int id_len;
+        uint err_cs;
+
+        /* Get the next identifier in the storage buffer. */
+        current_byte= read_identifier(digest_storage, current_byte,
+                                      &id_ptr, &id_len);
+        /* Verify that the converted text will fit. */
+        if (to_cs->mbmaxlen*id_len > max_converted_size)
         {
-          strncpy(digest_text, id_string, id_length);
-          digest_text+= id_length;
+          truncated= true;
+          break;
+        }
+        /* Convert identifier string into the storage character set. */
+        int id_length= my_convert(id_string, max_converted_size, to_cs, id_ptr,
+                                  id_len, from_cs, &err_cs);
+        
+        if (id_length == 0 || err_cs != 0)
+        {
+          truncated= true;
+          break;
+        }
+        /* Copy the converted identifier into the digest string. */
+        bytes_needed= id_length + 3; /* quote <id> quote space  */
+        if (bytes_needed <= bytes_available)
+        {
+          *digest_text++= '`';
+          if (id_length > 0)
+          {
+            memcpy(digest_text, id_string, id_length);
+            digest_text+= id_length;
+          }
+          *digest_text++= '`';
+          *digest_text++= ' ';
+          bytes_available-= bytes_needed;
+        }
+        else
+        {
+          truncated= true;
         }
-        *digest_text= '`';
-        digest_text++;
-        *digest_text= ' ';
-        digest_text++;
-        available_bytes_to_write-= need_bytes;
-      }
-      else
-      {
-        truncated= true;
       }
       break;
 
     /* Everything else is printed as is. */
     default:
       /* 
-        Make sure not to overflow digest_text buffer while writing
-        this token string.
+        Make sure not to overflow digest_text buffer.
         +1 is to make sure extra space for ' '.
       */
       int tok_length= tok_data->m_token_length;
-      need_bytes= tok_length + 1;
+      bytes_needed= tok_length + 1;
 
-      if (need_bytes <= available_bytes_to_write)
+      if (bytes_needed <= bytes_available)
       {
-        strncpy(digest_text,
-                tok_data->m_token_string,
-                tok_length);
+        strncpy(digest_text, tok_data->m_token_string, tok_length);
         digest_text+= tok_length;
-        *digest_text= ' ';
-        digest_text++;
-        available_bytes_to_write-= need_bytes;
+        *digest_text++= ' ';
+        bytes_available-= bytes_needed;
       }
       else
       {
         truncated= true;
       }
+      break;
     }
   }
 

=== modified file 'storage/perfschema/pfs_digest.h'
--- a/storage/perfschema/pfs_digest.h	2012-02-28 15:57:52 +0000
+++ b/storage/perfschema/pfs_digest.h	2012-03-29 03:22:29 +0000
@@ -46,24 +46,16 @@ struct PFS_digest_hash
 /** A statement digest stat record. */
 struct PFS_statements_digest_stat
 {
-  /**
-    Digest MD5 Hash.
-  */
+  /** Digest MD5 Hash. */
   PFS_digest_hash m_digest_hash;
 
-  /**
-    Digest Storage.
-  */
+  /** Digest Storage. */
   PSI_digest_storage m_digest_storage;
 
-  /**
-    Statement stat.
-  */
+  /** Statement stat. */
   PFS_statement_stat m_stat;
 
-  /**
-    First Seen/last seen.
-  */
+  /** First and last seen timestamps.*/
   ulonglong m_first_seen;
   ulonglong m_last_seen;
 
@@ -78,10 +70,10 @@ void cleanup_digest();
 
 int init_digest_hash(void);
 void cleanup_digest_hash(void);
-PFS_statement_stat* find_or_create_digest(PFS_thread*,
-                                          PSI_digest_storage*);
+PFS_statement_stat* find_or_create_digest(PFS_thread *thread,
+                                          PSI_digest_storage *digest_storage);
 
-void get_digest_text(char* digest_text, PSI_digest_storage*);
+void get_digest_text(char *digest_text, PSI_digest_storage *digest_storage);
 
 void reset_esms_by_digest();
 
@@ -90,8 +82,8 @@ extern PFS_statements_digest_stat *state
 
 /* Instrumentation callbacks for pfs.cc */
 
-struct PSI_digest_locker* pfs_digest_start_v1(PSI_statement_locker *locker);
-PSI_digest_locker* pfs_digest_add_token_v1(PSI_digest_locker *locker,
+struct PSI_digest_locker *pfs_digest_start_v1(PSI_statement_locker *locker);
+PSI_digest_locker *pfs_digest_add_token_v1(PSI_digest_locker *locker,
                                            uint token,
                                            OPAQUE_LEX_YYSTYPE *yylval);
 
@@ -99,6 +91,7 @@ static inline void digest_reset(PSI_dige
 {
   digest->m_full= false;
   digest->m_byte_count= 0;
+  digest->m_csid= 0; //TBD default character set
 }
 
 static inline void digest_copy(PSI_digest_storage *to, const PSI_digest_storage *from)
@@ -107,6 +100,7 @@ static inline void digest_copy(PSI_diges
   {
     to->m_full= from->m_full;
     to->m_byte_count= from->m_byte_count;
+    to->m_csid= from->m_csid;
     DBUG_ASSERT(to->m_byte_count <= PSI_MAX_DIGEST_STORAGE_SIZE);
     memcpy(to->m_token_array, from->m_token_array, to->m_byte_count);
   }
@@ -116,11 +110,12 @@ static inline void digest_copy(PSI_diges
     DBUG_ASSERT(from->m_byte_count == 0);
     to->m_full= false;
     to->m_byte_count= 0;
+    to->m_csid= 0;
   }
 }
 
 /** 
-  Function to read a single token from token array.
+  Read a single token from token array.
 */
 inline int read_token(PSI_digest_storage *digest_storage,
                       int index, uint *tok)
@@ -141,7 +136,7 @@ inline int read_token(PSI_digest_storage
 }
 
 /**
-  Function to store a single token in token array.
+  Store a single token in token array.
 */
 inline void store_token(PSI_digest_storage* digest_storage, uint token)
 {
@@ -162,7 +157,7 @@ inline void store_token(PSI_digest_stora
 }
 
 /**
-  Function to read an identifier from token array.
+  Read an identifier from token array.
 */
 inline int read_identifier(PSI_digest_storage* digest_storage,
                            int index, char ** id_string, int *id_length)
@@ -186,7 +181,7 @@ inline int read_identifier(PSI_digest_st
 }
 
 /**
-  Function to store an identifier in token array.
+  Store an identifier in token array.
 */
 inline void store_token_identifier(PSI_digest_storage* digest_storage,
                                    uint token,
@@ -207,9 +202,7 @@ inline void store_token_identifier(PSI_d
     dest[3]= (id_length >> 8) & 0xff;
     /* Write the string data */
     if (id_length > 0)
-    {
-      strncpy((char *)(dest + 4), id_name, id_length);
-    }
+      memcpy((char *)(dest + 4), id_name, id_length);
     digest_storage->m_byte_count+= bytes_needed; 
   }
   else

=== modified file 'storage/perfschema/table_helper.cc'
--- a/storage/perfschema/table_helper.cc	2012-03-19 19:29:28 +0000
+++ b/storage/perfschema/table_helper.cc	2012-03-29 03:22:29 +0000
@@ -101,7 +101,7 @@ void PFS_account_row::set_field(uint ind
   }
 }
 
-int PFS_digest_row::make_row(PFS_statements_digest_stat* pfs)
+int PFS_digest_row::make_row(PFS_statements_digest_stat *pfs)
 {
   /*
     "0" value for byte_count indicates special entry i.e. aggregated

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk branch (chris.powers:3862 to 3863) Bug#13809293Christopher Powers29 Mar