2737 Frazer Clement 2008-11-08 [merge]
Merge 6.2 -> 6.3
modified:
mysql-test/suite/ndb/r/ndb_blob.result
mysql-test/suite/ndb/t/ndb_blob.test
sql/ha_ndbcluster.cc
storage/ndb/include/ndbapi/NdbBlob.hpp
storage/ndb/include/ndbapi/NdbOperation.hpp
storage/ndb/include/ndbapi/NdbScanOperation.hpp
storage/ndb/src/common/debugger/signaldata/SignalNames.cpp
storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp
storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
storage/ndb/src/ndbapi/NdbBlob.cpp
storage/ndb/src/ndbapi/NdbOperation.cpp
storage/ndb/src/ndbapi/NdbOperationSearch.cpp
storage/ndb/src/ndbapi/NdbScanOperation.cpp
storage/ndb/test/ndbapi/testNdbApi.cpp
storage/ndb/test/ndbapi/testOperations.cpp
storage/ndb/test/ndbapi/testTransactions.cpp
storage/ndb/test/run-test/daily-basic-tests.txt
2736 Jonas Oreland 2008-11-07
ndb - remove incorrect assertions
modified:
storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
=== modified file 'mysql-test/suite/ndb/r/ndb_blob.result'
--- a/mysql-test/suite/ndb/r/ndb_blob.result 2008-06-03 15:03:16 +0000
+++ b/mysql-test/suite/ndb/r/ndb_blob.result 2008-11-08 21:22:57 +0000
@@ -636,3 +636,16 @@ select (giga = repeat(@stuff, 2000)) fro
(giga = repeat(@stuff, 2000))
1
drop table t1;
+create table t1 (
+id int,
+data longblob,
+primary key(id))
+engine=ndb;
+set @blurb= repeat('B', 1000000);
+set @blurbHash= sha1(@blurb);
+set autocommit = 1;
+insert into t1 values (1, @blurb);
+create table result_space (k int primary key, result int) engine=myisam;
+set autocommit = 0;
+drop table result_space;
+drop table t1;
=== modified file 'mysql-test/suite/ndb/t/ndb_blob.test'
--- a/mysql-test/suite/ndb/t/ndb_blob.test 2008-06-03 15:03:16 +0000
+++ b/mysql-test/suite/ndb/t/ndb_blob.test 2008-11-08 21:22:57 +0000
@@ -588,3 +588,114 @@ select sha1(giga) from t1;
select (giga = repeat(@stuff, 2000)) from t1 where a=0;
drop table t1;
+
+# bug# 39867 : Blob part operation error handling
+# We attempt to generate a transporter overload
+# and check that an error is generated, rather than
+# rubbish being silently returned.
+# Since transporter overload is not easy to reliably
+# reproduce, this testcase passes when all SELECTS
+# return either the correct result, or fail with
+# MySQL error 1297, and warnings about transporter
+# overload from Ndb. (1218)
+# The testcase will fail if there is no error, and
+# incorrect data/NULL, or if there is an error other
+# than 1297 due to 1218.
+#
+
+create table t1 (
+ id int,
+ data longblob,
+ primary key(id))
+ engine=ndb;
+
+set @blurb= repeat('B', 1000000); # ~1MB of stuff
+set @blurbHash= sha1(@blurb);
+
+set autocommit = 1;
+
+let $mysqltest_loopcounter= 500;
+let $success_count=0;
+let $fail_count=0;
+
+
+insert into t1 values (1, @blurb);
+
+create table result_space (k int primary key, result int) engine=myisam;
+
+--disable_result_log
+--disable_query_log
+
+while ($mysqltest_loopcounter)
+{
+ # Allow success or unmapped error type (1297).
+ --error 0,1297
+ insert into result_space select 1, (sha1(data) = @blurbHash) from t1 where id=1;
+
+ let $orig_errno= $mysql_errno;
+
+ # Statement execution success path
+ if (!$orig_errno)
+ {
+ # Test that the SHA1 of the data read was as expected
+ # (e.g. comparison returned true)
+ let $is_right_answer=`SELECT result from result_space where k=1`;
+
+ if (!$is_right_answer)
+ {
+ --enable_result_log
+ echo SELECT succeeded but gave bad result.
+ SHOW WARNINGS;
+ die "Bad data returned";
+ }
+ #echo Success gave correct result;
+ inc $success_count;
+ }
+
+ # Statement execution failure path
+ if ($orig_errno)
+ {
+ inc $fail_count;
+ #echo FAIL;
+
+ # For the error we are interested in (1218), MySQLD returns a generic error
+ # code (1297). We use the warning info to check the Ndb error.
+ # Note that sometimes the end of the warning states 'from NDB', sometimes
+ # 'from NDBCLUSTER'. Probably it should be made consistent.
+ #
+ let $warning_message= query_get_value("SHOW WARNINGS", Message, 1);
+ let $is_correct_message= `SELECT "$warning_message" LIKE "Got temporary error 1218 'Send Buffers overloaded in NDB kernel' from NDB%"`;
+
+ if (!$is_correct_message)
+ {
+ --enable_result_log
+ echo SELECT failed with incorrect error ($mysql_errno);
+ SHOW WARNINGS;
+ die "Incorrect error from statement";
+ }
+ #echo Failed as expected;
+ }
+
+ delete from result_space;
+
+ #echo $mysqltest_loopcounter;
+
+ dec $mysqltest_loopcounter;
+
+ if ($fail_count = 20)
+ {
+ # That's enough punishment
+ #echo Exiting loop early at iteration $mysqltest_loopcounter;
+ let $mysqltest_loopcounter= 0;
+ }
+}
+
+--enable_result_log
+--enable_query_log
+
+# Interesting, but can't output as it's different every time
+# echo Successes $success_count;
+# echo Failures $fail_count;
+set autocommit = 0;
+drop table result_space;
+drop table t1;
=== modified file 'sql/ha_ndbcluster.cc'
--- a/sql/ha_ndbcluster.cc 2008-10-29 13:22:19 +0000
+++ b/sql/ha_ndbcluster.cc 2008-11-08 21:22:57 +0000
@@ -921,6 +921,33 @@ ha_ndbcluster::copy_row_to_buffer(Thd_nd
return row;
}
+/**
+ * findBlobError
+ * This method attempts to find an error in the hierarchy of runtime
+ * NDBAPI objects from Blob up to transaction.
+ * It will return -1 if no error is found, 0 if an error is found.
+ */
+int findBlobError(NdbError& error, NdbBlob* pBlob)
+{
+ error= pBlob->getNdbError();
+ if (error.code != 0)
+ return 0;
+
+ const NdbOperation* pOp= pBlob->getNdbOperation();
+ error= pOp->getNdbError();
+ if (error.code != 0)
+ return 0;
+
+ NdbTransaction* pTrans= pOp->getNdbTransaction();
+ error= pTrans->getNdbError();
+ if (error.code != 0)
+ return 0;
+
+ /* No error on any of the objects */
+ return -1;
+}
+
+
int g_get_ndb_blobs_value(NdbBlob *ndb_blob, void *arg)
{
ha_ndbcluster *ha= (ha_ndbcluster *)arg;
@@ -999,7 +1026,19 @@ int g_get_ndb_blobs_value(NdbBlob *ndb_b
uchar *buf= ha->m_blobs_buffer + offset;
uint32 len= ha->m_blobs_buffer_size - offset;
if (ndb_blob->readData(buf, len) != 0)
- ERR_RETURN(ndb_blob->getNdbError());
+ {
+ NdbError err;
+ if (findBlobError(err, ndb_blob) == 0)
+ {
+ ERR_RETURN(err);
+ }
+ else
+ {
+ /* Should always have some error code set */
+ assert(err.code != 0);
+ ERR_RETURN(err);
+ }
+ }
DBUG_PRINT("info", ("[%u] offset: %u buf: 0x%lx len=%u",
i, offset, (long) buf, len));
DBUG_ASSERT(len == len64);
=== modified file 'storage/ndb/include/ndbapi/NdbBlob.hpp'
--- a/storage/ndb/include/ndbapi/NdbBlob.hpp 2008-02-19 10:41:22 +0000
+++ b/storage/ndb/include/ndbapi/NdbBlob.hpp 2008-11-08 20:40:15 +0000
@@ -263,6 +263,13 @@ public:
*/
const NdbError& getNdbError() const;
/**
+ * Get a pointer to the operation which this Blob Handle
+ * was initially created as part of.
+ * Note that this could be a scan operation.
+ * Note that the pointer returned is a const pointer.
+ */
+ const NdbOperation* getNdbOperation() const;
+ /**
* Return info about all blobs in this operation.
*
* Get first blob in list.
=== modified file 'storage/ndb/include/ndbapi/NdbOperation.hpp'
--- a/storage/ndb/include/ndbapi/NdbOperation.hpp 2008-08-07 11:51:34 +0000
+++ b/storage/ndb/include/ndbapi/NdbOperation.hpp 2008-11-08 21:22:57 +0000
@@ -838,6 +838,7 @@ public:
* @return method number where the error occured.
*/
int getNdbErrorLine();
+ int getNdbErrorLine() const;
/**
* Get table name of this operation.
@@ -886,6 +887,11 @@ public:
*/
AbortOption getAbortOption() const;
int setAbortOption(AbortOption);
+
+ /**
+ * Get NdbTransaction object pointer for this operation
+ */
+ virtual NdbTransaction* getNdbTransaction() const;
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
@@ -1042,7 +1048,6 @@ protected:
public:
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
- NdbTransaction* getNdbTransaction();
const NdbOperation* next() const;
const NdbRecAttr* getFirstRecAttr() const;
@@ -1483,6 +1488,13 @@ NdbOperation::getNdbErrorLine()
return theErrorLine;
}
+inline
+int
+NdbOperation::getNdbErrorLine() const
+{
+ return theErrorLine;
+}
+
/******************************************************************************
void next(NdbOperation* aNdbOperation);
=== modified file 'storage/ndb/include/ndbapi/NdbScanOperation.hpp'
--- a/storage/ndb/include/ndbapi/NdbScanOperation.hpp 2008-08-11 12:46:21 +0000
+++ b/storage/ndb/include/ndbapi/NdbScanOperation.hpp 2008-11-08 21:22:57 +0000
@@ -377,6 +377,11 @@ public:
const NdbOperation::OperationOptions *opts = 0,
Uint32 sizeOfOptions = 0);
+ /**
+ * Get NdbTransaction object for this scan operation
+ */
+ NdbTransaction* getNdbTransaction() const;
+
protected:
NdbScanOperation(Ndb* aNdb,
NdbOperation::Type aType = NdbOperation::TableScan);
@@ -657,4 +662,14 @@ NdbScanOperation::deleteCurrentTuple(Ndb
opts, sizeOfOptions);
}
+inline
+NdbTransaction*
+NdbScanOperation::getNdbTransaction() const
+{
+ /* return the user visible transaction object ptr, not the
+ * scan's 'internal' / buddy transaction object
+ */
+ return m_transConnection;
+};
+
#endif
=== modified file 'storage/ndb/src/common/debugger/signaldata/SignalNames.cpp'
--- a/storage/ndb/src/common/debugger/signaldata/SignalNames.cpp 2007-11-23 07:15:16 +0000
+++ b/storage/ndb/src/common/debugger/signaldata/SignalNames.cpp 2008-11-08 21:22:57 +0000
@@ -647,6 +647,8 @@ const GsnName SignalNames [] = {
,{ GSN_UPGRADE_PROTOCOL_ORD, "UPGRADE_PROTOCOL_ORD" }
+ ,{ GSN_TC_HBREP, "TC_HBREP" }
+
,{ GSN_START_TOREF, "START_TOREF" }
,{ GSN_END_TOREF, "END_TOREF" }
,{ GSN_START_PERMREP, "START_PERMREP" }
=== modified file 'storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp'
--- a/storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp 2008-08-27 20:10:42 +0000
+++ b/storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp 2008-11-08 21:22:57 +0000
@@ -212,6 +212,15 @@ void Cmvmi::execEVENT_REP(Signal* signal
if (nodeId == 0)
{
nodeId= refToNode(signal->getSendersBlockRef());
+
+ if (nodeId == 0)
+ {
+ /* Event reporter supplied no node id,
+ * assume it was local
+ */
+ nodeId= getOwnNodeId();
+ }
+
eventReport->setNodeId(nodeId);
}
=== modified file 'storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp'
--- a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp 2008-11-07 10:33:31 +0000
+++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp 2008-11-08 21:22:57 +0000
@@ -2285,9 +2285,10 @@ void Dblqh::noFreeRecordLab(Signal* sign
releaseTcrec(signal, tcConnectptr);
}
- if (LqhKeyReq::getSimpleFlag(reqInfo) &&
+ if (LqhKeyReq::getDirtyFlag(reqInfo) &&
LqhKeyReq::getOperation(reqInfo) == ZREAD){
jam();
+ /* Dirty read sends TCKEYREF direct to client, and nothing to TC */
ndbrequire(LqhKeyReq::getApplicationAddressFlag(reqInfo));
const Uint32 apiRef = lqhKeyReq->variableData[0];
const Uint32 apiOpRec = lqhKeyReq->variableData[1];
@@ -2301,6 +2302,9 @@ void Dblqh::noFreeRecordLab(Signal* sign
sendTCKEYREF(signal, apiRef, signal->getSendersBlockRef(), 0);
} else {
jam();
+ /* All ops apart from dirty read send LQHKEYREF to TC
+ * (This includes simple read)
+ */
const Uint32 clientPtr = lqhKeyReq->clientConnectPtr;
Uint32 TcOprec = clientPtr;
=== modified file 'storage/ndb/src/ndbapi/NdbBlob.cpp'
--- a/storage/ndb/src/ndbapi/NdbBlob.cpp 2008-06-03 10:00:31 +0000
+++ b/storage/ndb/src/ndbapi/NdbBlob.cpp 2008-11-08 20:40:15 +0000
@@ -3070,3 +3070,8 @@ NdbBlob::blobsNextBlob()
return theNext;
}
+const NdbOperation*
+NdbBlob::getNdbOperation() const
+{
+ return theNdbOp;
+};
=== modified file 'storage/ndb/src/ndbapi/NdbOperation.cpp'
--- a/storage/ndb/src/ndbapi/NdbOperation.cpp 2008-04-29 13:03:02 +0000
+++ b/storage/ndb/src/ndbapi/NdbOperation.cpp 2008-11-08 21:22:57 +0000
@@ -519,7 +519,7 @@ NdbOperation::getTable() const
}
NdbTransaction*
-NdbOperation::getNdbTransaction()
+NdbOperation::getNdbTransaction() const
{
return theNdbCon;
}
=== modified file 'storage/ndb/src/ndbapi/NdbOperationSearch.cpp'
--- a/storage/ndb/src/ndbapi/NdbOperationSearch.cpp 2008-06-03 10:00:31 +0000
+++ b/storage/ndb/src/ndbapi/NdbOperationSearch.cpp 2008-11-08 21:06:51 +0000
@@ -58,7 +58,9 @@ NdbOperation::equal_impl(const NdbColumn
{
DBUG_ENTER("NdbOperation::equal_impl");
DBUG_PRINT("enter", ("col: %s op: %d val: 0x%lx",
- tAttrInfo->m_name.c_str(), theOperationType,
+ (tAttrInfo == NULL) ? "NULL" :
+ tAttrInfo->m_name.c_str(),
+ theOperationType,
(long) aValuePassed));
const char* aValue = aValuePassed;
=== modified file 'storage/ndb/src/ndbapi/NdbScanOperation.cpp'
--- a/storage/ndb/src/ndbapi/NdbScanOperation.cpp 2008-11-06 16:51:50 +0000
+++ b/storage/ndb/src/ndbapi/NdbScanOperation.cpp 2008-11-08 21:22:57 +0000
@@ -2362,31 +2362,49 @@ NdbScanOperation::takeOverScanOpNdbRecor
NdbBlob*
NdbScanOperation::getBlobHandle(const char* anAttrName)
{
- /* We need the row KeyInfo for Blobs
- * Old Api scans have saved flags at this point
- */
- if (m_scanUsingOldApi)
- m_savedScanFlagsOldApi|= SF_KeyInfo;
+ const NdbColumnImpl* col= m_currentTable->getColumn(anAttrName);
+
+ if (col != NULL)
+ {
+ /* We need the row KeyInfo for Blobs
+ * Old Api scans have saved flags at this point
+ */
+ if (m_scanUsingOldApi)
+ m_savedScanFlagsOldApi|= SF_KeyInfo;
+ else
+ m_keyInfo= 1;
+
+ return NdbOperation::getBlobHandle(m_transConnection, col);
+ }
else
- m_keyInfo= 1;
-
- return NdbOperation::getBlobHandle(m_transConnection,
- m_currentTable->getColumn(anAttrName));
+ {
+ setErrorCode(4004);
+ return NULL;
+ }
}
NdbBlob*
NdbScanOperation::getBlobHandle(Uint32 anAttrId)
{
- /* We need the row KeyInfo for Blobs
- * Old Api scans have saved flags at this point
- */
- if (m_scanUsingOldApi)
- m_savedScanFlagsOldApi|= SF_KeyInfo;
+ const NdbColumnImpl* col= m_currentTable->getColumn(anAttrId);
+
+ if (col != NULL)
+ {
+ /* We need the row KeyInfo for Blobs
+ * Old Api scans have saved flags at this point
+ */
+ if (m_scanUsingOldApi)
+ m_savedScanFlagsOldApi|= SF_KeyInfo;
+ else
+ m_keyInfo= 1;
+
+ return NdbOperation::getBlobHandle(m_transConnection, col);
+ }
else
- m_keyInfo= 1;
-
- return NdbOperation::getBlobHandle(m_transConnection,
- m_currentTable->getColumn(anAttrId));
+ {
+ setErrorCode(4004);
+ return NULL;
+ }
}
/**
=== modified file 'storage/ndb/test/ndbapi/testNdbApi.cpp'
--- a/storage/ndb/test/ndbapi/testNdbApi.cpp 2008-06-03 12:37:17 +0000
+++ b/storage/ndb/test/ndbapi/testNdbApi.cpp 2008-11-08 21:06:51 +0000
@@ -26,10 +26,8 @@
#define MAX_NDB_OBJECTS 32678
#define CHECK(b) if (!(b)) { \
- ndbout << "ERR: "<< step->getName() \
- << " failed on line " << __LINE__ << endl; \
- result = NDBT_FAILED; \
- continue; }
+ ndbout << "ERR: failed on line " << __LINE__ << endl; \
+ return -1; }
#define CHECKE(b) if (!(b)) { \
errors++; \
@@ -628,6 +626,175 @@ int runGetNdbOperationNoTab(NDBT_Context
return NDBT_OK;
}
+int runBadColNameHandling(NDBT_Context* ctx, NDBT_Step* step){
+ int result = NDBT_OK;
+ const NdbDictionary::Table* pTab = ctx->getTab();
+
+
+ Ndb* pNdb = new Ndb(&ctx->m_cluster_connection, "TEST_DB");
+ if (pNdb == NULL){
+ ndbout << "pNdb == NULL" << endl;
+ return NDBT_FAILED;
+ }
+ if (pNdb->init()){
+ ERR(pNdb->getNdbError());
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ const int CASES= 5;
+ int i;
+
+ for (i= 0; i < CASES; i++)
+ {
+ ndbout << "Case " << i << endl;
+ NdbConnection* pCon = pNdb->startTransaction();
+ if (pCon == NULL){
+ pNdb->closeTransaction(pCon);
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ /* Cases 0-3 use PK ops, 4 + use scans */
+ NdbOperation* pOp = (i < 4 ? pCon->getNdbOperation(pTab->getName()):
+ pCon->getNdbScanOperation(pTab->getName()));
+ if (pOp == NULL){
+ ERR(pCon->getNdbError());
+ pNdb->closeTransaction(pCon);
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ bool failed= false;
+ int expectedError= 0;
+ HugoOperations hugoOps(*pTab);
+
+ switch(i) {
+ case 0:
+ if (pOp->readTuple() != 0){
+ ERR(pCon->getNdbError());
+ pNdb->closeTransaction(pCon);
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ // getValue should fail, we check that we get correct errors
+ // in expected places.
+ expectedError= 4004;
+ failed= (pOp->getValue("MOST_IMPROBABLE2") == NULL);
+ break;
+
+ case 1:
+ if (pOp->readTuple() != 0){
+ ERR(pCon->getNdbError());
+ pNdb->closeTransaction(pCon);
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ // equal should fail, we check that we get correct errors
+ // in expected places.
+ expectedError= 4004;
+ failed= (pOp->equal("MOST_IMPROBABLE2", 0) != 0);
+ break;
+
+ case 2:
+ if (pOp->writeTuple() != 0){
+ ERR(pCon->getNdbError());
+ pNdb->closeTransaction(pCon);
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ // set equality on pk columns
+ for(int a = 0; a<pTab->getNoOfColumns(); a++){
+ if (pTab->getColumn(a)->getPrimaryKey() == true){
+ if(hugoOps.equalForAttr(pOp, a, 1) != 0){
+ const NdbError err = pCon->getNdbError();
+ ERR(err);
+ pNdb->closeTransaction(pCon);
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+ }
+ }
+
+ // setValue should fail, we check that we get correct errors
+ // in expected places.
+ expectedError= 4004;
+ failed= (pOp->setValue("MOST_IMPROBABLE2", 0) != 0);
+ break;
+
+ case 3:
+ if (pOp->readTuple() != 0){
+ ERR(pCon->getNdbError());
+ pNdb->closeTransaction(pCon);
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ // getBlobHandle should fail, we check that we get correct errors
+ // in expected places.
+ expectedError= 4004;
+ failed= (pOp->getBlobHandle("MOST_IMPROBABLE2") == NULL);
+ break;
+
+ case 4:
+ {
+ NdbScanOperation* sop= (NdbScanOperation*) pOp;
+ if (sop->readTuples() != 0){
+ ERR(pCon->getNdbError());
+ pNdb->closeTransaction(pCon);
+ delete pNdb;
+ return NDBT_FAILED;
+ }
+
+ // getBlobHandle should fail, we check that we get correct errors
+ // in expected places.
+ expectedError= 4004;
+ ndbout << "About to call getBlobHandle" << endl;
+ failed= (sop->getBlobHandle("MOST_IMPROBABLE2") == NULL);
+
+ sop->close();
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ if (failed)
+ {
+ const NdbError opErr= pOp->getNdbError();
+ const NdbError transErr = pCon->getNdbError();
+ ERR(opErr);
+ ERR(transErr);
+ if (opErr.code != transErr.code) {
+ ndbout << "Error reporting mismatch, expected "
+ << expectedError << endl;
+ result = NDBT_FAILED;
+ }
+ if (opErr.code != expectedError){
+ ndbout << "No or bad error detected, expected "
+ << expectedError << endl;
+ result = NDBT_FAILED;
+ }
+ } else {
+ ndbout << "Case " << i << " did not fail" << endl;
+ result = NDBT_FAILED;
+ }
+
+ pNdb->closeTransaction(pCon);
+
+ if (result == NDBT_FAILED)
+ break;
+ } // for
+
+ delete pNdb;
+
+ return result;
+}
+
int runMissingOperation(NDBT_Context* ctx, NDBT_Step* step){
int result = NDBT_OK;
const NdbDictionary::Table* pTab = ctx->getTab();
@@ -1326,6 +1493,7 @@ op_row(NdbTransaction* pTrans, HugoOpera
case 3:
case 4:
case 5:
+ case 12:
pOp = pTrans->getNdbOperation(pTab->getName());
break;
case 9:
@@ -1365,10 +1533,13 @@ op_row(NdbTransaction* pTrans, HugoOpera
case 11:
pOp->deleteTuple();
break;
+ case 12:
+ CHECK(!pOp->simpleRead());
+ break;
default:
abort();
}
-
+
for(int a = 0; a<pTab->getNoOfColumns(); a++){
if (pTab->getColumn(a)->getPrimaryKey() == true){
if(hugoOps.equalForAttr(pOp, a, row) != 0){
@@ -1384,8 +1555,9 @@ op_row(NdbTransaction* pTrans, HugoOpera
case 6:
case 7:
case 8:
+ case 12:
for(int a = 0; a<pTab->getNoOfColumns(); a++){
- pOp->getValue(a);
+ CHECK(pOp->getValue(a));
}
break;
case 3:
@@ -1427,6 +1599,8 @@ static void print(int op)
case 9: str = "noop "; break;
case 10: str = "uk update "; break;
case 11: str = "uk delete "; break;
+ case 12: str = "pk read-si"; break;
+
default:
abort();
}
@@ -1457,9 +1631,10 @@ runTestIgnoreError(NDBT_Context* ctx, ND
printf("case: <op1> <op2> c/nc ao/ie\n");
Uint32 tno = 0;
- for (Uint32 op1 = 0; op1 < 12; op1++)
+ for (Uint32 op1 = 0; op1 < 13; op1++)
{
- for (Uint32 op2 = op1; op2 < 12; op2++)
+ // NOTE : I get a node crash if the following loop starts from 0!
+ for (Uint32 op2 = op1; op2 < 13; op2++)
{
int ret;
NdbTransaction* pTrans = 0;
@@ -1486,25 +1661,25 @@ runTestIgnoreError(NDBT_Context* ctx, ND
hugoTrans.loadTable(pNdb, 1);
- pTrans = pNdb->startTransaction();
- op_row(pTrans, hugoOps, pTab, op1, 0);
+ CHECK(pTrans = pNdb->startTransaction());
+ CHECK(!op_row(pTrans, hugoOps, pTab, op1, 0));
ret = pTrans->execute(et, ao);
pTrans->close();
printf("%d ", ret);
hugoTrans.clearTable(pNdb);
hugoTrans.loadTable(pNdb, 1);
- pTrans = pNdb->startTransaction();
- op_row(pTrans, hugoOps, pTab, op1, 1);
+ CHECK(pTrans = pNdb->startTransaction());
+ CHECK(!op_row(pTrans, hugoOps, pTab, op1, 1));
ret = pTrans->execute(et, ao);
pTrans->close();
printf("%d ", ret);
hugoTrans.clearTable(pNdb);
hugoTrans.loadTable(pNdb, 1);
- pTrans = pNdb->startTransaction();
- op_row(pTrans, hugoOps, pTab, op1, 0);
- op_row(pTrans, hugoOps, pTab, op2, 1);
+ CHECK(pTrans = pNdb->startTransaction());
+ CHECK(!op_row(pTrans, hugoOps, pTab, op1, 0));
+ CHECK(!op_row(pTrans, hugoOps, pTab, op2, 1));
ret = pTrans->execute(et, ao);
pTrans->close();
printf("%d\n", ret);
@@ -1728,6 +1903,85 @@ done:
return result;
}
+int
+simpleReadAbortOnError(NDBT_Context* ctx, NDBT_Step* step)
+{
+ /* Simple read has some error handling issues
+ * Setting the operation to be AbortOnError can expose these
+ */
+ Ndb* pNdb = GETNDB(step);
+ const NdbDictionary::Table* pTab= ctx->getTab();
+ HugoOperations hugoOps(*pTab);
+ NdbRestarter restarter;
+
+ hugoOps.startTransaction(pNdb);
+ CHECK(!hugoOps.pkWriteRecord(pNdb,0));
+ CHECK(!hugoOps.execute_Commit(pNdb, AbortOnError));
+
+ NdbTransaction* trans;
+
+ CHECK(trans= pNdb->startTransaction());
+
+ /* Insert error 5047 which causes next LQHKEYREQ to fail due
+ * to 'transporter overload'
+ * Error insert is self-clearing
+ */
+ restarter.insertErrorInAllNodes(5047);
+
+ /* Create SimpleRead on row 0, which exists (though we'll get
+ * 'transporter overload for this'
+ */
+ NdbOperation* op;
+ CHECK(op= trans->getNdbOperation(pTab));
+
+ CHECK(!op->simpleRead());
+
+ for(int a = 0; a<pTab->getNoOfColumns(); a++){
+ if (pTab->getColumn(a)->getPrimaryKey() == true){
+ if(hugoOps.equalForAttr(op, a, 0) != 0){
+ restarter.insertErrorInAllNodes(0);
+ return NDBT_FAILED;
+ }
+ }
+ }
+ for(int a = 0; a<pTab->getNoOfColumns(); a++){
+ CHECK(op->getValue(a));
+ }
+
+ CHECK(!op->setAbortOption(NdbOperation::AbortOnError));
+
+ /* Create normal read on row 0 which will succeed */
+ NdbOperation* op2;
+ CHECK(op2= trans->getNdbOperation(pTab));
+
+ CHECK(!op2->readTuple());
+
+ for(int a = 0; a<pTab->getNoOfColumns(); a++){
+ if (pTab->getColumn(a)->getPrimaryKey() == true){
+ if(hugoOps.equalForAttr(op2, a, 0) != 0){
+ restarter.insertErrorInAllNodes(0);
+ return NDBT_FAILED;
+ }
+ }
+ }
+ for(int a = 0; a<pTab->getNoOfColumns(); a++){
+ CHECK(op2->getValue(a));
+ }
+
+ CHECK(!op2->setAbortOption(NdbOperation::AbortOnError));
+
+
+ CHECK(trans->execute(NoCommit) == -1);
+
+ CHECK(trans->getNdbError().code == 1218); // Transporter Overload
+
+ restarter.insertErrorInAllNodes(0);
+
+ return NDBT_OK;
+
+}
+
+
NDBT_TESTSUITE(testNdbApi);
TESTCASE("MaxNdb",
"Create Ndb objects until no more can be created\n"){
@@ -1769,6 +2023,10 @@ TESTCASE("GetOperationNoTab",
"Call getNdbOperation on a table that does not exist\n"){
INITIALIZER(runGetNdbOperationNoTab);
}
+TESTCASE("BadColNameHandling",
+ "Call methods with an invalid column name and check error handling\n"){
+ INITIALIZER(runBadColNameHandling);
+}
TESTCASE("MissingOperation",
"Missing operation request(insertTuple) should give an error code\n"){
INITIALIZER(runMissingOperation);
@@ -1840,6 +2098,10 @@ TESTCASE("Bug37158",
""){
INITIALIZER(runBug37158);
}
+TESTCASE("SimpleReadAbortOnError",
+ "Test behaviour of Simple reads with Abort On Error"){
+ INITIALIZER(simpleReadAbortOnError);
+}
NDBT_TESTSUITE_END(testNdbApi);
int main(int argc, const char** argv){
=== modified file 'storage/ndb/test/ndbapi/testOperations.cpp'
--- a/storage/ndb/test/ndbapi/testOperations.cpp 2007-08-01 03:07:58 +0000
+++ b/storage/ndb/test/ndbapi/testOperations.cpp 2008-11-08 20:45:48 +0000
@@ -59,6 +59,20 @@ OperationTestCase matrix[] = {
{ "FReadUpdate", false, "READ", 626, 0, "UPDATE", 626, 0, 626, 0 },
{ "FReadDelete", false, "READ", 626, 0, "DELETE", 626, 0, 626, 0 },
+ { "FSimpleReadRead", false, "S-READ", 626, 0, "READ", 626, 0, 626, 0 },
+ { "FSimpleReadReadEx",
+ false, "S-READ", 626, 0, "READ-EX", 626, 0, 626, 0 },
+ { "FSimpleReadSimpleRead",
+ false, "S-READ", 626, 0, "S-READ", 626, 0, 626, 0 },
+ { "FSimpleReadDirtyRead",
+ false, "S-READ", 626, 0, "D-READ", 626, 0, 626, 0 },
+ { "FSimpleReadInsert",
+ false, "S-READ", 626, 0, "INSERT", 0, 1, 0, 1 },
+ { "FSimpleReadUpdate",
+ false, "S-READ", 626, 0, "UPDATE", 626, 0, 626, 0 },
+ { "FSimpleReadDelete",
+ false, "S-READ", 626, 0, "DELETE", 626, 0, 626, 0 },
+
{ "ReadExRead", true, "READ-EX", 0, 0, "READ", 0, 0, 0, 0 },
{ "ReadExReadEx", true, "READ-EX", 0, 0, "READ-EX", 0, 0, 0, 0 },
{ "ReadExSimpleRead", true, "READ-EX", 0, 0, "S-READ", 0, 0, 0, 0 },
@@ -118,7 +132,7 @@ runOp(HugoOperations & hugoOps,
} else if(strcmp(op, "READ-EX") == 0){
C2(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Exclusive), 0);
} else if(strcmp(op, "S-READ") == 0){
- C2(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Read), 0);
+ C2(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_SimpleRead), 0);
} else if(strcmp(op, "D-READ") == 0){
C2(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_CommittedRead), 0);
} else if(strcmp(op, "INSERT") == 0){
=== modified file 'storage/ndb/test/ndbapi/testTransactions.cpp'
--- a/storage/ndb/test/ndbapi/testTransactions.cpp 2006-12-23 19:20:40 +0000
+++ b/storage/ndb/test/ndbapi/testTransactions.cpp 2008-11-08 20:45:48 +0000
@@ -109,6 +109,23 @@ OperationTestCase matrix[] = {
{ "ScanExScanDe", true, "SCAN-EX",1, "SCAN-DE", 266, X, 0, 1 },
#endif
+ { "SimpleReadRead", true, "S-READ", 1, "READ", 0, 1, 0, 1 },
+ { "SimpleReadReadEx", true, "S-READ", 1, "READ-EX", 0, 1, 0, 1 }, // no lock held
+ { "SimpleReadSimpleRead",
+ true, "S-READ", 1, "S-READ", 0, 1, 0, 1 },
+ { "SimpleReadDirtyRead",
+ true, "S-READ", 1, "D-READ", 0, 1, 0, 1 },
+ { "SimpleReadInsert", true, "S-READ", 1, "INSERT", 630, X, 0, 1 }, // no lock held
+ { "SimpleReadUpdate", true, "S-READ", 1, "UPDATE", 0, 2, 0, 2 }, // no lock held
+ { "SimpleReadDelete", true, "S-READ", 1, "DELETE", 0, X, 626, X }, // no lock held
+ { "SimpleReadScan", true, "S-READ", 1, "SCAN", 0, 1, 0, 1 },
+ { "SimpleReadScanHl", true, "S-READ", 1, "SCAN-HL", 0, 1, 0, 1 },
+ { "SimpleReadScanEx", true, "S-READ", 1, "SCAN-EX", 0, 1, 0, 1 }, // no lock held
+#if 0
+ { "SimpleReadScanUp", true, "S-READ", 1, "SCAN-UP", 0, 1, 0, 2 }, // no lock held
+ { "SimpleReadScanDe", true, "S-READ", 1, "SCAN-DE", 0, X, 626, X }, // no lock held
+#endif
+
{ "ReadExRead", true, "READ-EX",1, "READ", 266, X, 0, 1 },
{ "ReadExReadEx", true, "READ-EX",1, "READ-EX", 266, X, 0, 1 },
{ "ReadExSimpleRead", true, "READ-EX",1, "S-READ", 266, X, 0, 1 },
@@ -169,6 +186,9 @@ OperationTestCase matrix[] = {
{ "DeleteScanDe", true, "DELETE", X, "SCAN-DE", 266, X, 626, X }
#endif
+
+
+
};
#define CHECK(a, b) { int x = a; int y = b; if (x != y) { \
@@ -193,7 +213,7 @@ runOp(HugoOperations & hugoOps,
} else if(strcmp(op, "READ-EX") == 0){
C2(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Exclusive) == 0);
} else if(strcmp(op, "S-READ") == 0){
- C2(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_Read) == 0);
+ C2(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_SimpleRead) == 0);
} else if(strcmp(op, "D-READ") == 0){
C2(hugoOps.pkReadRecord(pNdb, 1, 1, NdbOperation::LM_CommittedRead) == 0);
} else if(strcmp(op, "INSERT") == 0){
=== modified file 'storage/ndb/test/run-test/daily-basic-tests.txt'
--- a/storage/ndb/test/run-test/daily-basic-tests.txt 2008-08-11 11:24:12 +0000
+++ b/storage/ndb/test/run-test/daily-basic-tests.txt 2008-11-08 21:22:57 +0000
@@ -765,6 +765,14 @@ cmd: testNdbApi
args: -n Bug28443
max-time: 500
+cmd: testNdbApi
+args: -n BadColNameHandling T6
+
+max-time: 500
+cmd: testNdbApi
+args: -n SimpleReadAbortOnError T1 T6 T15
+
+max-time: 500
cmd: testInterpreter
args: T1
@@ -1183,3 +1191,4 @@ cmd: test_event
args -r 5000 -n Bug30780 T1
#EOF 2008-08-11
+
| Thread |
|---|
| • bzr push into mysql-5.1 branch (frazer:2736 to 2737) | Frazer Clement | 8 Nov |