2897 Frazer Clement 2009-03-02
Bug 43268 Ndb : Change Blob part tables partitioning for UserDefined partitioning
Handling of partitioning cleaned up for UserDefined partitioning and Blobs.
The tight coupling between Blob main table partitions and part tables is removed.
The manual setting of partitionId for non UserDefined tables is removed.
testBlobs is enhanced to verify behaviour across DistrKeyLin, DistrKeyHash,
UserDefined partitioning types.
A small bug with Blob Write via a unique index is resolved.
modified:
storage/ndb/include/ndbapi/NdbBlob.hpp
storage/ndb/src/ndbapi/NdbBlob.cpp
storage/ndb/test/ndbapi/testBlobs.cpp
2896 Jonas Oreland 2009-03-02
ndb - fix testBackup -n FailMaster T1
modified:
storage/ndb/src/kernel/blocks/backup/Backup.cpp
=== modified file 'storage/ndb/include/ndbapi/NdbBlob.hpp'
--- a/storage/ndb/include/ndbapi/NdbBlob.hpp 2008-11-08 20:40:15 +0000
+++ b/storage/ndb/include/ndbapi/NdbBlob.hpp 2009-03-02 16:08:11 +0000
@@ -386,6 +386,7 @@ private:
NdbOperation* theHeadInlineReadOp;
bool theHeadInlineUpdateFlag;
// partition id for data events
+ bool userDefinedPartitioning;
Uint32 noPartitionId() { return ~(Uint32)0; }
Uint32 thePartitionId;
NdbRecAttr* thePartitionIdRecAttr;
@@ -440,6 +441,8 @@ private:
int getHeadInlineValue(NdbOperation* anOp);
void getHeadFromRecAttr();
int setHeadInlineValue(NdbOperation* anOp);
+ void setHeadPartitionId(NdbOperation* anOp);
+ void setPartPartitionId(NdbOperation* anOp);
// data operations
int readDataPrivate(char* buf, Uint32& bytes);
int writeDataPrivate(const char* buf, Uint32 bytes);
=== modified file 'storage/ndb/src/ndbapi/NdbBlob.cpp'
--- a/storage/ndb/src/ndbapi/NdbBlob.cpp 2008-11-08 20:40:15 +0000
+++ b/storage/ndb/src/ndbapi/NdbBlob.cpp 2009-03-02 16:08:11 +0000
@@ -97,8 +97,6 @@ NdbBlob::getBlobTable(NdbTableImpl& bt,
bt.setLogging(t->getLogging());
/*
BLOB tables use the same fragmentation as the original table
- but may change the fragment type if it is UserDefined since it
- must be hash based so that the kernel can handle it on its own.
It also uses the same tablespaces and it never uses any range or
list arrays.
*/
@@ -109,25 +107,8 @@ NdbBlob::getBlobTable(NdbTableImpl& bt,
bt.setFragmentCount(t->getFragmentCount());
bt.m_tablespace_id = t->m_tablespace_id;
bt.m_tablespace_version = t->m_tablespace_version;
- switch (t->getFragmentType())
- {
- case NdbDictionary::Object::FragAllSmall:
- case NdbDictionary::Object::FragAllMedium:
- case NdbDictionary::Object::FragAllLarge:
- case NdbDictionary::Object::FragSingle:
- bt.setFragmentType(t->getFragmentType());
- break;
- case NdbDictionary::Object::DistrKeyLin:
- case NdbDictionary::Object::DistrKeyHash:
- bt.setFragmentType(t->getFragmentType());
- break;
- case NdbDictionary::Object::UserDefined:
- bt.setFragmentType(NdbDictionary::Object::DistrKeyHash);
- break;
- default:
- DBUG_ASSERT(0);
- break;
- }
+ bt.setFragmentType(t->getFragmentType());
+
DBUG_PRINT("info", ("Define BLOB table V%d with"
" primary table = %u and Fragment Type = %u",
blobVersion,
@@ -362,6 +343,7 @@ NdbBlob::init()
theHeadInlineRecAttr = NULL;
theHeadInlineReadOp = NULL;
theHeadInlineUpdateFlag = false;
+ userDefinedPartitioning = false;
thePartitionId = noPartitionId();
thePartitionIdRecAttr = NULL;
theNullFlag = -1;
@@ -546,6 +528,37 @@ NdbBlob::getDistKey(Uint32 part)
return dist;
}
+inline void
+NdbBlob::setHeadPartitionId(NdbOperation* anOp)
+{
+ /* For UserDefined partitioned tables,
+ * we must set the head row's partition id
+ * manually when reading/modifying it with
+ * primary key or unique key.
+ * For scans we do not have to.
+ */
+ if (userDefinedPartitioning &&
+ (thePartitionId != noPartitionId())) {
+ anOp->setPartitionId(thePartitionId);
+ }
+}
+
+inline void
+NdbBlob::setPartPartitionId(NdbOperation* anOp)
+{
+ /* For UserDefined partitioned tables
+ * we must set the part row's partition
+ * id manually when performing operations.
+ * This means that stripe size is ignored
+ * for UserDefined partitioned tables.
+ * All part row operations use primary keys
+ */
+ if (userDefinedPartitioning) {
+ assert(thePartitionId != noPartitionId());
+ anOp->setPartitionId(thePartitionId);
+ }
+}
+
// pack/unpack table/index key XXX support routines, shortcuts
int
@@ -937,6 +950,7 @@ NdbBlob::setPartKeyValue(NdbOperation* a
DBUG_RETURN(-1);
}
}
+ setPartPartitionId(anOp);
DBUG_RETURN(0);
}
@@ -1012,14 +1026,26 @@ NdbBlob::getHeadInlineValue(NdbOperation
* specific checks
*/
theHeadInlineRecAttr = anOp->getValue_impl(theColumn, theHeadInlineBuf.data);
- thePartitionIdRecAttr =
- anOp->getValue_impl(&NdbColumnImpl::getImpl(*NdbDictionary::Column::FRAGMENT));
-
- if (theHeadInlineRecAttr == NULL ||
- thePartitionIdRecAttr == NULL) {
+ if (theHeadInlineRecAttr == NULL) {
setErrorCode(anOp);
DBUG_RETURN(-1);
}
+ if (userDefinedPartitioning)
+ {
+ /* For UserDefined partitioned tables, we ask for the partition
+ * id of the main table row to use for the parts
+ * Not technically needed for main table access via PK, which must
+ * have partition id set for access, but we do it anyway and check
+ * it's as expected.
+ */
+ thePartitionIdRecAttr =
+ anOp->getValue_impl(&NdbColumnImpl::getImpl(*NdbDictionary::Column::FRAGMENT));
+
+ if (thePartitionIdRecAttr == NULL) {
+ setErrorCode(anOp);
+ DBUG_RETURN(-1);
+ }
+ }
/*
* If we get no data from this op then the operation is aborted
* one way or other. Following hack in 5.0 makes sure we don't read
@@ -1041,20 +1067,30 @@ NdbBlob::getHeadFromRecAttr()
if (theNullFlag == 0) {
unpackBlobHead();
theLength = theHead.length;
- if (theEventBlobVersion == -1) {
+ } else {
+ theLength = 0;
+ }
+ if (theEventBlobVersion == -1) {
+ if (userDefinedPartitioning)
+ {
+ /* Use main table fragment id as partition id
+ * for blob parts table
+ */
Uint32 id = thePartitionIdRecAttr->u_32_value();
DBUG_PRINT("info", ("table partition id: %u", id));
if (thePartitionId == noPartitionId()) {
DBUG_PRINT("info", ("discovered here"));
- // setting even in non-partitioned case
thePartitionId = id;
} else {
assert(thePartitionId == id);
}
}
- } else {
- theLength = 0;
+ else
+ {
+ assert(thePartitionIdRecAttr == NULL);
+ }
}
+
DBUG_PRINT("info", ("theNullFlag=%d theLength=%llu",
theNullFlag, theLength));
DBUG_VOID_RETURN;
@@ -1679,10 +1715,7 @@ NdbBlob::readTablePart(char* buf, Uint32
setErrorCode(tOp);
DBUG_RETURN(-1);
}
- if (thePartitionId != noPartitionId() &&
- theStripeSize == 0) {
- tOp->setPartitionId(thePartitionId);
- }
+
tOp->m_abortOption = NdbOperation::AbortOnError;
thePendingBlobOps |= (1 << NdbOperation::ReadRequest);
theNdbCon->thePendingBlobOps |= (1 << NdbOperation::ReadRequest);
@@ -1742,10 +1775,7 @@ NdbBlob::insertPart(const char* buf, Uin
setErrorCode(tOp);
DBUG_RETURN(-1);
}
- if (thePartitionId != noPartitionId() &&
- theStripeSize == 0) {
- tOp->setPartitionId(thePartitionId);
- }
+
tOp->m_abortOption = NdbOperation::AbortOnError;
thePendingBlobOps |= (1 << NdbOperation::InsertRequest);
theNdbCon->thePendingBlobOps |= (1 << NdbOperation::InsertRequest);
@@ -1782,10 +1812,7 @@ NdbBlob::updatePart(const char* buf, Uin
setErrorCode(tOp);
DBUG_RETURN(-1);
}
- if (thePartitionId != noPartitionId() &&
- theStripeSize == 0) {
- tOp->setPartitionId(thePartitionId);
- }
+
tOp->m_abortOption = NdbOperation::AbortOnError;
thePendingBlobOps |= (1 << NdbOperation::UpdateRequest);
theNdbCon->thePendingBlobOps |= (1 << NdbOperation::UpdateRequest);
@@ -1806,10 +1833,7 @@ NdbBlob::deleteParts(Uint32 part, Uint32
setErrorCode(tOp);
DBUG_RETURN(-1);
}
- if (thePartitionId != noPartitionId() &&
- theStripeSize == 0) {
- tOp->setPartitionId(thePartitionId);
- }
+
tOp->m_abortOption = NdbOperation::AbortOnError;
n++;
thePendingBlobOps |= (1 << NdbOperation::DeleteRequest);
@@ -1846,10 +1870,6 @@ NdbBlob::deletePartsUnknown(Uint32 part)
setErrorCode(tOp);
DBUG_RETURN(-1);
}
- if (thePartitionId != noPartitionId() &&
- theStripeSize == 0) {
- tOp->setPartitionId(thePartitionId);
- }
tOp->m_abortOption= NdbOperation::AO_IgnoreError;
tOp->m_noErrorPropagation = true;
n++;
@@ -2009,8 +2029,14 @@ NdbBlob::atPrepareCommon(NdbTransaction*
// prepare blob column and table
if (prepareColumn() == -1)
return -1;
- // check if mysql or user has set partition id
- if (theNdbOp->theDistrKeyIndicator_) {
+ userDefinedPartitioning= (theTable->getFragmentType() ==
+ NdbDictionary::Object::UserDefined);
+ /* UserDefined Partitioning
+ * If user has set partitionId specifically, take it for
+ * Blob head and part operations
+ */
+ if (userDefinedPartitioning &&
+ theNdbOp->theDistrKeyIndicator_) {
thePartitionId = theNdbOp->getPartitionId();
DBUG_PRINT("info", ("op partition id: %u", thePartitionId));
}
@@ -2460,9 +2486,8 @@ NdbBlob::preExecute(NdbTransaction::Exec
setErrorCode(NdbBlobImpl::ErrAbort);
DBUG_RETURN(-1);
}
- if (thePartitionId != noPartitionId()) {
- tOp->setPartitionId(thePartitionId);
- }
+ setHeadPartitionId(tOp);
+
DBUG_PRINT("info", ("Insert : added op to update head+inline in preExecute"));
}
}
@@ -2503,9 +2528,8 @@ NdbBlob::preExecute(NdbTransaction::Exec
setErrorCode(tOp);
DBUG_RETURN(-1);
}
- if (thePartitionId != noPartitionId()) {
- tOp->setPartitionId(thePartitionId);
- }
+ setHeadPartitionId(tOp);
+
if (isWriteOp()) {
/* There may be no data currently, so ignore tuple not found etc. */
tOp->m_abortOption = NdbOperation::AO_IgnoreError;
@@ -2535,6 +2559,11 @@ NdbBlob::preExecute(NdbTransaction::Exec
if (this == tFirstBlob) {
// first blob does it for all
if (g_ndb_blob_ok_to_read_index_table) {
+ /* Cannot work for userDefinedPartitioning + write() op as
+ * we need to read the 'main' partition Id
+ * Maybe this branch should be removed?
+ */
+ assert(!userDefinedPartitioning);
Uint32 pkAttrId = theAccessTable->getNoOfColumns() - 1;
NdbOperation* tOp = theNdbCon->getNdbOperation(theAccessTable, theNdbOp);
if (tOp == NULL ||
@@ -2553,6 +2582,20 @@ NdbBlob::preExecute(NdbTransaction::Exec
setErrorCode(tOp);
DBUG_RETURN(-1);
}
+ if (userDefinedPartitioning && isWriteOp())
+ {
+ /* Index Write op does not perform head read before deleting parts
+ * as it cannot safely IgnoreErrors.
+ * To get partitioning right we read partition id for main row
+ * here.
+ */
+ thePartitionIdRecAttr = tOp->getValue_impl(&NdbColumnImpl::getImpl(*NdbDictionary::Column::FRAGMENT));
+
+ if (thePartitionIdRecAttr == NULL) {
+ setErrorCode(tOp);
+ DBUG_RETURN(-1);
+ }
+ }
}
DBUG_PRINT("info", ("Index op : added op before to read table key"));
}
@@ -2621,9 +2664,8 @@ NdbBlob::preExecute(NdbTransaction::Exec
setErrorCode(NdbBlobImpl::ErrAbort);
DBUG_RETURN(-1);
}
- if (thePartitionId != noPartitionId()) {
- tOp->setPartitionId(thePartitionId);
- }
+ setHeadPartitionId(tOp);
+
DBUG_PRINT("info", ("NdbRecord table write : added op to update head+inline"));
}
}
@@ -2755,9 +2797,8 @@ NdbBlob::postExecute(NdbTransaction::Exe
setErrorCode(NdbBlobImpl::ErrAbort);
DBUG_RETURN(-1);
}
- if (thePartitionId != noPartitionId()) {
- tOp->setPartitionId(thePartitionId);
- }
+ setHeadPartitionId(tOp);
+
DBUG_PRINT("info", ("Insert : added op to update head+inline"));
}
}
@@ -2822,6 +2863,33 @@ NdbBlob::postExecute(NdbTransaction::Exe
}
if (isWriteOp() && isIndexOp()) {
// XXX until IgnoreError fixed for index op
+ if (userDefinedPartitioning)
+ {
+ /* For Index Write with UserDefined partitioning, we get the
+ * partition id from the main table key read created in
+ * preExecute().
+ * Extra complexity as only the first Blob does the read, other
+ * Blobs grab result from first.
+ */
+ if (thePartitionIdRecAttr != NULL)
+ {
+ assert( this == theNdbOp->theBlobList );
+ Uint32 id= thePartitionIdRecAttr->u_32_value();
+ assert( id != noPartitionId() );
+ DBUG_PRINT("info", ("Index write, setting partition id to %d", id));
+ thePartitionId= id;
+ }
+ else
+ {
+ /* First Blob (not us) in this op got the partition Id */
+ assert( theNdbOp->theBlobList );
+ assert( this != theNdbOp->theBlobList );
+
+ thePartitionId= theNdbOp->theBlobList->thePartitionId;
+
+ assert(thePartitionId != noPartitionId());
+ }
+ }
if (deletePartsUnknown(0) == -1)
DBUG_RETURN(-1);
if (theSetFlag && theGetSetBytes > theInlineSize) {
@@ -2855,9 +2923,8 @@ NdbBlob::postExecute(NdbTransaction::Exe
setErrorCode(NdbBlobImpl::ErrAbort);
DBUG_RETURN(-1);
}
- if (thePartitionId != noPartitionId()) {
- tOp->setPartitionId(thePartitionId);
- }
+ setHeadPartitionId(tOp);
+
tOp->m_abortOption = NdbOperation::AbortOnError;
DBUG_PRINT("info", ("added op to update head+inline"));
}
@@ -2889,9 +2956,8 @@ NdbBlob::preCommit()
setErrorCode(NdbBlobImpl::ErrAbort);
DBUG_RETURN(-1);
}
- if (thePartitionId != noPartitionId()) {
- tOp->setPartitionId(thePartitionId);
- }
+ setHeadPartitionId(tOp);
+
tOp->m_abortOption = NdbOperation::AbortOnError;
DBUG_PRINT("info", ("added op to update head+inline"));
}
=== modified file 'storage/ndb/test/ndbapi/testBlobs.cpp'
--- a/storage/ndb/test/ndbapi/testBlobs.cpp 2008-05-23 10:20:10 +0000
+++ b/storage/ndb/test/ndbapi/testBlobs.cpp 2009-03-02 16:08:11 +0000
@@ -210,6 +210,9 @@ static Uint32 g_batchSize= 0;
static Uint32 g_scanFlags= 0;
static Uint32 g_parallel= 0;
static Uint32 g_usingDisk= false;
+static const Uint32 MAX_FRAGS=48 * 8 * 4; // e.g. 48 nodes, 8 frags/node, 4 replicas
+static Uint16 frag_ng_mappings[MAX_FRAGS];
+
static const char* stylename[3] = {
"style=getValue/setValue",
@@ -480,6 +483,12 @@ dropTable()
return 0;
}
+static unsigned
+urandom(unsigned n)
+{
+ return n == 0 ? 0 : random() % n;
+}
+
static int
createTable(int storageType)
{
@@ -494,7 +503,39 @@ createTable(int storageType)
if (storageType == STORAGE_DISK)
tab.setTablespaceName(g_tsName);
tab.setLogging(loggingRequired);
- tab.setFragmentType(NdbDictionary::Object::FragAllLarge);
+
+ /* Choose from the interesting fragmentation types :
+ * DistrKeyHash, DistrKeyLin, UserDefined
+ * Others are obsolete fragment-count setting variants
+ * of DistrKeyLin
+ * For UserDefined partitioning, we need to set the partition
+ * id for all PK operations.
+ */
+ Uint32 fragTypeRange= 1 + (NdbDictionary::Object::UserDefined -
+ NdbDictionary::Object::DistrKeyHash);
+ Uint32 fragType= NdbDictionary::Object::DistrKeyHash + urandom(fragTypeRange);
+
+ tab.setFragmentType((NdbDictionary::Object::FragmentType)fragType);
+
+ if (fragType == NdbDictionary::Object::UserDefined)
+ {
+ /* Need to set the FragmentCount and fragment to NG mapping
+ * for this partitioning type
+ */
+ const Uint32 numNodes= g_ncc->no_db_nodes();
+ const Uint32 numReplicas= 2; // Assumption
+ const Uint32 guessNumNgs= numNodes/2;
+ const Uint32 numNgs= guessNumNgs?guessNumNgs : 1;
+ const Uint32 numFragsPerNode= 2 + (rand() % 3);
+ const Uint32 numPartitions= numReplicas * numNgs * numFragsPerNode;
+
+ tab.setFragmentCount(numPartitions);
+ for (Uint32 i=0; i<numPartitions; i++)
+ {
+ frag_ng_mappings[i]= i % numNgs;
+ }
+ tab.setFragmentData(frag_ng_mappings, sizeof(uint16) * numPartitions);
+ }
const Chr& pk2chr = g_opt.m_pk2chr;
// col PK1 - Uint32
{ NdbDictionary::Column col("PK1");
@@ -615,12 +656,6 @@ createTable(int storageType)
// tuples
-static unsigned
-urandom(unsigned n)
-{
- return n == 0 ? 0 : random() % n;
-}
-
struct Bval {
const Bcol& m_bcol;
char* m_val;
@@ -730,6 +765,11 @@ struct Tup {
return m_pk2;
return urandom(2) == 0 ? m_pk2 : m_pk2eq;
}
+ Uint32 getPartitionId(Uint32 numParts) const {
+ /* Only for UserDefined tables really */
+ return m_pk1 % numParts; // MySQLD hash(PK1) style partitioning
+ }
+
private:
Tup(const Tup&);
Tup& operator=(const Tup&);
@@ -738,6 +778,32 @@ private:
static Tup* g_tups;
static void
+setUDpartId(const Tup& tup, NdbOperation* op)
+{
+ const NdbDictionary::Table* tab= op->getTable();
+ if (tab->getFragmentType() == NdbDictionary::Object::UserDefined)
+ {
+ Uint32 partId= tup.getPartitionId(tab->getFragmentCount());
+ DBG("Setting partition id to " << partId << " out of " <<
+ tab->getFragmentCount());
+ op->setPartitionId(partId);
+ }
+}
+
+static void
+setUDpartIdNdbRecord(const Tup& tup,
+ const NdbDictionary::Table* tab,
+ NdbOperation::OperationOptions& opts)
+{
+ opts.optionsPresent= 0;
+ if (tab->getFragmentType() == NdbDictionary::Object::UserDefined)
+ {
+ opts.optionsPresent= NdbOperation::OperationOptions::OO_PARTITION_ID;
+ opts.partitionId= tup.getPartitionId(tab->getFragmentCount());
+ }
+}
+
+static void
calcBval(const Bcol& b, Bval& v, bool keepsize)
{
if (b.m_nullable && urandom(10) == 0) {
@@ -1163,6 +1229,7 @@ verifyHeadInline(Tup& tup)
CHK(g_opr->equal("PK2", tup.pk2()) == 0);
CHK(g_opr->equal("PK3", (char*)&tup.m_pk3) == 0);
}
+ setUDpartId(tup, g_opr);
NdbRecAttr* ra1;
NdbRecAttr* ra2;
NdbRecAttr* ra_frag;
@@ -1229,6 +1296,10 @@ verifyBlobTable(const Bval& v, Uint32 pk
CHK((ra_data = g_ops->getValue("NDB$DATA")) != 0);
}
+ /* No partition id set on Blob part table scan so that we
+ * find any misplaced parts in other partitions
+ */
+
CHK((ra_frag = g_ops->getValue(NdbDictionary::Column::FRAGMENT)) != 0);
CHK(g_con->execute(NoCommit) == 0);
unsigned partcount;
@@ -1251,7 +1322,8 @@ verifyBlobTable(const Bval& v, Uint32 pk
continue;
}
Uint32 part = ra_part->u_32_value();
- DBG("part " << part << " of " << partcount);
+ Uint32 frag2 = ra_frag->u_32_value();
+ DBG("part " << part << " of " << partcount << " from fragment " << frag2);
CHK(part < partcount && ! seen[part]);
seen[part] = 1;
unsigned n = b.m_inline + part * b.m_partsize;
@@ -1293,7 +1365,6 @@ verifyBlobTable(const Bval& v, Uint32 pk
i++;
}
}
- Uint32 frag2 = ra_frag->u_32_value();
DBG("frags main=" << frag << " blob=" << frag2 << " stripe=" << b.m_stripe);
if (b.m_stripe == 0)
CHK(frag == frag2);
@@ -1352,6 +1423,7 @@ insertPk(int style, int api)
CHK(g_opr->equal("PK2", tup.m_pk2) == 0);
CHK(g_opr->equal("PK3", tup.m_pk3) == 0);
}
+ setUDpartId(tup, g_opr);
CHK(getBlobHandles(g_opr) == 0);
}
else
@@ -1361,7 +1433,15 @@ insertPk(int style, int api)
memcpy(&tup.m_row[g_pk2_offset], tup.m_pk2, g_opt.m_pk2chr.m_totlen);
memcpy(&tup.m_row[g_pk3_offset], &tup.m_pk3, sizeof(tup.m_pk3));
}
- CHK((g_const_opr = g_con->insertTuple(g_full_record, tup.m_row)) != 0);
+ NdbOperation::OperationOptions opts;
+ setUDpartIdNdbRecord(tup,
+ g_ndb->getDictionary()->getTable(g_opt.m_tname),
+ opts);
+ CHK((g_const_opr = g_con->insertTuple(g_full_record,
+ tup.m_row,
+ NULL,
+ &opts,
+ sizeof(opts))) != 0);
CHK(getBlobHandles(g_const_opr) == 0);
}
if (style == 0) {
@@ -1414,6 +1494,7 @@ readPk(int style, int api)
CHK(g_opr->equal("PK2", tup.m_pk2) == 0);
CHK(g_opr->equal("PK3", tup.m_pk3) == 0);
}
+ setUDpartId(tup, g_opr);
CHK(getBlobHandles(g_opr) == 0);
}
else
@@ -1423,13 +1504,24 @@ readPk(int style, int api)
memcpy(&tup.m_key_row[g_pk2_offset], tup.pk2(), g_opt.m_pk2chr.m_totlen);
memcpy(&tup.m_key_row[g_pk3_offset], &tup.m_pk3, sizeof(tup.m_pk3));
}
+ NdbOperation::OperationOptions opts;
+ setUDpartIdNdbRecord(tup,
+ g_ndb->getDictionary()->getTable(g_opt.m_tname),
+ opts);
if (urandom(2) == 0)
CHK((g_const_opr = g_con->readTuple(g_key_record, tup.m_key_row,
- g_blob_record, tup.m_row)) != 0);
+ g_blob_record, tup.m_row,
+ NdbOperation::LM_Read,
+ NULL,
+ &opts,
+ sizeof(opts))) != 0);
else
CHK((g_const_opr = g_con->readTuple(g_key_record, tup.m_key_row,
g_blob_record, tup.m_row,
- NdbOperation::LM_CommittedRead)) != 0);
+ NdbOperation::LM_CommittedRead,
+ NULL,
+ &opts,
+ sizeof(opts))) != 0);
CHK(getBlobHandles(g_const_opr) == 0);
}
if (style == 0) {
@@ -1485,6 +1577,7 @@ updatePk(int style, int api)
CHK(g_opr->equal("PK2", tup.m_pk2) == 0);
CHK(g_opr->equal("PK3", tup.m_pk3) == 0);
}
+ setUDpartId(tup, g_opr);
CHK(getBlobHandles(g_opr) == 0);
}
else
@@ -1494,19 +1587,27 @@ updatePk(int style, int api)
memcpy(&tup.m_key_row[g_pk2_offset], tup.pk2(), g_opt.m_pk2chr.m_totlen);
memcpy(&tup.m_key_row[g_pk3_offset], &tup.m_pk3, sizeof(tup.m_pk3));
}
+ NdbOperation::OperationOptions opts;
+ setUDpartIdNdbRecord(tup,
+ g_ndb->getDictionary()->getTable(g_opt.m_tname),
+ opts);
if (mode == 0) {
DBG("using updateTuple");
CHK((g_const_opr= g_con->updateTuple(g_key_record, tup.m_key_row,
- g_blob_record, tup.m_row)) != 0);
+ g_blob_record, tup.m_row,
+ NULL, &opts, sizeof(opts))) != 0);
} else if (mode == 1) {
DBG("using readTuple exclusive");
CHK((g_const_opr= g_con->readTuple(g_key_record, tup.m_key_row,
g_blob_record, tup.m_row,
- NdbOperation::LM_Exclusive)) != 0);
+ NdbOperation::LM_Exclusive,
+ NULL, &opts, sizeof(opts))) != 0);
} else {
DBG("using readTuple - will fail and retry");
CHK((g_const_opr= g_con->readTuple(g_key_record, tup.m_key_row,
- g_blob_record, tup.m_row)) != 0);
+ g_blob_record, tup.m_row,
+ NdbOperation::LM_Read,
+ NULL, &opts, sizeof(opts))) != 0);
}
CHK(getBlobHandles(g_const_opr) == 0);
}
@@ -1552,6 +1653,7 @@ writePk(int style, int api)
CHK(g_opr->equal("PK2", tup.m_pk2) == 0);
CHK(g_opr->equal("PK3", tup.m_pk3) == 0);
}
+ setUDpartId(tup, g_opr);
CHK(getBlobHandles(g_opr) == 0);
}
else
@@ -1564,8 +1666,13 @@ writePk(int style, int api)
memcpy(&tup.m_key_row[g_pk3_offset], &tup.m_pk3, sizeof(tup.m_pk3));
memcpy(&tup.m_row[g_pk3_offset], &tup.m_pk3, sizeof(tup.m_pk3));
}
+ NdbOperation::OperationOptions opts;
+ setUDpartIdNdbRecord(tup,
+ g_ndb->getDictionary()->getTable(g_opt.m_tname),
+ opts);
CHK((g_const_opr= g_con->writeTuple(g_key_record, tup.m_key_row,
- g_full_record, tup.m_row)) != 0);
+ g_full_record, tup.m_row,
+ NULL, &opts, sizeof(opts))) != 0);
CHK(getBlobHandles(g_const_opr) == 0);
}
if (style == 0) {
@@ -1601,6 +1708,11 @@ deletePk(int api)
{
CHK((g_opr = g_con->getNdbOperation(g_opt.m_tname)) != 0);
CHK(g_opr->deleteTuple() == 0);
+ /* Must set explicit partitionId before equal() calls as that's
+ * where implicit Blob handles are created which need the
+ * partitioning info
+ */
+ setUDpartId(tup, g_opr);
CHK(g_opr->equal("PK1", tup.m_pk1) == 0);
if (g_opt.m_pk2chr.m_len != 0)
{
@@ -1615,8 +1727,13 @@ deletePk(int api)
memcpy(&tup.m_key_row[g_pk2_offset], tup.pk2(), g_opt.m_pk2chr.m_totlen);
memcpy(&tup.m_key_row[g_pk3_offset], &tup.m_pk3, sizeof(tup.m_pk3));
}
+ NdbOperation::OperationOptions opts;
+ setUDpartIdNdbRecord(tup,
+ g_ndb->getDictionary()->getTable(g_opt.m_tname),
+ opts);
CHK((g_const_opr= g_con->deleteTuple(g_key_record, tup.m_key_row,
- g_full_record)) != 0);
+ g_full_record, NULL,
+ NULL, &opts, sizeof(opts))) != 0);
}
if (++n == g_opt.m_batch) {
CHK(g_con->execute(Commit) == 0);
@@ -1665,6 +1782,7 @@ deleteNoPk()
DBG("deletePk pk1=" << hex << tup.m_pk1);
CHK((g_opr = g_con->getNdbOperation(g_opt.m_tname)) != 0);
CHK(g_opr->deleteTuple() == 0);
+ setUDpartId(tup, g_opr);
CHK(g_opr->equal("PK1", tup.m_pk1) == 0);
if (pk2chr.m_len != 0) {
CHK(g_opr->equal("PK2", tup.m_pk2) == 0);
@@ -1700,12 +1818,14 @@ readIdx(int style, int api)
CHK(g_opx->readTuple(NdbOperation::LM_CommittedRead) == 0);
CHK(g_opx->equal("PK2", tup.m_pk2) == 0);
CHK(g_opx->equal("PK3", tup.m_pk3) == 0);
+ /* No need to set partition Id for unique indexes */
CHK(getBlobHandles(g_opx) == 0);
}
else
{
memcpy(&tup.m_key_row[g_pk2_offset], tup.pk2(), g_opt.m_pk2chr.m_totlen);
memcpy(&tup.m_key_row[g_pk3_offset], &tup.m_pk3, sizeof(tup.m_pk3));
+ /* No need to set partition Id for unique indexes */
if (urandom(2) == 0)
CHK((g_const_opr= g_con->readTuple(g_idx_record, tup.m_key_row,
g_blob_record, tup.m_row)) != 0);
@@ -1753,12 +1873,14 @@ updateIdx(int style, int api)
CHK(g_opx->updateTuple() == 0);
CHK(g_opx->equal("PK2", tup.m_pk2) == 0);
CHK(g_opx->equal("PK3", tup.m_pk3) == 0);
+ /* No need to set partition Id for unique indexes */
CHK(getBlobHandles(g_opx) == 0);
}
else
{
memcpy(&tup.m_key_row[g_pk2_offset], tup.pk2(), g_opt.m_pk2chr.m_totlen);
memcpy(&tup.m_key_row[g_pk3_offset], &tup.m_pk3, sizeof(tup.m_pk3));
+ /* No need to set partition Id for unique indexes */
CHK((g_const_opr= g_con->updateTuple(g_idx_record, tup.m_key_row,
g_blob_record, tup.m_row)) != 0);
CHK(getBlobHandles(g_const_opr) == 0);
@@ -1795,6 +1917,7 @@ writeIdx(int style, int api)
CHK(g_opx->writeTuple() == 0);
CHK(g_opx->equal("PK2", tup.m_pk2) == 0);
CHK(g_opx->equal("PK3", tup.m_pk3) == 0);
+ /* No need to set partition Id for unique indexes */
CHK(getBlobHandles(g_opx) == 0);
}
else
@@ -1804,6 +1927,7 @@ writeIdx(int style, int api)
memcpy(&tup.m_row[g_pk1_offset], &tup.m_pk1, sizeof(tup.m_pk1));
memcpy(&tup.m_row[g_pk2_offset], tup.pk2(), g_opt.m_pk2chr.m_totlen);
memcpy(&tup.m_row[g_pk3_offset], &tup.m_pk3, sizeof(tup.m_pk3));
+ /* No need to set partition Id for unique indexes */
CHK((g_const_opr= g_con->writeTuple(g_idx_record, tup.m_key_row,
g_full_record, tup.m_row)) != 0);
CHK(getBlobHandles(g_const_opr) == 0);
@@ -1845,11 +1969,13 @@ deleteIdx(int api)
CHK(g_opx->deleteTuple() == 0);
CHK(g_opx->equal("PK2", tup.m_pk2) == 0);
CHK(g_opx->equal("PK3", tup.m_pk3) == 0);
+ /* No need to set partition Id for unique indexes */
}
else
{
memcpy(&tup.m_key_row[g_pk2_offset], tup.pk2(), g_opt.m_pk2chr.m_totlen);
memcpy(&tup.m_key_row[g_pk3_offset], &tup.m_pk3, sizeof(tup.m_pk3));
+ /* No need to set partition Id for unique indexes */
CHK((g_const_opr= g_con->deleteTuple(g_idx_record, tup.m_key_row,
g_full_record)) != 0);
}
@@ -1906,10 +2032,12 @@ readScan(int style, int api, bool idx)
CHK(g_ops->getValue("PK2", tup.m_pk2) != 0);
CHK(g_ops->getValue("PK3", (char *) &tup.m_pk3) != 0);
}
+ /* Don't bother setting UserDefined partitions for scan tests */
CHK(getBlobHandles(g_ops) == 0);
}
else
{
+ /* Don't bother setting UserDefined partitions for scan tests */
if (urandom(2) == 0)
if (! idx)
CHK((g_ops= g_con->scanTable(g_full_record,
@@ -2008,9 +2136,11 @@ updateScan(int style, int api, bool idx)
CHK(g_ops->getValue("PK2", tup.m_pk2) != 0);
CHK(g_ops->getValue("PK3", (char *) &tup.m_pk3) != 0);
}
+ /* Don't bother setting UserDefined partitions for scan tests */
}
else
{
+ /* Don't bother setting UserDefined partitions for scan tests */
if (! idx)
CHK((g_ops= g_con->scanTable(g_key_record,
NdbOperation::LM_Exclusive)) != 0);
@@ -2108,9 +2238,11 @@ deleteScan(int api, bool idx)
CHK(g_ops->getValue("PK2", tup.m_pk2) != 0);
CHK(g_ops->getValue("PK3", (char *) &tup.m_pk3) != 0);
}
+ /* Don't bother setting UserDefined partitions for scan tests */
}
else
{
+ /* Don't bother setting UserDefined partitions for scan tests */
if (! idx)
CHK((g_ops= g_con->scanTable(g_key_record,
NdbOperation::LM_Exclusive)) != 0);
@@ -2291,6 +2423,7 @@ setupOperation(NdbOperation*& op, OpType
if (pkop)
{
+ setUDpartId(tup, op);
CHK(op->equal("PK1", tup.m_pk1) == 0);
if (g_opt.m_pk2chr.m_len != 0)
{
@@ -2431,6 +2564,7 @@ bugtest_36756()
CHK(g_opr->equal("PK2", tupExists.m_pk2) == 0);
CHK(g_opr->equal("PK3", tupExists.m_pk3) == 0);
}
+ setUDpartId(tupExists, g_opr);
CHK(getBlobHandles(g_opr) == 0);
CHK(setBlobValue(tupExists) == 0);
@@ -2497,6 +2631,7 @@ bugtest_36756()
CHK((g_con= g_ndb->startTransaction()) != 0);
CHK((g_opr= g_con->getNdbOperation(g_opt.m_tname)) != 0);
CHK(g_opr->deleteTuple() == 0);
+ setUDpartId(tupExists, g_opr);
CHK(g_opr->equal("PK1", tupExists.m_pk1) == 0);
if (g_opt.m_pk2chr.m_len != 0)
{
@@ -2546,7 +2681,7 @@ testmain()
srandom(g_opt.m_seed);
}
for (g_loop = 0; g_opt.m_loop == 0 || g_loop < g_opt.m_loop; g_loop++) {
- for (int storage= 0; storage < 2; storage++) {
+ for (int storage= 0; storage < 2; storage++) {
if (!testcase(storageSymbol[storage]))
continue;
@@ -2555,6 +2690,7 @@ testmain()
CHK(createTable(storage) == 0);
{ /* Dump created table information */
Bcol& b1 = g_blob1;
+ DBG("FragType: " << g_dic->getTable(g_opt.m_tname)->getFragmentType());
CHK(NdbBlob::getBlobTableName(b1.m_btname, g_ndb, g_opt.m_tname, "BL1") == 0);
DBG("BL1: inline=" << b1.m_inline << " part=" << b1.m_partsize << " table=" << b1.m_btname);
if (! g_opt.m_oneblob) {
| Thread |
|---|
| • bzr push into mysql-5.1-telco-6.3 branch (frazer:2896 to 2897) | Frazer Clement | 3 Mar |