List:Commits« Previous MessageNext Message »
From:Magnus Blåudd Date:February 8 2011 12:57pm
Subject:bzr commit into mysql-5.1-telco-7.1 branch (magnus.blaudd:4087)
View as plain text  
#At file:///home/msvensson/mysql/tmp/LXzuyUtS_9/7.1/ based on revid:magnus.blaudd@stripped6jruuaa45z

 4087 Magnus Blåudd	2011-02-08 [merge]
      Merge 7.0 -> 7.1

    added:
      mysql-test/suite/ndb/r/ndb_create_table.result
      mysql-test/suite/ndb/t/ndb_create_table.test
    modified:
      sql/ha_ndbcluster.cc
      sql/ha_ndbcluster_binlog.cc
      sql/ha_ndbcluster_binlog.h
      storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
      storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
      storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp
      storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp
      storage/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp
=== added file 'mysql-test/suite/ndb/r/ndb_create_table.result'
--- a/mysql-test/suite/ndb/r/ndb_create_table.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/ndb/r/ndb_create_table.result	2011-02-07 15:07:22 +0000
@@ -0,0 +1,27 @@
+create table t1 (a int primary key)
+engine NDB
+comment='NDB_TABLE=NOLOGGING';
+show warnings;
+Level	Code	Message
+drop table t1;
+create table t1 (a int primary key)
+engine NDB
+comment='NDB_TABLE=NOLOGGING=1,NOLOGGING';
+show warnings;
+Level	Code	Message
+Warning	1478	NDB_TABLE= : modifier NOLOGGING specified twice
+drop table t1;
+create table t1 (a int primary key)
+engine NDB
+comment='NDB_TABLE=NOLOGGING=a,NOLOGGING';
+show warnings;
+Level	Code	Message
+Warning	1478	NDB_TABLE= : invalid value 'a' for NOLOGGING
+drop table t1;
+create table t1 (a int primary key)
+engine NDB
+comment='NDB_TABLE=NOLOGGING,NOLOGGINGa';
+show warnings;
+Level	Code	Message
+Warning	1478	NDB_TABLE= : unknown modifier: NOLOGGINGa
+drop table t1;

=== added file 'mysql-test/suite/ndb/t/ndb_create_table.test'
--- a/mysql-test/suite/ndb/t/ndb_create_table.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/ndb/t/ndb_create_table.test	2011-02-07 15:07:22 +0000
@@ -0,0 +1,31 @@
+-- source include/have_ndb.inc
+
+create table t1 (a int primary key)
+engine NDB
+comment='NDB_TABLE=NOLOGGING';
+show warnings;
+drop table t1;
+
+--disable_warnings
+create table t1 (a int primary key)
+engine NDB
+comment='NDB_TABLE=NOLOGGING=1,NOLOGGING';
+--enable_warnings
+show warnings;
+drop table t1;
+
+--disable_warnings
+create table t1 (a int primary key)
+engine NDB
+comment='NDB_TABLE=NOLOGGING=a,NOLOGGING';
+--enable_warnings
+show warnings;
+drop table t1;
+
+--disable_warnings
+create table t1 (a int primary key)
+engine NDB
+comment='NDB_TABLE=NOLOGGING,NOLOGGINGa';
+--enable_warnings
+show warnings;
+drop table t1;

=== modified file 'sql/ha_ndbcluster.cc'
--- a/sql/ha_ndbcluster.cc	2011-02-04 18:34:09 +0000
+++ b/sql/ha_ndbcluster.cc	2011-02-08 12:57:53 +0000
@@ -7234,6 +7234,269 @@ static int ndbcluster_rollback(handlerto
   DBUG_RETURN(res);
 }
 
+/**
+ * Support for create table/column modifiers
+ *   by exploiting the comment field
+ */
+struct NDB_Modifier
+{
+  enum { M_BOOL } m_type;
+  const char * m_name;
+  size_t m_name_len;
+  bool m_found;
+  union {
+    bool m_val_bool;
+#ifdef TODO__
+    int m_val_int;
+    struct {
+      const char * str;
+      size_t len;
+    } m_val_str;
+#endif
+  };
+};
+
+static const
+struct NDB_Modifier ndb_table_modifiers[] =
+{
+  { NDB_Modifier::M_BOOL, STRING_WITH_LEN("NOLOGGING"), 0, {0} },
+  { NDB_Modifier::M_BOOL, 0, 0, 0, {0} }
+};
+
+/**
+ * NDB_Modifiers
+ *
+ * This class implements a simple parser for getting modifiers out
+ *   of a string (e.g a comment field)
+ */
+class NDB_Modifiers
+{
+public:
+  NDB_Modifiers(const NDB_Modifier modifiers[]);
+  ~NDB_Modifiers();
+
+  /**
+   * parse string-with length (not necessarily NULL terminated)
+   */
+  int parse(THD* thd, const char * prefix, const char * str, size_t strlen);
+
+  /**
+   * Get modifier...returns NULL if unknown
+   */
+  const NDB_Modifier * get(const char * name) const;
+private:
+  uint m_len;
+  struct NDB_Modifier * m_modifiers;
+
+  int parse_modifier(THD *thd, const char * prefix,
+                     struct NDB_Modifier* m, const char * str);
+};
+
+static
+bool
+end_of_token(const char * str)
+{
+  return str[0] == 0 || str[0] == ' ' || str[0] == ',';
+}
+
+NDB_Modifiers::NDB_Modifiers(const NDB_Modifier modifiers[])
+{
+  for (m_len = 0; modifiers[m_len].m_name != 0; m_len++)
+  {}
+  m_modifiers = new NDB_Modifier[m_len];
+  memcpy(m_modifiers, modifiers, m_len * sizeof(NDB_Modifier));
+}
+
+NDB_Modifiers::~NDB_Modifiers()
+{
+  delete [] m_modifiers;
+}
+
+int
+NDB_Modifiers::parse_modifier(THD *thd,
+                              const char * prefix,
+                              struct NDB_Modifier* m,
+                              const char * str)
+{
+  if (m->m_found)
+  {
+    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+                        ER_ILLEGAL_HA_CREATE_OPTION,
+                        "%s : modifier %s specified twice",
+                        prefix, m->m_name);
+  }
+
+  switch(m->m_type){
+  case NDB_Modifier::M_BOOL:
+    if (end_of_token(str))
+    {
+      m->m_val_bool = true;
+      goto found;
+    }
+    if (str[0] != '=')
+      break;
+
+    str++;
+    if (str[0] == '1' && end_of_token(str+1))
+    {
+      m->m_val_bool = true;
+      goto found;
+    }
+
+    if (str[0] == '0' && end_of_token(str+1))
+    {
+      m->m_val_bool = false;
+      goto found;
+    }
+  }
+
+  {
+    const char * end = strpbrk(str, " ,");
+    if (end)
+    {
+      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+                          ER_ILLEGAL_HA_CREATE_OPTION,
+                          "%s : invalid value '%.*s' for %s",
+                          prefix, (int)(end - str), str, m->m_name);
+    }
+    else
+    {
+      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+                          ER_ILLEGAL_HA_CREATE_OPTION,
+                          "%s : invalid value '%s' for %s",
+                          prefix, str, m->m_name);
+    }
+  }
+  return -1;
+found:
+  m->m_found = true;
+  return 0;
+}
+
+int
+NDB_Modifiers::parse(THD *thd,
+                     const char * prefix,
+                     const char * _source,
+                     size_t _source_len)
+{
+  if (_source == 0 || _source_len == 0)
+    return 0;
+
+  const char * source = 0;
+
+  /**
+   * Check if _source is NULL-terminated
+   */
+  for (size_t i = 0; i<_source_len; i++)
+  {
+    if (_source[i] == 0)
+    {
+      source = _source;
+      break;
+    }
+  }
+
+  if (source == 0)
+  {
+    /**
+     * Make NULL terminated string so that strXXX-functions are safe
+     */
+    char * tmp = new char[_source_len+1];
+    if (tmp == 0)
+    {
+      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+                          ER_ILLEGAL_HA_CREATE_OPTION,
+                          "%s : unable to parse due to out of memory",
+                          prefix);
+      return -1;
+    }
+    memcpy(tmp, _source, _source_len);
+    tmp[_source_len] = 0;
+    source = tmp;
+  }
+
+  const char * pos = source;
+  if ((pos = strstr(pos, prefix)) == 0)
+  {
+    if (source != _source)
+      delete [] source;
+    return 0;
+  }
+
+  pos += strlen(prefix);
+
+  while (pos && pos[0] != 0 && pos[0] != ' ')
+  {
+    const char * end = strpbrk(pos, " ,"); // end of current modifier
+
+    for (uint i = 0; i < m_len; i++)
+    {
+      size_t l = m_modifiers[i].m_name_len;
+      if (strncmp(pos, m_modifiers[i].m_name, l) == 0)
+      {
+        /**
+         * Found modifier...
+         */
+
+        if (! (end_of_token(pos + l) || pos[l] == '='))
+          goto unknown;
+
+        pos += l;
+        int res = parse_modifier(thd, prefix, m_modifiers+i, pos);
+
+        if (res == -1)
+        {
+          /**
+           * We continue parsing even if modifier had error
+           */
+        }
+
+        goto next;
+      }
+    }
+
+    {
+  unknown:
+      if (end)
+      {
+        push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+                            ER_ILLEGAL_HA_CREATE_OPTION,
+                            "%s : unknown modifier: %.*s",
+                            prefix, (int)(end - pos), pos);
+      }
+      else
+      {
+        push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+                            ER_ILLEGAL_HA_CREATE_OPTION,
+                            "%s : unknown modifier: %s",
+                            prefix, pos);
+      }
+    }
+
+next:
+    pos = end;
+    if (pos && pos[0] == ',')
+      pos++;
+  }
+
+  if (source != _source)
+    delete [] source;
+
+  return 0;
+}
+
+const NDB_Modifier *
+NDB_Modifiers::get(const char * name) const
+{
+  for (uint i = 0; i < m_len; i++)
+  {
+    if (strcmp(name, m_modifiers[i].m_name) == 0)
+    {
+      return m_modifiers + i;
+    }
+  }
+  return 0;
+}
 
 /**
   Define NDB column based on Field.
@@ -7982,6 +8245,11 @@ int ha_ndbcluster::create(const char *na
     ndbtab_g.reinit();
   }
 
+  NDB_Modifiers table_modifiers(ndb_table_modifiers);
+  table_modifiers.parse(thd, "NDB_TABLE=", create_info->comment.str,
+                        create_info->comment.length);
+  const NDB_Modifier * mod_nologging = table_modifiers.get("NOLOGGING");
+
   if ((dict->beginSchemaTrans() == -1))
   {
     DBUG_PRINT("info", ("Failed to start schema transaction"));
@@ -8008,6 +8276,11 @@ int ha_ndbcluster::create(const char *na
     {
       tab.setLogging(FALSE);
     }
+
+    if (mod_nologging->m_found)
+    {
+      tab.setLogging(!mod_nologging->m_val_bool);
+    }
   }
   tab.setSingleUserMode(single_user_mode);
 
@@ -13671,6 +13944,16 @@ int ha_ndbcluster::check_if_supported_al
      {
        new_tab.setFragmentCount(part_info->no_parts);
      }
+
+     NDB_Modifiers table_modifiers(ndb_table_modifiers);
+     table_modifiers.parse(thd, "NDB_TABLE=", create_info->comment.str,
+                           create_info->comment.length);
+     const NDB_Modifier* mod_nologging = table_modifiers.get("NOLOGGING");
+
+     if (mod_nologging->m_found)
+     {
+       new_tab.setLogging(!mod_nologging->m_val_bool);
+     }
      
      if (dict->supportedAlterTable(*old_tab, new_tab))
      {

=== modified file 'sql/ha_ndbcluster_binlog.cc'
--- a/sql/ha_ndbcluster_binlog.cc	2011-02-04 17:52:38 +0000
+++ b/sql/ha_ndbcluster_binlog.cc	2011-02-08 10:07:46 +0000
@@ -3560,6 +3560,8 @@ add_ndb_binlog_index_err:
   Functions for start, stop, wait for ndbcluster binlog thread
 *********************************************************************/
 
+pthread_handler_t ndb_binlog_thread_func(void *arg);
+
 int ndbcluster_binlog_start()
 {
   DBUG_ENTER("ndbcluster_binlog_start");
@@ -5967,7 +5969,8 @@ enum Binlog_thread_state
 extern ulong opt_ndb_report_thresh_binlog_epoch_slip;
 extern ulong opt_ndb_report_thresh_binlog_mem_usage;
 
-pthread_handler_t ndb_binlog_thread_func(void *arg)
+pthread_handler_t
+ndb_binlog_thread_func(void *arg)
 {
   THD *thd; /* needs to be first for thread_stack */
   Ndb *i_ndb= 0;

=== modified file 'sql/ha_ndbcluster_binlog.h'
--- a/sql/ha_ndbcluster_binlog.h	2010-11-10 10:09:55 +0000
+++ b/sql/ha_ndbcluster_binlog.h	2011-02-08 10:09:53 +0000
@@ -249,16 +249,11 @@ ndbcluster_read_binlog_replication(THD *
 int ndb_create_table_from_engine(THD *thd, const char *db,
                                  const char *table_name);
 int ndbcluster_binlog_start();
-pthread_handler_t ndb_binlog_thread_func(void *arg);
 
-/*
-  table mysql.ndb_apply_status
-*/
 int ndbcluster_setup_binlog_table_shares(THD *thd);
 extern NDB_SHARE *ndb_apply_status_share;
 extern NDB_SHARE *ndb_schema_share;
 
-extern THD *injector_thd;
 extern my_bool ndb_binlog_running;
 extern my_bool ndb_binlog_tables_inited;
 extern my_bool ndb_binlog_is_ready;

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp	2011-01-30 20:56:00 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp	2011-02-07 13:21:49 +0000
@@ -943,6 +943,13 @@ ArrayPool<TupTriggerData> c_triggerPool;
   STATIC_CONST( DD = 1 );
   STATIC_CONST( DYN_BM_LEN_BITS = 8 );
   STATIC_CONST( DYN_BM_LEN_MASK = ((1 << DYN_BM_LEN_BITS) - 1));
+
+  /* Array length in the data structures like
+     dynTabDescriptor, dynVarSizeMask, dynFixSizeMask, etc.
+     1 for dynamic main memory data,
+     2 for dynamic main memory and dynamic disk data.
+  */
+  STATIC_CONST( NO_DYNAMICS = 2 );
   
   struct Tablerec {
     Tablerec(ArrayPool<TupTriggerData> & triggerPool) : 
@@ -965,7 +972,7 @@ ArrayPool<TupTriggerData> c_triggerPool;
       _after_ seeing all columns, hence must be separate from the readKeyArray
       et al descriptor, which is allocated before seeing columns.
     */
-    Uint32 dynTabDescriptor;
+    Uint32 dynTabDescriptor[2];
 
     /* Mask of variable-sized dynamic attributes. */
     Uint32* dynVarSizeMask[2];
@@ -1020,7 +1027,7 @@ ArrayPool<TupTriggerData> c_triggerPool;
     Uint16 m_no_of_disk_attributes;
     Uint16 noOfKeyAttr;
     Uint16 noOfCharsets;
-    Uint16 m_dyn_null_bits;
+    Uint16 m_dyn_null_bits[2];
 
     bool need_expand() const { 
       return m_no_of_attributes > m_attributes[MM].m_no_of_fixsize;
@@ -2825,7 +2832,8 @@ private:
                                  const Uint32* offset);
   void setupDynDescriptorReferences(Uint32 dynDescr,
                                     Tablerec* const regTabPtr,
-                                    const Uint32* offset);
+                                    const Uint32* offset,
+                                    Uint32 ind=0);
   void setUpKeyArray(Tablerec* regTabPtr);
   bool addfragtotab(Tablerec* regTabPtr, Uint32 fragId, Uint32 fragIndex);
   void deleteFragTab(Tablerec* regTabPtr, Uint32 fragId);

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp	2011-01-30 20:56:00 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp	2011-02-08 08:36:36 +0000
@@ -1246,6 +1246,146 @@ expand_dyn_part(Dbtup::KeyReqStruct::Var
   return (Uint32 *)dst_ptr;
 }
 
+static
+Uint32*
+shrink_dyn_part(Dbtup::KeyReqStruct::Var_data *dst,
+                Uint32 *dst_ptr,
+                const Dbtup::Tablerec* tabPtrP,
+                const Uint32 * tabDesc,
+                const Uint16* order,
+                Uint32 dynvar,
+                Uint32 dynfix,
+                Uint32 ind)
+{
+  /**
+   * Now build the dynamic part, if any.
+   * First look for any trailing all-NULL words of the bitmap; we do
+   * not need to store those.
+   */
+  assert((UintPtr(dst->m_dyn_data_ptr)&3) == 0);
+  char *dyn_src_ptr= dst->m_dyn_data_ptr;
+  Uint32 bm_len = tabPtrP->m_offsets[ind].m_dyn_null_words; // In words
+
+  /* If no dynamic variables, store nothing. */
+  assert(bm_len);
+  {
+    /**
+     * clear bm-len bits, so they won't incorrect indicate
+     *   a non-zero map
+     */
+    * ((Uint32 *)dyn_src_ptr) &= ~Uint32(Dbtup::DYN_BM_LEN_MASK);
+
+    Uint32 *bm_ptr= (Uint32 *)dyn_src_ptr + bm_len - 1;
+    while(*bm_ptr == 0)
+    {
+      bm_ptr--;
+      bm_len--;
+      if(bm_len == 0)
+        break;
+    }
+  }
+
+  if (bm_len)
+  {
+    /**
+     * Copy the bitmap, counting the number of variable sized
+     * attributes that are not NULL on the way.
+     */
+    Uint32 *dyn_dst_ptr= dst_ptr;
+    Uint32 dyn_var_count= 0;
+    const Uint32 *src_bm_ptr= (Uint32 *)(dyn_src_ptr);
+    Uint32 *dst_bm_ptr= (Uint32 *)dyn_dst_ptr;
+
+    /* ToDo: Put all of the dynattr code inside if(bm_len>0) { ... },
+     * split to separate function. */
+    Uint16 dyn_dst_data_offset= 0;
+    const Uint32 *dyn_bm_var_mask_ptr= tabPtrP->dynVarSizeMask[ind];
+    for(Uint16 i= 0; i< bm_len; i++)
+    {
+      Uint32 v= src_bm_ptr[i];
+      dyn_var_count+= BitmaskImpl::count_bits(v & *dyn_bm_var_mask_ptr++);
+      dst_bm_ptr[i]= v;
+    }
+
+    Uint32 tmp = *dyn_dst_ptr;
+    assert(bm_len <= Dbtup::DYN_BM_LEN_MASK);
+    * dyn_dst_ptr = (tmp & ~(Uint32)Dbtup::DYN_BM_LEN_MASK) | bm_len;
+    dyn_dst_ptr+= bm_len;
+    dyn_dst_data_offset= 2*dyn_var_count + 2;
+
+    Uint16 *dyn_src_off_array= dst->m_dyn_offset_arr_ptr;
+    Uint16 *dyn_src_lenoff_array=
+      dyn_src_off_array + dst->m_dyn_len_offset;
+    Uint16* dyn_dst_off_array = (Uint16*)dyn_dst_ptr;
+
+    /**
+     * Copy over the variable sized not-NULL attributes.
+     * Data offsets are counted from the start of the offset array, and
+     * we store one additional offset to be able to easily compute the
+     * data length as the difference between offsets.
+     */
+    Uint16 off_idx= 0;
+    for(Uint32 i= 0; i<dynvar; i++)
+    {
+      /**
+       * Note that we must use the destination (shrunken) bitmap here,
+       * as the source (expanded) bitmap may have been already clobbered
+       * (by offset data).
+       */
+      Uint32 attrDesc2 = tabDesc[order[dynfix+i]+1];
+      Uint32 pos = AttributeOffset::getNullFlagPos(attrDesc2);
+      if (bm_len > (pos >> 5) && BitmaskImpl::get(bm_len, dst_bm_ptr, pos))
+      {
+        dyn_dst_off_array[off_idx++]= dyn_dst_data_offset;
+        Uint32 dyn_src_off= dyn_src_off_array[i];
+        Uint32 dyn_len= dyn_src_lenoff_array[i] - dyn_src_off;
+        memmove(((char *)dyn_dst_ptr) + dyn_dst_data_offset,
+                dyn_src_ptr + dyn_src_off,
+                dyn_len);
+        dyn_dst_data_offset+= dyn_len;
+      }
+    }
+    /* If all dynamic attributes are NULL, we store nothing. */
+    dyn_dst_off_array[off_idx]= dyn_dst_data_offset;
+    assert(dyn_dst_off_array + off_idx == (Uint16*)dyn_dst_ptr+dyn_var_count);
+
+    char *dynvar_end_ptr= ((char *)dyn_dst_ptr) + dyn_dst_data_offset;
+    char *dyn_dst_data_ptr= (char *)(ALIGN_WORD(dynvar_end_ptr));
+
+    /**
+     * Zero out any padding bytes. Might not be strictly necessary,
+     * but seems cleaner than leaving random stuff in there.
+     */
+    bzero(dynvar_end_ptr, dyn_dst_data_ptr-dynvar_end_ptr);
+
+    /* *
+     * Copy over the fixed-sized not-NULL attributes.
+     * Note that attributes are copied in reverse order; this is to avoid
+     * overwriting not-yet-copied data, as the data is also stored in
+     * reverse order.
+     */
+    for(Uint32 i= dynfix; i > 0; )
+    {
+      i--;
+      Uint16 j= order[i];
+      Uint32 attrDesc2 = tabDesc[j+1];
+      Uint32 pos = AttributeOffset::getNullFlagPos(attrDesc2);
+      if(bm_len > (pos >>5 ) && BitmaskImpl::get(bm_len, dst_bm_ptr, pos))
+      {
+        Uint32 fixsize=
+          4*AttributeDescriptor::getSizeInWords(tabDesc[j]);
+        memmove(dyn_dst_data_ptr,
+                dyn_src_ptr + dyn_src_off_array[dynvar+i],
+                fixsize);
+        dyn_dst_data_ptr += fixsize;
+      }
+    }
+    dst_ptr = (Uint32*)dyn_dst_data_ptr;
+    assert((UintPtr(dst_ptr) & 3) == 0);
+  }
+  return (Uint32 *)dst_ptr;
+}
+
 /* ---------------------------------------------------------------- */
 /* ----------------------------- INSERT --------------------------- */
 /* ---------------------------------------------------------------- */
@@ -3338,6 +3478,7 @@ Dbtup::shrink_tuple(KeyReqStruct* req_st
   
   Uint32 *dst_ptr= ptr->get_end_of_fix_part_ptr(tabPtrP);
   Uint16* src_off_ptr= req_struct->var_pos_array;
+  order += mm_fix;
 
   sizes[MM] = 1;
   sizes[DD] = 0;
@@ -3364,140 +3505,15 @@ Dbtup::shrink_tuple(KeyReqStruct* req_st
       }
       *dst_off_ptr= off;
       dst_ptr = ALIGN_WORD(dst_data_ptr);
+      order += mm_vars; // Point to first dynfix entry
     }
     
     if (mm_dyns)
     {
-      /**
-       * Now build the dynamic part, if any.
-       * First look for any trailing all-NULL words of the bitmap; we do
-       * not need to store those.
-       */
-      ndbassert((UintPtr(dst->m_dyn_data_ptr)&3) == 0);
-      char *dyn_src_ptr= dst->m_dyn_data_ptr;
-      Uint32 bm_len = tabPtrP->m_offsets[MM].m_dyn_null_words; // In words
-
-      /* If no dynamic variables, store nothing. */
-      ndbassert(bm_len);
-      {
-        /**
-         * clear bm-len bits, so they won't incorrect indicate
-         *   a non-zero map
-         */
-        * ((Uint32 *)dyn_src_ptr) &= ~Uint32(DYN_BM_LEN_MASK);
-
-        Uint32 *bm_ptr= (Uint32 *)dyn_src_ptr + bm_len - 1;
-        while(*bm_ptr == 0)
-        {
-          bm_ptr--;
-          bm_len--;
-          if(bm_len == 0)
-            break;
-        }
-      }
-      
-      if (bm_len)
-      {
-        /**
-         * Copy the bitmap, counting the number of variable sized
-         * attributes that are not NULL on the way.
-         */
-        Uint32 *dyn_dst_ptr= dst_ptr;
-        Uint32 dyn_var_count= 0;
-        const Uint32 *src_bm_ptr= (Uint32 *)(dyn_src_ptr);
-        Uint32 *dst_bm_ptr= (Uint32 *)dyn_dst_ptr;
-        
-        /* ToDo: Put all of the dynattr code inside if(bm_len>0) { ... }, 
-         * split to separate function. */
-        Uint16 dyn_dst_data_offset= 0;
-        const Uint32 *dyn_bm_var_mask_ptr= tabPtrP->dynVarSizeMask[MM];
-        for(Uint16 i= 0; i< bm_len; i++)
-        {
-          Uint32 v= src_bm_ptr[i];
-          dyn_var_count+= BitmaskImpl::count_bits(v & *dyn_bm_var_mask_ptr++);
-          dst_bm_ptr[i]= v;
-        }
-        
-        Uint32 tmp = *dyn_dst_ptr;
-        ndbassert(bm_len <= DYN_BM_LEN_MASK);
-        * dyn_dst_ptr = (tmp & ~(Uint32)DYN_BM_LEN_MASK) | bm_len;
-        dyn_dst_ptr+= bm_len;
-        dyn_dst_data_offset= 2*dyn_var_count + 2;
-        
-        Uint16 *dyn_src_off_array= dst->m_dyn_offset_arr_ptr;
-        Uint16 *dyn_src_lenoff_array=
-          dyn_src_off_array + dst->m_dyn_len_offset;
-        Uint16* dyn_dst_off_array = (Uint16*)dyn_dst_ptr;
-        
-        /**
-         * Copy over the variable sized not-NULL attributes.
-         * Data offsets are counted from the start of the offset array, and
-         * we store one additional offset to be able to easily compute the
-         * data length as the difference between offsets.
-         */
-        Uint16 off_idx= 0;
-        order+= mm_fix+mm_vars;     // Point to first dynfix entry
-        for(Uint32 i= 0; i<mm_dynvar; i++)
-        {
-          /**
-           * Note that we must use the destination (shrunken) bitmap here, 
-           * as the source (expanded) bitmap may have been already clobbered 
-           * (by offset data).
-           */
-          Uint32 attrDesc2 = tabDesc[order[mm_dynfix+i]+1];
-          Uint32 pos = AttributeOffset::getNullFlagPos(attrDesc2);
-          if (bm_len > (pos >> 5) && BitmaskImpl::get(bm_len, dst_bm_ptr, pos))
-          {
-            dyn_dst_off_array[off_idx++]= dyn_dst_data_offset;
-            Uint32 dyn_src_off= dyn_src_off_array[i];
-            Uint32 dyn_len= dyn_src_lenoff_array[i] - dyn_src_off;
-            memmove(((char *)dyn_dst_ptr) + dyn_dst_data_offset,
-                    dyn_src_ptr + dyn_src_off,
-                    dyn_len);
-            dyn_dst_data_offset+= dyn_len;
-          }
-        }
-        /* If all dynamic attributes are NULL, we store nothing. */
-        dyn_dst_off_array[off_idx]= dyn_dst_data_offset;
-        ndbassert(dyn_dst_off_array + off_idx == (Uint16*)dyn_dst_ptr+dyn_var_count);
-        
-        char *dynvar_end_ptr= ((char *)dyn_dst_ptr) + dyn_dst_data_offset;
-        char *dyn_dst_data_ptr= (char *)(ALIGN_WORD(dynvar_end_ptr));
-        
-        /**
-         * Zero out any padding bytes. Might not be strictly necessary, 
-         * but seems cleaner than leaving random stuff in there.
-         */
-        bzero(dynvar_end_ptr, dyn_dst_data_ptr-dynvar_end_ptr);
-        
-        /* *
-         * Copy over the fixed-sized not-NULL attributes.
-         * Note that attributes are copied in reverse order; this is to avoid
-         * overwriting not-yet-copied data, as the data is also stored in 
-         * reverse order.
-         */
-        for(Uint32 i= mm_dynfix; i > 0; )
-        {
-          i--;
-          Uint16 j= order[i];
-          Uint32 attrDesc2 = tabDesc[j+1];
-          Uint32 pos = AttributeOffset::getNullFlagPos(attrDesc2);
-          if(bm_len > (pos >>5 ) && BitmaskImpl::get(bm_len, dst_bm_ptr, pos))
-          {
-            Uint32 fixsize=
-              4*AttributeDescriptor::getSizeInWords(tabDesc[j]);
-            memmove(dyn_dst_data_ptr,
-                    dyn_src_ptr + dyn_src_off_array[mm_dynvar+i],
-                    fixsize);
-            dyn_dst_data_ptr += fixsize;
-          }
-        }
-        dst_ptr = (Uint32*)dyn_dst_data_ptr;
-        ndbassert((UintPtr(dst_ptr) & 3) == 0);
-        
-        ndbassert(dyn_dst_data_ptr <= ((char*)ptr) + 8192);
-        ndbassert((UintPtr(dyn_dst_data_ptr) & 3) == 0);
-      }
+      dst_ptr = shrink_dyn_part(dst, dst_ptr, tabPtrP, tabDesc,
+                                order, mm_dynvar, mm_dynfix, MM);
+      ndbassert((char*)dst_ptr <= ((char*)ptr) + 8192);
+      order += mm_dynfix + mm_dynvar;
     }
     
     Uint32 varpart_len= Uint32(dst_ptr - varstart);

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp	2011-01-30 20:56:00 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp	2011-02-07 13:21:49 +0000
@@ -771,7 +771,8 @@ Dbtup::initTab(Tablerec* const regTabPtr
 
   regTabPtr->tabDescriptor = RNIL;
   regTabPtr->readKeyArray = RNIL;
-  regTabPtr->dynTabDescriptor = RNIL;
+  regTabPtr->dynTabDescriptor[MM] = RNIL;
+  regTabPtr->dynTabDescriptor[DD] = RNIL;
   regTabPtr->dynFixSizeMask[MM] = NULL;
   regTabPtr->dynVarSizeMask[MM] = NULL;
   regTabPtr->dynFixSizeMask[DD] = NULL;

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp	2011-02-01 23:27:25 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp	2011-02-07 13:21:49 +0000
@@ -111,11 +111,13 @@ Dbtup::execCREATE_TAB_REQ(Signal* signal
   regTabPtr.p->m_attributes[DD].m_no_of_dyn_var= 0;
 
   // Reserve space for bitmap length
-  regTabPtr.p->m_dyn_null_bits= DYN_BM_LEN_BITS;
+  regTabPtr.p->m_dyn_null_bits[MM]= DYN_BM_LEN_BITS;
+  regTabPtr.p->m_dyn_null_bits[DD]= DYN_BM_LEN_BITS;
   regTabPtr.p->noOfKeyAttr= req->noOfKeyAttr;
   regTabPtr.p->noOfCharsets= req->noOfCharsets;
   regTabPtr.p->m_no_of_attributes= req->noOfAttributes;
-  regTabPtr.p->dynTabDescriptor= RNIL;
+  regTabPtr.p->dynTabDescriptor[MM]= RNIL;
+  regTabPtr.p->dynTabDescriptor[DD]= RNIL;
 
   {
     Uint32 offset[10];
@@ -233,7 +235,7 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal*
      * xxx internally as 'null'.
      */
 
-    Uint32 null_pos= regTabPtr.p->m_dyn_null_bits;
+    Uint32 null_pos= regTabPtr.p->m_dyn_null_bits[ind];
 
     if (AttributeDescriptor::getArrayType(attrDescriptor)==NDB_ARRAYTYPE_FIXED)
     {
@@ -252,7 +254,7 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal*
          * ensure that the full size bitmap is stored when non-NULL.
          */
         null_pos+= bits;
-        regTabPtr.p->m_dyn_null_bits+= bits+1;
+        regTabPtr.p->m_dyn_null_bits[ind]+= bits+1;
       }
       else
       {
@@ -267,7 +269,7 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal*
 
         regTabPtr.p->m_attributes[ind].m_no_of_dyn_fix++;
         Uint32 null_bits= (bytes+3) >> 2;
-        regTabPtr.p->m_dyn_null_bits+= null_bits;
+        regTabPtr.p->m_dyn_null_bits[ind]+= null_bits;
       }
     }
     else
@@ -276,7 +278,7 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal*
   treat_as_varsize:
       jam();
       regTabPtr.p->m_attributes[ind].m_no_of_dyn_var++;
-      regTabPtr.p->m_dyn_null_bits++;
+      regTabPtr.p->m_dyn_null_bits[ind]++;
     }
     AttributeOffset::setNullFlagPos(attrDes2, null_pos);
 
@@ -326,17 +328,23 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal*
 #undef BTW
 
   {
-    /* Allocate  dynamic descriptor. */
-    Uint32 offset[3];
-    Uint32 allocSize= getDynTabDescrOffsets((regTabPtr.p->m_dyn_null_bits+31)>>5,
-                                            offset);
-    Uint32 dynTableDescriptorRef= allocTabDescr(allocSize);
-    if (dynTableDescriptorRef == RNIL)
+    /* Allocate  dynamic descriptors. */
+    for (Uint32 i = 0; i < NO_DYNAMICS; ++i)
     {
-      jam();
-      goto error;
+
+      Uint32 offset[3];
+      Uint32 allocSize= getDynTabDescrOffsets(
+                          (regTabPtr.p->m_dyn_null_bits[i]+31)>>5,
+                          offset);
+      Uint32 dynTableDescriptorRef= allocTabDescr(allocSize);
+      if (dynTableDescriptorRef == RNIL)
+      {
+        jam();
+        goto error;
+      }
+      setupDynDescriptorReferences(dynTableDescriptorRef,
+                                   regTabPtr.p, offset, i);
     }
-    setupDynDescriptorReferences(dynTableDescriptorRef, regTabPtr.p, offset);
   }
 
   /* Compute table aggregate metadata. */
@@ -1049,7 +1057,7 @@ Dbtup::handleAlterTablePrepare(Signal *s
       in ALTER_TAB_REQ[commit];
     */
     Uint32 charsetIndex= regTabPtr->noOfCharsets;
-    Uint32 dyn_nullbits= regTabPtr->m_dyn_null_bits;
+    Uint32 dyn_nullbits= regTabPtr->m_dyn_null_bits[MM];
     if (dyn_nullbits == 0)
     {
       jam();
@@ -1182,7 +1190,7 @@ Dbtup::handleAlterTableCommit(Signal *si
     regTabPtr->m_attributes[MM].m_no_of_dyn_fix= regAlterTabOpPtr.p->noOfDynFix;
     regTabPtr->m_attributes[MM].m_no_of_dyn_var= regAlterTabOpPtr.p->noOfDynVar;
     regTabPtr->m_attributes[MM].m_no_of_dynamic= regAlterTabOpPtr.p->noOfDynamic;
-    regTabPtr->m_dyn_null_bits= regAlterTabOpPtr.p->noOfDynNullBits;
+    regTabPtr->m_dyn_null_bits[MM]= regAlterTabOpPtr.p->noOfDynNullBits;
 
     /* Install the new (larger) table descriptors. */
     setUpDescriptorReferences(regAlterTabOpPtr.p->tableDescriptor,
@@ -1342,13 +1350,17 @@ Dbtup::handleCharsetPos(Uint32 csNumber,
 void
 Dbtup::computeTableMetaData(Tablerec *regTabPtr)
 {
-  if (regTabPtr->m_dyn_null_bits == DYN_BM_LEN_BITS)
+  Uint32 dyn_null_words[2];
+
+  for (Uint32 i = 0; i < NO_DYNAMICS; ++i)
   {
-    regTabPtr->m_dyn_null_bits = 0;
+    if (regTabPtr->m_dyn_null_bits[i] == DYN_BM_LEN_BITS)
+    {
+      regTabPtr->m_dyn_null_bits[i] = 0;
+    }
+    dyn_null_words[i] = (regTabPtr->m_dyn_null_bits[i]+31)>>5;
+    regTabPtr->m_offsets[i].m_dyn_null_words = dyn_null_words[i];
   }
-  
-  Uint32 dyn_null_words= (regTabPtr->m_dyn_null_bits+31)>>5;
-  regTabPtr->m_offsets[MM].m_dyn_null_words= dyn_null_words;
 
   /* Compute the size of the static headers. */
   Uint32 pos[2] = { 0, 0 };
@@ -1403,7 +1415,6 @@ Dbtup::computeTableMetaData(Tablerec *re
     We also compute the dynamic bitmasks here.
   */
   Uint32 *tabDesc= (Uint32*)(tableDescriptor+regTabPtr->tabDescriptor);
-  Uint32 *dynDesc= (Uint32*)(tableDescriptor+regTabPtr->dynTabDescriptor);
   Uint32 fix_size[2]= {0, 0};
   Uint32 var_size[2]= {0, 0};
   Uint32 dyn_size[2]= {0, 0};
@@ -1413,8 +1424,11 @@ Dbtup::computeTableMetaData(Tablerec *re
   Uint32 dynamic_count= 0;
   regTabPtr->blobAttributeMask.clear();
   regTabPtr->notNullAttributeMask.clear();
-  bzero(regTabPtr->dynVarSizeMask[MM], dyn_null_words<<2);
-  bzero(regTabPtr->dynFixSizeMask[MM], dyn_null_words<<2);
+  for (Uint32 i = 0; i < NO_DYNAMICS; ++i)
+  {
+    bzero(regTabPtr->dynVarSizeMask[i], dyn_null_words[i]<<2);
+    bzero(regTabPtr->dynFixSizeMask[i], dyn_null_words[i]<<2);
+  }
 
   for(Uint32 i= 0; i<regTabPtr->m_no_of_attributes; i++)
   {
@@ -1474,10 +1488,10 @@ Dbtup::computeTableMetaData(Tablerec *re
 
           off= dynfix_count++ + regTabPtr->m_attributes[ind].m_no_of_dyn_var;
           while(size_in_words-- > 0)
-	  {
-	    BitmaskImpl::set(dyn_null_words, 
-			     regTabPtr->dynFixSizeMask[ind], null_pos++);
-	  }
+          {
+            BitmaskImpl::set(dyn_null_words[ind],
+                             regTabPtr->dynFixSizeMask[ind], null_pos++);
+          }
         }
         else
           off= 0;                               // Bit type
@@ -1487,7 +1501,7 @@ Dbtup::computeTableMetaData(Tablerec *re
       treat_as_varsize:
         jam();
         off= dynvar_count++;
-	BitmaskImpl::set(dyn_null_words, regTabPtr->dynVarSizeMask[ind], null_pos);
+        BitmaskImpl::set(dyn_null_words[ind], regTabPtr->dynVarSizeMask[ind], null_pos);
       }
     }
     AttributeOffset::setOffset(attrDes2, off);
@@ -1646,12 +1660,13 @@ void Dbtup::setUpDescriptorReferences(Ui
 
 void Dbtup::setupDynDescriptorReferences(Uint32 dynDescr,
                                          Tablerec* const regTabPtr,
-                                         const Uint32* offset)
+                                         const Uint32* offset,
+                                         Uint32 ind)
 {
-  regTabPtr->dynTabDescriptor= dynDescr;
+  regTabPtr->dynTabDescriptor[ind]= dynDescr;
   Uint32* desc= &tableDescriptor[dynDescr].tabDescr;
-  regTabPtr->dynVarSizeMask[MM] = desc+offset[0];
-  regTabPtr->dynFixSizeMask[MM] = desc+offset[1];
+  regTabPtr->dynVarSizeMask[ind] = desc+offset[0];
+  regTabPtr->dynFixSizeMask[ind] = desc+offset[1];
 }
 
 Uint32
@@ -1832,14 +1847,19 @@ void Dbtup::releaseTabDescr(Tablerec* co
     releaseTabDescr(descriptor);
   }
 
-  descriptor= regTabPtr->dynTabDescriptor;
-  if(descriptor != RNIL)
+  /* Release dynamic descriptor, etc for mm and disk data. */
+
+  for (Uint16 i = 0; i < NO_DYNAMICS; ++i)
   {
     jam();
-    regTabPtr->dynTabDescriptor= RNIL;
-    regTabPtr->dynVarSizeMask[MM]= NULL;
-    regTabPtr->dynFixSizeMask[MM]= NULL;
-    releaseTabDescr(descriptor);
+    descriptor= regTabPtr->dynTabDescriptor[i];
+    if(descriptor != RNIL)
+    {
+      regTabPtr->dynTabDescriptor[i]= RNIL;
+      regTabPtr->dynVarSizeMask[i]= NULL;
+      regTabPtr->dynFixSizeMask[i]= NULL;
+      releaseTabDescr(descriptor);
+    }
   }
 }
 

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp	2011-02-01 21:05:11 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp	2011-02-07 13:21:49 +0000
@@ -344,9 +344,9 @@ Dbtup::verifytabdes()
       }
       {
         Uint32 offset[3];
-        Uint32 MaskSize = (ptr.p->m_dyn_null_bits + 31) >> 5;
+        Uint32 MaskSize = (ptr.p->m_dyn_null_bits[MM] + 31) >> 5;
         const Uint32 alloc = getDynTabDescrOffsets(MaskSize, offset);
-        const Uint32 desc = ptr.p->dynTabDescriptor;
+        const Uint32 desc = ptr.p->dynTabDescriptor[MM];
         Uint32 size = alloc;
         if (size % ZTD_FREE_SIZE != 0)
           size += ZTD_FREE_SIZE - size % ZTD_FREE_SIZE;

No bundle (reason: revision is a merge).
Thread
bzr commit into mysql-5.1-telco-7.1 branch (magnus.blaudd:4087) Magnus Blåudd8 Feb