diff --git a/storage/ndb/src/kernel/blocks/ERROR_codes.txt b/storage/ndb/src/kernel/blocks/ERROR_codes.txt index 3c220912064..fc22118e113 100644 --- a/storage/ndb/src/kernel/blocks/ERROR_codes.txt +++ b/storage/ndb/src/kernel/blocks/ERROR_codes.txt @@ -2,7 +2,7 @@ Next QMGR 1 Next NDBCNTR 1000 Next NDBFS 2000 Next DBACC 3002 -Next DBTUP 4014 +Next DBTUP 4024 Next DBLQH 5043 Next DBDICT 6007 Next DBDIH 7177 @@ -486,3 +486,6 @@ Dbtup: 4019 - handleInsert - Alloc rowid error 4020 - handleInsert - Size change error 4021 - handleInsert - Out of disk space + +4022 - addTuxEntries - fail before add of first entry +4023 - addTuxEntries - fail add of last entry (the entry for last index) diff --git a/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp b/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp index 3396ca1332f..e19e43f6d47 100644 --- a/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp +++ b/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp @@ -254,6 +254,8 @@ inline const Uint32* ALIGN_WORD(const void* ptr) #define ZSTORED_PROCEDURE_FREE 0xffff #define ZMIN_PAGE_LIMIT_TUP_COMMITREQ 2 +#define ZSKIP_TUX_TRIGGERS 0x1 // flag for TUP_ABORTREQ + #endif class Dbtup: public SimulatedBlock { @@ -2155,6 +2157,7 @@ private: //------------------------------------------------------------------ //------------------------------------------------------------------ void tupkeyErrorLab(Signal* signal); + void do_tup_abortreq(Signal*, Uint32 flags); //------------------------------------------------------------------ //------------------------------------------------------------------ diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp index aa55985c1f2..16c51f7aa6e 100644 --- a/storage/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp +++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp @@ -62,12 +62,17 @@ void Dbtup::freeAttrinbufrec(Uint32 anAttrBuf) * Abort abort this operation and all after (nextActiveOp's) */ void Dbtup::execTUP_ABORTREQ(Signal* signal) +{ + ljamEntry(); + do_tup_abortreq(signal, 0); +} + +void Dbtup::do_tup_abortreq(Signal* signal, Uint32 flags) { OperationrecPtr regOperPtr; FragrecordPtr regFragPtr; TablerecPtr regTabPtr; - ljamEntry(); regOperPtr.i = signal->theData[0]; c_operation_pool.getPtr(regOperPtr); TransState trans_state= get_trans_state(regOperPtr.p); @@ -91,7 +96,8 @@ void Dbtup::execTUP_ABORTREQ(Signal* signal) if (get_tuple_state(regOperPtr.p) == TUPLE_PREPARED) { ljam(); - if (!regTabPtr.p->tuxCustomTriggers.isEmpty()) + if (!regTabPtr.p->tuxCustomTriggers.isEmpty() && + (flags & ZSKIP_TUX_TRIGGERS) == 0) executeTuxAbortTriggers(signal, regOperPtr.p, regFragPtr.p, @@ -103,7 +109,8 @@ void Dbtup::execTUP_ABORTREQ(Signal* signal) ljam(); c_operation_pool.getPtr(loopOpPtr); if (get_tuple_state(loopOpPtr.p) != TUPLE_ALREADY_ABORTED && - !regTabPtr.p->tuxCustomTriggers.isEmpty()) { + !regTabPtr.p->tuxCustomTriggers.isEmpty() && + (flags & ZSKIP_TUX_TRIGGERS) == 0) { ljam(); executeTuxAbortTriggers(signal, loopOpPtr.p, diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp index 3021799fd11..6cde3e51e5a 100644 --- a/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp +++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp @@ -747,6 +747,20 @@ void Dbtup::execTUPKEYREQ(Signal* signal) regFragPtr, regTabPtr) != 0) { jam(); + /* + * TUP insert succeeded but add of TUX entries failed. All + * TUX changes have been rolled back at this point. + * + * We will abort via tupkeyErrorLab() as usual. This routine + * however resets the operation to ZREAD. The TUP_ABORTREQ + * arriving later cannot then undo the insert. + * + * Therefore we call TUP_ABORTREQ already now. Diskdata etc + * should be in memory and timeslicing cannot occur. We must + * skip TUX abort triggers since TUX is already aborted. + */ + signal->theData[0] = operPtr.i; + do_tup_abortreq(signal, ZSKIP_TUX_TRIGGERS); tupkeyErrorLab(signal); return; } @@ -775,6 +789,11 @@ void Dbtup::execTUPKEYREQ(Signal* signal) regFragPtr, regTabPtr) != 0) { jam(); + /* + * See insert case. + */ + signal->theData[0] = operPtr.i; + do_tup_abortreq(signal, ZSKIP_TUX_TRIGGERS); tupkeyErrorLab(signal); return; } diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp index 62cd1f06157..0e1b251d8a5 100644 --- a/storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp +++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp @@ -1111,6 +1111,12 @@ Dbtup::addTuxEntries(Signal* signal, Operationrec* regOperPtr, Tablerec* regTabPtr) { + if (ERROR_INSERTED(4022)) { + ljam(); + CLEAR_ERROR_INSERT_VALUE; + terrorCode = 9999; + return -1; + } TuxMaintReq* const req = (TuxMaintReq*)signal->getDataPtrSend(); const DLList& triggerList = regTabPtr->tuxCustomTriggers; TriggerPtr triggerPtr; @@ -1120,6 +1126,14 @@ Dbtup::addTuxEntries(Signal* signal, ljam(); req->indexId = triggerPtr.p->indexId; req->errorCode = RNIL; + if (ERROR_INSERTED(4023) && + ! triggerList.hasNext(triggerPtr)) { + ljam(); + CLEAR_ERROR_INSERT_VALUE; + terrorCode = 9999; + failPtrI = triggerPtr.i; + goto fail; + } EXECUTE_DIRECT(DBTUX, GSN_TUX_MAINT_REQ, signal, TuxMaintReq::SignalLength); ljamEntry();