diff options
author | Vadim B. Mikheev <vadim4o@yahoo.com> | 1998-12-15 12:47:01 +0000 |
---|---|---|
committer | Vadim B. Mikheev <vadim4o@yahoo.com> | 1998-12-15 12:47:01 +0000 |
commit | 3f7fbf85dc5b42dfd33c803efe6c90533773576a (patch) | |
tree | df8f84075ae7a27fa6b7ec0d063a03898e0b1bbb /src/backend/executor | |
parent | c5a27161a188b235ce3c0afb1b12e8942ac8e963 (diff) | |
download | postgresql-3f7fbf85dc5b42dfd33c803efe6c90533773576a.tar.gz |
Initial MVCC code.
New code for locking buffer' context.
Diffstat (limited to 'src/backend/executor')
-rw-r--r-- | src/backend/executor/execMain.c | 97 | ||||
-rw-r--r-- | src/backend/executor/execUtils.c | 31 | ||||
-rw-r--r-- | src/backend/executor/nodeHash.c | 10 |
3 files changed, 92 insertions, 46 deletions
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 45be159ae1..712f228534 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -26,7 +26,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.59 1998/11/27 19:51:59 vadim Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.60 1998/12/15 12:46:04 vadim Exp $ * *------------------------------------------------------------------------- */ @@ -51,6 +51,7 @@ /* #include "access/localam.h" */ #include "optimizer/var.h" #include "access/heapam.h" +#include "access/xact.h" #include "catalog/heap.h" #include "commands/trigger.h" @@ -421,7 +422,6 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate) { /****************** * if we have a result relation, open it and - * initialize the result relation info stuff. ****************** */ @@ -440,14 +440,7 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate) elog(ERROR, "You can't change sequence relation %s", resultRelationDesc->rd_rel->relname.data); - /* - * Write-lock the result relation right away: if the relation is - * used in a subsequent scan, we won't have to elevate the - * read-lock set by heap_beginscan to a write-lock (needed by - * heap_insert, heap_delete and heap_replace). This will hopefully - * prevent some deadlocks. - 01/24/94 - */ - RelationSetLockForWrite(resultRelationDesc); + LockRelation(resultRelationDesc, RowExclusiveLock); resultRelationInfo = makeNode(RelationInfo); resultRelationInfo->ri_RangeTableIndex = resultRelationIndex; @@ -461,7 +454,8 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate) * in the result relation information.. ****************** */ - ExecOpenIndices(resultRelationOid, resultRelationInfo); + if (operation != CMD_DELETE) + ExecOpenIndices(resultRelationOid, resultRelationInfo); estate->es_result_relation_info = resultRelationInfo; } @@ -1006,8 +1000,10 @@ ExecDelete(TupleTableSlot *slot, ItemPointer tupleid, EState *estate) { - RelationInfo *resultRelationInfo; - Relation resultRelationDesc; + RelationInfo *resultRelationInfo; + Relation resultRelationDesc; + ItemPointerData ctid; + int result; /****************** * get the result relation information @@ -1022,19 +1018,35 @@ ExecDelete(TupleTableSlot *slot, { bool dodelete; - dodelete = ExecBRDeleteTriggers(resultRelationDesc, tupleid); + dodelete = ExecBRDeleteTriggers(estate, tupleid); if (!dodelete) /* "do nothing" */ return; } - /****************** + /* * delete the tuple - ****************** */ - if (heap_delete(resultRelationDesc, /* relation desc */ - tupleid)) /* item pointer to tuple */ - return; + result = heap_delete(resultRelationDesc, tupleid, &ctid); + switch (result) + { + case HeapTupleSelfUpdated: + return; + + case HeapTupleMayBeUpdated: + break; + + case HeapTupleUpdated: + if (XactIsoLevel == XACT_SERIALIZED) + elog(ERROR, "Serialize access failed due to concurrent update"); + else + elog(ERROR, "Isolation level %u is not supported", XactIsoLevel); + return; + + default: + elog(ERROR, "Unknown status %u from heap_delete", result); + return; + } IncrDeleted(); (estate->es_processed)++; @@ -1054,7 +1066,7 @@ ExecDelete(TupleTableSlot *slot, /* AFTER ROW DELETE Triggers */ if (resultRelationDesc->trigdesc && resultRelationDesc->trigdesc->n_after_row[TRIGGER_EVENT_DELETE] > 0) - ExecARDeleteTriggers(resultRelationDesc, tupleid); + ExecARDeleteTriggers(estate, tupleid); } @@ -1075,10 +1087,12 @@ ExecReplace(TupleTableSlot *slot, EState *estate, Query *parseTree) { - HeapTuple tuple; - RelationInfo *resultRelationInfo; - Relation resultRelationDesc; - int numIndices; + HeapTuple tuple; + RelationInfo *resultRelationInfo; + Relation resultRelationDesc; + ItemPointerData ctid; + int result; + int numIndices; /****************** * abort the operation if not running transactions @@ -1117,7 +1131,7 @@ ExecReplace(TupleTableSlot *slot, { HeapTuple newtuple; - newtuple = ExecBRUpdateTriggers(resultRelationDesc, tupleid, tuple); + newtuple = ExecBRUpdateTriggers(estate, tupleid, tuple); if (newtuple == NULL) /* "do nothing" */ return; @@ -1140,19 +1154,28 @@ ExecReplace(TupleTableSlot *slot, ExecConstraints("ExecReplace", resultRelationDesc, tuple); } - /****************** + /* * replace the heap tuple - * - * Don't want to continue if our heap_replace didn't actually - * do a replace. This would be the case if heap_replace - * detected a non-functional update. -kw 12/30/93 - ****************** */ - if (heap_replace(resultRelationDesc, /* relation desc */ - tupleid, /* item ptr of tuple to replace */ - tuple)) - { /* replacement heap tuple */ - return; + result = heap_replace(resultRelationDesc, tupleid, tuple, &ctid); + switch (result) + { + case HeapTupleSelfUpdated: + return; + + case HeapTupleMayBeUpdated: + break; + + case HeapTupleUpdated: + if (XactIsoLevel == XACT_SERIALIZED) + elog(ERROR, "Serialize access failed due to concurrent update"); + else + elog(ERROR, "Isolation level %u is not supported", XactIsoLevel); + return; + + default: + elog(ERROR, "Unknown status %u from heap_replace", result); + return; } IncrReplaced(); @@ -1187,7 +1210,7 @@ ExecReplace(TupleTableSlot *slot, /* AFTER ROW UPDATE Triggers */ if (resultRelationDesc->trigdesc && resultRelationDesc->trigdesc->n_after_row[TRIGGER_EVENT_UPDATE] > 0) - ExecARUpdateTriggers(resultRelationDesc, tupleid, tuple); + ExecARUpdateTriggers(estate, tupleid, tuple); } #if 0 diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c index 1af4fcbc88..58dbcd19ef 100644 --- a/src/backend/executor/execUtils.c +++ b/src/backend/executor/execUtils.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.40 1998/11/27 19:52:01 vadim Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.41 1998/12/15 12:46:05 vadim Exp $ * *------------------------------------------------------------------------- */ @@ -868,7 +868,23 @@ ExecOpenIndices(Oid resultRelationOid, indexOid = lfirsti(indexoid); indexDesc = index_open(indexOid); if (indexDesc != NULL) + { relationDescs[i++] = indexDesc; + /* + * Hack for not btree and hash indices: they use relation level + * exclusive locking on updation (i.e. - they are not ready + * for MVCC) and so we have to exclusively lock indices here + * to prevent deadlocks if we will scan them - index_beginscan + * places AccessShareLock, indices update methods don't use + * locks at all. We release this lock in ExecCloseIndices. + * Note, that hashes use page level locking - i.e. are not + * deadlock-free, - let's them be on their way -:)) + * vadim 03-12-1998 + */ + if (indexDesc->rd_rel->relam != BTREE_AM_OID && + indexDesc->rd_rel->relam != HASH_AM_OID) + LockRelation(indexDesc, AccessExclusiveLock); + } } /* ---------------- @@ -948,9 +964,18 @@ ExecCloseIndices(RelationInfo *resultRelationInfo) relationDescs = resultRelationInfo->ri_IndexRelationDescs; for (i = 0; i < numIndices; i++) - if (relationDescs[i] != NULL) - index_close(relationDescs[i]); + { + if (relationDescs[i] == NULL) + continue; + /* + * Notes in ExecOpenIndices. + */ + if (relationDescs[i]->rd_rel->relam != BTREE_AM_OID && + relationDescs[i]->rd_rel->relam != HASH_AM_OID) + UnlockRelation(relationDescs[i], AccessExclusiveLock); + index_close(relationDescs[i]); + } /* * XXX should free indexInfo array here too. */ diff --git a/src/backend/executor/nodeHash.c b/src/backend/executor/nodeHash.c index 5f528850ff..5ec45c7c79 100644 --- a/src/backend/executor/nodeHash.c +++ b/src/backend/executor/nodeHash.c @@ -6,7 +6,7 @@ * Copyright (c) 1994, Regents of the University of California * * - * $Id: nodeHash.c,v 1.27 1998/12/14 08:11:02 scrappy Exp $ + * $Id: nodeHash.c,v 1.28 1998/12/15 12:46:06 vadim Exp $ * *------------------------------------------------------------------------- */ @@ -693,13 +693,13 @@ ExecScanHashBucket(HashJoinState *hjstate, else heapTuple = (HeapTuple) LONGALIGN(((char *) curtuple + curtuple->t_len + HEAPTUPLESIZE)); - - heapTuple->t_data = (HeapTupleHeader) - ((char *) heapTuple + HEAPTUPLESIZE); while (heapTuple < (HeapTuple) ABSADDR(bucket->bottom)) { + heapTuple->t_data = (HeapTupleHeader) + ((char *) heapTuple + HEAPTUPLESIZE); + inntuple = ExecStoreTuple(heapTuple, /* tuple to store */ hjstate->hj_HashTupleSlot, /* slot */ InvalidBuffer, /* tuple has no buffer */ @@ -713,8 +713,6 @@ ExecScanHashBucket(HashJoinState *hjstate, heapTuple = (HeapTuple) LONGALIGN(((char *) heapTuple + heapTuple->t_len + HEAPTUPLESIZE)); - heapTuple->t_data = (HeapTupleHeader) - ((char *) heapTuple + HEAPTUPLESIZE); } if (firstotuple == NULL) |