Below is the list of changes that have just been committed into a local
5.1 repository of knielsen. When knielsen does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2007-03-12 08:42:59+01:00, knielsen@ymer.(none) +2 -0
Merge ymer.(none):/usr/local/mysql/mysql-5.0-ndb
into ymer.(none):/usr/local/mysql/mysql-5.1-new-ndb
MERGE: 1.1810.2636.23
storage/ndb/src/ndbapi/NdbBlob.cpp@stripped, 2007-03-12 08:42:55+01:00, knielsen@ymer.(none) +0 -0
Auto merged
MERGE: 1.22.11.2
storage/ndb/src/ndbapi/NdbBlob.cpp@stripped, 2007-03-12 08:42:55+01:00, knielsen@ymer.(none) +0 -0
Merge rename: ndb/src/ndbapi/NdbBlob.cpp -> storage/ndb/src/ndbapi/NdbBlob.cpp
storage/ndb/test/ndbapi/testBlobs.cpp@stripped, 2007-03-12 08:42:55+01:00, knielsen@ymer.(none) +0 -0
Auto merged
MERGE: 1.20.15.2
storage/ndb/test/ndbapi/testBlobs.cpp@stripped, 2007-03-12 08:42:55+01:00, knielsen@ymer.(none) +0 -0
Merge rename: ndb/test/ndbapi/testBlobs.cpp -> storage/ndb/test/ndbapi/testBlobs.cpp
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: knielsen
# Host: ymer.(none)
# Root: /usr/local/mysql/mysql-5.1-new-ndb/RESYNC
--- 1.20.15.1/ndb/test/ndbapi/testBlobs.cpp 2007-03-12 08:43:07 +01:00
+++ 1.36/storage/ndb/test/ndbapi/testBlobs.cpp 2007-03-12 08:43:07 +01:00
@@ -735,7 +735,7 @@ verifyHeadInline(const Tup& tup)
if (! g_opt.m_oneblob)
CHK((ra2 = g_opr->getValue("BL2")) != 0);
if (tup.m_exists) {
- CHK(g_con->execute(Commit) == 0);
+ CHK(g_con->execute(Commit, AbortOnError) == 0);
DBG("verifyHeadInline BL1");
CHK(verifyHeadInline(g_opt.m_blob1, tup.m_blob1, ra1) == 0);
if (! g_opt.m_oneblob) {
@@ -743,7 +743,8 @@ verifyHeadInline(const Tup& tup)
CHK(verifyHeadInline(g_opt.m_blob2, tup.m_blob2, ra2) == 0);
}
} else {
- CHK(g_con->execute(Commit) == -1 && g_con->getNdbError().code == 626);
+ CHK(g_con->execute(Commit, AbortOnError) == -1 &&
+ g_con->getNdbError().code == 626);
}
g_ndb->closeTransaction(g_con);
g_opr = 0;
@@ -1535,7 +1536,7 @@ testperf()
g_dic = g_ndb->getDictionary();
NdbDictionary::Table tab(g_opt.m_tnameperf);
if (g_dic->getTable(tab.getName()) != 0)
- CHK(g_dic->dropTable(tab) == 0);
+ CHK(g_dic->dropTable(tab.getName()) == 0);
// col A - pk
{ NdbDictionary::Column col("A");
col.setType(NdbDictionary::Column::Unsigned);
--- 1.22.11.1/ndb/src/ndbapi/NdbBlob.cpp 2007-03-12 08:43:07 +01:00
+++ 1.53/storage/ndb/src/ndbapi/NdbBlob.cpp 2007-03-12 08:43:07 +01:00
@@ -23,6 +23,7 @@
#include "NdbBlobImpl.hpp"
#include <NdbScanOperation.hpp>
#include <signaldata/TcKeyReq.hpp>
+#include <NdbEventOperationImpl.hpp>
/*
* Reading index table directly (as a table) is faster but there are
@@ -30,7 +31,21 @@
*/
static const bool g_ndb_blob_ok_to_read_index_table = false;
-// state (inline)
+// get state
+
+NdbBlob::State
+NdbBlob::getState()
+{
+ return theState;
+}
+
+void
+NdbBlob::getVersion(int& version)
+{
+ version = theEventBlobVersion;
+}
+
+// set state (inline)
inline void
NdbBlob::setState(State newState)
@@ -46,32 +61,72 @@ NdbBlob::setState(State newState)
int
NdbBlob::getBlobTableName(char* btname, Ndb* anNdb, const char* tableName, const char* columnName)
{
+ DBUG_ENTER("NdbBlob::getBlobTableName");
NdbTableImpl* t = anNdb->theDictionary->m_impl.getTable(tableName);
if (t == NULL)
- return -1;
+ DBUG_RETURN(-1);
NdbColumnImpl* c = t->getColumn(columnName);
if (c == NULL)
- return -1;
+ DBUG_RETURN(-1);
getBlobTableName(btname, t, c);
- return 0;
+ DBUG_RETURN(0);
}
void
NdbBlob::getBlobTableName(char* btname, const NdbTableImpl* t, const NdbColumnImpl* c)
{
- assert(t != 0 && c != 0 && c->getBlobType());
+ DBUG_ENTER("NdbBlob::getBlobTableName");
+ assert(t != 0 && c != 0 && c->getBlobType() && c->getPartSize() != 0);
memset(btname, 0, NdbBlobImpl::BlobTableNameSize);
- sprintf(btname, "NDB$BLOB_%d_%d", (int)t->m_tableId, (int)c->m_attrId);
+ sprintf(btname, "NDB$BLOB_%d_%d", (int)t->m_id, (int)c->m_column_no);
+ DBUG_PRINT("info", ("blob table name: %s", btname));
+ DBUG_VOID_RETURN;
}
void
NdbBlob::getBlobTable(NdbTableImpl& bt, const NdbTableImpl* t, const NdbColumnImpl* c)
{
+ DBUG_ENTER("NdbBlob::getBlobTable");
char btname[NdbBlobImpl::BlobTableNameSize];
getBlobTableName(btname, t, c);
bt.setName(btname);
bt.setLogging(t->getLogging());
- bt.setFragmentType(t->getFragmentType());
+ /*
+ 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.
+ */
+ bt.m_primaryTableId = t->m_id;
+ bt.m_fd.clear();
+ bt.m_ts.clear();
+ bt.m_range.clear();
+ 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;
+ }
+ DBUG_PRINT("info",
+ ("Create BLOB table with primary table = %u and Fragment Type = %u",
+ bt.m_primaryTableId, (uint)bt.getFragmentType()));
{ NdbDictionary::Column bc("PK");
bc.setType(NdbDictionary::Column::Unsigned);
assert(t->m_keyLenInWords != 0);
@@ -105,8 +160,67 @@ NdbBlob::getBlobTable(NdbTableImpl& bt,
break;
}
bc.setLength(c->getPartSize());
+ bc.setStorageType(c->getStorageType());
bt.addColumn(bc);
}
+ DBUG_VOID_RETURN;
+}
+
+int
+NdbBlob::getBlobEventName(char* bename, Ndb* anNdb, const char* eventName, const char* columnName)
+{
+ NdbEventImpl* e = anNdb->theDictionary->m_impl.getEvent(eventName);
+ if (e == NULL)
+ return -1;
+ NdbColumnImpl* c = e->m_tableImpl->getColumn(columnName);
+ if (c == NULL)
+ return -1;
+ getBlobEventName(bename, e, c);
+ delete e; // it is from new NdbEventImpl
+ return 0;
+}
+
+void
+NdbBlob::getBlobEventName(char* bename, const NdbEventImpl* e, const NdbColumnImpl* c)
+{
+ // XXX events should have object id
+ snprintf(bename, MAX_TAB_NAME_SIZE, "NDB$BLOBEVENT_%s_%d", e->m_name.c_str(), (int)c->m_column_no);
+}
+
+void
+NdbBlob::getBlobEvent(NdbEventImpl& be, const NdbEventImpl* e, const NdbColumnImpl* c)
+{
+ DBUG_ENTER("NdbBlob::getBlobEvent");
+ // blob table
+ assert(c->m_blobTable != NULL);
+ const NdbTableImpl& bt = *c->m_blobTable;
+ // blob event name
+ char bename[MAX_TAB_NAME_SIZE+1];
+ getBlobEventName(bename, e, c);
+ bename[sizeof(bename)-1]= 0;
+ be.setName(bename);
+ be.setTable(bt);
+ // simple assigments
+ be.mi_type = e->mi_type;
+ be.m_dur = e->m_dur;
+ be.m_mergeEvents = e->m_mergeEvents;
+ // report unchanged data
+ // not really needed now since UPD is DEL o INS and we subscribe to all
+ be.setReport(NdbDictionary::Event::ER_ALL);
+ // columns PK - DIST - PART - DATA
+ { const NdbColumnImpl* bc = bt.getColumn((Uint32)0);
+ be.addColumn(*bc);
+ }
+ { const NdbColumnImpl* bc = bt.getColumn((Uint32)1);
+ be.addColumn(*bc);
+ }
+ { const NdbColumnImpl* bc = bt.getColumn((Uint32)2);
+ be.addColumn(*bc);
+ }
+ { const NdbColumnImpl* bc = bt.getColumn((Uint32)3);
+ be.addColumn(*bc);
+ }
+ DBUG_VOID_RETURN;
}
// initialization
@@ -120,9 +234,16 @@ void
NdbBlob::init()
{
theState = Idle;
+ theEventBlobVersion = -1;
theNdb = NULL;
theNdbCon = NULL;
theNdbOp = NULL;
+ theEventOp = NULL;
+ theBlobEventOp = NULL;
+ theBlobEventPkRecAttr = NULL;
+ theBlobEventDistRecAttr = NULL;
+ theBlobEventPartRecAttr = NULL;
+ theBlobEventDataRecAttr = NULL;
theTable = NULL;
theAccessTable = NULL;
theBlobTable = NULL;
@@ -188,9 +309,16 @@ NdbBlob::Buf::alloc(unsigned n)
}
void
+NdbBlob::Buf::zerorest()
+{
+ assert(size <= maxsize);
+ memset(data + size, 0, maxsize - size);
+}
+
+void
NdbBlob::Buf::copyfrom(const NdbBlob::Buf& src)
{
- assert(size == src.size);
+ size = src.size;
memcpy(data, src.data, size);
}
@@ -305,6 +433,76 @@ NdbBlob::getDistKey(Uint32 part)
return (part / theStripeSize) % theStripeSize;
}
+// pack/unpack table/index key XXX support routines, shortcuts
+
+int
+NdbBlob::packKeyValue(const NdbTableImpl* aTable, const Buf& srcBuf)
+{
+ DBUG_ENTER("NdbBlob::packKeyValue");
+ const Uint32* data = (const Uint32*)srcBuf.data;
+ unsigned pos = 0;
+ Uint32* pack_data = (Uint32*)thePackKeyBuf.data;
+ unsigned pack_pos = 0;
+ for (unsigned i = 0; i < aTable->m_columns.size(); i++) {
+ NdbColumnImpl* c = aTable->m_columns[i];
+ assert(c != NULL);
+ if (c->m_pk) {
+ unsigned len = c->m_attrSize * c->m_arraySize;
+ Uint32 pack_len;
+ bool ok = c->get_var_length(&data[pos], pack_len);
+ if (! ok) {
+ setErrorCode(NdbBlobImpl::ErrCorruptPK);
+ DBUG_RETURN(-1);
+ }
+ memcpy(&pack_data[pack_pos], &data[pos], pack_len);
+ while (pack_len % 4 != 0) {
+ char* p = (char*)&pack_data[pack_pos] + pack_len++;
+ *p = 0;
+ }
+ pos += (len + 3) / 4;
+ pack_pos += pack_len / 4;
+ }
+ }
+ assert(4 * pos == srcBuf.size);
+ assert(4 * pack_pos <= thePackKeyBuf.maxsize);
+ thePackKeyBuf.size = 4 * pack_pos;
+ thePackKeyBuf.zerorest();
+ DBUG_RETURN(0);
+}
+
+int
+NdbBlob::unpackKeyValue(const NdbTableImpl* aTable, Buf& dstBuf)
+{
+ DBUG_ENTER("NdbBlob::unpackKeyValue");
+ Uint32* data = (Uint32*)dstBuf.data;
+ unsigned pos = 0;
+ const Uint32* pack_data = (const Uint32*)thePackKeyBuf.data;
+ unsigned pack_pos = 0;
+ for (unsigned i = 0; i < aTable->m_columns.size(); i++) {
+ NdbColumnImpl* c = aTable->m_columns[i];
+ assert(c != NULL);
+ if (c->m_pk) {
+ unsigned len = c->m_attrSize * c->m_arraySize;
+ Uint32 pack_len;
+ bool ok = c->get_var_length(&pack_data[pack_pos], pack_len);
+ if (! ok) {
+ setErrorCode(NdbBlobImpl::ErrCorruptPK);
+ DBUG_RETURN(-1);
+ }
+ memcpy(&data[pos], &pack_data[pack_pos], pack_len);
+ while (pack_len % 4 != 0) {
+ char* p = (char*)&data[pos] + pack_len++;
+ *p = 0;
+ }
+ pos += (len + 3) / 4;
+ pack_pos += pack_len / 4;
+ }
+ }
+ assert(4 * pos == dstBuf.size);
+ assert(4 * pack_pos == thePackKeyBuf.size);
+ DBUG_RETURN(0);
+}
+
// getters and setters
int
@@ -347,13 +545,15 @@ NdbBlob::setTableKeyValue(NdbOperation*
assert(c != NULL);
if (c->m_pk) {
unsigned len = c->m_attrSize * c->m_arraySize;
- if (anOp->equal_impl(c, (const char*)&data[pos], len) == -1) {
+ if (anOp->equal_impl(c, (const char*)&data[pos]) == -1) {
setErrorCode(anOp);
DBUG_RETURN(-1);
}
pos += (len + 3) / 4;
}
}
+ if (theNdbOp->theDistrKeyIndicator_)
+ anOp->setPartitionId(theNdbOp->getPartitionId());
assert(pos == theKeyBuf.size / 4);
DBUG_RETURN(0);
}
@@ -371,7 +571,7 @@ NdbBlob::setAccessKeyValue(NdbOperation*
assert(c != NULL);
if (c->m_pk) {
unsigned len = c->m_attrSize * c->m_arraySize;
- if (anOp->equal_impl(c, (const char*)&data[pos], len) == -1) {
+ if (anOp->equal_impl(c, (const char*)&data[pos]) == -1) {
setErrorCode(anOp);
DBUG_RETURN(-1);
}
@@ -386,10 +586,10 @@ int
NdbBlob::setPartKeyValue(NdbOperation* anOp, Uint32 part)
{
DBUG_ENTER("NdbBlob::setPartKeyValue");
- DBUG_PRINT("info", ("dist=%u part=%u key=", getDistKey(part), part));
- DBUG_DUMP("info", theKeyBuf.data, 4 * theTable->m_keyLenInWords);
+ DBUG_PRINT("info", ("dist=%u part=%u packkey=", getDistKey(part), part));
+ DBUG_DUMP("info", thePackKeyBuf.data, 4 * thePackKeyBuf.size);
// TODO use attr ids after compatibility with 4.1.7 not needed
- if (anOp->equal("PK", theKeyBuf.data) == -1 ||
+ if (anOp->equal("PK", thePackKeyBuf.data) == -1 ||
anOp->equal("DIST", getDistKey(part)) == -1 ||
anOp->equal("PART", part) == -1) {
setErrorCode(anOp);
@@ -416,8 +616,10 @@ NdbBlob::getHeadFromRecAttr()
DBUG_ENTER("NdbBlob::getHeadFromRecAttr");
assert(theHeadInlineRecAttr != NULL);
theNullFlag = theHeadInlineRecAttr->isNULL();
- assert(theNullFlag != -1);
+ assert(theEventBlobVersion >= 0 || theNullFlag != -1);
theLength = ! theNullFlag ? theHead->length : 0;
+ DBUG_PRINT("info", ("theNullFlag=%d theLength=%llu",
+ theNullFlag, theLength));
DBUG_VOID_RETURN;
}
@@ -430,7 +632,7 @@ NdbBlob::setHeadInlineValue(NdbOperation
memset(theInlineData + theLength, 0, theInlineSize - theLength);
assert(theNullFlag != -1);
const char* aValue = theNullFlag ? 0 : theHeadInlineBuf.data;
- if (anOp->setValue(theColumn, aValue, theHeadInlineBuf.size) == -1) {
+ if (anOp->setValue(theColumn, aValue) == -1) {
setErrorCode(anOp);
DBUG_RETURN(-1);
}
@@ -521,7 +723,19 @@ NdbBlob::setActiveHook(ActiveHook active
// misc operations
int
-NdbBlob::getNull(bool& isNull)
+NdbBlob::getDefined(int& isNull) // deprecated
+{
+ DBUG_ENTER("NdbBlob::getDefined");
+ if (theState == Prepared && theSetFlag) {
+ isNull = (theSetBuf == NULL);
+ DBUG_RETURN(0);
+ }
+ isNull = theNullFlag;
+ DBUG_RETURN(0);
+}
+
+int
+NdbBlob::getNull(bool& isNull) // deprecated
{
DBUG_ENTER("NdbBlob::getNull");
if (theState == Prepared && theSetFlag) {
@@ -537,6 +751,23 @@ NdbBlob::getNull(bool& isNull)
}
int
+NdbBlob::getNull(int& isNull)
+{
+ DBUG_ENTER("NdbBlob::getNull");
+ if (theState == Prepared && theSetFlag) {
+ isNull = (theSetBuf == NULL);
+ DBUG_RETURN(0);
+ }
+ isNull = theNullFlag;
+ if (isNull == -1 && theEventBlobVersion == -1) {
+ setErrorCode(NdbBlobImpl::ErrState);
+ DBUG_RETURN(-1);
+ }
+ DBUG_PRINT("info", ("isNull=%d", isNull));
+ DBUG_RETURN(0);
+}
+
+int
NdbBlob::setNull()
{
DBUG_ENTER("NdbBlob::setNull");
@@ -882,6 +1113,18 @@ NdbBlob::readParts(char* buf, Uint32 par
{
DBUG_ENTER("NdbBlob::readParts");
DBUG_PRINT("info", ("part=%u count=%u", part, count));
+ int ret;
+ if (theEventBlobVersion == -1)
+ ret = readTableParts(buf, part, count);
+ else
+ ret = readEventParts(buf, part, count);
+ DBUG_RETURN(ret);
+}
+
+int
+NdbBlob::readTableParts(char* buf, Uint32 part, Uint32 count)
+{
+ DBUG_ENTER("NdbBlob::readTableParts");
Uint32 n = 0;
while (n < count) {
NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTable);
@@ -892,7 +1135,7 @@ NdbBlob::readParts(char* buf, Uint32 par
setErrorCode(tOp);
DBUG_RETURN(-1);
}
- tOp->m_abortOption = NdbTransaction::AbortOnError;
+ tOp->m_abortOption = NdbOperation::AbortOnError;
buf += thePartSize;
n++;
thePendingBlobOps |= (1 << NdbOperation::ReadRequest);
@@ -902,6 +1145,18 @@ NdbBlob::readParts(char* buf, Uint32 par
}
int
+NdbBlob::readEventParts(char* buf, Uint32 part, Uint32 count)
+{
+ DBUG_ENTER("NdbBlob::readEventParts");
+ int ret = theEventOp->readBlobParts(buf, this, part, count);
+ if (ret != 0) {
+ setErrorCode(theEventOp);
+ DBUG_RETURN(-1);
+ }
+ DBUG_RETURN(0);
+}
+
+int
NdbBlob::insertParts(const char* buf, Uint32 part, Uint32 count)
{
DBUG_ENTER("NdbBlob::insertParts");
@@ -916,7 +1171,7 @@ NdbBlob::insertParts(const char* buf, Ui
setErrorCode(tOp);
DBUG_RETURN(-1);
}
- tOp->m_abortOption = NdbTransaction::AbortOnError;
+ tOp->m_abortOption = NdbOperation::AbortOnError;
buf += thePartSize;
n++;
thePendingBlobOps |= (1 << NdbOperation::InsertRequest);
@@ -940,7 +1195,7 @@ NdbBlob::updateParts(const char* buf, Ui
setErrorCode(tOp);
DBUG_RETURN(-1);
}
- tOp->m_abortOption = NdbTransaction::AbortOnError;
+ tOp->m_abortOption = NdbOperation::AbortOnError;
buf += thePartSize;
n++;
thePendingBlobOps |= (1 << NdbOperation::UpdateRequest);
@@ -963,7 +1218,7 @@ NdbBlob::deleteParts(Uint32 part, Uint32
setErrorCode(tOp);
DBUG_RETURN(-1);
}
- tOp->m_abortOption = NdbTransaction::AbortOnError;
+ tOp->m_abortOption = NdbOperation::AbortOnError;
n++;
thePendingBlobOps |= (1 << NdbOperation::DeleteRequest);
theNdbCon->thePendingBlobOps |= (1 << NdbOperation::DeleteRequest);
@@ -999,7 +1254,7 @@ NdbBlob::deletePartsUnknown(Uint32 part)
setErrorCode(tOp);
DBUG_RETURN(-1);
}
- tOp->m_abortOption= NdbTransaction::AO_IgnoreError;
+ tOp->m_abortOption= NdbOperation::AO_IgnoreError;
n++;
}
DBUG_PRINT("info", ("bat=%u", bat));
@@ -1091,68 +1346,40 @@ NdbBlob::atPrepare(NdbTransaction* aCon,
theTable = anOp->m_currentTable;
theAccessTable = anOp->m_accessTable;
theColumn = aColumn;
- NdbDictionary::Column::Type partType = NdbDictionary::Column::Undefined;
- switch (theColumn->getType()) {
- case NdbDictionary::Column::Blob:
- partType = NdbDictionary::Column::Binary;
- theFillChar = 0x0;
- break;
- case NdbDictionary::Column::Text:
- partType = NdbDictionary::Column::Char;
- theFillChar = 0x20;
- break;
- default:
- setErrorCode(NdbBlobImpl::ErrUsage);
+ // prepare blob column and table
+ if (prepareColumn() == -1)
DBUG_RETURN(-1);
- }
- // sizes
- theInlineSize = theColumn->getInlineSize();
- thePartSize = theColumn->getPartSize();
- theStripeSize = theColumn->getStripeSize();
- // sanity check
- assert((NDB_BLOB_HEAD_SIZE << 2) == sizeof(Head));
- assert(theColumn->m_attrSize * theColumn->m_arraySize == sizeof(Head) + theInlineSize);
- if (thePartSize > 0) {
- const NdbDictionary::Table* bt = NULL;
- const NdbDictionary::Column* bc = NULL;
- if (theStripeSize == 0 ||
- (bt = theColumn->getBlobTable()) == NULL ||
- (bc = bt->getColumn("DATA")) == NULL ||
- bc->getType() != partType ||
- bc->getLength() != (int)thePartSize) {
- setErrorCode(NdbBlobImpl::ErrTable);
- DBUG_RETURN(-1);
- }
- theBlobTable = &NdbTableImpl::getImpl(*bt);
- }
- // buffers
- theKeyBuf.alloc(theTable->m_keyLenInWords << 2);
+ // extra buffers
theAccessKeyBuf.alloc(theAccessTable->m_keyLenInWords << 2);
- theHeadInlineBuf.alloc(sizeof(Head) + theInlineSize);
theHeadInlineCopyBuf.alloc(sizeof(Head) + theInlineSize);
- thePartBuf.alloc(thePartSize);
- theHead = (Head*)theHeadInlineBuf.data;
- theInlineData = theHeadInlineBuf.data + sizeof(Head);
// handle different operation types
bool supportedOp = false;
if (isKeyOp()) {
if (isTableOp()) {
// get table key
- Uint32* data = (Uint32*)theKeyBuf.data;
- unsigned size = theTable->m_keyLenInWords;
+ Uint32* data = (Uint32*)thePackKeyBuf.data;
+ Uint32 size = theTable->m_keyLenInWords; // in-out
if (theNdbOp->getKeyFromTCREQ(data, size) == -1) {
setErrorCode(NdbBlobImpl::ErrUsage);
DBUG_RETURN(-1);
}
+ thePackKeyBuf.size = 4 * size;
+ thePackKeyBuf.zerorest();
+ if (unpackKeyValue(theTable, theKeyBuf) == -1)
+ DBUG_RETURN(-1);
}
if (isIndexOp()) {
// get index key
- Uint32* data = (Uint32*)theAccessKeyBuf.data;
- unsigned size = theAccessTable->m_keyLenInWords;
+ Uint32* data = (Uint32*)thePackKeyBuf.data;
+ Uint32 size = theAccessTable->m_keyLenInWords; // in-out
if (theNdbOp->getKeyFromTCREQ(data, size) == -1) {
setErrorCode(NdbBlobImpl::ErrUsage);
DBUG_RETURN(-1);
}
+ thePackKeyBuf.size = 4 * size;
+ thePackKeyBuf.zerorest();
+ if (unpackKeyValue(theAccessTable, theAccessKeyBuf) == -1)
+ DBUG_RETURN(-1);
}
if (isReadOp()) {
// upgrade lock mode
@@ -1192,6 +1419,105 @@ NdbBlob::atPrepare(NdbTransaction* aCon,
DBUG_RETURN(0);
}
+int
+NdbBlob::atPrepare(NdbEventOperationImpl* anOp, NdbEventOperationImpl* aBlobOp, const NdbColumnImpl* aColumn, int version)
+{
+ DBUG_ENTER("NdbBlob::atPrepare [event]");
+ DBUG_PRINT("info", ("this=%p op=%p", this, anOp));
+ assert(theState == Idle);
+ assert(version == 0 || version == 1);
+ theEventBlobVersion = version;
+ // ndb api stuff
+ theNdb = anOp->m_ndb;
+ theEventOp = anOp;
+ theBlobEventOp = aBlobOp;
+ theTable = anOp->m_eventImpl->m_tableImpl;
+ theAccessTable = theTable;
+ theColumn = aColumn;
+ // prepare blob column and table
+ if (prepareColumn() == -1)
+ DBUG_RETURN(-1);
+ // tinyblob sanity
+ assert((theBlobEventOp == NULL) == (theBlobTable == NULL));
+ // extra buffers
+ theBlobEventDataBuf.alloc(thePartSize);
+ // prepare receive of head+inline
+ theHeadInlineRecAttr = theEventOp->getValue(aColumn, theHeadInlineBuf.data, version);
+ if (theHeadInlineRecAttr == NULL) {
+ setErrorCode(theEventOp);
+ DBUG_RETURN(-1);
+ }
+ // prepare receive of blob part
+ if (theBlobEventOp != NULL) {
+ if ((theBlobEventPkRecAttr =
+ theBlobEventOp->getValue(theBlobTable->getColumn((Uint32)0),
+ thePackKeyBuf.data, version)) == NULL ||
+ (theBlobEventDistRecAttr =
+ theBlobEventOp->getValue(theBlobTable->getColumn((Uint32)1),
+ (char*)0, version)) == NULL ||
+ (theBlobEventPartRecAttr =
+ theBlobEventOp->getValue(theBlobTable->getColumn((Uint32)2),
+ (char*)&thePartNumber, version)) == NULL ||
+ (theBlobEventDataRecAttr =
+ theBlobEventOp->getValue(theBlobTable->getColumn((Uint32)3),
+ theBlobEventDataBuf.data, version)) == NULL) {
+ setErrorCode(theBlobEventOp);
+ DBUG_RETURN(-1);
+ }
+ }
+ setState(Prepared);
+ DBUG_RETURN(0);
+}
+
+int
+NdbBlob::prepareColumn()
+{
+ DBUG_ENTER("prepareColumn");
+ NdbDictionary::Column::Type partType = NdbDictionary::Column::Undefined;
+ switch (theColumn->getType()) {
+ case NdbDictionary::Column::Blob:
+ partType = NdbDictionary::Column::Binary;
+ theFillChar = 0x0;
+ break;
+ case NdbDictionary::Column::Text:
+ partType = NdbDictionary::Column::Char;
+ theFillChar = 0x20;
+ break;
+ default:
+ setErrorCode(NdbBlobImpl::ErrUsage);
+ DBUG_RETURN(-1);
+ }
+ // sizes
+ theInlineSize = theColumn->getInlineSize();
+ thePartSize = theColumn->getPartSize();
+ theStripeSize = theColumn->getStripeSize();
+ // sanity check
+ assert((NDB_BLOB_HEAD_SIZE << 2) == sizeof(Head));
+ assert(theColumn->m_attrSize * theColumn->m_arraySize == sizeof(Head) + theInlineSize);
+ if (thePartSize > 0) {
+ const NdbTableImpl* bt = NULL;
+ const NdbColumnImpl* bc = NULL;
+ if (theStripeSize == 0 ||
+ (bt = theColumn->m_blobTable) == NULL ||
+ (bc = bt->getColumn("DATA")) == NULL ||
+ bc->getType() != partType ||
+ bc->getLength() != (int)thePartSize) {
+ setErrorCode(NdbBlobImpl::ErrTable);
+ DBUG_RETURN(-1);
+ }
+ // blob table
+ theBlobTable = &NdbTableImpl::getImpl(*bt);
+ }
+ // these buffers are always used
+ theKeyBuf.alloc(theTable->m_keyLenInWords << 2);
+ thePackKeyBuf.alloc(max(theTable->m_keyLenInWords, theAccessTable->m_keyLenInWords) << 2);
+ theHeadInlineBuf.alloc(sizeof(Head) + theInlineSize);
+ theHead = (Head*)theHeadInlineBuf.data;
+ theInlineData = theHeadInlineBuf.data + sizeof(Head);
+ thePartBuf.alloc(thePartSize);
+ DBUG_RETURN(0);
+}
+
/*
* Before execute of prepared operation. May add new operations before
* this one. May ask that this operation and all before it (a "batch")
@@ -1264,7 +1590,7 @@ NdbBlob::preExecute(NdbTransaction::Exec
DBUG_RETURN(-1);
}
if (isWriteOp()) {
- tOp->m_abortOption = NdbTransaction::AO_IgnoreError;
+ tOp->m_abortOption = NdbOperation::AO_IgnoreError;
}
theHeadInlineReadOp = tOp;
// execute immediately
@@ -1283,7 +1609,7 @@ NdbBlob::preExecute(NdbTransaction::Exec
if (tOp == NULL ||
tOp->readTuple() == -1 ||
setAccessKeyValue(tOp) == -1 ||
- tOp->getValue(pkAttrId, theKeyBuf.data) == NULL) {
+ tOp->getValue(pkAttrId, thePackKeyBuf.data) == NULL) {
setErrorCode(tOp);
DBUG_RETURN(-1);
}
@@ -1310,7 +1636,7 @@ NdbBlob::preExecute(NdbTransaction::Exec
DBUG_RETURN(-1);
}
if (isWriteOp()) {
- tOp->m_abortOption = NdbTransaction::AO_IgnoreError;
+ tOp->m_abortOption = NdbOperation::AO_IgnoreError;
}
theHeadInlineReadOp = tOp;
// execute immediately
@@ -1372,10 +1698,13 @@ NdbBlob::postExecute(NdbTransaction::Exe
assert(isKeyOp());
if (isIndexOp()) {
NdbBlob* tFirstBlob = theNdbOp->theBlobList;
- if (this != tFirstBlob) {
+ if (this == tFirstBlob) {
+ packKeyValue(theTable, theKeyBuf);
+ } else {
// copy key from first blob
- assert(theKeyBuf.size == tFirstBlob->theKeyBuf.size);
- memcpy(theKeyBuf.data, tFirstBlob->theKeyBuf.data, tFirstBlob->theKeyBuf.size);
+ theKeyBuf.copyfrom(tFirstBlob->theKeyBuf);
+ thePackKeyBuf.copyfrom(tFirstBlob->thePackKeyBuf);
+ thePackKeyBuf.zerorest();
}
}
if (isReadOp()) {
@@ -1480,7 +1809,7 @@ NdbBlob::postExecute(NdbTransaction::Exe
setErrorCode(NdbBlobImpl::ErrAbort);
DBUG_RETURN(-1);
}
- tOp->m_abortOption = NdbTransaction::AbortOnError;
+ tOp->m_abortOption = NdbOperation::AbortOnError;
DBUG_PRINT("info", ("added op to update head+inline"));
}
DBUG_RETURN(0);
@@ -1510,7 +1839,7 @@ NdbBlob::preCommit()
setErrorCode(NdbBlobImpl::ErrAbort);
DBUG_RETURN(-1);
}
- tOp->m_abortOption = NdbTransaction::AbortOnError;
+ tOp->m_abortOption = NdbOperation::AbortOnError;
DBUG_PRINT("info", ("added op to update head+inline"));
}
}
@@ -1529,12 +1858,17 @@ NdbBlob::atNextResult()
DBUG_RETURN(-1);
assert(isScanOp());
// get primary key
- { Uint32* data = (Uint32*)theKeyBuf.data;
- unsigned size = theTable->m_keyLenInWords;
- if (((NdbScanOperation*)theNdbOp)->getKeyFromKEYINFO20(data, size) == -1) {
+ { NdbScanOperation* tScanOp = (NdbScanOperation*)theNdbOp;
+ Uint32* data = (Uint32*)thePackKeyBuf.data;
+ unsigned size = theTable->m_keyLenInWords; // in-out
+ if (tScanOp->getKeyFromKEYINFO20(data, size) == -1) {
setErrorCode(NdbBlobImpl::ErrUsage);
DBUG_RETURN(-1);
}
+ thePackKeyBuf.size = 4 * size;
+ thePackKeyBuf.zerorest();
+ if (unpackKeyValue(theTable, theKeyBuf) == -1)
+ DBUG_RETURN(-1);
}
getHeadFromRecAttr();
if (setPos(0) == -1)
@@ -1554,6 +1888,30 @@ NdbBlob::atNextResult()
DBUG_RETURN(0);
}
+/*
+ * After next event on main table.
+ */
+int
+NdbBlob::atNextEvent()
+{
+ DBUG_ENTER("NdbBlob::atNextEvent");
+ Uint32 optype =
+ SubTableData::getOperation(theEventOp->m_data_item->sdata->requestInfo);
+ DBUG_PRINT("info", ("this=%p op=%p blob op=%p version=%d optype=%u", this, theEventOp, theBlobEventOp, theEventBlobVersion, optype));
+ if (theState == Invalid)
+ DBUG_RETURN(-1);
+ assert(theEventBlobVersion >= 0);
+ if (optype >= NdbDictionary::Event::_TE_FIRST_NON_DATA_EVENT)
+ DBUG_RETURN(0);
+ getHeadFromRecAttr();
+ if (theNullFlag == -1) // value not defined
+ DBUG_RETURN(0);
+ if (setPos(0) == -1)
+ DBUG_RETURN(-1);
+ setState(Active);
+ DBUG_RETURN(0);
+}
+
// misc
const NdbDictionary::Column*
@@ -1600,6 +1958,17 @@ NdbBlob::setErrorCode(NdbTransaction* aC
if (theNdbCon != NULL && (code = theNdbCon->theError.code) != 0)
;
else if ((code = theNdb->theError.code) != 0)
+ ;
+ else
+ code = NdbBlobImpl::ErrUnknown;
+ setErrorCode(code, invalidFlag);
+}
+
+void
+NdbBlob::setErrorCode(NdbEventOperationImpl* anOp, bool invalidFlag)
+{
+ int code = 0;
+ if ((code = anOp->m_error.code) != 0)
;
else
code = NdbBlobImpl::ErrUnknown;
| Thread |
|---|
| • bk commit into 5.1 tree (knielsen:1.2482) | knielsen | 12 Mar |