List:Commits« Previous MessageNext Message »
From:Frazer Clement Date:July 26 2010 12:31pm
Subject:bzr push into mysql-5.1-telco-6.2 branch (frazer:3115 to 3116) Bug#54788
View as plain text  
 3116 Frazer Clement	2010-07-26
      Bug#54788 DROP DATABASE can remove hidden blob tables without removing parent tables
      
      1) Drop database code should not attempt to directly drop Blob part tables
         (NDB$BLOB_T_C)
      2) NdbApi should not allow Blob part tables to be dropped by applications
         This is true for normal NdbApi usage, but not for the 'Global dict cache' 
         mode used by MySQLD.
      3) NdbApi should allow a main table with dropped Blob part tables to be 
         'opened', so that it can be dropped.  Otherwise we are left with an
         indestructable table.
      
      A new testcase is added which reproduces the problem fixed by (1 + 2) above.
      There is no automated testcase for fix 3, but it has been tested manually.

    modified:
      mysql-test/suite/ndb/r/ndb_database.result
      mysql-test/suite/ndb/t/ndb_database.test
      sql/ha_ndbcluster.cc
      storage/ndb/src/ndbapi/NdbDictionary.cpp
      storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp
      storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp
 3115 Frazer Clement	2010-07-14
      Fix ndb_gis in 6.2

    modified:
      mysql-test/suite/ndb/r/ndb_gis.result
      mysql-test/suite/ndb/t/ndb_gis.test
=== modified file 'mysql-test/suite/ndb/r/ndb_database.result'
--- a/mysql-test/suite/ndb/r/ndb_database.result	2007-06-27 12:28:02 +0000
+++ b/mysql-test/suite/ndb/r/ndb_database.result	2010-07-26 10:35:07 +0000
@@ -11,3 +11,45 @@ use mysqltest;
 show tables;
 Tables_in_mysqltest
 drop database mysqltest;
+create database newdb;
+create table newdb.t1 (a int primary key) engine=myisam;
+create table newdb.t1 (a int primary key,
+b1  blob,
+b2  blob,
+b3  blob,
+b4  blob,
+b5  blob,
+b6  blob,
+b7  blob,
+b8  blob,
+b9  blob,
+b10 blob,
+b11 blob,
+b12 blob,
+b13 blob,
+b14 blob,
+b15 blob,
+b16 blob,
+b17 blob,
+b18 blob,
+b19 blob,
+b20 blob,
+b21 blob,
+b22 blob,
+b23 blob,
+b24 blob,
+b25 blob,
+b26 blob,
+b27 blob,
+b28 blob,
+b29 blob) engine = ndb;
+drop database newdb;
+create database newdb;
+use newdb;
+show tables;
+Tables_in_newdb
+create table newdb.t1(a int primary key) engine=ndb;
+show tables;
+Tables_in_newdb
+t1
+drop database newdb;

=== modified file 'mysql-test/suite/ndb/t/ndb_database.test'
--- a/mysql-test/suite/ndb/t/ndb_database.test	2007-07-04 20:38:53 +0000
+++ b/mysql-test/suite/ndb/t/ndb_database.test	2010-07-26 10:35:07 +0000
@@ -22,3 +22,66 @@ show tables;
 drop database mysqltest;
 
 # End of 4.1 tests
+
+
+
+#
+# bug# 54788 DROP DATABASE can remove hidden blob tables without removing parent tables
+#
+# Dropping a database on a server where Ndb tables with Blobs were
+# 'occluded' by a local table can result in Blob part tables being
+# deleted, but the main table not being deleted.
+#
+--connection server1
+# Create database with occluding table t1
+create database newdb;
+create table newdb.t1 (a int primary key) engine=myisam;
+
+--connection server2
+# Create Ndb table with Blobs
+# Lots of Blobs to increase prob. that Ndb-list-objects returns a
+# Blob part table before the main table.
+create table newdb.t1 (a int primary key,
+                       b1  blob,
+                       b2  blob,
+                       b3  blob,
+                       b4  blob,
+                       b5  blob,
+                       b6  blob,
+                       b7  blob,
+                       b8  blob,
+                       b9  blob,
+                       b10 blob,
+                       b11 blob,
+                       b12 blob,
+                       b13 blob,
+                       b14 blob,
+                       b15 blob,
+                       b16 blob,
+                       b17 blob,
+                       b18 blob,
+                       b19 blob,
+                       b20 blob,
+                       b21 blob,
+                       b22 blob,
+                       b23 blob,
+                       b24 blob,
+                       b25 blob,
+                       b26 blob,
+                       b27 blob,
+                       b28 blob,
+                       b29 blob) engine = ndb;
+
+--connection server1
+drop database newdb;
+
+--connection server2
+# Now check that the table is gone
+create database newdb;
+use newdb;
+show tables;
+
+# Check that we can reuse the table name etc.
+create table newdb.t1(a int primary key) engine=ndb;
+show tables;
+drop database newdb;
\ No newline at end of file

=== modified file 'sql/ha_ndbcluster.cc'
--- a/sql/ha_ndbcluster.cc	2010-07-14 10:51:55 +0000
+++ b/sql/ha_ndbcluster.cc	2010-07-26 10:35:07 +0000
@@ -7290,7 +7290,10 @@ int ndbcluster_drop_database_impl(THD *t
     DBUG_PRINT("info", ("Found %s/%s in NDB", elmt.database, elmt.name));     
     
     // Add only tables that belongs to db
-    if (my_strcasecmp(system_charset_info, elmt.database, dbname))
+    // Ignore Blob part tables - they are deleted when their table
+    // is deleted.
+    if (my_strcasecmp(system_charset_info, elmt.database, dbname) ||
+        IS_NDB_BLOB_PREFIX(elmt.name))
       continue;
     DBUG_PRINT("info", ("%s must be dropped", elmt.name));     
     drop_list.push_back(thd->strdup(elmt.name));

=== modified file 'storage/ndb/src/ndbapi/NdbDictionary.cpp'
--- a/storage/ndb/src/ndbapi/NdbDictionary.cpp	2010-03-01 13:15:18 +0000
+++ b/storage/ndb/src/ndbapi/NdbDictionary.cpp	2010-07-26 10:35:07 +0000
@@ -1649,22 +1649,58 @@ int 
 NdbDictionary::Dictionary::createTable(const Table & t)
 {
   DBUG_ENTER("NdbDictionary::Dictionary::createTable");
-  DBUG_RETURN(m_impl.createTable(NdbTableImpl::getImpl(t)));
+  if (likely(! is_ndb_blob_table(t.getName())))
+  {
+    DBUG_RETURN(m_impl.createTable(NdbTableImpl::getImpl(t)));
+  }
+  else
+  {
+    /* 4307 : Invalid table name */
+    m_impl.m_error.code = 4307;
+    DBUG_RETURN(-1);
+  }
 }
 
 int
 NdbDictionary::Dictionary::dropTable(Table & t){
-  return m_impl.dropTable(NdbTableImpl::getImpl(t));
+  if (likely(! is_ndb_blob_table(t.getName())))
+  {
+    return m_impl.dropTable(NdbTableImpl::getImpl(t));
+  }
+  else
+  {
+    /* 4249 : Invalid table */
+    m_impl.m_error.code = 4249;
+    return -1;
+  }
 }
 
 int
 NdbDictionary::Dictionary::dropTableGlobal(const Table & t){
-  return m_impl.dropTableGlobal(NdbTableImpl::getImpl(t));
+  if (likely(! is_ndb_blob_table(t.getName())))
+  {
+    return m_impl.dropTableGlobal(NdbTableImpl::getImpl(t));
+  }
+  else
+  {
+    /* 4249 : Invalid table */
+    m_impl.m_error.code = 4249;
+    return -1;
+  }
 }
 
 int
 NdbDictionary::Dictionary::dropTable(const char * name){
-  return m_impl.dropTable(name);
+  if (likely(! is_ndb_blob_table(name)))
+  {
+    return m_impl.dropTable(name);
+  }
+  else
+  {
+    /* 4307 : Invalid table name */
+    m_impl.m_error.code = 4307;
+    return -1;
+  }
 }
 
 bool

=== modified file 'storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp'
--- a/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp	2010-03-01 13:15:18 +0000
+++ b/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp	2010-07-26 10:35:07 +0000
@@ -74,6 +74,19 @@ is_ndb_blob_table(const NdbTableImpl* t)
   return is_ndb_blob_table(t->m_internalName.c_str());
 }
 
+bool
+ignore_broken_blob_tables()
+{
+  /* To be able to fix broken blob tables, we must be able
+   * to ignore them when getting the table description
+   */
+  char envBuf[10];
+  const char* v = NdbEnv_GetEnv("NDB_FORCE_IGNORE_BROKEN_BLOB",
+                                envBuf,
+                                10);
+  return (v != NULL && *v != 0 && *v != '0' && *v != 'n' && *v != 'N');
+}
+
 //#define EVENT_DEBUG
 
 /**
@@ -1491,7 +1504,7 @@ int
 NdbDictionaryImpl::getBlobTables(NdbTableImpl &t)
 {
   unsigned n= t.m_noOfBlobs;
-  DBUG_ENTER("NdbDictionaryImpl::addBlobTables");
+  DBUG_ENTER("NdbDictionaryImpl::getBlobTables");
   // optimized for blob column being the last one
   // and not looking for more than one if not neccessary
   for (unsigned i = t.m_columns.size(); i > 0 && n > 0;) {
@@ -1507,7 +1520,14 @@ NdbDictionaryImpl::getBlobTables(NdbTabl
     NdbTableImpl* bt =
       m_receiver.getTable(btname_internal, m_ndb.usingFullyQualifiedNames());
     if (bt == NULL)
+    {
+      if (ignore_broken_blob_tables())
+      {
+        DBUG_PRINT("info", ("Blob table %s not found, continuing", btname));
+        continue;
+      }
       DBUG_RETURN(-1);
+    }
 
     // TODO check primary id/version when returned by DICT
 
@@ -2601,13 +2621,24 @@ NdbDictInterface::compChangeMask(const N
   DBUG_ENTER("compChangeMask");
   bool found_varpart;
   change_mask= 0;
+  Uint32 old_sz= old_impl.m_columns.size();
+  Uint32 sz= impl.m_columns.size();
 
   /* These are the supported properties that may be altered. */
   DBUG_PRINT("info", ("old_impl.m_internalName='%s' impl.m_internalName='%s'",
                       old_impl.m_internalName.c_str(),
                       impl.m_internalName.c_str()));
   if(impl.m_internalName != old_impl.m_internalName)
+  {
+    if (unlikely(is_ndb_blob_table(old_impl.m_externalName.c_str()) ||
+                 is_ndb_blob_table(impl.m_externalName.c_str())))
+    {
+      /* Attempt to alter to/from Blob part table name */
+      DBUG_PRINT("info", ("Attempt to alter to/from Blob part table name"));
+      goto invalid_alter_table;
+    }
     AlterTableReq::setNameFlag(change_mask, true);
+  }
   if(!impl.m_frm.equal(old_impl.m_frm))
     AlterTableReq::setFrmFlag(change_mask, true);
   if(!impl.m_fd.equal(old_impl.m_fd))
@@ -2620,8 +2651,6 @@ NdbDictInterface::compChangeMask(const N
     AlterTableReq::setTsFlag(change_mask, true);
 
   /* No other property can be changed in alter table. */
-  Uint32 old_sz= old_impl.m_columns.size();
-  Uint32 sz= impl.m_columns.size();
   if(impl.m_fragmentCount != old_impl.m_fragmentCount ||
      impl.m_logging != old_impl.m_logging ||
      impl.m_temporary != old_impl.m_temporary ||
@@ -5658,13 +5687,25 @@ NdbDictionaryImpl::createDefaultNdbRecor
        */
       if (col->getBlobType() && col->getPartSize() != 0)
       {
-        assert(col->m_blobTable != NULL);
-
-        int res= createDefaultNdbRecord(col->m_blobTable, NULL);
-        if (res != 0)
+        if (likely(col->m_blobTable != NULL))
         {
-          free(pkMask);
-          DBUG_RETURN(-1);
+          int res= createDefaultNdbRecord(col->m_blobTable, NULL);
+          if (res != 0)
+          {
+            free(pkMask);
+            DBUG_RETURN(-1);
+          }
+        } 
+        else
+        {
+          if (!ignore_broken_blob_tables())
+          {
+            assert(false);
+            /* 4263 - Invalid blob attributes or invalid blob parts table */
+            m_error.code = 4263;
+            free(pkMask);
+            DBUG_RETURN(-1);
+          }
         }
       } 
     }

=== modified file 'storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp'
--- a/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp	2010-03-01 13:15:18 +0000
+++ b/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp	2010-07-26 10:35:07 +0000
@@ -1139,6 +1139,21 @@ inline
 NdbTableImpl *
 NdbDictionaryImpl::getTableGlobal(const char * table_name)
 {
+  if (unlikely(strchr(table_name, '$') != 0)) {
+    if (is_ndb_blob_table(table_name)) 
+    {
+      /* Could attempt to get the Blob table here, but
+       * instead we will generate an error.
+       * The non-global getTable() calls can fetch Blob
+       * tables correctly if necessary.
+       *
+       * 4307 Invalid Table name
+       */
+      m_error.code = 4307;
+      return NULL;
+    }
+  }
+
   const BaseString internal_tabname(m_ndb.internalize_table_name(table_name));
   return fetchGlobalTableImplRef(InitTable(internal_tabname));
 }


Attachment: [text/bzr-bundle] bzr/frazer@mysql.com-20100726103507-fr67922iumzd5czd.bundle
Thread
bzr push into mysql-5.1-telco-6.2 branch (frazer:3115 to 3116) Bug#54788Frazer Clement26 Jul