From e83ca9e2312e31ccf4430e8fd24744eff3d6fe75 Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Wed, 17 Jul 2024 17:09:03 -0500 Subject: [PATCH v6 3/4] introduce pg_sequence_read_tuple XXX: NEEDS CATVERSION BUMP --- src/backend/commands/sequence.c | 62 ++++++++++++++++++++++++++ src/include/catalog/pg_proc.dat | 6 +++ src/test/regress/expected/sequence.out | 7 +++ src/test/regress/sql/sequence.sql | 3 ++ 4 files changed, 78 insertions(+) diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c index 9f28d40466..364097c457 100644 --- a/src/backend/commands/sequence.c +++ b/src/backend/commands/sequence.c @@ -1773,6 +1773,68 @@ pg_sequence_parameters(PG_FUNCTION_ARGS) return HeapTupleGetDatum(heap_form_tuple(tupdesc, values, isnull)); } + +/* + * Return the sequence tuple. + * + * This is primarily intended for use by pg_dump to gather sequence data + * without needing to individually query each sequence relation. + */ +Datum +pg_sequence_read_tuple(PG_FUNCTION_ARGS) +{ + Oid relid = PG_GETARG_OID(0); + SeqTable elm; + Relation seqrel; + Datum values[SEQ_COL_LASTCOL]; + bool isnull[SEQ_COL_LASTCOL]; + TupleDesc resultTupleDesc; + HeapTuple resultHeapTuple; + Datum result; + + resultTupleDesc = CreateTemplateTupleDesc(SEQ_COL_LASTCOL); + TupleDescInitEntry(resultTupleDesc, (AttrNumber) 1, "last_value", + INT8OID, -1, 0); + TupleDescInitEntry(resultTupleDesc, (AttrNumber) 2, "log_cnt", + INT8OID, -1, 0); + TupleDescInitEntry(resultTupleDesc, (AttrNumber) 3, "is_called", + BOOLOID, -1, 0); + resultTupleDesc = BlessTupleDesc(resultTupleDesc); + + init_sequence(relid, &elm, &seqrel); + + /* + * Return all NULLs for sequences for which we lack privileges, other + * sessions' temporary sequences, and unlogged sequences on standbys. + */ + if (pg_class_aclcheck(relid, GetUserId(), ACL_SELECT) == ACLCHECK_OK && + !RELATION_IS_OTHER_TEMP(seqrel) && + (RelationIsPermanent(seqrel) || !RecoveryInProgress())) + { + Buffer buf; + HeapTupleData seqtuple; + Form_pg_sequence_data seq; + + seq = read_seq_tuple(seqrel, &buf, &seqtuple); + + memset(isnull, false, sizeof(isnull)); + values[0] = Int64GetDatum(seq->last_value); + values[1] = Int64GetDatum(seq->log_cnt); + values[2] = BoolGetDatum(seq->is_called); + + UnlockReleaseBuffer(buf); + } + else + memset(isnull, true, sizeof(isnull)); + + sequence_close(seqrel, NoLock); + + resultHeapTuple = heap_form_tuple(resultTupleDesc, values, isnull); + result = HeapTupleGetDatum(resultHeapTuple); + PG_RETURN_DATUM(result); +} + + /* * Return the last value from the sequence * diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 73d9cf8582..a16aec302e 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -3329,6 +3329,12 @@ proname => 'pg_sequence_last_value', provolatile => 'v', proparallel => 'u', prorettype => 'int8', proargtypes => 'regclass', prosrc => 'pg_sequence_last_value' }, +{ oid => '9876', descr => 'return sequence tuple, for use by pg_dump', + proname => 'pg_sequence_read_tuple', provolatile => 'v', proparallel => 'u', + prorettype => 'record', proargtypes => 'regclass', + proallargtypes => '{regclass,int8,int8,bool}', proargmodes => '{i,o,o,o}', + proargnames => '{sequence_oid,last_value,log_cnt,is_called}', + prosrc => 'pg_sequence_read_tuple' }, { oid => '275', descr => 'return the next oid for a system table', proname => 'pg_nextoid', provolatile => 'v', proparallel => 'u', diff --git a/src/test/regress/expected/sequence.out b/src/test/regress/expected/sequence.out index 2b47b7796b..e749c4574e 100644 --- a/src/test/regress/expected/sequence.out +++ b/src/test/regress/expected/sequence.out @@ -839,4 +839,11 @@ SELECT nextval('test_seq1'); 3 (1 row) +-- pg_sequence_read_tuple +SELECT * FROM pg_sequence_read_tuple('test_seq1'); + last_value | log_cnt | is_called +------------+---------+----------- + 10 | 32 | t +(1 row) + DROP SEQUENCE test_seq1; diff --git a/src/test/regress/sql/sequence.sql b/src/test/regress/sql/sequence.sql index 674f5f1f66..ea447938ae 100644 --- a/src/test/regress/sql/sequence.sql +++ b/src/test/regress/sql/sequence.sql @@ -413,4 +413,7 @@ SELECT nextval('test_seq1'); SELECT nextval('test_seq1'); SELECT nextval('test_seq1'); +-- pg_sequence_read_tuple +SELECT * FROM pg_sequence_read_tuple('test_seq1'); + DROP SEQUENCE test_seq1; -- 2.39.3 (Apple Git-146)