Hi Srinath
On 23.07.25 09:03, Srinath Reddy Sadipiralla wrote:
> +1 for the patch,i have reviewed and tested this patch, except these
> below cosmetic changes it LGTM.
>
> cosmetic changes:
> 1) add comment about %i in get_prompt api.
Done.
> 2) maybe we can use read-write instead of read/write to be consistent
> with the
> naming such as options of target_session_attrs uses read-write.
I believe that 'read/write' is more idiomatic than 'read-write' in this
context. 'Read-only' works as a hyphenated adjective, and 'read/write'
is typically treated as a paired label that indicates two distinct
capabilities --- read and write. What do you think?
v3 attached.
Thanks for the thorough testing and review!
Best, Jim
From 260d23ca92d5c31dc717cca4fd05b760e0069142 Mon Sep 17 00:00:00 2001
From: Jim Jones <jim.jo...@uni-muenster.de>
Date: Wed, 23 Jul 2025 09:35:15 +0200
Subject: [PATCH v3] 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 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 | 16 ++++++++++++++++
2 files changed, 30 insertions(+)
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index 4f7b11175c..c8e1449766 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -5008,6 +5008,20 @@ testdb=> <userinput>INSERT INTO my_table VALUES (:'content');</userinput>
</listitem>
</varlistentry>
+ <varlistentry id="app-psql-prompting-i">
+ <term><literal>%i</literal></term>
+ <listitem>
+ <para>
+ Displays the session's read-only status as <literal>read-only</literal>
+ if the server is in hot standby (<literal>in_hot_standby</literal> is
+ <literal>on</literal>) or the default transaction mode is read-only
+ (<literal>default_transaction_read_only</literal> is <literal>on</literal>),
+ or <literal>read-write</literal> otherwise. Useful for identifying
+ sessions that cannot perform writes, such as in replication setups.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry id="app-psql-prompting-x">
<term><literal>%x</literal></term>
<listitem>
diff --git a/src/bin/psql/prompt.c b/src/bin/psql/prompt.c
index b08d7328fb..1d0eca5cfc 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,21 @@ 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 && strcmp(hs, "on") == 0) ||
+ (ro && 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