diff options
author | unknown <tomas@whalegate.ndb.mysql.com> | 2007-05-10 08:06:09 +0200 |
---|---|---|
committer | unknown <tomas@whalegate.ndb.mysql.com> | 2007-05-10 08:06:09 +0200 |
commit | 8d8a3205c579333ae84c9242365ddca0202306d9 (patch) | |
tree | 2d5565953b289fe2d26ba02e3f090fec5de45661 /storage | |
parent | b32473a3d56374ae2620ecead5d29ff6d2239e96 (diff) | |
parent | 3d78e6fcd3b99c69416893a30e991aeb51eb6763 (diff) | |
download | mariadb-git-8d8a3205c579333ae84c9242365ddca0202306d9.tar.gz |
Merge whalegate.ndb.mysql.com:/home/tomas/mysql-5.1-opt
into whalegate.ndb.mysql.com:/home/tomas/mysql-5.1-single-user
sql/field.cc:
Auto merged
sql/field.h:
Auto merged
sql/ha_ndbcluster.cc:
Auto merged
sql/sql_table.cc:
Auto merged
sql/handler.cc:
manual merge
sql/mysqld.cc:
manual merge
sql/set_var.cc:
manual merge
sql/sql_plugin.cc:
manual merge
Diffstat (limited to 'storage')
-rw-r--r-- | storage/ndb/config/common.mk.am | 2 | ||||
-rw-r--r-- | storage/ndb/include/ndbapi/NdbRecAttr.hpp | 28 | ||||
-rw-r--r-- | storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp | 15 | ||||
-rw-r--r-- | storage/ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp | 2 | ||||
-rw-r--r-- | storage/ndb/src/kernel/vm/DynArr256.cpp | 101 | ||||
-rw-r--r-- | storage/ndb/src/kernel/vm/DynArr256.hpp | 12 | ||||
-rw-r--r-- | storage/ndb/src/mgmsrv/ConfigInfo.cpp | 33 | ||||
-rw-r--r-- | storage/ndb/src/mgmsrv/MgmtSrvr.cpp | 10 | ||||
-rw-r--r-- | storage/ndb/src/ndbapi/ClusterMgr.cpp | 6 | ||||
-rw-r--r-- | storage/ndb/src/ndbapi/ClusterMgr.hpp | 2 | ||||
-rw-r--r-- | storage/ndb/src/ndbapi/NdbRecAttr.cpp | 6 | ||||
-rw-r--r-- | storage/ndb/src/ndbapi/ndberror.c | 2 | ||||
-rw-r--r-- | storage/ndb/test/ndbapi/testBasic.cpp | 125 | ||||
-rw-r--r-- | storage/ndb/test/run-test/daily-basic-tests.txt | 4 | ||||
-rw-r--r-- | storage/ndb/tools/restore/consumer_restore.cpp | 35 | ||||
-rw-r--r-- | storage/ndb/tools/restore/consumer_restore.hpp | 2 | ||||
-rw-r--r-- | storage/ndb/tools/restore/restore_main.cpp | 13 |
17 files changed, 322 insertions, 76 deletions
diff --git a/storage/ndb/config/common.mk.am b/storage/ndb/config/common.mk.am index 5ed3855f31e..9633a52e91f 100644 --- a/storage/ndb/config/common.mk.am +++ b/storage/ndb/config/common.mk.am @@ -25,3 +25,5 @@ INCLUDES = $(INCLUDES_LOC) LDADD = $(LDADD_LOC) DEFS = @DEFS@ @NDB_DEFS@ $(DEFS_LOC) $(NDB_EXTRA_FLAGS) NDB_CXXFLAGS=@ndb_cxxflags_fix@ $(NDB_CXXFLAGS_LOC) +NDB_AM_CXXFLAGS:= $(AM_CXXFLAGS) +AM_CXXFLAGS=$(NDB_AM_CXXFLAGS) $(NDB_CXXFLAGS) diff --git a/storage/ndb/include/ndbapi/NdbRecAttr.hpp b/storage/ndb/include/ndbapi/NdbRecAttr.hpp index ac098831180..121339e470b 100644 --- a/storage/ndb/include/ndbapi/NdbRecAttr.hpp +++ b/storage/ndb/include/ndbapi/NdbRecAttr.hpp @@ -153,6 +153,13 @@ public: /** * Get value stored in NdbRecAttr object. * + * @return Int8 value. + */ + Int8 int8_value() const; + + /** + * Get value stored in NdbRecAttr object. + * * @return 64 bit unsigned value. */ Uint64 u_64_value() const; @@ -188,6 +195,13 @@ public: /** * Get value stored in NdbRecAttr object. * + * @return Uint8 value. + */ + Uint8 u_8_value() const; + + /** + * Get value stored in NdbRecAttr object. + * * @return Float value. */ float float_value() const; @@ -316,6 +330,13 @@ NdbRecAttr::char_value() const } inline +Int8 +NdbRecAttr::int8_value() const +{ + return *(Int8*)theRef; +} + +inline Uint32 NdbRecAttr::u_32_value() const { @@ -337,6 +358,13 @@ NdbRecAttr::u_char_value() const } inline +Uint8 +NdbRecAttr::u_8_value() const +{ + return *(Uint8*)theRef; +} + +inline void NdbRecAttr::release() { diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp index 69b2d6d116e..59b3de2227b 100644 --- a/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp +++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp @@ -1201,9 +1201,19 @@ int Dbtup::handleInsertReq(Signal* signal, if(!prevOp->is_first_operation()) org= (Tuple_header*)c_undo_buffer.get_ptr(&prevOp->m_copy_tuple_location); if (regTabPtr->need_expand()) + { expand_tuple(req_struct, sizes, org, regTabPtr, !disk_insert); + memset(req_struct->m_disk_ptr->m_null_bits+ + regTabPtr->m_offsets[DD].m_null_offset, 0xFF, + 4*regTabPtr->m_offsets[DD].m_null_words); + } else + { memcpy(dst, org, 4*regTabPtr->m_offsets[MM].m_fix_header_size); + } + memset(tuple_ptr->m_null_bits+ + regTabPtr->m_offsets[MM].m_null_offset, 0xFF, + 4*regTabPtr->m_offsets[MM].m_null_words); } if (disk_insert) @@ -1491,6 +1501,7 @@ int Dbtup::handleDeleteReq(Signal* signal, goto error; } memcpy(dst, org, regTabPtr->total_rec_size << 2); + req_struct->m_tuple_ptr = (Tuple_header*)dst; } else { @@ -1528,7 +1539,9 @@ int Dbtup::handleDeleteReq(Signal* signal, return 0; } - if (setup_read(req_struct, regOperPtr, regFragPtr, regTabPtr, disk)) + if (regTabPtr->need_expand(disk)) + prepare_read(req_struct, regTabPtr, disk); + { Uint32 RlogSize; int ret= handleReadReq(signal, regOperPtr, regTabPtr, req_struct); diff --git a/storage/ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp b/storage/ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp index 966f82cc9c2..411e7064efa 100644 --- a/storage/ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp +++ b/storage/ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp @@ -75,7 +75,7 @@ template <class T> class MemoryChannel { public: - MemoryChannel( int size= 256); + MemoryChannel( int size= 512); virtual ~MemoryChannel( ); void writeChannel( T *t); diff --git a/storage/ndb/src/kernel/vm/DynArr256.cpp b/storage/ndb/src/kernel/vm/DynArr256.cpp index ff3e7578c6c..cfa8b8a51e6 100644 --- a/storage/ndb/src/kernel/vm/DynArr256.cpp +++ b/storage/ndb/src/kernel/vm/DynArr256.cpp @@ -344,18 +344,28 @@ err: void DynArr256::init(ReleaseIterator &iter) { - iter.m_sz = 0; + iter.m_sz = 1; iter.m_pos = 0; - iter.m_ptr_i[0] = m_head.m_ptr_i; - iter.m_ptr_i[1] = RNIL; + iter.m_ptr_i[0] = RNIL; + iter.m_ptr_i[1] = m_head.m_ptr_i; iter.m_ptr_i[2] = RNIL; iter.m_ptr_i[3] = RNIL; + iter.m_ptr_i[4] = RNIL; } -bool -DynArr256::release(ReleaseIterator &iter) +/** + * Iter is in next pos + * + * 0 - done + * 1 - data + * 2 - no data + */ +Uint32 +DynArr256::release(ReleaseIterator &iter, Uint32 * retptr) { - Uint32 ptrI = iter.m_ptr_i[iter.m_sz]; + Uint32 sz = iter.m_sz; + Uint32 pos = iter.m_pos; + Uint32 ptrI = iter.m_ptr_i[sz]; Uint32 page_no = ptrI >> DA256_BITS; Uint32 page_idx = ptrI & DA256_MASK; Uint32 type_id = (~m_pool.m_type_id) & 0xFFFF; @@ -364,9 +374,8 @@ DynArr256::release(ReleaseIterator &iter) if (ptrI != RNIL) { - Uint32 tmp = iter.m_pos & 255; - Uint32 p0 = tmp; - for (; p0<256 && p0 < tmp + 16; p0++) + Uint32 p0 = iter.m_pos & 255; + for (; p0<256; p0++) { Uint32 *retVal, *magic_ptr, p; if (p0 != 255) @@ -389,55 +398,53 @@ DynArr256::release(ReleaseIterator &iter) } Uint32 magic = *magic_ptr; + Uint32 val = *retVal; if (unlikely(! ((magic & (1 << p)) && (magic >> 16) == type_id))) goto err; - Uint32 val = * retVal; - if (val != RNIL) + if (sz == m_head.m_sz) { - if (iter.m_sz + 2 == m_head.m_sz) + * retptr = val; + p0++; + if (p0 != 256) { - * retVal = RNIL; - m_pool.release(val); - iter.m_pos = (iter.m_pos & ~255) + p0; - return false; + /** + * Move next + */ + iter.m_pos &= ~(Uint32)255; + iter.m_pos |= p0; } else { - * retVal = RNIL; - iter.m_sz++; - iter.m_ptr_i[iter.m_sz] = val; - iter.m_pos = (p0 << 8); - return false; + /** + * Move up + */ + m_pool.release(ptrI); + iter.m_sz --; + iter.m_pos >>= 8; } + return 1; + } + else if (val != RNIL) + { + iter.m_sz++; + iter.m_ptr_i[iter.m_sz] = val; + iter.m_pos = (p0 << 8); + * retVal = RNIL; + return 2; } } - if (p0 == 256) - { - if (iter.m_sz == 0) - goto done; - iter.m_sz--; - iter.m_pos >>= 8; - - m_pool.release(ptrI); - return false; - } - else - { - iter.m_pos = (iter.m_pos & ~255) + p0; - return false; - } + assert(p0 == 256); + m_pool.release(ptrI); + iter.m_sz --; + iter.m_pos >>= 8; + return 2; } done: - if (m_head.m_ptr_i != RNIL) - { - m_pool.release(m_head.m_ptr_i); - } - new (&m_head) Head(); - return true; + return 0; err: require(false); @@ -638,6 +645,7 @@ static void simple(DynArr256 & arr, int argc, char* argv[]) { + ndbout_c("argc: %d", argc); for (Uint32 i = 1; i<(Uint32)argc; i++) { Uint32 * s = arr.set(atoi(argv[i])); @@ -865,7 +873,8 @@ write(DynArr256& arr, int argc, char ** argv) ndbout_c("Elapsed %lldus -> %f us/set", start, uspg); DynArr256::ReleaseIterator iter; arr.init(iter); - while(!arr.release(iter)); + Uint32 val; + while(arr.release(iter, &val)); } } @@ -902,7 +911,7 @@ main(int argc, char** argv) DynArr256::Head head; DynArr256 arr(pool, head); - if (strcmp(argv[1], "--args") == 0) + if (strcmp(argv[1], "--simple") == 0) simple(arr, argc, argv); else if (strcmp(argv[1], "--basic") == 0) basic(arr, argc, argv); @@ -913,8 +922,8 @@ main(int argc, char** argv) DynArr256::ReleaseIterator iter; arr.init(iter); - Uint32 cnt = 0; - while (!arr.release(iter)) cnt++; + Uint32 cnt = 0, val; + while (arr.release(iter, &val)) cnt++; ndbout_c("allocatedpages: %d allocatednodes: %d releasednodes: %d" " releasecnt: %d", diff --git a/storage/ndb/src/kernel/vm/DynArr256.hpp b/storage/ndb/src/kernel/vm/DynArr256.hpp index 31329add1a2..780dee7e4bf 100644 --- a/storage/ndb/src/kernel/vm/DynArr256.hpp +++ b/storage/ndb/src/kernel/vm/DynArr256.hpp @@ -49,6 +49,8 @@ public: Uint32 m_ptr_i; Uint32 m_sz; + + bool isEmpty() const { return m_sz == 0;} }; DynArr256(DynArr256Pool & pool, Head& head) : @@ -61,12 +63,16 @@ public: { Uint32 m_sz; Uint32 m_pos; - Uint32 m_ptr_i[4]; + Uint32 m_ptr_i[5]; }; void init(ReleaseIterator&); - bool release(ReleaseIterator&); - + /** + * return 0 - done + * 1 - data (in retptr) + * 2 - nodata + */ + Uint32 release(ReleaseIterator&, Uint32* retptr); protected: Head & m_head; DynArr256Pool & m_pool; diff --git a/storage/ndb/src/mgmsrv/ConfigInfo.cpp b/storage/ndb/src/mgmsrv/ConfigInfo.cpp index 26e50cb8a68..e27e55d2a13 100644 --- a/storage/ndb/src/mgmsrv/ConfigInfo.cpp +++ b/storage/ndb/src/mgmsrv/ConfigInfo.cpp @@ -2897,25 +2897,50 @@ static bool fixNodeId(InitConfigFileParser::Context & ctx, const char * data) char buf[] = "NodeIdX"; buf[6] = data[sizeof("NodeI")]; char sysbuf[] = "SystemX"; sysbuf[6] = data[sizeof("NodeI")]; const char* nodeId; - require(ctx.m_currentSection->get(buf, &nodeId)); + if(!ctx.m_currentSection->get(buf, &nodeId)) + { + ctx.reportError("Mandatory parameter %s missing from section" + "[%s] starting at line: %d", + buf, ctx.fname, ctx.m_sectionLineno); + return false; + } char tmpLine[MAX_LINE_LENGTH]; strncpy(tmpLine, nodeId, MAX_LINE_LENGTH); char* token1 = strtok(tmpLine, "."); char* token2 = strtok(NULL, "."); Uint32 id; - + + if(!token1) + { + ctx.reportError("Value for mandatory parameter %s missing from section " + "[%s] starting at line: %d", + buf, ctx.fname, ctx.m_sectionLineno); + return false; + } if (token2 == NULL) { // Only a number given errno = 0; char* p; id = strtol(token1, &p, 10); - if (errno != 0) warning("STRTOK1", nodeId); + if (errno != 0 || id <= 0x0 || id > MAX_NODES) + { + ctx.reportError("Illegal value for mandatory parameter %s from section " + "[%s] starting at line: %d", + buf, ctx.fname, ctx.m_sectionLineno); + return false; + } require(ctx.m_currentSection->put(buf, id, true)); } else { // A pair given (e.g. "uppsala.32") errno = 0; char* p; id = strtol(token2, &p, 10); - if (errno != 0) warning("STRTOK2", nodeId); + if (errno != 0 || id <= 0x0 || id > MAX_NODES) + { + ctx.reportError("Illegal value for mandatory parameter %s from section " + "[%s] starting at line: %d", + buf, ctx.fname, ctx.m_sectionLineno); + return false; + } require(ctx.m_currentSection->put(buf, id, true)); require(ctx.m_currentSection->put(sysbuf, token1)); } diff --git a/storage/ndb/src/mgmsrv/MgmtSrvr.cpp b/storage/ndb/src/mgmsrv/MgmtSrvr.cpp index dde6829c82c..f84c79b704f 100644 --- a/storage/ndb/src/mgmsrv/MgmtSrvr.cpp +++ b/storage/ndb/src/mgmsrv/MgmtSrvr.cpp @@ -628,6 +628,16 @@ MgmtSrvr::start(BaseString &error_string) ndbout_c("This is probably a bug."); } + /* + set api reg req frequency quite high: + + 100 ms interval to make sure we have fairly up-to-date + info from the nodes. This to make sure that this info + is not dependent on heart beat settings in the + configuration + */ + theFacade->theClusterMgr->set_max_api_reg_req_interval(100); + TransporterRegistry *reg = theFacade->get_registry(); for(unsigned int i=0;i<reg->m_transporter_interface.size();i++) { BaseString msg; diff --git a/storage/ndb/src/ndbapi/ClusterMgr.cpp b/storage/ndb/src/ndbapi/ClusterMgr.cpp index 52c95df6d15..f51a5098c53 100644 --- a/storage/ndb/src/ndbapi/ClusterMgr.cpp +++ b/storage/ndb/src/ndbapi/ClusterMgr.cpp @@ -61,6 +61,7 @@ ClusterMgr::ClusterMgr(TransporterFacade & _facade): clusterMgrThreadMutex = NdbMutex_Create(); waitForHBCond= NdbCondition_Create(); waitingForHB= false; + m_max_api_reg_req_interval= 0xFFFFFFFF; // MAX_INT noOfAliveNodes= 0; noOfConnectedNodes= 0; theClusterMgrThread= 0; @@ -243,7 +244,7 @@ ClusterMgr::threadMain( ){ } theFacade.lock_mutex(); - for (int i = 1; i < MAX_NODES; i++){ + for (int i = 1; i < MAX_NDB_NODES; i++){ /** * Send register request (heartbeat) to all available nodes * at specified timing intervals @@ -264,7 +265,8 @@ ClusterMgr::threadMain( ){ } theNode.hbCounter += timeSlept; - if (theNode.hbCounter >= theNode.hbFrequency) { + if (theNode.hbCounter >= m_max_api_reg_req_interval || + theNode.hbCounter >= theNode.hbFrequency) { /** * It is now time to send a new Heartbeat */ diff --git a/storage/ndb/src/ndbapi/ClusterMgr.hpp b/storage/ndb/src/ndbapi/ClusterMgr.hpp index 6e74620dd4f..0a261eb202f 100644 --- a/storage/ndb/src/ndbapi/ClusterMgr.hpp +++ b/storage/ndb/src/ndbapi/ClusterMgr.hpp @@ -50,6 +50,7 @@ public: void startThread(); void forceHB(); + void set_max_api_reg_req_interval(unsigned int millisec) { m_max_api_reg_req_interval = millisec; } private: void threadMain(); @@ -89,6 +90,7 @@ public: Uint32 m_connect_count; private: + Uint32 m_max_api_reg_req_interval; Uint32 noOfAliveNodes; Uint32 noOfConnectedNodes; Node theNodes[MAX_NODES]; diff --git a/storage/ndb/src/ndbapi/NdbRecAttr.cpp b/storage/ndb/src/ndbapi/NdbRecAttr.cpp index 7615ee71c65..38ca14085f0 100644 --- a/storage/ndb/src/ndbapi/NdbRecAttr.cpp +++ b/storage/ndb/src/ndbapi/NdbRecAttr.cpp @@ -270,7 +270,7 @@ ndbrecattr_print_formatted(NdbOut& out, const NdbRecAttr &r, out << r.u_short_value(); break; case NdbDictionary::Column::Tinyunsigned: - out << (unsigned) r.u_char_value(); + out << (unsigned) r.u_8_value(); break; case NdbDictionary::Column::Bigint: out << r.int64_value(); @@ -285,7 +285,7 @@ ndbrecattr_print_formatted(NdbOut& out, const NdbRecAttr &r, out << r.short_value(); break; case NdbDictionary::Column::Tinyint: - out << (int) r.char_value(); + out << (int) r.int8_value(); break; case NdbDictionary::Column::Binary: if (!f.hex_format) @@ -411,7 +411,7 @@ ndbrecattr_print_formatted(NdbOut& out, const NdbRecAttr &r, break; case NdbDictionary::Column::Year: { - uint year = 1900 + r.u_char_value(); + uint year = 1900 + r.u_8_value(); char buf[40]; sprintf(buf, "%04d", year); out << buf; diff --git a/storage/ndb/src/ndbapi/ndberror.c b/storage/ndb/src/ndbapi/ndberror.c index 3cecd15684d..8c40ddf2116 100644 --- a/storage/ndb/src/ndbapi/ndberror.c +++ b/storage/ndb/src/ndbapi/ndberror.c @@ -151,7 +151,7 @@ ErrorBundle ErrorCodes[] = { */ { 4007, DMEC, UR, "Send to ndbd node failed" }, { 4008, DMEC, UR, "Receive from NDB failed" }, - { 4009, DMEC, UR, "Cluster Failure" }, + { 4009, HA_ERR_NO_CONNECTION, UR, "Cluster Failure" }, { 4012, DMEC, UR, "Request ndbd time-out, maybe due to high load or communication problems"}, { 4013, DMEC, UR, "Request timed out in waiting for node failure"}, diff --git a/storage/ndb/test/ndbapi/testBasic.cpp b/storage/ndb/test/ndbapi/testBasic.cpp index 44c3d023169..952b5a50dc5 100644 --- a/storage/ndb/test/ndbapi/testBasic.cpp +++ b/storage/ndb/test/ndbapi/testBasic.cpp @@ -1290,17 +1290,7 @@ runDeleteRead(NDBT_Context* ctx, NDBT_Step* step){ NdbTransaction* pTrans = pNdb->startTransaction(); NdbOperation* pOp = pTrans->getNdbOperation(tab->getName()); pOp->deleteTuple(); - for(a = 0; a<tab->getNoOfColumns(); a++) - { - if (tab->getColumn(a)->getPrimaryKey() == true) - { - if(tmp.equalForAttr(pOp, a, 0) != 0) - { - ERR(pTrans->getNdbError()); - return NDBT_FAILED; - } - } - } + tmp.equalForRow(pOp, loops); // Define attributes to read for(a = 0; a<tab->getNoOfColumns(); a++) @@ -1313,6 +1303,30 @@ runDeleteRead(NDBT_Context* ctx, NDBT_Step* step){ pTrans->execute(Commit); pTrans->close(); + + pTrans = pNdb->startTransaction(); + pOp = pTrans->getNdbOperation(tab->getName()); + pOp->insertTuple(); + tmp.setValues(pOp, loops, 0); + + pOp = pTrans->getNdbOperation(tab->getName()); + pOp->deleteTuple(); + tmp.equalForRow(pOp, loops); + for(a = 0; a<tab->getNoOfColumns(); a++) + { + if((row.attributeStore(a) = pOp->getValue(tab->getColumn(a)->getName())) == 0) + { + ERR(pTrans->getNdbError()); + return NDBT_FAILED; + } + } + if (pTrans->execute(Commit) != 0) + { + ERR(pTrans->getNdbError()); + return NDBT_FAILED; + } + + pTrans->close(); } return NDBT_OK; @@ -1444,6 +1458,91 @@ runBug28073(NDBT_Context *ctx, NDBT_Step* step) template class Vector<Uint64>; +int +runBug20535(NDBT_Context* ctx, NDBT_Step* step) +{ + Uint32 i; + Ndb* pNdb = GETNDB(step); + const NdbDictionary::Table * tab = ctx->getTab(); + NdbDictionary::Dictionary * dict = pNdb->getDictionary(); + + bool null = false; + for (i = 0; i<tab->getNoOfColumns(); i++) + { + if (tab->getColumn(i)->getNullable()) + { + null = true; + break; + } + } + + if (!null) + return NDBT_OK; + + HugoTransactions hugoTrans(* tab); + hugoTrans.loadTable(pNdb, 1); + + NdbTransaction* pTrans = pNdb->startTransaction(); + NdbOperation* pOp = pTrans->getNdbOperation(tab->getName()); + pOp->deleteTuple(); + hugoTrans.equalForRow(pOp, 0); + if (pTrans->execute(NoCommit) != 0) + return NDBT_FAILED; + + pOp = pTrans->getNdbOperation(tab->getName()); + pOp->insertTuple(); + hugoTrans.equalForRow(pOp, 0); + for (i = 0; i<tab->getNoOfColumns(); i++) + { + if (!tab->getColumn(i)->getPrimaryKey() && + !tab->getColumn(i)->getNullable()) + { + hugoTrans.setValueForAttr(pOp, i, 0, 1); + } + } + + if (pTrans->execute(Commit) != 0) + return NDBT_FAILED; + + pTrans->close(); + + pTrans = pNdb->startTransaction(); + pOp = pTrans->getNdbOperation(tab->getName()); + pOp->readTuple(); + hugoTrans.equalForRow(pOp, 0); + Vector<NdbRecAttr*> values; + for (i = 0; i<tab->getNoOfColumns(); i++) + { + if (!tab->getColumn(i)->getPrimaryKey() && + tab->getColumn(i)->getNullable()) + { + values.push_back(pOp->getValue(i)); + } + } + + if (pTrans->execute(Commit) != 0) + return NDBT_FAILED; + + null = true; + for (i = 0; i<values.size(); i++) + { + if (!values[i]->isNULL()) + { + null = false; + ndbout_c("column %s is not NULL", values[i]->getColumn()->getName()); + } + } + + pTrans->close(); + + if (null) + return NDBT_OK; + else + return NDBT_FAILED; +} + +template class Vector<NdbRecAttr*>; + NDBT_TESTSUITE(testBasic); TESTCASE("PkInsert", "Verify that we can insert and delete from this table using PK" @@ -1728,6 +1827,10 @@ TESTCASE("Bug28073", "Infinite loop in lock queue" ){ STEP(runBug28073); } +TESTCASE("Bug20535", + "Verify what happens when we fill the db" ){ + STEP(runBug20535); +} NDBT_TESTSUITE_END(testBasic); #if 0 diff --git a/storage/ndb/test/run-test/daily-basic-tests.txt b/storage/ndb/test/run-test/daily-basic-tests.txt index 96473c28199..e080536dad9 100644 --- a/storage/ndb/test/run-test/daily-basic-tests.txt +++ b/storage/ndb/test/run-test/daily-basic-tests.txt @@ -248,6 +248,10 @@ cmd: testBasic args: -n Bug28073 max-time: 500 +cmd: testBasic +args: -n Bug20535 + +max-time: 500 cmd: testIndex args: -n Bug25059 -r 3000 T1 diff --git a/storage/ndb/tools/restore/consumer_restore.cpp b/storage/ndb/tools/restore/consumer_restore.cpp index 3dd4b072671..b7db8145c56 100644 --- a/storage/ndb/tools/restore/consumer_restore.cpp +++ b/storage/ndb/tools/restore/consumer_restore.cpp @@ -894,6 +894,21 @@ BackupRestore::table(const TableS & table){ { copy.setMaxRows(table.getNoOfRecords()); } + + NdbTableImpl &tableImpl = NdbTableImpl::getImpl(copy); + if (table.getBackupVersion() < MAKE_VERSION(5,1,0) && !m_no_upgrade){ + for(int i= 0; i < copy.getNoOfColumns(); i++) + { + NdbDictionary::Column::Type t = copy.getColumn(i)->getType(); + + if (t == NdbDictionary::Column::Varchar || + t == NdbDictionary::Column::Varbinary) + tableImpl.getColumn(i)->setArrayType(NdbDictionary::Column::ArrayTypeShortVar); + if (t == NdbDictionary::Column::Longvarchar || + t == NdbDictionary::Column::Longvarbinary) + tableImpl.getColumn(i)->setArrayType(NdbDictionary::Column::ArrayTypeMediumVar); + } + } if (dict->createTable(copy) == -1) { @@ -1141,8 +1156,22 @@ void BackupRestore::tuple_a(restore_callback_t *cb) int size = attr_desc->size; int arraySize = attr_desc->arraySize; char * dataPtr = attr_data->string_value; - Uint32 length = attr_data->size; - + Uint32 length = 0; + + const unsigned char * src = (const unsigned char *)dataPtr; + switch(attr_desc->m_column->getType()){ + case NdbDictionary::Column::Varchar: + case NdbDictionary::Column::Varbinary: + length = src[0] + 1; + break; + case NdbDictionary::Column::Longvarchar: + case NdbDictionary::Column::Longvarbinary: + length = src[0] + (src[1] << 8) + 2; + break; + default: + length = attr_data->size; + break; + } if (j == 0 && tup.getTable()->have_auto_inc(i)) tup.getTable()->update_max_auto_val(dataPtr,size*arraySize); @@ -1162,7 +1191,7 @@ void BackupRestore::tuple_a(restore_callback_t *cb) if (ret < 0) { ndbout_c("Column: %d type %d %d %d %d",i, attr_desc->m_column->getType(), - size, arraySize, attr_data->size); + size, arraySize, length); break; } } diff --git a/storage/ndb/tools/restore/consumer_restore.hpp b/storage/ndb/tools/restore/consumer_restore.hpp index 0bc9d8e8d20..8694cbffb0c 100644 --- a/storage/ndb/tools/restore/consumer_restore.hpp +++ b/storage/ndb/tools/restore/consumer_restore.hpp @@ -51,6 +51,7 @@ public: m_callback = 0; m_free_callback = 0; m_temp_error = false; + m_no_upgrade = false; m_transactions = 0; m_cache.m_old_table = 0; } @@ -91,6 +92,7 @@ public: bool m_restore_meta; bool m_no_restore_disk; bool m_restore_epoch; + bool m_no_upgrade; // for upgrade ArrayType from 5.0 backup file. Uint32 m_logCount; Uint32 m_dataCount; diff --git a/storage/ndb/tools/restore/restore_main.cpp b/storage/ndb/tools/restore/restore_main.cpp index adccd024d88..79aebbaac45 100644 --- a/storage/ndb/tools/restore/restore_main.cpp +++ b/storage/ndb/tools/restore/restore_main.cpp @@ -34,6 +34,7 @@ static int ga_nodeId = 0; static int ga_nParallelism = 128; static int ga_backupId = 0; static bool ga_dont_ignore_systab_0 = false; +static bool ga_no_upgrade = false; static Vector<class BackupConsumer *> g_consumers; static BackupPrinter* g_printer = NULL; @@ -115,6 +116,10 @@ static struct my_option my_long_options[] = "Restore meta data into NDB Cluster using NDBAPI", (gptr*) &_restore_meta, (gptr*) &_restore_meta, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "no-upgrade", 'u', + "Don't upgrade array type for var attributes, which don't resize VAR data and don't change column attributes", + (gptr*) &ga_no_upgrade, (gptr*) &ga_no_upgrade, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, { "no-restore-disk-objects", 'd', "Dont restore disk objects (tablespace/logfilegroups etc)", (gptr*) &_no_restore_disk, (gptr*) &_no_restore_disk, 0, @@ -460,6 +465,11 @@ o verify nodegroup mapping restore->m_no_restore_disk = true; } + if (ga_no_upgrade) + { + restore->m_no_upgrade = true; + } + if (ga_restore_epoch) { restore->m_restore_epoch = true; @@ -644,6 +654,8 @@ main(int argc, char** argv) g_options.appfmt(" -n %d", ga_nodeId); if (_restore_meta) g_options.appfmt(" -m"); + if (ga_no_upgrade) + g_options.appfmt(" -u"); if (ga_skip_table_check) g_options.appfmt(" -s"); if (_restore_data) @@ -655,7 +667,6 @@ main(int argc, char** argv) g_options.appfmt(" -p %d", ga_nParallelism); g_connect_string = opt_connect_str; - /** * we must always load meta data, even if we will only print it to stdout */ |