Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit657c098

Browse files
author
Neil Conway
committed
Add a function lastval(), which returns the value returned by the
last nextval() or setval() performed by the current session. Update thedocs, add regression tests, and bump the catalog version. Patch fromDennis Björklund, various improvements by Neil Conway.
1 parentc59887f commit657c098

File tree

7 files changed

+202
-36
lines changed

7 files changed

+202
-36
lines changed

‎doc/src/sgml/func.sgml

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.251 2005/06/06 16:29:01 tgl Exp $
2+
$PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.252 2005/06/07 07:08:34 neilc Exp $
33
PostgreSQL documentation
44
-->
55

@@ -6487,6 +6487,9 @@ SELECT TIMESTAMP 'now'; -- incorrect for use with DEFAULT
64876487
<indexterm>
64886488
<primary>currval</primary>
64896489
</indexterm>
6490+
<indexterm>
6491+
<primary>lastval</primary>
6492+
</indexterm>
64906493
<indexterm>
64916494
<primary>setval</primary>
64926495
</indexterm>
@@ -6519,6 +6522,12 @@ SELECT TIMESTAMP 'now'; -- incorrect for use with DEFAULT
65196522
<row>
65206523
<entry><literal><function>currval</function>(<type>text</type>)</literal></entry>
65216524
<entry><type>bigint</type></entry>
6525+
<entry>Return value most recently obtained with
6526+
<function>nextval</function> for specified sequence</entry>
6527+
</row>
6528+
<row>
6529+
<entry><literal><function>lastval</function>()</literal></entry>
6530+
<entry><type>bigint</type></entry>
65226531
<entry>Return value most recently obtained with <function>nextval</function></entry>
65236532
</row>
65246533
<row>
@@ -6587,6 +6596,22 @@ nextval('foo') <lineannotation>searches search path for <literal>fo
65876596
</listitem>
65886597
</varlistentry>
65896598

6599+
<varlistentry>
6600+
<term><function>lastval</function></term>
6601+
<listitem>
6602+
<para>
6603+
Return the value most recently returned by
6604+
<function>nextval</> in the current session. This function is
6605+
identical to <function>currval</function>, except that instead
6606+
of taking the sequence name as an argument it fetches the
6607+
value of the last sequence that <function>nextval</function>
6608+
was used on in the current session. It is an error to call
6609+
<function>lastval</function> if <function>nextval</function>
6610+
has not yet been called in the current session.
6611+
</para>
6612+
</listitem>
6613+
</varlistentry>
6614+
65906615
<varlistentry>
65916616
<term><function>setval</function></term>
65926617
<listitem>

‎src/backend/commands/sequence.c

Lines changed: 83 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/commands/sequence.c,v 1.122 2005/06/06 20:22:57 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/commands/sequence.c,v 1.123 2005/06/07 07:08:34 neilc Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -24,6 +24,7 @@
2424
#include"utils/acl.h"
2525
#include"utils/builtins.h"
2626
#include"utils/resowner.h"
27+
#include"utils/syscache.h"
2728

2829

2930
/*
@@ -68,7 +69,13 @@ typedef SeqTableData *SeqTable;
6869

6970
staticSeqTableseqtab=NULL;/* Head of list of SeqTable items */
7071

72+
/*
73+
* last_used_seq is updated by nextval() to point to the last used
74+
* sequence.
75+
*/
76+
staticSeqTableData*last_used_seq=NULL;
7177

78+
staticvoidacquire_share_lock(Relationseqrel,SeqTableseq);
7279
staticvoidinit_sequence(RangeVar*relation,
7380
SeqTable*p_elm,Relation*p_rel);
7481
staticForm_pg_sequenceread_info(SeqTableelm,Relationrel,Buffer*buf);
@@ -400,6 +407,7 @@ nextval(PG_FUNCTION_ARGS)
400407

401408
if (elm->last!=elm->cached)/* some numbers were cached */
402409
{
410+
last_used_seq=elm;
403411
elm->last+=elm->increment;
404412
relation_close(seqrel,NoLock);
405413
PG_RETURN_INT64(elm->last);
@@ -521,6 +529,8 @@ nextval(PG_FUNCTION_ARGS)
521529
elm->last=result;/* last returned number */
522530
elm->cached=last;/* last fetched number */
523531

532+
last_used_seq=elm;
533+
524534
START_CRIT_SECTION();
525535

526536
/* XLOG stuff */
@@ -602,6 +612,42 @@ currval(PG_FUNCTION_ARGS)
602612
PG_RETURN_INT64(result);
603613
}
604614

615+
Datum
616+
lastval(PG_FUNCTION_ARGS)
617+
{
618+
Relationseqrel;
619+
int64result;
620+
621+
if (last_used_seq==NULL)
622+
ereport(ERROR,
623+
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
624+
errmsg("lastval is not yet defined in this session")));
625+
626+
/* Someone may have dropped the sequence since the last nextval() */
627+
if (!SearchSysCacheExists(RELOID,
628+
ObjectIdGetDatum(last_used_seq->relid),
629+
0,0,0))
630+
ereport(ERROR,
631+
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
632+
errmsg("lastval is not yet defined in this session")));
633+
634+
seqrel=relation_open(last_used_seq->relid,NoLock);
635+
acquire_share_lock(seqrel,last_used_seq);
636+
637+
/* nextval() must have already been called for this sequence */
638+
Assert(last_used_seq->increment!=0);
639+
640+
if (pg_class_aclcheck(last_used_seq->relid,GetUserId(),ACL_SELECT)!=ACLCHECK_OK)
641+
ereport(ERROR,
642+
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
643+
errmsg("permission denied for sequence %s",
644+
RelationGetRelationName(seqrel))));
645+
646+
result=last_used_seq->last;
647+
relation_close(seqrel,NoLock);
648+
PG_RETURN_INT64(result);
649+
}
650+
605651
/*
606652
* Main internal procedure that handles 2 & 3 arg forms of SETVAL.
607653
*
@@ -740,6 +786,41 @@ setval_and_iscalled(PG_FUNCTION_ARGS)
740786
}
741787

742788

789+
/*
790+
* If we haven't touched the sequence already in this transaction,
791+
* we need to acquire AccessShareLock. We arrange for the lock to
792+
* be owned by the top transaction, so that we don't need to do it
793+
* more than once per xact.
794+
*/
795+
staticvoid
796+
acquire_share_lock(Relationseqrel,SeqTableseq)
797+
{
798+
TransactionIdthisxid=GetTopTransactionId();
799+
800+
if (seq->xid!=thisxid)
801+
{
802+
ResourceOwnercurrentOwner;
803+
804+
currentOwner=CurrentResourceOwner;
805+
PG_TRY();
806+
{
807+
CurrentResourceOwner=TopTransactionResourceOwner;
808+
LockRelation(seqrel,AccessShareLock);
809+
}
810+
PG_CATCH();
811+
{
812+
/* Ensure CurrentResourceOwner is restored on error */
813+
CurrentResourceOwner=currentOwner;
814+
PG_RE_THROW();
815+
}
816+
PG_END_TRY();
817+
CurrentResourceOwner=currentOwner;
818+
819+
/* Flag that we have a lock in the current xact. */
820+
seq->xid=thisxid;
821+
}
822+
}
823+
743824
/*
744825
* Given a relation name, open and lock the sequence. p_elm and p_rel are
745826
* output parameters.
@@ -748,7 +829,6 @@ static void
748829
init_sequence(RangeVar*relation,SeqTable*p_elm,Relation*p_rel)
749830
{
750831
Oidrelid=RangeVarGetRelid(relation, false);
751-
TransactionIdthisxid=GetTopTransactionId();
752832
volatileSeqTableelm;
753833
Relationseqrel;
754834

@@ -796,35 +876,7 @@ init_sequence(RangeVar *relation, SeqTable *p_elm, Relation *p_rel)
796876
seqtab=elm;
797877
}
798878

799-
/*
800-
* If we haven't touched the sequence already in this transaction,
801-
* we need to acquire AccessShareLock. We arrange for the lock to
802-
* be owned by the top transaction, so that we don't need to do it
803-
* more than once per xact.
804-
*/
805-
if (elm->xid!=thisxid)
806-
{
807-
ResourceOwnercurrentOwner;
808-
809-
currentOwner=CurrentResourceOwner;
810-
PG_TRY();
811-
{
812-
CurrentResourceOwner=TopTransactionResourceOwner;
813-
814-
LockRelation(seqrel,AccessShareLock);
815-
}
816-
PG_CATCH();
817-
{
818-
/* Ensure CurrentResourceOwner is restored on error */
819-
CurrentResourceOwner=currentOwner;
820-
PG_RE_THROW();
821-
}
822-
PG_END_TRY();
823-
CurrentResourceOwner=currentOwner;
824-
825-
/* Flag that we have a lock in the current xact. */
826-
elm->xid=thisxid;
827-
}
879+
acquire_share_lock(seqrel,elm);
828880

829881
*p_elm=elm;
830882
*p_rel=seqrel;

‎src/include/catalog/catversion.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
3838
* Portions Copyright (c) 1994, Regents of the University of California
3939
*
40-
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.272 2005/05/30 20:59:17 momjian Exp $
40+
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.273 2005/06/07 07:08:34 neilc Exp $
4141
*
4242
*-------------------------------------------------------------------------
4343
*/
@@ -53,6 +53,6 @@
5353
*/
5454

5555
/*yyyymmddN */
56-
#defineCATALOG_VERSION_NO200505302
56+
#defineCATALOG_VERSION_NO200506071
5757

5858
#endif

‎src/include/catalog/pg_proc.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.363 2005/05/20 01:29:55 neilc Exp $
10+
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.364 2005/06/07 07:08:34 neilc Exp $
1111
*
1212
* NOTES
1313
* The script catalog/genbki.sh reads this file and generates .bki
@@ -3644,6 +3644,8 @@ DATA(insert OID = 2557 ( bool PGNSP PGUID 12 f f t f i 1 16 "23" _null_ _
36443644
DESCR("convert int4 to boolean");
36453645
DATA(insertOID=2558 (int4PGNSPPGUID12fftfi123"16"_null__null__null_bool_int4-_null_ ));
36463646
DESCR("convert boolean to int4");
3647+
DATA(insertOID=2559 (lastvalPGNSPPGUID12fftfv020""_null__null__null_lastval-_null_ ));
3648+
DESCR("current value from last used sequence");
36473649

36483650

36493651
/*

‎src/include/commands/sequence.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
9-
* $PostgreSQL: pgsql/src/include/commands/sequence.h,v 1.31 2005/06/06 17:01:25 tgl Exp $
9+
* $PostgreSQL: pgsql/src/include/commands/sequence.h,v 1.32 2005/06/07 07:08:35 neilc Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -82,6 +82,7 @@ typedef struct xl_seq_rec
8282

8383
externDatumnextval(PG_FUNCTION_ARGS);
8484
externDatumcurrval(PG_FUNCTION_ARGS);
85+
externDatumlastval(PG_FUNCTION_ARGS);
8586
externDatumsetval(PG_FUNCTION_ARGS);
8687
externDatumsetval_and_iscalled(PG_FUNCTION_ARGS);
8788

‎src/test/regress/expected/sequence.out

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,62 @@ COMMENT ON SEQUENCE asdf IS 'won''t work';
7676
ERROR: relation "asdf" does not exist
7777
COMMENT ON SEQUENCE sequence_test2 IS 'will work';
7878
COMMENT ON SEQUENCE sequence_test2 IS NULL;
79+
-- Test lastval()
80+
CREATE SEQUENCE seq;
81+
SELECT nextval('seq');
82+
nextval
83+
---------
84+
1
85+
(1 row)
86+
87+
SELECT lastval();
88+
lastval
89+
---------
90+
1
91+
(1 row)
92+
93+
SELECT setval('seq', 99);
94+
setval
95+
--------
96+
99
97+
(1 row)
98+
99+
SELECT lastval();
100+
lastval
101+
---------
102+
99
103+
(1 row)
104+
105+
CREATE SEQUENCE seq2;
106+
SELECT nextval('seq2');
107+
nextval
108+
---------
109+
1
110+
(1 row)
111+
112+
SELECT lastval();
113+
lastval
114+
---------
115+
1
116+
(1 row)
117+
118+
DROP SEQUENCE seq2;
119+
-- should fail
120+
SELECT lastval();
121+
ERROR: lastval is not yet defined in this session
122+
CREATE USER seq_user;
123+
BEGIN;
124+
SET LOCAL SESSION AUTHORIZATION seq_user;
125+
CREATE SEQUENCE seq3;
126+
SELECT nextval('seq3');
127+
nextval
128+
---------
129+
1
130+
(1 row)
131+
132+
REVOKE ALL ON seq3 FROM seq_user;
133+
SELECT lastval();
134+
ERROR: permission denied for sequence seq3
135+
ROLLBACK;
136+
DROP USER seq_user;
137+
DROP SEQUENCE seq;

‎src/test/regress/sql/sequence.sql

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,30 @@ COMMENT ON SEQUENCE asdf IS 'won''t work';
4242
COMMENT ON SEQUENCE sequence_test2 IS'will work';
4343
COMMENT ON SEQUENCE sequence_test2 ISNULL;
4444

45+
-- Test lastval()
46+
CREATESEQUENCEseq;
47+
SELECT nextval('seq');
48+
SELECT lastval();
49+
SELECT setval('seq',99);
50+
SELECT lastval();
51+
52+
CREATESEQUENCEseq2;
53+
SELECT nextval('seq2');
54+
SELECT lastval();
55+
56+
DROPSEQUENCE seq2;
57+
-- should fail
58+
SELECT lastval();
59+
60+
CREATEUSERseq_user;
61+
62+
BEGIN;
63+
SET LOCAL SESSION AUTHORIZATION seq_user;
64+
CREATESEQUENCEseq3;
65+
SELECT nextval('seq3');
66+
REVOKE ALLON seq3FROM seq_user;
67+
SELECT lastval();
68+
ROLLBACK;
69+
70+
DROPUSER seq_user;
71+
DROPSEQUENCE seq;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp