📄 dbtuptrigger.cpp
字号:
/* Copyright (C) 2003 MySQL AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#define DBTUP_C#include "Dbtup.hpp"#include <RefConvert.hpp>#include <ndb_limits.h>#include <pc.hpp>#include <AttributeDescriptor.hpp>#include "AttributeOffset.hpp"#include <AttributeHeader.hpp>#include <signaldata/FireTrigOrd.hpp>#include <signaldata/CreateTrig.hpp>#include <signaldata/TuxMaint.hpp>#define ljam() { jamLine(7000 + __LINE__); }#define ljamEntry() { jamEntryLine(7000 + __LINE__); }/* **************************************************************** *//* ---------------------------------------------------------------- *//* ----------------------- TRIGGER HANDLING ----------------------- *//* ---------------------------------------------------------------- *//* **************************************************************** */ArrayList<Dbtup::TupTriggerData>*Dbtup::findTriggerList(Tablerec* table, TriggerType::Value ttype, TriggerActionTime::Value ttime, TriggerEvent::Value tevent){ ArrayList<TupTriggerData>* tlist = NULL; switch (ttype) { case TriggerType::SUBSCRIPTION: case TriggerType::SUBSCRIPTION_BEFORE: switch (tevent) { case TriggerEvent::TE_INSERT: ljam(); if (ttime == TriggerActionTime::TA_DETACHED) tlist = &table->subscriptionInsertTriggers; break; case TriggerEvent::TE_UPDATE: ljam(); if (ttime == TriggerActionTime::TA_DETACHED) tlist = &table->subscriptionUpdateTriggers; break; case TriggerEvent::TE_DELETE: ljam(); if (ttime == TriggerActionTime::TA_DETACHED) tlist = &table->subscriptionDeleteTriggers; break; default: break; } break; case TriggerType::SECONDARY_INDEX: switch (tevent) { case TriggerEvent::TE_INSERT: ljam(); if (ttime == TriggerActionTime::TA_AFTER) tlist = &table->afterInsertTriggers; break; case TriggerEvent::TE_UPDATE: ljam(); if (ttime == TriggerActionTime::TA_AFTER) tlist = &table->afterUpdateTriggers; break; case TriggerEvent::TE_DELETE: ljam(); if (ttime == TriggerActionTime::TA_AFTER) tlist = &table->afterDeleteTriggers; break; default: break; } break; case TriggerType::ORDERED_INDEX: switch (tevent) { case TriggerEvent::TE_CUSTOM: ljam(); if (ttime == TriggerActionTime::TA_CUSTOM) tlist = &table->tuxCustomTriggers; break; default: break; } break; case TriggerType::READ_ONLY_CONSTRAINT: switch (tevent) { case TriggerEvent::TE_UPDATE: ljam(); if (ttime == TriggerActionTime::TA_AFTER) tlist = &table->constraintUpdateTriggers; break; default: break; } break; default: break; } return tlist;}// Trigger signalsvoidDbtup::execCREATE_TRIG_REQ(Signal* signal){ ljamEntry(); BlockReference senderRef = signal->getSendersBlockRef(); const CreateTrigReq reqCopy = *(const CreateTrigReq*)signal->getDataPtr(); const CreateTrigReq* const req = &reqCopy; // Find table TablerecPtr tabPtr; tabPtr.i = req->getTableId(); ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec); // Create trigger and associate it with the table if (createTrigger(tabPtr.p, req)) { ljam(); // Send conf CreateTrigConf* const conf = (CreateTrigConf*)signal->getDataPtrSend(); conf->setUserRef(reference()); conf->setConnectionPtr(req->getConnectionPtr()); conf->setRequestType(req->getRequestType()); conf->setTableId(req->getTableId()); conf->setIndexId(req->getIndexId()); conf->setTriggerId(req->getTriggerId()); conf->setTriggerInfo(req->getTriggerInfo()); sendSignal(senderRef, GSN_CREATE_TRIG_CONF, signal, CreateTrigConf::SignalLength, JBB); } else { ljam(); // Send ref CreateTrigRef* const ref = (CreateTrigRef*)signal->getDataPtrSend(); ref->setUserRef(reference()); ref->setConnectionPtr(req->getConnectionPtr()); ref->setRequestType(req->getRequestType()); ref->setTableId(req->getTableId()); ref->setIndexId(req->getIndexId()); ref->setTriggerId(req->getTriggerId()); ref->setTriggerInfo(req->getTriggerInfo()); ref->setErrorCode(CreateTrigRef::TooManyTriggers); sendSignal(senderRef, GSN_CREATE_TRIG_REF, signal, CreateTrigRef::SignalLength, JBB); }}//Dbtup::execCREATE_TRIG_REQ()voidDbtup::execDROP_TRIG_REQ(Signal* signal){ ljamEntry(); BlockReference senderRef = signal->getSendersBlockRef(); const DropTrigReq reqCopy = *(const DropTrigReq*)signal->getDataPtr(); const DropTrigReq* const req = &reqCopy; // Find table TablerecPtr tabPtr; tabPtr.i = req->getTableId(); ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec); // Drop trigger Uint32 r = dropTrigger(tabPtr.p, req); if (r == 0){ // Send conf DropTrigConf* const conf = (DropTrigConf*)signal->getDataPtrSend(); conf->setUserRef(senderRef); conf->setConnectionPtr(req->getConnectionPtr()); conf->setRequestType(req->getRequestType()); conf->setTableId(req->getTableId()); conf->setIndexId(req->getIndexId()); conf->setTriggerId(req->getTriggerId()); sendSignal(senderRef, GSN_DROP_TRIG_CONF, signal, DropTrigConf::SignalLength, JBB); } else { // Send ref DropTrigRef* const ref = (DropTrigRef*)signal->getDataPtrSend(); ref->setUserRef(senderRef); ref->setConnectionPtr(req->getConnectionPtr()); ref->setRequestType(req->getRequestType()); ref->setTableId(req->getTableId()); ref->setIndexId(req->getIndexId()); ref->setTriggerId(req->getTriggerId()); ref->setErrorCode((DropTrigRef::ErrorCode)r); ref->setErrorLine(__LINE__); ref->setErrorNode(refToNode(reference())); sendSignal(senderRef, GSN_DROP_TRIG_REF, signal, DropTrigRef::SignalLength, JBB); }}//Dbtup::DROP_TRIG_REQ()/* ---------------------------------------------------------------- *//* ------------------------- createTrigger ------------------------ *//* *//* Creates a new trigger record by fetching one from the trigger *//* pool and associates it with the given table. *//* Trigger type can be one of secondary_index, subscription, *//* constraint(NYI), foreign_key(NYI), schema_upgrade(NYI), *//* api_trigger(NYI) or sql_trigger(NYI). */ /* Note that this method only checks for total number of allowed *//* triggers. Checking the number of allowed triggers per table is *//* done by TRIX. *//* *//* ---------------------------------------------------------------- */boolDbtup::createTrigger(Tablerec* table, const CreateTrigReq* req){ if (ERROR_INSERTED(4003)) { CLEAR_ERROR_INSERT_VALUE; return false; } TriggerType::Value ttype = req->getTriggerType(); TriggerActionTime::Value ttime = req->getTriggerActionTime(); TriggerEvent::Value tevent = req->getTriggerEvent(); ArrayList<TupTriggerData>* tlist = findTriggerList(table, ttype, ttime, tevent); ndbrequire(tlist != NULL); TriggerPtr tptr; if (!tlist->seize(tptr)) return false; // Set trigger id tptr.p->triggerId = req->getTriggerId(); // ndbout_c("Create TupTrigger %u = %u %u %u %u", tptr.p->triggerId, table, ttype, ttime, tevent); // Set index id tptr.p->indexId = req->getIndexId(); // Set trigger type etc tptr.p->triggerType = ttype; tptr.p->triggerActionTime = ttime; tptr.p->triggerEvent = tevent; tptr.p->sendBeforeValues = true; if ((tptr.p->triggerType == TriggerType::SUBSCRIPTION) && ((tptr.p->triggerEvent == TriggerEvent::TE_UPDATE) || (tptr.p->triggerEvent == TriggerEvent::TE_DELETE))) { ljam(); tptr.p->sendBeforeValues = false; } tptr.p->sendOnlyChangedAttributes = false; if (((tptr.p->triggerType == TriggerType::SUBSCRIPTION) || (tptr.p->triggerType == TriggerType::SUBSCRIPTION_BEFORE)) && (tptr.p->triggerEvent == TriggerEvent::TE_UPDATE)) { ljam(); tptr.p->sendOnlyChangedAttributes = true; } // Set monitor all tptr.p->monitorAllAttributes = req->getMonitorAllAttributes(); tptr.p->monitorReplicas = req->getMonitorReplicas(); tptr.p->m_receiverBlock = refToBlock(req->getReceiverRef()); tptr.p->attributeMask.clear(); if (tptr.p->monitorAllAttributes) { ljam(); for(Uint32 i = 0; i < table->noOfAttr; i++) { if (!primaryKey(table, i)) { ljam(); tptr.p->attributeMask.set(i); } } } else { // Set attribute mask ljam(); tptr.p->attributeMask = req->getAttributeMask(); } return true;}//Dbtup::createTrigger()boolDbtup::primaryKey(Tablerec* const regTabPtr, Uint32 attrId){ Uint32 attrDescriptorStart = regTabPtr->tabDescriptor; Uint32 attrDescriptor = getTabDescrWord(attrDescriptorStart + (attrId * ZAD_SIZE)); return (bool)AttributeDescriptor::getPrimaryKey(attrDescriptor);}//Dbtup::primaryKey()/* ---------------------------------------------------------------- *//* -------------------------- dropTrigger ------------------------- *//* *//* Deletes a trigger record by disassociating it with the given *//* table and returning it to the trigger pool. *//* Trigger type can be one of secondary_index, subscription, *//* constraint(NYI), foreign_key(NYI), schema_upgrade(NYI), *//* api_trigger(NYI) or sql_trigger(NYI). */ /* *//* ---------------------------------------------------------------- */Uint32Dbtup::dropTrigger(Tablerec* table, const DropTrigReq* req){ if (ERROR_INSERTED(4004)) { CLEAR_ERROR_INSERT_VALUE; return 9999; } Uint32 triggerId = req->getTriggerId(); TriggerType::Value ttype = req->getTriggerType(); TriggerActionTime::Value ttime = req->getTriggerActionTime(); TriggerEvent::Value tevent = req->getTriggerEvent(); // ndbout_c("Drop TupTrigger %u = %u %u %u %u", triggerId, table, ttype, ttime, tevent); ArrayList<TupTriggerData>* tlist = findTriggerList(table, ttype, ttime, tevent); ndbrequire(tlist != NULL); Ptr<TupTriggerData> ptr; for (tlist->first(ptr); !ptr.isNull(); tlist->next(ptr)) { ljam(); if (ptr.p->triggerId == triggerId) { ljam(); tlist->release(ptr.i); return 0; } } return DropTrigRef::TriggerNotFound;}//Dbtup::dropTrigger()/* ---------------------------------------------------------------- *//* -------------- checkImmediateTriggersAfterOp ------------------ *//* *//* Called after an insert, delete, or update operation takes *//* place. Fetches before tuple for deletes and updates and *//* after tuple for inserts and updates. *//* Executes immediate triggers by sending FIRETRIGORD *//* *//* ---------------------------------------------------------------- */void Dbtup::checkImmediateTriggersAfterInsert(Signal* signal, Operationrec* const regOperPtr, Tablerec* const regTablePtr){ if(refToBlock(regOperPtr->coordinatorTC) == DBLQH) { return; } if ((regOperPtr->primaryReplica) && (!(regTablePtr->afterInsertTriggers.isEmpty()))) { ljam(); fireImmediateTriggers(signal, regTablePtr->afterInsertTriggers, regOperPtr); }//if}//Dbtup::checkImmediateTriggersAfterInsert()void Dbtup::checkImmediateTriggersAfterUpdate(Signal* signal, Operationrec* const regOperPtr, Tablerec* const regTablePtr){ if(refToBlock(regOperPtr->coordinatorTC) == DBLQH) { return; } if ((regOperPtr->primaryReplica) && (!(regTablePtr->afterUpdateTriggers.isEmpty()))) { ljam(); fireImmediateTriggers(signal, regTablePtr->afterUpdateTriggers, regOperPtr); }//if if ((regOperPtr->primaryReplica) && (!(regTablePtr->constraintUpdateTriggers.isEmpty()))) { ljam(); fireImmediateTriggers(signal, regTablePtr->constraintUpdateTriggers, regOperPtr); }//if}//Dbtup::checkImmediateTriggersAfterUpdate()void Dbtup::checkImmediateTriggersAfterDelete(Signal* signal, Operationrec* const regOperPtr,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -