Skip to content

Commit c8b06bb

Browse files
Introduce pg_sequence_read_tuple().
This new function returns the data for the given sequence, i.e., the values within the sequence tuple. Since this function is a substitute for SELECT from the sequence, the SELECT privilege is required on the sequence in question. It returns all NULLs for sequences for which we lack privileges, other sessions' temporary sequences, and unlogged sequences on standbys. This function is primarily intended for use by pg_dump in a follow-up commit that will use it to optimize dumpSequenceData(). Like pg_sequence_last_value(), which is a support function for the pg_sequences system view, pg_sequence_read_tuple() is left undocumented. Bumps catversion. Reviewed-by: Michael Paquier, Tom Lane Discussion: https://postgr.es/m/20240503025140.GA1227404%40nathanxps13
1 parent 68e9629 commit c8b06bb

File tree

5 files changed

+78
-1
lines changed

5 files changed

+78
-1
lines changed

src/backend/commands/sequence.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1773,6 +1773,67 @@ pg_sequence_parameters(PG_FUNCTION_ARGS)
17731773
return HeapTupleGetDatum(heap_form_tuple(tupdesc, values, isnull));
17741774
}
17751775

1776+
1777+
/*
1778+
* Return the sequence tuple.
1779+
*
1780+
* This is primarily intended for use by pg_dump to gather sequence data
1781+
* without needing to individually query each sequence relation.
1782+
*/
1783+
Datum
1784+
pg_sequence_read_tuple(PG_FUNCTION_ARGS)
1785+
{
1786+
Oid relid = PG_GETARG_OID(0);
1787+
SeqTable elm;
1788+
Relation seqrel;
1789+
Datum values[SEQ_COL_LASTCOL] = {0};
1790+
bool isnull[SEQ_COL_LASTCOL] = {0};
1791+
TupleDesc resultTupleDesc;
1792+
HeapTuple resultHeapTuple;
1793+
Datum result;
1794+
1795+
resultTupleDesc = CreateTemplateTupleDesc(SEQ_COL_LASTCOL);
1796+
TupleDescInitEntry(resultTupleDesc, (AttrNumber) 1, "last_value",
1797+
INT8OID, -1, 0);
1798+
TupleDescInitEntry(resultTupleDesc, (AttrNumber) 2, "log_cnt",
1799+
INT8OID, -1, 0);
1800+
TupleDescInitEntry(resultTupleDesc, (AttrNumber) 3, "is_called",
1801+
BOOLOID, -1, 0);
1802+
resultTupleDesc = BlessTupleDesc(resultTupleDesc);
1803+
1804+
init_sequence(relid, &elm, &seqrel);
1805+
1806+
/*
1807+
* Return all NULLs for sequences for which we lack privileges, other
1808+
* sessions' temporary sequences, and unlogged sequences on standbys.
1809+
*/
1810+
if (pg_class_aclcheck(relid, GetUserId(), ACL_SELECT) == ACLCHECK_OK &&
1811+
!RELATION_IS_OTHER_TEMP(seqrel) &&
1812+
(RelationIsPermanent(seqrel) || !RecoveryInProgress()))
1813+
{
1814+
Buffer buf;
1815+
HeapTupleData seqtuple;
1816+
Form_pg_sequence_data seq;
1817+
1818+
seq = read_seq_tuple(seqrel, &buf, &seqtuple);
1819+
1820+
values[0] = Int64GetDatum(seq->last_value);
1821+
values[1] = Int64GetDatum(seq->log_cnt);
1822+
values[2] = BoolGetDatum(seq->is_called);
1823+
1824+
UnlockReleaseBuffer(buf);
1825+
}
1826+
else
1827+
memset(isnull, true, sizeof(isnull));
1828+
1829+
sequence_close(seqrel, NoLock);
1830+
1831+
resultHeapTuple = heap_form_tuple(resultTupleDesc, values, isnull);
1832+
result = HeapTupleGetDatum(resultHeapTuple);
1833+
PG_RETURN_DATUM(result);
1834+
}
1835+
1836+
17761837
/*
17771838
* Return the last value from the sequence
17781839
*

src/include/catalog/catversion.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,6 @@
5757
*/
5858

5959
/* yyyymmddN */
60-
#define CATALOG_VERSION_NO 202407252
60+
#define CATALOG_VERSION_NO 202407311
6161

6262
#endif

src/include/catalog/pg_proc.dat

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3329,6 +3329,12 @@
33293329
proname => 'pg_sequence_last_value', provolatile => 'v', proparallel => 'u',
33303330
prorettype => 'int8', proargtypes => 'regclass',
33313331
prosrc => 'pg_sequence_last_value' },
3332+
{ oid => '9876', descr => 'return sequence tuple, for use by pg_dump',
3333+
proname => 'pg_sequence_read_tuple', provolatile => 'v', proparallel => 'u',
3334+
prorettype => 'record', proargtypes => 'regclass',
3335+
proallargtypes => '{regclass,int8,int8,bool}', proargmodes => '{i,o,o,o}',
3336+
proargnames => '{sequence_oid,last_value,log_cnt,is_called}',
3337+
prosrc => 'pg_sequence_read_tuple' },
33323338

33333339
{ oid => '275', descr => 'return the next oid for a system table',
33343340
proname => 'pg_nextoid', provolatile => 'v', proparallel => 'u',

src/test/regress/expected/sequence.out

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -839,4 +839,11 @@ SELECT nextval('test_seq1');
839839
3
840840
(1 row)
841841

842+
-- pg_sequence_read_tuple
843+
SELECT * FROM pg_sequence_read_tuple('test_seq1');
844+
last_value | log_cnt | is_called
845+
------------+---------+-----------
846+
10 | 32 | t
847+
(1 row)
848+
842849
DROP SEQUENCE test_seq1;

src/test/regress/sql/sequence.sql

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,4 +413,7 @@ SELECT nextval('test_seq1');
413413
SELECT nextval('test_seq1');
414414
SELECT nextval('test_seq1');
415415

416+
-- pg_sequence_read_tuple
417+
SELECT * FROM pg_sequence_read_tuple('test_seq1');
418+
416419
DROP SEQUENCE test_seq1;

0 commit comments

Comments
 (0)