Loading mysql-test/r/rpl_ndb_basic.result +25 −0 Original line number Diff line number Diff line Loading @@ -122,3 +122,28 @@ select * from t1 order by nid; nid nom prenom 1 DEAD ABC1 DROP TABLE t1; CREATE TABLE t1 (c1 INT KEY) ENGINE=NDB; INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); ALTER TABLE t1 ADD c2 INT; SELECT * FROM t1 ORDER BY c1; c1 c2 1 NULL 2 NULL 3 NULL 4 NULL 5 NULL 6 NULL 7 NULL 8 NULL 9 NULL 10 NULL ALTER TABLE t1 CHANGE c2 c2 TEXT CHARACTER SET utf8; ALTER TABLE t1 CHANGE c2 c2 BLOB; SELECT * FROM t1 ORDER BY c1 LIMIT 5; c1 c2 1 NULL 2 NULL 3 NULL 4 NULL 5 NULL DROP TABLE t1; mysql-test/t/disabled.def +2 −2 Original line number Diff line number Diff line Loading @@ -25,9 +25,9 @@ rpl_ndb_2innodb : BUG#19004 2006-03-22 tomas ndb: partition by range an rpl_ndb_2myisam : BUG#19004 2006-03-22 tomas ndb: partition by range and update hangs rpl_ndb_auto_inc : BUG#17086 2006-02-16 jmiller CR: auto_increment_increment and auto_increment_offset produce duplicate key er rpl_ndb_ddl : result file needs update + test needs to checked rpl_ndb_innodb2ndb : BUG#18094 2006-03-16 mats Slave caches invalid table definition after atlters causes select failure rpl_ndb_innodb2ndb : BUG#17400 2006-04-19 tomas Cluster Replication: delete & update of rows in table without pk fails on slave. rpl_ndb_log : BUG#18947 2006-03-21 tomas CRBR: order in binlog of create table and insert (on different table) not determ rpl_ndb_myisam2ndb : BUG#18094 2006-03-16 mats Slave caches invalid table definition after atlters causes select failure rpl_ndb_myisam2ndb : BUG#17400 2006-04-19 tomas Cluster Replication: delete & update of rows in table without pk fails on slave. rpl_ndb_relay_space : BUG#16993 2006-02-16 jmiller RBR: ALTER TABLE ZEROFILL AUTO_INCREMENT is not replicated correctly rpl_switch_stm_row_mixed : BUG#18590 2006-03-28 brian rpl_row_basic_7ndb : BUG#17400 2006-04-09 brian Cluster Replication: delete & update of rows in table without pk fails on slave. Loading mysql-test/t/rpl_ndb_basic.test +31 −0 Original line number Diff line number Diff line Loading @@ -143,6 +143,37 @@ COMMIT; --connection slave select * from t1 order by nid; # cleanup --connection master DROP TABLE t1; # # BUG#18094 # Slave caches invalid table definition after atlters causes select failure # --connection master CREATE TABLE t1 (c1 INT KEY) ENGINE=NDB; INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); ALTER TABLE t1 ADD c2 INT; --sync_slave_with_master connection slave; SELECT * FROM t1 ORDER BY c1; connection master; ALTER TABLE t1 CHANGE c2 c2 TEXT CHARACTER SET utf8; ALTER TABLE t1 CHANGE c2 c2 BLOB; --sync_slave_with_master connection slave; # here we would get error 1412 prior to bug SELECT * FROM t1 ORDER BY c1 LIMIT 5; # cleanup --connection master DROP TABLE t1; Loading sql/ha_ndbcluster.cc +58 −26 Original line number Diff line number Diff line Loading @@ -466,7 +466,7 @@ void ha_ndbcluster::no_uncommitted_rows_reset(THD *thd) # The mapped error code */ int ha_ndbcluster::invalidate_dictionary_cache(bool global) int ha_ndbcluster::invalidate_dictionary_cache(bool global, const NDBTAB *ndbtab) { NDBDICT *dict= get_ndb()->getDictionary(); DBUG_ENTER("invalidate_dictionary_cache"); Loading Loading @@ -494,20 +494,17 @@ int ha_ndbcluster::invalidate_dictionary_cache(bool global) DBUG_PRINT("info", ("Released ndbcluster mutex")); } #endif const NDBTAB *tab= dict->getTable(m_tabname); if (!tab) DBUG_RETURN(1); if (tab->getObjectStatus() == NdbDictionary::Object::Invalid) if (!ndbtab) { // Global cache has already been invalidated dict->removeCachedTable(m_tabname); global= FALSE; DBUG_PRINT("info", ("global: %d", global)); ndbtab= dict->getTable(m_tabname); if (!ndbtab) DBUG_RETURN(1); } else dict->invalidateTable(m_tabname); dict->invalidateTable(ndbtab); table_share->version= 0L; /* Free when thread is ready */ } else if (ndbtab) dict->removeCachedTable(ndbtab); else dict->removeCachedTable(m_tabname); Loading Loading @@ -564,7 +561,7 @@ int ha_ndbcluster::ndb_err(NdbTransaction *trans) table_list.alias= table_list.table_name= m_tabname; close_cached_tables(current_thd, 0, &table_list); invalidate_dictionary_cache(TRUE); invalidate_dictionary_cache(TRUE, m_table); if (err.code==284) { Loading Loading @@ -1041,7 +1038,7 @@ int ha_ndbcluster::get_metadata(const char *path) // Check if thread has stale local cache if (tab->getObjectStatus() == NdbDictionary::Object::Invalid) { invalidate_dictionary_cache(FALSE); invalidate_dictionary_cache(FALSE, tab); if (!(tab= dict->getTable(m_tabname))) ERR_RETURN(dict->getNdbError()); DBUG_PRINT("info", ("Table schema version: %d", tab->getObjectVersion())); Loading @@ -1064,7 +1061,7 @@ int ha_ndbcluster::get_metadata(const char *path) if (!invalidating_ndb_table) { DBUG_PRINT("info", ("Invalidating table")); invalidate_dictionary_cache(TRUE); invalidate_dictionary_cache(TRUE, tab); invalidating_ndb_table= TRUE; } else Loading @@ -1091,7 +1088,7 @@ int ha_ndbcluster::get_metadata(const char *path) DBUG_RETURN(error); m_table_version= tab->getObjectVersion(); m_table= (void *)tab; m_table= tab; m_table_info= NULL; // Set in external lock DBUG_RETURN(open_indexes(ndb, table, FALSE)); Loading Loading @@ -1150,7 +1147,7 @@ int ha_ndbcluster::table_changed(const void *pack_frm_data, uint pack_frm_len) // Check if thread has stale local cache if (orig_tab->getObjectStatus() == NdbDictionary::Object::Invalid) { dict->removeCachedTable(m_tabname); dict->removeCachedTable(orig_tab); if (!(orig_tab= dict->getTable(m_tabname))) ERR_RETURN(dict->getNdbError()); } Loading Loading @@ -1219,13 +1216,31 @@ int ha_ndbcluster::add_index_handle(THD *thd, NDBDICT *dict, KEY *key_info, int error= 0; NDB_INDEX_TYPE idx_type= get_index_type_from_table(index_no); m_index[index_no].type= idx_type; DBUG_ENTER("ha_ndbcluster::get_index_handle"); DBUG_ENTER("ha_ndbcluster::add_index_handle"); DBUG_PRINT("enter", ("table %s", m_tabname)); if (idx_type != PRIMARY_KEY_INDEX && idx_type != UNIQUE_INDEX) { DBUG_PRINT("info", ("Get handle to index %s", index_name)); const NDBINDEX *index= dict->getIndex(index_name, m_tabname); if (!index) ERR_RETURN(dict->getNdbError()); const NDBINDEX *index; do { index= dict->getIndex(index_name, m_tabname); if (!index) ERR_RETURN(dict->getNdbError()); DBUG_PRINT("info", ("index: 0x%x id: %d version: %d.%d status: %d", index, index->getObjectId(), index->getObjectVersion() & 0xFFFFFF, index->getObjectVersion() >> 24, index->getObjectStatus())); if (index->getObjectStatus() != NdbDictionary::Object::Retrieved) { dict->removeCachedIndex(index); continue; } break; } while (1); m_index[index_no].index= (void *) index; // ordered index - add stats NDB_INDEX_DATA& d=m_index[index_no]; Loading Loading @@ -1254,8 +1269,25 @@ int ha_ndbcluster::add_index_handle(THD *thd, NDBDICT *dict, KEY *key_info, m_has_unique_index= TRUE; strxnmov(unique_index_name, FN_LEN, index_name, unique_suffix, NullS); DBUG_PRINT("info", ("Get handle to unique_index %s", unique_index_name)); const NDBINDEX *index= dict->getIndex(unique_index_name, m_tabname); if (!index) ERR_RETURN(dict->getNdbError()); const NDBINDEX *index; do { index= dict->getIndex(unique_index_name, m_tabname); if (!index) ERR_RETURN(dict->getNdbError()); DBUG_PRINT("info", ("index: 0x%x id: %d version: %d.%d status: %d", index, index->getObjectId(), index->getObjectVersion() & 0xFFFFFF, index->getObjectVersion() >> 24, index->getObjectStatus())); if (index->getObjectStatus() != NdbDictionary::Object::Retrieved) { dict->removeCachedIndex(index); continue; } break; } while (1); m_index[index_no].unique_index= (void *) index; error= fix_unique_index_attr_order(m_index[index_no], index, key_info); } Loading Loading @@ -3954,7 +3986,7 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) if ((trans && tab->getObjectStatus() != NdbDictionary::Object::Retrieved) || tab->getObjectStatus() == NdbDictionary::Object::Invalid) { invalidate_dictionary_cache(FALSE); invalidate_dictionary_cache(FALSE, tab); if (!(tab= dict->getTable(m_tabname, &tab_info))) ERR_RETURN(dict->getNdbError()); DBUG_PRINT("info", ("Table schema version: %d", Loading @@ -3970,7 +4002,7 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) } if (m_table != (void *)tab) { m_table= (void *)tab; m_table= tab; m_table_version = tab->getObjectVersion(); if (!(my_errno= open_indexes(ndb, table, FALSE))) DBUG_RETURN(my_errno); Loading Loading @@ -4990,7 +5022,7 @@ int ha_ndbcluster::rename_table(const char *from, const char *to) // Check if thread has stale local cache if (orig_tab->getObjectStatus() == NdbDictionary::Object::Invalid) { dict->removeCachedTable(m_tabname); dict->removeCachedTable(orig_tab); if (!(orig_tab= dict->getTable(m_tabname))) ERR_RETURN(dict->getNdbError()); } Loading @@ -5002,7 +5034,7 @@ int ha_ndbcluster::rename_table(const char *from, const char *to) DBUG_ASSERT(r == 0); } #endif m_table= (void *)orig_tab; m_table= orig_tab; // Change current database to that of target table set_dbname(to); ndb->setDatabaseName(m_dbname); Loading Loading @@ -9988,7 +10020,7 @@ bool ha_ndbcluster::get_no_parts(const char *name, uint *no_parts) // Check if thread has stale local cache if (tab->getObjectStatus() == NdbDictionary::Object::Invalid) { invalidate_dictionary_cache(FALSE); invalidate_dictionary_cache(FALSE, tab); if (!(tab= dict->getTable(m_tabname))) ERR_BREAK(dict->getNdbError(), err); } Loading sql/ha_ndbcluster.h +3 −2 Original line number Diff line number Diff line Loading @@ -778,7 +778,8 @@ static void set_tabname(const char *pathname, char *tabname); void print_results(); ulonglong get_auto_increment(); int invalidate_dictionary_cache(bool global); int invalidate_dictionary_cache(bool global, const NdbDictionary::Table *ndbtab); int ndb_err(NdbTransaction*); bool uses_blob_value(); Loading Loading @@ -816,7 +817,7 @@ static void set_tabname(const char *pathname, char *tabname); NdbTransaction *m_active_trans; NdbScanOperation *m_active_cursor; void *m_table; const NdbDictionary::Table *m_table; int m_table_version; void *m_table_info; char m_dbname[FN_HEADLEN]; Loading Loading
mysql-test/r/rpl_ndb_basic.result +25 −0 Original line number Diff line number Diff line Loading @@ -122,3 +122,28 @@ select * from t1 order by nid; nid nom prenom 1 DEAD ABC1 DROP TABLE t1; CREATE TABLE t1 (c1 INT KEY) ENGINE=NDB; INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); ALTER TABLE t1 ADD c2 INT; SELECT * FROM t1 ORDER BY c1; c1 c2 1 NULL 2 NULL 3 NULL 4 NULL 5 NULL 6 NULL 7 NULL 8 NULL 9 NULL 10 NULL ALTER TABLE t1 CHANGE c2 c2 TEXT CHARACTER SET utf8; ALTER TABLE t1 CHANGE c2 c2 BLOB; SELECT * FROM t1 ORDER BY c1 LIMIT 5; c1 c2 1 NULL 2 NULL 3 NULL 4 NULL 5 NULL DROP TABLE t1;
mysql-test/t/disabled.def +2 −2 Original line number Diff line number Diff line Loading @@ -25,9 +25,9 @@ rpl_ndb_2innodb : BUG#19004 2006-03-22 tomas ndb: partition by range an rpl_ndb_2myisam : BUG#19004 2006-03-22 tomas ndb: partition by range and update hangs rpl_ndb_auto_inc : BUG#17086 2006-02-16 jmiller CR: auto_increment_increment and auto_increment_offset produce duplicate key er rpl_ndb_ddl : result file needs update + test needs to checked rpl_ndb_innodb2ndb : BUG#18094 2006-03-16 mats Slave caches invalid table definition after atlters causes select failure rpl_ndb_innodb2ndb : BUG#17400 2006-04-19 tomas Cluster Replication: delete & update of rows in table without pk fails on slave. rpl_ndb_log : BUG#18947 2006-03-21 tomas CRBR: order in binlog of create table and insert (on different table) not determ rpl_ndb_myisam2ndb : BUG#18094 2006-03-16 mats Slave caches invalid table definition after atlters causes select failure rpl_ndb_myisam2ndb : BUG#17400 2006-04-19 tomas Cluster Replication: delete & update of rows in table without pk fails on slave. rpl_ndb_relay_space : BUG#16993 2006-02-16 jmiller RBR: ALTER TABLE ZEROFILL AUTO_INCREMENT is not replicated correctly rpl_switch_stm_row_mixed : BUG#18590 2006-03-28 brian rpl_row_basic_7ndb : BUG#17400 2006-04-09 brian Cluster Replication: delete & update of rows in table without pk fails on slave. Loading
mysql-test/t/rpl_ndb_basic.test +31 −0 Original line number Diff line number Diff line Loading @@ -143,6 +143,37 @@ COMMIT; --connection slave select * from t1 order by nid; # cleanup --connection master DROP TABLE t1; # # BUG#18094 # Slave caches invalid table definition after atlters causes select failure # --connection master CREATE TABLE t1 (c1 INT KEY) ENGINE=NDB; INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); ALTER TABLE t1 ADD c2 INT; --sync_slave_with_master connection slave; SELECT * FROM t1 ORDER BY c1; connection master; ALTER TABLE t1 CHANGE c2 c2 TEXT CHARACTER SET utf8; ALTER TABLE t1 CHANGE c2 c2 BLOB; --sync_slave_with_master connection slave; # here we would get error 1412 prior to bug SELECT * FROM t1 ORDER BY c1 LIMIT 5; # cleanup --connection master DROP TABLE t1; Loading
sql/ha_ndbcluster.cc +58 −26 Original line number Diff line number Diff line Loading @@ -466,7 +466,7 @@ void ha_ndbcluster::no_uncommitted_rows_reset(THD *thd) # The mapped error code */ int ha_ndbcluster::invalidate_dictionary_cache(bool global) int ha_ndbcluster::invalidate_dictionary_cache(bool global, const NDBTAB *ndbtab) { NDBDICT *dict= get_ndb()->getDictionary(); DBUG_ENTER("invalidate_dictionary_cache"); Loading Loading @@ -494,20 +494,17 @@ int ha_ndbcluster::invalidate_dictionary_cache(bool global) DBUG_PRINT("info", ("Released ndbcluster mutex")); } #endif const NDBTAB *tab= dict->getTable(m_tabname); if (!tab) DBUG_RETURN(1); if (tab->getObjectStatus() == NdbDictionary::Object::Invalid) if (!ndbtab) { // Global cache has already been invalidated dict->removeCachedTable(m_tabname); global= FALSE; DBUG_PRINT("info", ("global: %d", global)); ndbtab= dict->getTable(m_tabname); if (!ndbtab) DBUG_RETURN(1); } else dict->invalidateTable(m_tabname); dict->invalidateTable(ndbtab); table_share->version= 0L; /* Free when thread is ready */ } else if (ndbtab) dict->removeCachedTable(ndbtab); else dict->removeCachedTable(m_tabname); Loading Loading @@ -564,7 +561,7 @@ int ha_ndbcluster::ndb_err(NdbTransaction *trans) table_list.alias= table_list.table_name= m_tabname; close_cached_tables(current_thd, 0, &table_list); invalidate_dictionary_cache(TRUE); invalidate_dictionary_cache(TRUE, m_table); if (err.code==284) { Loading Loading @@ -1041,7 +1038,7 @@ int ha_ndbcluster::get_metadata(const char *path) // Check if thread has stale local cache if (tab->getObjectStatus() == NdbDictionary::Object::Invalid) { invalidate_dictionary_cache(FALSE); invalidate_dictionary_cache(FALSE, tab); if (!(tab= dict->getTable(m_tabname))) ERR_RETURN(dict->getNdbError()); DBUG_PRINT("info", ("Table schema version: %d", tab->getObjectVersion())); Loading @@ -1064,7 +1061,7 @@ int ha_ndbcluster::get_metadata(const char *path) if (!invalidating_ndb_table) { DBUG_PRINT("info", ("Invalidating table")); invalidate_dictionary_cache(TRUE); invalidate_dictionary_cache(TRUE, tab); invalidating_ndb_table= TRUE; } else Loading @@ -1091,7 +1088,7 @@ int ha_ndbcluster::get_metadata(const char *path) DBUG_RETURN(error); m_table_version= tab->getObjectVersion(); m_table= (void *)tab; m_table= tab; m_table_info= NULL; // Set in external lock DBUG_RETURN(open_indexes(ndb, table, FALSE)); Loading Loading @@ -1150,7 +1147,7 @@ int ha_ndbcluster::table_changed(const void *pack_frm_data, uint pack_frm_len) // Check if thread has stale local cache if (orig_tab->getObjectStatus() == NdbDictionary::Object::Invalid) { dict->removeCachedTable(m_tabname); dict->removeCachedTable(orig_tab); if (!(orig_tab= dict->getTable(m_tabname))) ERR_RETURN(dict->getNdbError()); } Loading Loading @@ -1219,13 +1216,31 @@ int ha_ndbcluster::add_index_handle(THD *thd, NDBDICT *dict, KEY *key_info, int error= 0; NDB_INDEX_TYPE idx_type= get_index_type_from_table(index_no); m_index[index_no].type= idx_type; DBUG_ENTER("ha_ndbcluster::get_index_handle"); DBUG_ENTER("ha_ndbcluster::add_index_handle"); DBUG_PRINT("enter", ("table %s", m_tabname)); if (idx_type != PRIMARY_KEY_INDEX && idx_type != UNIQUE_INDEX) { DBUG_PRINT("info", ("Get handle to index %s", index_name)); const NDBINDEX *index= dict->getIndex(index_name, m_tabname); if (!index) ERR_RETURN(dict->getNdbError()); const NDBINDEX *index; do { index= dict->getIndex(index_name, m_tabname); if (!index) ERR_RETURN(dict->getNdbError()); DBUG_PRINT("info", ("index: 0x%x id: %d version: %d.%d status: %d", index, index->getObjectId(), index->getObjectVersion() & 0xFFFFFF, index->getObjectVersion() >> 24, index->getObjectStatus())); if (index->getObjectStatus() != NdbDictionary::Object::Retrieved) { dict->removeCachedIndex(index); continue; } break; } while (1); m_index[index_no].index= (void *) index; // ordered index - add stats NDB_INDEX_DATA& d=m_index[index_no]; Loading Loading @@ -1254,8 +1269,25 @@ int ha_ndbcluster::add_index_handle(THD *thd, NDBDICT *dict, KEY *key_info, m_has_unique_index= TRUE; strxnmov(unique_index_name, FN_LEN, index_name, unique_suffix, NullS); DBUG_PRINT("info", ("Get handle to unique_index %s", unique_index_name)); const NDBINDEX *index= dict->getIndex(unique_index_name, m_tabname); if (!index) ERR_RETURN(dict->getNdbError()); const NDBINDEX *index; do { index= dict->getIndex(unique_index_name, m_tabname); if (!index) ERR_RETURN(dict->getNdbError()); DBUG_PRINT("info", ("index: 0x%x id: %d version: %d.%d status: %d", index, index->getObjectId(), index->getObjectVersion() & 0xFFFFFF, index->getObjectVersion() >> 24, index->getObjectStatus())); if (index->getObjectStatus() != NdbDictionary::Object::Retrieved) { dict->removeCachedIndex(index); continue; } break; } while (1); m_index[index_no].unique_index= (void *) index; error= fix_unique_index_attr_order(m_index[index_no], index, key_info); } Loading Loading @@ -3954,7 +3986,7 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) if ((trans && tab->getObjectStatus() != NdbDictionary::Object::Retrieved) || tab->getObjectStatus() == NdbDictionary::Object::Invalid) { invalidate_dictionary_cache(FALSE); invalidate_dictionary_cache(FALSE, tab); if (!(tab= dict->getTable(m_tabname, &tab_info))) ERR_RETURN(dict->getNdbError()); DBUG_PRINT("info", ("Table schema version: %d", Loading @@ -3970,7 +4002,7 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) } if (m_table != (void *)tab) { m_table= (void *)tab; m_table= tab; m_table_version = tab->getObjectVersion(); if (!(my_errno= open_indexes(ndb, table, FALSE))) DBUG_RETURN(my_errno); Loading Loading @@ -4990,7 +5022,7 @@ int ha_ndbcluster::rename_table(const char *from, const char *to) // Check if thread has stale local cache if (orig_tab->getObjectStatus() == NdbDictionary::Object::Invalid) { dict->removeCachedTable(m_tabname); dict->removeCachedTable(orig_tab); if (!(orig_tab= dict->getTable(m_tabname))) ERR_RETURN(dict->getNdbError()); } Loading @@ -5002,7 +5034,7 @@ int ha_ndbcluster::rename_table(const char *from, const char *to) DBUG_ASSERT(r == 0); } #endif m_table= (void *)orig_tab; m_table= orig_tab; // Change current database to that of target table set_dbname(to); ndb->setDatabaseName(m_dbname); Loading Loading @@ -9988,7 +10020,7 @@ bool ha_ndbcluster::get_no_parts(const char *name, uint *no_parts) // Check if thread has stale local cache if (tab->getObjectStatus() == NdbDictionary::Object::Invalid) { invalidate_dictionary_cache(FALSE); invalidate_dictionary_cache(FALSE, tab); if (!(tab= dict->getTable(m_tabname))) ERR_BREAK(dict->getNdbError(), err); } Loading
sql/ha_ndbcluster.h +3 −2 Original line number Diff line number Diff line Loading @@ -778,7 +778,8 @@ static void set_tabname(const char *pathname, char *tabname); void print_results(); ulonglong get_auto_increment(); int invalidate_dictionary_cache(bool global); int invalidate_dictionary_cache(bool global, const NdbDictionary::Table *ndbtab); int ndb_err(NdbTransaction*); bool uses_blob_value(); Loading Loading @@ -816,7 +817,7 @@ static void set_tabname(const char *pathname, char *tabname); NdbTransaction *m_active_trans; NdbScanOperation *m_active_cursor; void *m_table; const NdbDictionary::Table *m_table; int m_table_version; void *m_table_info; char m_dbname[FN_HEADLEN]; Loading