From 5efff1feec8a84c53035fbfc793af72fa3049003 Mon Sep 17 00:00:00 2001 From: "pekka@mysql.com" <> Date: Mon, 8 May 2006 15:19:17 +0200 Subject: [PATCH 1/7] ndb - bug#14509, part 1: move autoincr pre-fetch from Ndb to local dict cache --- mysql-test/r/ndb_alter_table.result | 23 +++- mysql-test/t/ndb_alter_table.test | 17 ++- ndb/include/ndbapi/Ndb.hpp | 21 ++-- ndb/src/ndbapi/DictCache.cpp | 2 + ndb/src/ndbapi/DictCache.hpp | 5 + ndb/src/ndbapi/Ndb.cpp | 151 +++++++++++++++------------ ndb/src/ndbapi/NdbDictionaryImpl.cpp | 4 - ndb/src/ndbapi/Ndbinit.cpp | 4 - 8 files changed, 136 insertions(+), 91 deletions(-) diff --git a/mysql-test/r/ndb_alter_table.result b/mysql-test/r/ndb_alter_table.result index acb67250c26..89999eca051 100644 --- a/mysql-test/r/ndb_alter_table.result +++ b/mysql-test/r/ndb_alter_table.result @@ -1,4 +1,4 @@ -DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t1, t2; drop database if exists mysqltest; CREATE TABLE t1 ( a INT NOT NULL, @@ -315,3 +315,24 @@ unique key tx1 (c002, c003, c004, c005)) engine=ndb; create index tx2 on t1 (c010, c011, c012, c013); drop table t1; +create table t1 (a int primary key auto_increment, b int) engine=ndb; +insert into t1 (b) values (101),(102),(103); +select * from t1 where a = 3; +a b +3 103 +alter table t1 rename t2; +insert into t2 (b) values (201),(202),(203); +select * from t2 where a = 6; +a b +6 203 +alter table t2 add c int; +insert into t2 (b) values (301),(302),(303); +select * from t2 where a = 9; +a b c +9 303 NULL +alter table t2 rename t1; +insert into t1 (b) values (401),(402),(403); +select * from t1 where a = 12; +a b c +12 403 NULL +drop table t1; diff --git a/mysql-test/t/ndb_alter_table.test b/mysql-test/t/ndb_alter_table.test index 0a0211c8c83..957b95c6fd9 100644 --- a/mysql-test/t/ndb_alter_table.test +++ b/mysql-test/t/ndb_alter_table.test @@ -3,7 +3,7 @@ -- source include/not_embedded.inc --disable_warnings -DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t1, t2; drop database if exists mysqltest; --enable_warnings @@ -326,5 +326,20 @@ on t1 (c010, c011, c012, c013); drop table t1; +# simple test that auto incr is not lost at rename or alter +create table t1 (a int primary key auto_increment, b int) engine=ndb; +insert into t1 (b) values (101),(102),(103); +select * from t1 where a = 3; +alter table t1 rename t2; +insert into t2 (b) values (201),(202),(203); +select * from t2 where a = 6; +alter table t2 add c int; +insert into t2 (b) values (301),(302),(303); +select * from t2 where a = 9; +alter table t2 rename t1; +insert into t1 (b) values (401),(402),(403); +select * from t1 where a = 12; +drop table t1; + # End of 4.1 tests diff --git a/ndb/include/ndbapi/Ndb.hpp b/ndb/include/ndbapi/Ndb.hpp index 7e2e9037a34..b9f5aa123b8 100644 --- a/ndb/include/ndbapi/Ndb.hpp +++ b/ndb/include/ndbapi/Ndb.hpp @@ -984,6 +984,7 @@ class BaseString; class NdbEventOperation; class NdbBlob; class NdbReceiver; +class Ndb_local_table_info; template struct Ndb_free_list_t; typedef void (* NdbEventCallback)(NdbEventOperation*, Ndb*, void*); @@ -1443,15 +1444,12 @@ public: bool increase = false); bool setAutoIncrementValue(const NdbDictionary::Table * aTable, Uint64 val, bool increase = false); - Uint64 getTupleIdFromNdb(const char* aTableName, - Uint32 cacheSize = 1000); - Uint64 getTupleIdFromNdb(Uint32 aTableId, - Uint32 cacheSize = 1000); - Uint64 readTupleIdFromNdb(Uint32 aTableId); - bool setTupleIdInNdb(const char* aTableName, Uint64 val, - bool increase); - bool setTupleIdInNdb(Uint32 aTableId, Uint64 val, bool increase); - Uint64 opTupleIdOnNdb(Uint32 aTableId, Uint64 opValue, Uint32 op); +private: + Uint64 getTupleIdFromNdb(Ndb_local_table_info* info, Uint32 cacheSize); + Uint64 readTupleIdFromNdb(Ndb_local_table_info* info); + bool setTupleIdInNdb(Ndb_local_table_info* info, Uint64 val, bool increase); + Uint64 opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 opValue, Uint32 op); +public: /** */ @@ -1650,11 +1648,6 @@ private: Uint64 the_last_check_time; Uint64 theFirstTransId; - - // The tupleId is retreived from DB the - // tupleId is unique for each tableid. - Uint64 theFirstTupleId[2048]; - Uint64 theLastTupleId[2048]; Uint32 theRestartGCI; // the Restart GCI used by DIHNDBTAMPER diff --git a/ndb/src/ndbapi/DictCache.cpp b/ndb/src/ndbapi/DictCache.cpp index 57d9b361522..dd48ee504ed 100644 --- a/ndb/src/ndbapi/DictCache.cpp +++ b/ndb/src/ndbapi/DictCache.cpp @@ -45,6 +45,8 @@ void Ndb_local_table_info::destroy(Ndb_local_table_info *info) Ndb_local_table_info::Ndb_local_table_info(NdbTableImpl *table_impl) { m_table_impl= table_impl; + m_first_tuple_id = ~(Uint64)0; + m_last_tuple_id = ~(Uint64)0; } Ndb_local_table_info::~Ndb_local_table_info() diff --git a/ndb/src/ndbapi/DictCache.hpp b/ndb/src/ndbapi/DictCache.hpp index 2df6a139542..2d137fcd5a9 100644 --- a/ndb/src/ndbapi/DictCache.hpp +++ b/ndb/src/ndbapi/DictCache.hpp @@ -33,6 +33,11 @@ public: static Ndb_local_table_info *create(NdbTableImpl *table_impl, Uint32 sz=0); static void destroy(Ndb_local_table_info *); NdbTableImpl *m_table_impl; + + // range of cached tuple ids per thread + Uint64 m_first_tuple_id; + Uint64 m_last_tuple_id; + Uint64 m_local_data[1]; // Must be last member. Used to access extra space. private: Ndb_local_table_info(NdbTableImpl *table_impl); diff --git a/ndb/src/ndbapi/Ndb.cpp b/ndb/src/ndbapi/Ndb.cpp index 7893aaae15c..5793daf35b5 100644 --- a/ndb/src/ndbapi/Ndb.cpp +++ b/ndb/src/ndbapi/Ndb.cpp @@ -768,11 +768,12 @@ Ndb::getAutoIncrementValue(const char* aTableName, Uint32 cacheSize) Ndb_local_table_info *info= theDictionary->get_local_table_info(internal_tabname, false); - if (info == 0) + if (info == 0) { + theError.code = theDictionary->getNdbError().code; DBUG_RETURN(~(Uint64)0); - const NdbTableImpl *table= info->m_table_impl; - Uint64 tupleId = getTupleIdFromNdb(table->m_tableId, cacheSize); - DBUG_PRINT("info", ("value %ul", (ulong) tupleId)); + } + Uint64 tupleId = getTupleIdFromNdb(info, cacheSize); + DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId)); DBUG_RETURN(tupleId); } @@ -783,50 +784,54 @@ Ndb::getAutoIncrementValue(const NdbDictionary::Table * aTable, Uint32 cacheSize if (aTable == 0) DBUG_RETURN(~(Uint64)0); const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable); - Uint64 tupleId = getTupleIdFromNdb(table->m_tableId, cacheSize); - DBUG_PRINT("info", ("value %ul", (ulong) tupleId)); + const BaseString& internal_tabname = table->m_internalName; + + Ndb_local_table_info *info= + theDictionary->get_local_table_info(internal_tabname, false); + if (info == 0) { + theError.code = theDictionary->getNdbError().code; + DBUG_RETURN(~(Uint64)0); + } + Uint64 tupleId = getTupleIdFromNdb(info, cacheSize); + DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId)); DBUG_RETURN(tupleId); } -Uint64 -Ndb::getTupleIdFromNdb(const char* aTableName, Uint32 cacheSize) -{ - const NdbTableImpl* table = theDictionary->getTable(aTableName); - if (table == 0) - return ~(Uint64)0; - return getTupleIdFromNdb(table->m_tableId, cacheSize); -} - Uint64 -Ndb::getTupleIdFromNdb(Uint32 aTableId, Uint32 cacheSize) +Ndb::getTupleIdFromNdb(Ndb_local_table_info* info, Uint32 cacheSize) { DBUG_ENTER("getTupleIdFromNdb"); - if ( theFirstTupleId[aTableId] != theLastTupleId[aTableId] ) + Uint64 tupleId; + if (info->m_first_tuple_id != info->m_last_tuple_id) { - theFirstTupleId[aTableId]++; - DBUG_PRINT("info", ("next cached value %ul", - (ulong) theFirstTupleId[aTableId])); - DBUG_RETURN(theFirstTupleId[aTableId]); + assert(info->m_first_tuple_id < info->m_last_tuple_id); + tupleId = ++info->m_first_tuple_id; + DBUG_PRINT("info", ("next cached value %llu", (ulonglong)tupleId)); } - else // theFirstTupleId == theLastTupleId + else { - DBUG_PRINT("info",("reading %u values from database", - (cacheSize == 0) ? 1 : cacheSize)); - DBUG_RETURN(opTupleIdOnNdb(aTableId, (cacheSize == 0) ? 1 : cacheSize, 0)); + if (cacheSize == 0) + cacheSize = 1; + DBUG_PRINT("info", ("reading %u values from database", (uint)cacheSize)); + tupleId = opTupleIdOnNdb(info, cacheSize, 0); } + DBUG_RETURN(tupleId); } Uint64 Ndb::readAutoIncrementValue(const char* aTableName) { DBUG_ENTER("readAutoIncrementValue"); - const NdbTableImpl* table = theDictionary->getTable(aTableName); - if (table == 0) { - theError= theDictionary->getNdbError(); + BaseString internal_tabname(internalize_table_name(aTableName)); + + Ndb_local_table_info *info= + theDictionary->get_local_table_info(internal_tabname, false); + if (info == 0) { + theError.code = theDictionary->getNdbError().code; DBUG_RETURN(~(Uint64)0); } - Uint64 tupleId = readTupleIdFromNdb(table->m_tableId); - DBUG_PRINT("info", ("value %ul", (ulong) tupleId)); + Uint64 tupleId = readTupleIdFromNdb(info); + DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId)); DBUG_RETURN(tupleId); } @@ -837,19 +842,34 @@ Ndb::readAutoIncrementValue(const NdbDictionary::Table * aTable) if (aTable == 0) DBUG_RETURN(~(Uint64)0); const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable); - Uint64 tupleId = readTupleIdFromNdb(table->m_tableId); - DBUG_PRINT("info", ("value %ul", (ulong) tupleId)); + const BaseString& internal_tabname = table->m_internalName; + + Ndb_local_table_info *info= + theDictionary->get_local_table_info(internal_tabname, false); + if (info == 0) { + theError.code = theDictionary->getNdbError().code; + DBUG_RETURN(~(Uint64)0); + } + Uint64 tupleId = readTupleIdFromNdb(info); + DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId)); DBUG_RETURN(tupleId); } Uint64 -Ndb::readTupleIdFromNdb(Uint32 aTableId) +Ndb::readTupleIdFromNdb(Ndb_local_table_info* info) { - if ( theFirstTupleId[aTableId] == theLastTupleId[aTableId] ) - // Cache is empty, check next in database - return opTupleIdOnNdb(aTableId, 0, 3); - - return theFirstTupleId[aTableId] + 1; + DBUG_ENTER("Ndb::readTupleIdFromNdb"); + Uint64 tupleId; + if (info->m_first_tuple_id != info->m_last_tuple_id) + { + assert(info->m_first_tuple_id < info->m_last_tuple_id); + tupleId = info->m_first_tuple_id + 1; + } + else // Cache is empty, check next in database + { + tupleId = opTupleIdOnNdb(info, 0, 3); + } + DBUG_RETURN(tupleId); } bool @@ -861,11 +881,10 @@ Ndb::setAutoIncrementValue(const char* aTableName, Uint64 val, bool increase) Ndb_local_table_info *info= theDictionary->get_local_table_info(internal_tabname, false); if (info == 0) { - theError= theDictionary->getNdbError(); + theError.code = theDictionary->getNdbError().code; DBUG_RETURN(false); } - const NdbTableImpl* table= info->m_table_impl; - DBUG_RETURN(setTupleIdInNdb(table->m_tableId, val, increase)); + DBUG_RETURN(setTupleIdInNdb(info, val, increase)); } bool @@ -873,51 +892,49 @@ Ndb::setAutoIncrementValue(const NdbDictionary::Table * aTable, Uint64 val, bool { DBUG_ENTER("setAutoIncrementValue"); if (aTable == 0) - DBUG_RETURN(~(Uint64)0); + DBUG_RETURN(false); const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable); - DBUG_RETURN(setTupleIdInNdb(table->m_tableId, val, increase)); -} + const BaseString& internal_tabname = table->m_internalName; -bool -Ndb::setTupleIdInNdb(const char* aTableName, Uint64 val, bool increase ) -{ - DBUG_ENTER("setTupleIdInNdb(const char*, ...)"); - const NdbTableImpl* table = theDictionary->getTable(aTableName); - if (table == 0) { - theError= theDictionary->getNdbError(); + Ndb_local_table_info *info= + theDictionary->get_local_table_info(internal_tabname, false); + if (info == 0) { + theError.code = theDictionary->getNdbError().code; DBUG_RETURN(false); } - DBUG_RETURN(setTupleIdInNdb(table->m_tableId, val, increase)); + DBUG_RETURN(setTupleIdInNdb(info, val, increase)); } bool -Ndb::setTupleIdInNdb(Uint32 aTableId, Uint64 val, bool increase ) +Ndb::setTupleIdInNdb(Ndb_local_table_info* info, Uint64 val, bool increase) { - DBUG_ENTER("setTupleIdInNdb(Uint32, ...)"); + DBUG_ENTER("setTupleIdInNdb"); if (increase) { - if (theFirstTupleId[aTableId] != theLastTupleId[aTableId]) + if (info->m_first_tuple_id != info->m_last_tuple_id) { // We have a cache sequence - if (val <= theFirstTupleId[aTableId]+1) + assert(info->m_first_tuple_id < info->m_last_tuple_id); + if (val <= info->m_first_tuple_id + 1) DBUG_RETURN(false); - if (val <= theLastTupleId[aTableId]) + if (val <= info->m_last_tuple_id) { - theFirstTupleId[aTableId] = val - 1; + info->m_first_tuple_id = val - 1; DBUG_RETURN(true); } // else continue; } - DBUG_RETURN((opTupleIdOnNdb(aTableId, val, 2) == val)); + DBUG_RETURN((opTupleIdOnNdb(info, val, 2) == val)); } else - DBUG_RETURN((opTupleIdOnNdb(aTableId, val, 1) == val)); + DBUG_RETURN((opTupleIdOnNdb(info, val, 1) == val)); } Uint64 -Ndb::opTupleIdOnNdb(Uint32 aTableId, Uint64 opValue, Uint32 op) +Ndb::opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 opValue, Uint32 op) { DBUG_ENTER("Ndb::opTupleIdOnNdb"); + Uint32 aTableId = info->m_table_impl->m_tableId; DBUG_PRINT("enter", ("table=%u value=%llu op=%u", aTableId, opValue, op)); NdbTransaction* tConnection; @@ -958,9 +975,9 @@ Ndb::opTupleIdOnNdb(Uint32 aTableId, Uint64 opValue, Uint32 op) tValue = tRecAttrResult->u_64_value(); - theFirstTupleId[aTableId] = tValue - opValue; - theLastTupleId[aTableId] = tValue - 1; - ret = theFirstTupleId[aTableId]; + info->m_first_tuple_id = tValue - opValue; + info->m_last_tuple_id = tValue - 1; + ret = info->m_first_tuple_id; break; case 1: tOperation->updateTuple(); @@ -970,8 +987,8 @@ Ndb::opTupleIdOnNdb(Uint32 aTableId, Uint64 opValue, Uint32 op) if (tConnection->execute( Commit ) == -1 ) goto error_handler; - theFirstTupleId[aTableId] = ~(Uint64)0; - theLastTupleId[aTableId] = ~(Uint64)0; + info->m_first_tuple_id = ~(Uint64)0; + info->m_last_tuple_id = ~(Uint64)0; ret = opValue; break; case 2: @@ -992,7 +1009,7 @@ Ndb::opTupleIdOnNdb(Uint32 aTableId, Uint64 opValue, Uint32 op) ret = ~(Uint64)0; else { - theFirstTupleId[aTableId] = theLastTupleId[aTableId] = opValue - 1; + info->m_first_tuple_id = info->m_last_tuple_id = opValue - 1; ret = opValue; } break; diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/ndb/src/ndbapi/NdbDictionaryImpl.cpp index 6cb8e1f9a24..26517948f2d 100644 --- a/ndb/src/ndbapi/NdbDictionaryImpl.cpp +++ b/ndb/src/ndbapi/NdbDictionaryImpl.cpp @@ -759,10 +759,6 @@ NdbDictionaryImpl::fetchGlobalTableImpl(const BaseString& internalTableName) Ndb_local_table_info::create(impl, m_local_table_data_size); m_localHash.put(internalTableName.c_str(), info); - - m_ndb.theFirstTupleId[impl->getTableId()] = ~0; - m_ndb.theLastTupleId[impl->getTableId()] = ~0; - return info; } diff --git a/ndb/src/ndbapi/Ndbinit.cpp b/ndb/src/ndbapi/Ndbinit.cpp index d4ab30aec4e..d5ad7066273 100644 --- a/ndb/src/ndbapi/Ndbinit.cpp +++ b/ndb/src/ndbapi/Ndbinit.cpp @@ -96,10 +96,6 @@ void Ndb::setup(Ndb_cluster_connection *ndb_cluster_connection, for (i = 0; i < MAX_NDB_NODES ; i++) { theConnectionArray[i] = NULL; }//forg - for (i = 0; i < 2048 ; i++) { - theFirstTupleId[i] = 0; - theLastTupleId[i] = 0; - }//for theImpl->m_dbname.assign(aDataBase); theImpl->m_schemaname.assign(aSchema); From e554f9b3d4555eaa3b4004a099ee595084610710 Mon Sep 17 00:00:00 2001 From: "pekka@mysql.com" <> Date: Thu, 11 May 2006 12:58:45 +0200 Subject: [PATCH 2/7] ndb - bug#14509 (5.0) part 2: create SYSTAB_0 row on first use --- ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp | 10 +++--- ndb/src/ndbapi/Ndb.cpp | 33 +++++++++++++++---- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp b/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp index c403aad5516..176bab0d4bf 100644 --- a/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp +++ b/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp @@ -1607,10 +1607,9 @@ void Ndbcntr::systemErrorLab(Signal* signal, int line) /* |-2048| # 1 00000001 | */ /* | : | : | */ /* | -1 | # 1 00000001 | */ -/* | 0 | 0 | */ -/* | 1 | 0 | */ -/* | : | : | */ -/* | 2047| 0 | */ +/* | 1 | 0 | tupleid sequence now created on first use */ +/* | : | : | v */ +/* | 2048| 0 | v */ /*---------------------------------------------------------------------------*/ void Ndbcntr::createSystableLab(Signal* signal, unsigned index) { @@ -1819,8 +1818,7 @@ void Ndbcntr::crSystab8Lab(Signal* signal) jam(); ckey = 1; ctransidPhase = ZFALSE; - crSystab7Lab(signal); - return; + // skip 2nd loop - tupleid sequence now created on first use }//if signal->theData[0] = ctcConnectionP; signal->theData[1] = reference(); diff --git a/ndb/src/ndbapi/Ndb.cpp b/ndb/src/ndbapi/Ndb.cpp index 5793daf35b5..c6b9f308fe8 100644 --- a/ndb/src/ndbapi/Ndb.cpp +++ b/ndb/src/ndbapi/Ndb.cpp @@ -813,6 +813,10 @@ Ndb::getTupleIdFromNdb(Ndb_local_table_info* info, Uint32 cacheSize) if (cacheSize == 0) cacheSize = 1; DBUG_PRINT("info", ("reading %u values from database", (uint)cacheSize)); + /* + * reserve next cacheSize entries in db. adds cacheSize to NEXTID + * and returns first tupleId in the new range. + */ tupleId = opTupleIdOnNdb(info, cacheSize, 0); } DBUG_RETURN(tupleId); @@ -865,8 +869,12 @@ Ndb::readTupleIdFromNdb(Ndb_local_table_info* info) assert(info->m_first_tuple_id < info->m_last_tuple_id); tupleId = info->m_first_tuple_id + 1; } - else // Cache is empty, check next in database + else { + /* + * peek at NEXTID. does not reserve it so the value is valid + * only if no other transactions are allowed. + */ tupleId = opTupleIdOnNdb(info, 0, 3); } DBUG_RETURN(tupleId); @@ -913,7 +921,6 @@ Ndb::setTupleIdInNdb(Ndb_local_table_info* info, Uint64 val, bool increase) { if (info->m_first_tuple_id != info->m_last_tuple_id) { - // We have a cache sequence assert(info->m_first_tuple_id < info->m_last_tuple_id); if (val <= info->m_first_tuple_id + 1) DBUG_RETURN(false); @@ -922,11 +929,17 @@ Ndb::setTupleIdInNdb(Ndb_local_table_info* info, Uint64 val, bool increase) info->m_first_tuple_id = val - 1; DBUG_RETURN(true); } - // else continue; } + /* + * if value <= NEXTID, do nothing. otherwise update NEXTID to + * value and set cached range to first = last = value - 1. + */ DBUG_RETURN((opTupleIdOnNdb(info, val, 2) == val)); } else + /* + * update NEXTID to given value. reset cached range. + */ DBUG_RETURN((opTupleIdOnNdb(info, val, 1) == val)); } @@ -980,7 +993,8 @@ Ndb::opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 opValue, Uint32 op) ret = info->m_first_tuple_id; break; case 1: - tOperation->updateTuple(); + // create on first use + tOperation->writeTuple(); tOperation->equal("SYSKEY_0", aTableId ); tOperation->setValue("NEXTID", opValue); @@ -996,6 +1010,7 @@ Ndb::opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 opValue, Uint32 op) tOperation->equal("SYSKEY_0", aTableId ); tOperation->load_const_u64(1, opValue); tOperation->read_attr("NEXTID", 2); + // compare NEXTID >= opValue tOperation->branch_le(2, 1, 0); tOperation->write_attr("NEXTID", 1); tOperation->interpret_exit_ok(); @@ -1003,10 +1018,14 @@ Ndb::opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 opValue, Uint32 op) tOperation->interpret_exit_nok(9999); if ( (result = tConnection->execute( Commit )) == -1 ) - goto error_handler; - - if (result == 9999) + { + if (tConnection->theError.code != 9999) + goto error_handler; + + // NEXTID >= opValue, return ~(Uint64)0 for now since + // there is no error check... ret = ~(Uint64)0; + } else { info->m_first_tuple_id = info->m_last_tuple_id = opValue - 1; From dd58dd51a17b65f14690dd1e50865d45672a7c21 Mon Sep 17 00:00:00 2001 From: "pekka@mysql.com" <> Date: Tue, 16 May 2006 12:58:41 +0200 Subject: [PATCH 3/7] ndb - bug#14509 [related] setAutoIncrement: add error handling --- ndb/include/ndbapi/Ndb.hpp | 12 ++++---- ndb/src/ndbapi/Ndb.cpp | 39 +++++++++++++------------- ndb/src/ndbapi/NdbDictionaryImpl.cpp | 13 ++++----- ndb/tools/restore/consumer_restore.cpp | 2 +- sql/ha_ndbcluster.cc | 10 +++---- 5 files changed, 36 insertions(+), 40 deletions(-) diff --git a/ndb/include/ndbapi/Ndb.hpp b/ndb/include/ndbapi/Ndb.hpp index b9f5aa123b8..f6610b29ad4 100644 --- a/ndb/include/ndbapi/Ndb.hpp +++ b/ndb/include/ndbapi/Ndb.hpp @@ -1432,7 +1432,7 @@ public: * * @param cacheSize number of values to cache in this Ndb object * - * @return tuple id or 0 on error + * @return tuple id or ~(Uint64)0 on error. */ Uint64 getAutoIncrementValue(const char* aTableName, Uint32 cacheSize = 1); @@ -1440,14 +1440,14 @@ public: Uint32 cacheSize = 1); Uint64 readAutoIncrementValue(const char* aTableName); Uint64 readAutoIncrementValue(const NdbDictionary::Table * aTable); - bool setAutoIncrementValue(const char* aTableName, Uint64 val, - bool increase = false); - bool setAutoIncrementValue(const NdbDictionary::Table * aTable, Uint64 val, - bool increase = false); + Uint64 setAutoIncrementValue(const char* aTableName, Uint64 val, + bool increase = false); + Uint64 setAutoIncrementValue(const NdbDictionary::Table * aTable, Uint64 val, + bool increase = false); private: Uint64 getTupleIdFromNdb(Ndb_local_table_info* info, Uint32 cacheSize); Uint64 readTupleIdFromNdb(Ndb_local_table_info* info); - bool setTupleIdInNdb(Ndb_local_table_info* info, Uint64 val, bool increase); + Uint64 setTupleIdInNdb(Ndb_local_table_info* info, Uint64 val, bool increase); Uint64 opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 opValue, Uint32 op); public: diff --git a/ndb/src/ndbapi/Ndb.cpp b/ndb/src/ndbapi/Ndb.cpp index c6b9f308fe8..9c3ca5cd94a 100644 --- a/ndb/src/ndbapi/Ndb.cpp +++ b/ndb/src/ndbapi/Ndb.cpp @@ -781,8 +781,7 @@ Uint64 Ndb::getAutoIncrementValue(const NdbDictionary::Table * aTable, Uint32 cacheSize) { DBUG_ENTER("getAutoIncrementValue"); - if (aTable == 0) - DBUG_RETURN(~(Uint64)0); + assert(aTable != 0); const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable); const BaseString& internal_tabname = table->m_internalName; @@ -843,8 +842,7 @@ Uint64 Ndb::readAutoIncrementValue(const NdbDictionary::Table * aTable) { DBUG_ENTER("readAutoIncrementValue"); - if (aTable == 0) - DBUG_RETURN(~(Uint64)0); + assert(aTable != 0); const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable); const BaseString& internal_tabname = table->m_internalName; @@ -880,7 +878,7 @@ Ndb::readTupleIdFromNdb(Ndb_local_table_info* info) DBUG_RETURN(tupleId); } -bool +Uint64 Ndb::setAutoIncrementValue(const char* aTableName, Uint64 val, bool increase) { DBUG_ENTER("setAutoIncrementValue"); @@ -890,17 +888,16 @@ Ndb::setAutoIncrementValue(const char* aTableName, Uint64 val, bool increase) theDictionary->get_local_table_info(internal_tabname, false); if (info == 0) { theError.code = theDictionary->getNdbError().code; - DBUG_RETURN(false); + DBUG_RETURN(~(Uint64)0); } DBUG_RETURN(setTupleIdInNdb(info, val, increase)); } -bool +Uint64 Ndb::setAutoIncrementValue(const NdbDictionary::Table * aTable, Uint64 val, bool increase) { DBUG_ENTER("setAutoIncrementValue"); - if (aTable == 0) - DBUG_RETURN(false); + assert(aTable != 0); const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable); const BaseString& internal_tabname = table->m_internalName; @@ -908,12 +905,12 @@ Ndb::setAutoIncrementValue(const NdbDictionary::Table * aTable, Uint64 val, bool theDictionary->get_local_table_info(internal_tabname, false); if (info == 0) { theError.code = theDictionary->getNdbError().code; - DBUG_RETURN(false); + DBUG_RETURN(~(Uint64)0); } DBUG_RETURN(setTupleIdInNdb(info, val, increase)); } -bool +Uint64 Ndb::setTupleIdInNdb(Ndb_local_table_info* info, Uint64 val, bool increase) { DBUG_ENTER("setTupleIdInNdb"); @@ -923,11 +920,14 @@ Ndb::setTupleIdInNdb(Ndb_local_table_info* info, Uint64 val, bool increase) { assert(info->m_first_tuple_id < info->m_last_tuple_id); if (val <= info->m_first_tuple_id + 1) - DBUG_RETURN(false); + DBUG_RETURN(val); if (val <= info->m_last_tuple_id) { info->m_first_tuple_id = val - 1; - DBUG_RETURN(true); + DBUG_PRINT("info", + ("Setting next auto increment cached value to %llu", + (ulonglong)val)); + DBUG_RETURN(val); } } /* @@ -954,8 +954,7 @@ Ndb::opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 opValue, Uint32 op) NdbOperation* tOperation= 0; // Compiler warning if not initialized Uint64 tValue; NdbRecAttr* tRecAttrResult; - int result; - Uint64 ret; + Uint64 ret = ~(Uint64)0; CHECK_STATUS_MACRO_ZERO; @@ -1017,17 +1016,17 @@ Ndb::opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 opValue, Uint32 op) tOperation->def_label(0); tOperation->interpret_exit_nok(9999); - if ( (result = tConnection->execute( Commit )) == -1 ) + if (tConnection->execute( Commit ) == -1) { if (tConnection->theError.code != 9999) goto error_handler; - - // NEXTID >= opValue, return ~(Uint64)0 for now since - // there is no error check... - ret = ~(Uint64)0; + ret = opValue; } else { + DBUG_PRINT("info", + ("Setting next auto increment value (db) to %llu", + (ulonglong)opValue)); info->m_first_tuple_id = info->m_last_tuple_id = opValue - 1; ret = opValue; } diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/ndb/src/ndbapi/NdbDictionaryImpl.cpp index 26517948f2d..b3824df48f4 100644 --- a/ndb/src/ndbapi/NdbDictionaryImpl.cpp +++ b/ndb/src/ndbapi/NdbDictionaryImpl.cpp @@ -1742,14 +1742,11 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb, DBUG_RETURN(ret); if (haveAutoIncrement) { - if (!ndb.setAutoIncrementValue(impl.m_externalName.c_str(), - autoIncrementValue)) { - if (ndb.theError.code == 0) { - m_error.code= 4336; - ndb.theError = m_error; - } else - m_error= ndb.theError; - ret = -1; // errorcode set in initialize_autoincrement + if (ndb.setAutoIncrementValue(impl.m_externalName.c_str(), + autoIncrementValue) == ~(Uint64)0) { + DBUG_ASSERT(ndb.theError.code != 0); + m_error= ndb.theError; + ret = -1; } } } diff --git a/ndb/tools/restore/consumer_restore.cpp b/ndb/tools/restore/consumer_restore.cpp index 038d57daf97..5563c51365b 100644 --- a/ndb/tools/restore/consumer_restore.cpp +++ b/ndb/tools/restore/consumer_restore.cpp @@ -150,7 +150,7 @@ BackupRestore::finalize_table(const TableS & table){ Uint64 max_val= table.get_max_auto_val(); Uint64 auto_val= m_ndb->readAutoIncrementValue(get_table(table.m_dictTable)); if (max_val+1 > auto_val || auto_val == ~(Uint64)0) - ret= m_ndb->setAutoIncrementValue(get_table(table.m_dictTable), max_val+1, false); + ret= m_ndb->setAutoIncrementValue(get_table(table.m_dictTable), max_val+1, false) != ~(Uint64)0; } return ret; } diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 138e8c72e7a..a7f680ffc1c 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -2197,11 +2197,11 @@ int ha_ndbcluster::write_row(byte *record) Ndb *ndb= get_ndb(); Uint64 next_val= (Uint64) table->next_number_field->val_int() + 1; DBUG_PRINT("info", - ("Trying to set next auto increment value to %lu", - (ulong) next_val)); - if (ndb->setAutoIncrementValue((const NDBTAB *) m_table, next_val, TRUE)) - DBUG_PRINT("info", - ("Setting next auto increment value to %u", next_val)); + ("Trying to set next auto increment value to %llu", + (ulonglong) next_val)); + if (ndb->setAutoIncrementValue((const NDBTAB *) m_table, next_val, TRUE) + == ~(Uint64)0) + ERR_RETURN(ndb->getNdbError()); } m_skip_auto_increment= TRUE; From fc7320466a10380eb44123ad4dd60450467b4dcc Mon Sep 17 00:00:00 2001 From: "pekka@mysql.com" <> Date: Tue, 16 May 2006 16:17:30 +0200 Subject: [PATCH 4/7] ndb - bug#14509 [related] fix a return value --- ndb/src/ndbapi/Ndb.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ndb/src/ndbapi/Ndb.cpp b/ndb/src/ndbapi/Ndb.cpp index 9c3ca5cd94a..b290037a84b 100644 --- a/ndb/src/ndbapi/Ndb.cpp +++ b/ndb/src/ndbapi/Ndb.cpp @@ -934,13 +934,13 @@ Ndb::setTupleIdInNdb(Ndb_local_table_info* info, Uint64 val, bool increase) * if value <= NEXTID, do nothing. otherwise update NEXTID to * value and set cached range to first = last = value - 1. */ - DBUG_RETURN((opTupleIdOnNdb(info, val, 2) == val)); + DBUG_RETURN((opTupleIdOnNdb(info, val, 2))); } else /* * update NEXTID to given value. reset cached range. */ - DBUG_RETURN((opTupleIdOnNdb(info, val, 1) == val)); + DBUG_RETURN((opTupleIdOnNdb(info, val, 1))); } Uint64 From 54963c2e52543735734e176440c3eb141c057643 Mon Sep 17 00:00:00 2001 From: "pekka@mysql.com" <> Date: Wed, 17 May 2006 12:40:10 +0200 Subject: [PATCH 5/7] ndb - bug#14509 [related] re-do auto-incr error handling --- ndb/include/ndbapi/Ndb.hpp | 35 +++--- ndb/src/ndbapi/Ndb.cpp | 158 ++++++++++++++----------- ndb/src/ndbapi/NdbDictionaryImpl.cpp | 2 +- ndb/test/ndbapi/testDict.cpp | 10 +- ndb/tools/restore/consumer_restore.cpp | 9 +- sql/ha_ndbcluster.cc | 36 +++--- 6 files changed, 145 insertions(+), 105 deletions(-) diff --git a/ndb/include/ndbapi/Ndb.hpp b/ndb/include/ndbapi/Ndb.hpp index f6610b29ad4..f128a45f5bf 100644 --- a/ndb/include/ndbapi/Ndb.hpp +++ b/ndb/include/ndbapi/Ndb.hpp @@ -1432,23 +1432,28 @@ public: * * @param cacheSize number of values to cache in this Ndb object * - * @return tuple id or ~(Uint64)0 on error. + * @return 0 or -1 on error, and tupleId in out parameter */ - Uint64 getAutoIncrementValue(const char* aTableName, - Uint32 cacheSize = 1); - Uint64 getAutoIncrementValue(const NdbDictionary::Table * aTable, - Uint32 cacheSize = 1); - Uint64 readAutoIncrementValue(const char* aTableName); - Uint64 readAutoIncrementValue(const NdbDictionary::Table * aTable); - Uint64 setAutoIncrementValue(const char* aTableName, Uint64 val, - bool increase = false); - Uint64 setAutoIncrementValue(const NdbDictionary::Table * aTable, Uint64 val, - bool increase = false); + int getAutoIncrementValue(const char* aTableName, + Uint64 & tupleId, Uint32 cacheSize); + int getAutoIncrementValue(const NdbDictionary::Table * aTable, + Uint64 & tupleId, Uint32 cacheSize); + int readAutoIncrementValue(const char* aTableName, + Uint64 & tupleId); + int readAutoIncrementValue(const NdbDictionary::Table * aTable, + Uint64 & tupleId); + int setAutoIncrementValue(const char* aTableName, + Uint64 tupleId, bool increase); + int setAutoIncrementValue(const NdbDictionary::Table * aTable, + Uint64 tupleId, bool increase); private: - Uint64 getTupleIdFromNdb(Ndb_local_table_info* info, Uint32 cacheSize); - Uint64 readTupleIdFromNdb(Ndb_local_table_info* info); - Uint64 setTupleIdInNdb(Ndb_local_table_info* info, Uint64 val, bool increase); - Uint64 opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 opValue, Uint32 op); + int getTupleIdFromNdb(Ndb_local_table_info* info, + Uint64 & tupleId, Uint32 cacheSize); + int readTupleIdFromNdb(Ndb_local_table_info* info, + Uint64 & tupleId); + int setTupleIdInNdb(Ndb_local_table_info* info, + Uint64 tupleId, bool increase); + int opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 & opValue, Uint32 op); public: /** diff --git a/ndb/src/ndbapi/Ndb.cpp b/ndb/src/ndbapi/Ndb.cpp index b290037a84b..56d68503825 100644 --- a/ndb/src/ndbapi/Ndb.cpp +++ b/ndb/src/ndbapi/Ndb.cpp @@ -760,27 +760,30 @@ Remark: Returns a new TupleId to the application. The TupleId comes from SYSTAB_0 where SYSKEY_0 = TableId. It is initialized to (TableId << 48) + 1 in NdbcntrMain.cpp. ****************************************************************************/ -Uint64 -Ndb::getAutoIncrementValue(const char* aTableName, Uint32 cacheSize) +int +Ndb::getAutoIncrementValue(const char* aTableName, + Uint64 & tupleId, Uint32 cacheSize) { - DBUG_ENTER("getAutoIncrementValue"); + DBUG_ENTER("Ndb::getAutoIncrementValue"); BaseString internal_tabname(internalize_table_name(aTableName)); Ndb_local_table_info *info= theDictionary->get_local_table_info(internal_tabname, false); if (info == 0) { theError.code = theDictionary->getNdbError().code; - DBUG_RETURN(~(Uint64)0); + DBUG_RETURN(-1); } - Uint64 tupleId = getTupleIdFromNdb(info, cacheSize); + if (getTupleIdFromNdb(info, tupleId, cacheSize) == -1) + DBUG_RETURN(-1); DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId)); - DBUG_RETURN(tupleId); + DBUG_RETURN(0); } -Uint64 -Ndb::getAutoIncrementValue(const NdbDictionary::Table * aTable, Uint32 cacheSize) +int +Ndb::getAutoIncrementValue(const NdbDictionary::Table * aTable, + Uint64 & tupleId, Uint32 cacheSize) { - DBUG_ENTER("getAutoIncrementValue"); + DBUG_ENTER("Ndb::getAutoIncrementValue"); assert(aTable != 0); const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable); const BaseString& internal_tabname = table->m_internalName; @@ -789,18 +792,19 @@ Ndb::getAutoIncrementValue(const NdbDictionary::Table * aTable, Uint32 cacheSize theDictionary->get_local_table_info(internal_tabname, false); if (info == 0) { theError.code = theDictionary->getNdbError().code; - DBUG_RETURN(~(Uint64)0); + DBUG_RETURN(-1); } - Uint64 tupleId = getTupleIdFromNdb(info, cacheSize); + if (getTupleIdFromNdb(info, tupleId, cacheSize) == -1) + DBUG_RETURN(-1); DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId)); - DBUG_RETURN(tupleId); + DBUG_RETURN(0); } -Uint64 -Ndb::getTupleIdFromNdb(Ndb_local_table_info* info, Uint32 cacheSize) +int +Ndb::getTupleIdFromNdb(Ndb_local_table_info* info, + Uint64 & tupleId, Uint32 cacheSize) { - DBUG_ENTER("getTupleIdFromNdb"); - Uint64 tupleId; + DBUG_ENTER("Ndb::getTupleIdFromNdb"); if (info->m_first_tuple_id != info->m_last_tuple_id) { assert(info->m_first_tuple_id < info->m_last_tuple_id); @@ -816,32 +820,38 @@ Ndb::getTupleIdFromNdb(Ndb_local_table_info* info, Uint32 cacheSize) * reserve next cacheSize entries in db. adds cacheSize to NEXTID * and returns first tupleId in the new range. */ - tupleId = opTupleIdOnNdb(info, cacheSize, 0); + Uint64 opValue = cacheSize; + if (opTupleIdOnNdb(info, opValue, 0) == -1) + DBUG_RETURN(-1); + tupleId = opValue; } - DBUG_RETURN(tupleId); + DBUG_RETURN(0); } -Uint64 -Ndb::readAutoIncrementValue(const char* aTableName) +int +Ndb::readAutoIncrementValue(const char* aTableName, + Uint64 & tupleId) { - DBUG_ENTER("readAutoIncrementValue"); + DBUG_ENTER("Ndb::readAutoIncrementValue"); BaseString internal_tabname(internalize_table_name(aTableName)); Ndb_local_table_info *info= theDictionary->get_local_table_info(internal_tabname, false); if (info == 0) { theError.code = theDictionary->getNdbError().code; - DBUG_RETURN(~(Uint64)0); + DBUG_RETURN(-1); } - Uint64 tupleId = readTupleIdFromNdb(info); + if (readTupleIdFromNdb(info, tupleId) == -1) + DBUG_RETURN(-1); DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId)); - DBUG_RETURN(tupleId); + DBUG_RETURN(0); } -Uint64 -Ndb::readAutoIncrementValue(const NdbDictionary::Table * aTable) +int +Ndb::readAutoIncrementValue(const NdbDictionary::Table * aTable, + Uint64 & tupleId) { - DBUG_ENTER("readAutoIncrementValue"); + DBUG_ENTER("Ndb::readAutoIncrementValue"); assert(aTable != 0); const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable); const BaseString& internal_tabname = table->m_internalName; @@ -850,18 +860,19 @@ Ndb::readAutoIncrementValue(const NdbDictionary::Table * aTable) theDictionary->get_local_table_info(internal_tabname, false); if (info == 0) { theError.code = theDictionary->getNdbError().code; - DBUG_RETURN(~(Uint64)0); + DBUG_RETURN(-1); } - Uint64 tupleId = readTupleIdFromNdb(info); + if (readTupleIdFromNdb(info, tupleId) == -1) + DBUG_RETURN(-1); DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId)); - DBUG_RETURN(tupleId); + DBUG_RETURN(0); } -Uint64 -Ndb::readTupleIdFromNdb(Ndb_local_table_info* info) +int +Ndb::readTupleIdFromNdb(Ndb_local_table_info* info, + Uint64 & tupleId) { DBUG_ENTER("Ndb::readTupleIdFromNdb"); - Uint64 tupleId; if (info->m_first_tuple_id != info->m_last_tuple_id) { assert(info->m_first_tuple_id < info->m_last_tuple_id); @@ -873,30 +884,37 @@ Ndb::readTupleIdFromNdb(Ndb_local_table_info* info) * peek at NEXTID. does not reserve it so the value is valid * only if no other transactions are allowed. */ - tupleId = opTupleIdOnNdb(info, 0, 3); + Uint64 opValue = 0; + if (opTupleIdOnNdb(info, opValue, 3) == -1) + DBUG_RETURN(-1); + tupleId = opValue; } - DBUG_RETURN(tupleId); + DBUG_RETURN(0); } -Uint64 -Ndb::setAutoIncrementValue(const char* aTableName, Uint64 val, bool increase) +int +Ndb::setAutoIncrementValue(const char* aTableName, + Uint64 tupleId, bool increase) { - DBUG_ENTER("setAutoIncrementValue"); + DBUG_ENTER("Ndb::setAutoIncrementValue"); BaseString internal_tabname(internalize_table_name(aTableName)); Ndb_local_table_info *info= theDictionary->get_local_table_info(internal_tabname, false); if (info == 0) { theError.code = theDictionary->getNdbError().code; - DBUG_RETURN(~(Uint64)0); + DBUG_RETURN(-1); } - DBUG_RETURN(setTupleIdInNdb(info, val, increase)); + if (setTupleIdInNdb(info, tupleId, increase) == -1) + DBUG_RETURN(-1); + DBUG_RETURN(0); } -Uint64 -Ndb::setAutoIncrementValue(const NdbDictionary::Table * aTable, Uint64 val, bool increase) +int +Ndb::setAutoIncrementValue(const NdbDictionary::Table * aTable, + Uint64 tupleId, bool increase) { - DBUG_ENTER("setAutoIncrementValue"); + DBUG_ENTER("Ndb::setAutoIncrementValue"); assert(aTable != 0); const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable); const BaseString& internal_tabname = table->m_internalName; @@ -905,46 +923,54 @@ Ndb::setAutoIncrementValue(const NdbDictionary::Table * aTable, Uint64 val, bool theDictionary->get_local_table_info(internal_tabname, false); if (info == 0) { theError.code = theDictionary->getNdbError().code; - DBUG_RETURN(~(Uint64)0); + DBUG_RETURN(-1); } - DBUG_RETURN(setTupleIdInNdb(info, val, increase)); + if (setTupleIdInNdb(info, tupleId, increase) == -1) + DBUG_RETURN(-1); + DBUG_RETURN(0); } -Uint64 -Ndb::setTupleIdInNdb(Ndb_local_table_info* info, Uint64 val, bool increase) +int +Ndb::setTupleIdInNdb(Ndb_local_table_info* info, + Uint64 tupleId, bool increase) { - DBUG_ENTER("setTupleIdInNdb"); + DBUG_ENTER("Ndb::setTupleIdInNdb"); if (increase) { if (info->m_first_tuple_id != info->m_last_tuple_id) { assert(info->m_first_tuple_id < info->m_last_tuple_id); - if (val <= info->m_first_tuple_id + 1) - DBUG_RETURN(val); - if (val <= info->m_last_tuple_id) + if (tupleId <= info->m_first_tuple_id + 1) + DBUG_RETURN(0); + if (tupleId <= info->m_last_tuple_id) { - info->m_first_tuple_id = val - 1; + info->m_first_tuple_id = tupleId - 1; DBUG_PRINT("info", ("Setting next auto increment cached value to %llu", - (ulonglong)val)); - DBUG_RETURN(val); + (ulonglong)tupleId)); + DBUG_RETURN(0); } } /* - * if value <= NEXTID, do nothing. otherwise update NEXTID to - * value and set cached range to first = last = value - 1. + * if tupleId <= NEXTID, do nothing. otherwise update NEXTID to + * tupleId and set cached range to first = last = tupleId - 1. */ - DBUG_RETURN((opTupleIdOnNdb(info, val, 2))); + if (opTupleIdOnNdb(info, tupleId, 2) == -1) + DBUG_RETURN(-1); } else + { /* * update NEXTID to given value. reset cached range. */ - DBUG_RETURN((opTupleIdOnNdb(info, val, 1))); + if (opTupleIdOnNdb(info, tupleId, 1) == -1) + DBUG_RETURN(-1); + } + DBUG_RETURN(0); } -Uint64 -Ndb::opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 opValue, Uint32 op) +int +Ndb::opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 & opValue, Uint32 op) { DBUG_ENTER("Ndb::opTupleIdOnNdb"); Uint32 aTableId = info->m_table_impl->m_tableId; @@ -954,7 +980,6 @@ Ndb::opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 opValue, Uint32 op) NdbOperation* tOperation= 0; // Compiler warning if not initialized Uint64 tValue; NdbRecAttr* tRecAttrResult; - Uint64 ret = ~(Uint64)0; CHECK_STATUS_MACRO_ZERO; @@ -989,7 +1014,7 @@ Ndb::opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 opValue, Uint32 op) info->m_first_tuple_id = tValue - opValue; info->m_last_tuple_id = tValue - 1; - ret = info->m_first_tuple_id; + opValue = info->m_first_tuple_id; // out break; case 1: // create on first use @@ -1002,7 +1027,6 @@ Ndb::opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 opValue, Uint32 op) info->m_first_tuple_id = ~(Uint64)0; info->m_last_tuple_id = ~(Uint64)0; - ret = opValue; break; case 2: tOperation->interpretedUpdateTuple(); @@ -1020,7 +1044,6 @@ Ndb::opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 opValue, Uint32 op) { if (tConnection->theError.code != 9999) goto error_handler; - ret = opValue; } else { @@ -1028,7 +1051,6 @@ Ndb::opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 opValue, Uint32 op) ("Setting next auto increment value (db) to %llu", (ulonglong)opValue)); info->m_first_tuple_id = info->m_last_tuple_id = opValue - 1; - ret = opValue; } break; case 3: @@ -1037,7 +1059,7 @@ Ndb::opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 opValue, Uint32 op) tRecAttrResult = tOperation->getValue("NEXTID"); if (tConnection->execute( Commit ) == -1 ) goto error_handler; - ret = tRecAttrResult->u_64_value(); + opValue = tRecAttrResult->u_64_value(); // out break; default: goto error_handler; @@ -1049,7 +1071,7 @@ Ndb::opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 opValue, Uint32 op) setDatabaseName(currentDb.c_str()); setDatabaseSchemaName(currentSchema.c_str()); - DBUG_RETURN(ret); + DBUG_RETURN(0); error_handler: theError.code = tConnection->theError.code; @@ -1063,7 +1085,7 @@ Ndb::opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 opValue, Uint32 op) theError.code, tConnection ? tConnection->theError.code : -1, tOperation ? tOperation->theError.code : -1)); - DBUG_RETURN(~(Uint64)0); + DBUG_RETURN(-1); } Uint32 diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/ndb/src/ndbapi/NdbDictionaryImpl.cpp index b3824df48f4..58452152dd9 100644 --- a/ndb/src/ndbapi/NdbDictionaryImpl.cpp +++ b/ndb/src/ndbapi/NdbDictionaryImpl.cpp @@ -1743,7 +1743,7 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb, if (haveAutoIncrement) { if (ndb.setAutoIncrementValue(impl.m_externalName.c_str(), - autoIncrementValue) == ~(Uint64)0) { + autoIncrementValue, false) == -1) { DBUG_ASSERT(ndb.theError.code != 0); m_error= ndb.theError; ret = -1; diff --git a/ndb/test/ndbapi/testDict.cpp b/ndb/test/ndbapi/testDict.cpp index dd5846f0d62..710a47bf3dc 100644 --- a/ndb/test/ndbapi/testDict.cpp +++ b/ndb/test/ndbapi/testDict.cpp @@ -1139,9 +1139,13 @@ runCreateAutoincrementTable(NDBT_Context* ctx, NDBT_Step* step){ for (int i = 0; i < 16; i++) { - Uint64 value = myNdb->getAutoIncrementValue(tabname, 1); - - if (value != (startvalue+i)) { + Uint64 value; + if (myNdb->getAutoIncrementValue(tabname, value, 1) == -1) { + g_err << "getAutoIncrementValue failed on " << tabname << endl; + APIERROR(myNdb->getNdbError()); + return NDBT_FAILED; + } + else if (value != (startvalue+i)) { g_err << "value = " << value << " expected " << startvalue+i << endl;; APIERROR(myNdb->getNdbError()); // ret = NDBT_FAILED; diff --git a/ndb/tools/restore/consumer_restore.cpp b/ndb/tools/restore/consumer_restore.cpp index 5563c51365b..d62ca3f610a 100644 --- a/ndb/tools/restore/consumer_restore.cpp +++ b/ndb/tools/restore/consumer_restore.cpp @@ -148,9 +148,12 @@ BackupRestore::finalize_table(const TableS & table){ if (table.have_auto_inc()) { Uint64 max_val= table.get_max_auto_val(); - Uint64 auto_val= m_ndb->readAutoIncrementValue(get_table(table.m_dictTable)); - if (max_val+1 > auto_val || auto_val == ~(Uint64)0) - ret= m_ndb->setAutoIncrementValue(get_table(table.m_dictTable), max_val+1, false) != ~(Uint64)0; + Uint64 auto_val; + int r= m_ndb->readAutoIncrementValue(get_table(table.m_dictTable), auto_val); + if (r == -1 && m_ndb->getNdbError().code != 626) + ret= false; + else if (r == -1 || max_val+1 > auto_val) + ret= m_ndb->setAutoIncrementValue(get_table(table.m_dictTable), max_val+1, false) != -1; } return ret; } diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index a7f680ffc1c..3937e9b24d0 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -73,7 +73,6 @@ handlerton ndbcluster_hton = { HTON_NO_FLAGS }; -#define NDB_FAILED_AUTO_INCREMENT ~(Uint64)0 #define NDB_AUTO_INCREMENT_RETRIES 10 #define NDB_INVALID_SCHEMA_OBJECT 241 @@ -2112,14 +2111,15 @@ int ha_ndbcluster::write_row(byte *record) { // Table has hidden primary key Ndb *ndb= get_ndb(); - Uint64 auto_value= NDB_FAILED_AUTO_INCREMENT; + int ret; + Uint64 auto_value; uint retries= NDB_AUTO_INCREMENT_RETRIES; do { - auto_value= ndb->getAutoIncrementValue((const NDBTAB *) m_table); - } while (auto_value == NDB_FAILED_AUTO_INCREMENT && + ret= ndb->getAutoIncrementValue((const NDBTAB *) m_table, auto_value, 1); + } while (ret == -1 && --retries && ndb->getNdbError().status == NdbError::TemporaryError); - if (auto_value == NDB_FAILED_AUTO_INCREMENT) + if (ret == -1) ERR_RETURN(ndb->getNdbError()); if (set_hidden_key(op, table->s->fields, (const byte*)&auto_value)) ERR_RETURN(op->getNdbError()); @@ -2200,7 +2200,7 @@ int ha_ndbcluster::write_row(byte *record) ("Trying to set next auto increment value to %llu", (ulonglong) next_val)); if (ndb->setAutoIncrementValue((const NDBTAB *) m_table, next_val, TRUE) - == ~(Uint64)0) + == -1) ERR_RETURN(ndb->getNdbError()); } m_skip_auto_increment= TRUE; @@ -3047,8 +3047,14 @@ void ha_ndbcluster::info(uint flag) { Ndb *ndb= get_ndb(); - auto_increment_value= - ndb->readAutoIncrementValue((const NDBTAB *) m_table); + if (ndb->readAutoIncrementValue((const NDBTAB *) m_table, + auto_increment_value) == -1) + { + const NdbError err= ndb->getNdbError(); + sql_print_error("Error %lu in readAutoIncrementValue(): %s", + (ulong) err.code, err.message); + auto_increment_value= ~(Uint64)0; + } } } DBUG_VOID_RETURN; @@ -4360,17 +4366,17 @@ ulonglong ha_ndbcluster::get_auto_increment() m_rows_to_insert - m_rows_inserted : ((m_rows_to_insert > m_autoincrement_prefetch) ? m_rows_to_insert : m_autoincrement_prefetch)); - auto_value= NDB_FAILED_AUTO_INCREMENT; + int ret; uint retries= NDB_AUTO_INCREMENT_RETRIES; do { - auto_value= - (m_skip_auto_increment) ? - ndb->readAutoIncrementValue((const NDBTAB *) m_table) - : ndb->getAutoIncrementValue((const NDBTAB *) m_table, cache_size); - } while (auto_value == NDB_FAILED_AUTO_INCREMENT && + ret= + m_skip_auto_increment ? + ndb->readAutoIncrementValue((const NDBTAB *) m_table, auto_value) : + ndb->getAutoIncrementValue((const NDBTAB *) m_table, auto_value, cache_size); + } while (ret == -1 && --retries && ndb->getNdbError().status == NdbError::TemporaryError); - if (auto_value == NDB_FAILED_AUTO_INCREMENT) + if (ret == -1) { const NdbError err= ndb->getNdbError(); sql_print_error("Error %lu in ::get_auto_increment(): %s", From 577246509f8d674d5a78dd631f91c6aab5759524 Mon Sep 17 00:00:00 2001 From: "pekka@mysql.com" <> Date: Thu, 25 May 2006 12:03:02 +0200 Subject: [PATCH 6/7] ndb - bug#14509 v5.1 part 1/2 : ndb api level [requires part 2/2] --- storage/ndb/include/ndbapi/Ndb.hpp | 37 +++-- storage/ndb/src/ndbapi/DictCache.cpp | 3 +- storage/ndb/src/ndbapi/DictCache.hpp | 3 +- storage/ndb/src/ndbapi/Ndb.cpp | 136 +++++++++++++------ storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp | 13 +- storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp | 2 - storage/ndb/src/ndbapi/ndberror.c | 1 - 7 files changed, 133 insertions(+), 62 deletions(-) diff --git a/storage/ndb/include/ndbapi/Ndb.hpp b/storage/ndb/include/ndbapi/Ndb.hpp index 8174bca0a5f..536f94a885a 100644 --- a/storage/ndb/include/ndbapi/Ndb.hpp +++ b/storage/ndb/include/ndbapi/Ndb.hpp @@ -1463,7 +1463,9 @@ public: /** * Return a unique tuple id for a table. The id sequence is - * ascending but may contain gaps. + * ascending but may contain gaps. Methods which have no + * TupleIdRange argument use NDB API dict cache. They may + * not be called from mysqld. * * @param aTableName table name * @@ -1471,28 +1473,47 @@ public: * * @return 0 or -1 on error, and tupleId in out parameter */ + struct TupleIdRange { + Uint64 m_first_tuple_id; + Uint64 m_last_tuple_id; + void reset() { + m_first_tuple_id = ~(Uint64)0; + m_last_tuple_id = ~(Uint64)0; + }; + }; + int initAutoIncrement(); int getAutoIncrementValue(const char* aTableName, Uint64 & tupleId, Uint32 cacheSize); int getAutoIncrementValue(const NdbDictionary::Table * aTable, Uint64 & tupleId, Uint32 cacheSize); + int getAutoIncrementValue(const NdbDictionary::Table * aTable, + TupleIdRange & range, Uint64 & tupleId, + Uint32 cacheSize); int readAutoIncrementValue(const char* aTableName, Uint64 & tupleId); int readAutoIncrementValue(const NdbDictionary::Table * aTable, Uint64 & tupleId); + int readAutoIncrementValue(const NdbDictionary::Table * aTable, + TupleIdRange & range, Uint64 & tupleId); int setAutoIncrementValue(const char* aTableName, Uint64 tupleId, bool increase); int setAutoIncrementValue(const NdbDictionary::Table * aTable, Uint64 tupleId, bool increase); + int setAutoIncrementValue(const NdbDictionary::Table * aTable, + TupleIdRange & range, Uint64 tupleId, + bool increase); private: - int getTupleIdFromNdb(Ndb_local_table_info* info, - Uint64 & tupleId, Uint32 cacheSize); - int readTupleIdFromNdb(Ndb_local_table_info* info, - Uint64 & tupleId); - int setTupleIdInNdb(Ndb_local_table_info* info, - Uint64 tupleId, bool increase); - int opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 & opValue, Uint32 op); + int getTupleIdFromNdb(const NdbTableImpl* table, + TupleIdRange & range, Uint64 & tupleId, + Uint32 cacheSize); + int readTupleIdFromNdb(const NdbTableImpl* table, + TupleIdRange & range, Uint64 & tupleId); + int setTupleIdInNdb(const NdbTableImpl* table, + TupleIdRange & range, Uint64 tupleId, bool increase); + int opTupleIdOnNdb(const NdbTableImpl* table, + TupleIdRange & range, Uint64 & opValue, Uint32 op); public: /** diff --git a/storage/ndb/src/ndbapi/DictCache.cpp b/storage/ndb/src/ndbapi/DictCache.cpp index 280b4210feb..5ed827b1b6d 100644 --- a/storage/ndb/src/ndbapi/DictCache.cpp +++ b/storage/ndb/src/ndbapi/DictCache.cpp @@ -47,8 +47,7 @@ Ndb_local_table_info::Ndb_local_table_info(NdbTableImpl *table_impl) { assert(! is_ndb_blob_table(table_impl)); m_table_impl= table_impl; - m_first_tuple_id = ~(Uint64)0; - m_last_tuple_id = ~(Uint64)0; + m_tuple_id_range.reset(); } Ndb_local_table_info::~Ndb_local_table_info() diff --git a/storage/ndb/src/ndbapi/DictCache.hpp b/storage/ndb/src/ndbapi/DictCache.hpp index 5bdaef88b94..b511387503a 100644 --- a/storage/ndb/src/ndbapi/DictCache.hpp +++ b/storage/ndb/src/ndbapi/DictCache.hpp @@ -35,8 +35,7 @@ public: NdbTableImpl *m_table_impl; // range of cached tuple ids per thread - Uint64 m_first_tuple_id; - Uint64 m_last_tuple_id; + Ndb::TupleIdRange m_tuple_id_range; Uint64 m_local_data[1]; // Must be last member. Used to access extra space. private: diff --git a/storage/ndb/src/ndbapi/Ndb.cpp b/storage/ndb/src/ndbapi/Ndb.cpp index 61c2dc725cf..3e4e66362c3 100644 --- a/storage/ndb/src/ndbapi/Ndb.cpp +++ b/storage/ndb/src/ndbapi/Ndb.cpp @@ -752,6 +752,7 @@ Ndb::getAutoIncrementValue(const char* aTableName, Uint64 & tupleId, Uint32 cacheSize) { DBUG_ENTER("Ndb::getAutoIncrementValue"); + ASSERT_NOT_MYSQLD; BaseString internal_tabname(internalize_table_name(aTableName)); Ndb_local_table_info *info= @@ -760,7 +761,9 @@ Ndb::getAutoIncrementValue(const char* aTableName, theError.code = theDictionary->getNdbError().code; DBUG_RETURN(-1); } - if (getTupleIdFromNdb(info, tupleId, cacheSize) == -1) + const NdbTableImpl* table = info->m_table_impl; + TupleIdRange & range = info->m_tuple_id_range; + if (getTupleIdFromNdb(table, range, tupleId, cacheSize) == -1) DBUG_RETURN(-1); DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId)); DBUG_RETURN(0); @@ -771,31 +774,48 @@ Ndb::getAutoIncrementValue(const NdbDictionary::Table * aTable, Uint64 & tupleId, Uint32 cacheSize) { DBUG_ENTER("Ndb::getAutoIncrementValue"); + ASSERT_NOT_MYSQLD; assert(aTable != 0); const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable); const BaseString& internal_tabname = table->m_internalName; Ndb_local_table_info *info= - theDictionary->get_local_table_info(internal_tabname, false); + theDictionary->get_local_table_info(internal_tabname); if (info == 0) { theError.code = theDictionary->getNdbError().code; DBUG_RETURN(-1); } - if (getTupleIdFromNdb(info, tupleId, cacheSize) == -1) + TupleIdRange & range = info->m_tuple_id_range; + if (getTupleIdFromNdb(table, range, tupleId, cacheSize) == -1) DBUG_RETURN(-1); DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId)); DBUG_RETURN(0); } int -Ndb::getTupleIdFromNdb(Ndb_local_table_info* info, - Uint64 & tupleId, Uint32 cacheSize) +Ndb::getAutoIncrementValue(const NdbDictionary::Table * aTable, + TupleIdRange & range, Uint64 & tupleId, + Uint32 cacheSize) +{ + DBUG_ENTER("Ndb::getAutoIncrementValue"); + assert(aTable != 0); + const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable); + + if (getTupleIdFromNdb(table, range, tupleId, cacheSize) == -1) + DBUG_RETURN(-1); + DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId)); + DBUG_RETURN(0); +} + +int +Ndb::getTupleIdFromNdb(const NdbTableImpl* table, + TupleIdRange & range, Uint64 & tupleId, Uint32 cacheSize) { DBUG_ENTER("Ndb::getTupleIdFromNdb"); - if (info->m_first_tuple_id != info->m_last_tuple_id) + if (range.m_first_tuple_id != range.m_last_tuple_id) { - assert(info->m_first_tuple_id < info->m_last_tuple_id); - tupleId = ++info->m_first_tuple_id; + assert(range.m_first_tuple_id < range.m_last_tuple_id); + tupleId = ++range.m_first_tuple_id; DBUG_PRINT("info", ("next cached value %llu", (ulonglong)tupleId)); } else @@ -808,7 +828,7 @@ Ndb::getTupleIdFromNdb(Ndb_local_table_info* info, * and returns first tupleId in the new range. */ Uint64 opValue = cacheSize; - if (opTupleIdOnNdb(info, opValue, 0) == -1) + if (opTupleIdOnNdb(table, range, opValue, 0) == -1) DBUG_RETURN(-1); tupleId = opValue; } @@ -820,15 +840,18 @@ Ndb::readAutoIncrementValue(const char* aTableName, Uint64 & tupleId) { DBUG_ENTER("Ndb::readAutoIncrementValue"); + ASSERT_NOT_MYSQLD; BaseString internal_tabname(internalize_table_name(aTableName)); Ndb_local_table_info *info= - theDictionary->get_local_table_info(internal_tabname, false); + theDictionary->get_local_table_info(internal_tabname); if (info == 0) { theError.code = theDictionary->getNdbError().code; DBUG_RETURN(-1); } - if (readTupleIdFromNdb(info, tupleId) == -1) + const NdbTableImpl* table = info->m_table_impl; + TupleIdRange & range = info->m_tuple_id_range; + if (readTupleIdFromNdb(table, range, tupleId) == -1) DBUG_RETURN(-1); DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId)); DBUG_RETURN(0); @@ -839,31 +862,47 @@ Ndb::readAutoIncrementValue(const NdbDictionary::Table * aTable, Uint64 & tupleId) { DBUG_ENTER("Ndb::readAutoIncrementValue"); + ASSERT_NOT_MYSQLD; assert(aTable != 0); const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable); const BaseString& internal_tabname = table->m_internalName; Ndb_local_table_info *info= - theDictionary->get_local_table_info(internal_tabname, false); + theDictionary->get_local_table_info(internal_tabname); if (info == 0) { theError.code = theDictionary->getNdbError().code; DBUG_RETURN(-1); } - if (readTupleIdFromNdb(info, tupleId) == -1) + TupleIdRange & range = info->m_tuple_id_range; + if (readTupleIdFromNdb(table, range, tupleId) == -1) DBUG_RETURN(-1); DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId)); DBUG_RETURN(0); } int -Ndb::readTupleIdFromNdb(Ndb_local_table_info* info, - Uint64 & tupleId) +Ndb::readAutoIncrementValue(const NdbDictionary::Table * aTable, + TupleIdRange & range, Uint64 & tupleId) +{ + DBUG_ENTER("Ndb::readAutoIncrementValue"); + assert(aTable != 0); + const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable); + + if (readTupleIdFromNdb(table, range, tupleId) == -1) + DBUG_RETURN(-1); + DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId)); + DBUG_RETURN(0); +} + +int +Ndb::readTupleIdFromNdb(const NdbTableImpl* table, + TupleIdRange & range, Uint64 & tupleId) { DBUG_ENTER("Ndb::readTupleIdFromNdb"); - if (info->m_first_tuple_id != info->m_last_tuple_id) + if (range.m_first_tuple_id != range.m_last_tuple_id) { - assert(info->m_first_tuple_id < info->m_last_tuple_id); - tupleId = info->m_first_tuple_id + 1; + assert(range.m_first_tuple_id < range.m_last_tuple_id); + tupleId = range.m_first_tuple_id + 1; } else { @@ -872,7 +911,7 @@ Ndb::readTupleIdFromNdb(Ndb_local_table_info* info, * only if no other transactions are allowed. */ Uint64 opValue = 0; - if (opTupleIdOnNdb(info, opValue, 3) == -1) + if (opTupleIdOnNdb(table, range, opValue, 3) == -1) DBUG_RETURN(-1); tupleId = opValue; } @@ -884,6 +923,7 @@ Ndb::setAutoIncrementValue(const char* aTableName, Uint64 tupleId, bool increase) { DBUG_ENTER("Ndb::setAutoIncrementValue"); + ASSERT_NOT_MYSQLD; BaseString internal_tabname(internalize_table_name(aTableName)); Ndb_local_table_info *info= @@ -892,7 +932,9 @@ Ndb::setAutoIncrementValue(const char* aTableName, theError.code = theDictionary->getNdbError().code; DBUG_RETURN(-1); } - if (setTupleIdInNdb(info, tupleId, increase) == -1) + const NdbTableImpl* table = info->m_table_impl; + TupleIdRange & range = info->m_tuple_id_range; + if (setTupleIdInNdb(table, range, tupleId, increase) == -1) DBUG_RETURN(-1); DBUG_RETURN(0); } @@ -902,36 +944,52 @@ Ndb::setAutoIncrementValue(const NdbDictionary::Table * aTable, Uint64 tupleId, bool increase) { DBUG_ENTER("Ndb::setAutoIncrementValue"); + ASSERT_NOT_MYSQLD; assert(aTable != 0); const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable); const BaseString& internal_tabname = table->m_internalName; Ndb_local_table_info *info= - theDictionary->get_local_table_info(internal_tabname, false); + theDictionary->get_local_table_info(internal_tabname); if (info == 0) { theError.code = theDictionary->getNdbError().code; DBUG_RETURN(-1); } - if (setTupleIdInNdb(info, tupleId, increase) == -1) + TupleIdRange & range = info->m_tuple_id_range; + if (setTupleIdInNdb(table, range, tupleId, increase) == -1) DBUG_RETURN(-1); DBUG_RETURN(0); } int -Ndb::setTupleIdInNdb(Ndb_local_table_info* info, - Uint64 tupleId, bool increase) +Ndb::setAutoIncrementValue(const NdbDictionary::Table * aTable, + TupleIdRange & range, Uint64 tupleId, + bool increase) +{ + DBUG_ENTER("Ndb::setAutoIncrementValue"); + assert(aTable != 0); + const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable); + + if (setTupleIdInNdb(table, range, tupleId, increase) == -1) + DBUG_RETURN(-1); + DBUG_RETURN(0); +} + +int +Ndb::setTupleIdInNdb(const NdbTableImpl* table, + TupleIdRange & range, Uint64 tupleId, bool increase) { DBUG_ENTER("Ndb::setTupleIdInNdb"); if (increase) { - if (info->m_first_tuple_id != info->m_last_tuple_id) + if (range.m_first_tuple_id != range.m_last_tuple_id) { - assert(info->m_first_tuple_id < info->m_last_tuple_id); - if (tupleId <= info->m_first_tuple_id + 1) + assert(range.m_first_tuple_id < range.m_last_tuple_id); + if (tupleId <= range.m_first_tuple_id + 1) DBUG_RETURN(0); - if (tupleId <= info->m_last_tuple_id) + if (tupleId <= range.m_last_tuple_id) { - info->m_first_tuple_id = tupleId - 1; + range.m_first_tuple_id = tupleId - 1; DBUG_PRINT("info", ("Setting next auto increment cached value to %llu", (ulonglong)tupleId)); @@ -942,7 +1000,7 @@ Ndb::setTupleIdInNdb(Ndb_local_table_info* info, * if tupleId <= NEXTID, do nothing. otherwise update NEXTID to * tupleId and set cached range to first = last = tupleId - 1. */ - if (opTupleIdOnNdb(info, tupleId, 2) == -1) + if (opTupleIdOnNdb(table, range, tupleId, 2) == -1) DBUG_RETURN(-1); } else @@ -950,7 +1008,7 @@ Ndb::setTupleIdInNdb(Ndb_local_table_info* info, /* * update NEXTID to given value. reset cached range. */ - if (opTupleIdOnNdb(info, tupleId, 1) == -1) + if (opTupleIdOnNdb(table, range, tupleId, 1) == -1) DBUG_RETURN(-1); } DBUG_RETURN(0); @@ -978,10 +1036,11 @@ int Ndb::initAutoIncrement() } int -Ndb::opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 & opValue, Uint32 op) +Ndb::opTupleIdOnNdb(const NdbTableImpl* table, + TupleIdRange & range, Uint64 & opValue, Uint32 op) { DBUG_ENTER("Ndb::opTupleIdOnNdb"); - Uint32 aTableId = info->m_table_impl->m_tableId; + Uint32 aTableId = table->m_id; DBUG_PRINT("enter", ("table=%u value=%llu op=%u", aTableId, opValue, op)); NdbTransaction* tConnection; @@ -1015,9 +1074,9 @@ Ndb::opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 & opValue, Uint32 op) tValue = tRecAttrResult->u_64_value(); - info->m_first_tuple_id = tValue - opValue; - info->m_last_tuple_id = tValue - 1; - opValue = info->m_first_tuple_id; // out + range.m_first_tuple_id = tValue - opValue; + range.m_last_tuple_id = tValue - 1; + opValue = range.m_first_tuple_id; // out break; case 1: // create on first use @@ -1028,8 +1087,7 @@ Ndb::opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 & opValue, Uint32 op) if (tConnection->execute( Commit ) == -1 ) goto error_handler; - info->m_first_tuple_id = ~(Uint64)0; - info->m_last_tuple_id = ~(Uint64)0; + range.reset(); break; case 2: tOperation->interpretedUpdateTuple(); @@ -1053,7 +1111,7 @@ Ndb::opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 & opValue, Uint32 op) DBUG_PRINT("info", ("Setting next auto increment value (db) to %llu", (ulonglong)opValue)); - info->m_first_tuple_id = info->m_last_tuple_id = opValue - 1; + range.m_first_tuple_id = range.m_last_tuple_id = opValue - 1; } break; case 3: diff --git a/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp index 8eb0b37120d..5d78472cef6 100644 --- a/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp +++ b/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp @@ -1343,9 +1343,6 @@ NdbDictionaryImpl::putTable(NdbTableImpl *impl) Ndb_local_table_info::create(impl, m_local_table_data_size); m_localHash.put(impl->m_internalName.c_str(), info); - - m_ndb.theFirstTupleId[impl->getTableId()] = ~0; - m_ndb.theLastTupleId[impl->getTableId()] = ~0; } int @@ -2205,11 +2202,11 @@ NdbDictionaryImpl::createTable(NdbTableImpl &t) } if (autoIncrement) { // XXX unlikely race condition - t.m_id may no longer be same table - if (! m_ndb.setTupleIdInNdb(t.m_id, initialValue, false)) { - if (m_ndb.theError.code) - m_error.code = m_ndb.theError.code; - else - m_error.code = 4336; + // the tuple id range is not used on input + Ndb::TupleIdRange range; + if (m_ndb.setTupleIdInNdb(&t, range, initialValue, false) == -1) { + assert(m_ndb.theError.code != 0); + m_error.code = m_ndb.theError.code; delete t2; DBUG_RETURN(-1); } diff --git a/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp b/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp index 5a7a1ebb0ab..9df52e1fda6 100644 --- a/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp +++ b/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp @@ -950,8 +950,6 @@ NdbDictionaryImpl::get_local_table_info(const BaseString& internalTableName) if (info) { m_localHash.put(internalTableName.c_str(), info); - m_ndb.theFirstTupleId[tab->getTableId()] = ~0; - m_ndb.theLastTupleId[tab->getTableId()] = ~0; } } } diff --git a/storage/ndb/src/ndbapi/ndberror.c b/storage/ndb/src/ndbapi/ndberror.c index 8185bf38c3e..c05924dacf8 100644 --- a/storage/ndb/src/ndbapi/ndberror.c +++ b/storage/ndb/src/ndbapi/ndberror.c @@ -600,7 +600,6 @@ ErrorBundle ErrorCodes[] = { { 4269, DMEC, IE, "No connection to ndb management server" }, { 4270, DMEC, IE, "Unknown blob error" }, { 4335, DMEC, AE, "Only one autoincrement column allowed per table. Having a table without primary key uses an autoincremented hidden key, i.e. a table without a primary key can not have an autoincremented column" }, - { 4336, DMEC, AE, "Auto-increment value set below current value" }, { 4271, DMEC, AE, "Invalid index object, not retrieved via getIndex()" }, { 4272, DMEC, AE, "Table definition has undefined column" }, { 4273, DMEC, IE, "No blob table in dict cache" }, From 7fcc77f49cf8e3a69583449005751ad5db0708d7 Mon Sep 17 00:00:00 2001 From: "pekka@mysql.com" <> Date: Thu, 25 May 2006 12:13:47 +0200 Subject: [PATCH 7/7] ndb - bug#14509 v5.1 part 2/2 : handler level --- mysql-test/r/ndb_basic.result | 48 +++++++++++++++---------------- mysql-test/t/ndb_alter_table.test | 30 +++++++++---------- sql/ha_ndbcluster.cc | 14 +++++---- sql/ha_ndbcluster.h | 15 +++++++++- 4 files changed, 62 insertions(+), 45 deletions(-) diff --git a/mysql-test/r/ndb_basic.result b/mysql-test/r/ndb_basic.result index 9477caf97ab..997a94d0afa 100644 --- a/mysql-test/r/ndb_basic.result +++ b/mysql-test/r/ndb_basic.result @@ -649,30 +649,30 @@ counter datavalue 6 newval 7 newval 8 newval -35 newval -36 newval -37 newval -38 newval -39 newval -40 newval -41 newval -42 newval -43 newval -44 newval -45 newval -46 newval -47 newval -48 newval -49 newval -50 newval -51 newval -52 newval -53 newval -54 newval -55 newval -56 newval -57 newval -58 newval +9 newval +10 newval +11 newval +12 newval +13 newval +14 newval +15 newval +16 newval +17 newval +18 newval +19 newval +20 newval +21 newval +22 newval +23 newval +24 newval +25 newval +26 newval +27 newval +28 newval +29 newval +30 newval +31 newval +32 newval drop table t1; CREATE TABLE t1 ( b INT ) PACK_KEYS = 0 ENGINE = ndb; select * from t1; diff --git a/mysql-test/t/ndb_alter_table.test b/mysql-test/t/ndb_alter_table.test index cd5c4819c51..8e3b4a6ca89 100644 --- a/mysql-test/t/ndb_alter_table.test +++ b/mysql-test/t/ndb_alter_table.test @@ -325,21 +325,6 @@ on t1 (c010, c011, c012, c013); drop table t1; -# simple test that auto incr is not lost at rename or alter -create table t1 (a int primary key auto_increment, b int) engine=ndb; -insert into t1 (b) values (101),(102),(103); -select * from t1 where a = 3; -alter table t1 rename t2; -insert into t2 (b) values (201),(202),(203); -select * from t2 where a = 6; -alter table t2 add c int; -insert into t2 (b) values (301),(302),(303); -select * from t2 where a = 9; -alter table t2 rename t1; -insert into t1 (b) values (401),(402),(403); -select * from t1 where a = 12; -drop table t1; - # End of 4.1 tests # On-line alter table @@ -398,3 +383,18 @@ LOAD DATA INFILE 'tmp.dat' INTO TABLE ndb_show_tables; select 'no_copy' from ndb_show_tables where id = @t1_id and name like '%t1%'; DROP TABLE t1, ndb_show_tables; + +# simple test that auto incr is not lost at rename or alter +create table t1 (a int primary key auto_increment, b int) engine=ndb; +insert into t1 (b) values (101),(102),(103); +select * from t1 where a = 3; +alter table t1 rename t2; +insert into t2 (b) values (201),(202),(203); +select * from t2 where a = 6; +alter table t2 add c int; +insert into t2 (b) values (301),(302),(303); +select * from t2 where a = 9; +alter table t2 rename t1; +insert into t1 (b) values (401),(402),(403); +select * from t1 where a = 12; +drop table t1; diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index a17416e006d..0baf2e09473 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -2464,7 +2464,8 @@ int ha_ndbcluster::write_row(byte *record) Uint64 auto_value; uint retries= NDB_AUTO_INCREMENT_RETRIES; do { - ret= ndb->getAutoIncrementValue(m_table, auto_value, 1); + Ndb_tuple_id_range_guard g(m_share); + ret= ndb->getAutoIncrementValue(m_table, g.range, auto_value, 1); } while (ret == -1 && --retries && ndb->getNdbError().status == NdbError::TemporaryError); @@ -2565,7 +2566,8 @@ int ha_ndbcluster::write_row(byte *record) DBUG_PRINT("info", ("Trying to set next auto increment value to %llu", (ulonglong) next_val)); - if (ndb->setAutoIncrementValue(m_table, next_val, TRUE) + Ndb_tuple_id_range_guard g(m_share); + if (ndb->setAutoIncrementValue(m_table, g.range, next_val, TRUE) == -1) ERR_RETURN(ndb->getNdbError()); } @@ -3528,8 +3530,9 @@ void ha_ndbcluster::info(uint flag) if (m_table) { Ndb *ndb= get_ndb(); + Ndb_tuple_id_range_guard g(m_share); - if (ndb->readAutoIncrementValue(m_table, + if (ndb->readAutoIncrementValue(m_table, g.range, auto_increment_value) == -1) { const NdbError err= ndb->getNdbError(); @@ -5231,10 +5234,11 @@ ulonglong ha_ndbcluster::get_auto_increment() int ret; uint retries= NDB_AUTO_INCREMENT_RETRIES; do { + Ndb_tuple_id_range_guard g(m_share); ret= m_skip_auto_increment ? - ndb->readAutoIncrementValue(m_table, auto_value) : - ndb->getAutoIncrementValue(m_table, auto_value, cache_size); + ndb->readAutoIncrementValue(m_table, g.range, auto_value) : + ndb->getAutoIncrementValue(m_table, g.range, auto_value, cache_size); } while (ret == -1 && --retries && ndb->getNdbError().status == NdbError::TemporaryError); diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h index f407cb0090f..f113994f3b2 100644 --- a/sql/ha_ndbcluster.h +++ b/sql/ha_ndbcluster.h @@ -106,6 +106,7 @@ typedef struct st_ndbcluster_share { ulonglong commit_count; char *db; char *table_name; + Ndb::TupleIdRange tuple_id_range; #ifdef HAVE_NDB_BINLOG uint32 flags; NdbEventOperation *op; @@ -138,6 +139,19 @@ set_ndb_share_state(NDB_SHARE *share, NDB_SHARE_STATE state) pthread_mutex_unlock(&share->mutex); } +struct Ndb_tuple_id_range_guard { + Ndb_tuple_id_range_guard(NDB_SHARE* _share) : + share(_share), + range(share->tuple_id_range) { + pthread_mutex_lock(&share->mutex); + } + ~Ndb_tuple_id_range_guard() { + pthread_mutex_unlock(&share->mutex); + } + NDB_SHARE* share; + Ndb::TupleIdRange& range; +}; + #ifdef HAVE_NDB_BINLOG /* NDB_SHARE.flags */ #define NSF_HIDDEN_PK 1 /* table has hidden primary key */ @@ -725,7 +739,6 @@ private: int drop_indexes(Ndb *ndb, TABLE *tab); int add_index_handle(THD *thd, NdbDictionary::Dictionary *dict, KEY *key_info, const char *index_name, uint index_no); - int initialize_autoincrement(const void *table); int get_metadata(const char* path); void release_metadata(THD *thd, Ndb *ndb); NDB_INDEX_TYPE get_index_type(uint idx_no) const;