IF (NOT) EXISTS in psql-completion - Mailing list pgsql-hackers

From Kyotaro HORIGUCHI
Subject IF (NOT) EXISTS in psql-completion
Date
Msg-id 20160205.170901.60679714.horiguchi.kyotaro@lab.ntt.co.jp
Whole thread Raw
Responses Re: IF (NOT) EXISTS in psql-completion
Re: IF (NOT) EXISTS in psql-completion
List pgsql-hackers
Hello,

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

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
following,
 {"NOT", "IF", "CONCURRENTLY", "INDEX", "UNIQUE", "CREATE"}
 Match3("CONCURRENTLY", "IF", "NOT") reutrns true. HeadMatches and TailMatches works on the same basis. This allows us
tomatch "CREATE xxx" subsyntaxes of CREATE SCHEMA independently. SHIFT_TO_LAST1() macro finds the last appearance of
specifiedword 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 previous_words.
 {"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  syntactically.
  The boilerplate is like the following,
  | else if (MatchesN(words before IF EXISTS))  |      COMPLETE_WITH_XXX(... "UNION SELECT 'IF EXISTS'");  | else if
(HeadMatchesN(wordsbefore "IF EXISTS") &&  |          MidMatchAndRemoveM(N, words to be removed) &&  |
MatchesN(wordsbefore "IF EXISTS"))  |      COMPLETE_WITH_XXXX();
 
  The first "else if" makes suggestion for the 'thing' with "IF  EXISTS".
  The MidMatchAndRemoveM in the second "else if" actually  removes "IF EXISTS" if match and the third MatchesN or all
matchingmacros 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  framework.


B. Masks the part in CREATE SCHEMA unrelated to the last CREATE subsyntax currently focused on.
  |    else if (HeadMatches2("CREATE", "SCHEMA") &&  |             SHIFT_TO_LAST1("CREATE") &&  |             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?

regards,

-- 
Kyotaro Horiguchi
NTT Open Source Software Center

pgsql-hackers by date:

Previous
From: Kyotaro HORIGUCHI
Date:
Subject: Re: Support for N synchronous standby servers - take 2
Next
From:
Date:
Subject: Re: [PROPOSAL] VACUUM Progress Checker.