List:Commits« Previous MessageNext Message »
From:Georgi Kodinov Date:May 4 2012 10:55am
Subject:bzr push into mysql-trunk branch (Georgi.Kodinov:3836 to 3838) WL#5924
View as plain text  
 3838 Georgi Kodinov	2012-05-04
      WL#5924 : Add connect string processing to mysql
      
      Applied a class hierarchy separation patch by Chris P.
      Now the iterator is an actual iterator and nothing but.
      All the non-iterator code was moved to an intermediary
      base class for the two P_S tables introduced by this WL.

    added:
      storage/perfschema/table_session_connect.cc
      storage/perfschema/table_session_connect.h
    modified:
      storage/perfschema/CMakeLists.txt
      storage/perfschema/cursor_by_thread_connect_attr.cc
      storage/perfschema/cursor_by_thread_connect_attr.h
      storage/perfschema/table_session_account_connect_attrs.cc
      storage/perfschema/table_session_account_connect_attrs.h
      storage/perfschema/table_session_connect_attrs.cc
      storage/perfschema/table_session_connect_attrs.h
 3837 Georgi Kodinov	2012-05-02
      WL#5924: Add connect string processing to mysql
      
      impose an artificial 64k length limit for the attributes blob
      to avoid DoS scenarios.

    modified:
      sql/sql_acl.cc
 3836 Georgi Kodinov	2012-05-02
      WL#5924 : Add connect string processing to mysql
      
      Addressed second part of Kristofer's comments:
      1. The overall length of the attributes transferred is 
      encoded as a dynamic length instead of as a fixed 2
      byte string.
      2. Added a write_length_encoded_string() to serialize 
      both name and length for uniformity.
      3. Adjusted some unit test buffer sizes.

    modified:
      libmysqld/lib_sql.cc
      sql-common/client.c
      sql/sql_acl.cc
      storage/perfschema/unittest/pfs_connect_attr-t.cc
=== modified file 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc	2012-05-02 14:54:35 +0000
+++ b/sql/sql_acl.cc	2012-05-02 15:09:57 +0000
@@ -8439,6 +8439,10 @@ read_client_connect_attrs(char **ptr, si
   if (length > *max_bytes_available)
     return true;
 
+  /* impose an artificial length limit of 64k */
+  if (length > 65535)
+    return true;
+
 #ifdef HAVE_PSI_THREAD_INTERFACE
   if (PSI_CALL(set_thread_connect_attrs)(*ptr, length, from_cs) && log_warnings)
     sql_print_warning("Connection attributes of length %lu were truncated",

=== modified file 'storage/perfschema/CMakeLists.txt'
--- a/storage/perfschema/CMakeLists.txt	2012-03-30 16:01:10 +0000
+++ b/storage/perfschema/CMakeLists.txt	2012-05-04 10:54:36 +0000
@@ -119,6 +119,7 @@ table_tiws_by_table.h
 table_tlws_by_table.h
 table_users.h
 cursor_by_thread_connect_attr.h
+table_session_connect.h
 table_session_connect_attrs.h
 table_session_account_connect_attrs.h
 cursor_by_account.cc
@@ -193,6 +194,7 @@ table_tiws_by_table.cc
 table_tlws_by_table.cc
 table_users.cc
 cursor_by_thread_connect_attr.cc
+table_session_connect.cc
 table_session_connect_attrs.cc
 table_session_account_connect_attrs.cc
 )

=== modified file 'storage/perfschema/cursor_by_thread_connect_attr.cc'
--- a/storage/perfschema/cursor_by_thread_connect_attr.cc	2012-05-02 11:04:32 +0000
+++ b/storage/perfschema/cursor_by_thread_connect_attr.cc	2012-05-04 10:54:36 +0000
@@ -16,174 +16,11 @@
 #include "my_global.h"
 #include "cursor_by_thread_connect_attr.h"
 
-static const TABLE_FIELD_TYPE field_types[]=
-{
-  {
-    { C_STRING_WITH_LEN("PROCESS_ID") },
-    { C_STRING_WITH_LEN("int(11)") },
-    { NULL, 0}
-  },
-  {
-    { C_STRING_WITH_LEN("ATTR_NAME") },
-    { C_STRING_WITH_LEN("varchar(32)") },
-    { NULL, 0}
-  },
-  {
-    { C_STRING_WITH_LEN("ATTR_VALUE") },
-    { C_STRING_WITH_LEN("varchar(1024)") },
-    { NULL, 0}
-  },
-  {
-    { C_STRING_WITH_LEN("ORDINAL_POSITION") },
-    { C_STRING_WITH_LEN("int(11)") },
-    { NULL, 0}
-  }
-};
-
-/** symbolic names for field offsets, keep in sync with field_types */
-enum field_offsets {
-  FO_PROCESS_ID,
-  FO_ATTR_NAME,
-  FO_ATTR_VALUE,
-  FO_ORDINAL_POSITION
-};
-
-TABLE_FIELD_DEF
-cursor_by_thread_connect_attr::m_field_def=
-{ 4, field_types };
-
 cursor_by_thread_connect_attr::cursor_by_thread_connect_attr(
   const PFS_engine_table_share *share) :
   PFS_engine_table(share, &m_pos), m_row_exists(false)
 {}
 
-/**
-  Take a length encoded string
-
-  @arg ptr  inout       the input string array
-  @arg dest             where to store the result
-  @arg dest_size        max size of @c dest
-  @arg copied_len       the actual length of the data copied
-  @arg start_ptr        pointer to the start of input
-  @arg input_length     the length of the incoming data
-  @arg copy_data        copy the data or just skip the input
-  @arg from_cs          character set in which @c ptr is encoded
-  @arg nchars_max       maximum number of characters to read
-  @return status
-    @retval true    parsing failed
-    @retval false   parsing succeeded
-*/
-static bool parse_length_encoded_string(const char **ptr,
-                                        char *dest, uint dest_size,
-                                        uint *copied_len,
-                                        const char *start_ptr, uint input_length,
-                                        bool copy_data,
-                                        const CHARSET_INFO *from_cs,
-                                        uint nchars_max)
-{
-  ulong copy_length, data_length;
-  const char *well_formed_error_pos= NULL, *cannot_convert_error_pos= NULL,
-        *from_end_pos= NULL;
-
-  copy_length= data_length= net_field_length((uchar **) ptr);
-
-  /* we don't tolerate NULL as a length */
-  if (data_length == NULL_LENGTH)
-    return true;
-
-  if (*ptr - start_ptr + data_length > input_length)
-    return true;
-
-  copy_length= well_formed_copy_nchars(&my_charset_utf8_bin, dest, dest_size,
-                                       from_cs, *ptr, data_length, nchars_max,
-                                       &well_formed_error_pos,
-                                       &cannot_convert_error_pos,
-                                       &from_end_pos);
-  *copied_len= copy_length;
-  (*ptr)+= data_length;
-
-  return false;
-}
-
-
-/**
-  Take the nth attribute name/value pair
-
-  Parse the attributes blob form the beginning, skipping the attributes
-  whose number is lower than the one we seek.
-  When we reach the attribute at an index we're looking for the values
-  are copied to the output parameters.
-  If parsing fails or no more attributes are found the function stops
-  and returns an error code.
-
-  @arg connect_attrs            pointer to the connect attributes blob
-  @arg connect_attrs_length     length of @c connect_attrs
-  @arg connect_attrs_cs         character set used to encode @c connect_attrs
-  @arg ordinal                  index of the attribute we need
-  @arg attr_name [out]          buffer to receive the attribute name
-  @arg max_attr_name            max size of @c attr_name in bytes
-  @arg attr_name_length [out]   number of bytes written in @attr_name
-  @arg attr_value [out]         buffer to receive the attribute name
-  @arg max_attr_value           max size of @c attr_value in bytes
-  @arg attr_value_length [out]  number of bytes written in @attr_value
-  @return status
-    @retval true    requested attribute pair is found and copied
-    @retval false   error. Either because of parsing or too few attributes.
-*/
-bool read_nth_attr(const char *connect_attrs, uint connect_attrs_length,
-                          const CHARSET_INFO *connect_attrs_cs,
-                          uint ordinal,
-                          char *attr_name, uint max_attr_name,
-                          uint *attr_name_length,
-                          char *attr_value, uint max_attr_value,
-                          uint *attr_value_length)
-{
-  uint idx;
-  const char *ptr;
-
-  for (ptr= connect_attrs, idx= 0;
-       (ptr - connect_attrs) < connect_attrs_length && idx <= ordinal;
-      idx++)
-  {
-    uint copy_length;
-    /* do the copying only if we absolutely have to */
-    bool fill_in_attr_name= idx == ordinal;
-    bool fill_in_attr_value= idx == ordinal;
-
-    /* read the key */
-    if (parse_length_encoded_string(&ptr,
-                                    attr_name, max_attr_name, &copy_length,
-                                    connect_attrs,
-                                    connect_attrs_length,
-                                    fill_in_attr_name,
-                                    connect_attrs_cs, 32) ||
-        !copy_length
-        )
-      return false;
-    if (idx == ordinal)
-      *attr_name_length= copy_length;
-
-
-    /* read the value */
-    if (parse_length_encoded_string(&ptr,
-                                    attr_value, max_attr_value, &copy_length,
-                                    connect_attrs,
-                                    connect_attrs_length,
-                                    fill_in_attr_value,
-                                    connect_attrs_cs, 1024))
-      return false;
-
-    if (idx == ordinal)
-      *attr_value_length= copy_length;
-
-    if (idx == ordinal)
-      return true;
-  }
-
-  return false;
-}
-
-
 int cursor_by_thread_connect_attr::rnd_next(void)
 {
   PFS_thread *thread;
@@ -235,89 +72,3 @@ void cursor_by_thread_connect_attr::rese
   m_pos.reset();
   m_next_pos.reset();
 }
-
-
-void cursor_by_thread_connect_attr::make_row(PFS_thread *pfs, uint ordinal)
-{
-  pfs_lock lock;
-  PFS_thread_class *safe_class;
-
-  m_row_exists= false;
-
-  /* Protect this reader against thread termination */
-  pfs->m_lock.begin_optimistic_lock(&lock);
-  safe_class= sanitize_thread_class(pfs->m_class);
-  if (unlikely(safe_class == NULL))
-    return;
-
-  /* populate the row */
-  if (read_nth_attr(pfs->m_connect_attrs, pfs->m_connect_attrs_length,
-                    pfs->m_connect_attrs_cs,
-                    ordinal,
-                    m_row.m_attr_name, (uint) sizeof(m_row.m_attr_name),
-                    &m_row.m_attr_name_length,
-                    m_row.m_attr_value, (uint) sizeof(m_row.m_attr_value),
-                    &m_row.m_attr_value_length))
-  {
-    /* we don't expect internal threads to have connection attributes */
-    DBUG_ASSERT(pfs->m_thread_id != 0);
-
-    m_row.m_ordinal_position= ordinal;
-    m_row.m_process_id= pfs->m_thread_id;
-  }
-  else
-    return;
-
-
-  if (pfs->m_lock.end_optimistic_lock(& lock))
-    m_row_exists= true;
-}
-
-
-int cursor_by_thread_connect_attr::read_row_values(TABLE *table,
-                                   unsigned char *buf,
-                                   Field **fields,
-                                   bool read_all)
-{
-  Field *f;
-
-  if (unlikely(!m_row_exists))
-    return HA_ERR_RECORD_DELETED;
-
-  /* Set the null bits */
-  DBUG_ASSERT(table->s->null_bytes == 1);
-  buf[0]= 0;
-
-  for (; (f= *fields) ; fields++)
-  {
-    if (read_all || bitmap_is_set(table->read_set, f->field_index))
-    {
-      switch(f->field_index)
-      {
-      case FO_PROCESS_ID:
-        if (m_row.m_process_id != 0)
-          set_field_ulong(f, m_row.m_process_id);
-        else
-          f->set_null();
-        break;
-      case FO_ATTR_NAME:
-        set_field_varchar_utf8(f, m_row.m_attr_name,
-                               m_row.m_attr_name_length);
-        break;
-      case FO_ATTR_VALUE:
-        if (m_row.m_attr_value_length)
-          set_field_varchar_utf8(f, m_row.m_attr_value,
-                                 m_row.m_attr_value_length);
-        else
-          f->set_null();
-        break;
-      case FO_ORDINAL_POSITION:
-        set_field_ulong(f, m_row.m_ordinal_position);
-        break;
-      default:
-        DBUG_ASSERT(false);
-      }
-    }
-  }
-  return 0;
-}

=== modified file 'storage/perfschema/cursor_by_thread_connect_attr.h'
--- a/storage/perfschema/cursor_by_thread_connect_attr.h	2012-05-02 11:04:32 +0000
+++ b/storage/perfschema/cursor_by_thread_connect_attr.h	2012-05-04 10:54:36 +0000
@@ -50,30 +50,6 @@ struct pos_connect_attr_by_thread_by_att
   }
 };
 
-#define MAX_ATTR_NAME_CHARS 32
-#define MAX_ATTR_VALUE_CHARS 1024
-#define MAX_UTF8_BYTES 6
-/**
-  A row of PERFORMANCE_SCHEMA.SESSION_CONNECT_ATTRS and
-  PERFORMANCE_SCHEMA.SESSION_ACCOUNT_CONNECT_ATTRS.
-*/
-struct row_session_connect_attrs
-{
-  /** Column PROCESS_ID. */
-  ulong m_process_id;
-  /** Column ATTR_NAME. In UTF-8 */
-  char m_attr_name[MAX_ATTR_NAME_CHARS * MAX_UTF8_BYTES];
-  /** Length in bytes of @c m_attr_name. */
-  uint m_attr_name_length;
-  /** Column ATTR_VALUE. In UTF-8 */
-  char m_attr_value[MAX_ATTR_VALUE_CHARS * MAX_UTF8_BYTES];
-  /** Length in bytes of @c m_attr_name. */
-  uint m_attr_value_length;
-  /** Column ORDINAL_POSITION. */
-  ulong m_ordinal_position;
-};
-
-
 /** Cursor CURSOR_BY_THREAD_CONNECT_ATTR. */
 class cursor_by_thread_connect_attr : public PFS_engine_table
 {
@@ -84,30 +60,22 @@ public:
 
 protected:
   cursor_by_thread_connect_attr(const PFS_engine_table_share *share);
-  virtual int read_row_values(TABLE *table, unsigned char *buf,
-                              Field **fields, bool read_all);
 
 public:
   ~cursor_by_thread_connect_attr()
   {}
 
 protected:
-  void make_row(PFS_thread *thread, uint ordinal);
-  virtual bool thread_fits(PFS_thread *thread, PFS_thread *current_thread) = 0;
+  virtual void make_row(PFS_thread *thread, uint ordinal)= 0;
+  virtual bool thread_fits(PFS_thread *thread, PFS_thread *current_thread)= 0;
+  /** True if row exists */
+  bool m_row_exists;
 
 private:
   /** Current position. */
   pos_connect_attr_by_thread_by_attr m_pos;
   /** Next position. */
   pos_connect_attr_by_thread_by_attr m_next_pos;
-
-protected:
-  /** Fields definition. */
-  static TABLE_FIELD_DEF m_field_def;
-  /** Current row. */
-  row_session_connect_attrs m_row;
-  /** True if the current row exists. */
-  bool m_row_exists;
 };
 
 /** @} */

=== modified file 'storage/perfschema/table_session_account_connect_attrs.cc'
--- a/storage/perfschema/table_session_account_connect_attrs.cc	2012-03-30 16:01:10 +0000
+++ b/storage/perfschema/table_session_account_connect_attrs.cc	2012-05-04 10:54:36 +0000
@@ -36,7 +36,6 @@ public:
 
 PFS_readonly_world_acl pfs_readonly_world_acl;
 
-
 PFS_engine_table_share
 table_session_account_connect_attrs::m_share=
 {
@@ -53,18 +52,15 @@ table_session_account_connect_attrs::m_s
   false /* checked */
 };
 
-
 PFS_engine_table* table_session_account_connect_attrs::create()
 {
   return new table_session_account_connect_attrs();
 }
 
-
 table_session_account_connect_attrs::table_session_account_connect_attrs()
-  : cursor_by_thread_connect_attr(&m_share)
+  : table_session_connect(&m_share)
 {}
 
-
 bool
 table_session_account_connect_attrs::thread_fits(PFS_thread *thread,
                                                  PFS_thread *current_thread){

=== modified file 'storage/perfschema/table_session_account_connect_attrs.h'
--- a/storage/perfschema/table_session_account_connect_attrs.h	2012-03-30 16:01:10 +0000
+++ b/storage/perfschema/table_session_account_connect_attrs.h	2012-05-04 10:54:36 +0000
@@ -16,15 +16,14 @@
 #ifndef TABLE_SESSION_ACCOUNT_CONNECT_ATTRS_H
 #define TABLE_SESSION_ACCOUNT_CONNECT_ATTRS_H
 
-#include "cursor_by_thread_connect_attr.h"
+#include "table_session_connect.h"
 /**
   \addtogroup Performance_schema_tables
   @{
 */
 
 /** Table PERFORMANCE_SCHEMA.SESSION_ACCOUNT_CONNECT_ATTRS. */
-class table_session_account_connect_attrs :
-  public cursor_by_thread_connect_attr
+class table_session_account_connect_attrs : public table_session_connect
 {
 public:
   /** Table share */
@@ -39,7 +38,7 @@ public:
   ~table_session_account_connect_attrs()
   {}
 
-private:
+protected:
   bool thread_fits(PFS_thread *thread, PFS_thread *current_thread);
 
 private:

=== added file 'storage/perfschema/table_session_connect.cc'
--- a/storage/perfschema/table_session_connect.cc	1970-01-01 00:00:00 +0000
+++ b/storage/perfschema/table_session_connect.cc	2012-05-04 10:54:36 +0000
@@ -0,0 +1,264 @@
+/* Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; version 2 of the License.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software Foundation,
+  51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
+
+#include "table_session_connect.h"
+
+static const TABLE_FIELD_TYPE field_types[]=
+{
+  {
+    { C_STRING_WITH_LEN("PROCESS_ID") },
+    { C_STRING_WITH_LEN("int(11)") },
+    { NULL, 0}
+  },
+  {
+    { C_STRING_WITH_LEN("ATTR_NAME") },
+    { C_STRING_WITH_LEN("varchar(32)") },
+    { NULL, 0}
+  },
+  {
+    { C_STRING_WITH_LEN("ATTR_VALUE") },
+    { C_STRING_WITH_LEN("varchar(1024)") },
+    { NULL, 0}
+  },
+  {
+    { C_STRING_WITH_LEN("ORDINAL_POSITION") },
+    { C_STRING_WITH_LEN("int(11)") },
+    { NULL, 0}
+  }
+};
+
+TABLE_FIELD_DEF table_session_connect::m_field_def=
+{ 4, field_types };
+
+table_session_connect::table_session_connect(const PFS_engine_table_share *share) :
+                       cursor_by_thread_connect_attr(share)
+{}
+
+/**
+  Take a length encoded string
+
+  @arg ptr  inout       the input string array
+  @arg dest             where to store the result
+  @arg dest_size        max size of @c dest
+  @arg copied_len       the actual length of the data copied
+  @arg start_ptr        pointer to the start of input
+  @arg input_length     the length of the incoming data
+  @arg copy_data        copy the data or just skip the input
+  @arg from_cs          character set in which @c ptr is encoded
+  @arg nchars_max       maximum number of characters to read
+  @return status
+    @retval true    parsing failed
+    @retval false   parsing succeeded
+*/
+bool parse_length_encoded_string(const char **ptr,
+                 char *dest, uint dest_size,
+                 uint *copied_len,
+                 const char *start_ptr, uint input_length,
+                 bool copy_data,
+                 const CHARSET_INFO *from_cs,
+                 uint nchars_max)
+{
+  ulong copy_length, data_length;
+  const char *well_formed_error_pos= NULL, *cannot_convert_error_pos= NULL,
+        *from_end_pos= NULL;
+
+  copy_length= data_length= net_field_length((uchar **) ptr);
+
+  /* we don't tolerate NULL as a length */
+  if (data_length == NULL_LENGTH)
+    return true;
+
+  if (*ptr - start_ptr + data_length > input_length)
+    return true;
+
+  copy_length= well_formed_copy_nchars(&my_charset_utf8_bin, dest, dest_size,
+                                       from_cs, *ptr, data_length, nchars_max,
+                                       &well_formed_error_pos,
+                                       &cannot_convert_error_pos,
+                                       &from_end_pos);
+  *copied_len= copy_length;
+  (*ptr)+= data_length;
+
+  return false;
+}
+
+/**
+  Take the nth attribute name/value pair
+
+  Parse the attributes blob form the beginning, skipping the attributes
+  whose number is lower than the one we seek.
+  When we reach the attribute at an index we're looking for the values
+  are copied to the output parameters.
+  If parsing fails or no more attributes are found the function stops
+  and returns an error code.
+
+  @arg connect_attrs            pointer to the connect attributes blob
+  @arg connect_attrs_length     length of @c connect_attrs
+  @arg connect_attrs_cs         character set used to encode @c connect_attrs
+  @arg ordinal                  index of the attribute we need
+  @arg attr_name [out]          buffer to receive the attribute name
+  @arg max_attr_name            max size of @c attr_name in bytes
+  @arg attr_name_length [out]   number of bytes written in @attr_name
+  @arg attr_value [out]         buffer to receive the attribute name
+  @arg max_attr_value           max size of @c attr_value in bytes
+  @arg attr_value_length [out]  number of bytes written in @attr_value
+  @return status
+    @retval true    requested attribute pair is found and copied
+    @retval false   error. Either because of parsing or too few attributes.
+*/
+bool read_nth_attr(const char *connect_attrs,
+                   uint connect_attrs_length,
+                   const CHARSET_INFO *connect_attrs_cs,
+                   uint ordinal,
+                   char *attr_name, uint max_attr_name,
+                   uint *attr_name_length,
+                   char *attr_value, uint max_attr_value,
+                   uint *attr_value_length)
+{
+  uint idx;
+  const char *ptr;
+
+  for (ptr= connect_attrs, idx= 0;
+       (uint)(ptr - connect_attrs) < connect_attrs_length && idx <= ordinal;
+      idx++)
+  {
+    uint copy_length;
+    /* do the copying only if we absolutely have to */
+    bool fill_in_attr_name= idx == ordinal;
+    bool fill_in_attr_value= idx == ordinal;
+
+    /* read the key */
+    if (parse_length_encoded_string(&ptr,
+                                    attr_name, max_attr_name, &copy_length,
+                                    connect_attrs,
+                                    connect_attrs_length,
+                                    fill_in_attr_name,
+                                    connect_attrs_cs, 32) ||
+        !copy_length
+        )
+      return false;
+
+    if (idx == ordinal)
+      *attr_name_length= copy_length;
+      
+    /* read the value */
+    if (parse_length_encoded_string(&ptr,
+                                    attr_value, max_attr_value, &copy_length,
+                                    connect_attrs,
+                                    connect_attrs_length,
+                                    fill_in_attr_value,
+                                    connect_attrs_cs, 1024))
+      return false;
+
+    if (idx == ordinal)
+      *attr_value_length= copy_length;
+
+    if (idx == ordinal)
+      return true;
+  }
+
+  return false;
+}
+
+void table_session_connect::make_row(PFS_thread *pfs, uint ordinal)
+{
+  pfs_lock lock;
+  PFS_thread_class *safe_class;
+
+  m_row_exists= false;
+
+  /* Protect this reader against thread termination */
+  pfs->m_lock.begin_optimistic_lock(&lock);
+  safe_class= sanitize_thread_class(pfs->m_class);
+  if (unlikely(safe_class == NULL))
+    return;
+
+  /* populate the row */
+  if (read_nth_attr(pfs->m_connect_attrs, pfs->m_connect_attrs_length,
+                    pfs->m_connect_attrs_cs,
+                    ordinal,
+                    m_row.m_attr_name, (uint) sizeof(m_row.m_attr_name),
+                    &m_row.m_attr_name_length,
+                    m_row.m_attr_value, (uint) sizeof(m_row.m_attr_value),
+                    &m_row.m_attr_value_length))
+  {
+    /* we don't expect internal threads to have connection attributes */
+    DBUG_ASSERT(pfs->m_thread_id != 0);
+
+    m_row.m_ordinal_position= ordinal;
+    m_row.m_process_id= pfs->m_thread_id;
+  }
+  else
+    return;
+
+  if (pfs->m_lock.end_optimistic_lock(& lock))
+    m_row_exists= true;
+}
+
+int table_session_connect::read_row_values(TABLE *table,
+                                         unsigned char *buf,
+                                         Field **fields,
+                                         bool read_all)
+{
+  Field *f;
+
+  if (unlikely(!m_row_exists))
+    return HA_ERR_RECORD_DELETED;
+
+  /* Set the null bits */
+  DBUG_ASSERT(table->s->null_bytes == 1);
+  buf[0]= 0;
+
+  for (; (f= *fields) ; fields++)
+  {
+    if (read_all || bitmap_is_set(table->read_set, f->field_index))
+    {
+      switch(f->field_index)
+      {
+      case FO_PROCESS_ID:
+        if (m_row.m_process_id != 0)
+          set_field_ulong(f, m_row.m_process_id);
+        else
+          f->set_null();
+        break;
+      case FO_ATTR_NAME:
+        set_field_varchar_utf8(f, m_row.m_attr_name,
+                               m_row.m_attr_name_length);
+        break;
+      case FO_ATTR_VALUE:
+        if (m_row.m_attr_value_length)
+          set_field_varchar_utf8(f, m_row.m_attr_value,
+                                 m_row.m_attr_value_length);
+        else
+          f->set_null();
+        break;
+      case FO_ORDINAL_POSITION:
+        set_field_ulong(f, m_row.m_ordinal_position);
+        break;
+      default:
+        DBUG_ASSERT(false);
+      }
+    }
+  }
+  return 0;
+}
+
+bool
+table_session_connect::thread_fits(PFS_thread *thread,
+                                 PFS_thread *current_thread)
+{
+  return true;
+}
+

=== added file 'storage/perfschema/table_session_connect.h'
--- a/storage/perfschema/table_session_connect.h	1970-01-01 00:00:00 +0000
+++ b/storage/perfschema/table_session_connect.h	2012-05-04 10:54:36 +0000
@@ -0,0 +1,77 @@
+/* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; version 2 of the License.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software Foundation,
+  51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
+
+#ifndef TABLE_SESSION_CONNECT_H
+#define TABLE_SESSION_CONNECT_H
+
+#include "pfs_column_types.h"
+#include "cursor_by_thread_connect_attr.h"
+#include "table_helper.h"
+
+#define MAX_ATTR_NAME_CHARS 32
+#define MAX_ATTR_VALUE_CHARS 1024
+#define MAX_UTF8_BYTES 6
+
+/** symbolic names for field offsets, keep in sync with field_types */
+enum field_offsets {
+  FO_PROCESS_ID,
+  FO_ATTR_NAME,
+  FO_ATTR_VALUE,
+  FO_ORDINAL_POSITION
+};
+
+/**
+  A row of PERFORMANCE_SCHEMA.SESSION_CONNECT_ATTRS and
+  PERFORMANCE_SCHEMA.SESSION_ACCOUNT_CONNECT_ATTRS.
+*/
+struct row_session_connect_attrs
+{
+  /** Column PROCESS_ID. */
+  ulong m_process_id;
+  /** Column ATTR_NAME. In UTF-8 */
+  char m_attr_name[MAX_ATTR_NAME_CHARS * MAX_UTF8_BYTES];
+  /** Length in bytes of @c m_attr_name. */
+  uint m_attr_name_length;
+  /** Column ATTR_VALUE. In UTF-8 */
+  char m_attr_value[MAX_ATTR_VALUE_CHARS * MAX_UTF8_BYTES];
+  /** Length in bytes of @c m_attr_name. */
+  uint m_attr_value_length;
+  /** Column ORDINAL_POSITION. */
+  ulong m_ordinal_position;
+};
+
+class table_session_connect : public cursor_by_thread_connect_attr
+{
+protected:
+  table_session_connect(const PFS_engine_table_share *share);
+
+public:
+  ~table_session_connect()
+  {}
+
+protected:
+  virtual void make_row(PFS_thread *pfs, uint ordinal);
+  virtual bool thread_fits(PFS_thread *thread, PFS_thread *current_thread);
+  virtual int read_row_values(TABLE *table, unsigned char *buf,
+                              Field **fields, bool read_all);
+protected:
+  /** Fields definition. */
+  static TABLE_FIELD_DEF m_field_def;
+  /** Current row. */
+  row_session_connect_attrs m_row;
+};
+
+/** @} */
+#endif

=== modified file 'storage/perfschema/table_session_connect_attrs.cc'
--- a/storage/perfschema/table_session_connect_attrs.cc	2012-03-30 16:01:10 +0000
+++ b/storage/perfschema/table_session_connect_attrs.cc	2012-05-04 10:54:36 +0000
@@ -33,19 +33,11 @@ table_session_connect_attrs::m_share=
   false /* checked */
 };
 
-
 PFS_engine_table* table_session_connect_attrs::create()
 {
   return new table_session_connect_attrs();
 }
 
-
 table_session_connect_attrs::table_session_connect_attrs()
-  : cursor_by_thread_connect_attr(&m_share)
+  : table_session_connect(&m_share)
 {}
-
-bool
-table_session_connect_attrs::thread_fits(PFS_thread *thread,
-                                                 PFS_thread *current_thread){
-  return true;
-}

=== modified file 'storage/perfschema/table_session_connect_attrs.h'
--- a/storage/perfschema/table_session_connect_attrs.h	2012-03-30 16:01:10 +0000
+++ b/storage/perfschema/table_session_connect_attrs.h	2012-05-04 10:54:36 +0000
@@ -16,14 +16,14 @@
 #ifndef TABLE_SESSION_CONNECT_ATTRS_H
 #define TABLE_SESSION_CONNECT_ATTRS_H
 
-#include "cursor_by_thread_connect_attr.h"
+#include "table_session_connect.h"
 /**
   \addtogroup Performance_schema_tables
   @{
 */
 
 /** Table PERFORMANCE_SCHEMA.SESSION_CONNECT_ATTRS. */
-class table_session_connect_attrs : public cursor_by_thread_connect_attr
+class table_session_connect_attrs : public table_session_connect
 {
 public:
   /** Table share */
@@ -39,9 +39,6 @@ public:
   {}
 
 private:
-  bool thread_fits(PFS_thread *thread, PFS_thread *current_thread);
-
-private:
   /** Table share lock. */
   static THR_LOCK m_table_lock;
 };

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk branch (Georgi.Kodinov:3836 to 3838) WL#5924Georgi Kodinov9 May