diff --git a/doc/src/sgml/system-views.sgml b/doc/src/sgml/system-views.sgml
index 5f8b99bf69..a272068782 100644
--- a/doc/src/sgml/system-views.sgml
+++ b/doc/src/sgml/system-views.sgml
@@ -2927,15 +2927,36 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx
The last sequence value written to disk. If caching is used,
this value can be greater than the last value handed out from the
- sequence. Null if the sequence has not been read from yet. Also, if
- the current user does not have USAGE
- or SELECT privilege on the sequence, the value is
- null.
+ sequence.
+
+
+ The last_value column will read as null if any of
+ the following are true:
+
+
+
+ The sequence has not been read from yet.
+
+
+
+
+ The current user does not have USAGE or
+ SELECT privilege on the sequence.
+
+
+
+
+ The sequence is unlogged and the server is a standby.
+
+
+
+
+
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index acaf660c68..1a73a63d61 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -1810,11 +1810,8 @@ pg_sequence_last_value(PG_FUNCTION_ARGS)
Oid relid = PG_GETARG_OID(0);
SeqTable elm;
Relation seqrel;
- Buffer buf;
- HeapTupleData seqtuple;
- Form_pg_sequence_data seq;
- bool is_called;
- int64 result;
+ bool is_called = false;
+ int64 result = 0;
/* open and lock sequence */
init_sequence(relid, &elm, &seqrel);
@@ -1825,12 +1822,28 @@ pg_sequence_last_value(PG_FUNCTION_ARGS)
errmsg("permission denied for sequence %s",
RelationGetRelationName(seqrel))));
- seq = read_seq_tuple(seqrel, &buf, &seqtuple);
+ /*
+ * We return NULL for other sessions' temporary sequences. The
+ * pg_sequences system view already filters those out, but this offers a
+ * defense against ERRORs in case someone invokes this function directly.
+ *
+ * Also, for the benefit of the pg_sequences view, we return NULL for
+ * unlogged sequences on standbys instead of throwing an error.
+ */
+ if (!RELATION_IS_OTHER_TEMP(seqrel) &&
+ (RelationIsPermanent(seqrel) || !RecoveryInProgress()))
+ {
+ Buffer buf;
+ HeapTupleData seqtuple;
+ Form_pg_sequence_data seq;
- is_called = seq->is_called;
- result = seq->last_value;
+ seq = read_seq_tuple(seqrel, &buf, &seqtuple);
- UnlockReleaseBuffer(buf);
+ is_called = seq->is_called;
+ result = seq->last_value;
+
+ UnlockReleaseBuffer(buf);
+ }
relation_close(seqrel, NoLock);
if (is_called)
diff --git a/src/test/recovery/t/001_stream_rep.pl b/src/test/recovery/t/001_stream_rep.pl
index 86864098f9..54c3d3bdf5 100644
--- a/src/test/recovery/t/001_stream_rep.pl
+++ b/src/test/recovery/t/001_stream_rep.pl
@@ -78,6 +78,15 @@ $result = $node_standby_2->safe_psql('postgres', "SELECT * FROM seq1");
print "standby 2: $result\n";
is($result, qq(33|0|t), 'check streamed sequence content on standby 2');
+# Check pg_sequence_last_value() returns NULL for unlogged sequence on standby
+$node_primary->safe_psql('postgres',
+ "CREATE UNLOGGED SEQUENCE ulseq; SELECT nextval('ulseq')");
+$primary_lsn = $node_primary->lsn('write');
+$node_primary->wait_for_catchup($node_standby_1, 'replay', $primary_lsn);
+is($node_standby_1->safe_psql('postgres',
+ "SELECT pg_sequence_last_value('ulseq'::regclass) IS NULL"),
+ 't', 'pg_sequence_last_value() on unlogged sequence on standby 1');
+
# Check that only READ-only queries can run on standbys
is($node_standby_1->psql('postgres', 'INSERT INTO tab_int VALUES (1)'),
3, 'read-only queries on standby 1');