Index: doc/src/sgml/func.sgml
===================================================================
RCS file: /cvsroot/pgsql/doc/src/sgml/func.sgml,v
retrieving revision 1.245
diff -u -c -r1.245 func.sgml
*** doc/src/sgml/func.sgml 13 Apr 2005 00:20:10 -0000 1.245
--- doc/src/sgml/func.sgml 8 May 2005 16:24:16 -0000
***************
*** 6475,6480 ****
--- 6475,6483 ----
currval
+ lastval
+
+
setval
***************
*** 6509,6514 ****
--- 6512,6523 ----
Return value most recently obtained with nextval
+ lastval()
+ bigint
+ Return the current value of the last sequence that nextval
+ was invoked on.
+
+
setval(text, bigint)
bigint
Set sequence's current value
***************
*** 6575,6580 ****
--- 6584,6600 ----
+ lastval
+
+
+ This function works exactly as currval except that
+ instead of taking the sequence name as an argument it will fetch the current
+ value of the last sequence that nextval was used on.
+
+
+
+
+
setval
Index: src/backend/commands/sequence.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/commands/sequence.c,v
retrieving revision 1.119
diff -u -c -r1.119 sequence.c
*** src/backend/commands/sequence.c 31 Dec 2004 21:59:41 -0000 1.119
--- src/backend/commands/sequence.c 8 May 2005 16:24:18 -0000
***************
*** 68,74 ****
--- 68,80 ----
static SeqTable seqtab = NULL; /* Head of list of SeqTable items */
+ /*
+ * last_used_seq is updated by nextval() to point out the last used
+ * sequence. It is the sequence used by lastval()
+ */
+ static SeqTableData *last_used_seq = NULL;
+ static void acquire_share_lock (Relation seqrel, SeqTableData *data);
static void init_sequence(RangeVar *relation,
SeqTable *p_elm, Relation *p_rel);
static Form_pg_sequence read_info(SeqTable elm, Relation rel, Buffer *buf);
***************
*** 402,407 ****
--- 408,414 ----
if (elm->last != elm->cached) /* some numbers were cached */
{
elm->last += elm->increment;
+ last_used_seq = elm;
relation_close(seqrel, NoLock);
PG_RETURN_INT64(elm->last);
}
***************
*** 522,527 ****
--- 529,536 ----
elm->last = result; /* last returned number */
elm->cached = last; /* last fetched number */
+ last_used_seq = elm;
+
START_CRIT_SECTION();
/* XLOG stuff */
***************
*** 604,609 ****
--- 613,653 ----
PG_RETURN_INT64(result);
}
+ Datum
+ lastval(PG_FUNCTION_ARGS)
+ {
+ Relation seqrel;
+ int64 result;
+
+ if (last_used_seq == NULL) {
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("nextval have not been used in the current session")));
+ }
+
+ seqrel = relation_open(last_used_seq->relid, NoLock);
+
+ acquire_share_lock (seqrel, last_used_seq);
+
+ if (pg_class_aclcheck(last_used_seq->relid, GetUserId(), ACL_SELECT) != ACLCHECK_OK)
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("permission denied for sequence with OID %d",
+ last_used_seq->relid)));
+
+ if (last_used_seq->increment == 0) /* nextval/read_info were not called */
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("currval of sequence with OID %d is not yet defined in this session",
+ last_used_seq->relid)));
+
+ result = last_used_seq->last;
+
+ relation_close(seqrel, NoLock);
+
+ PG_RETURN_INT64(result);
+ }
+
/*
* Main internal procedure that handles 2 & 3 arg forms of SETVAL.
*
***************
*** 745,750 ****
--- 789,831 ----
/*
+ * 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.
+ */
+ static void
+ acquire_share_lock (Relation seqrel,
+ SeqTableData *data)
+ {
+ TransactionId thisxid = GetTopTransactionId();
+
+ if (data->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. */
+ data->xid = thisxid;
+ }
+ }
+
+ /*
* Given a relation name, open and lock the sequence. p_elm and p_rel are
* output parameters.
*/
***************
*** 752,758 ****
init_sequence(RangeVar *relation, SeqTable *p_elm, Relation *p_rel)
{
Oid relid = RangeVarGetRelid(relation, false);
- TransactionId thisxid = GetTopTransactionId();
volatile SeqTable elm;
Relation seqrel;
--- 833,838 ----
***************
*** 800,834 ****
seqtab = elm;
}
! /*
! * 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;
--- 880,886 ----
seqtab = elm;
}
! acquire_share_lock (seqrel, elm);
*p_elm = elm;
*p_rel = seqrel;
Index: src/include/catalog/pg_proc.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/catalog/pg_proc.h,v
retrieving revision 1.360
diff -u -c -r1.360 pg_proc.h
*** src/include/catalog/pg_proc.h 30 Apr 2005 20:31:38 -0000 1.360
--- src/include/catalog/pg_proc.h 8 May 2005 16:24:21 -0000
***************
*** 3636,3641 ****
--- 3636,3643 ----
DESCR("convert int4 to boolean");
DATA(insert OID = 2558 ( int4 PGNSP PGUID 12 f f t f i 1 23 "16" _null_ _null_ _null_ bool_int4 - _null_ ));
DESCR("convert boolean to int4");
+ DATA(insert OID = 2559 ( lastval PGNSP PGUID 12 f f t f v 0 20 "" _null_ _null_ _null_ lastval - _null_ ));
+ DESCR("current value from last used sequence");
/*
Index: src/include/commands/sequence.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/commands/sequence.h,v
retrieving revision 1.30
diff -u -c -r1.30 sequence.h
*** src/include/commands/sequence.h 31 Dec 2004 22:03:28 -0000 1.30
--- src/include/commands/sequence.h 8 May 2005 16:24:21 -0000
***************
*** 82,87 ****
--- 82,88 ----
extern Datum nextval(PG_FUNCTION_ARGS);
extern Datum currval(PG_FUNCTION_ARGS);
+ extern Datum lastval(PG_FUNCTION_ARGS);
extern Datum setval(PG_FUNCTION_ARGS);
extern Datum setval_and_iscalled(PG_FUNCTION_ARGS);