aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNathan Bossart <nathan@postgresql.org>2024-07-31 10:12:42 -0500
committerNathan Bossart <nathan@postgresql.org>2024-07-31 10:12:42 -0500
commitc8b06bb969bf26c01f10b835e59d0aff39b7f516 (patch)
tree1042c5639ec85ca305eb414c6e77efe55487150f /src
parent68e9629985981ce8f8f04b5a9f8b3781eacaafd6 (diff)
downloadpostgresql-c8b06bb969bf26c01f10b835e59d0aff39b7f516.tar.gz
postgresql-c8b06bb969bf26c01f10b835e59d0aff39b7f516.zip
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
Diffstat (limited to 'src')
-rw-r--r--src/backend/commands/sequence.c61
-rw-r--r--src/include/catalog/catversion.h2
-rw-r--r--src/include/catalog/pg_proc.dat6
-rw-r--r--src/test/regress/expected/sequence.out7
-rw-r--r--src/test/regress/sql/sequence.sql3
5 files changed, 78 insertions, 1 deletions
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index 9f28d40466b..8c1131f0202 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -1773,6 +1773,67 @@ 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] = {0};
+ bool isnull[SEQ_COL_LASTCOL] = {0};
+ 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);
+
+ 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/catversion.h b/src/include/catalog/catversion.h
index 2f221b6ad0a..d588daebb46 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -57,6 +57,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 202407252
+#define CATALOG_VERSION_NO 202407311
#endif
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 06b2f4ba66c..54b50ee5d61 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 2b47b7796b1..e749c4574e3 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 674f5f1f668..ea447938aea 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;