4957 Pekka Nousiainen 2012-08-05
bug#13881465 a02_patch_v3.diff
bug test and patch v3
modified:
mysql-test/suite/ndb/r/ndb_blob.result
mysql-test/suite/ndb/t/ndb_blob.test
storage/ndb/include/ndbapi/NdbBlob.hpp
storage/ndb/include/ndbapi/NdbTransaction.hpp
storage/ndb/src/ndbapi/NdbBlob.cpp
storage/ndb/src/ndbapi/NdbTransaction.cpp
storage/ndb/test/run-test/daily-basic-tests.txt
storage/ndb/tools/ndb_blob_tool.cpp
4956 Mauritz Sundell 2012-07-12
ndb - autotest on ndb07 need use default storage engine myisam
modified:
storage/ndb/test/run-test/conf-ndb07.cnf
=== modified file 'mysql-test/suite/ndb/r/ndb_blob.result'
--- a/mysql-test/suite/ndb/r/ndb_blob.result 2010-01-28 15:16:46 +0000
+++ b/mysql-test/suite/ndb/r/ndb_blob.result 2012-08-05 10:05:54 +0000
@@ -723,3 +723,61 @@ select a, length(b) from t1 FOR UPDATE;
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
commit;
drop table t1;
+# bug#13881465
+create table t1 (
+a int unsigned not null,
+b text not null,
+primary key using hash (a)
+) engine=ndb;
+set @x1 = repeat('x1',140);
+set @x2 = repeat('x2',140);
+set @y1 = repeat('y1',140);
+set @y2 = repeat('y2',140);
+insert into t1 values (0+0x1133, @x1);
+insert into t1 values (0+0x2233, @x2);
+delete from t1;
+insert into t1 values (0+0x1133, @y1);
+insert into t1 values (0+0x2233, @y2);
+delete from t1;
+insert into t1 values (0+0x1133, @x1);
+insert into t1 values (0+0x2233, @x2);
+delete from t1 where b is not null;
+insert into t1 values (0+0x1133, @y1);
+insert into t1 values (0+0x2233, @y2);
+delete from t1;
+insert into t1 values (0+0x1133, @x1);
+insert into t1 values (0+0x2233, @x2);
+delete from t1 where substr(b,2*140-1,1) = 'x';
+insert into t1 values (0+0x1133, @y1);
+insert into t1 values (0+0x2233, @y2);
+delete from t1;
+drop table t1;
+create table t1 (
+a int unsigned not null,
+b text,
+c text,
+primary key using hash (a)
+) engine=ndb;
+set @x1 = repeat('x1',5000);
+set @x2 = repeat('x2',5000);
+set @y1 = repeat('y1',5000);
+set @y2 = repeat('y2',5000);
+insert into t1 values (0+0x1133, @x1, @y1);
+insert into t1 values (0+0x2233, @x2, @y2);
+select sha1(b), sha1(c) from t1 order by a;
+sha1(b) sha1(c)
+9e29f5566c7ee71d03e1c658545be37110484730 5c8da1b925d954b81e53dc857afac4487fcf0c13
+684c12ec8c05dee9ae57bff333034e3c14393cf0 c49f848d220fe0dfbd62a5526c2e56b923aac741
+update t1 set b=replace(b,'x','y'), c=replace(c,'y','x');
+select sha1(b), sha1(c) from t1 order by a;
+sha1(b) sha1(c)
+5c8da1b925d954b81e53dc857afac4487fcf0c13 9e29f5566c7ee71d03e1c658545be37110484730
+c49f848d220fe0dfbd62a5526c2e56b923aac741 684c12ec8c05dee9ae57bff333034e3c14393cf0
+delete from t1 where substr(b,2*5000-1,1) = 'y' and substr(c,2*5000-1,1) = 'x';
+select count(*) from t1;
+count(*)
+0
+insert into t1 values (0+0x1133, @x1, @y1);
+insert into t1 values (0+0x2233, @x2, @y2);
+delete from t1;
+drop table t1;
=== modified file 'mysql-test/suite/ndb/t/ndb_blob.test'
--- a/mysql-test/suite/ndb/t/ndb_blob.test 2010-01-28 15:16:46 +0000
+++ b/mysql-test/suite/ndb/t/ndb_blob.test 2012-08-05 10:05:54 +0000
@@ -680,3 +680,73 @@ commit;
connection con1;
drop table t1;
+
+--echo # bug#13881465
+# DELETE BY SCAN LEAVES ORPHANED BLOB PART ROWS
+
+create table t1 (
+ a int unsigned not null,
+ b text not null,
+ primary key using hash (a)
+) engine=ndb;
+
+set @x1 = repeat('x1',140);
+set @x2 = repeat('x2',140);
+set @y1 = repeat('y1',140);
+set @y2 = repeat('y2',140);
+
+# ok
+insert into t1 values (0+0x1133, @x1);
+insert into t1 values (0+0x2233, @x2);
+delete from t1;
+insert into t1 values (0+0x1133, @y1);
+insert into t1 values (0+0x2233, @y2);
+delete from t1;
+
+# failed (handler uselessly reads full blob)
+insert into t1 values (0+0x1133, @x1);
+insert into t1 values (0+0x2233, @x2);
+delete from t1 where b is not null;
+# --error ER_DUP_ENTRY
+insert into t1 values (0+0x1133, @y1);
+insert into t1 values (0+0x2233, @y2);
+delete from t1;
+
+# failed (make sure full blob is read)
+insert into t1 values (0+0x1133, @x1);
+insert into t1 values (0+0x2233, @x2);
+delete from t1 where substr(b,2*140-1,1) = 'x';
+# --error ER_DUP_ENTRY
+insert into t1 values (0+0x1133, @y1);
+insert into t1 values (0+0x2233, @y2);
+delete from t1;
+
+drop table t1;
+
+# also test multiple blobs
+create table t1 (
+ a int unsigned not null,
+ b text,
+ c text,
+ primary key using hash (a)
+) engine=ndb;
+
+set @x1 = repeat('x1',5000);
+set @x2 = repeat('x2',5000);
+set @y1 = repeat('y1',5000);
+set @y2 = repeat('y2',5000);
+
+insert into t1 values (0+0x1133, @x1, @y1);
+insert into t1 values (0+0x2233, @x2, @y2);
+select sha1(b), sha1(c) from t1 order by a;
+# would be nice to swap values but of course MySQL cannot
+# update t1 set b = c, c = b;
+update t1 set b=replace(b,'x','y'), c=replace(c,'y','x');
+select sha1(b), sha1(c) from t1 order by a;
+delete from t1 where substr(b,2*5000-1,1) = 'y' and substr(c,2*5000-1,1) = 'x';
+select count(*) from t1;
+insert into t1 values (0+0x1133, @x1, @y1);
+insert into t1 values (0+0x2233, @x2, @y2);
+delete from t1;
+
+drop table t1;
=== modified file 'storage/ndb/include/ndbapi/NdbBlob.hpp'
--- a/storage/ndb/include/ndbapi/NdbBlob.hpp 2011-06-30 15:59:25 +0000
+++ b/storage/ndb/include/ndbapi/NdbBlob.hpp 2012-08-05 10:05:54 +0000
@@ -499,6 +499,7 @@ private:
// pending ops
int executePendingBlobReads();
int executePendingBlobWrites();
+ int executePendingMainOps();
// callbacks
int invokeActiveHook();
// blob handle maintenance
=== modified file 'storage/ndb/include/ndbapi/NdbTransaction.hpp'
--- a/storage/ndb/include/ndbapi/NdbTransaction.hpp 2011-06-30 15:59:25 +0000
+++ b/storage/ndb/include/ndbapi/NdbTransaction.hpp 2012-08-05 10:05:54 +0000
@@ -1173,6 +1173,8 @@ private:
Uint32 theBuddyConPtr;
// optim: any blobs
bool theBlobFlag;
+ // any prepared key ops with blobs
+ bool theBlobPreparedKeyOpsFlag;
Uint8 thePendingBlobOps;
Uint32 maxPendingBlobReadBytes;
Uint32 maxPendingBlobWriteBytes;
=== modified file 'storage/ndb/src/ndbapi/NdbBlob.cpp'
--- a/storage/ndb/src/ndbapi/NdbBlob.cpp 2011-12-09 19:15:17 +0000
+++ b/storage/ndb/src/ndbapi/NdbBlob.cpp 2012-08-05 10:05:54 +0000
@@ -1443,6 +1443,13 @@ NdbBlob::readDataPrivate(char* buf, Uint
DBUG_RETURN(-1);
}
if (len > 0) {
+ if (theEventBlobVersion == -1) {
+ // likely to executeNoBlobs
+ if (executePendingMainOps() == -1)
+ DBUG_RETURN(-1);
+ }
+ }
+ if (len > 0) {
assert(pos >= theInlineSize);
Uint32 off = (pos - theInlineSize) % thePartSize;
// partial first block
@@ -2020,6 +2027,39 @@ NdbBlob::executePendingBlobWrites()
DBUG_RETURN(0);
}
+/*
+ * bug#13881465
+ *
+ * Calling executeNoBlobs() can execute previous prepared main ops,
+ * by-passing their preExecute() triggers. This method calls normal
+ * execute() first if there are any prepared key ops with blobs.
+ *
+ * The scenario in bug#13881465 was a scan delete batch, where user
+ * at 2nd result row first did a blob read where last part was partial,
+ * forcing executeNoBlobs().
+ */
+
+int
+NdbBlob::executePendingMainOps()
+{
+ DBUG_ENTER("NdbBlob::executePendingMainOps");
+#ifdef VM_TRACE
+ {
+ const char* p = NdbEnv_GetEnv("NDB_BLOB_BUG13881465", (char*)0, 0);
+ if (p != 0 && strchr("1Y", p[0]) != 0)
+ DBUG_RETURN(0);
+ }
+#endif
+ if (theNdbCon->theBlobPreparedKeyOpsFlag) {
+ if (theNdbCon->execute(NdbTransaction::NoCommit) == -1)
+ DBUG_RETURN(-1);
+ assert(theNdbCon->theBlobPreparedKeyOpsFlag == false);
+ } else {
+ DBUG_PRINT("info", ("no prepared blob ops in trans"));
+ }
+ DBUG_RETURN(0);
+}
+
// callbacks
int
@@ -2118,6 +2158,12 @@ NdbBlob::atPrepareCommon(NdbTransaction*
theTable = anOp->m_currentTable;
theAccessTable = anOp->m_accessTable;
theColumn = aColumn;
+ DBUG_PRINT("info", ("optype=%d", theNdbOp->theOperationType));
+ // mark that transaction has prepared key ops with blobs
+ if (isKeyOp() && !theNdbCon->theBlobPreparedKeyOpsFlag) {
+ DBUG_PRINT("info", ("set transaction theBlobPreparedKeyOpsFlag = true"));
+ theNdbCon->theBlobPreparedKeyOpsFlag = true;
+ }
// prepare blob column and table
if (prepareColumn() == -1)
return -1;
=== modified file 'storage/ndb/src/ndbapi/NdbTransaction.cpp'
--- a/storage/ndb/src/ndbapi/NdbTransaction.cpp 2011-10-22 09:38:48 +0000
+++ b/storage/ndb/src/ndbapi/NdbTransaction.cpp 2012-08-05 10:05:54 +0000
@@ -78,6 +78,7 @@ NdbTransaction::NdbTransaction( Ndb* aNd
m_scanningQuery(NULL),
theBuddyConPtr(0xFFFFFFFF),
theBlobFlag(false),
+ theBlobPreparedKeyOpsFlag(false),
thePendingBlobOps(0),
maxPendingBlobReadBytes(~Uint32(0)),
maxPendingBlobWriteBytes(~Uint32(0)),
@@ -163,6 +164,7 @@ NdbTransaction::init()
theBuddyConPtr = 0xFFFFFFFF;
//
theBlobFlag = false;
+ theBlobPreparedKeyOpsFlag = false;
thePendingBlobOps = 0;
m_theFirstLockHandle = NULL;
m_theLastLockHandle = NULL;
@@ -365,7 +367,7 @@ NdbTransaction::execute(ExecType aTypeOf
* operation, in case it adds extra ops
*/
firstSavedOp = tPrepOp->next(); // Could be NULL
- lastSavedOp = theLastOpInList;
+ lastSavedOp = firstSavedOp != NULL ? theLastOpInList : NULL;
DBUG_PRINT("info", ("Splitting ops list between %p and %p",
firstSavedOp, lastSavedOp));
tPrepOp->next(NULL);
@@ -555,6 +557,12 @@ NdbTransaction::execute(ExecType aTypeOf
theError = firstTransError;
}
+ if (theBlobPreparedKeyOpsFlag)
+ {
+ DBUG_PRINT("info", ("set transaction theBlobPreparedKeyOpsFlag = false"));
+ theBlobPreparedKeyOpsFlag = false;
+ }
+
DBUG_RETURN(ret);
}
=== modified file 'storage/ndb/test/run-test/daily-basic-tests.txt'
--- a/storage/ndb/test/run-test/daily-basic-tests.txt 2012-06-26 09:18:05 +0000
+++ b/storage/ndb/test/run-test/daily-basic-tests.txt 2012-08-05 10:05:54 +0000
@@ -1874,4 +1874,8 @@ args: -n LeakApiConnectObjects T1
max-time: 300
cmd: testScan
args: -n extraNextResultBug11748194 T1
+
+max-time: 300
+cmd: ndb_blob_tool
+args: --bug13881465=1 -r 100
=== modified file 'storage/ndb/tools/ndb_blob_tool.cpp'
--- a/storage/ndb/tools/ndb_blob_tool.cpp 2012-06-05 11:49:49 +0000
+++ b/storage/ndb/tools/ndb_blob_tool.cpp 2012-08-05 10:05:54 +0000
@@ -20,7 +20,7 @@
#include <NdbApi.hpp>
#include <NDBT.hpp>
-static const char* opt_dbname = 0;
+static const char* opt_dbname = "TEST_DB";
static my_bool opt_check_orphans = false;
static my_bool opt_delete_orphans = false;
static const char* opt_dump_file = 0;
@@ -87,6 +87,10 @@ struct Val { // attr value scanned from
static Val* g_vallist = 0;
static int g_valcount = 0;
+// bug tests
+static int opt_bug13881465 = 0;
+static int opt_records = 1000;
+
#define CHK1(b) \
if (!(b)) { \
ret = -1; \
@@ -494,12 +498,345 @@ doall()
return ret;
}
+/*
+ * bug#13881465
+ */
+
+// blob length bigger than inline 256 and not complete parts 2000
+static const int bug13881465_blen = 280; // not 256+2000
+
+// either of these options "disables" the bug
+// do not read blob value before delete (bit 2)
+static bool bug13881465_optnoread = false;
+// use another transaction to do deleteCurrentTuple (bit 4)
+static bool bug13881465_optnewtx = false;
+
+// other options just for testing
+// use blob ActiveHook instead of getValue (bit 8)
+static bool bug13881465_optactivehook = false;
+
+static NdbDictionary::RecordSpecification bug13881465_recspec[2];
+
+static int
+bug13881465_create()
+{
+ DBUG_ENTER("bug13881465_create");
+ int ret = 0;
+ do
+ {
+ (void)g_dic->dropTable(g_tabname);
+ NdbDictionary::Table tab;
+ tab.setName(g_tabname);
+ {
+ NdbDictionary::Column c;
+ c.setName("a");
+ c.setType(NdbDictionary::Column::Int);
+ c.setPrimaryKey(true);
+ tab.addColumn(c);
+ }
+ {
+ NdbDictionary::Column c;
+ c.setName("b");
+ c.setType(NdbDictionary::Column::Text);
+ c.setNullable(false);
+ c.setPartSize(2000);
+ tab.addColumn(c);
+ }
+ CHK2(g_dic->createTable(tab) == 0, g_dic->getNdbError());
+ CHK2((g_tab = g_dic->getTable(g_tabname)) != 0, g_dic->getNdbError());
+
+ NdbDictionary::RecordSpecification* rs = bug13881465_recspec;
+ {
+ const NdbDictionary::Column* c = g_tab->getColumn("a");
+ assert(c != 0);
+ rs[0].column = c;
+ rs[0].offset = 0;
+ rs[0].nullbit_byte_offset = ~(Uint32)0;
+ rs[0].nullbit_bit_in_byte = ~(Uint32)0;
+ }
+ {
+ const NdbDictionary::Column* c = g_tab->getColumn("b");
+ assert(c != 0);
+ rs[1].column = c;
+ rs[1].offset = 4;
+ rs[1].nullbit_byte_offset = ~(Uint32)0;
+ rs[1].nullbit_bit_in_byte = ~(Uint32)0;
+ }
+ }
+ while (0);
+ DBUG_RETURN(ret);
+}
+
+static int
+bug13881465_drop()
+{
+ DBUG_ENTER("bug13881465_drop");
+ int ret = 0;
+ do
+ {
+ CHK2(g_dic->dropTable(g_tabname) == 0, g_dic->getNdbError());
+ }
+ while (0);
+ DBUG_RETURN(ret);
+}
+
+static void
+bug13881465_bval(int k, const char* xx, char* buf)
+{
+ const int blen = bug13881465_blen;
+ sprintf(buf, "%s%d", xx, k);
+ int n = strlen(buf);
+ for (int i = 0; i < blen; i++)
+ {
+ buf[i] = buf[i % n];
+ }
+}
+
+static int
+bug13881465_insert(int k, const char* xx)
+{
+ DBUG_ENTER("bug13881465_insert");
+ int ret = 0;
+ do
+ {
+ NdbTransaction* tx = 0;
+ CHK2((tx = g_ndb->startTransaction()) != 0, g_ndb->getNdbError());
+
+ NdbOperation* op = 0;
+ CHK2((op = tx->getNdbOperation(g_tab)) != 0, tx->getNdbError());
+ CHK2(op->insertTuple() == 0, op->getNdbError());
+
+ Int32 a = k + 0x12340000;
+ CHK2(op->equal("a", (const char*)&a) == 0, op->getNdbError());
+
+ const int blen = bug13881465_blen;
+ char buf[blen + 1];
+ bug13881465_bval(k, xx, buf);
+ buf[blen] = 0;
+ NdbBlob* bh = 0;
+ CHK2((bh = op->getBlobHandle("b")) != 0, op->getNdbError());
+ CHK2(bh->setValue(buf, blen) == 0, bh->getNdbError());
+
+ CHK2(tx->execute(Commit) == 0, tx->getNdbError());
+ g_ndb->closeTransaction(tx);
+ }
+ while (0);
+ DBUG_RETURN(ret);
+}
+
+static int
+bug13881465_insertall(const char* xx)
+{
+ DBUG_ENTER("bug13881465_insertall");
+ int ret = 0;
+ for (int k = 0; k < opt_records; k++)
+ {
+ CHK1(bug13881465_insert(k, xx) == 0);
+ }
+ DBUG_RETURN(ret);
+}
+
+static int
+bug13881465_activehook(NdbBlob* bh, void* arg)
+{
+ DBUG_ENTER("bug13881465_activehook");
+ int ret = 0;
+ char* buf = (char*)arg;
+ do
+ {
+ int isNull = -1;
+ CHK2(bh->getNull(isNull) == 0, bh->getNdbError());
+ CHK2(isNull == 0, "blob isNull=" << isNull);
+
+ Uint64 length64;
+ CHK2(bh->getLength(length64) == 0, bh->getNdbError());
+ int length = (int)length64;
+ const int blen = bug13881465_blen;
+ CHK2(length == blen, "length " << length << "!=" << blen);
+
+ Uint32 bytes32 = (Uint32)length64;
+ CHK2(bh->readData(buf, bytes32) == 0, bh->getNdbError());
+ int bytes = (int)bytes32;
+ CHK2(bytes == length, "bytes " << bytes << "!=" << length);
+ }
+ while (0);
+ DBUG_RETURN(ret);
+}
+
+static int
+bug13881465_scandelete(const char* xx, int &rows)
+{
+ DBUG_ENTER("bug13881465_scandelete");
+ int ret = 0;
+ rows = 0;
+ do
+ {
+ NdbTransaction* scantx = 0;
+ CHK2((scantx = g_ndb->startTransaction()) != 0, g_ndb->getNdbError());
+
+ Int32 a = -1;
+ NdbRecord* rec = 0;
+ struct { Int32 a; char b[16+256]; } recbuf;
+ NdbScanOperation* scanop = 0;
+
+ const NdbOperation::LockMode lm = NdbOperation::LM_Exclusive;
+
+ {
+ const NdbDictionary::RecordSpecification* rs = bug13881465_recspec;
+ rec = 0;
+ CHK2((rec = g_dic->createRecord(g_tab, rs, 2, sizeof(rs[0]))) != 0, g_dic->getNdbError());
+ Uint32 len = NdbDictionary::getRecordRowLength(rec);
+ assert(len == sizeof(recbuf));
+ CHK2((scanop = scantx->scanTable(rec, lm)) != 0, scantx->getNdbError());
+ }
+
+ NdbBlob* bh = 0;
+ CHK2((bh = scanop->getBlobHandle("b")) != 0, scanop->getNdbError());
+
+ const int blen = bug13881465_blen;
+ char buf1[blen+1];
+ if (!bug13881465_optnoread)
+ {
+ if (!bug13881465_optactivehook)
+ {
+ CHK2(bh->getValue(buf1, blen) == 0, bh->getNdbError());
+ }
+ else
+ {
+ CHK2(bh->setActiveHook(bug13881465_activehook, (void*)buf1) == 0, bh->getNdbError());
+ }
+ }
+
+ CHK2(scantx->execute(NoCommit) == 0, scantx->getNdbError());
+
+ NdbTransaction* tx = 0;
+ if (!bug13881465_optnewtx)
+ {
+ // use scantx
+ }
+ else
+ {
+ CHK2((tx = g_ndb->startTransaction()) != 0, g_ndb->getNdbError());
+ }
+
+ int res = -1;
+ while (1)
+ {
+ a = -1;
+ memset(buf1, 0xff, blen);
+ res = scanop->nextResultCopyOut((char*)&recbuf, true, false);
+ CHK2(res == 0 || res == 1, scanop->getNdbError());
+ if (res == 1)
+ break;
+
+ int batch = 0;
+ while (1)
+ {
+ a = recbuf.a;
+ DBUG_PRINT("info", ("scanned a=%x", a));
+ g_info << "scanned a=" << hex << a << endl;
+ buf1[blen] = 0;
+
+ {
+ int k = a - 0x12340000;
+ CHK2(k >= 0 && k < opt_records, "a=" << a << " k=" << k);
+ if (!bug13881465_optnoread)
+ {
+ char buf2[blen + 1];
+ bug13881465_bval(k, xx, buf2);
+ buf2[blen] = 0;
+ CHK2(memcmp(buf1, buf2, blen) == 0, buf1 << " VS " << buf2);
+ }
+ }
+
+ const NdbOperation* delop = 0;
+ if (!bug13881465_optnewtx)
+ {
+ CHK2((delop = scanop->deleteCurrentTuple(scantx, rec)) != 0, scanop->getNdbError());
+ }
+ else
+ {
+ CHK2((delop = scanop->deleteCurrentTuple(tx, rec)) != 0, scanop->getNdbError());
+ }
+ DBUG_PRINT("info", ("delete op=%p", delop));
+ batch++;
+ rows++;
+
+ a = -1;
+ memset(buf1, 0xff, blen);
+ res = scanop->nextResultCopyOut((char*)&recbuf, false, false);
+ CHK2(res == 0 || res == 2, scanop->getNdbError());
+ if (res == 2)
+ break;
+ }
+ CHK1(ret == 0);
+ g_info << "got batch: " << batch << endl;
+
+ if (!bug13881465_optnewtx)
+ {
+ CHK2(scantx->execute(NoCommit) == 0, scantx->getNdbError());
+ }
+ else
+ {
+ CHK2(tx->execute(NoCommit) == 0, tx->getNdbError());
+ }
+ }
+ CHK1(ret == 0);
+
+ if (!bug13881465_optnewtx)
+ {
+ CHK2(scantx->execute(Commit) == 0, scantx->getNdbError());
+ }
+ else
+ {
+ CHK2(tx->execute(Commit) == 0, tx->getNdbError());
+ g_ndb->closeTransaction(tx);
+ }
+ g_ndb->closeTransaction(scantx);
+ }
+ while (0);
+ DBUG_RETURN(ret);
+}
+
+static int
+bug13881465_run()
+{
+ DBUG_ENTER("bug13881465_run");
+ int ret = 0;
+ g_tabname = newstr("t1");
+
+ do
+ {
+ bug13881465_optnoread = (opt_bug13881465 & 2);
+ bug13881465_optnewtx = (opt_bug13881465 & 4);
+ bug13881465_optactivehook = (opt_bug13881465 & 8);
+ g_err << "opt:"
+ << " noread(2)=" << bug13881465_optnoread
+ << " newtx(4)=" << bug13881465_optnewtx
+ << " activehook(8)=" << bug13881465_optactivehook
+ << endl;
+
+ CHK1(doconnect() == 0);
+ CHK1(bug13881465_create() == 0);
+ CHK1(bug13881465_insertall("x") == 0);
+ int rows = -1;
+ CHK1(bug13881465_scandelete("x", rows) == 0);
+ CHK2(rows == opt_records, "wrong number of rows: " << rows);
+ CHK1(bug13881465_insertall("y") == 0);
+ CHK1(bug13881465_drop() == 0);
+ }
+ while (0);
+
+ dodisconnect();
+ DBUG_RETURN(ret);
+}
+
static struct my_option
my_long_options[] =
{
NDB_STD_OPTS("ndb_blob_tool"),
{ "database", 'd',
- "Name of database table is in",
+ "Name of database table is in (default: TEST_DB)",
(uchar**) &opt_dbname, (uchar**) &opt_dbname, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
{ "check-orphans", NDB_OPT_NOSHORT,
@@ -518,6 +855,13 @@ my_long_options[] =
"Verbose messages",
(uchar **)&opt_verbose, (uchar **)&opt_verbose, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+ { "bug13881465", NDB_OPT_NOSHORT,
+ "Run only bug#13881465 ndbapi test, arg is option bits (arg 1 runs default case), uses table t1",
+ (uchar **)&opt_bug13881465, (uchar **)&opt_bug13881465, 0,
+ GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ { "records", 'r', "Number of rows for bug# tests",
+ (uchar**) &opt_records, (uchar**) &opt_records, 0,
+ GET_INT, REQUIRED_ARG, 1000, 0, 0, 0, 0, 0 },
{ 0, 0,
0,
0, 0, 0,
@@ -546,9 +890,6 @@ usage()
static int
checkopts(int argc, char** argv)
{
- if (opt_dbname == 0)
- opt_dbname = "TEST_DB";
-
if (argc < 1)
{
g_err << "Table name required" << endl;
@@ -602,14 +943,31 @@ main(int argc, char** argv)
int ret;
ndb_opt_set_usage_funcs(short_usage_sub, usage);
ret = handle_options(&argc, &argv, my_long_options, ndb_std_get_one_option);
- if (ret != 0 || checkopts(argc, argv) != 0)
+ if (ret != 0)
return NDBT_ProgramExit(NDBT_WRONGARGS);
setOutputLevel(opt_verbose ? 2 : 0);
+ bool bugtests = opt_bug13881465;
+
+ if (!bugtests)
+ {
+ if (ret != 0 || checkopts(argc, argv) != 0)
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+
+ ret = doall();
+ freeall();
+ if (ret == -1)
+ return NDBT_ProgramExit(NDBT_FAILED);
+ return NDBT_ProgramExit(NDBT_OK);
+ }
+
+ if (opt_bug13881465)
+ {
+ ret = bug13881465_run();
+ if (ret == -1)
+ return NDBT_ProgramExit(NDBT_FAILED);
+ return NDBT_ProgramExit(NDBT_OK);
+ }
- ret = doall();
- freeall();
- if (ret == -1)
- return NDBT_ProgramExit(NDBT_FAILED);
- return NDBT_ProgramExit(NDBT_OK);
+ return NDBT_OK;
}
No bundle (reason: useless for push emails).
| Thread |
|---|
| • bzr push into mysql-5.1-telco-7.0 branch (pekka.nousiainen:4956 to 4957)Bug#13881465 | Pekka Nousiainen | 5 Aug |