Re: tab-completion debug print - Mailing list pgsql-hackers

From Kyotaro HORIGUCHI
Subject Re: tab-completion debug print
Date
Msg-id 20181213.200739.07969126.horiguchi.kyotaro@lab.ntt.co.jp
Whole thread Raw
In response to Re: tab-completion debug print  (Kyotaro HORIGUCHI <horiguchi.kyotaro@lab.ntt.co.jp>)
Responses Re: tab-completion debug print
List pgsql-hackers
Hello.

At Wed, 28 Nov 2018 17:28:39 +0900 (Tokyo Standard Time), Kyotaro HORIGUCHI <horiguchi.kyotaro@lab.ntt.co.jp> wrote in
<20181128.172839.242071562.horiguchi.kyotaro@lab.ntt.co.jp>
> I'm not sure how much it is wanted but it's easy to do.  Using
> psql variable doesn't seem to make sense since the debug print
> (currently) requires session log file, which can be turned on
> only at the startup time. '-g' option is available by 0003.
> 
> $ psql -gL ~/psql.log  postgres 
> 
> > Can we conceive of a circumstance where the check for -L/\L would be
> > significant?  I've seen people type pretty quickly, but not thus far
> > fast enough to notice a cache miss.
> 
> We could switch completion_matches body as necessity using
> function poniter, but we aren't so eager for speed here. It is at
> most called every time entering tab.

So, the new version v6 patch consists of the following two files:

- v6-0001-Tab-copletion-debug-log.patch

  Full-context version. Activated by -DTABCOMPLETION_DEBUG at
  compile time and always emit logs into session log file
  specified -L. The format of a line looks like below.

> tab-complete.c:1870: (...table t1 alter [CO]) -> ("CO", "COLUMN", "CONSTRAINT")


- v6-0002-Add-psql-g-option-to-control-debug-print.patch

  Applies on top of 0001. Code is always active, -g addition to
  -L activates debug print into the log file. If only -g is
  specified it is forcibly turned off.

  > $ psql postgres -g
  > psql: no session log file, turn off debug print
  > psql (12devel)
  > Type "help" for help.

  -g option shows in help message. (perhaps arguable.)

I'll register this to the next CF.

regards.

-- 
Kyotaro Horiguchi
NTT Open Source Software Center
From ab5f2b27a13ee6fd19e0c496748d1b0d299e86d6 Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <horiguchi.kyotaro@lab.ntt.co.jp>
Date: Tue, 27 Nov 2018 14:57:46 +0900
Subject: [PATCH 1/2] Tab-copletion debug log

With this patch, psql built with TABCOMPLETION_DEBUG defined emits
tab-completion debug log into the file specified -L option.
---
 src/bin/psql/tab-complete.c | 82 +++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 75 insertions(+), 7 deletions(-)

diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index fa44b2820b..8addca60a6 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -60,6 +60,67 @@ extern char *filename_completion_function();
 #define completion_matches rl_completion_matches
 #endif
 
+/*
+ * By enabling TABCOMPLETION_DEBUG, every completion attempt is logged in
+ * session log file if any.
+ */
+#ifdef TABCOMPLETION_DEBUG
+
+#undef completion_matches
+#define completion_matches(text, func) \
+    completion_debug(__LINE__, (text), (func), \
+                     previous_words, previous_words_count)
+
+#define DEBUG_NCONTEXT 3
+
+static char **
+completion_debug(int line, const char *text, rl_compentry_func_t *func,
+                 char **previous_words, int previous_words_count)
+{
+#ifdef HAVE_RL_COMPLETION_MATCHES
+    char **list = rl_completion_matches(text, func);
+#else
+    char **list = completion_matches(text, func);
+#endif
+
+    if (pset.logfile)
+    {
+        /* Emit completion log */
+
+        /* Enclose empty list with brackets since it is an intermediate state
+         * which is immediately followed by a non-empty list.
+         */
+        fprintf(pset.logfile, "%s:%d: %s(", __FILE__, line, list ? "" : "[");
+
+        /* input context */
+        if (previous_words_count > 0)
+        {
+            int nwords = DEBUG_NCONTEXT;
+
+            /* ellipse more than DEBUG_NCONTEXT words back */
+            if (previous_words_count > nwords)
+                fprintf(pset.logfile, "...");
+            else
+                nwords = previous_words_count;
+
+            for (int i = 0 ; i < nwords ; ++i)
+                fprintf(pset.logfile, "%s ", previous_words[nwords - i - 1]);
+        }
+
+        fprintf(pset.logfile, "[%s]) -> (", text);
+
+        /* completion result */
+        for (int i = 0; list && list[i]; ++i)
+            fprintf(pset.logfile, "%s\"%s\"", i ? ", " : "", list[i]);            
+        fprintf(pset.logfile, ")%s\n", list ? "": "]");
+
+        fflush(pset.logfile);
+    }
+
+    return list;
+}
+#endif    /* TABCOMPLETION_DEBUG */
+
 /* word break characters */
 #define WORD_BREAKS        "\t\n@$><=;|&{() "
 
@@ -1012,7 +1073,8 @@ static void append_variable_names(char ***varnames, int *nvars,
                       int *maxvars, const char *varname,
                       const char *prefix, const char *suffix);
 static char **complete_from_variables(const char *text,
-                        const char *prefix, const char *suffix, bool need_value);
+                      const char *prefix, const char *suffix, bool need_value,
+                      char ** previous_words, int previous_words_count);
 static char *complete_from_files(const char *text, int state);
 
 static char *pg_strdup_keyword_case(const char *s, const char *ref);
@@ -1385,11 +1447,14 @@ psql_completion(const char *text, int start, int end)
     else if (text[0] == ':' && text[1] != ':')
     {
         if (text[1] == '\'')
-            matches = complete_from_variables(text, ":'", "'", true);
+            matches = complete_from_variables(text, ":'", "'", true,
+                         previous_words, previous_words_count);
         else if (text[1] == '"')
-            matches = complete_from_variables(text, ":\"", "\"", true);
+            matches = complete_from_variables(text, ":\"", "\"", true,
+                         previous_words, previous_words_count);
         else
-            matches = complete_from_variables(text, ":", "", true);
+            matches = complete_from_variables(text, ":", "", true,
+                         previous_words, previous_words_count);
     }
 
     /* If no previous word, suggest one of the basic sql commands */
@@ -3548,9 +3613,11 @@ psql_completion(const char *text, int start, int end)
             COMPLETE_WITH_CS("single", "double");
     }
     else if (TailMatchesCS("\\unset"))
-        matches = complete_from_variables(text, "", "", true);
+        matches = complete_from_variables(text, "", "", true,
+                         previous_words, previous_words_count);
     else if (TailMatchesCS("\\set"))
-        matches = complete_from_variables(text, "", "", false);
+        matches = complete_from_variables(text, "", "", false,
+                         previous_words, previous_words_count);
     else if (TailMatchesCS("\\set", MatchAny))
     {
         if (TailMatchesCS("AUTOCOMMIT|ON_ERROR_STOP|QUIET|"
@@ -4102,7 +4169,8 @@ append_variable_names(char ***varnames, int *nvars,
  */
 static char **
 complete_from_variables(const char *text, const char *prefix, const char *suffix,
-                        bool need_value)
+                        bool need_value,
+                        char ** previous_words, int previous_words_count)
 {
     char      **matches;
     char      **varnames;
-- 
2.16.3

From 5a7dbb38167c226dcc093e5190b0ab4437c138df Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <horiguchi.kyotaro@lab.ntt.co.jp>
Date: Wed, 28 Nov 2018 11:24:53 +0900
Subject: [PATCH 2/2] Add psql -g option to control debug print

Added -g option and related help messages. TABCOMPLETION_DEBUG was
removed and the previously ifdef'ed code became always active.
---
 src/bin/psql/help.c         |  2 +-
 src/bin/psql/settings.h     |  1 +
 src/bin/psql/startup.c      | 12 +++++++++++-
 src/bin/psql/tab-complete.c | 14 +-------------
 4 files changed, 14 insertions(+), 15 deletions(-)

diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index 2e9fe760eb..43f224f3e8 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -123,7 +123,7 @@ usage(unsigned short int pager)
                       "                           set field separator for unaligned output to zero byte\n"));
     fprintf(output, _("  -0, --record-separator-zero\n"
                       "                           set record separator for unaligned output to zero byte\n"));
-
+    fprintf(output, _("  -g, --debug              turn on debug print to session log file\n"));
     fprintf(output, _("\nConnection options:\n"));
     /* Display default host */
     env = getenv("PGHOST");
diff --git a/src/bin/psql/settings.h b/src/bin/psql/settings.h
index 176c85afd0..c0bc96bf20 100644
--- a/src/bin/psql/settings.h
+++ b/src/bin/psql/settings.h
@@ -140,6 +140,7 @@ typedef struct _psqlSettings
     const char *prompt3;
     PGVerbosity verbosity;        /* current error verbosity level */
     PGContextVisibility show_context;    /* current context display level */
+    bool        debug;
 } PsqlSettings;
 
 extern PsqlSettings pset;
diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c
index e7536a8a06..25f78bcc2c 100644
--- a/src/bin/psql/startup.c
+++ b/src/bin/psql/startup.c
@@ -310,6 +310,12 @@ main(int argc, char *argv[])
             exit(EXIT_FAILURE);
         }
     }
+    else if (pset.debug)
+    {
+        fprintf(stderr, _("%s: no session log file, turn off debug print\n"),
+                pset.progname);
+        pset.debug = false;
+    }
 
     if (!options.no_psqlrc)
         process_psqlrc(argv[0]);
@@ -440,6 +446,7 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts *options)
         {"no-align", no_argument, NULL, 'A'},
         {"command", required_argument, NULL, 'c'},
         {"dbname", required_argument, NULL, 'd'},
+        {"debug", no_argument, NULL, 'g'},
         {"echo-queries", no_argument, NULL, 'e'},
         {"echo-errors", no_argument, NULL, 'b'},
         {"echo-hidden", no_argument, NULL, 'E'},
@@ -480,7 +487,7 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts *options)
 
     memset(options, 0, sizeof *options);
 
-    while ((c = getopt_long(argc, argv, "aAbc:d:eEf:F:h:HlL:no:p:P:qR:sStT:U:v:VwWxXz?01",
+    while ((c = getopt_long(argc, argv, "aAbc:d:eEf:F:gh:HlL:no:p:P:qR:sStT:U:v:VwWxXz?01",
                             long_options, &optindex)) != -1)
     {
         switch (c)
@@ -518,6 +525,9 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts *options)
                                           ACT_FILE,
                                           optarg);
                 break;
+            case 'g':
+                pset.debug = true;
+                break;
             case 'F':
                 pset.popt.topt.fieldSep.separator = pg_strdup(optarg);
                 pset.popt.topt.fieldSep.separator_zero = false;
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 8addca60a6..e034ff6da2 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -56,17 +56,6 @@
 extern char *filename_completion_function();
 #endif
 
-#ifdef HAVE_RL_COMPLETION_MATCHES
-#define completion_matches rl_completion_matches
-#endif
-
-/*
- * By enabling TABCOMPLETION_DEBUG, every completion attempt is logged in
- * session log file if any.
- */
-#ifdef TABCOMPLETION_DEBUG
-
-#undef completion_matches
 #define completion_matches(text, func) \
     completion_debug(__LINE__, (text), (func), \
                      previous_words, previous_words_count)
@@ -83,7 +72,7 @@ completion_debug(int line, const char *text, rl_compentry_func_t *func,
     char **list = completion_matches(text, func);
 #endif
 
-    if (pset.logfile)
+    if (pset.debug && pset.logfile)
     {
         /* Emit completion log */
 
@@ -119,7 +108,6 @@ completion_debug(int line, const char *text, rl_compentry_func_t *func,
 
     return list;
 }
-#endif    /* TABCOMPLETION_DEBUG */
 
 /* word break characters */
 #define WORD_BREAKS        "\t\n@$><=;|&{() "
-- 
2.16.3


pgsql-hackers by date:

Previous
From: Sergei Kornilov
Date:
Subject: Re: allow online change primary_conninfo
Next
From: Alexander Korotkov
Date:
Subject: Re: Connections hang indefinitely while taking a gin index's LWLockbuffer_content lock