Re: PSQL - improve tab completion for pub/sub options

From: solai v <solai(dot)cdac(at)gmail(dot)com>
To: Peter Smith <smithpb2250(at)gmail(dot)com>
Cc: Hüseyin Demir <huseyin(dot)d3r(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: PSQL - improve tab completion for pub/sub options
Date: 2026-10-30 05:36:24
Message-ID: CAF0whucL8ZNyN_Y8+z0zREYr=6_JccY775xBavom3bqNiF-6+g@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi all,

On Mon, Oct 26, 2026 at 5:33 PM Peter Smith <smithpb2250(at)gmail(dot)com> wrote:
>
> On Sun, Aug 9, 2026 at 6:55 PM Hüseyin Demir <huseyin(dot)d3r(at)gmail(dot)com> wrote:
> > Hi,
> >
> > Created a v3 and issued the following topics I found.
> >
> > - Fixed typo in CREATE SUBSCRIPTION block: max_rentention_duration →
> > max_retention_duration (was causing the TailMatches check to never
> > fire for that option)
> > - Applied pgindent to clean up indentation in the ALTER PUBLICATION
> > and ALTER SUBSCRIPTION SET blocks (reproduces the same fix pattern
> > identified in v1 review)
>
> Thanks for your review, and catching that typo.
>
> >
> > While reviewing, I noticed you applied the "(*)" idiom to ALTER
> > PUBLICATION/SUBSCRIPTION SET blocks (great fix), but the CREATE
> > PUBLICATION/SUBSCRIPTION blocks still use the seen_with scan. For
> > consistency, the same pattern could be applied there too. What is your
> > opinion about it?
> >
> >
>
> Yeah, IIRC, I already tried to do that but came to grief.
>
> e.g. Compared to ALTER, the CREATE PUBLICATION/SUBSCRIPION has a lot
> more flexibility before the "WITH (", like multiple publication
> clauses or multiple subscribed publications, so I'd need MatchManyN
> for those...
>
> However, MatchAnyN is only supported inside Matches() -- not HeadMatches().
>
> But if we try to use Matches like:
>
> else if (Matches("CREATE", "PUBLICATION", MatchAny, MatchAnyN, "WITH", "(*") &&
> !Matches("CREATE", "PUBLICATION", MatchAny, MatchAnyN, "WITH", "(*)"))
>
> ... then it just doesn't work for the comma "," separators. IIUC it's
> because the comma is another token.
>
> The following response from AI explains it better:
> ------
> "(*" means: one word that starts with (. It matches "(", "(a",
> "(publish", but it only ever matches a single token from
> previous_words[].
>
> That's actually what makes the HeadMatches approach work —
> get_previous_words() groups a completed parenthesized expression into
> one token (e.g. "(publish = insert)"), which matches "(*)" (starts
> with (, ends with )). An uncompleted one like "(" matches "(*" but not
> "(*)". Words typed inside the open parens appear at lower indices and
> don't interfere with the position of the ( token when checked from the
> head.
>
> So the multi-word wildcard you'd need is MatchAnyN (""), which is only
> supported by Matches/MatchesCS — and that's exactly why Matches(...,
> MatchAnyN, "WITH", "(*") breaks after a comma: by the time options are
> typed, previous_words[0] is something like "insert,", not "(".
> ------
>
> So, it's catch-22:
> syntax flexiblity of CREATE means I want MatchAnyN
> --> but MatchAnyN is not compatible with HeadMatches
> --> need to use Matches
> --> but Matches cannot work, because logic needs needs HeadMatches
> ;-(
>
> ~~
>
> I've experimented with other things like:
>
> else if (Matches("CREATE", "PUBLICATION", MatchAny, MatchAnyN, "WITH", "(*") ||
> Matches("CREATE", "PUBLICATION", MatchAny, MatchAnyN, "WITH", "(", MatchAnyN))
>
> ... but, apparently the Matches() logic only recognizes the first MatchAnyN.
>
> To cut a long story short, the only approach that I found that works
> was the `seen_with` scan.
>
> ~~~
>
> PSA v4. It has unchanged content from v3, but restores the original
> commit message of my patch.

Thank you for the updated patch. I tested the tab-completion behaviour
for publication and subscription options and inspected the relevant
completion logic in src/bin/psql/tab-complete.in.c. The completion
suggestions are displayed correctly when the cursor is immediately
after the opening parenthesis. For example: ALTER PUBLICATION test_pub
SET (
However, the suggestions are not displayed when entering subsequent
options after a comma. For example: ALTER PUBLICATION test_pub SET
(publish = 'insert',
I investigated the relevant completion conditions and the
complete_from_list() implementation in src/bin/psql/tab-complete.c.
The current completion logic attempts to handle this case using
text[0] == ','. However, complete_from_list() uses the current text as
a prefix when filtering the completion candidates. Since the prefix is
a comma, it does not match the available option names, and
consequently no suggestions are displayed.
I also checked the WORD_BREAKS definition and observed that the comma
is not currently included in it. Could you please look into this
behaviour and consider an appropriate way to support completion after
commas without affecting other existing psql completion contexts?

Regards
Solai

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Kirill Reshke 2026-10-30 05:44:00 Re: [PG19] pg_upgrade --check passes, then the upgrade fails
Previous Message Bertrand Drouvot 2026-10-30 05:25:12 Re: Report buffer access strategies in EXPLAIN