IF (NOT) EXISTS in psql-completion

From: Kyotaro HORIGUCHI <horiguchi(dot)kyotaro(at)lab(dot)ntt(dot)co(dot)jp>
To: pgsql-hackers(at)postgresql(dot)org
Subject: IF (NOT) EXISTS in psql-completion
Date: 2016-02-05 08:09:01
Message-ID: 20160205.170901.60679714.horiguchi.kyotaro@lab.ntt.co.jp
Views: Raw Message | Whole Thread | Download mbox
Lists: pgsql-hackers


I considered how to make tab-completion robust for syntactical
noises, in other words, optional words in syntax. Typically "IF
(NOT) EXISTS", UNIQUE and TEMPORARY are words that don't affect
further completion. However, the current delimit-matching
mechanism is not so capable (or is complexty-prone) to live with
such noises. I have proposed to use regular expressions or
simplified one for the robustness but it was too complex to be

This is another answer for the problem. Removal of such words
on-the-fly makes further matching more robust.

Next, currently some CREATE xxx subsyntaxes of CREATE SCHEMA are
matched using TailMatching but it makes difficult the
options-removal operations, which needs forward matching.

So I introduced two things to resolve them by this patch.

1. HEAD_SHIFT macro

It shifts the beginning index in previous_words for *MatchN
macros. When the varialbe is 3 and previous_words is as


Match3("CONCURRENTLY", "IF", "NOT") reutrns true. HeadMatches
and TailMatches works on the same basis. This allows us to
match "CREATE xxx" subsyntaxes of CREATE SCHEMA
independently. SHIFT_TO_LAST1() macro finds the last appearance
of specified word and HEAD_SHIFT to there if found.

2. MidMatchAndRemoveN() macros

These macros remove specified words starts from specfied number
of words after the current beginning. Having head_shift = 0 and
the following previous_words,

{"i_t1_a", "EXISTS", "IF", "INDEX", "DROP"}

MidMatchAndRemove2(2, "IF", "EXISTS") leaves the following

{"i_t1_a", "INDEX", "DROP"}

Using these things, the patch as whole does the following things.

A. Allows "IF (NOT) EXISTS" at almost everywhere it allowed

The boilerplate is like the following,

| else if (MatchesN(words before IF EXISTS))
| else if (HeadMatchesN(words before "IF EXISTS") &&
| MidMatchAndRemoveM(N, words to be removed) &&
| MatchesN(words before "IF EXISTS"))

The first "else if" makes suggestion for the 'thing' with "IF

The MidMatchAndRemoveM in the second "else if" actually
removes "IF EXISTS" if match and the third MatchesN or all
matching macros ever after don't see the removed words. So
they can make a suggestion without seeing such noises.

This looks a bit hackery but works well in the current

B. Masks the part in CREATE SCHEMA unrelated to the last CREATE
subsyntax currently focused on.

| else if (HeadMatches2("CREATE", "SCHEMA") &&
| false) {} /* FALL THROUGH */

The result of this, for the query like this,

CREATE SCHEMA foo bar baz CREATE foe fee CREATE hoge hage

all the following part of psql_completion works as if the
current query is just "CREATE hoge hage".

Does anybody have suggestions, opinions or objections?


Kyotaro Horiguchi
NTT Open Source Software Center

Attachment Content-Type Size
0001-Suggest-IF-NOT-EXISTS-for-tab-completion-of-psql.patch text/x-patch 40.3 KB


Browse pgsql-hackers by date

  From Date Subject
Next Message pokurev 2016-02-05 08:15:58 Re: [PROPOSAL] VACUUM Progress Checker.
Previous Message Kyotaro HORIGUCHI 2016-02-05 07:40:21 Re: Support for N synchronous standby servers - take 2