diff options
Diffstat (limited to 'src/backend/commands/sequence.c')
-rw-r--r-- | src/backend/commands/sequence.c | 62 |
1 files changed, 44 insertions, 18 deletions
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c index 53ec53e39fd..de71560d1da 100644 --- a/src/backend/commands/sequence.c +++ b/src/backend/commands/sequence.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/sequence.c,v 1.116 2004/08/29 05:06:41 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/commands/sequence.c,v 1.117 2004/09/16 16:58:28 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -23,6 +23,8 @@ #include "miscadmin.h" #include "utils/acl.h" #include "utils/builtins.h" +#include "utils/resowner.h" + /* * We don't want to log each fetching of a value from a sequence, @@ -754,25 +756,14 @@ static void init_sequence(RangeVar *relation, SeqTable *p_elm, Relation *p_rel) { Oid relid = RangeVarGetRelid(relation, false); - TransactionId thisxid = GetCurrentTransactionId(); - SeqTable elm; + TransactionId thisxid = GetTopTransactionId(); + volatile SeqTable elm; Relation seqrel; - /* Look to see if we already have a seqtable entry for relation */ - for (elm = seqtab; elm != NULL; elm = elm->next) - { - if (elm->relid == relid) - break; - } - /* - * Open the sequence relation, acquiring AccessShareLock if we don't - * already have a lock in the current xact. + * Open the sequence relation. */ - if (elm == NULL || elm->xid != thisxid) - seqrel = relation_open(relid, AccessShareLock); - else - seqrel = relation_open(relid, NoLock); + seqrel = relation_open(relid, NoLock); if (seqrel->rd_rel->relkind != RELKIND_SEQUENCE) ereport(ERROR, @@ -780,6 +771,13 @@ init_sequence(RangeVar *relation, SeqTable *p_elm, Relation *p_rel) errmsg("\"%s\" is not a sequence", relation->relname))); + /* Look to see if we already have a seqtable entry for relation */ + for (elm = seqtab; elm != NULL; elm = elm->next) + { + if (elm->relid == relid) + break; + } + /* * Allocate new seqtable entry if we didn't find one. * @@ -799,14 +797,42 @@ init_sequence(RangeVar *relation, SeqTable *p_elm, Relation *p_rel) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"))); elm->relid = relid; + elm->xid = InvalidTransactionId; /* increment is set to 0 until we do read_info (see currval) */ elm->last = elm->cached = elm->increment = 0; elm->next = seqtab; seqtab = elm; } - /* Flag that we have a lock in the current xact. */ - elm->xid = thisxid; + /* + * If we haven't touched the sequence already in this transaction, + * we need to acquire AccessShareLock. We arrange for the lock to + * be owned by the top transaction, so that we don't need to do it + * more than once per xact. + */ + if (elm->xid != thisxid) + { + ResourceOwner currentOwner; + + currentOwner = CurrentResourceOwner; + PG_TRY(); + { + CurrentResourceOwner = TopTransactionResourceOwner; + + LockRelation(seqrel, AccessShareLock); + } + PG_CATCH(); + { + /* Ensure CurrentResourceOwner is restored on error */ + CurrentResourceOwner = currentOwner; + PG_RE_THROW(); + } + PG_END_TRY(); + CurrentResourceOwner = currentOwner; + + /* Flag that we have a lock in the current xact. */ + elm->xid = thisxid; + } *p_elm = elm; *p_rel = seqrel; |