mirror of
https://github.com/postgres/postgres.git
synced 2025-08-30 06:01:21 +03:00
Initial MVCC code.
New code for locking buffer' context.
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.42 1998/11/27 19:51:53 vadim Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.43 1998/12/15 12:45:50 vadim Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -218,7 +218,7 @@ Async_Listen(char *relname, int pid)
|
||||
TPRINTF(TRACE_NOTIFY, "Async_Listen: %s", relname);
|
||||
|
||||
lRel = heap_openr(ListenerRelationName);
|
||||
RelationSetLockForWrite(lRel);
|
||||
LockRelation(lRel, AccessExclusiveLock);
|
||||
tdesc = RelationGetDescr(lRel);
|
||||
|
||||
/* Detect whether we are already listening on this relname */
|
||||
@@ -242,7 +242,7 @@ Async_Listen(char *relname, int pid)
|
||||
if (alreadyListener)
|
||||
{
|
||||
elog(NOTICE, "Async_Listen: We are already listening on %s", relname);
|
||||
RelationUnsetLockForWrite(lRel);
|
||||
UnlockRelation(lRel, AccessExclusiveLock);
|
||||
heap_close(lRel);
|
||||
return;
|
||||
}
|
||||
@@ -267,7 +267,7 @@ Async_Listen(char *relname, int pid)
|
||||
heap_insert(lRel, newtup);
|
||||
pfree(newtup);
|
||||
|
||||
RelationUnsetLockForWrite(lRel);
|
||||
UnlockRelation(lRel, AccessExclusiveLock);
|
||||
heap_close(lRel);
|
||||
|
||||
/*
|
||||
@@ -320,9 +320,9 @@ Async_Unlisten(char *relname, int pid)
|
||||
if (lTuple != NULL)
|
||||
{
|
||||
lRel = heap_openr(ListenerRelationName);
|
||||
RelationSetLockForWrite(lRel);
|
||||
heap_delete(lRel, &lTuple->t_self);
|
||||
RelationUnsetLockForWrite(lRel);
|
||||
LockRelation(lRel, AccessExclusiveLock);
|
||||
heap_delete(lRel, &lTuple->t_self, NULL);
|
||||
UnlockRelation(lRel, AccessExclusiveLock);
|
||||
heap_close(lRel);
|
||||
}
|
||||
/* We do not complain about unlistening something not being listened;
|
||||
@@ -358,7 +358,7 @@ Async_UnlistenAll()
|
||||
TPRINTF(TRACE_NOTIFY, "Async_UnlistenAll");
|
||||
|
||||
lRel = heap_openr(ListenerRelationName);
|
||||
RelationSetLockForWrite(lRel);
|
||||
LockRelation(lRel, AccessExclusiveLock);
|
||||
tdesc = RelationGetDescr(lRel);
|
||||
|
||||
/* Find and delete all entries with my listenerPID */
|
||||
@@ -369,10 +369,10 @@ Async_UnlistenAll()
|
||||
sRel = heap_beginscan(lRel, 0, SnapshotNow, 1, key);
|
||||
|
||||
while (HeapTupleIsValid(lTuple = heap_getnext(sRel, 0)))
|
||||
heap_delete(lRel, &lTuple->t_self);
|
||||
heap_delete(lRel, &lTuple->t_self, NULL);
|
||||
|
||||
heap_endscan(sRel);
|
||||
RelationUnsetLockForWrite(lRel);
|
||||
UnlockRelation(lRel, AccessExclusiveLock);
|
||||
heap_close(lRel);
|
||||
}
|
||||
|
||||
@@ -463,7 +463,7 @@ AtCommit_Notify()
|
||||
TPRINTF(TRACE_NOTIFY, "AtCommit_Notify");
|
||||
|
||||
lRel = heap_openr(ListenerRelationName);
|
||||
RelationSetLockForWrite(lRel);
|
||||
LockRelation(lRel, AccessExclusiveLock);
|
||||
tdesc = RelationGetDescr(lRel);
|
||||
sRel = heap_beginscan(lRel, 0, SnapshotNow, 0, (ScanKey) NULL);
|
||||
|
||||
@@ -516,7 +516,7 @@ AtCommit_Notify()
|
||||
* but as far as I can see we should just do it for any
|
||||
* failure (certainly at least for EPERM too...)
|
||||
*/
|
||||
heap_delete(lRel, &lTuple->t_self);
|
||||
heap_delete(lRel, &lTuple->t_self, NULL);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -527,7 +527,7 @@ AtCommit_Notify()
|
||||
{
|
||||
rTuple = heap_modifytuple(lTuple, lRel,
|
||||
value, nulls, repl);
|
||||
heap_replace(lRel, &lTuple->t_self, rTuple);
|
||||
heap_replace(lRel, &lTuple->t_self, rTuple, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -741,7 +741,7 @@ ProcessIncomingNotify(void)
|
||||
StartTransactionCommand();
|
||||
|
||||
lRel = heap_openr(ListenerRelationName);
|
||||
RelationSetLockForWrite(lRel);
|
||||
LockRelation(lRel, AccessExclusiveLock);
|
||||
tdesc = RelationGetDescr(lRel);
|
||||
|
||||
/* Scan only entries with my listenerPID */
|
||||
@@ -772,7 +772,7 @@ ProcessIncomingNotify(void)
|
||||
NotifyMyFrontEnd(relname, sourcePID);
|
||||
/* Rewrite the tuple with 0 in notification column */
|
||||
rTuple = heap_modifytuple(lTuple, lRel, value, nulls, repl);
|
||||
heap_replace(lRel, &lTuple->t_self, rTuple);
|
||||
heap_replace(lRel, &lTuple->t_self, rTuple, NULL);
|
||||
}
|
||||
}
|
||||
heap_endscan(sRel);
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.33 1998/11/27 19:51:54 vadim Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.34 1998/12/15 12:45:52 vadim Exp $
|
||||
*
|
||||
* NOTES
|
||||
* The PortalExecutorHeapMemory crap needs to be eliminated
|
||||
@@ -482,7 +482,7 @@ PerformAddAttribute(char *relationName,
|
||||
heap_close(attrdesc);
|
||||
|
||||
((Form_pg_class) GETSTRUCT(reltup))->relnatts = maxatts;
|
||||
heap_replace(rel, &reltup->t_self, reltup);
|
||||
heap_replace(rel, &reltup->t_self, reltup, NULL);
|
||||
|
||||
/* keep catalog indices current */
|
||||
CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, ridescs);
|
||||
|
@@ -6,7 +6,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.64 1998/11/27 19:51:54 vadim Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.65 1998/12/15 12:45:53 vadim Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -777,6 +777,20 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
|
||||
pfree(typmod);
|
||||
}
|
||||
pfree(byval);
|
||||
|
||||
/* comments in execUtils.c */
|
||||
if (has_index)
|
||||
{
|
||||
for (i = 0; i < n_indices; i++)
|
||||
{
|
||||
if (index_rels[i] == NULL)
|
||||
continue;
|
||||
if ((index_rels[i])->rd_rel->relam != BTREE_AM_OID &&
|
||||
(index_rels[i])->rd_rel->relam != HASH_AM_OID)
|
||||
UnlockRelation(index_rels[i], AccessExclusiveLock);
|
||||
index_close(index_rels[i]);
|
||||
}
|
||||
}
|
||||
heap_close(rel);
|
||||
}
|
||||
|
||||
@@ -914,7 +928,14 @@ GetIndexRelations(Oid main_relation_oid,
|
||||
*index_rels = (Relation *) palloc(*n_indices * sizeof(Relation));
|
||||
|
||||
for (i = 0, scan = head; i < *n_indices; i++, scan = scan->next)
|
||||
{
|
||||
(*index_rels)[i] = index_open(scan->index_rel_oid);
|
||||
/* comments in execUtils.c */
|
||||
if ((*index_rels)[i] != NULL &&
|
||||
((*index_rels)[i])->rd_rel->relam != BTREE_AM_OID &&
|
||||
((*index_rels)[i])->rd_rel->relam != HASH_AM_OID)
|
||||
LockRelation((*index_rels)[i], AccessExclusiveLock);
|
||||
}
|
||||
|
||||
for (i = 0, scan = head; i < *n_indices + 1; i++)
|
||||
{
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.27 1998/12/14 05:18:43 scrappy Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.28 1998/12/15 12:45:55 vadim Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -235,7 +235,7 @@ check_permissions(char *command,
|
||||
* delays when multiple 'createdb's or 'destroydb's are run simult.
|
||||
* -mer 7/3/91
|
||||
*/
|
||||
RelationSetLockForWrite(dbrel);
|
||||
LockRelation(dbrel, AccessExclusiveLock);
|
||||
dbtup = get_pg_dbtup(command, dbname, dbrel);
|
||||
dbfound = HeapTupleIsValid(dbtup);
|
||||
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/defind.c,v 1.28 1998/11/27 19:51:56 vadim Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/defind.c,v 1.29 1998/12/15 12:45:56 vadim Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -342,7 +342,7 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable)
|
||||
heapRelation = heap_open(relationId);
|
||||
indexRelation = index_open(indexId);
|
||||
|
||||
RelationSetLockForWrite(heapRelation);
|
||||
LockRelation(heapRelation, ShareLock);
|
||||
|
||||
InitIndexStrategy(numberOfAttributes, indexRelation, accessMethodId);
|
||||
|
||||
|
@@ -174,7 +174,7 @@ DropProceduralLanguage(DropPLangStmt *stmt)
|
||||
}
|
||||
|
||||
rel = heap_openr(LanguageRelationName);
|
||||
heap_delete(rel, &langTup->t_self);
|
||||
heap_delete(rel, &langTup->t_self, NULL);
|
||||
|
||||
pfree(langTup);
|
||||
heap_close(rel);
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.30 1998/11/27 19:51:57 vadim Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.31 1998/12/15 12:45:57 vadim Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -102,7 +102,7 @@ RemoveOperator(char *operatorName, /* operator name */
|
||||
elog(ERROR, "RemoveOperator: operator '%s': permission denied",
|
||||
operatorName);
|
||||
#endif
|
||||
heap_delete(relation, &tup->t_self);
|
||||
heap_delete(relation, &tup->t_self, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -157,7 +157,7 @@ SingleOpOperatorRemove(Oid typeOid)
|
||||
key[0].sk_attno = attnums[i];
|
||||
scan = heap_beginscan(rel, 0, SnapshotNow, 1, key);
|
||||
while (HeapTupleIsValid(tup = heap_getnext(scan, 0)))
|
||||
heap_delete(rel, &tup->t_self);
|
||||
heap_delete(rel, &tup->t_self, NULL);
|
||||
heap_endscan(scan);
|
||||
}
|
||||
heap_close(rel);
|
||||
@@ -268,7 +268,7 @@ RemoveType(char *typeName) /* type name to be removed */
|
||||
|
||||
relation = heap_openr(TypeRelationName);
|
||||
typeOid = tup->t_data->t_oid;
|
||||
heap_delete(relation, &tup->t_self);
|
||||
heap_delete(relation, &tup->t_self, NULL);
|
||||
|
||||
/* Now, Delete the "array of" that type */
|
||||
shadow_type = makeArrayTypeName(typeName);
|
||||
@@ -282,7 +282,7 @@ RemoveType(char *typeName) /* type name to be removed */
|
||||
}
|
||||
|
||||
typeOid = tup->t_data->t_oid;
|
||||
heap_delete(relation, &tup->t_self);
|
||||
heap_delete(relation, &tup->t_self, NULL);
|
||||
|
||||
heap_close(relation);
|
||||
}
|
||||
@@ -357,7 +357,7 @@ RemoveFunction(char *functionName, /* function name to be removed */
|
||||
elog(ERROR, "RemoveFunction: function \"%s\" is built-in", functionName);
|
||||
}
|
||||
|
||||
heap_delete(relation, &tup->t_self);
|
||||
heap_delete(relation, &tup->t_self, NULL);
|
||||
|
||||
heap_close(relation);
|
||||
}
|
||||
@@ -428,7 +428,7 @@ RemoveAggregate(char *aggName, char *aggType)
|
||||
aggName);
|
||||
}
|
||||
}
|
||||
heap_delete(relation, &tup->t_self);
|
||||
heap_delete(relation, &tup->t_self, NULL);
|
||||
|
||||
heap_close(relation);
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.18 1998/11/27 19:51:57 vadim Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.19 1998/12/15 12:45:58 vadim Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -180,7 +180,7 @@ renameatt(char *relname,
|
||||
newattname, NAMEDATALEN);
|
||||
|
||||
attrelation = heap_openr(AttributeRelationName);
|
||||
heap_replace(attrelation, &oldatttup->t_self, oldatttup);
|
||||
heap_replace(attrelation, &oldatttup->t_self, oldatttup, NULL);
|
||||
|
||||
/* keep system catalog indices current */
|
||||
CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, irelations);
|
||||
@@ -248,7 +248,7 @@ renamerel(char *oldrelname, char *newrelname)
|
||||
|
||||
/* insert fixed rel tuple */
|
||||
relrelation = heap_openr(RelationRelationName);
|
||||
heap_replace(relrelation, &oldreltup->t_self, oldreltup);
|
||||
heap_replace(relrelation, &oldreltup->t_self, oldreltup, NULL);
|
||||
|
||||
/* keep the system catalog indices current */
|
||||
CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, irelations);
|
||||
|
@@ -162,7 +162,7 @@ DefineSequence(CreateSeqStmt *seq)
|
||||
rel = heap_openr(seq->seqname);
|
||||
Assert(RelationIsValid(rel));
|
||||
|
||||
RelationSetLockForWrite(rel);
|
||||
LockRelation(rel, AccessExclusiveLock);
|
||||
|
||||
tupDesc = RelationGetDescr(rel);
|
||||
|
||||
@@ -185,7 +185,7 @@ DefineSequence(CreateSeqStmt *seq)
|
||||
if (WriteBuffer(buf) == STATUS_ERROR)
|
||||
elog(ERROR, "DefineSequence: WriteBuffer failed");
|
||||
|
||||
RelationUnsetLockForWrite(rel);
|
||||
UnlockRelation(rel, AccessExclusiveLock);
|
||||
heap_close(rel);
|
||||
|
||||
return;
|
||||
@@ -200,7 +200,6 @@ nextval(struct varlena * seqin)
|
||||
SeqTable elm;
|
||||
Buffer buf;
|
||||
Form_pg_sequence seq;
|
||||
ItemPointerData iptr;
|
||||
int4 incby,
|
||||
maxv,
|
||||
minv,
|
||||
@@ -209,7 +208,7 @@ nextval(struct varlena * seqin)
|
||||
next,
|
||||
rescnt = 0;
|
||||
|
||||
/* open and WIntentLock sequence */
|
||||
/* open and AccessShareLock sequence */
|
||||
elm = init_sequence("nextval", seqname);
|
||||
pfree(seqname);
|
||||
|
||||
@@ -219,7 +218,7 @@ nextval(struct varlena * seqin)
|
||||
return elm->last;
|
||||
}
|
||||
|
||||
seq = read_info("nextval", elm, &buf); /* lock page and read
|
||||
seq = read_info("nextval", elm, &buf); /* lock page' buffer and read
|
||||
* tuple */
|
||||
|
||||
next = result = seq->last_value;
|
||||
@@ -282,12 +281,11 @@ nextval(struct varlena * seqin)
|
||||
seq->last_value = next; /* last fetched number */
|
||||
seq->is_called = 't';
|
||||
|
||||
LockBuffer(buf, BUFFER_LOCK_UNLOCK);
|
||||
|
||||
if (WriteBuffer(buf) == STATUS_ERROR)
|
||||
elog(ERROR, "%s.nextval: WriteBuffer failed", elm->name);
|
||||
|
||||
ItemPointerSet(&iptr, 0, FirstOffsetNumber);
|
||||
RelationUnsetSingleWLockPage(elm->rel, &iptr);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
@@ -300,7 +298,7 @@ currval(struct varlena * seqin)
|
||||
SeqTable elm;
|
||||
int4 result;
|
||||
|
||||
/* open and WIntentLock sequence */
|
||||
/* open and AccessShareLock sequence */
|
||||
elm = init_sequence("currval", seqname);
|
||||
pfree(seqname);
|
||||
|
||||
@@ -320,7 +318,6 @@ setval(struct varlena * seqin, int4 next)
|
||||
SeqTable elm;
|
||||
Buffer buf;
|
||||
Form_pg_sequence seq;
|
||||
ItemPointerData iptr;
|
||||
|
||||
#ifndef NO_SECURITY
|
||||
if (pg_aclcheck(seqname, getpgusername(), ACL_WR) != ACLCHECK_OK)
|
||||
@@ -328,9 +325,9 @@ setval(struct varlena * seqin, int4 next)
|
||||
seqname, seqname);
|
||||
#endif
|
||||
|
||||
/* open and WIntentLock sequence */
|
||||
/* open and AccessShareLock sequence */
|
||||
elm = init_sequence("setval", seqname);
|
||||
seq = read_info("setval", elm, &buf); /* lock page and read
|
||||
seq = read_info("setval", elm, &buf); /* lock page' buffer and read
|
||||
* tuple */
|
||||
|
||||
if (seq->cache_value != 1)
|
||||
@@ -353,27 +350,22 @@ setval(struct varlena * seqin, int4 next)
|
||||
seq->last_value = next; /* last fetched number */
|
||||
seq->is_called = 't';
|
||||
|
||||
LockBuffer(buf, BUFFER_LOCK_UNLOCK);
|
||||
|
||||
if (WriteBuffer(buf) == STATUS_ERROR)
|
||||
elog(ERROR, "%s.settval: WriteBuffer failed", seqname);
|
||||
|
||||
ItemPointerSet(&iptr, 0, FirstOffsetNumber);
|
||||
RelationUnsetSingleWLockPage(elm->rel, &iptr);
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
static Form_pg_sequence
|
||||
read_info(char *caller, SeqTable elm, Buffer *buf)
|
||||
{
|
||||
ItemPointerData iptr;
|
||||
PageHeader page;
|
||||
ItemId lp;
|
||||
PageHeader page;
|
||||
ItemId lp;
|
||||
HeapTupleData tuple;
|
||||
sequence_magic *sm;
|
||||
Form_pg_sequence seq;
|
||||
|
||||
ItemPointerSet(&iptr, 0, FirstOffsetNumber);
|
||||
RelationSetSingleWLockPage(elm->rel, &iptr);
|
||||
Form_pg_sequence seq;
|
||||
|
||||
if (RelationGetNumberOfBlocks(elm->rel) != 1)
|
||||
elog(ERROR, "%s.%s: invalid number of blocks in sequence",
|
||||
@@ -383,6 +375,8 @@ read_info(char *caller, SeqTable elm, Buffer *buf)
|
||||
if (!BufferIsValid(*buf))
|
||||
elog(ERROR, "%s.%s: ReadBuffer failed", elm->name, caller);
|
||||
|
||||
LockBuffer(*buf, BUFFER_LOCK_EXCLUSIVE);
|
||||
|
||||
page = (PageHeader) BufferGetPage(*buf);
|
||||
sm = (sequence_magic *) PageGetSpecialPointer(page);
|
||||
|
||||
@@ -439,7 +433,7 @@ init_sequence(char *caller, char *name)
|
||||
if (!RelationIsValid(temp->rel))
|
||||
elog(ERROR, "%s.%s: sequence does not exist", name, caller);
|
||||
|
||||
RelationSetWIntentLock(temp->rel);
|
||||
LockRelation(temp->rel, AccessShareLock);
|
||||
|
||||
if (temp->rel->rd_rel->relkind != RELKIND_SEQUENCE)
|
||||
elog(ERROR, "%s.%s: %s is not sequence !", name, caller, name);
|
||||
@@ -485,7 +479,7 @@ CloseSequences(void)
|
||||
{
|
||||
rel = elm->rel;
|
||||
elm->rel = (Relation) NULL;
|
||||
RelationUnsetWIntentLock(rel);
|
||||
UnlockRelation(rel, AccessShareLock);
|
||||
heap_close(rel);
|
||||
}
|
||||
elm = elm->next;
|
||||
|
@@ -40,7 +40,7 @@ void RelationBuildTriggers(Relation relation);
|
||||
void FreeTriggerDesc(Relation relation);
|
||||
|
||||
static void DescribeTrigger(TriggerDesc *trigdesc, Trigger *trigger);
|
||||
static HeapTuple GetTupleForTrigger(Relation relation, ItemPointer tid,
|
||||
static HeapTuple GetTupleForTrigger(EState *estate, ItemPointer tid,
|
||||
bool before);
|
||||
|
||||
extern GlobalMemory CacheCxt;
|
||||
@@ -77,7 +77,7 @@ CreateTrigger(CreateTrigStmt *stmt)
|
||||
if (!RelationIsValid(rel))
|
||||
elog(ERROR, "CreateTrigger: there is no relation %s", stmt->relname);
|
||||
|
||||
RelationSetLockForWrite(rel);
|
||||
LockRelation(rel, AccessExclusiveLock);
|
||||
|
||||
TRIGGER_CLEAR_TYPE(tgtype);
|
||||
if (stmt->before)
|
||||
@@ -114,7 +114,7 @@ CreateTrigger(CreateTrigStmt *stmt)
|
||||
|
||||
/* Scan pg_trigger */
|
||||
tgrel = heap_openr(TriggerRelationName);
|
||||
RelationSetLockForWrite(tgrel);
|
||||
LockRelation(tgrel, AccessExclusiveLock);
|
||||
ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,
|
||||
F_OIDEQ, RelationGetRelid(rel));
|
||||
tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &key);
|
||||
@@ -211,7 +211,7 @@ CreateTrigger(CreateTrigStmt *stmt)
|
||||
CatalogIndexInsert(idescs, Num_pg_trigger_indices, tgrel, tuple);
|
||||
CatalogCloseIndices(Num_pg_trigger_indices, idescs);
|
||||
pfree(tuple);
|
||||
RelationUnsetLockForWrite(tgrel);
|
||||
UnlockRelation(tgrel, AccessExclusiveLock);
|
||||
heap_close(tgrel);
|
||||
|
||||
pfree(DatumGetPointer(values[Anum_pg_trigger_tgname - 1]));
|
||||
@@ -227,7 +227,7 @@ CreateTrigger(CreateTrigStmt *stmt)
|
||||
pgrel = heap_openr(RelationRelationName);
|
||||
((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found + 1;
|
||||
RelationInvalidateHeapTuple(pgrel, tuple);
|
||||
heap_replace(pgrel, &tuple->t_self, tuple);
|
||||
heap_replace(pgrel, &tuple->t_self, tuple, NULL);
|
||||
CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, ridescs);
|
||||
CatalogIndexInsert(ridescs, Num_pg_class_indices, pgrel, tuple);
|
||||
CatalogCloseIndices(Num_pg_class_indices, ridescs);
|
||||
@@ -267,10 +267,10 @@ DropTrigger(DropTrigStmt *stmt)
|
||||
if (!RelationIsValid(rel))
|
||||
elog(ERROR, "DropTrigger: there is no relation %s", stmt->relname);
|
||||
|
||||
RelationSetLockForWrite(rel);
|
||||
LockRelation(rel, AccessExclusiveLock);
|
||||
|
||||
tgrel = heap_openr(TriggerRelationName);
|
||||
RelationSetLockForWrite(tgrel);
|
||||
LockRelation(tgrel, AccessExclusiveLock);
|
||||
ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,
|
||||
F_OIDEQ, RelationGetRelid(rel));
|
||||
tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &key);
|
||||
@@ -280,7 +280,7 @@ DropTrigger(DropTrigStmt *stmt)
|
||||
|
||||
if (namestrcmp(&(pg_trigger->tgname), stmt->trigname) == 0)
|
||||
{
|
||||
heap_delete(tgrel, &tuple->t_self);
|
||||
heap_delete(tgrel, &tuple->t_self, NULL);
|
||||
tgfound++;
|
||||
}
|
||||
else
|
||||
@@ -293,7 +293,7 @@ DropTrigger(DropTrigStmt *stmt)
|
||||
elog(NOTICE, "DropTrigger: found (and deleted) %d trigger %s on relation %s",
|
||||
tgfound, stmt->trigname, stmt->relname);
|
||||
heap_endscan(tgscan);
|
||||
RelationUnsetLockForWrite(tgrel);
|
||||
UnlockRelation(tgrel, AccessExclusiveLock);
|
||||
heap_close(tgrel);
|
||||
|
||||
tuple = SearchSysCacheTupleCopy(RELNAME,
|
||||
@@ -306,7 +306,7 @@ DropTrigger(DropTrigStmt *stmt)
|
||||
pgrel = heap_openr(RelationRelationName);
|
||||
((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found;
|
||||
RelationInvalidateHeapTuple(pgrel, tuple);
|
||||
heap_replace(pgrel, &tuple->t_self, tuple);
|
||||
heap_replace(pgrel, &tuple->t_self, tuple, NULL);
|
||||
CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, ridescs);
|
||||
CatalogIndexInsert(ridescs, Num_pg_class_indices, pgrel, tuple);
|
||||
CatalogCloseIndices(Num_pg_class_indices, ridescs);
|
||||
@@ -333,17 +333,17 @@ RelationRemoveTriggers(Relation rel)
|
||||
HeapTuple tup;
|
||||
|
||||
tgrel = heap_openr(TriggerRelationName);
|
||||
RelationSetLockForWrite(tgrel);
|
||||
LockRelation(tgrel, AccessExclusiveLock);
|
||||
ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,
|
||||
F_OIDEQ, RelationGetRelid(rel));
|
||||
|
||||
tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &key);
|
||||
|
||||
while (HeapTupleIsValid(tup = heap_getnext(tgscan, 0)))
|
||||
heap_delete(tgrel, &tup->t_self);
|
||||
heap_delete(tgrel, &tup->t_self, NULL);
|
||||
|
||||
heap_endscan(tgscan);
|
||||
RelationUnsetLockForWrite(tgrel);
|
||||
UnlockRelation(tgrel, AccessExclusiveLock);
|
||||
heap_close(tgrel);
|
||||
|
||||
}
|
||||
@@ -376,7 +376,6 @@ RelationBuildTriggers(Relation relation)
|
||||
ObjectIdGetDatum(RelationGetRelid(relation)));
|
||||
|
||||
tgrel = heap_openr(TriggerRelationName);
|
||||
RelationSetLockForRead(tgrel);
|
||||
irel = index_openr(TriggerRelidIndex);
|
||||
sd = index_beginscan(irel, false, 1, &skey);
|
||||
|
||||
@@ -450,7 +449,6 @@ RelationBuildTriggers(Relation relation)
|
||||
index_endscan(sd);
|
||||
pfree(sd);
|
||||
index_close(irel);
|
||||
RelationUnsetLockForRead(tgrel);
|
||||
heap_close(tgrel);
|
||||
|
||||
/* Build trigdesc */
|
||||
@@ -657,16 +655,17 @@ ExecARInsertTriggers(Relation rel, HeapTuple trigtuple)
|
||||
}
|
||||
|
||||
bool
|
||||
ExecBRDeleteTriggers(Relation rel, ItemPointer tupleid)
|
||||
ExecBRDeleteTriggers(EState *estate, ItemPointer tupleid)
|
||||
{
|
||||
TriggerData *SaveTriggerData;
|
||||
int ntrigs = rel->trigdesc->n_before_row[TRIGGER_EVENT_DELETE];
|
||||
Trigger **trigger = rel->trigdesc->tg_before_row[TRIGGER_EVENT_DELETE];
|
||||
HeapTuple trigtuple;
|
||||
HeapTuple newtuple = NULL;
|
||||
int i;
|
||||
Relation rel = estate->es_result_relation_info->ri_RelationDesc;
|
||||
TriggerData *SaveTriggerData;
|
||||
int ntrigs = rel->trigdesc->n_before_row[TRIGGER_EVENT_DELETE];
|
||||
Trigger **trigger = rel->trigdesc->tg_before_row[TRIGGER_EVENT_DELETE];
|
||||
HeapTuple trigtuple;
|
||||
HeapTuple newtuple = NULL;
|
||||
int i;
|
||||
|
||||
trigtuple = GetTupleForTrigger(rel, tupleid, true);
|
||||
trigtuple = GetTupleForTrigger(estate, tupleid, true);
|
||||
if (trigtuple == NULL)
|
||||
return false;
|
||||
|
||||
@@ -692,15 +691,16 @@ ExecBRDeleteTriggers(Relation rel, ItemPointer tupleid)
|
||||
}
|
||||
|
||||
void
|
||||
ExecARDeleteTriggers(Relation rel, ItemPointer tupleid)
|
||||
ExecARDeleteTriggers(EState *estate, ItemPointer tupleid)
|
||||
{
|
||||
Relation rel = estate->es_result_relation_info->ri_RelationDesc;
|
||||
TriggerData *SaveTriggerData;
|
||||
int ntrigs = rel->trigdesc->n_after_row[TRIGGER_EVENT_DELETE];
|
||||
Trigger **trigger = rel->trigdesc->tg_after_row[TRIGGER_EVENT_DELETE];
|
||||
HeapTuple trigtuple;
|
||||
int i;
|
||||
|
||||
trigtuple = GetTupleForTrigger(rel, tupleid, false);
|
||||
trigtuple = GetTupleForTrigger(estate, tupleid, false);
|
||||
Assert(trigtuple != NULL);
|
||||
|
||||
SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData));
|
||||
@@ -722,17 +722,18 @@ ExecARDeleteTriggers(Relation rel, ItemPointer tupleid)
|
||||
}
|
||||
|
||||
HeapTuple
|
||||
ExecBRUpdateTriggers(Relation rel, ItemPointer tupleid, HeapTuple newtuple)
|
||||
ExecBRUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple newtuple)
|
||||
{
|
||||
TriggerData *SaveTriggerData;
|
||||
int ntrigs = rel->trigdesc->n_before_row[TRIGGER_EVENT_UPDATE];
|
||||
Trigger **trigger = rel->trigdesc->tg_before_row[TRIGGER_EVENT_UPDATE];
|
||||
HeapTuple trigtuple;
|
||||
HeapTuple oldtuple;
|
||||
HeapTuple intuple = newtuple;
|
||||
int i;
|
||||
Relation rel = estate->es_result_relation_info->ri_RelationDesc;
|
||||
TriggerData *SaveTriggerData;
|
||||
int ntrigs = rel->trigdesc->n_before_row[TRIGGER_EVENT_UPDATE];
|
||||
Trigger **trigger = rel->trigdesc->tg_before_row[TRIGGER_EVENT_UPDATE];
|
||||
HeapTuple trigtuple;
|
||||
HeapTuple oldtuple;
|
||||
HeapTuple intuple = newtuple;
|
||||
int i;
|
||||
|
||||
trigtuple = GetTupleForTrigger(rel, tupleid, true);
|
||||
trigtuple = GetTupleForTrigger(estate, tupleid, true);
|
||||
if (trigtuple == NULL)
|
||||
return NULL;
|
||||
|
||||
@@ -759,15 +760,16 @@ ExecBRUpdateTriggers(Relation rel, ItemPointer tupleid, HeapTuple newtuple)
|
||||
}
|
||||
|
||||
void
|
||||
ExecARUpdateTriggers(Relation rel, ItemPointer tupleid, HeapTuple newtuple)
|
||||
ExecARUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple newtuple)
|
||||
{
|
||||
Relation rel = estate->es_result_relation_info->ri_RelationDesc;
|
||||
TriggerData *SaveTriggerData;
|
||||
int ntrigs = rel->trigdesc->n_after_row[TRIGGER_EVENT_UPDATE];
|
||||
Trigger **trigger = rel->trigdesc->tg_after_row[TRIGGER_EVENT_UPDATE];
|
||||
HeapTuple trigtuple;
|
||||
int i;
|
||||
|
||||
trigtuple = GetTupleForTrigger(rel, tupleid, false);
|
||||
trigtuple = GetTupleForTrigger(estate, tupleid, false);
|
||||
Assert(trigtuple != NULL);
|
||||
|
||||
SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData));
|
||||
@@ -789,48 +791,67 @@ ExecARUpdateTriggers(Relation rel, ItemPointer tupleid, HeapTuple newtuple)
|
||||
}
|
||||
|
||||
static HeapTuple
|
||||
GetTupleForTrigger(Relation relation, ItemPointer tid, bool before)
|
||||
GetTupleForTrigger(EState *estate, ItemPointer tid, bool before)
|
||||
{
|
||||
ItemId lp;
|
||||
Relation relation = estate->es_result_relation_info->ri_RelationDesc;
|
||||
HeapTupleData tuple;
|
||||
HeapTuple result;
|
||||
PageHeader dp;
|
||||
Buffer b;
|
||||
|
||||
b = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
|
||||
|
||||
if (!BufferIsValid(b))
|
||||
elog(ERROR, "GetTupleForTrigger: failed ReadBuffer");
|
||||
|
||||
dp = (PageHeader) BufferGetPage(b);
|
||||
lp = PageGetItemId(dp, ItemPointerGetOffsetNumber(tid));
|
||||
|
||||
Assert(ItemIdIsUsed(lp));
|
||||
|
||||
tuple.t_data = (HeapTupleHeader) PageGetItem((Page) dp, lp);
|
||||
tuple.t_len = ItemIdGetLength(lp);
|
||||
tuple.t_self = *tid;
|
||||
Buffer buffer;
|
||||
|
||||
if (before)
|
||||
{
|
||||
if (TupleUpdatedByCurXactAndCmd(&tuple))
|
||||
{
|
||||
elog(NOTICE, "GetTupleForTrigger: Non-functional delete/update");
|
||||
ReleaseBuffer(b);
|
||||
return NULL;
|
||||
}
|
||||
int test;
|
||||
|
||||
HeapTupleSatisfies(&tuple, relation, b, dp,
|
||||
false, 0, (ScanKey) NULL);
|
||||
if (!tuple.t_data)
|
||||
/*
|
||||
* mark tuple for update
|
||||
*/
|
||||
tuple.t_self = *tid;
|
||||
test = heap_mark4update(relation, &tuple, &buffer);
|
||||
switch (test)
|
||||
{
|
||||
ReleaseBuffer(b);
|
||||
elog(ERROR, "GetTupleForTrigger: (am)invalid tid");
|
||||
case HeapTupleSelfUpdated:
|
||||
ReleaseBuffer(buffer);
|
||||
return(NULL);
|
||||
|
||||
case HeapTupleMayBeUpdated:
|
||||
break;
|
||||
|
||||
case HeapTupleUpdated:
|
||||
ReleaseBuffer(buffer);
|
||||
if (XactIsoLevel == XACT_SERIALIZED)
|
||||
elog(ERROR, "Serialize access failed due to concurrent update");
|
||||
else
|
||||
elog(ERROR, "Isolation level %u is not supported", XactIsoLevel);
|
||||
return(NULL);
|
||||
|
||||
default:
|
||||
ReleaseBuffer(buffer);
|
||||
elog(ERROR, "Unknown status %u from heap_mark4update", test);
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PageHeader dp;
|
||||
ItemId lp;
|
||||
|
||||
buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
|
||||
|
||||
if (!BufferIsValid(buffer))
|
||||
elog(ERROR, "GetTupleForTrigger: failed ReadBuffer");
|
||||
|
||||
dp = (PageHeader) BufferGetPage(buffer);
|
||||
lp = PageGetItemId(dp, ItemPointerGetOffsetNumber(tid));
|
||||
|
||||
Assert(ItemIdIsUsed(lp));
|
||||
|
||||
tuple.t_data = (HeapTupleHeader) PageGetItem((Page) dp, lp);
|
||||
tuple.t_len = ItemIdGetLength(lp);
|
||||
tuple.t_self = *tid;
|
||||
}
|
||||
|
||||
result = heap_copytuple(&tuple);
|
||||
ReleaseBuffer(b);
|
||||
ReleaseBuffer(buffer);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: user.c,v 1.22 1998/12/14 08:11:00 scrappy Exp $
|
||||
* $Id: user.c,v 1.23 1998/12/15 12:46:00 vadim Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -136,7 +136,7 @@ DefineUser(CreateUserStmt *stmt)
|
||||
* Secure a write lock on pg_shadow so we can be sure of what the next
|
||||
* usesysid should be.
|
||||
*/
|
||||
RelationSetLockForWrite(pg_shadow_rel);
|
||||
LockRelation(pg_shadow_rel, AccessExclusiveLock);
|
||||
|
||||
scan = heap_beginscan(pg_shadow_rel, false, SnapshotNow, 0, NULL);
|
||||
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
|
||||
@@ -154,7 +154,7 @@ DefineUser(CreateUserStmt *stmt)
|
||||
|
||||
if (exists)
|
||||
{
|
||||
RelationUnsetLockForWrite(pg_shadow_rel);
|
||||
UnlockRelation(pg_shadow_rel, AccessExclusiveLock);
|
||||
heap_close(pg_shadow_rel);
|
||||
UserAbortTransactionBlock();
|
||||
elog(ERROR,
|
||||
@@ -187,7 +187,7 @@ DefineUser(CreateUserStmt *stmt)
|
||||
* This goes after the UpdatePgPwdFile to be certain that two backends
|
||||
* to not attempt to write to the pg_pwd file at the same time.
|
||||
*/
|
||||
RelationUnsetLockForWrite(pg_shadow_rel);
|
||||
UnlockRelation(pg_shadow_rel, AccessExclusiveLock);
|
||||
heap_close(pg_shadow_rel);
|
||||
|
||||
if (IsTransactionBlock() && !inblock)
|
||||
@@ -235,14 +235,14 @@ AlterUser(AlterUserStmt *stmt)
|
||||
* dump of the pg_pwd file is done, there is not another backend doing
|
||||
* the same.
|
||||
*/
|
||||
RelationSetLockForWrite(pg_shadow_rel);
|
||||
LockRelation(pg_shadow_rel, AccessExclusiveLock);
|
||||
|
||||
tuple = SearchSysCacheTuple(USENAME,
|
||||
PointerGetDatum(stmt->user),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
{
|
||||
RelationUnsetLockForWrite(pg_shadow_rel);
|
||||
UnlockRelation(pg_shadow_rel, AccessExclusiveLock);
|
||||
heap_close(pg_shadow_rel);
|
||||
UserAbortTransactionBlock(); /* needed? */
|
||||
elog(ERROR, "alterUser: user \"%s\" does not exist", stmt->user);
|
||||
@@ -288,7 +288,7 @@ AlterUser(AlterUserStmt *stmt)
|
||||
|
||||
UpdatePgPwdFile(sql);
|
||||
|
||||
RelationUnsetLockForWrite(pg_shadow_rel);
|
||||
UnlockRelation(pg_shadow_rel, AccessExclusiveLock);
|
||||
heap_close(pg_shadow_rel);
|
||||
|
||||
if (IsTransactionBlock() && !inblock)
|
||||
@@ -342,14 +342,14 @@ RemoveUser(char *user)
|
||||
* dump of the pg_pwd file is done, there is not another backend doing
|
||||
* the same.
|
||||
*/
|
||||
RelationSetLockForWrite(pg_shadow_rel);
|
||||
LockRelation(pg_shadow_rel, AccessExclusiveLock);
|
||||
|
||||
tuple = SearchSysCacheTuple(USENAME,
|
||||
PointerGetDatum(user),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
{
|
||||
RelationUnsetLockForWrite(pg_shadow_rel);
|
||||
UnlockRelation(pg_shadow_rel, AccessExclusiveLock);
|
||||
heap_close(pg_shadow_rel);
|
||||
UserAbortTransactionBlock();
|
||||
elog(ERROR, "removeUser: user \"%s\" does not exist", user);
|
||||
@@ -422,7 +422,7 @@ RemoveUser(char *user)
|
||||
|
||||
UpdatePgPwdFile(sql);
|
||||
|
||||
RelationUnsetLockForWrite(pg_shadow_rel);
|
||||
UnlockRelation(pg_shadow_rel, AccessExclusiveLock);
|
||||
heap_close(pg_shadow_rel);
|
||||
|
||||
if (IsTransactionBlock() && !inblock)
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.91 1998/11/27 19:51:58 vadim Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.92 1998/12/15 12:46:01 vadim Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -497,7 +497,7 @@ vc_vacone(Oid relid, bool analyze, List *va_cols)
|
||||
}
|
||||
|
||||
/* we require the relation to be locked until the indices are cleaned */
|
||||
RelationSetLockForWrite(onerel);
|
||||
LockRelation(onerel, AccessExclusiveLock);
|
||||
|
||||
/* scan it */
|
||||
vacuum_pages.vpl_num_pages = fraged_pages.vpl_num_pages = 0;
|
||||
@@ -1918,7 +1918,7 @@ vc_delhilowstats(Oid relid, int attcnt, int *attnums)
|
||||
if (i >= attcnt)
|
||||
continue; /* don't delete it */
|
||||
}
|
||||
heap_delete(pgstatistic, &tuple->t_self);
|
||||
heap_delete(pgstatistic, &tuple->t_self, NULL);
|
||||
}
|
||||
|
||||
heap_endscan(scan);
|
||||
@@ -1928,11 +1928,7 @@ vc_delhilowstats(Oid relid, int attcnt, int *attnums)
|
||||
static void
|
||||
vc_setpagelock(Relation rel, BlockNumber blkno)
|
||||
{
|
||||
ItemPointerData itm;
|
||||
|
||||
ItemPointerSet(&itm, blkno, 1);
|
||||
|
||||
RelationSetLockForWritePage(rel, &itm);
|
||||
LockPage(rel, blkno, ExclusiveLock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user