]> granicus.if.org Git - postgresql/commitdiff
Fix tab completion of "SET variable TO|=" to not offer bogus completions.
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 2 Jul 2019 17:35:14 +0000 (13:35 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 2 Jul 2019 17:35:14 +0000 (13:35 -0400)
Don't think that the context "UPDATE tab SET var =" is a GUC-setting
command.

If we have "SET var =" but the "var" is not a known GUC variable,
don't offer any completions.  The most likely explanation is that
we've misparsed the context and it's not really a GUC-setting command.

Per gripe from Ken Tanzer.  Back-patch to 9.6.  The issue exists
further back, but before 9.6 the code looks very different and it
doesn't actually know whether the "var" name matches anything,
so I desisted from trying to fix it.

Discussion: https://postgr.es/m/CAD3a31XpXzrZA9TT3BqLSHghdTK+=cXjNCE+oL2Zn4+oWoc=qA@mail.gmail.com

src/bin/psql/tab-complete.c

index 83b2b9cee3c7c2cabf29ffaa848ecb4671d053a8..d47384295871a980dcaac7675883d53ca94e03c2 100644 (file)
@@ -3249,8 +3249,13 @@ psql_completion(const char *text, int start, int end)
        else if (HeadMatches2("ALTER", "DATABASE|FUNCTION|ROLE|USER") &&
                         TailMatches2("SET", MatchAny))
                COMPLETE_WITH_LIST2("FROM CURRENT", "TO");
-       /* Suggest possible variable values */
-       else if (TailMatches3("SET", MatchAny, "TO|="))
+
+       /*
+        * Suggest possible variable values in SET variable TO|=, along with the
+        * preceding ALTER syntaxes.
+        */
+       else if (TailMatches3("SET", MatchAny, "TO|=") &&
+                        !TailMatches5("UPDATE", MatchAny, "SET", MatchAny, "TO|="))
        {
                /* special cased code for individual GUCs */
                if (TailMatches2("DateStyle", "TO|="))
@@ -3273,21 +3278,29 @@ psql_completion(const char *text, int start, int end)
                        /* generic, type based, GUC support */
                        char       *guctype = get_guctype(prev2_wd);
 
-                       if (guctype && strcmp(guctype, "enum") == 0)
+                       /*
+                        * Note: if we don't recognize the GUC name, it's important to not
+                        * offer any completions, as most likely we've misinterpreted the
+                        * context and this isn't a GUC-setting command at all.
+                        */
+                       if (guctype)
                        {
-                               char            querybuf[1024];
+                               if (strcmp(guctype, "enum") == 0)
+                               {
+                                       char            querybuf[1024];
 
-                               snprintf(querybuf, sizeof(querybuf), Query_for_enum, prev2_wd);
-                               COMPLETE_WITH_QUERY(querybuf);
-                       }
-                       else if (guctype && strcmp(guctype, "bool") == 0)
-                               COMPLETE_WITH_LIST9("on", "off", "true", "false", "yes", "no",
-                                                                       "1", "0", "DEFAULT");
-                       else
-                               COMPLETE_WITH_CONST("DEFAULT");
+                                       snprintf(querybuf, sizeof(querybuf),
+                                                        Query_for_enum, prev2_wd);
+                                       COMPLETE_WITH_QUERY(querybuf);
+                               }
+                               else if (strcmp(guctype, "bool") == 0)
+                                       COMPLETE_WITH_LIST9("on", "off", "true", "false",
+                                                                               "yes", "no", "1", "0", "DEFAULT");
+                               else
+                                       COMPLETE_WITH_CONST("DEFAULT");
 
-                       if (guctype)
                                free(guctype);
+                       }
                }
        }