From 1323e4b555fbd63796a759d0b6741b8258ad88eb Mon Sep 17 00:00:00 2001 From: Jim Jones Date: Mon, 27 Oct 2025 08:36:48 +0100 Subject: [PATCH v5] Add %i prompt escape to indicate server read-only status This patch introduces a new prompt escape `%i` for psql, which shows whether the connected server is operating in read-only or read/write mode. It expands to `read-only` if either the server is in hot standby mode (`in_hot_standby = on`) or the session's default transaction mode is read-only (`default_transaction_read_only = on`). Otherwise, it displays `read/write`. This is useful for distinguishing read-only sessions (e.g. connected to a standby, or using a default read-only transaction mode) from read/write ones at a glance, especially when working with multiple connections in replicated or restricted environments. --- doc/src/sgml/ref/psql-ref.sgml | 14 ++++++++++++++ src/bin/psql/prompt.c | 17 +++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml index 1a339600bc..662dfb2ed5 100644 --- a/doc/src/sgml/ref/psql-ref.sgml +++ b/doc/src/sgml/ref/psql-ref.sgml @@ -5044,6 +5044,20 @@ testdb=> INSERT INTO my_table VALUES (:'content'); + + %i + + + Displays the session's read-only status as read-only + if the server is in hot standby (in_hot_standby is + on) or the default transaction mode is read-only + (default_transaction_read_only is on), + or read-write otherwise. Useful for identifying + sessions that cannot perform writes, such as in replication setups. + + + + %x diff --git a/src/bin/psql/prompt.c b/src/bin/psql/prompt.c index b08d7328fb..fdcb779d43 100644 --- a/src/bin/psql/prompt.c +++ b/src/bin/psql/prompt.c @@ -43,6 +43,8 @@ * or a ! if session is not connected to a database; * in prompt2 -, *, ', or "; * in prompt3 nothing + * %i - displays "read-only" if in hot standby or default_transaction_read_only + * is on, "read/write" otherwise. * %x - transaction status: empty, *, !, ? (unknown or no connection) * %l - The line number inside the current statement, starting from 1. * %? - the error code of the last query (not yet implemented) @@ -247,7 +249,22 @@ get_prompt(promptStatus_t status, ConditionalStack cstack) break; } break; + case 'i': + if (pset.db) + { + const char *hs = PQparameterStatus(pset.db, "in_hot_standby"); + const char *ro = PQparameterStatus(pset.db, "default_transaction_read_only"); + if (!hs || !ro) + strlcpy(buf, _("unknown"), sizeof(buf)); + else if (strcmp(hs, "on") == 0 || strcmp(ro, "on") == 0) + strlcpy(buf, "read-only", sizeof(buf)); + else + strlcpy(buf, "read/write", sizeof(buf)); + } + else + buf[0] = '\0'; + break; case 'x': if (!pset.db) buf[0] = '?'; -- 2.43.0