display hot standby state in psql prompt

Started by Jim Jones9 months ago52 messages
Jump to latest
#1Jim Jones
jim.jones@uni-muenster.de

Hi,

Some weeks ago we briefly discussed in the discord channel the
possibility of introducing a psql prompt display option to identify if
the connected database is in hot standby mode, which can be useful when
using multiple hosts in the connection string. Right now, it's using the
in_hot_standby value in prompt.c to determine the database state:

case 'i':
    if (pset.db && PQparameterStatus(pset.db, "in_hot_standby"))
    {
        const char *hs = PQparameterStatus(pset.db, "in_hot_standby");
        if (hs && strcmp(hs, "on") == 0)
            strlcpy(buf, "standby", sizeof(buf));
        else
            strlcpy(buf, "primary", sizeof(buf));

.. which could be used like this:

psql (18beta1)
Type "help" for help.

postgres=# \set PROMPT1 '[%i] # '
[standby] # SELECT pg_promote();
 pg_promote
------------
 t
(1 row)

[primary] #

The hardcoded "standby" and "primary" strings are not very flexible, but
I am not sure how to make these strings customisable just yet.

Any thoughts on this feature?

Best regards, Jim

#2Greg Sabino Mullane
greg@turnstep.com
In reply to: Jim Jones (#1)
Re: display hot standby state in psql prompt

On Wed, Jun 25, 2025 at 4:02 AM Jim Jones <jim.jones@uni-muenster.de> wrote:

if (pset.db && PQparameterStatus(pset.db, "in_hot_standby"))

Seems transaction_read_only might be a more useful thing to examine? That's
the side-effect, if you will, that people really care about when in hot
standby mode (and of course, we can get into TRO other ways).

Cheers,
Greg

--
Crunchy Data - https://www.crunchydata.com
Enterprise Postgres Software Products & Tech Support

#3Jim Jones
jim.jones@uni-muenster.de
In reply to: Greg Sabino Mullane (#2)
Re: display hot standby state in psql prompt

Hi Greg

On 25.06.25 17:17, Greg Sabino Mullane wrote:

Seems transaction_read_only might be a more useful thing to examine?
That's the side-effect, if you will, that people really care about
when in hot standby mode (and of course, we can get into TRO other ways).

Good point. But wouldn't it mean that I would need to execute a query
every time the prompt is refreshed? Since I cannot get the value of
transaction_read_only via PQparameterStatus. I like the idea, but I'm
concerned about the overhead.

Best, Jim

#4Greg Sabino Mullane
greg@turnstep.com
In reply to: Jim Jones (#3)
Re: display hot standby state in psql prompt

On Wed, Jun 25, 2025 at 11:50 AM Jim Jones <jim.jones@uni-muenster.de>
wrote:

Since I cannot get the value of transaction_read_only via
PQparameterStatus.

Hmmm... we can at least get default_transaction_read_only. As fe-connect.c
points out:
/*
* "transaction_read_only = on" proves that at least one
* of default_transaction_read_only and in_hot_standby
is
* on, but we don't actually know which. We don't care
* though for the purpose of identifying a read-only
* session, so satisfy the CONNECTION_CHECK_TARGET code
by
* claiming they are both on. On the other hand, if
it's
* a read-write session, they are certainly both off.
*/
Maybe that's good enough? It won't detect people starting a new transaction
and declaring it read-only, but it should be sufficient to warn people when
a connection is starting out in a read-only state. And it will still toggle
auto-magically on promotion.

Cheers,
Greg

--
Crunchy Data - https://www.crunchydata.com
Enterprise Postgres Software Products & Tech Support

#5Jim Jones
jim.jones@uni-muenster.de
In reply to: Greg Sabino Mullane (#4)
Re: display hot standby state in psql prompt

On 26.06.25 02:52, Greg Sabino Mullane wrote:

On Wed, Jun 25, 2025 at 11:50 AM Jim Jones <jim.jones@uni-muenster.de>
wrote:

Since I cannot get the value of transaction_read_only via
PQparameterStatus.

Hmmm... we can at least get default_transaction_read_only. As
fe-connect.c points out:
                    /*
                     * "transaction_read_only = on" proves that at
least one
                     * of default_transaction_read_only and
in_hot_standby is
                     * on, but we don't actually know which.  We don't
care
                     * though for the purpose of identifying a read-only
                     * session, so satisfy the CONNECTION_CHECK_TARGET
code by
                     * claiming they are both on.  On the other hand,
if it's
                     * a read-write session, they are certainly both off.
                     */
Maybe that's good enough? It won't detect people starting a new
transaction and declaring it read-only, but it should be sufficient to
warn people when a connection is starting out in a read-only state.
And it will still toggle auto-magically on promotion.

Combining in_hot_standby and default_transaction_read_only might provide
better coverage for this feature, e.g.

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;

Relying solely on default_transaction_read_onlycould be misleading, as a
database in hot standby mode might be wrongly shown as "read/write".
(draft patch attached)

Some tests:

== default_transaction_read_only set to 'on'

psql (18beta1)
Type "help" for help.

db=# \set PROMPT1 '[%n@%/ %i] '
[jim@db read-only] SHOW default_transaction_read_only ;
 default_transaction_read_only
-------------------------------
 on
(1 row)

[jim@db read-only] SHOW in_hot_standby ;
 in_hot_standby
----------------
 off
(1 row)

[jim@db read-only]

== cluster in hot standby

psql (18beta1)
Type "help" for help.

db=# \set PROMPT1 '[%n@%/ %i] '
[jim@db read-only] SHOW in_hot_standby ;
 in_hot_standby
----------------
 on
(1 row)

[jim@db read-only] SHOW default_transaction_read_only ;
 default_transaction_read_only
-------------------------------
 off
(1 row)

[jim@db read-only] SELECT pg_promote();
 pg_promote
------------
 t
(1 row)

[jim@db read/write]

What do you think?

Thanks!

Best regards, Jim

Attachments:

v1-0001-Add-i-prompt-escape-to-indicate-server-read-only-.patchtext/x-patch; charset=UTF-8; name=v1-0001-Add-i-prompt-escape-to-indicate-server-read-only-.patchDownload+29-1
#6Greg Sabino Mullane
greg@turnstep.com
In reply to: Jim Jones (#5)
Re: display hot standby state in psql prompt

On Thu, Jun 26, 2025 at 3:22 AM Jim Jones <jim.jones@uni-muenster.de> wrote:

What do you think?

Seems good enough for me. I think as long as we document it well, it's only
going to be a net positive, even with some edge cases.

Cheers,
Greg

--
Crunchy Data - https://www.crunchydata.com
Enterprise Postgres Software Products & Tech Support

#7Jim Jones
jim.jones@uni-muenster.de
In reply to: Greg Sabino Mullane (#6)
Re: display hot standby state in psql prompt

Hi

On 21.07.25 21:12, Greg Sabino Mullane wrote:

Seems good enough for me. I think as long as we document it well, it's
only going to be a net positive, even with some edge cases.

I just moved the patch from PG19-Drafts to PG19-2 commitfest.[1]

Thanks a lot for the feedback!

Best regards, Jim

1 - https://commitfest.postgresql.org/patch/5872/

Attachments:

v2-0001-Add-i-prompt-escape-to-indicate-server-read-only-.patchtext/x-patch; charset=UTF-8; name=v2-0001-Add-i-prompt-escape-to-indicate-server-read-only-.patchDownload+28-1
#8Srinath Reddy Sadipiralla
srinath2133@gmail.com
In reply to: Jim Jones (#7)
Re: display hot standby state in psql prompt

Hi Jim,

On Tue, Jul 22, 2025 at 4:40 PM Jim Jones <jim.jones@uni-muenster.de> wrote:

Hi

On 21.07.25 21:12, Greg Sabino Mullane wrote:

Seems good enough for me. I think as long as we document it well, it's
only going to be a net positive, even with some edge cases.

I just moved the patch from PG19-Drafts to PG19-2 commitfest.[1]

Thanks a lot for the feedback!

Best regards, Jim

1 - https://commitfest.postgresql.org/patch/5872/

+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.
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.

testing:

=> in primary node:

psql (19devel)
Type "help" for help.

postgres=# \set PROMPT1 '[%i] # '
[read/write] # set default_transaction_read_only=on;
SET
[read-only] # set default_transaction_read_only=off;
SET
[read/write] # show in_hot_standby ;
in_hot_standby
----------------
off
(1 row)

[read/write] # set default_transaction_read_only=on;
SET
[read-only] # show in_hot_standby ;
in_hot_standby
----------------
off
(1 row)

[read-only] # \q

=> in replica node

psql (19devel)
Type "help" for help.

postgres=# \set PROMPT1 '[%i] # '
[read-only] # show in_hot_standby ;
in_hot_standby
----------------
on
(1 row)

[read-only] # show default_transaction_read_only;
default_transaction_read_only
-------------------------------
off
(1 row)

[read-only] # set default_transaction_read_only=on;
SET
[read-only] # set transaction_read_only=on;
SET
[read-only] # set transaction_read_only=off;
ERROR: cannot set transaction read-write mode during recovery
[read-only] # select pg_promote();
pg_promote
------------
t
(1 row)

[read-only] # show in_hot_standby ;
in_hot_standby
----------------
off
(1 row)

[read-only] # show default_transaction_read_only;
default_transaction_read_only
-------------------------------
on
(1 row)

[read-only] # set default_transaction_read_only=off;
SET
[read/write] #

--
Thanks,
Srinath Reddy Sadipiralla
EDB: https://www.enterprisedb.com/

#9Jim Jones
jim.jones@uni-muenster.de
In reply to: Srinath Reddy Sadipiralla (#8)
Re: display hot standby state in psql prompt

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

Attachments:

v3-0001-Add-i-prompt-escape-to-indicate-server-read-only-.patchtext/x-patch; charset=UTF-8; name=v3-0001-Add-i-prompt-escape-to-indicate-server-read-only-.patchDownload+30-1
#10Srinath Reddy Sadipiralla
srinath2133@gmail.com
In reply to: Jim Jones (#9)
Re: display hot standby state in psql prompt

On Wed, Jul 23, 2025 at 1:33 PM Jim Jones <jim.jones@uni-muenster.de> wrote:

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?

Makes sense.

--
Thanks,
Srinath Reddy Sadipiralla
EDB: https://www.enterprisedb.com/

#11Nathan Bossart
nathandbossart@gmail.com
In reply to: Jim Jones (#9)
Re: display hot standby state in psql prompt

On Wed, Jul 23, 2025 at 10:03:54AM +0200, Jim Jones wrote:

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?

My first thought when looking at this thread/patch was that something like
"read-write" might be a bit long for a psql prompt. I probably would've
chosen something like "r" or "ro" for read-only and "rw" for read-write. I
suppose you could argue that those are more difficult to see, and this
seems particularly useful when you want to be sure that you won't
inadvertently write any data.

--
nathan

#12Jim Jones
jim.jones@uni-muenster.de
In reply to: Nathan Bossart (#11)
Re: display hot standby state in psql prompt

Hi Nathan

On 23/10/2025 23:02, Nathan Bossart wrote:

My first thought when looking at this thread/patch was that something like
"read-write" might be a bit long for a psql prompt. I probably would've
chosen something like "r" or "ro" for read-only and "rw" for read-write. I
suppose you could argue that those are more difficult to see, and this
seems particularly useful when you want to be sure that you won't
inadvertently write any data.

I can see the appeal of keeping the indicator as short as possible in a
prompt, but that can also make it a bit harder to quickly distinguish
between the read/write and read-only states. In this case, clarity might
be more important than compactness. Then again, the traditional shell
prompt symbols ($, #) aren't exactly self-explanatory either, and people
seem fine with those :)

Although I prefer it being explicit in this case, I can live with either
approach. Do you think we should go for "ro" or "rw"?

Thanks for the review!

Best, Jim

#13Nathan Bossart
nathandbossart@gmail.com
In reply to: Jim Jones (#12)
Re: display hot standby state in psql prompt

On Fri, Oct 24, 2025 at 01:07:41AM +0200, Jim Jones wrote:

Although I prefer it being explicit in this case, I can live with either
approach. Do you think we should go for "ro" or "rw"?

I'm currently leaning towards ro/rw, but I'm also hoping that others chime
in with opinions here.

--
nathan

#14Greg Sabino Mullane
greg@turnstep.com
In reply to: Nathan Bossart (#13)
Re: display hot standby state in psql prompt

On Fri, Oct 24, 2025 at 10:12 AM Nathan Bossart <nathandbossart@gmail.com>
wrote:

I'm currently leaning towards ro/rw, but I'm also hoping that others chime
in with opinions here.

-1. Too short, too cryptic, too similar. I know our existing symbols aren't
great either, but we can do better.

Cheers,
Greg

--
Crunchy Data - https://www.crunchydata.com
Enterprise Postgres Software Products & Tech Support

#15Nathan Bossart
nathandbossart@gmail.com
In reply to: Greg Sabino Mullane (#14)
Re: display hot standby state in psql prompt

On Fri, Oct 24, 2025 at 10:54:57AM -0400, Greg Sabino Mullane wrote:

On Fri, Oct 24, 2025 at 10:12 AM Nathan Bossart <nathandbossart@gmail.com>
wrote:

I'm currently leaning towards ro/rw, but I'm also hoping that others chime
in with opinions here.

-1. Too short, too cryptic, too similar. I know our existing symbols aren't
great either, but we can do better.

What would you prefer instead?

--
nathan

#16Greg Sabino Mullane
greg@turnstep.com
In reply to: Nathan Bossart (#15)
Re: display hot standby state in psql prompt

*shrug* I still like the earlier versions:

read-only
read/write

#17Srinath Reddy Sadipiralla
srinath2133@gmail.com
In reply to: Greg Sabino Mullane (#16)
Re: display hot standby state in psql prompt

On Fri, Oct 24, 2025 at 8:36 PM Greg Sabino Mullane <htamfids@gmail.com>
wrote:

read-only
read/write

+1

--
Thanks,
Srinath Reddy Sadipiralla
EDB: https://www.enterprisedb.com/

#18Fujii Masao
masao.fujii@gmail.com
In reply to: Jim Jones (#9)
Re: display hot standby state in psql prompt

On Wed, Jul 23, 2025 at 5:04 PM Jim Jones <jim.jones@uni-muenster.de> wrote:

v3 attached.

+ const char *hs = PQparameterStatus(pset.db, "in_hot_standby");
+ const char *ro = PQparameterStatus(pset.db, "default_transaction_read_only");

When either hs or ro is NULL, the displayed status can be incorrect.
For example, connecting to a standby server running PostgreSQL 10
incorrectly shows "read/write". In such cases, wouldn't it be clearer
to display something like "unknown", similar to how the "Hot Standby"
column in \conninfo reports "unknown"?

Regards,

--
Fujii Masao

#19Jim Jones
jim.jones@uni-muenster.de
In reply to: Fujii Masao (#18)
Re: display hot standby state in psql prompt

On 24/10/2025 17:21, Fujii Masao wrote:

+ const char *hs = PQparameterStatus(pset.db, "in_hot_standby");
+ const char *ro = PQparameterStatus(pset.db, "default_transaction_read_only");

When either hs or ro is NULL, the displayed status can be incorrect.
For example, connecting to a standby server running PostgreSQL 10
incorrectly shows "read/write". In such cases, wouldn't it be clearer
to display something like "unknown", similar to how the "Hot Standby"
column in \conninfo reports "unknown"?

Oh, it didn't occur to me to test this edge case. Thanks for the hint!

Would this be what you have in mind?

if (!hs || !ro)
strlcpy(buf, "unknown", sizeof(buf));
else if ((hs && strcmp(hs, "on") == 0) ||
(ro && strcmp(ro, "on") == 0))
strlcpy(buf, "read-only", sizeof(buf));
else
strlcpy(buf, "read/write", sizeof(buf));

Best, Jim

#20Jim Jones
jim.jones@uni-muenster.de
In reply to: Jim Jones (#19)
Re: display hot standby state in psql prompt

On 24/10/2025 18:13, Jim Jones wrote:

On 24/10/2025 17:21, Fujii Masao wrote:

+ const char *hs = PQparameterStatus(pset.db, "in_hot_standby");
+ const char *ro = PQparameterStatus(pset.db, "default_transaction_read_only");

When either hs or ro is NULL, the displayed status can be incorrect.
For example, connecting to a standby server running PostgreSQL 10
incorrectly shows "read/write". In such cases, wouldn't it be clearer
to display something like "unknown", similar to how the "Hot Standby"
column in \conninfo reports "unknown"?

Oh, it didn't occur to me to test this edge case. Thanks for the hint!

Would this be what you have in mind?

if (!hs || !ro)
strlcpy(buf, "unknown", sizeof(buf));
else if ((hs && strcmp(hs, "on") == 0) ||
(ro && strcmp(ro, "on") == 0))
strlcpy(buf, "read-only", sizeof(buf));
else
strlcpy(buf, "read/write", sizeof(buf));

I just realised I forgot to attach the patch. Sorry about that!
PFA v4.

Best, Jim

Attachments:

v4-0001-Add-i-prompt-escape-to-indicate-server-read-only-.patchtext/x-patch; charset=UTF-8; name=v4-0001-Add-i-prompt-escape-to-indicate-server-read-only-.patchDownload+33-2
#21Fujii Masao
masao.fujii@gmail.com
In reply to: Jim Jones (#19)
#22Jim Jones
jim.jones@uni-muenster.de
In reply to: Fujii Masao (#21)
#23Nathan Bossart
nathandbossart@gmail.com
In reply to: Srinath Reddy Sadipiralla (#17)
#24Nathan Bossart
nathandbossart@gmail.com
In reply to: Jim Jones (#22)
#25Jim Jones
jim.jones@uni-muenster.de
In reply to: Nathan Bossart (#24)
#26Nathan Bossart
nathandbossart@gmail.com
In reply to: Jim Jones (#25)
#27Fujii Masao
masao.fujii@gmail.com
In reply to: Nathan Bossart (#26)
#28Jim Jones
jim.jones@uni-muenster.de
In reply to: Fujii Masao (#27)
#29Nathan Bossart
nathandbossart@gmail.com
In reply to: Jim Jones (#28)
#30Jim Jones
jim.jones@uni-muenster.de
In reply to: Nathan Bossart (#29)
#31Fujii Masao
masao.fujii@gmail.com
In reply to: Jim Jones (#28)
#32Chao Li
li.evan.chao@gmail.com
In reply to: Fujii Masao (#31)
#33Jim Jones
jim.jones@uni-muenster.de
In reply to: Chao Li (#32)
#34Jim Jones
jim.jones@uni-muenster.de
In reply to: Nathan Bossart (#29)
#35Chao Li
li.evan.chao@gmail.com
In reply to: Jim Jones (#33)
#36Jim Jones
jim.jones@uni-muenster.de
In reply to: Chao Li (#35)
#37Chao Li
li.evan.chao@gmail.com
In reply to: Jim Jones (#36)
#38Jim Jones
jim.jones@uni-muenster.de
In reply to: Jim Jones (#34)
#39Andreas Karlsson
andreas.karlsson@percona.com
In reply to: Jim Jones (#38)
#40Jim Jones
jim.jones@uni-muenster.de
In reply to: Andreas Karlsson (#39)
#41Fujii Masao
masao.fujii@gmail.com
In reply to: Jim Jones (#40)
#42Jim Jones
jim.jones@uni-muenster.de
In reply to: Fujii Masao (#41)
#43Fujii Masao
masao.fujii@gmail.com
In reply to: Jim Jones (#42)
#44Jim Jones
jim.jones@uni-muenster.de
In reply to: Fujii Masao (#43)
#45Fujii Masao
masao.fujii@gmail.com
In reply to: Jim Jones (#44)
#46Jim Jones
jim.jones@uni-muenster.de
In reply to: Fujii Masao (#45)
#47Fujii Masao
masao.fujii@gmail.com
In reply to: Jim Jones (#46)
#48Jim Jones
jim.jones@uni-muenster.de
In reply to: Fujii Masao (#47)
#49Chao Li
li.evan.chao@gmail.com
In reply to: Jim Jones (#48)
#50Fujii Masao
masao.fujii@gmail.com
In reply to: Chao Li (#49)
#51Jim Jones
jim.jones@uni-muenster.de
In reply to: Fujii Masao (#50)
#52Fujii Masao
masao.fujii@gmail.com
In reply to: Jim Jones (#51)