head 1.16; access; symbols Version_2_1:1.8; locks; strict; comment @ * @; 1.16 date 91.11.18.22.21.22; author mer; state Exp; branches; next 1.15; 1.15 date 91.06.18.15.41.41; author sp; state Exp; branches; next 1.14; 1.14 date 91.05.09.18.10.57; author sp; state Exp; branches; next 1.13; 1.13 date 91.04.23.12.25.41; author sp; state Exp; branches; next 1.12; 1.12 date 91.04.11.21.32.45; author sp; state Exp; branches; next 1.11; 1.11 date 91.04.10.16.10.22; author sp; state Exp; branches; next 1.10; 1.10 date 91.04.08.18.15.38; author sp; state Exp; branches; next 1.9; 1.9 date 91.03.18.12.32.29; author sp; state Exp; branches; next 1.8; 1.8 date 91.02.24.20.00.48; author sp; state Exp; branches; next 1.7; 1.7 date 91.01.17.19.07.50; author sp; state Exp; branches; next 1.6; 1.6 date 90.10.26.23.34.04; author kemnitz; state Exp; branches; next 1.5; 1.5 date 90.10.16.17.20.53; author sp; state Exp; branches; next 1.4; 1.4 date 90.09.25.17.04.38; author kemnitz; state Exp; branches; next 1.3; 1.3 date 90.04.03.17.16.48; author sp; state Exp; branches; next 1.2; 1.2 date 90.03.07.17.22.57; author sp; state Exp; branches; next 1.1; 1.1 date 90.01.11.14.44.11; author sp; state Exp; branches; next ; desc @takes care of 'on replace' rule execution. @ 1.16 log @prototypes finale @ text @/*=================================================================== * * FILE: * prs2replace.c * * IDENTIFICATION: * $Header: /users/mer/postgres/src/rules/prs2/RCS/prs2replace.c,v 1.15 1991/06/18 15:41:41 sp Exp mer $ * * DESCRIPTION: * * *=================================================================== */ #include "tmp/c.h" #include "utils/log.h" #include "rules/prs2.h" #include "rules/prs2stub.h" #include "nodes/execnodes.h" /* which includes access/rulescan.h */ #include "parser/parse.h" /* for the APPEND/DELETE */ /*------------------------------------------------------------------- * * prs2Replace */ Prs2Status prs2Replace(prs2EStateInfo, relationRuleInfo, explainRelation, oldTuple, oldBuffer, newTuple, newBuffer, rawTuple, rawBuffer, attributeArray, numberOfAttributes, relation, returnedTupleP, returnedBufferP) Prs2EStateInfo prs2EStateInfo; RelationRuleInfo relationRuleInfo; Relation explainRelation; HeapTuple oldTuple; Buffer oldBuffer; HeapTuple newTuple; Buffer newBuffer; HeapTuple rawTuple; Buffer rawBuffer; AttributeNumberPtr attributeArray; int numberOfAttributes; Relation relation; HeapTuple *returnedTupleP; Buffer *returnedBufferP; { RuleLock oldLocks, oldTupleLocks, explocks; RuleLock newLocks; RuleLock relLocks; RuleLock finalLocks; Prs2Stub stubs; Prs2OneLock oneLock; int i,j; AttributeValues oldAttrValues, newAttrValues, rawAttrValues; AttributeNumber attr, maxattrs, attrno; int newTupleMade; Name relName; bool insteadRuleFound; bool insteadRuleFoundThisTime; TupleDescriptor tupDesc; /* * Find the locks of the tuple. * * To find the locks of the RAW(old) tuple, we have to check both * for relation level locks and for tuple level locks. * * NOTE: 'old' tuple has no lock on it, because locks * are not propagated from node to node inside the executor. * * NOTE: 'on replace' rules have either a relation level * lock, or a tuple-level-lock on the old tuple. * * The rule stubs need only be checked at the end, and only * to find out what locks the "new" tuple should get. * */ relName = & ((RelationGetRelationTupleForm(relation))->relname); tupDesc = RelationGetTupleDescriptor(relation); relLocks = relationRuleInfo->relationLocks; stubs = relationRuleInfo->relationStubs; if (relationRuleInfo->ignoreTupleLocks) oldTupleLocks = prs2MakeLocks(); else oldTupleLocks = prs2GetLocksFromTuple(rawTuple, rawBuffer); oldLocks = prs2LockUnion(oldTupleLocks, relLocks); /* * now extract from the tuple the array of the attribute values. */ newAttrValues = attributeValuesCreate(newTuple, newBuffer, relation); oldAttrValues = attributeValuesCreate(oldTuple, oldBuffer, relation); rawAttrValues = attributeValuesCreate(rawTuple, rawBuffer, relation); /* * First activate all the 'late evaluation' rules, i.e. * all the rules that try to update the fields of the 'new' tuple * * NOTE: WE use as locks of the new tuple the locks of the old * tuple! But in reality we are only interested in the * 'LockTypeReplaceWrite' locks... */ maxattrs = RelationGetNumberOfAttributes(relation); for(attr=1; attr <= maxattrs; attr++) { prs2ActivateBackwardChainingRules( prs2EStateInfo, explainRelation, relation, attr, PRS2_NEW_TUPLE, oldTuple->t_oid, oldAttrValues, oldLocks, LockTypeRetrieveWrite, newTuple->t_oid, newAttrValues, oldLocks, LockTypeReplaceWrite, attributeArray, numberOfAttributes); } /* * Then, activate all the 'forward chaining rules' * NOTE: Both old & new locks have the same "LockTypeReplaceAction" * locks */ insteadRuleFound = false; for(i=0; it_oid, oldAttrValues, oldLocks, LockTypeRetrieveWrite, newTuple->t_oid, newAttrValues, InvalidRuleLock, LockTypeInvalid, &insteadRuleFoundThisTime, attributeArray, numberOfAttributes); if (insteadRuleFoundThisTime) { insteadRuleFound = true; } } /* * Look also for 'on replace' rules with * an 'InvalidAttributeNumber' locked attrno. * (I.e. rules like: 'on replace to EMP where... do...' */ prs2ActivateForwardChainingRules( prs2EStateInfo, explainRelation, relation, InvalidAttributeNumber, LockTypeReplaceAction, PRS2_OLD_TUPLE, oldTuple->t_oid, oldAttrValues, oldLocks, LockTypeRetrieveWrite, newTuple->t_oid, newAttrValues, InvalidRuleLock, LockTypeInvalid, &insteadRuleFoundThisTime, attributeArray, numberOfAttributes); if (insteadRuleFoundThisTime) { insteadRuleFound = true; } /* * Now all the correct values * Create a new tuple combining the 'raw' tuple, i.e. the * tuple without any rules activated and the 'new' tuple. */ *returnedBufferP = InvalidBuffer; *returnedTupleP = attributeValuesCombineNewAndOldTuple( rawAttrValues, newAttrValues, relation, attributeArray, numberOfAttributes); /* * OK, now find out the rule locks that the new tuple * must get. * NOTE: these locks will NOT include "export" locks * yet. These, will be calculated in a while... */ newLocks = prs2FindLocksForNewTupleFromStubs( *returnedTupleP, *returnedBufferP, stubs, relation); /* * are there any export locks "broken" ??? * That includes * a) new export locks that didn't exist before * b) removal of old export locks * c) value of an attribute locked by an export lock has changed. */ explocks = prs2FindNewExportLocksFromLocks(newLocks); for (i=0; idata[attrno-1]->atttypid, APPEND); } } for (i=0; idata[attrno-1]->atttypid, DELETE); } } for (i=0; idata[attrno-1]->atttypid, DELETE); if (!newAttrValues[attrno-1].isNull) prs2ActivateExportLockRulePlan(oneLock, newAttrValues[attrno-1].value, tupDesc->data[attrno-1]->atttypid, APPEND); } } } /* * Calculate the new locks for this tuple. * This is the union of 'newLocks' and the 'explocks' * * NOTE: THING TO DO: * REMOVE ALL IMPORT LOCKS (same thing in prs2append.c) * THEY DON"T BREAK ANYTHING BUT THEY CHEW UP SPACE... */ finalLocks = prs2LockUnion(newLocks, explocks); HeapTupleSetRuleLock(*returnedTupleP, InvalidBuffer, finalLocks); /* * clean up, sweep the floor and do the laundry.... */ prs2FreeLocks(oldLocks); prs2FreeLocks(oldTupleLocks); attributeValuesFree(newAttrValues, relation); attributeValuesFree(oldAttrValues, relation); prs2FreeLocks(newLocks); prs2FreeLocks(explocks); if (insteadRuleFound) { return(PRS2_STATUS_INSTEAD); } else { return(PRS2_STATUS_TUPLE_CHANGED); } } @ 1.15 log @various small bug fixes... @ text @d7 1 a7 1 * $Header: RCS/prs2replace.c,v 1.14 91/05/09 18:10:57 sp Exp $ d86 1 a86 2 oldTupleLocks = prs2GetLocksFromTuple(rawTuple, rawBuffer, RelationGetTupleDescriptor(relation)); @ 1.14 log @Ignore the tuple locks if 'RelationRuleInfo->ignoreTupleLocks' is true (which happens if the relation currently being scanned is "pg_class"). @ text @d7 1 a7 1 * $Header: RCS/prs2replace.c,v 1.13 91/04/23 12:25:41 sp Exp Locker: sp $ d50 1 d197 2 a204 1 HeapTupleSetRuleLock(*returnedTupleP, InvalidBuffer, newLocks); d264 3 a266 1 oldAttrValues[attrno-1].value, DELETE); d276 10 d294 2 @ 1.13 log @the rule stubs are retrieved from the relationRuleInfo instead of looking in the sys cache. @ text @d7 1 a7 1 * $Header: RCS/prs2replace.c,v 1.12 91/04/11 21:32:45 sp Exp $ d82 4 a85 1 oldTupleLocks = prs2GetLocksFromTuple(rawTuple, rawBuffer, @ 1.12 log @we also pass the result RelationRuleInfo which contains the relation level lock, so we don't have to search the syscache to find them. @ text @d7 1 a7 1 * $Header: RCS/prs2replace.c,v 1.11 91/04/10 16:10:22 sp Exp Locker: sp $ d50 1 d81 1 d197 1 @ 1.11 log @minor bug fix... @ text @d7 1 a7 1 * $Header: RCS/prs2replace.c,v 1.10 91/04/08 18:15:38 sp Exp $ d18 2 d27 2 a28 1 prs2Replace(prs2EStateInfo, explainRelation, oldTuple, oldBuffer, d33 1 a59 2 d79 1 a79 1 relLocks = prs2GetLocksFromRelation(relName); a84 10 * XXX HACK! HACK! HACK! * * When `old' tuple was formed, we evaluated ALL backward * chaining rules defined on it. * So, get rid of the "write" locks of on retrieve-do retrieve * (otherwise, we might re-activate them unnecessarily) */ prs2RemoveLocksOfTypeInPlace(oldLocks, LockTypeRetrieveWrite); /* a270 1 prs2FreeLocks(relLocks); @ 1.10 log @misc changes to support locking more than one path in the rule qualification's tree... @ text @d7 1 a7 1 * $Header: RCS/prs2replace.c,v 1.9 91/03/18 12:32:29 sp Exp Locker: sp $ d215 1 a215 1 oneLock = prs2GetOneLockFromLocks(explocks); d230 1 a230 1 oneLock = prs2GetOneLockFromLocks(explocks); d246 1 a246 1 oneLock = prs2GetOneLockFromLocks(explocks); @ 1.9 log @Now we can also handle 'on replace to EMP where ... do ...' rules too.. @ text @d7 1 a7 1 * $Header: RCS/prs2replace.c,v 1.8 91/02/24 20:00:48 sp Exp Locker: sp $ d18 1 d43 1 a43 1 RuleLock oldLocks, oldTupleLocks; d46 2 a47 1 int i; d49 1 a49 1 AttributeNumber attr, maxattrs; d54 1 d57 1 d75 1 d90 1 a90 1 prs2RemoveLocksOfTypeInPlace(oldLocks, LockTypeTupleRetrieveWrite); d105 1 a105 1 * 'LockTypeTupleReplaceWrite' locks... d118 1 a118 1 LockTypeTupleRetrieveWrite, d122 1 a122 1 LockTypeTupleReplaceWrite, d129 1 a129 1 * NOTE: Both old & new locks have the same "LockTypeTupleReplaceAction" d139 1 a139 1 LockTypeTupleReplaceAction, d144 1 a144 1 LockTypeTupleRetrieveWrite, d166 1 a166 1 LockTypeTupleReplaceAction, d171 1 a171 1 LockTypeTupleRetrieveWrite, d206 69 @ 1.8 log @We take care of rule stubs + we must also check the tuple level locks... @ text @d7 1 a7 1 * $Header: RCS/prs2replace.c,v 1.7 91/01/17 19:07:50 sp Exp $ d150 26 @ 1.7 log @We now support both relation & tuple level locks. @ text @d7 1 a7 1 * $Header: RCS/prs2replace.c,v 1.6 90/10/26 23:34:04 kemnitz Exp Locker: sp $ d43 1 a43 1 RuleLock newLocks, newTupleLocks; d57 1 a57 1 * To find the locks of the old tuple, we have to check both d59 3 d63 6 a68 3 * For the "new" tuple, we have to check the relation level locks * and the locks from the rule stubs which are put in the tuple * itself by the executor. d73 1 a73 1 newTupleLocks = prs2GetLocksFromTuple(newTuple, newBuffer, a74 2 oldTupleLocks = prs2GetLocksFromTuple(oldTuple, oldBuffer, RelationGetTupleDescriptor(relation)); a75 1 newLocks = prs2LockUnion(newTupleLocks, relLocks); d78 10 d97 4 d102 1 a102 1 maxattrs = RelationGetNumberOfAttributes(relation); d116 1 a116 1 newLocks, d142 2 a143 2 newLocks, LockTypeTupleRetrieveWrite, a163 1 HeapTupleSetRuleLock(*returnedTupleP, InvalidBuffer, newTupleLocks); d165 13 a177 1 prs2FreeLocks(newLocks); d179 2 @ 1.6 log @A small speed improvement - took RelationGetNumberOfAttributes(relation) out of for loop - it was being called for every iterate. @ text @d7 1 a7 1 * $Header: RCS/prs2replace.c,v 1.5 90/10/16 17:20:53 sp Exp Locker: kemnitz $ d42 3 a44 1 RuleLock oldLocks, newLocks; d57 6 a62 6 * XXX: * The "old" tuple's lock are stored in the tuple (that * happenned at a lower level of the plan, when prs2Retrieve * was called as part of the scan operation. * To find the locks of the "new" tuple we have to look at * the RelationRelation. d65 3 a67 3 newLocks = prs2GetLocksFromRelation(relName); #ifdef NO oldLocks = prs2GetLocksFromTuple(oldTuple, oldBuffer, d69 4 a72 9 #else /* * XXX * in the current implementation, "oldTuple" is the same as * "rawTuple", i.e. as all locks are currently "relation level" * locks, no locks are actually stored in the tuple! */ oldLocks = prs2CopyLocks(newLocks); #endif d147 1 @ 1.5 log @attributeValuesFree now takes an extra argument + locks are never in tuples, always go to pg_relation to get them. @ text @d7 1 a7 1 * $Header: RCS/prs2replace.c,v 1.4 90/09/25 17:04:38 kemnitz Exp Locker: sp $ d45 1 a45 1 AttributeNumber attr; d88 2 a89 1 for(attr=1; attr <= RelationGetNumberOfAttributes(relation); attr++) { @ 1.4 log @Updating from revision 1.3 to revision 1.5 @ text @d7 1 a7 1 * $Header: RCS/prs2replace.c,v 1.5 90/08/13 20:30:04 sp Exp $ d64 1 d67 9 d152 2 a153 2 attributeValuesFree(newAttrValues); attributeValuesFree(oldAttrValues); @ 1.3 log @Now it works! @ text @d7 1 a7 1 * $Header: RCS/prs2replace.c,v 1.2 90/03/07 17:22:57 sp Exp $ d15 3 a17 3 #include "c.h" #include "log.h" #include "prs2.h" d88 1 a88 1 LockTypeRetrieveWrite, d92 1 a92 1 LockTypeReplaceWrite, d99 1 a99 1 * NOTE: Both old & new locks have the same "LockTypeReplaceAction" d109 1 a109 1 LockTypeReplaceAction, d114 1 a114 1 LockTypeRetrieveWrite, d118 1 a118 1 LockTypeRetrieveWrite, @ 1.2 log @'prs2Replace' is a dummy routine returning always PRS2_STATUS_TUPLE_UNCHANGED @ text @d7 1 a7 1 * $Header: RCS/prs2replace.c,v 1.1 90/01/11 14:44:11 sp Exp Locker: sp $ d24 2 a25 1 prs2Replace(prs2EStateInfo, oldTuple, oldBuffer, newTuple, newBuffer, d29 1 d34 2 a41 24 return(PRS2_STATUS_TUPLE_UNCHANGED); } #ifdef NOT_YET /*------------------------------------------------------------------- * * prs2Replace */ Prs2Status prs2Replace(prs2EStateInfo, oldTuple, oldBuffer, newTuple, newBuffer, attributeArray, numberOfAttributes, relation, returnedTupleP, returnedBufferP) Prs2EStateInfo prs2EStateInfo; HeapTuple oldTuple; Buffer oldBuffer; HeapTuple newTuple; Buffer newBuffer; AttributeNumberPtr attributeArray; int numberOfAttributes; Relation relation; HeapTuple *returnedTupleP; Buffer *returnedBufferP; { d44 2 a45 1 AttributeValues oldAttrValues, newAttrValues; d72 1 d78 1 a78 1 for(i=0; it_oid, oldAttrValues, oldLocks, LockTypeRetrieveWrite); d106 1 d119 3 a121 2 LockTypeInvalid, &insteadRuleFoundThisTime); d129 2 a130 1 * Create a new tuple with the correct values. d132 7 a138 4 newTupleMade = attributeValuesMakeNewTuple( newTuple, newBuffer, newAttrValues, newLocks, LockTypeInvalid, relation, returnedTupleP); d147 2 a150 6 if (newTupleMade) { *returnedBufferP = InvalidBuffer; return(PRS2_STATUS_TUPLE_CHANGED); } else { return(PRS2_STATUS_TUPLE_UNCHANGED); } a151 1 #endif NOT_YET @ 1.1 log @Initial revision @ text @d7 1 a7 1 * $Header: RCS/prs2replace.c,v 1.1 90/01/10 14:56:27 sp Exp Locker: sp $ d19 21 d41 2 d48 13 a60 1 prs2Replace() d62 102 d165 1 @