Commit 1476b484 authored by mskold@mysql.com's avatar mskold@mysql.com

Additional fixes for WL#1892

parent 93bfec62
...@@ -8,6 +8,8 @@ a b c ...@@ -8,6 +8,8 @@ a b c
2 two two 2 two two
alter table t1 drop index c; alter table t1 drop index c;
select * from t1 where c = 'two'; select * from t1 where c = 'two';
ERROR HY000: Table definition has changed, please retry transaction
select * from t1 where c = 'two';
a b c a b c
2 two two 2 two two
drop table t1; drop table t1;
......
...@@ -17,6 +17,8 @@ select * from t1 where c = 'two'; ...@@ -17,6 +17,8 @@ select * from t1 where c = 'two';
connection server1; connection server1;
alter table t1 drop index c; alter table t1 drop index c;
connection server2; connection server2;
--error 1412
select * from t1 where c = 'two';
select * from t1 where c = 'two'; select * from t1 where c = 'two';
connection server1; connection server1;
drop table t1; drop table t1;
......
...@@ -974,22 +974,25 @@ int ha_ndbcluster::get_metadata(const char *path) ...@@ -974,22 +974,25 @@ int ha_ndbcluster::get_metadata(const char *path)
if (cmp_frm(tab, pack_data, pack_length)) if (cmp_frm(tab, pack_data, pack_length))
{ {
if (!invalidating_ndb_table) if (m_share->state != NSS_ALTERED)
{ {
DBUG_PRINT("info", ("Invalidating table")); if (!invalidating_ndb_table)
invalidate_dictionary_cache(TRUE); {
invalidating_ndb_table= TRUE; DBUG_PRINT("info", ("Invalidating table"));
} invalidate_dictionary_cache(TRUE);
else invalidating_ndb_table= TRUE;
{ }
DBUG_PRINT("error", else
("metadata, pack_length: %d getFrmLength: %d memcmp: %d", {
pack_length, tab->getFrmLength(), DBUG_PRINT("error",
memcmp(pack_data, tab->getFrmData(), pack_length))); ("metadata, pack_length: %d getFrmLength: %d memcmp: %d",
DBUG_DUMP("pack_data", (char*)pack_data, pack_length); pack_length, tab->getFrmLength(),
DBUG_DUMP("frm", (char*)tab->getFrmData(), tab->getFrmLength()); memcmp(pack_data, tab->getFrmData(), pack_length)));
error= HA_ERR_TABLE_DEF_CHANGED; DBUG_DUMP("pack_data", (char*)pack_data, pack_length);
invalidating_ndb_table= FALSE; DBUG_DUMP("frm", (char*)tab->getFrmData(), tab->getFrmLength());
error= HA_ERR_TABLE_DEF_CHANGED;
invalidating_ndb_table= FALSE;
}
} }
} }
else else
...@@ -1044,6 +1047,36 @@ static int fix_unique_index_attr_order(NDB_INDEX_DATA &data, ...@@ -1044,6 +1047,36 @@ static int fix_unique_index_attr_order(NDB_INDEX_DATA &data,
DBUG_RETURN(0); DBUG_RETURN(0);
} }
int ha_ndbcluster::table_changed(const void *pack_frm_data, uint pack_frm_len)
{
Ndb *ndb;
NDBDICT *dict;
const NDBTAB *orig_tab;
NdbDictionary::Table new_tab;
int result;
DBUG_ENTER("ha_ndbcluster::table_changed");
DBUG_PRINT("info", ("Modifying frm for table %s", m_tabname));
if (check_ndb_connection())
DBUG_RETURN(my_errno= HA_ERR_NO_CONNECTION);
ndb= get_ndb();
dict= ndb->getDictionary();
if (!(orig_tab= dict->getTable(m_tabname)))
ERR_RETURN(dict->getNdbError());
// Check if thread has stale local cache
if (orig_tab->getObjectStatus() == NdbDictionary::Object::Invalid)
{
dict->removeCachedTable(m_tabname);
if (!(orig_tab= dict->getTable(m_tabname)))
ERR_RETURN(dict->getNdbError());
}
new_tab= *orig_tab;
new_tab.setFrm(pack_frm_data, pack_frm_len);
if (dict->alterTable(new_tab) != 0)
ERR_RETURN(dict->getNdbError());
DBUG_RETURN(0);
}
/* /*
Create all the indexes for a table. Create all the indexes for a table.
If any index should fail to be created, If any index should fail to be created,
...@@ -4280,6 +4313,46 @@ int ha_ndbcluster::create(const char *name, ...@@ -4280,6 +4313,46 @@ int ha_ndbcluster::create(const char *name,
DBUG_RETURN(my_errno); DBUG_RETURN(my_errno);
} }
int ha_ndbcluster::create_handler_files(const char *file)
{
const char *name;
Ndb* ndb;
const NDBTAB *tab;
const void *data, *pack_data;
uint length, pack_length;
int error= 0;
DBUG_ENTER("create_handler_files");
if (!(ndb= get_ndb()))
DBUG_RETURN(HA_ERR_NO_CONNECTION);
NDBDICT *dict= ndb->getDictionary();
if (!(tab= dict->getTable(m_tabname)))
DBUG_RETURN(0); // Must be a create, ignore since frm is saved in create
name= table->s->normalized_path.str;
DBUG_PRINT("enter", ("m_tabname: %s, path: %s", m_tabname, name));
if (readfrm(name, &data, &length) ||
packfrm(data, length, &pack_data, &pack_length))
{
DBUG_PRINT("info", ("Missing frm for %s", m_tabname));
my_free((char*)data, MYF(MY_ALLOW_ZERO_PTR));
my_free((char*)pack_data, MYF(MY_ALLOW_ZERO_PTR));
DBUG_RETURN(1);
}
if (cmp_frm(tab, pack_data, pack_length))
{
DBUG_PRINT("info", ("Table %s has changed, altering frm in ndb",
m_tabname));
error= table_changed(pack_data, pack_length);
}
my_free((char*)data, MYF(MY_ALLOW_ZERO_PTR));
my_free((char*)pack_data, MYF(MY_ALLOW_ZERO_PTR));
DBUG_RETURN(error);
}
int ha_ndbcluster::create_index(const char *name, KEY *key_info, int ha_ndbcluster::create_index(const char *name, KEY *key_info,
NDB_INDEX_TYPE idx_type, uint idx_no) NDB_INDEX_TYPE idx_type, uint idx_no)
{ {
...@@ -4407,7 +4480,7 @@ int ha_ndbcluster::add_index(TABLE *table_arg, ...@@ -4407,7 +4480,7 @@ int ha_ndbcluster::add_index(TABLE *table_arg,
if((error= create_index(key_info[idx].name, key, idx_type, idx))) if((error= create_index(key_info[idx].name, key, idx_type, idx)))
break; break;
} }
m_share->state= NSS_ALTERED;
DBUG_RETURN(error); DBUG_RETURN(error);
} }
...@@ -4442,6 +4515,7 @@ int ha_ndbcluster::prepare_drop_index(TABLE *table_arg, ...@@ -4442,6 +4515,7 @@ int ha_ndbcluster::prepare_drop_index(TABLE *table_arg,
THD *thd= current_thd; THD *thd= current_thd;
Thd_ndb *thd_ndb= get_thd_ndb(thd); Thd_ndb *thd_ndb= get_thd_ndb(thd);
Ndb *ndb= thd_ndb->ndb; Ndb *ndb= thd_ndb->ndb;
m_share->state= NSS_ALTERED;
DBUG_RETURN(renumber_indexes(ndb, table_arg)); DBUG_RETURN(renumber_indexes(ndb, table_arg));
} }
...@@ -4452,14 +4526,11 @@ int ha_ndbcluster::final_drop_index(TABLE *table_arg) ...@@ -4452,14 +4526,11 @@ int ha_ndbcluster::final_drop_index(TABLE *table_arg)
{ {
DBUG_ENTER("ha_ndbcluster::final_drop_index"); DBUG_ENTER("ha_ndbcluster::final_drop_index");
DBUG_PRINT("info", ("ha_ndbcluster::final_drop_index")); DBUG_PRINT("info", ("ha_ndbcluster::final_drop_index"));
int error= 0;
// Really drop indexes // Really drop indexes
THD *thd= current_thd; THD *thd= current_thd;
Thd_ndb *thd_ndb= get_thd_ndb(thd); Thd_ndb *thd_ndb= get_thd_ndb(thd);
Ndb *ndb= thd_ndb->ndb; Ndb *ndb= thd_ndb->ndb;
error= drop_indexes(ndb, table_arg); DBUG_RETURN(drop_indexes(ndb, table_arg));
DBUG_RETURN(error);
} }
/* /*
...@@ -5282,9 +5353,13 @@ int ndbcluster_find_all_files(THD *thd) ...@@ -5282,9 +5353,13 @@ int ndbcluster_find_all_files(THD *thd)
} }
else if (cmp_frm(ndbtab, pack_data, pack_length)) else if (cmp_frm(ndbtab, pack_data, pack_length))
{ {
discover= 1; NDB_SHARE *share= get_share(key, 0, false);
sql_print_information("NDB: mismatch in frm for %s.%s, discovering...", if (!share || share->state != NSS_ALTERED)
elmt.database, elmt.name); {
discover= 1;
sql_print_information("NDB: mismatch in frm for %s.%s, discovering...",
elmt.database, elmt.name);
}
} }
my_free((char*) data, MYF(MY_ALLOW_ZERO_PTR)); my_free((char*) data, MYF(MY_ALLOW_ZERO_PTR));
my_free((char*) pack_data, MYF(MY_ALLOW_ZERO_PTR)); my_free((char*) pack_data, MYF(MY_ALLOW_ZERO_PTR));
...@@ -6451,7 +6526,7 @@ NDB_SHARE *ndbcluster_get_share(const char *key, TABLE *table, ...@@ -6451,7 +6526,7 @@ NDB_SHARE *ndbcluster_get_share(const char *key, TABLE *table,
MEM_ROOT *old_root= *root_ptr; MEM_ROOT *old_root= *root_ptr;
init_sql_alloc(&share->mem_root, 1024, 0); init_sql_alloc(&share->mem_root, 1024, 0);
*root_ptr= &share->mem_root; // remember to reset before return *root_ptr= &share->mem_root; // remember to reset before return
share->state= NSS_INITIAL;
/* enough space for key, db, and table_name */ /* enough space for key, db, and table_name */
share->key= alloc_root(*root_ptr, 2 * (length + 1)); share->key= alloc_root(*root_ptr, 2 * (length + 1));
share->key_length= length; share->key_length= length;
...@@ -9003,13 +9078,6 @@ static void ndb_set_fragmentation(NDBTAB &tab, TABLE *form, uint pk_length) ...@@ -9003,13 +9078,6 @@ static void ndb_set_fragmentation(NDBTAB &tab, TABLE *form, uint pk_length)
bool ha_ndbcluster::check_if_incompatible_data(HA_CREATE_INFO *info, bool ha_ndbcluster::check_if_incompatible_data(HA_CREATE_INFO *info,
uint table_changes) uint table_changes)
{ {
/*
TODO: Remove the dummy return below, when cluster gets
signal from alter table when only .frm is changed. Cluster
needs it to manage the copies.
*/
return COMPATIBLE_DATA_NO;
if (table_changes != IS_EQUAL_YES) if (table_changes != IS_EQUAL_YES)
return COMPATIBLE_DATA_NO; return COMPATIBLE_DATA_NO;
......
...@@ -80,10 +80,12 @@ typedef union { const NdbRecAttr *rec; NdbBlob *blob; void *ptr; } NdbValue; ...@@ -80,10 +80,12 @@ typedef union { const NdbRecAttr *rec; NdbBlob *blob; void *ptr; } NdbValue;
typedef enum { typedef enum {
NSS_INITIAL= 0, NSS_INITIAL= 0,
NSS_DROPPED NSS_DROPPED,
NSS_ALTERED
} NDB_SHARE_STATE; } NDB_SHARE_STATE;
typedef struct st_ndbcluster_share { typedef struct st_ndbcluster_share {
NDB_SHARE_STATE state;
MEM_ROOT mem_root; MEM_ROOT mem_root;
THR_LOCK lock; THR_LOCK lock;
pthread_mutex_t mutex; pthread_mutex_t mutex;
...@@ -97,7 +99,6 @@ typedef struct st_ndbcluster_share { ...@@ -97,7 +99,6 @@ typedef struct st_ndbcluster_share {
char *table_name; char *table_name;
#ifdef HAVE_NDB_BINLOG #ifdef HAVE_NDB_BINLOG
uint32 flags; uint32 flags;
NDB_SHARE_STATE state;
NdbEventOperation *op; NdbEventOperation *op;
NdbEventOperation *op_old; // for rename table NdbEventOperation *op_old; // for rename table
char *old_names; // for rename table char *old_names; // for rename table
...@@ -587,6 +588,7 @@ class ha_ndbcluster: public handler ...@@ -587,6 +588,7 @@ class ha_ndbcluster: public handler
int rename_table(const char *from, const char *to); int rename_table(const char *from, const char *to);
int delete_table(const char *name); int delete_table(const char *name);
int create(const char *name, TABLE *form, HA_CREATE_INFO *info); int create(const char *name, TABLE *form, HA_CREATE_INFO *info);
int create_handler_files(const char *file);
int get_default_no_partitions(ulonglong max_rows); int get_default_no_partitions(ulonglong max_rows);
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **store_lock(THD *thd,
THR_LOCK_DATA **to, THR_LOCK_DATA **to,
...@@ -674,6 +676,7 @@ private: ...@@ -674,6 +676,7 @@ private:
int create_index(const char *name, KEY *key_info, int create_index(const char *name, KEY *key_info,
NDB_INDEX_TYPE idx_type, uint idx_no); NDB_INDEX_TYPE idx_type, uint idx_no);
int drop_ndb_index(const char *name); int drop_ndb_index(const char *name);
int table_changed(const void *pack_frm_data, uint pack_frm_len);
// Index list management // Index list management
int create_indexes(Ndb *ndb, TABLE *tab); int create_indexes(Ndb *ndb, TABLE *tab);
void clear_index(int i); void clear_index(int i);
......
...@@ -3562,6 +3562,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -3562,6 +3562,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
uint *index_drop_buffer; uint *index_drop_buffer;
uint index_add_count; uint index_add_count;
uint *index_add_buffer; uint *index_add_buffer;
bool committed= 0;
DBUG_ENTER("mysql_alter_table"); DBUG_ENTER("mysql_alter_table");
thd->proc_info="init"; thd->proc_info="init";
...@@ -4968,6 +4969,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -4968,6 +4969,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
DBUG_PRINT("info", ("Committing after add/drop index")); DBUG_PRINT("info", ("Committing after add/drop index"));
if (ha_commit_stmt(thd) || ha_commit(thd)) if (ha_commit_stmt(thd) || ha_commit(thd))
goto err; goto err;
committed= 1;
} }
} }
/*end of if (! new_table) for add/drop index*/ /*end of if (! new_table) for add/drop index*/
...@@ -5099,7 +5101,6 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -5099,7 +5101,6 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
VOID(pthread_mutex_unlock(&LOCK_open)); VOID(pthread_mutex_unlock(&LOCK_open));
goto err; goto err;
} }
#ifdef XXX_TO_BE_DONE_LATER_BY_WL1892
if (! need_copy_table) if (! need_copy_table)
{ {
if (! table) if (! table)
...@@ -5116,7 +5117,6 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -5116,7 +5117,6 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
goto err; goto err;
} }
} }
#endif
if (thd->lock || new_name != table_name) // True if WIN32 if (thd->lock || new_name != table_name) // True if WIN32
{ {
/* /*
...@@ -5166,11 +5166,14 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -5166,11 +5166,14 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
wait_if_global_read_lock(), which could create a deadlock if called wait_if_global_read_lock(), which could create a deadlock if called
with LOCK_open. with LOCK_open.
*/ */
error = ha_commit_stmt(thd); if (!committed)
if (ha_commit(thd)) {
error=1; error = ha_commit_stmt(thd);
if (error) if (ha_commit(thd))
goto err; error=1;
if (error)
goto err;
}
thd->proc_info="end"; thd->proc_info="end";
DBUG_ASSERT(!(mysql_bin_log.is_open() && binlog_row_based && DBUG_ASSERT(!(mysql_bin_log.is_open() && binlog_row_based &&
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment