]> granicus.if.org Git - postgresql/blob - src/bin/psql/tab-complete.c
Add a 'parallel_degree' reloption.
[postgresql] / src / bin / psql / tab-complete.c
1 /*
2  * psql - the PostgreSQL interactive terminal
3  *
4  * Copyright (c) 2000-2016, PostgreSQL Global Development Group
5  *
6  * src/bin/psql/tab-complete.c
7  */
8
9 /*----------------------------------------------------------------------
10  * This file implements a somewhat more sophisticated readline "TAB
11  * completion" in psql. It is not intended to be AI, to replace
12  * learning SQL, or to relieve you from thinking about what you're
13  * doing. Also it does not always give you all the syntactically legal
14  * completions, only those that are the most common or the ones that
15  * the programmer felt most like implementing.
16  *
17  * CAVEAT: Tab completion causes queries to be sent to the backend.
18  * The number of tuples returned gets limited, in most default
19  * installations to 1000, but if you still don't like this prospect,
20  * you can turn off tab completion in your ~/.inputrc (or else
21  * ${INPUTRC}) file so:
22  *
23  *       $if psql
24  *       set disable-completion on
25  *       $endif
26  *
27  * See `man 3 readline' or `info readline' for the full details.
28  *
29  * BUGS:
30  * - Quotes, parentheses, and other funny characters are not handled
31  *       all that gracefully.
32  *----------------------------------------------------------------------
33  */
34
35 #include "postgres_fe.h"
36 #include "tab-complete.h"
37 #include "input.h"
38
39 /* If we don't have this, we might as well forget about the whole thing: */
40 #ifdef USE_READLINE
41
42 #include <ctype.h>
43 #include "libpq-fe.h"
44 #include "pqexpbuffer.h"
45 #include "common.h"
46 #include "settings.h"
47 #include "stringutils.h"
48
49 #ifdef HAVE_RL_FILENAME_COMPLETION_FUNCTION
50 #define filename_completion_function rl_filename_completion_function
51 #else
52 /* missing in some header files */
53 extern char *filename_completion_function();
54 #endif
55
56 #ifdef HAVE_RL_COMPLETION_MATCHES
57 #define completion_matches rl_completion_matches
58 #endif
59
60 /* word break characters */
61 #define WORD_BREAKS             "\t\n@$><=;|&{() "
62
63 /*
64  * Since readline doesn't let us pass any state through to the tab completion
65  * callback, we have to use this global variable to let get_previous_words()
66  * get at the previous lines of the current command.  Ick.
67  */
68 PQExpBuffer tab_completion_query_buf = NULL;
69
70 /*
71  * This struct is used to define "schema queries", which are custom-built
72  * to obtain possibly-schema-qualified names of database objects.  There is
73  * enough similarity in the structure that we don't want to repeat it each
74  * time.  So we put the components of each query into this struct and
75  * assemble them with the common boilerplate in _complete_from_query().
76  */
77 typedef struct SchemaQuery
78 {
79         /*
80          * Name of catalog or catalogs to be queried, with alias, eg.
81          * "pg_catalog.pg_class c".  Note that "pg_namespace n" will be added.
82          */
83         const char *catname;
84
85         /*
86          * Selection condition --- only rows meeting this condition are candidates
87          * to display.  If catname mentions multiple tables, include the necessary
88          * join condition here.  For example, "c.relkind = 'r'". Write NULL (not
89          * an empty string) if not needed.
90          */
91         const char *selcondition;
92
93         /*
94          * Visibility condition --- which rows are visible without schema
95          * qualification?  For example, "pg_catalog.pg_table_is_visible(c.oid)".
96          */
97         const char *viscondition;
98
99         /*
100          * Namespace --- name of field to join to pg_namespace.oid. For example,
101          * "c.relnamespace".
102          */
103         const char *namespace;
104
105         /*
106          * Result --- the appropriately-quoted name to return, in the case of an
107          * unqualified name.  For example, "pg_catalog.quote_ident(c.relname)".
108          */
109         const char *result;
110
111         /*
112          * In some cases a different result must be used for qualified names.
113          * Enter that here, or write NULL if result can be used.
114          */
115         const char *qualresult;
116 } SchemaQuery;
117
118
119 /* Store maximum number of records we want from database queries
120  * (implemented via SELECT ... LIMIT xx).
121  */
122 static int      completion_max_records;
123
124 /*
125  * Communication variables set by COMPLETE_WITH_FOO macros and then used by
126  * the completion callback functions.  Ugly but there is no better way.
127  */
128 static const char *completion_charp;    /* to pass a string */
129 static const char *const * completion_charpp;   /* to pass a list of strings */
130 static const char *completion_info_charp;               /* to pass a second string */
131 static const char *completion_info_charp2;              /* to pass a third string */
132 static const SchemaQuery *completion_squery;    /* to pass a SchemaQuery */
133 static bool completion_case_sensitive;  /* completion is case sensitive */
134
135 /*
136  * A few macros to ease typing. You can use these to complete the given
137  * string with
138  * 1) The results from a query you pass it. (Perhaps one of those below?)
139  * 2) The results from a schema query you pass it.
140  * 3) The items from a null-pointer-terminated list (with or without
141  *        case-sensitive comparison; see also COMPLETE_WITH_LISTn, below).
142  * 4) A string constant.
143  * 5) The list of attributes of the given table (possibly schema-qualified).
144  * 6/ The list of arguments to the given function (possibly schema-qualified).
145  */
146 #define COMPLETE_WITH_QUERY(query) \
147 do { \
148         completion_charp = query; \
149         matches = completion_matches(text, complete_from_query); \
150 } while (0)
151
152 #define COMPLETE_WITH_SCHEMA_QUERY(query, addon) \
153 do { \
154         completion_squery = &(query); \
155         completion_charp = addon; \
156         matches = completion_matches(text, complete_from_schema_query); \
157 } while (0)
158
159 #define COMPLETE_WITH_LIST_CS(list) \
160 do { \
161         completion_charpp = list; \
162         completion_case_sensitive = true; \
163         matches = completion_matches(text, complete_from_list); \
164 } while (0)
165
166 #define COMPLETE_WITH_LIST(list) \
167 do { \
168         completion_charpp = list; \
169         completion_case_sensitive = false; \
170         matches = completion_matches(text, complete_from_list); \
171 } while (0)
172
173 #define COMPLETE_WITH_CONST(string) \
174 do { \
175         completion_charp = string; \
176         completion_case_sensitive = false; \
177         matches = completion_matches(text, complete_from_const); \
178 } while (0)
179
180 #define COMPLETE_WITH_ATTR(relation, addon) \
181 do { \
182         char   *_completion_schema; \
183         char   *_completion_table; \
184 \
185         _completion_schema = strtokx(relation, " \t\n\r", ".", "\"", 0, \
186                                                                  false, false, pset.encoding); \
187         (void) strtokx(NULL, " \t\n\r", ".", "\"", 0, \
188                                    false, false, pset.encoding); \
189         _completion_table = strtokx(NULL, " \t\n\r", ".", "\"", 0, \
190                                                                 false, false, pset.encoding); \
191         if (_completion_table == NULL) \
192         { \
193                 completion_charp = Query_for_list_of_attributes  addon; \
194                 completion_info_charp = relation; \
195         } \
196         else \
197         { \
198                 completion_charp = Query_for_list_of_attributes_with_schema  addon; \
199                 completion_info_charp = _completion_table; \
200                 completion_info_charp2 = _completion_schema; \
201         } \
202         matches = completion_matches(text, complete_from_query); \
203 } while (0)
204
205 #define COMPLETE_WITH_FUNCTION_ARG(function) \
206 do { \
207         char   *_completion_schema; \
208         char   *_completion_function; \
209 \
210         _completion_schema = strtokx(function, " \t\n\r", ".", "\"", 0, \
211                                                                  false, false, pset.encoding); \
212         (void) strtokx(NULL, " \t\n\r", ".", "\"", 0, \
213                                    false, false, pset.encoding); \
214         _completion_function = strtokx(NULL, " \t\n\r", ".", "\"", 0, \
215                                                                    false, false, pset.encoding); \
216         if (_completion_function == NULL) \
217         { \
218                 completion_charp = Query_for_list_of_arguments; \
219                 completion_info_charp = function; \
220         } \
221         else \
222         { \
223                 completion_charp = Query_for_list_of_arguments_with_schema; \
224                 completion_info_charp = _completion_function; \
225                 completion_info_charp2 = _completion_schema; \
226         } \
227         matches = completion_matches(text, complete_from_query); \
228 } while (0)
229
230 /*
231  * These macros simplify use of COMPLETE_WITH_LIST for short, fixed lists.
232  * There is no COMPLETE_WITH_LIST1; use COMPLETE_WITH_CONST for that case.
233  */
234 #define COMPLETE_WITH_LIST2(s1, s2) \
235 do { \
236         static const char *const list[] = { s1, s2, NULL }; \
237         COMPLETE_WITH_LIST(list); \
238 } while (0)
239
240 #define COMPLETE_WITH_LIST3(s1, s2, s3) \
241 do { \
242         static const char *const list[] = { s1, s2, s3, NULL }; \
243         COMPLETE_WITH_LIST(list); \
244 } while (0)
245
246 #define COMPLETE_WITH_LIST4(s1, s2, s3, s4) \
247 do { \
248         static const char *const list[] = { s1, s2, s3, s4, NULL }; \
249         COMPLETE_WITH_LIST(list); \
250 } while (0)
251
252 #define COMPLETE_WITH_LIST5(s1, s2, s3, s4, s5) \
253 do { \
254         static const char *const list[] = { s1, s2, s3, s4, s5, NULL }; \
255         COMPLETE_WITH_LIST(list); \
256 } while (0)
257
258 #define COMPLETE_WITH_LIST6(s1, s2, s3, s4, s5, s6) \
259 do { \
260         static const char *const list[] = { s1, s2, s3, s4, s5, s6, NULL }; \
261         COMPLETE_WITH_LIST(list); \
262 } while (0)
263
264 #define COMPLETE_WITH_LIST7(s1, s2, s3, s4, s5, s6, s7) \
265 do { \
266         static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, NULL }; \
267         COMPLETE_WITH_LIST(list); \
268 } while (0)
269
270 #define COMPLETE_WITH_LIST8(s1, s2, s3, s4, s5, s6, s7, s8) \
271 do { \
272         static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, s8, NULL }; \
273         COMPLETE_WITH_LIST(list); \
274 } while (0)
275
276 #define COMPLETE_WITH_LIST9(s1, s2, s3, s4, s5, s6, s7, s8, s9) \
277 do { \
278         static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, s8, s9, NULL }; \
279         COMPLETE_WITH_LIST(list); \
280 } while (0)
281
282 #define COMPLETE_WITH_LIST10(s1, s2, s3, s4, s5, s6, s7, s8, s9, s10) \
283 do { \
284         static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, NULL }; \
285         COMPLETE_WITH_LIST(list); \
286 } while (0)
287
288 /*
289  * Likewise for COMPLETE_WITH_LIST_CS.
290  */
291 #define COMPLETE_WITH_LIST_CS2(s1, s2) \
292 do { \
293         static const char *const list[] = { s1, s2, NULL }; \
294         COMPLETE_WITH_LIST_CS(list); \
295 } while (0)
296
297 #define COMPLETE_WITH_LIST_CS3(s1, s2, s3) \
298 do { \
299         static const char *const list[] = { s1, s2, s3, NULL }; \
300         COMPLETE_WITH_LIST_CS(list); \
301 } while (0)
302
303 #define COMPLETE_WITH_LIST_CS4(s1, s2, s3, s4) \
304 do { \
305         static const char *const list[] = { s1, s2, s3, s4, NULL }; \
306         COMPLETE_WITH_LIST_CS(list); \
307 } while (0)
308
309 #define COMPLETE_WITH_LIST_CS5(s1, s2, s3, s4, s5) \
310 do { \
311         static const char *const list[] = { s1, s2, s3, s4, s5, NULL }; \
312         COMPLETE_WITH_LIST_CS(list); \
313 } while (0)
314
315 /*
316  * Assembly instructions for schema queries
317  */
318
319 static const SchemaQuery Query_for_list_of_aggregates = {
320         /* catname */
321         "pg_catalog.pg_proc p",
322         /* selcondition */
323         "p.proisagg",
324         /* viscondition */
325         "pg_catalog.pg_function_is_visible(p.oid)",
326         /* namespace */
327         "p.pronamespace",
328         /* result */
329         "pg_catalog.quote_ident(p.proname)",
330         /* qualresult */
331         NULL
332 };
333
334 static const SchemaQuery Query_for_list_of_datatypes = {
335         /* catname */
336         "pg_catalog.pg_type t",
337         /* selcondition --- ignore table rowtypes and array types */
338         "(t.typrelid = 0 "
339         " OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid)) "
340         "AND t.typname !~ '^_'",
341         /* viscondition */
342         "pg_catalog.pg_type_is_visible(t.oid)",
343         /* namespace */
344         "t.typnamespace",
345         /* result */
346         "pg_catalog.format_type(t.oid, NULL)",
347         /* qualresult */
348         "pg_catalog.quote_ident(t.typname)"
349 };
350
351 static const SchemaQuery Query_for_list_of_domains = {
352         /* catname */
353         "pg_catalog.pg_type t",
354         /* selcondition */
355         "t.typtype = 'd'",
356         /* viscondition */
357         "pg_catalog.pg_type_is_visible(t.oid)",
358         /* namespace */
359         "t.typnamespace",
360         /* result */
361         "pg_catalog.quote_ident(t.typname)",
362         /* qualresult */
363         NULL
364 };
365
366 static const SchemaQuery Query_for_list_of_functions = {
367         /* catname */
368         "pg_catalog.pg_proc p",
369         /* selcondition */
370         NULL,
371         /* viscondition */
372         "pg_catalog.pg_function_is_visible(p.oid)",
373         /* namespace */
374         "p.pronamespace",
375         /* result */
376         "pg_catalog.quote_ident(p.proname)",
377         /* qualresult */
378         NULL
379 };
380
381 static const SchemaQuery Query_for_list_of_indexes = {
382         /* catname */
383         "pg_catalog.pg_class c",
384         /* selcondition */
385         "c.relkind IN ('i')",
386         /* viscondition */
387         "pg_catalog.pg_table_is_visible(c.oid)",
388         /* namespace */
389         "c.relnamespace",
390         /* result */
391         "pg_catalog.quote_ident(c.relname)",
392         /* qualresult */
393         NULL
394 };
395
396 static const SchemaQuery Query_for_list_of_sequences = {
397         /* catname */
398         "pg_catalog.pg_class c",
399         /* selcondition */
400         "c.relkind IN ('S')",
401         /* viscondition */
402         "pg_catalog.pg_table_is_visible(c.oid)",
403         /* namespace */
404         "c.relnamespace",
405         /* result */
406         "pg_catalog.quote_ident(c.relname)",
407         /* qualresult */
408         NULL
409 };
410
411 static const SchemaQuery Query_for_list_of_foreign_tables = {
412         /* catname */
413         "pg_catalog.pg_class c",
414         /* selcondition */
415         "c.relkind IN ('f')",
416         /* viscondition */
417         "pg_catalog.pg_table_is_visible(c.oid)",
418         /* namespace */
419         "c.relnamespace",
420         /* result */
421         "pg_catalog.quote_ident(c.relname)",
422         /* qualresult */
423         NULL
424 };
425
426 static const SchemaQuery Query_for_list_of_tables = {
427         /* catname */
428         "pg_catalog.pg_class c",
429         /* selcondition */
430         "c.relkind IN ('r')",
431         /* viscondition */
432         "pg_catalog.pg_table_is_visible(c.oid)",
433         /* namespace */
434         "c.relnamespace",
435         /* result */
436         "pg_catalog.quote_ident(c.relname)",
437         /* qualresult */
438         NULL
439 };
440
441 static const SchemaQuery Query_for_list_of_constraints_with_schema = {
442         /* catname */
443         "pg_catalog.pg_constraint c",
444         /* selcondition */
445         "c.conrelid <> 0",
446         /* viscondition */
447         "true",                                         /* there is no pg_constraint_is_visible */
448         /* namespace */
449         "c.connamespace",
450         /* result */
451         "pg_catalog.quote_ident(c.conname)",
452         /* qualresult */
453         NULL
454 };
455
456 /* Relations supporting INSERT, UPDATE or DELETE */
457 static const SchemaQuery Query_for_list_of_updatables = {
458         /* catname */
459         "pg_catalog.pg_class c",
460         /* selcondition */
461         "c.relkind IN ('r', 'f', 'v')",
462         /* viscondition */
463         "pg_catalog.pg_table_is_visible(c.oid)",
464         /* namespace */
465         "c.relnamespace",
466         /* result */
467         "pg_catalog.quote_ident(c.relname)",
468         /* qualresult */
469         NULL
470 };
471
472 static const SchemaQuery Query_for_list_of_relations = {
473         /* catname */
474         "pg_catalog.pg_class c",
475         /* selcondition */
476         NULL,
477         /* viscondition */
478         "pg_catalog.pg_table_is_visible(c.oid)",
479         /* namespace */
480         "c.relnamespace",
481         /* result */
482         "pg_catalog.quote_ident(c.relname)",
483         /* qualresult */
484         NULL
485 };
486
487 static const SchemaQuery Query_for_list_of_tsvmf = {
488         /* catname */
489         "pg_catalog.pg_class c",
490         /* selcondition */
491         "c.relkind IN ('r', 'S', 'v', 'm', 'f')",
492         /* viscondition */
493         "pg_catalog.pg_table_is_visible(c.oid)",
494         /* namespace */
495         "c.relnamespace",
496         /* result */
497         "pg_catalog.quote_ident(c.relname)",
498         /* qualresult */
499         NULL
500 };
501
502 static const SchemaQuery Query_for_list_of_tmf = {
503         /* catname */
504         "pg_catalog.pg_class c",
505         /* selcondition */
506         "c.relkind IN ('r', 'm', 'f')",
507         /* viscondition */
508         "pg_catalog.pg_table_is_visible(c.oid)",
509         /* namespace */
510         "c.relnamespace",
511         /* result */
512         "pg_catalog.quote_ident(c.relname)",
513         /* qualresult */
514         NULL
515 };
516
517 static const SchemaQuery Query_for_list_of_tm = {
518         /* catname */
519         "pg_catalog.pg_class c",
520         /* selcondition */
521         "c.relkind IN ('r', 'm')",
522         /* viscondition */
523         "pg_catalog.pg_table_is_visible(c.oid)",
524         /* namespace */
525         "c.relnamespace",
526         /* result */
527         "pg_catalog.quote_ident(c.relname)",
528         /* qualresult */
529         NULL
530 };
531
532 static const SchemaQuery Query_for_list_of_views = {
533         /* catname */
534         "pg_catalog.pg_class c",
535         /* selcondition */
536         "c.relkind IN ('v')",
537         /* viscondition */
538         "pg_catalog.pg_table_is_visible(c.oid)",
539         /* namespace */
540         "c.relnamespace",
541         /* result */
542         "pg_catalog.quote_ident(c.relname)",
543         /* qualresult */
544         NULL
545 };
546
547 static const SchemaQuery Query_for_list_of_matviews = {
548         /* catname */
549         "pg_catalog.pg_class c",
550         /* selcondition */
551         "c.relkind IN ('m')",
552         /* viscondition */
553         "pg_catalog.pg_table_is_visible(c.oid)",
554         /* namespace */
555         "c.relnamespace",
556         /* result */
557         "pg_catalog.quote_ident(c.relname)",
558         /* qualresult */
559         NULL
560 };
561
562
563 /*
564  * Queries to get lists of names of various kinds of things, possibly
565  * restricted to names matching a partially entered name.  In these queries,
566  * the first %s will be replaced by the text entered so far (suitably escaped
567  * to become a SQL literal string).  %d will be replaced by the length of the
568  * string (in unescaped form).  A second and third %s, if present, will be
569  * replaced by a suitably-escaped version of the string provided in
570  * completion_info_charp.  A fourth and fifth %s are similarly replaced by
571  * completion_info_charp2.
572  *
573  * Beware that the allowed sequences of %s and %d are determined by
574  * _complete_from_query().
575  */
576
577 #define Query_for_list_of_attributes \
578 "SELECT pg_catalog.quote_ident(attname) "\
579 "  FROM pg_catalog.pg_attribute a, pg_catalog.pg_class c "\
580 " WHERE c.oid = a.attrelid "\
581 "   AND a.attnum > 0 "\
582 "   AND NOT a.attisdropped "\
583 "   AND substring(pg_catalog.quote_ident(attname),1,%d)='%s' "\
584 "   AND (pg_catalog.quote_ident(relname)='%s' "\
585 "        OR '\"' || relname || '\"'='%s') "\
586 "   AND pg_catalog.pg_table_is_visible(c.oid)"
587
588 #define Query_for_list_of_attributes_with_schema \
589 "SELECT pg_catalog.quote_ident(attname) "\
590 "  FROM pg_catalog.pg_attribute a, pg_catalog.pg_class c, pg_catalog.pg_namespace n "\
591 " WHERE c.oid = a.attrelid "\
592 "   AND n.oid = c.relnamespace "\
593 "   AND a.attnum > 0 "\
594 "   AND NOT a.attisdropped "\
595 "   AND substring(pg_catalog.quote_ident(attname),1,%d)='%s' "\
596 "   AND (pg_catalog.quote_ident(relname)='%s' "\
597 "        OR '\"' || relname || '\"' ='%s') "\
598 "   AND (pg_catalog.quote_ident(nspname)='%s' "\
599 "        OR '\"' || nspname || '\"' ='%s') "
600
601 #define Query_for_list_of_template_databases \
602 "SELECT pg_catalog.quote_ident(datname) FROM pg_catalog.pg_database "\
603 " WHERE substring(pg_catalog.quote_ident(datname),1,%d)='%s' AND datistemplate"
604
605 #define Query_for_list_of_databases \
606 "SELECT pg_catalog.quote_ident(datname) FROM pg_catalog.pg_database "\
607 " WHERE substring(pg_catalog.quote_ident(datname),1,%d)='%s'"
608
609 #define Query_for_list_of_tablespaces \
610 "SELECT pg_catalog.quote_ident(spcname) FROM pg_catalog.pg_tablespace "\
611 " WHERE substring(pg_catalog.quote_ident(spcname),1,%d)='%s'"
612
613 #define Query_for_list_of_encodings \
614 " SELECT DISTINCT pg_catalog.pg_encoding_to_char(conforencoding) "\
615 "   FROM pg_catalog.pg_conversion "\
616 "  WHERE substring(pg_catalog.pg_encoding_to_char(conforencoding),1,%d)=UPPER('%s')"
617
618 #define Query_for_list_of_languages \
619 "SELECT pg_catalog.quote_ident(lanname) "\
620 "  FROM pg_catalog.pg_language "\
621 " WHERE lanname != 'internal' "\
622 "   AND substring(pg_catalog.quote_ident(lanname),1,%d)='%s'"
623
624 #define Query_for_list_of_schemas \
625 "SELECT pg_catalog.quote_ident(nspname) FROM pg_catalog.pg_namespace "\
626 " WHERE substring(pg_catalog.quote_ident(nspname),1,%d)='%s'"
627
628 #define Query_for_list_of_alter_system_set_vars \
629 "SELECT name FROM "\
630 " (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings "\
631 "  WHERE context != 'internal') ss "\
632 " WHERE substring(name,1,%d)='%s'"\
633 " UNION ALL SELECT 'all' ss"
634
635 #define Query_for_list_of_set_vars \
636 "SELECT name FROM "\
637 " (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings "\
638 "  WHERE context IN ('user', 'superuser') "\
639 "  UNION ALL SELECT 'constraints' "\
640 "  UNION ALL SELECT 'transaction' "\
641 "  UNION ALL SELECT 'session' "\
642 "  UNION ALL SELECT 'role' "\
643 "  UNION ALL SELECT 'tablespace' "\
644 "  UNION ALL SELECT 'all') ss "\
645 " WHERE substring(name,1,%d)='%s'"
646
647 #define Query_for_list_of_show_vars \
648 "SELECT name FROM "\
649 " (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings "\
650 "  UNION ALL SELECT 'session authorization' "\
651 "  UNION ALL SELECT 'all') ss "\
652 " WHERE substring(name,1,%d)='%s'"
653
654 #define Query_for_list_of_roles \
655 " SELECT pg_catalog.quote_ident(rolname) "\
656 "   FROM pg_catalog.pg_roles "\
657 "  WHERE substring(pg_catalog.quote_ident(rolname),1,%d)='%s'"
658
659 #define Query_for_list_of_grant_roles \
660 " SELECT pg_catalog.quote_ident(rolname) "\
661 "   FROM pg_catalog.pg_roles "\
662 "  WHERE substring(pg_catalog.quote_ident(rolname),1,%d)='%s'"\
663 " UNION ALL SELECT 'PUBLIC'"\
664 " UNION ALL SELECT 'CURRENT_USER'"\
665 " UNION ALL SELECT 'SESSION_USER'"
666
667 /* the silly-looking length condition is just to eat up the current word */
668 #define Query_for_table_owning_index \
669 "SELECT pg_catalog.quote_ident(c1.relname) "\
670 "  FROM pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_index i"\
671 " WHERE c1.oid=i.indrelid and i.indexrelid=c2.oid"\
672 "       and (%d = pg_catalog.length('%s'))"\
673 "       and pg_catalog.quote_ident(c2.relname)='%s'"\
674 "       and pg_catalog.pg_table_is_visible(c2.oid)"
675
676 /* the silly-looking length condition is just to eat up the current word */
677 #define Query_for_index_of_table \
678 "SELECT pg_catalog.quote_ident(c2.relname) "\
679 "  FROM pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_index i"\
680 " WHERE c1.oid=i.indrelid and i.indexrelid=c2.oid"\
681 "       and (%d = pg_catalog.length('%s'))"\
682 "       and pg_catalog.quote_ident(c1.relname)='%s'"\
683 "       and pg_catalog.pg_table_is_visible(c2.oid)"
684
685 /* the silly-looking length condition is just to eat up the current word */
686 #define Query_for_constraint_of_table \
687 "SELECT pg_catalog.quote_ident(conname) "\
688 "  FROM pg_catalog.pg_class c1, pg_catalog.pg_constraint con "\
689 " WHERE c1.oid=conrelid and (%d = pg_catalog.length('%s'))"\
690 "       and pg_catalog.quote_ident(c1.relname)='%s'"\
691 "       and pg_catalog.pg_table_is_visible(c1.oid)"
692
693 #define Query_for_all_table_constraints \
694 "SELECT pg_catalog.quote_ident(conname) "\
695 "  FROM pg_catalog.pg_constraint c "\
696 " WHERE c.conrelid <> 0 "
697
698 /* the silly-looking length condition is just to eat up the current word */
699 #define Query_for_constraint_of_type \
700 "SELECT pg_catalog.quote_ident(conname) "\
701 "  FROM pg_catalog.pg_type t, pg_catalog.pg_constraint con "\
702 " WHERE t.oid=contypid and (%d = pg_catalog.length('%s'))"\
703 "       and pg_catalog.quote_ident(t.typname)='%s'"\
704 "       and pg_catalog.pg_type_is_visible(t.oid)"
705
706 /* the silly-looking length condition is just to eat up the current word */
707 #define Query_for_list_of_tables_for_constraint \
708 "SELECT pg_catalog.quote_ident(relname) "\
709 "  FROM pg_catalog.pg_class"\
710 " WHERE (%d = pg_catalog.length('%s'))"\
711 "   AND oid IN "\
712 "       (SELECT conrelid FROM pg_catalog.pg_constraint "\
713 "         WHERE pg_catalog.quote_ident(conname)='%s')"
714
715 /* the silly-looking length condition is just to eat up the current word */
716 #define Query_for_rule_of_table \
717 "SELECT pg_catalog.quote_ident(rulename) "\
718 "  FROM pg_catalog.pg_class c1, pg_catalog.pg_rewrite "\
719 " WHERE c1.oid=ev_class and (%d = pg_catalog.length('%s'))"\
720 "       and pg_catalog.quote_ident(c1.relname)='%s'"\
721 "       and pg_catalog.pg_table_is_visible(c1.oid)"
722
723 /* the silly-looking length condition is just to eat up the current word */
724 #define Query_for_list_of_tables_for_rule \
725 "SELECT pg_catalog.quote_ident(relname) "\
726 "  FROM pg_catalog.pg_class"\
727 " WHERE (%d = pg_catalog.length('%s'))"\
728 "   AND oid IN "\
729 "       (SELECT ev_class FROM pg_catalog.pg_rewrite "\
730 "         WHERE pg_catalog.quote_ident(rulename)='%s')"
731
732 /* the silly-looking length condition is just to eat up the current word */
733 #define Query_for_trigger_of_table \
734 "SELECT pg_catalog.quote_ident(tgname) "\
735 "  FROM pg_catalog.pg_class c1, pg_catalog.pg_trigger "\
736 " WHERE c1.oid=tgrelid and (%d = pg_catalog.length('%s'))"\
737 "       and pg_catalog.quote_ident(c1.relname)='%s'"\
738 "       and pg_catalog.pg_table_is_visible(c1.oid)"\
739 "       and not tgisinternal"
740
741 /* the silly-looking length condition is just to eat up the current word */
742 #define Query_for_list_of_tables_for_trigger \
743 "SELECT pg_catalog.quote_ident(relname) "\
744 "  FROM pg_catalog.pg_class"\
745 " WHERE (%d = pg_catalog.length('%s'))"\
746 "   AND oid IN "\
747 "       (SELECT tgrelid FROM pg_catalog.pg_trigger "\
748 "         WHERE pg_catalog.quote_ident(tgname)='%s')"
749
750 #define Query_for_list_of_ts_configurations \
751 "SELECT pg_catalog.quote_ident(cfgname) FROM pg_catalog.pg_ts_config "\
752 " WHERE substring(pg_catalog.quote_ident(cfgname),1,%d)='%s'"
753
754 #define Query_for_list_of_ts_dictionaries \
755 "SELECT pg_catalog.quote_ident(dictname) FROM pg_catalog.pg_ts_dict "\
756 " WHERE substring(pg_catalog.quote_ident(dictname),1,%d)='%s'"
757
758 #define Query_for_list_of_ts_parsers \
759 "SELECT pg_catalog.quote_ident(prsname) FROM pg_catalog.pg_ts_parser "\
760 " WHERE substring(pg_catalog.quote_ident(prsname),1,%d)='%s'"
761
762 #define Query_for_list_of_ts_templates \
763 "SELECT pg_catalog.quote_ident(tmplname) FROM pg_catalog.pg_ts_template "\
764 " WHERE substring(pg_catalog.quote_ident(tmplname),1,%d)='%s'"
765
766 #define Query_for_list_of_fdws \
767 " SELECT pg_catalog.quote_ident(fdwname) "\
768 "   FROM pg_catalog.pg_foreign_data_wrapper "\
769 "  WHERE substring(pg_catalog.quote_ident(fdwname),1,%d)='%s'"
770
771 #define Query_for_list_of_servers \
772 " SELECT pg_catalog.quote_ident(srvname) "\
773 "   FROM pg_catalog.pg_foreign_server "\
774 "  WHERE substring(pg_catalog.quote_ident(srvname),1,%d)='%s'"
775
776 #define Query_for_list_of_user_mappings \
777 " SELECT pg_catalog.quote_ident(usename) "\
778 "   FROM pg_catalog.pg_user_mappings "\
779 "  WHERE substring(pg_catalog.quote_ident(usename),1,%d)='%s'"
780
781 #define Query_for_list_of_access_methods \
782 " SELECT pg_catalog.quote_ident(amname) "\
783 "   FROM pg_catalog.pg_am "\
784 "  WHERE substring(pg_catalog.quote_ident(amname),1,%d)='%s'"
785
786 /* the silly-looking length condition is just to eat up the current word */
787 #define Query_for_list_of_arguments \
788 "SELECT pg_catalog.oidvectortypes(proargtypes)||')' "\
789 "  FROM pg_catalog.pg_proc "\
790 " WHERE (%d = pg_catalog.length('%s'))"\
791 "   AND (pg_catalog.quote_ident(proname)='%s'"\
792 "        OR '\"' || proname || '\"'='%s') "\
793 "   AND (pg_catalog.pg_function_is_visible(pg_proc.oid))"
794
795 /* the silly-looking length condition is just to eat up the current word */
796 #define Query_for_list_of_arguments_with_schema \
797 "SELECT pg_catalog.oidvectortypes(proargtypes)||')' "\
798 "  FROM pg_catalog.pg_proc p, pg_catalog.pg_namespace n "\
799 " WHERE (%d = pg_catalog.length('%s'))"\
800 "   AND n.oid = p.pronamespace "\
801 "   AND (pg_catalog.quote_ident(proname)='%s' "\
802 "        OR '\"' || proname || '\"' ='%s') "\
803 "   AND (pg_catalog.quote_ident(nspname)='%s' "\
804 "        OR '\"' || nspname || '\"' ='%s') "
805
806 #define Query_for_list_of_extensions \
807 " SELECT pg_catalog.quote_ident(extname) "\
808 "   FROM pg_catalog.pg_extension "\
809 "  WHERE substring(pg_catalog.quote_ident(extname),1,%d)='%s'"
810
811 #define Query_for_list_of_available_extensions \
812 " SELECT pg_catalog.quote_ident(name) "\
813 "   FROM pg_catalog.pg_available_extensions "\
814 "  WHERE substring(pg_catalog.quote_ident(name),1,%d)='%s' AND installed_version IS NULL"
815
816 /* the silly-looking length condition is just to eat up the current word */
817 #define Query_for_list_of_available_extension_versions \
818 " SELECT pg_catalog.quote_ident(version) "\
819 "   FROM pg_catalog.pg_available_extension_versions "\
820 "  WHERE (%d = pg_catalog.length('%s'))"\
821 "    AND pg_catalog.quote_ident(name)='%s'"
822
823 #define Query_for_list_of_prepared_statements \
824 " SELECT pg_catalog.quote_ident(name) "\
825 "   FROM pg_catalog.pg_prepared_statements "\
826 "  WHERE substring(pg_catalog.quote_ident(name),1,%d)='%s'"
827
828 #define Query_for_list_of_event_triggers \
829 " SELECT pg_catalog.quote_ident(evtname) "\
830 "   FROM pg_catalog.pg_event_trigger "\
831 "  WHERE substring(pg_catalog.quote_ident(evtname),1,%d)='%s'"
832
833 #define Query_for_list_of_tablesample_methods \
834 " SELECT pg_catalog.quote_ident(proname) "\
835 "   FROM pg_catalog.pg_proc "\
836 "  WHERE prorettype = 'pg_catalog.tsm_handler'::pg_catalog.regtype AND "\
837 "        proargtypes[0] = 'pg_catalog.internal'::pg_catalog.regtype AND "\
838 "        substring(pg_catalog.quote_ident(proname),1,%d)='%s'"
839
840 #define Query_for_list_of_policies \
841 " SELECT pg_catalog.quote_ident(polname) "\
842 "   FROM pg_catalog.pg_policy "\
843 "  WHERE substring(pg_catalog.quote_ident(polname),1,%d)='%s'"
844
845 #define Query_for_list_of_tables_for_policy \
846 "SELECT pg_catalog.quote_ident(relname) "\
847 "  FROM pg_catalog.pg_class"\
848 " WHERE (%d = pg_catalog.length('%s'))"\
849 "   AND oid IN "\
850 "       (SELECT polrelid FROM pg_catalog.pg_policy "\
851 "         WHERE pg_catalog.quote_ident(polname)='%s')"
852
853 #define Query_for_enum \
854 " SELECT name FROM ( "\
855 "   SELECT pg_catalog.quote_ident(pg_catalog.unnest(enumvals)) AS name "\
856 "     FROM pg_catalog.pg_settings "\
857 "    WHERE pg_catalog.lower(name)=pg_catalog.lower('%s') "\
858 "    UNION ALL " \
859 "   SELECT 'DEFAULT' ) ss "\
860 "  WHERE pg_catalog.substring(name,1,%%d)='%%s'"
861
862 /*
863  * This is a list of all "things" in Pgsql, which can show up after CREATE or
864  * DROP; and there is also a query to get a list of them.
865  */
866
867 typedef struct
868 {
869         const char *name;
870         const char *query;                      /* simple query, or NULL */
871         const SchemaQuery *squery;      /* schema query, or NULL */
872         const bits32 flags;                     /* visibility flags, see below */
873 } pgsql_thing_t;
874
875 #define THING_NO_CREATE         (1 << 0)        /* should not show up after CREATE */
876 #define THING_NO_DROP           (1 << 1)        /* should not show up after DROP */
877 #define THING_NO_SHOW           (THING_NO_CREATE | THING_NO_DROP)
878
879 static const pgsql_thing_t words_after_create[] = {
880         {"ACCESS METHOD", NULL, NULL},
881         {"AGGREGATE", NULL, &Query_for_list_of_aggregates},
882         {"CAST", NULL, NULL},           /* Casts have complex structures for names, so
883                                                                  * skip it */
884         {"COLLATION", "SELECT pg_catalog.quote_ident(collname) FROM pg_catalog.pg_collation WHERE collencoding IN (-1, pg_catalog.pg_char_to_encoding(pg_catalog.getdatabaseencoding())) AND substring(pg_catalog.quote_ident(collname),1,%d)='%s'"},
885
886         /*
887          * CREATE CONSTRAINT TRIGGER is not supported here because it is designed
888          * to be used only by pg_dump.
889          */
890         {"CONFIGURATION", Query_for_list_of_ts_configurations, NULL, THING_NO_SHOW},
891         {"CONVERSION", "SELECT pg_catalog.quote_ident(conname) FROM pg_catalog.pg_conversion WHERE substring(pg_catalog.quote_ident(conname),1,%d)='%s'"},
892         {"DATABASE", Query_for_list_of_databases},
893         {"DICTIONARY", Query_for_list_of_ts_dictionaries, NULL, THING_NO_SHOW},
894         {"DOMAIN", NULL, &Query_for_list_of_domains},
895         {"EVENT TRIGGER", NULL, NULL},
896         {"EXTENSION", Query_for_list_of_extensions},
897         {"FOREIGN DATA WRAPPER", NULL, NULL},
898         {"FOREIGN TABLE", NULL, NULL},
899         {"FUNCTION", NULL, &Query_for_list_of_functions},
900         {"GROUP", Query_for_list_of_roles},
901         {"LANGUAGE", Query_for_list_of_languages},
902         {"INDEX", NULL, &Query_for_list_of_indexes},
903         {"MATERIALIZED VIEW", NULL, &Query_for_list_of_matviews},
904         {"OPERATOR", NULL, NULL},       /* Querying for this is probably not such a
905                                                                  * good idea. */
906         {"OWNED", NULL, NULL, THING_NO_CREATE},         /* for DROP OWNED BY ... */
907         {"PARSER", Query_for_list_of_ts_parsers, NULL, THING_NO_SHOW},
908         {"POLICY", NULL, NULL},
909         {"ROLE", Query_for_list_of_roles},
910         {"RULE", "SELECT pg_catalog.quote_ident(rulename) FROM pg_catalog.pg_rules WHERE substring(pg_catalog.quote_ident(rulename),1,%d)='%s'"},
911         {"SCHEMA", Query_for_list_of_schemas},
912         {"SEQUENCE", NULL, &Query_for_list_of_sequences},
913         {"SERVER", Query_for_list_of_servers},
914         {"TABLE", NULL, &Query_for_list_of_tables},
915         {"TABLESPACE", Query_for_list_of_tablespaces},
916         {"TEMP", NULL, NULL, THING_NO_DROP},            /* for CREATE TEMP TABLE ... */
917         {"TEMPLATE", Query_for_list_of_ts_templates, NULL, THING_NO_SHOW},
918         {"TEXT SEARCH", NULL, NULL},
919         {"TRIGGER", "SELECT pg_catalog.quote_ident(tgname) FROM pg_catalog.pg_trigger WHERE substring(pg_catalog.quote_ident(tgname),1,%d)='%s' AND NOT tgisinternal"},
920         {"TYPE", NULL, &Query_for_list_of_datatypes},
921         {"UNIQUE", NULL, NULL, THING_NO_DROP},          /* for CREATE UNIQUE INDEX ... */
922         {"UNLOGGED", NULL, NULL, THING_NO_DROP},        /* for CREATE UNLOGGED TABLE
923                                                                                                  * ... */
924         {"USER", Query_for_list_of_roles},
925         {"USER MAPPING FOR", NULL, NULL},
926         {"VIEW", NULL, &Query_for_list_of_views},
927         {NULL}                                          /* end of list */
928 };
929
930
931 /* Forward declaration of functions */
932 static char **psql_completion(const char *text, int start, int end);
933 static char *create_command_generator(const char *text, int state);
934 static char *drop_command_generator(const char *text, int state);
935 static char *complete_from_query(const char *text, int state);
936 static char *complete_from_schema_query(const char *text, int state);
937 static char *_complete_from_query(int is_schema_query,
938                                          const char *text, int state);
939 static char *complete_from_list(const char *text, int state);
940 static char *complete_from_const(const char *text, int state);
941 static void append_variable_names(char ***varnames, int *nvars,
942                                           int *maxvars, const char *varname,
943                                           const char *prefix, const char *suffix);
944 static char **complete_from_variables(const char *text,
945                                         const char *prefix, const char *suffix, bool need_value);
946 static char *complete_from_files(const char *text, int state);
947
948 static char *pg_strdup_keyword_case(const char *s, const char *ref);
949 static char *escape_string(const char *text);
950 static PGresult *exec_query(const char *query);
951
952 static char **get_previous_words(int point, char **buffer, int *nwords);
953
954 static char *get_guctype(const char *varname);
955
956 #ifdef NOT_USED
957 static char *quote_file_name(char *text, int match_type, char *quote_pointer);
958 static char *dequote_file_name(char *text, char quote_char);
959 #endif
960
961
962 /*
963  * Initialize the readline library for our purposes.
964  */
965 void
966 initialize_readline(void)
967 {
968         rl_readline_name = (char *) pset.progname;
969         rl_attempted_completion_function = psql_completion;
970
971         rl_basic_word_break_characters = WORD_BREAKS;
972
973         completion_max_records = 1000;
974
975         /*
976          * There is a variable rl_completion_query_items for this but apparently
977          * it's not defined everywhere.
978          */
979 }
980
981 /*
982  * Check if 'word' matches any of the '|'-separated strings in 'pattern',
983  * using case-insensitive or case-sensitive comparisons.
984  *
985  * If pattern is NULL, it's a wild card that matches any word.
986  * If pattern begins with '!', the result is negated, ie we check that 'word'
987  * does *not* match any alternative appearing in the rest of 'pattern'.
988  * Any alternative can end with '*' which is a wild card, i.e., it means
989  * match any word that matches the characters so far.  (We do not currently
990  * support '*' elsewhere than the end of an alternative.)
991  *
992  * For readability, callers should use the macros MatchAny and MatchAnyExcept
993  * to invoke those two special cases for 'pattern'.  (But '|' and '*' must
994  * just be written directly in patterns.)
995  */
996 #define MatchAny  NULL
997 #define MatchAnyExcept(pattern)  ("!" pattern)
998
999 static bool
1000 word_matches_internal(const char *pattern,
1001                                           const char *word,
1002                                           bool case_sensitive)
1003 {
1004         size_t          wordlen,
1005                                 patternlen;
1006
1007         /* NULL pattern matches anything. */
1008         if (pattern == NULL)
1009                 return true;
1010
1011         /* Handle negated patterns from the MatchAnyExcept macro. */
1012         if (*pattern == '!')
1013                 return !word_matches_internal(pattern + 1, word, case_sensitive);
1014
1015         /* Else consider each alternative in the pattern. */
1016         wordlen = strlen(word);
1017         for (;;)
1018         {
1019                 const char *c;
1020
1021                 /* Find end of current alternative. */
1022                 c = pattern;
1023                 while (*c != '\0' && *c != '|')
1024                         c++;
1025                 /* Was there a wild card?  (Assumes first alternative is not empty) */
1026                 if (c[-1] == '*')
1027                 {
1028                         /* Yes, wildcard match? */
1029                         patternlen = c - pattern - 1;
1030                         if (wordlen >= patternlen &&
1031                                 (case_sensitive ?
1032                                  strncmp(word, pattern, patternlen) == 0 :
1033                                  pg_strncasecmp(word, pattern, patternlen) == 0))
1034                                 return true;
1035                 }
1036                 else
1037                 {
1038                         /* No, plain match? */
1039                         patternlen = c - pattern;
1040                         if (wordlen == patternlen &&
1041                                 (case_sensitive ?
1042                                  strncmp(word, pattern, wordlen) == 0 :
1043                                  pg_strncasecmp(word, pattern, wordlen) == 0))
1044                                 return true;
1045                 }
1046                 /* Out of alternatives? */
1047                 if (*c == '\0')
1048                         break;
1049                 /* Nope, try next alternative. */
1050                 pattern = c + 1;
1051         }
1052
1053         return false;
1054 }
1055
1056 /*
1057  * There are enough matching calls below that it seems worth having these two
1058  * interface routines rather than including a third parameter in every call.
1059  *
1060  * word_matches --- match case-insensitively.
1061  */
1062 static bool
1063 word_matches(const char *pattern, const char *word)
1064 {
1065         return word_matches_internal(pattern, word, false);
1066 }
1067
1068 /*
1069  * word_matches_cs --- match case-sensitively.
1070  */
1071 static bool
1072 word_matches_cs(const char *pattern, const char *word)
1073 {
1074         return word_matches_internal(pattern, word, true);
1075 }
1076
1077 /*
1078  * Check if the final character of 's' is 'c'.
1079  */
1080 static bool
1081 ends_with(const char *s, char c)
1082 {
1083         size_t          length = strlen(s);
1084
1085         return (length > 0 && s[length - 1] == c);
1086 }
1087
1088 /*
1089  * The completion function.
1090  *
1091  * According to readline spec this gets passed the text entered so far and its
1092  * start and end positions in the readline buffer. The return value is some
1093  * partially obscure list format that can be generated by readline's
1094  * completion_matches() function, so we don't have to worry about it.
1095  */
1096 static char **
1097 psql_completion(const char *text, int start, int end)
1098 {
1099         /* This is the variable we'll return. */
1100         char      **matches = NULL;
1101
1102         /* Workspace for parsed words. */
1103         char       *words_buffer;
1104
1105         /* This array will contain pointers to parsed words. */
1106         char      **previous_words;
1107
1108         /* The number of words found on the input line. */
1109         int                     previous_words_count;
1110
1111         /*
1112          * For compactness, we use these macros to reference previous_words[].
1113          * Caution: do not access a previous_words[] entry without having checked
1114          * previous_words_count to be sure it's valid.  In most cases below, that
1115          * check is implicit in a TailMatches() or similar macro, but in some
1116          * places we have to check it explicitly.
1117          */
1118 #define prev_wd   (previous_words[0])
1119 #define prev2_wd  (previous_words[1])
1120 #define prev3_wd  (previous_words[2])
1121 #define prev4_wd  (previous_words[3])
1122 #define prev5_wd  (previous_words[4])
1123 #define prev6_wd  (previous_words[5])
1124 #define prev7_wd  (previous_words[6])
1125 #define prev8_wd  (previous_words[7])
1126 #define prev9_wd  (previous_words[8])
1127
1128         /* Macros for matching the last N words before point, case-insensitively. */
1129 #define TailMatches1(p1) \
1130         (previous_words_count >= 1 && \
1131          word_matches(p1, prev_wd))
1132
1133 #define TailMatches2(p2, p1) \
1134         (previous_words_count >= 2 && \
1135          word_matches(p1, prev_wd) && \
1136          word_matches(p2, prev2_wd))
1137
1138 #define TailMatches3(p3, p2, p1) \
1139         (previous_words_count >= 3 && \
1140          word_matches(p1, prev_wd) && \
1141          word_matches(p2, prev2_wd) && \
1142          word_matches(p3, prev3_wd))
1143
1144 #define TailMatches4(p4, p3, p2, p1) \
1145         (previous_words_count >= 4 && \
1146          word_matches(p1, prev_wd) && \
1147          word_matches(p2, prev2_wd) && \
1148          word_matches(p3, prev3_wd) && \
1149          word_matches(p4, prev4_wd))
1150
1151 #define TailMatches5(p5, p4, p3, p2, p1) \
1152         (previous_words_count >= 5 && \
1153          word_matches(p1, prev_wd) && \
1154          word_matches(p2, prev2_wd) && \
1155          word_matches(p3, prev3_wd) && \
1156          word_matches(p4, prev4_wd) && \
1157          word_matches(p5, prev5_wd))
1158
1159 #define TailMatches6(p6, p5, p4, p3, p2, p1) \
1160         (previous_words_count >= 6 && \
1161          word_matches(p1, prev_wd) && \
1162          word_matches(p2, prev2_wd) && \
1163          word_matches(p3, prev3_wd) && \
1164          word_matches(p4, prev4_wd) && \
1165          word_matches(p5, prev5_wd) && \
1166          word_matches(p6, prev6_wd))
1167
1168 #define TailMatches7(p7, p6, p5, p4, p3, p2, p1) \
1169         (previous_words_count >= 7 && \
1170          word_matches(p1, prev_wd) && \
1171          word_matches(p2, prev2_wd) && \
1172          word_matches(p3, prev3_wd) && \
1173          word_matches(p4, prev4_wd) && \
1174          word_matches(p5, prev5_wd) && \
1175          word_matches(p6, prev6_wd) && \
1176          word_matches(p7, prev7_wd))
1177
1178 #define TailMatches8(p8, p7, p6, p5, p4, p3, p2, p1) \
1179         (previous_words_count >= 8 && \
1180          word_matches(p1, prev_wd) && \
1181          word_matches(p2, prev2_wd) && \
1182          word_matches(p3, prev3_wd) && \
1183          word_matches(p4, prev4_wd) && \
1184          word_matches(p5, prev5_wd) && \
1185          word_matches(p6, prev6_wd) && \
1186          word_matches(p7, prev7_wd) && \
1187          word_matches(p8, prev8_wd))
1188
1189 #define TailMatches9(p9, p8, p7, p6, p5, p4, p3, p2, p1) \
1190         (previous_words_count >= 9 && \
1191          word_matches(p1, prev_wd) && \
1192          word_matches(p2, prev2_wd) && \
1193          word_matches(p3, prev3_wd) && \
1194          word_matches(p4, prev4_wd) && \
1195          word_matches(p5, prev5_wd) && \
1196          word_matches(p6, prev6_wd) && \
1197          word_matches(p7, prev7_wd) && \
1198          word_matches(p8, prev8_wd) && \
1199          word_matches(p9, prev9_wd))
1200
1201         /* Macros for matching the last N words before point, case-sensitively. */
1202 #define TailMatchesCS1(p1) \
1203         (previous_words_count >= 1 && \
1204          word_matches_cs(p1, prev_wd))
1205 #define TailMatchesCS2(p2, p1) \
1206         (previous_words_count >= 2 && \
1207          word_matches_cs(p1, prev_wd) && \
1208          word_matches_cs(p2, prev2_wd))
1209
1210         /*
1211          * Macros for matching N words beginning at the start of the line,
1212          * case-insensitively.
1213          */
1214 #define Matches1(p1) \
1215         (previous_words_count == 1 && \
1216          TailMatches1(p1))
1217 #define Matches2(p1, p2) \
1218         (previous_words_count == 2 && \
1219          TailMatches2(p1, p2))
1220 #define Matches3(p1, p2, p3) \
1221         (previous_words_count == 3 && \
1222          TailMatches3(p1, p2, p3))
1223 #define Matches4(p1, p2, p3, p4) \
1224         (previous_words_count == 4 && \
1225          TailMatches4(p1, p2, p3, p4))
1226 #define Matches5(p1, p2, p3, p4, p5) \
1227         (previous_words_count == 5 && \
1228          TailMatches5(p1, p2, p3, p4, p5))
1229 #define Matches6(p1, p2, p3, p4, p5, p6) \
1230         (previous_words_count == 6 && \
1231          TailMatches6(p1, p2, p3, p4, p5, p6))
1232 #define Matches7(p1, p2, p3, p4, p5, p6, p7) \
1233         (previous_words_count == 7 && \
1234          TailMatches7(p1, p2, p3, p4, p5, p6, p7))
1235 #define Matches8(p1, p2, p3, p4, p5, p6, p7, p8) \
1236         (previous_words_count == 8 && \
1237          TailMatches8(p1, p2, p3, p4, p5, p6, p7, p8))
1238 #define Matches9(p1, p2, p3, p4, p5, p6, p7, p8, p9) \
1239         (previous_words_count == 9 && \
1240          TailMatches9(p1, p2, p3, p4, p5, p6, p7, p8, p9))
1241
1242         /*
1243          * Macros for matching N words at the start of the line, regardless of
1244          * what is after them, case-insensitively.
1245          */
1246 #define HeadMatches1(p1) \
1247         (previous_words_count >= 1 && \
1248          word_matches(p1, previous_words[previous_words_count - 1]))
1249
1250 #define HeadMatches2(p1, p2) \
1251         (previous_words_count >= 2 && \
1252          word_matches(p1, previous_words[previous_words_count - 1]) && \
1253          word_matches(p2, previous_words[previous_words_count - 2]))
1254
1255 #define HeadMatches3(p1, p2, p3) \
1256         (previous_words_count >= 3 && \
1257          word_matches(p1, previous_words[previous_words_count - 1]) && \
1258          word_matches(p2, previous_words[previous_words_count - 2]) && \
1259          word_matches(p3, previous_words[previous_words_count - 3]))
1260
1261         /* Known command-starting keywords. */
1262         static const char *const sql_commands[] = {
1263                 "ABORT", "ALTER", "ANALYZE", "BEGIN", "CHECKPOINT", "CLOSE", "CLUSTER",
1264                 "COMMENT", "COMMIT", "COPY", "CREATE", "DEALLOCATE", "DECLARE",
1265                 "DELETE FROM", "DISCARD", "DO", "DROP", "END", "EXECUTE", "EXPLAIN",
1266                 "FETCH", "GRANT", "IMPORT", "INSERT", "LISTEN", "LOAD", "LOCK",
1267                 "MOVE", "NOTIFY", "PREPARE",
1268                 "REASSIGN", "REFRESH MATERIALIZED VIEW", "REINDEX", "RELEASE",
1269                 "RESET", "REVOKE", "ROLLBACK",
1270                 "SAVEPOINT", "SECURITY LABEL", "SELECT", "SET", "SHOW", "START",
1271                 "TABLE", "TRUNCATE", "UNLISTEN", "UPDATE", "VACUUM", "VALUES", "WITH",
1272                 NULL
1273         };
1274
1275         /* psql's backslash commands. */
1276         static const char *const backslash_commands[] = {
1277                 "\\a", "\\connect", "\\conninfo", "\\C", "\\cd", "\\copy", "\\copyright",
1278                 "\\d", "\\da", "\\db", "\\dc", "\\dC", "\\dd", "\\ddp", "\\dD",
1279                 "\\des", "\\det", "\\deu", "\\dew", "\\dE", "\\df",
1280                 "\\dF", "\\dFd", "\\dFp", "\\dFt", "\\dg", "\\di", "\\dl", "\\dL",
1281                 "\\dm", "\\dn", "\\do", "\\dO", "\\dp", "\\drds", "\\ds", "\\dS",
1282                 "\\dt", "\\dT", "\\dv", "\\du", "\\dx", "\\dy",
1283                 "\\e", "\\echo", "\\ef", "\\encoding", "\\errverbose", "\\ev",
1284                 "\\f", "\\g", "\\gexec", "\\gset", "\\h", "\\help", "\\H", "\\i", "\\ir", "\\l",
1285                 "\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",
1286                 "\\o", "\\p", "\\password", "\\prompt", "\\pset", "\\q", "\\qecho", "\\r",
1287                 "\\s", "\\set", "\\setenv", "\\sf", "\\sv", "\\t", "\\T",
1288                 "\\timing", "\\unset", "\\x", "\\w", "\\watch", "\\z", "\\!", NULL
1289         };
1290
1291         (void) end;                                     /* "end" is not used */
1292
1293 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
1294         rl_completion_append_character = ' ';
1295 #endif
1296
1297         /* Clear a few things. */
1298         completion_charp = NULL;
1299         completion_charpp = NULL;
1300         completion_info_charp = NULL;
1301         completion_info_charp2 = NULL;
1302
1303         /*
1304          * Scan the input line to extract the words before our current position.
1305          * According to those we'll make some smart decisions on what the user is
1306          * probably intending to type.
1307          */
1308         previous_words = get_previous_words(start,
1309                                                                                 &words_buffer,
1310                                                                                 &previous_words_count);
1311
1312         /* If current word is a backslash command, offer completions for that */
1313         if (text[0] == '\\')
1314                 COMPLETE_WITH_LIST_CS(backslash_commands);
1315
1316         /* If current word is a variable interpolation, handle that case */
1317         else if (text[0] == ':' && text[1] != ':')
1318         {
1319                 if (text[1] == '\'')
1320                         matches = complete_from_variables(text, ":'", "'", true);
1321                 else if (text[1] == '"')
1322                         matches = complete_from_variables(text, ":\"", "\"", true);
1323                 else
1324                         matches = complete_from_variables(text, ":", "", true);
1325         }
1326
1327         /* If no previous word, suggest one of the basic sql commands */
1328         else if (previous_words_count == 0)
1329                 COMPLETE_WITH_LIST(sql_commands);
1330
1331 /* CREATE */
1332         /* complete with something you can create */
1333         else if (TailMatches1("CREATE"))
1334                 matches = completion_matches(text, create_command_generator);
1335
1336 /* DROP, but not DROP embedded in other commands */
1337         /* complete with something you can drop */
1338         else if (Matches1("DROP"))
1339                 matches = completion_matches(text, drop_command_generator);
1340
1341 /* ALTER */
1342
1343         /* ALTER TABLE */
1344         else if (Matches2("ALTER", "TABLE"))
1345                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
1346                                                                    "UNION SELECT 'ALL IN TABLESPACE'");
1347
1348         /* ALTER something */
1349         else if (Matches1("ALTER"))
1350         {
1351                 static const char *const list_ALTER[] =
1352                 {"AGGREGATE", "COLLATION", "CONVERSION", "DATABASE", "DEFAULT PRIVILEGES", "DOMAIN",
1353                         "EVENT TRIGGER", "EXTENSION", "FOREIGN DATA WRAPPER", "FOREIGN TABLE", "FUNCTION",
1354                         "GROUP", "INDEX", "LANGUAGE", "LARGE OBJECT", "MATERIALIZED VIEW", "OPERATOR",
1355                         "POLICY", "ROLE", "RULE", "SCHEMA", "SERVER", "SEQUENCE", "SYSTEM", "TABLE",
1356                         "TABLESPACE", "TEXT SEARCH", "TRIGGER", "TYPE",
1357                 "USER", "USER MAPPING FOR", "VIEW", NULL};
1358
1359                 COMPLETE_WITH_LIST(list_ALTER);
1360         }
1361         /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx */
1362         else if (TailMatches4("ALL", "IN", "TABLESPACE", MatchAny))
1363                 COMPLETE_WITH_LIST2("SET TABLESPACE", "OWNED BY");
1364         /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY */
1365         else if (TailMatches6("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY"))
1366                 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
1367         /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY xxx */
1368         else if (TailMatches7("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY", MatchAny))
1369                 COMPLETE_WITH_CONST("SET TABLESPACE");
1370         /* ALTER AGGREGATE,FUNCTION <name> */
1371         else if (Matches3("ALTER", "AGGREGATE|FUNCTION", MatchAny))
1372                 COMPLETE_WITH_CONST("(");
1373         /* ALTER AGGREGATE,FUNCTION <name> (...) */
1374         else if (Matches4("ALTER", "AGGREGATE|FUNCTION", MatchAny, MatchAny))
1375         {
1376                 if (ends_with(prev_wd, ')'))
1377                         COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1378                 else
1379                         COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
1380         }
1381
1382         /* ALTER SCHEMA <name> */
1383         else if (Matches3("ALTER", "SCHEMA", MatchAny))
1384                 COMPLETE_WITH_LIST2("OWNER TO", "RENAME TO");
1385
1386         /* ALTER COLLATION <name> */
1387         else if (Matches3("ALTER", "COLLATION", MatchAny))
1388                 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1389
1390         /* ALTER CONVERSION <name> */
1391         else if (Matches3("ALTER", "CONVERSION", MatchAny))
1392                 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1393
1394         /* ALTER DATABASE <name> */
1395         else if (Matches3("ALTER", "DATABASE", MatchAny))
1396                 COMPLETE_WITH_LIST7("RESET", "SET", "OWNER TO", "RENAME TO",
1397                                                         "IS_TEMPLATE", "ALLOW_CONNECTIONS",
1398                                                         "CONNECTION LIMIT");
1399
1400         /* ALTER EVENT TRIGGER */
1401         else if (Matches3("ALTER", "EVENT", "TRIGGER"))
1402                 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
1403
1404         /* ALTER EVENT TRIGGER <name> */
1405         else if (Matches4("ALTER", "EVENT", "TRIGGER", MatchAny))
1406                 COMPLETE_WITH_LIST4("DISABLE", "ENABLE", "OWNER TO", "RENAME TO");
1407
1408         /* ALTER EVENT TRIGGER <name> ENABLE */
1409         else if (Matches5("ALTER", "EVENT", "TRIGGER", MatchAny, "ENABLE"))
1410                 COMPLETE_WITH_LIST2("REPLICA", "ALWAYS");
1411
1412         /* ALTER EXTENSION <name> */
1413         else if (Matches3("ALTER", "EXTENSION", MatchAny))
1414                 COMPLETE_WITH_LIST4("ADD", "DROP", "UPDATE", "SET SCHEMA");
1415
1416         /* ALTER FOREIGN */
1417         else if (Matches2("ALTER", "FOREIGN"))
1418                 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
1419
1420         /* ALTER FOREIGN DATA WRAPPER <name> */
1421         else if (Matches5("ALTER", "FOREIGN", "DATA", "WRAPPER", MatchAny))
1422                 COMPLETE_WITH_LIST5("HANDLER", "VALIDATOR", "OPTIONS", "OWNER TO", "RENAME TO");
1423
1424         /* ALTER FOREIGN TABLE <name> */
1425         else if (Matches4("ALTER", "FOREIGN", "TABLE", MatchAny))
1426         {
1427                 static const char *const list_ALTER_FOREIGN_TABLE[] =
1428                 {"ADD", "ALTER", "DISABLE TRIGGER", "DROP", "ENABLE", "INHERIT",
1429                         "NO INHERIT", "OPTIONS", "OWNER TO", "RENAME", "SET",
1430                 "VALIDATE CONSTRAINT", NULL};
1431
1432                 COMPLETE_WITH_LIST(list_ALTER_FOREIGN_TABLE);
1433         }
1434
1435         /* ALTER INDEX */
1436         else if (Matches2("ALTER", "INDEX"))
1437                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
1438                                                                    "UNION SELECT 'ALL IN TABLESPACE'");
1439         /* ALTER INDEX <name> */
1440         else if (Matches3("ALTER", "INDEX", MatchAny))
1441                 COMPLETE_WITH_LIST4("OWNER TO", "RENAME TO", "SET", "RESET");
1442         /* ALTER INDEX <name> SET */
1443         else if (Matches4("ALTER", "INDEX", MatchAny, "SET"))
1444                 COMPLETE_WITH_LIST2("(", "TABLESPACE");
1445         /* ALTER INDEX <name> RESET */
1446         else if (Matches4("ALTER", "INDEX", MatchAny, "RESET"))
1447                 COMPLETE_WITH_CONST("(");
1448         /* ALTER INDEX <foo> SET|RESET ( */
1449         else if (Matches5("ALTER", "INDEX", MatchAny, "RESET", "("))
1450                 COMPLETE_WITH_LIST3("fillfactor", "fastupdate",
1451                                                         "gin_pending_list_limit");
1452         else if (Matches5("ALTER", "INDEX", MatchAny, "SET", "("))
1453                 COMPLETE_WITH_LIST3("fillfactor =", "fastupdate =",
1454                                                         "gin_pending_list_limit =");
1455
1456         /* ALTER LANGUAGE <name> */
1457         else if (Matches3("ALTER", "LANGUAGE", MatchAny))
1458                 COMPLETE_WITH_LIST2("OWNER_TO", "RENAME TO");
1459
1460         /* ALTER LARGE OBJECT <oid> */
1461         else if (Matches4("ALTER", "LARGE", "OBJECT", MatchAny))
1462                 COMPLETE_WITH_CONST("OWNER TO");
1463
1464         /* ALTER MATERIALIZED VIEW */
1465         else if (Matches3("ALTER", "MATERIALIZED", "VIEW"))
1466                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews,
1467                                                                    "UNION SELECT 'ALL IN TABLESPACE'");
1468
1469         /* ALTER USER,ROLE <name> */
1470         else if (Matches3("ALTER", "USER|ROLE", MatchAny) &&
1471                          !TailMatches2("USER", "MAPPING"))
1472         {
1473                 static const char *const list_ALTERUSER[] =
1474                 {"BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
1475                         "ENCRYPTED", "INHERIT", "LOGIN", "NOBYPASSRLS",
1476                         "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
1477                         "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD", "RENAME TO",
1478                         "REPLICATION", "RESET", "SET", "SUPERUSER", "UNENCRYPTED",
1479                 "VALID UNTIL", "WITH", NULL};
1480
1481                 COMPLETE_WITH_LIST(list_ALTERUSER);
1482         }
1483
1484         /* ALTER USER,ROLE <name> WITH */
1485         else if (Matches4("ALTER", "USER|ROLE", MatchAny, "WITH"))
1486         {
1487                 /* Similar to the above, but don't complete "WITH" again. */
1488                 static const char *const list_ALTERUSER_WITH[] =
1489                 {"BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
1490                         "ENCRYPTED", "INHERIT", "LOGIN", "NOBYPASSRLS",
1491                         "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
1492                         "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD", "RENAME TO",
1493                         "REPLICATION", "RESET", "SET", "SUPERUSER", "UNENCRYPTED",
1494                 "VALID UNTIL", NULL};
1495
1496                 COMPLETE_WITH_LIST(list_ALTERUSER_WITH);
1497         }
1498
1499         /* complete ALTER USER,ROLE <name> ENCRYPTED,UNENCRYPTED with PASSWORD */
1500         else if (Matches4("ALTER", "USER|ROLE", MatchAny, "ENCRYPTED|UNENCRYPTED"))
1501                 COMPLETE_WITH_CONST("PASSWORD");
1502         /* ALTER DEFAULT PRIVILEGES */
1503         else if (Matches3("ALTER", "DEFAULT", "PRIVILEGES"))
1504                 COMPLETE_WITH_LIST3("FOR ROLE", "FOR USER", "IN SCHEMA");
1505         /* ALTER DEFAULT PRIVILEGES FOR */
1506         else if (Matches4("ALTER", "DEFAULT", "PRIVILEGES", "FOR"))
1507                 COMPLETE_WITH_LIST2("ROLE", "USER");
1508         /* ALTER DEFAULT PRIVILEGES { FOR ROLE ... | IN SCHEMA ... } */
1509         else if (Matches6("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER", MatchAny) ||
1510                 Matches6("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA", MatchAny))
1511                 COMPLETE_WITH_LIST2("GRANT", "REVOKE");
1512         /* ALTER DOMAIN <name> */
1513         else if (Matches3("ALTER", "DOMAIN", MatchAny))
1514                 COMPLETE_WITH_LIST6("ADD", "DROP", "OWNER TO", "RENAME", "SET",
1515                                                         "VALIDATE CONSTRAINT");
1516         /* ALTER DOMAIN <sth> DROP */
1517         else if (Matches4("ALTER", "DOMAIN", MatchAny, "DROP"))
1518                 COMPLETE_WITH_LIST3("CONSTRAINT", "DEFAULT", "NOT NULL");
1519         /* ALTER DOMAIN <sth> DROP|RENAME|VALIDATE CONSTRAINT */
1520         else if (Matches5("ALTER", "DOMAIN", MatchAny, "DROP|RENAME|VALIDATE", "CONSTRAINT"))
1521         {
1522                 completion_info_charp = prev3_wd;
1523                 COMPLETE_WITH_QUERY(Query_for_constraint_of_type);
1524         }
1525         /* ALTER DOMAIN <sth> RENAME */
1526         else if (Matches4("ALTER", "DOMAIN", MatchAny, "RENAME"))
1527                 COMPLETE_WITH_LIST2("CONSTRAINT", "TO");
1528         /* ALTER DOMAIN <sth> RENAME CONSTRAINT <sth> */
1529         else if (Matches6("ALTER", "DOMAIN", MatchAny, "RENAME", "CONSTRAINT", MatchAny))
1530                 COMPLETE_WITH_CONST("TO");
1531
1532         /* ALTER DOMAIN <sth> SET */
1533         else if (Matches4("ALTER", "DOMAIN", MatchAny, "SET"))
1534                 COMPLETE_WITH_LIST3("DEFAULT", "NOT NULL", "SCHEMA");
1535         /* ALTER SEQUENCE <name> */
1536         else if (Matches3("ALTER", "SEQUENCE", MatchAny))
1537         {
1538                 static const char *const list_ALTERSEQUENCE[] =
1539                 {"INCREMENT", "MINVALUE", "MAXVALUE", "RESTART", "NO", "CACHE", "CYCLE",
1540                 "SET SCHEMA", "OWNED BY", "OWNER TO", "RENAME TO", NULL};
1541
1542                 COMPLETE_WITH_LIST(list_ALTERSEQUENCE);
1543         }
1544         /* ALTER SEQUENCE <name> NO */
1545         else if (Matches4("ALTER", "SEQUENCE", MatchAny, "NO"))
1546                 COMPLETE_WITH_LIST3("MINVALUE", "MAXVALUE", "CYCLE");
1547         /* ALTER SERVER <name> */
1548         else if (Matches3("ALTER", "SERVER", MatchAny))
1549                 COMPLETE_WITH_LIST4("VERSION", "OPTIONS", "OWNER TO", "RENAME TO");
1550         /* ALTER SERVER <name> VERSION <version>*/
1551         else if (Matches5("ALTER", "SERVER", MatchAny, "VERSION", MatchAny))
1552                 COMPLETE_WITH_CONST("OPTIONS");
1553         /* ALTER SYSTEM SET, RESET, RESET ALL */
1554         else if (Matches2("ALTER", "SYSTEM"))
1555                 COMPLETE_WITH_LIST2("SET", "RESET");
1556         /* ALTER SYSTEM SET|RESET <name> */
1557         else if (Matches3("ALTER", "SYSTEM", "SET|RESET"))
1558                 COMPLETE_WITH_QUERY(Query_for_list_of_alter_system_set_vars);
1559         /* ALTER VIEW <name> */
1560         else if (Matches3("ALTER", "VIEW", MatchAny))
1561                 COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO",
1562                                                         "SET SCHEMA");
1563         /* ALTER MATERIALIZED VIEW <name> */
1564         else if (Matches4("ALTER", "MATERIALIZED", "VIEW", MatchAny))
1565                 COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO",
1566                                                         "SET SCHEMA");
1567
1568         /* ALTER POLICY <name> */
1569         else if (Matches2("ALTER", "POLICY"))
1570                 COMPLETE_WITH_QUERY(Query_for_list_of_policies);
1571         /* ALTER POLICY <name> ON */
1572         else if (Matches3("ALTER", "POLICY", MatchAny))
1573                 COMPLETE_WITH_CONST("ON");
1574         /* ALTER POLICY <name> ON <table> */
1575         else if (Matches4("ALTER", "POLICY", MatchAny, "ON"))
1576         {
1577                 completion_info_charp = prev2_wd;
1578                 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_policy);
1579         }
1580         /* ALTER POLICY <name> ON <table> - show options */
1581         else if (Matches5("ALTER", "POLICY", MatchAny, "ON", MatchAny))
1582                 COMPLETE_WITH_LIST4("RENAME TO", "TO", "USING (", "WITH CHECK (");
1583         /* ALTER POLICY <name> ON <table> TO <role> */
1584         else if (Matches6("ALTER", "POLICY", MatchAny, "ON", MatchAny, "TO"))
1585                 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
1586         /* ALTER POLICY <name> ON <table> USING ( */
1587         else if (Matches6("ALTER", "POLICY", MatchAny, "ON", MatchAny, "USING"))
1588                 COMPLETE_WITH_CONST("(");
1589         /* ALTER POLICY <name> ON <table> WITH CHECK ( */
1590         else if (Matches7("ALTER", "POLICY", MatchAny, "ON", MatchAny, "WITH", "CHECK"))
1591                 COMPLETE_WITH_CONST("(");
1592
1593         /* ALTER RULE <name>, add ON */
1594         else if (Matches3("ALTER", "RULE", MatchAny))
1595                 COMPLETE_WITH_CONST("ON");
1596
1597         /* If we have ALTER RULE <name> ON, then add the correct tablename */
1598         else if (Matches4("ALTER", "RULE", MatchAny, "ON"))
1599         {
1600                 completion_info_charp = prev2_wd;
1601                 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule);
1602         }
1603
1604         /* ALTER RULE <name> ON <name> */
1605         else if (Matches5("ALTER", "RULE", MatchAny, "ON", MatchAny))
1606                 COMPLETE_WITH_CONST("RENAME TO");
1607
1608         /* ALTER TRIGGER <name>, add ON */
1609         else if (Matches3("ALTER", "TRIGGER", MatchAny))
1610                 COMPLETE_WITH_CONST("ON");
1611
1612         else if (Matches4("ALTER", "TRIGGER", MatchAny, MatchAny))
1613         {
1614                 completion_info_charp = prev2_wd;
1615                 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger);
1616         }
1617
1618         /*
1619          * If we have ALTER TRIGGER <sth> ON, then add the correct tablename
1620          */
1621         else if (Matches4("ALTER", "TRIGGER", MatchAny, "ON"))
1622                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
1623
1624         /* ALTER TRIGGER <name> ON <name> */
1625         else if (Matches5("ALTER", "TRIGGER", MatchAny, "ON", MatchAny))
1626                 COMPLETE_WITH_CONST("RENAME TO");
1627
1628         /*
1629          * If we detect ALTER TABLE <name>, suggest sub commands
1630          */
1631         else if (Matches3("ALTER", "TABLE", MatchAny))
1632         {
1633                 static const char *const list_ALTER2[] =
1634                 {"ADD", "ALTER", "CLUSTER ON", "DISABLE", "DROP", "ENABLE", "INHERIT",
1635                         "NO INHERIT", "RENAME", "RESET", "OWNER TO", "SET",
1636                 "VALIDATE CONSTRAINT", "REPLICA IDENTITY", NULL};
1637
1638                 COMPLETE_WITH_LIST(list_ALTER2);
1639         }
1640         /* ALTER TABLE xxx ENABLE */
1641         else if (Matches4("ALTER", "TABLE", MatchAny, "ENABLE"))
1642                 COMPLETE_WITH_LIST5("ALWAYS", "REPLICA", "ROW LEVEL SECURITY", "RULE",
1643                                                         "TRIGGER");
1644         else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "REPLICA|ALWAYS"))
1645                 COMPLETE_WITH_LIST2("RULE", "TRIGGER");
1646         else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "RULE"))
1647         {
1648                 completion_info_charp = prev3_wd;
1649                 COMPLETE_WITH_QUERY(Query_for_rule_of_table);
1650         }
1651         else if (Matches6("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "RULE"))
1652         {
1653                 completion_info_charp = prev4_wd;
1654                 COMPLETE_WITH_QUERY(Query_for_rule_of_table);
1655         }
1656         else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "TRIGGER"))
1657         {
1658                 completion_info_charp = prev3_wd;
1659                 COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
1660         }
1661         else if (Matches6("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "TRIGGER"))
1662         {
1663                 completion_info_charp = prev4_wd;
1664                 COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
1665         }
1666         /* ALTER TABLE xxx INHERIT */
1667         else if (Matches4("ALTER", "TABLE", MatchAny, "INHERIT"))
1668                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
1669         /* ALTER TABLE xxx NO INHERIT */
1670         else if (Matches5("ALTER", "TABLE", MatchAny, "NO", "INHERIT"))
1671                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
1672         /* ALTER TABLE xxx DISABLE */
1673         else if (Matches4("ALTER", "TABLE", MatchAny, "DISABLE"))
1674                 COMPLETE_WITH_LIST3("ROW LEVEL SECURITY", "RULE", "TRIGGER");
1675         else if (Matches5("ALTER", "TABLE", MatchAny, "DISABLE", "RULE"))
1676         {
1677                 completion_info_charp = prev3_wd;
1678                 COMPLETE_WITH_QUERY(Query_for_rule_of_table);
1679         }
1680         else if (Matches5("ALTER", "TABLE", MatchAny, "DISABLE", "TRIGGER"))
1681         {
1682                 completion_info_charp = prev3_wd;
1683                 COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
1684         }
1685
1686         /* ALTER TABLE xxx ALTER */
1687         else if (Matches4("ALTER", "TABLE", MatchAny, "ALTER"))
1688                 COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT'");
1689
1690         /* ALTER TABLE xxx RENAME */
1691         else if (Matches4("ALTER", "TABLE", MatchAny, "RENAME"))
1692                 COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT' UNION SELECT 'TO'");
1693         else if (Matches5("ALTER", "TABLE", MatchAny, "ALTER|RENAME", "COLUMN"))
1694                 COMPLETE_WITH_ATTR(prev3_wd, "");
1695
1696         /* ALTER TABLE xxx RENAME yyy */
1697         else if (Matches5("ALTER", "TABLE", MatchAny, "RENAME", MatchAnyExcept("CONSTRAINT|TO")))
1698                 COMPLETE_WITH_CONST("TO");
1699
1700         /* ALTER TABLE xxx RENAME COLUMN/CONSTRAINT yyy */
1701         else if (Matches6("ALTER", "TABLE", MatchAny, "RENAME", "COLUMN|CONSTRAINT", MatchAnyExcept("TO")))
1702                 COMPLETE_WITH_CONST("TO");
1703
1704         /* If we have ALTER TABLE <sth> DROP, provide COLUMN or CONSTRAINT */
1705         else if (Matches4("ALTER", "TABLE", MatchAny, "DROP"))
1706                 COMPLETE_WITH_LIST2("COLUMN", "CONSTRAINT");
1707         /* If we have ALTER TABLE <sth> DROP COLUMN, provide list of columns */
1708         else if (Matches5("ALTER", "TABLE", MatchAny, "DROP", "COLUMN"))
1709                 COMPLETE_WITH_ATTR(prev3_wd, "");
1710
1711         /*
1712          * If we have ALTER TABLE <sth> ALTER|DROP|RENAME|VALIDATE CONSTRAINT,
1713          * provide list of constraints
1714          */
1715         else if (Matches5("ALTER", "TABLE", MatchAny, "ALTER|DROP|RENAME|VALIDATE", "CONSTRAINT"))
1716         {
1717                 completion_info_charp = prev3_wd;
1718                 COMPLETE_WITH_QUERY(Query_for_constraint_of_table);
1719         }
1720         /* ALTER TABLE ALTER [COLUMN] <foo> */
1721         else if (Matches6("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny) ||
1722                          Matches5("ALTER", "TABLE", MatchAny, "ALTER", MatchAny))
1723                 COMPLETE_WITH_LIST4("TYPE", "SET", "RESET", "DROP");
1724         /* ALTER TABLE ALTER [COLUMN] <foo> SET */
1725         else if (Matches7("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET") ||
1726                          Matches6("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET"))
1727                 COMPLETE_WITH_LIST5("(", "DEFAULT", "NOT NULL", "STATISTICS", "STORAGE");
1728         /* ALTER TABLE ALTER [COLUMN] <foo> SET ( */
1729         else if (Matches8("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "(") ||
1730                  Matches7("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "("))
1731                 COMPLETE_WITH_LIST2("n_distinct", "n_distinct_inherited");
1732         /* ALTER TABLE ALTER [COLUMN] <foo> SET STORAGE */
1733         else if (Matches8("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "STORAGE") ||
1734         Matches7("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "STORAGE"))
1735                 COMPLETE_WITH_LIST4("PLAIN", "EXTERNAL", "EXTENDED", "MAIN");
1736         /* ALTER TABLE ALTER [COLUMN] <foo> DROP */
1737         else if (Matches7("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "DROP") ||
1738                          Matches8("ALTER", "TABLE", MatchAny, "TABLE", MatchAny, "ALTER", MatchAny, "DROP"))
1739                 COMPLETE_WITH_LIST2("DEFAULT", "NOT NULL");
1740         else if (Matches4("ALTER", "TABLE", MatchAny, "CLUSTER"))
1741                 COMPLETE_WITH_CONST("ON");
1742         else if (Matches5("ALTER", "TABLE", MatchAny, "CLUSTER", "ON"))
1743         {
1744                 completion_info_charp = prev3_wd;
1745                 COMPLETE_WITH_QUERY(Query_for_index_of_table);
1746         }
1747         /* If we have ALTER TABLE <sth> SET, provide list of attributes and '(' */
1748         else if (Matches4("ALTER", "TABLE", MatchAny, "SET"))
1749                 COMPLETE_WITH_LIST7("(", "LOGGED", "SCHEMA", "TABLESPACE", "UNLOGGED",
1750                                                         "WITH", "WITHOUT");
1751
1752         /*
1753          * If we have ALTER TABLE <sth> SET TABLESPACE provide a list of
1754          * tablespaces
1755          */
1756         else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "TABLESPACE"))
1757                 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
1758         /* If we have ALTER TABLE <sth> SET WITH provide OIDS */
1759         else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "WITH"))
1760                 COMPLETE_WITH_CONST("OIDS");
1761         /* If we have ALTER TABLE <sth> SET WITHOUT provide CLUSTER or OIDS */
1762         else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "WITHOUT"))
1763                 COMPLETE_WITH_LIST2("CLUSTER", "OIDS");
1764         /* ALTER TABLE <foo> RESET */
1765         else if (Matches4("ALTER", "TABLE", MatchAny, "RESET"))
1766                 COMPLETE_WITH_CONST("(");
1767         /* ALTER TABLE <foo> SET|RESET ( */
1768         else if (Matches5("ALTER", "TABLE", MatchAny, "SET|RESET", "("))
1769         {
1770                 static const char *const list_TABLEOPTIONS[] =
1771                 {
1772                         "autovacuum_analyze_scale_factor",
1773                         "autovacuum_analyze_threshold",
1774                         "autovacuum_enabled",
1775                         "autovacuum_freeze_max_age",
1776                         "autovacuum_freeze_min_age",
1777                         "autovacuum_freeze_table_age",
1778                         "autovacuum_multixact_freeze_max_age",
1779                         "autovacuum_multixact_freeze_min_age",
1780                         "autovacuum_multixact_freeze_table_age",
1781                         "autovacuum_vacuum_cost_delay",
1782                         "autovacuum_vacuum_cost_limit",
1783                         "autovacuum_vacuum_scale_factor",
1784                         "autovacuum_vacuum_threshold",
1785                         "fillfactor",
1786                         "parallel_degree",
1787                         "log_autovacuum_min_duration",
1788                         "toast.autovacuum_enabled",
1789                         "toast.autovacuum_freeze_max_age",
1790                         "toast.autovacuum_freeze_min_age",
1791                         "toast.autovacuum_freeze_table_age",
1792                         "toast.autovacuum_multixact_freeze_max_age",
1793                         "toast.autovacuum_multixact_freeze_min_age",
1794                         "toast.autovacuum_multixact_freeze_table_age",
1795                         "toast.autovacuum_vacuum_cost_delay",
1796                         "toast.autovacuum_vacuum_cost_limit",
1797                         "toast.autovacuum_vacuum_scale_factor",
1798                         "toast.autovacuum_vacuum_threshold",
1799                         "toast.log_autovacuum_min_duration",
1800                         "user_catalog_table",
1801                         NULL
1802                 };
1803
1804                 COMPLETE_WITH_LIST(list_TABLEOPTIONS);
1805         }
1806         else if (Matches7("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING", "INDEX"))
1807         {
1808                 completion_info_charp = prev5_wd;
1809                 COMPLETE_WITH_QUERY(Query_for_index_of_table);
1810         }
1811         else if (Matches6("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING"))
1812                 COMPLETE_WITH_CONST("INDEX");
1813         else if (Matches5("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY"))
1814                 COMPLETE_WITH_LIST4("FULL", "NOTHING", "DEFAULT", "USING");
1815         else if (Matches4("ALTER", "TABLE", MatchAny, "REPLICA"))
1816                 COMPLETE_WITH_CONST("IDENTITY");
1817
1818         /* ALTER TABLESPACE <foo> with RENAME TO, OWNER TO, SET, RESET */
1819         else if (Matches3("ALTER", "TABLESPACE", MatchAny))
1820                 COMPLETE_WITH_LIST4("RENAME TO", "OWNER TO", "SET", "RESET");
1821         /* ALTER TABLESPACE <foo> SET|RESET */
1822         else if (Matches4("ALTER", "TABLESPACE", MatchAny, "SET|RESET"))
1823                 COMPLETE_WITH_CONST("(");
1824         /* ALTER TABLESPACE <foo> SET|RESET ( */
1825         else if (Matches5("ALTER", "TABLESPACE", MatchAny, "SET|RESET", "("))
1826                 COMPLETE_WITH_LIST3("seq_page_cost", "random_page_cost",
1827                                                         "effective_io_concurrency");
1828
1829         /* ALTER TEXT SEARCH */
1830         else if (Matches3("ALTER", "TEXT", "SEARCH"))
1831                 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
1832         else if (Matches5("ALTER", "TEXT", "SEARCH", "TEMPLATE|PARSER", MatchAny))
1833                 COMPLETE_WITH_LIST2("RENAME TO", "SET SCHEMA");
1834         else if (Matches5("ALTER", "TEXT", "SEARCH", "DICTIONARY", MatchAny))
1835                 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1836         else if (Matches5("ALTER", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
1837                 COMPLETE_WITH_LIST6("ADD MAPPING FOR", "ALTER MAPPING",
1838                                                         "DROP MAPPING FOR",
1839                                                         "OWNER TO", "RENAME TO", "SET SCHEMA");
1840
1841         /* complete ALTER TYPE <foo> with actions */
1842         else if (Matches3("ALTER", "TYPE", MatchAny))
1843                 COMPLETE_WITH_LIST7("ADD ATTRIBUTE", "ADD VALUE", "ALTER ATTRIBUTE",
1844                                                         "DROP ATTRIBUTE",
1845                                                         "OWNER TO", "RENAME", "SET SCHEMA");
1846         /* complete ALTER TYPE <foo> ADD with actions */
1847         else if (Matches4("ALTER", "TYPE", MatchAny, "ADD"))
1848                 COMPLETE_WITH_LIST2("ATTRIBUTE", "VALUE");
1849         /* ALTER TYPE <foo> RENAME      */
1850         else if (Matches4("ALTER", "TYPE", MatchAny, "RENAME"))
1851                 COMPLETE_WITH_LIST2("ATTRIBUTE", "TO");
1852         /* ALTER TYPE xxx RENAME ATTRIBUTE yyy */
1853         else if (Matches6("ALTER", "TYPE", MatchAny, "RENAME", "ATTRIBUTE", MatchAny))
1854                 COMPLETE_WITH_CONST("TO");
1855
1856         /*
1857          * If we have ALTER TYPE <sth> ALTER/DROP/RENAME ATTRIBUTE, provide list
1858          * of attributes
1859          */
1860         else if (Matches5("ALTER", "TYPE", MatchAny, "ALTER|DROP|RENAME", "ATTRIBUTE"))
1861                 COMPLETE_WITH_ATTR(prev3_wd, "");
1862         /* ALTER TYPE ALTER ATTRIBUTE <foo> */
1863         else if (Matches6("ALTER", "TYPE", MatchAny, "ALTER", "ATTRIBUTE", MatchAny))
1864                 COMPLETE_WITH_CONST("TYPE");
1865         /* complete ALTER GROUP <foo> */
1866         else if (Matches3("ALTER", "GROUP", MatchAny))
1867                 COMPLETE_WITH_LIST3("ADD USER", "DROP USER", "RENAME TO");
1868         /* complete ALTER GROUP <foo> ADD|DROP with USER */
1869         else if (Matches4("ALTER", "GROUP", MatchAny, "ADD|DROP"))
1870                 COMPLETE_WITH_CONST("USER");
1871         /* complete ALTER GROUP <foo> ADD|DROP USER with a user name */
1872         else if (Matches5("ALTER", "GROUP", MatchAny, "ADD|DROP", "USER"))
1873                 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
1874
1875 /* BEGIN, END, ABORT */
1876         else if (Matches1("BEGIN|END|ABORT"))
1877                 COMPLETE_WITH_LIST2("WORK", "TRANSACTION");
1878 /* COMMIT */
1879         else if (Matches1("COMMIT"))
1880                 COMPLETE_WITH_LIST3("WORK", "TRANSACTION", "PREPARED");
1881 /* RELEASE SAVEPOINT */
1882         else if (Matches1("RELEASE"))
1883                 COMPLETE_WITH_CONST("SAVEPOINT");
1884 /* ROLLBACK */
1885         else if (Matches1("ROLLBACK"))
1886                 COMPLETE_WITH_LIST4("WORK", "TRANSACTION", "TO SAVEPOINT", "PREPARED");
1887 /* CLUSTER */
1888         else if (Matches1("CLUSTER"))
1889                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, "UNION SELECT 'VERBOSE'");
1890         else if (Matches2("CLUSTER", "VERBOSE"))
1891                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
1892         /* If we have CLUSTER <sth>, then add "USING" */
1893         else if (Matches2("CLUSTER", MatchAnyExcept("VERBOSE|ON")))
1894                 COMPLETE_WITH_CONST("USING");
1895         /* If we have CLUSTER VERBOSE <sth>, then add "USING" */
1896         else if (Matches3("CLUSTER", "VERBOSE", MatchAny))
1897                 COMPLETE_WITH_CONST("USING");
1898         /* If we have CLUSTER <sth> USING, then add the index as well */
1899         else if (Matches3("CLUSTER", MatchAny, "USING") ||
1900                          Matches4("CLUSTER", "VERBOSE", MatchAny, "USING"))
1901         {
1902                 completion_info_charp = prev2_wd;
1903                 COMPLETE_WITH_QUERY(Query_for_index_of_table);
1904         }
1905
1906 /* COMMENT */
1907         else if (Matches1("COMMENT"))
1908                 COMPLETE_WITH_CONST("ON");
1909         else if (Matches2("COMMENT", "ON"))
1910         {
1911                 static const char *const list_COMMENT[] =
1912                 {"CAST", "COLLATION", "CONVERSION", "DATABASE", "EVENT TRIGGER", "EXTENSION",
1913                         "FOREIGN DATA WRAPPER", "FOREIGN TABLE",
1914                         "SERVER", "INDEX", "LANGUAGE", "POLICY", "RULE", "SCHEMA", "SEQUENCE",
1915                         "TABLE", "TYPE", "VIEW", "MATERIALIZED VIEW", "COLUMN", "AGGREGATE", "FUNCTION",
1916                         "OPERATOR", "TRIGGER", "CONSTRAINT", "DOMAIN", "LARGE OBJECT",
1917                 "TABLESPACE", "TEXT SEARCH", "ROLE", NULL};
1918
1919                 COMPLETE_WITH_LIST(list_COMMENT);
1920         }
1921         else if (Matches3("COMMENT", "ON", "FOREIGN"))
1922                 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
1923         else if (Matches4("COMMENT", "ON", "TEXT", "SEARCH"))
1924                 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
1925         else if (Matches3("COMMENT", "ON", "CONSTRAINT"))
1926                 COMPLETE_WITH_QUERY(Query_for_all_table_constraints);
1927         else if (Matches4("COMMENT", "ON", "CONSTRAINT", MatchAny))
1928                 COMPLETE_WITH_CONST("ON");
1929         else if (Matches5("COMMENT", "ON", "CONSTRAINT", MatchAny, "ON"))
1930         {
1931                 completion_info_charp = prev2_wd;
1932                 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_constraint);
1933         }
1934         else if (Matches4("COMMENT", "ON", "MATERIALIZED", "VIEW"))
1935                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
1936         else if (Matches4("COMMENT", "ON", "EVENT", "TRIGGER"))
1937                 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
1938         else if (Matches4("COMMENT", "ON", MatchAny, MatchAnyExcept("IS")) ||
1939                 Matches5("COMMENT", "ON", MatchAny, MatchAny, MatchAnyExcept("IS")) ||
1940                          Matches6("COMMENT", "ON", MatchAny, MatchAny, MatchAny, MatchAnyExcept("IS")))
1941                 COMPLETE_WITH_CONST("IS");
1942
1943 /* COPY */
1944
1945         /*
1946          * If we have COPY, offer list of tables or "(" (Also cover the analogous
1947          * backslash command).
1948          */
1949         else if (Matches1("COPY|\\copy"))
1950                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
1951                                                                    " UNION ALL SELECT '('");
1952         /* If we have COPY BINARY, complete with list of tables */
1953         else if (Matches2("COPY", "BINARY"))
1954                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
1955         /* If we have COPY (, complete it with legal commands */
1956         else if (Matches2("COPY|\\copy", "("))
1957                 COMPLETE_WITH_LIST7("SELECT", "TABLE", "VALUES", "INSERT", "UPDATE", "DELETE", "WITH");
1958         /* If we have COPY [BINARY] <sth>, complete it with "TO" or "FROM" */
1959         else if (Matches2("COPY|\\copy", MatchAny) ||
1960                          Matches3("COPY", "BINARY", MatchAny))
1961                 COMPLETE_WITH_LIST2("FROM", "TO");
1962         /* If we have COPY [BINARY] <sth> FROM|TO, complete with filename */
1963         else if (Matches3("COPY|\\copy", MatchAny, "FROM|TO") ||
1964                          Matches4("COPY", "BINARY", MatchAny, "FROM|TO"))
1965         {
1966                 completion_charp = "";
1967                 matches = completion_matches(text, complete_from_files);
1968         }
1969
1970         /* Handle COPY [BINARY] <sth> FROM|TO filename */
1971         else if (Matches4("COPY|\\copy", MatchAny, "FROM|TO", MatchAny) ||
1972                          Matches5("COPY", "BINARY", MatchAny, "FROM|TO", MatchAny))
1973                 COMPLETE_WITH_LIST6("BINARY", "OIDS", "DELIMITER", "NULL", "CSV",
1974                                                         "ENCODING");
1975
1976         /* Handle COPY [BINARY] <sth> FROM|TO filename CSV */
1977         else if (Matches5("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "CSV") ||
1978                          Matches6("COPY", "BINARY", MatchAny, "FROM|TO", MatchAny, "CSV"))
1979                 COMPLETE_WITH_LIST5("HEADER", "QUOTE", "ESCAPE", "FORCE QUOTE",
1980                                                         "FORCE NOT NULL");
1981
1982         /* CREATE ACCESS METHOD */
1983         /* Complete "CREATE ACCESS METHOD <name>" */
1984         else if (Matches4("CREATE", "ACCESS", "METHOD", MatchAny))
1985                 COMPLETE_WITH_CONST("TYPE");
1986         /* Complete "CREATE ACCESS METHOD <name> TYPE" */
1987         else if (Matches5("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE"))
1988                 COMPLETE_WITH_CONST("INDEX");
1989         /* Complete "CREATE ACCESS METHOD <name> TYPE <type>" */
1990         else if (Matches6("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE", MatchAny))
1991                 COMPLETE_WITH_CONST("HANDLER");
1992
1993         /* CREATE DATABASE */
1994         else if (Matches3("CREATE", "DATABASE", MatchAny))
1995                 COMPLETE_WITH_LIST9("OWNER", "TEMPLATE", "ENCODING", "TABLESPACE",
1996                                                         "IS_TEMPLATE",
1997                                                         "ALLOW_CONNECTIONS", "CONNECTION LIMIT",
1998                                                         "LC_COLLATE", "LC_CTYPE");
1999
2000         else if (Matches4("CREATE", "DATABASE", MatchAny, "TEMPLATE"))
2001                 COMPLETE_WITH_QUERY(Query_for_list_of_template_databases);
2002
2003         /* CREATE EXTENSION */
2004         /* Complete with available extensions rather than installed ones. */
2005         else if (Matches2("CREATE", "EXTENSION"))
2006                 COMPLETE_WITH_QUERY(Query_for_list_of_available_extensions);
2007         /* CREATE EXTENSION <name> */
2008         else if (Matches3("CREATE", "EXTENSION", MatchAny))
2009                 COMPLETE_WITH_LIST3("WITH SCHEMA", "CASCADE", "VERSION");
2010         /* CREATE EXTENSION <name> VERSION */
2011         else if (Matches4("CREATE", "EXTENSION", MatchAny, "VERSION"))
2012         {
2013                 completion_info_charp = prev2_wd;
2014                 COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions);
2015         }
2016
2017         /* CREATE FOREIGN */
2018         else if (Matches2("CREATE", "FOREIGN"))
2019                 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
2020
2021         /* CREATE FOREIGN DATA WRAPPER */
2022         else if (Matches5("CREATE", "FOREIGN", "DATA", "WRAPPER", MatchAny))
2023                 COMPLETE_WITH_LIST3("HANDLER", "VALIDATOR", "OPTIONS");
2024
2025         /* CREATE INDEX --- is allowed inside CREATE SCHEMA, so use TailMatches */
2026         /* First off we complete CREATE UNIQUE with "INDEX" */
2027         else if (TailMatches2("CREATE", "UNIQUE"))
2028                 COMPLETE_WITH_CONST("INDEX");
2029         /* If we have CREATE|UNIQUE INDEX, then add "ON", "CONCURRENTLY",
2030            and existing indexes */
2031         else if (TailMatches2("CREATE|UNIQUE", "INDEX"))
2032                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
2033                                                                    " UNION SELECT 'ON'"
2034                                                                    " UNION SELECT 'CONCURRENTLY'");
2035         /* Complete ... INDEX|CONCURRENTLY [<name>] ON with a list of tables  */
2036         else if (TailMatches3("INDEX|CONCURRENTLY", MatchAny, "ON") ||
2037                          TailMatches2("INDEX|CONCURRENTLY", "ON"))
2038                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
2039         /* Complete CREATE|UNIQUE INDEX CONCURRENTLY with "ON" and existing indexes */
2040         else if (TailMatches3("CREATE|UNIQUE", "INDEX", "CONCURRENTLY"))
2041                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
2042                                                                    " UNION SELECT 'ON'");
2043         /* Complete CREATE|UNIQUE INDEX [CONCURRENTLY] <sth> with "ON" */
2044         else if (TailMatches3("CREATE|UNIQUE", "INDEX", MatchAny) ||
2045                          TailMatches4("CREATE|UNIQUE", "INDEX", "CONCURRENTLY", MatchAny))
2046                 COMPLETE_WITH_CONST("ON");
2047
2048         /*
2049          * Complete INDEX <name> ON <table> with a list of table columns (which
2050          * should really be in parens)
2051          */
2052         else if (TailMatches4("INDEX", MatchAny, "ON", MatchAny) ||
2053                          TailMatches3("INDEX|CONCURRENTLY", "ON", MatchAny))
2054                 COMPLETE_WITH_LIST2("(", "USING");
2055         else if (TailMatches5("INDEX", MatchAny, "ON", MatchAny, "(") ||
2056                          TailMatches4("INDEX|CONCURRENTLY", "ON", MatchAny, "("))
2057                 COMPLETE_WITH_ATTR(prev2_wd, "");
2058         /* same if you put in USING */
2059         else if (TailMatches5("ON", MatchAny, "USING", MatchAny, "("))
2060                 COMPLETE_WITH_ATTR(prev4_wd, "");
2061         /* Complete USING with an index method */
2062         else if (TailMatches6("INDEX", MatchAny, MatchAny, "ON", MatchAny, "USING") ||
2063                          TailMatches5("INDEX", MatchAny, "ON", MatchAny, "USING") ||
2064                          TailMatches4("INDEX", "ON", MatchAny, "USING"))
2065                 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
2066         else if (TailMatches4("ON", MatchAny, "USING", MatchAny) &&
2067                          !TailMatches6("POLICY", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny) &&
2068                          !TailMatches4("FOR", MatchAny, MatchAny, MatchAny))
2069                 COMPLETE_WITH_CONST("(");
2070
2071         /* CREATE POLICY */
2072         /* Complete "CREATE POLICY <name> ON" */
2073         else if (Matches3("CREATE", "POLICY", MatchAny))
2074                 COMPLETE_WITH_CONST("ON");
2075         /* Complete "CREATE POLICY <name> ON <table>" */
2076         else if (Matches4("CREATE", "POLICY", MatchAny, "ON"))
2077                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2078         /* Complete "CREATE POLICY <name> ON <table> FOR|TO|USING|WITH CHECK" */
2079         else if (Matches5("CREATE", "POLICY", MatchAny, "ON", MatchAny))
2080                 COMPLETE_WITH_LIST4("FOR", "TO", "USING (", "WITH CHECK (");
2081         /* CREATE POLICY <name> ON <table> FOR ALL|SELECT|INSERT|UPDATE|DELETE */
2082         else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR"))
2083                 COMPLETE_WITH_LIST5("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
2084         /* Complete "CREATE POLICY <name> ON <table> FOR INSERT TO|WITH CHECK" */
2085         else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "INSERT"))
2086                 COMPLETE_WITH_LIST2("TO", "WITH CHECK (");
2087         /* Complete "CREATE POLICY <name> ON <table> FOR SELECT|DELETE TO|USING" */
2088         else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "SELECT|DELETE"))
2089                 COMPLETE_WITH_LIST2("TO", "USING (");
2090         /* CREATE POLICY <name> ON <table> FOR ALL|UPDATE TO|USING|WITH CHECK */
2091         else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "ALL|UPDATE"))
2092                 COMPLETE_WITH_LIST3("TO", "USING (", "WITH CHECK (");
2093         /* Complete "CREATE POLICY <name> ON <table> TO <role>" */
2094         else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "TO"))
2095                 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
2096         /* Complete "CREATE POLICY <name> ON <table> USING (" */
2097         else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "USING"))
2098                 COMPLETE_WITH_CONST("(");
2099
2100 /* CREATE RULE */
2101         /* Complete "CREATE RULE <sth>" with "AS ON" */
2102         else if (Matches3("CREATE", "RULE", MatchAny))
2103                 COMPLETE_WITH_CONST("AS ON");
2104         /* Complete "CREATE RULE <sth> AS" with "ON" */
2105         else if (Matches4("CREATE", "RULE", MatchAny, "AS"))
2106                 COMPLETE_WITH_CONST("ON");
2107         /* Complete "CREATE RULE <sth> AS ON" with SELECT|UPDATE|INSERT|DELETE */
2108         else if (Matches5("CREATE", "RULE", MatchAny, "AS", "ON"))
2109                 COMPLETE_WITH_LIST4("SELECT", "UPDATE", "INSERT", "DELETE");
2110         /* Complete "AS ON SELECT|UPDATE|INSERT|DELETE" with a "TO" */
2111         else if (TailMatches3("AS", "ON", "SELECT|UPDATE|INSERT|DELETE"))
2112                 COMPLETE_WITH_CONST("TO");
2113         /* Complete "AS ON <sth> TO" with a table name */
2114         else if (TailMatches4("AS", "ON", "SELECT|UPDATE|INSERT|DELETE", "TO"))
2115                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2116
2117 /* CREATE SEQUENCE --- is allowed inside CREATE SCHEMA, so use TailMatches */
2118         else if (TailMatches3("CREATE", "SEQUENCE", MatchAny) ||
2119                          TailMatches4("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny))
2120                 COMPLETE_WITH_LIST8("INCREMENT BY", "MINVALUE", "MAXVALUE", "NO", "CACHE",
2121                                                         "CYCLE", "OWNED BY", "START WITH");
2122         else if (TailMatches4("CREATE", "SEQUENCE", MatchAny, "NO") ||
2123                 TailMatches5("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny, "NO"))
2124                 COMPLETE_WITH_LIST3("MINVALUE", "MAXVALUE", "CYCLE");
2125
2126 /* CREATE SERVER <name> */
2127         else if (Matches3("CREATE", "SERVER", MatchAny))
2128                 COMPLETE_WITH_LIST3("TYPE", "VERSION", "FOREIGN DATA WRAPPER");
2129
2130 /* CREATE TABLE --- is allowed inside CREATE SCHEMA, so use TailMatches */
2131         /* Complete "CREATE TEMP/TEMPORARY" with the possible temp objects */
2132         else if (TailMatches2("CREATE", "TEMP|TEMPORARY"))
2133                 COMPLETE_WITH_LIST3("SEQUENCE", "TABLE", "VIEW");
2134         /* Complete "CREATE UNLOGGED" with TABLE or MATVIEW */
2135         else if (TailMatches2("CREATE", "UNLOGGED"))
2136                 COMPLETE_WITH_LIST2("TABLE", "MATERIALIZED VIEW");
2137
2138 /* CREATE TABLESPACE */
2139         else if (Matches3("CREATE", "TABLESPACE", MatchAny))
2140                 COMPLETE_WITH_LIST2("OWNER", "LOCATION");
2141         /* Complete CREATE TABLESPACE name OWNER name with "LOCATION" */
2142         else if (Matches5("CREATE", "TABLESPACE", MatchAny, "OWNER", MatchAny))
2143                 COMPLETE_WITH_CONST("LOCATION");
2144
2145 /* CREATE TEXT SEARCH */
2146         else if (Matches3("CREATE", "TEXT", "SEARCH"))
2147                 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2148         else if (Matches5("CREATE", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
2149                 COMPLETE_WITH_CONST("(");
2150
2151 /* CREATE TRIGGER --- is allowed inside CREATE SCHEMA, so use TailMatches */
2152         /* complete CREATE TRIGGER <name> with BEFORE,AFTER,INSTEAD OF */
2153         else if (TailMatches3("CREATE", "TRIGGER", MatchAny))
2154                 COMPLETE_WITH_LIST3("BEFORE", "AFTER", "INSTEAD OF");
2155         /* complete CREATE TRIGGER <name> BEFORE,AFTER with an event */
2156         else if (TailMatches4("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER"))
2157                 COMPLETE_WITH_LIST4("INSERT", "DELETE", "UPDATE", "TRUNCATE");
2158         /* complete CREATE TRIGGER <name> INSTEAD OF with an event */
2159         else if (TailMatches5("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF"))
2160                 COMPLETE_WITH_LIST3("INSERT", "DELETE", "UPDATE");
2161         /* complete CREATE TRIGGER <name> BEFORE,AFTER sth with OR,ON */
2162         else if (TailMatches5("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny) ||
2163           TailMatches6("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny))
2164                 COMPLETE_WITH_LIST2("ON", "OR");
2165
2166         /*
2167          * complete CREATE TRIGGER <name> BEFORE,AFTER event ON with a list of
2168          * tables
2169          */
2170         else if (TailMatches6("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny, "ON"))
2171                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2172         /* complete CREATE TRIGGER ... INSTEAD OF event ON with a list of views */
2173         else if (TailMatches7("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny, "ON"))
2174                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
2175         /* complete CREATE TRIGGER ... EXECUTE with PROCEDURE */
2176         else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches1("EXECUTE"))
2177                 COMPLETE_WITH_CONST("PROCEDURE");
2178
2179 /* CREATE ROLE,USER,GROUP <name> */
2180         else if (Matches3("CREATE", "ROLE|GROUP|USER", MatchAny) &&
2181                          !TailMatches2("USER", "MAPPING"))
2182         {
2183                 static const char *const list_CREATEROLE[] =
2184                 {"ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
2185                         "ENCRYPTED", "IN", "INHERIT", "LOGIN", "NOBYPASSRLS",
2186                         "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
2187                         "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
2188                         "REPLICATION", "ROLE", "SUPERUSER", "SYSID", "UNENCRYPTED",
2189                 "VALID UNTIL", "WITH", NULL};
2190
2191                 COMPLETE_WITH_LIST(list_CREATEROLE);
2192         }
2193
2194 /* CREATE ROLE,USER,GROUP <name> WITH */
2195         else if (Matches4("CREATE", "ROLE|GROUP|USER", MatchAny, "WITH"))
2196         {
2197                 /* Similar to the above, but don't complete "WITH" again. */
2198                 static const char *const list_CREATEROLE_WITH[] =
2199                 {"ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
2200                         "ENCRYPTED", "IN", "INHERIT", "LOGIN", "NOBYPASSRLS",
2201                         "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
2202                         "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
2203                         "REPLICATION", "ROLE", "SUPERUSER", "SYSID", "UNENCRYPTED",
2204                 "VALID UNTIL", NULL};
2205
2206                 COMPLETE_WITH_LIST(list_CREATEROLE_WITH);
2207         }
2208
2209         /*
2210          * complete CREATE ROLE,USER,GROUP <name> ENCRYPTED,UNENCRYPTED with
2211          * PASSWORD
2212          */
2213         else if (Matches4("CREATE", "ROLE|USER|GROUP", MatchAny, "ENCRYPTED|UNENCRYPTED"))
2214                 COMPLETE_WITH_CONST("PASSWORD");
2215         /* complete CREATE ROLE,USER,GROUP <name> IN with ROLE,GROUP */
2216         else if (Matches4("CREATE", "ROLE|USER|GROUP", MatchAny, "IN"))
2217                 COMPLETE_WITH_LIST2("GROUP", "ROLE");
2218
2219 /* CREATE VIEW --- is allowed inside CREATE SCHEMA, so use TailMatches */
2220         /* Complete CREATE VIEW <name> with AS */
2221         else if (TailMatches3("CREATE", "VIEW", MatchAny))
2222                 COMPLETE_WITH_CONST("AS");
2223         /* Complete "CREATE VIEW <sth> AS with "SELECT" */
2224         else if (TailMatches4("CREATE", "VIEW", MatchAny, "AS"))
2225                 COMPLETE_WITH_CONST("SELECT");
2226
2227 /* CREATE MATERIALIZED VIEW */
2228         else if (Matches2("CREATE", "MATERIALIZED"))
2229                 COMPLETE_WITH_CONST("VIEW");
2230         /* Complete CREATE MATERIALIZED VIEW <name> with AS */
2231         else if (Matches4("CREATE", "MATERIALIZED", "VIEW", MatchAny))
2232                 COMPLETE_WITH_CONST("AS");
2233         /* Complete "CREATE MATERIALIZED VIEW <sth> AS with "SELECT" */
2234         else if (Matches5("CREATE", "MATERIALIZED", "VIEW", MatchAny, "AS"))
2235                 COMPLETE_WITH_CONST("SELECT");
2236
2237 /* CREATE EVENT TRIGGER */
2238         else if (Matches2("CREATE", "EVENT"))
2239                 COMPLETE_WITH_CONST("TRIGGER");
2240         /* Complete CREATE EVENT TRIGGER <name> with ON */
2241         else if (Matches4("CREATE", "EVENT", "TRIGGER", MatchAny))
2242                 COMPLETE_WITH_CONST("ON");
2243         /* Complete CREATE EVENT TRIGGER <name> ON with event_type */
2244         else if (Matches5("CREATE", "EVENT", "TRIGGER", MatchAny, "ON"))
2245                 COMPLETE_WITH_LIST3("ddl_command_start", "ddl_command_end", "sql_drop");
2246
2247 /* DECLARE */
2248         else if (Matches2("DECLARE", MatchAny))
2249                 COMPLETE_WITH_LIST5("BINARY", "INSENSITIVE", "SCROLL", "NO SCROLL",
2250                                                         "CURSOR");
2251         else if (HeadMatches1("DECLARE") && TailMatches1("CURSOR"))
2252                 COMPLETE_WITH_LIST3("WITH HOLD", "WITHOUT HOLD", "FOR");
2253
2254 /* DELETE --- can be inside EXPLAIN, RULE, etc */
2255         /* ... despite which, only complete DELETE with FROM at start of line */
2256         else if (Matches1("DELETE"))
2257                 COMPLETE_WITH_CONST("FROM");
2258         /* Complete DELETE FROM with a list of tables */
2259         else if (TailMatches2("DELETE", "FROM"))
2260                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
2261         /* Complete DELETE FROM <table> */
2262         else if (TailMatches3("DELETE", "FROM", MatchAny))
2263                 COMPLETE_WITH_LIST2("USING", "WHERE");
2264         /* XXX: implement tab completion for DELETE ... USING */
2265
2266 /* DISCARD */
2267         else if (Matches1("DISCARD"))
2268                 COMPLETE_WITH_LIST4("ALL", "PLANS", "SEQUENCES", "TEMP");
2269
2270 /* DO */
2271         else if (Matches1("DO"))
2272                 COMPLETE_WITH_CONST("LANGUAGE");
2273
2274 /* DROP */
2275         /* Complete DROP object with CASCADE / RESTRICT */
2276         else if (Matches3("DROP",
2277                                           "COLLATION|CONVERSION|DOMAIN|EXTENSION|LANGUAGE|SCHEMA|SEQUENCE|SERVER|TABLE|TYPE|VIEW",
2278                                           MatchAny) ||
2279                          Matches4("DROP", "ACCESS", "METHOD", MatchAny) ||
2280                          (Matches4("DROP", "AGGREGATE|FUNCTION", MatchAny, MatchAny) &&
2281                           ends_with(prev_wd, ')')) ||
2282                          Matches4("DROP", "EVENT", "TRIGGER", MatchAny) ||
2283                          Matches5("DROP", "FOREIGN", "DATA", "WRAPPER", MatchAny) ||
2284                          Matches4("DROP", "FOREIGN", "TABLE", MatchAny) ||
2285                          Matches5("DROP", "TEXT", "SEARCH", "CONFIGURATION|DICTIONARY|PARSER|TEMPLATE", MatchAny))
2286                 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2287
2288         /* help completing some of the variants */
2289         else if (Matches3("DROP", "AGGREGATE|FUNCTION", MatchAny))
2290                 COMPLETE_WITH_CONST("(");
2291         else if (Matches4("DROP", "AGGREGATE|FUNCTION", MatchAny, "("))
2292                 COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
2293         else if (Matches2("DROP", "FOREIGN"))
2294                 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
2295
2296         /* DROP INDEX */
2297         else if (Matches2("DROP", "INDEX"))
2298                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
2299                                                                    " UNION SELECT 'CONCURRENTLY'");
2300         else if (Matches3("DROP", "INDEX", "CONCURRENTLY"))
2301                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
2302         else if (Matches3("DROP", "INDEX", MatchAny))
2303                 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2304         else if (Matches4("DROP", "INDEX", "CONCURRENTLY", MatchAny))
2305                 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2306
2307         /* DROP MATERIALIZED VIEW */
2308         else if (Matches2("DROP", "MATERIALIZED"))
2309                 COMPLETE_WITH_CONST("VIEW");
2310         else if (Matches3("DROP", "MATERIALIZED", "VIEW"))
2311                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
2312
2313         /* DROP OWNED BY */
2314         else if (Matches2("DROP", "OWNED"))
2315                 COMPLETE_WITH_CONST("BY");
2316         else if (Matches3("DROP", "OWNED", "BY"))
2317                 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2318
2319         else if (Matches3("DROP", "TEXT", "SEARCH"))
2320                 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2321
2322         /* DROP TRIGGER */
2323         else if (Matches3("DROP", "TRIGGER", MatchAny))
2324                 COMPLETE_WITH_CONST("ON");
2325         else if (Matches4("DROP", "TRIGGER", MatchAny, "ON"))
2326         {
2327                 completion_info_charp = prev2_wd;
2328                 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger);
2329         }
2330         else if (Matches5("DROP", "TRIGGER", MatchAny, "ON", MatchAny))
2331                 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2332
2333         /* DROP EVENT TRIGGER */
2334         else if (Matches2("DROP", "EVENT"))
2335                 COMPLETE_WITH_CONST("TRIGGER");
2336         else if (Matches3("DROP", "EVENT", "TRIGGER"))
2337                 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
2338
2339         /* DROP POLICY <name>  */
2340         else if (Matches2("DROP", "POLICY"))
2341                 COMPLETE_WITH_QUERY(Query_for_list_of_policies);
2342         /* DROP POLICY <name> ON */
2343         else if (Matches3("DROP", "POLICY", MatchAny))
2344                 COMPLETE_WITH_CONST("ON");
2345         /* DROP POLICY <name> ON <table> */
2346         else if (Matches4("DROP", "POLICY", MatchAny, "ON"))
2347         {
2348                 completion_info_charp = prev2_wd;
2349                 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_policy);
2350         }
2351
2352         /* DROP RULE */
2353         else if (Matches3("DROP", "RULE", MatchAny))
2354                 COMPLETE_WITH_CONST("ON");
2355         else if (Matches4("DROP", "RULE", MatchAny, "ON"))
2356         {
2357                 completion_info_charp = prev2_wd;
2358                 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule);
2359         }
2360         else if (Matches5("DROP", "RULE", MatchAny, "ON", MatchAny))
2361                 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2362
2363 /* EXECUTE */
2364         else if (Matches1("EXECUTE"))
2365                 COMPLETE_WITH_QUERY(Query_for_list_of_prepared_statements);
2366
2367 /* EXPLAIN */
2368
2369         /*
2370          * Complete EXPLAIN [ANALYZE] [VERBOSE] with list of EXPLAIN-able commands
2371          */
2372         else if (Matches1("EXPLAIN"))
2373                 COMPLETE_WITH_LIST7("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE",
2374                                                         "ANALYZE", "VERBOSE");
2375         else if (Matches2("EXPLAIN", "ANALYZE"))
2376                 COMPLETE_WITH_LIST6("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE",
2377                                                         "VERBOSE");
2378         else if (Matches2("EXPLAIN", "VERBOSE") ||
2379                          Matches3("EXPLAIN", "ANALYZE", "VERBOSE"))
2380                 COMPLETE_WITH_LIST5("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE");
2381
2382 /* FETCH && MOVE */
2383         /* Complete FETCH with one of FORWARD, BACKWARD, RELATIVE */
2384         else if (Matches1("FETCH|MOVE"))
2385                 COMPLETE_WITH_LIST4("ABSOLUTE", "BACKWARD", "FORWARD", "RELATIVE");
2386         /* Complete FETCH <sth> with one of ALL, NEXT, PRIOR */
2387         else if (Matches2("FETCH|MOVE", MatchAny))
2388                 COMPLETE_WITH_LIST3("ALL", "NEXT", "PRIOR");
2389
2390         /*
2391          * Complete FETCH <sth1> <sth2> with "FROM" or "IN". These are equivalent,
2392          * but we may as well tab-complete both: perhaps some users prefer one
2393          * variant or the other.
2394          */
2395         else if (Matches3("FETCH|MOVE", MatchAny, MatchAny))
2396                 COMPLETE_WITH_LIST2("FROM", "IN");
2397
2398 /* FOREIGN DATA WRAPPER */
2399         /* applies in ALTER/DROP FDW and in CREATE SERVER */
2400         else if (TailMatches3("FOREIGN", "DATA", "WRAPPER") &&
2401                          !TailMatches4("CREATE", MatchAny, MatchAny, MatchAny))
2402                 COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
2403         /* applies in CREATE SERVER */
2404         else if (TailMatches4("FOREIGN", "DATA", "WRAPPER", MatchAny) &&
2405                          HeadMatches2("CREATE", "SERVER"))
2406                 COMPLETE_WITH_CONST("OPTIONS");
2407
2408 /* FOREIGN TABLE */
2409         else if (TailMatches2("FOREIGN", "TABLE") &&
2410                          !TailMatches3("CREATE", MatchAny, MatchAny))
2411                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL);
2412
2413 /* FOREIGN SERVER */
2414         else if (TailMatches2("FOREIGN", "SERVER"))
2415                 COMPLETE_WITH_QUERY(Query_for_list_of_servers);
2416
2417 /* GRANT && REVOKE --- is allowed inside CREATE SCHEMA, so use TailMatches */
2418         /* Complete GRANT/REVOKE with a list of roles and privileges */
2419         else if (TailMatches1("GRANT|REVOKE"))
2420                 COMPLETE_WITH_QUERY(Query_for_list_of_roles
2421                                                         " UNION SELECT 'SELECT'"
2422                                                         " UNION SELECT 'INSERT'"
2423                                                         " UNION SELECT 'UPDATE'"
2424                                                         " UNION SELECT 'DELETE'"
2425                                                         " UNION SELECT 'TRUNCATE'"
2426                                                         " UNION SELECT 'REFERENCES'"
2427                                                         " UNION SELECT 'TRIGGER'"
2428                                                         " UNION SELECT 'CREATE'"
2429                                                         " UNION SELECT 'CONNECT'"
2430                                                         " UNION SELECT 'TEMPORARY'"
2431                                                         " UNION SELECT 'EXECUTE'"
2432                                                         " UNION SELECT 'USAGE'"
2433                                                         " UNION SELECT 'ALL'");
2434
2435         /*
2436          * Complete GRANT/REVOKE <privilege> with "ON", GRANT/REVOKE <role> with
2437          * TO/FROM
2438          */
2439         else if (TailMatches2("GRANT|REVOKE", MatchAny))
2440         {
2441                 if (TailMatches1("SELECT|INSERT|UPDATE|DELETE|TRUNCATE|REFERENCES|TRIGGER|CREATE|CONNECT|TEMPORARY|TEMP|EXECUTE|USAGE|ALL"))
2442                         COMPLETE_WITH_CONST("ON");
2443                 else if (TailMatches2("GRANT", MatchAny))
2444                         COMPLETE_WITH_CONST("TO");
2445                 else
2446                         COMPLETE_WITH_CONST("FROM");
2447         }
2448
2449         /*
2450          * Complete GRANT/REVOKE <sth> ON with a list of tables, views, and
2451          * sequences.
2452          *
2453          * Keywords like DATABASE, FUNCTION, LANGUAGE and SCHEMA added to query
2454          * result via UNION; seems to work intuitively.
2455          *
2456          * Note: GRANT/REVOKE can get quite complex; tab-completion as implemented
2457          * here will only work if the privilege list contains exactly one
2458          * privilege.
2459          */
2460         else if (TailMatches3("GRANT|REVOKE", MatchAny, "ON"))
2461                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf,
2462                                                                    " UNION SELECT 'ALL FUNCTIONS IN SCHEMA'"
2463                                                                    " UNION SELECT 'ALL SEQUENCES IN SCHEMA'"
2464                                                                    " UNION SELECT 'ALL TABLES IN SCHEMA'"
2465                                                                    " UNION SELECT 'DATABASE'"
2466                                                                    " UNION SELECT 'DOMAIN'"
2467                                                                    " UNION SELECT 'FOREIGN DATA WRAPPER'"
2468                                                                    " UNION SELECT 'FOREIGN SERVER'"
2469                                                                    " UNION SELECT 'FUNCTION'"
2470                                                                    " UNION SELECT 'LANGUAGE'"
2471                                                                    " UNION SELECT 'LARGE OBJECT'"
2472                                                                    " UNION SELECT 'SCHEMA'"
2473                                                                    " UNION SELECT 'SEQUENCE'"
2474                                                                    " UNION SELECT 'TABLE'"
2475                                                                    " UNION SELECT 'TABLESPACE'"
2476                                                                    " UNION SELECT 'TYPE'");
2477
2478         else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", "ALL"))
2479                 COMPLETE_WITH_LIST3("FUNCTIONS IN SCHEMA", "SEQUENCES IN SCHEMA",
2480                                                         "TABLES IN SCHEMA");
2481
2482         else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", "FOREIGN"))
2483                 COMPLETE_WITH_LIST2("DATA WRAPPER", "SERVER");
2484
2485         /*
2486          * Complete "GRANT/REVOKE * ON DATABASE/DOMAIN/..." with a list of
2487          * appropriate objects.
2488          *
2489          * Complete "GRANT/REVOKE * ON *" with "TO/FROM".
2490          */
2491         else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", MatchAny))
2492         {
2493                 if (TailMatches1("DATABASE"))
2494                         COMPLETE_WITH_QUERY(Query_for_list_of_databases);
2495                 else if (TailMatches1("DOMAIN"))
2496                         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL);
2497                 else if (TailMatches1("FUNCTION"))
2498                         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
2499                 else if (TailMatches1("LANGUAGE"))
2500                         COMPLETE_WITH_QUERY(Query_for_list_of_languages);
2501                 else if (TailMatches1("SCHEMA"))
2502                         COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
2503                 else if (TailMatches1("SEQUENCE"))
2504                         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences, NULL);
2505                 else if (TailMatches1("TABLE"))
2506                         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
2507                 else if (TailMatches1("TABLESPACE"))
2508                         COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
2509                 else if (TailMatches1("TYPE"))
2510                         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL);
2511                 else if (TailMatches4("GRANT", MatchAny, MatchAny, MatchAny))
2512                         COMPLETE_WITH_CONST("TO");
2513                 else
2514                         COMPLETE_WITH_CONST("FROM");
2515         }
2516
2517         /*
2518          * Complete "GRANT/REVOKE ... TO/FROM" with username, PUBLIC,
2519          * CURRENT_USER, or SESSION_USER.
2520          */
2521         else if ((HeadMatches1("GRANT") && TailMatches1("TO")) ||
2522                          (HeadMatches1("REVOKE") && TailMatches1("FROM")))
2523                 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
2524
2525         /* Complete "GRANT/REVOKE ... ON * *" with TO/FROM */
2526         else if (HeadMatches1("GRANT") && TailMatches3("ON", MatchAny, MatchAny))
2527                 COMPLETE_WITH_CONST("TO");
2528         else if (HeadMatches1("REVOKE") && TailMatches3("ON", MatchAny, MatchAny))
2529                 COMPLETE_WITH_CONST("FROM");
2530
2531         /* Complete "GRANT/REVOKE * ON ALL * IN SCHEMA *" with TO/FROM */
2532         else if (TailMatches8("GRANT|REVOKE", MatchAny, "ON", "ALL", MatchAny, "IN", "SCHEMA", MatchAny))
2533         {
2534                 if (TailMatches8("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
2535                         COMPLETE_WITH_CONST("TO");
2536                 else
2537                         COMPLETE_WITH_CONST("FROM");
2538         }
2539
2540         /* Complete "GRANT/REVOKE * ON FOREIGN DATA WRAPPER *" with TO/FROM */
2541         else if (TailMatches7("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "DATA", "WRAPPER", MatchAny))
2542         {
2543                 if (TailMatches7("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
2544                         COMPLETE_WITH_CONST("TO");
2545                 else
2546                         COMPLETE_WITH_CONST("FROM");
2547         }
2548
2549         /* Complete "GRANT/REVOKE * ON FOREIGN SERVER *" with TO/FROM */
2550         else if (TailMatches6("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "SERVER", MatchAny))
2551         {
2552                 if (TailMatches6("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
2553                         COMPLETE_WITH_CONST("TO");
2554                 else
2555                         COMPLETE_WITH_CONST("FROM");
2556         }
2557
2558 /* GROUP BY */
2559         else if (TailMatches3("FROM", MatchAny, "GROUP"))
2560                 COMPLETE_WITH_CONST("BY");
2561
2562 /* IMPORT FOREIGN SCHEMA */
2563         else if (Matches1("IMPORT"))
2564                 COMPLETE_WITH_CONST("FOREIGN SCHEMA");
2565         else if (Matches2("IMPORT", "FOREIGN"))
2566                 COMPLETE_WITH_CONST("SCHEMA");
2567
2568 /* INSERT --- can be inside EXPLAIN, RULE, etc */
2569         /* Complete INSERT with "INTO" */
2570         else if (TailMatches1("INSERT"))
2571                 COMPLETE_WITH_CONST("INTO");
2572         /* Complete INSERT INTO with table names */
2573         else if (TailMatches2("INSERT", "INTO"))
2574                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
2575         /* Complete "INSERT INTO <table> (" with attribute names */
2576         else if (TailMatches4("INSERT", "INTO", MatchAny, "("))
2577                 COMPLETE_WITH_ATTR(prev2_wd, "");
2578
2579         /*
2580          * Complete INSERT INTO <table> with "(" or "VALUES" or "SELECT" or
2581          * "TABLE" or "DEFAULT VALUES"
2582          */
2583         else if (TailMatches3("INSERT", "INTO", MatchAny))
2584                 COMPLETE_WITH_LIST5("(", "DEFAULT VALUES", "SELECT", "TABLE", "VALUES");
2585
2586         /*
2587          * Complete INSERT INTO <table> (attribs) with "VALUES" or "SELECT" or
2588          * "TABLE"
2589          */
2590         else if (TailMatches4("INSERT", "INTO", MatchAny, MatchAny) &&
2591                          ends_with(prev_wd, ')'))
2592                 COMPLETE_WITH_LIST3("SELECT", "TABLE", "VALUES");
2593
2594         /* Insert an open parenthesis after "VALUES" */
2595         else if (TailMatches1("VALUES") && !TailMatches2("DEFAULT", "VALUES"))
2596                 COMPLETE_WITH_CONST("(");
2597
2598 /* LOCK */
2599         /* Complete LOCK [TABLE] with a list of tables */
2600         else if (Matches1("LOCK"))
2601                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
2602                                                                    " UNION SELECT 'TABLE'");
2603         else if (Matches2("LOCK", "TABLE"))
2604                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
2605
2606         /* For the following, handle the case of a single table only for now */
2607
2608         /* Complete LOCK [TABLE] <table> with "IN" */
2609         else if (Matches2("LOCK", MatchAnyExcept("TABLE")) ||
2610                          Matches3("LOCK", "TABLE", MatchAny))
2611                 COMPLETE_WITH_CONST("IN");
2612
2613         /* Complete LOCK [TABLE] <table> IN with a lock mode */
2614         else if (Matches3("LOCK", MatchAny, "IN") ||
2615                          Matches4("LOCK", "TABLE", MatchAny, "IN"))
2616                 COMPLETE_WITH_LIST8("ACCESS SHARE MODE",
2617                                                         "ROW SHARE MODE", "ROW EXCLUSIVE MODE",
2618                                                         "SHARE UPDATE EXCLUSIVE MODE", "SHARE MODE",
2619                                                         "SHARE ROW EXCLUSIVE MODE",
2620                                                         "EXCLUSIVE MODE", "ACCESS EXCLUSIVE MODE");
2621
2622 /* NOTIFY --- can be inside EXPLAIN, RULE, etc */
2623         else if (TailMatches1("NOTIFY"))
2624                 COMPLETE_WITH_QUERY("SELECT pg_catalog.quote_ident(channel) FROM pg_catalog.pg_listening_channels() AS channel WHERE substring(pg_catalog.quote_ident(channel),1,%d)='%s'");
2625
2626 /* OPTIONS */
2627         else if (TailMatches1("OPTIONS"))
2628                 COMPLETE_WITH_CONST("(");
2629
2630 /* OWNER TO  - complete with available roles */
2631         else if (TailMatches2("OWNER", "TO"))
2632                 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2633
2634 /* ORDER BY */
2635         else if (TailMatches3("FROM", MatchAny, "ORDER"))
2636                 COMPLETE_WITH_CONST("BY");
2637         else if (TailMatches4("FROM", MatchAny, "ORDER", "BY"))
2638                 COMPLETE_WITH_ATTR(prev3_wd, "");
2639
2640 /* PREPARE xx AS */
2641         else if (Matches3("PREPARE", MatchAny, "AS"))
2642                 COMPLETE_WITH_LIST4("SELECT", "UPDATE", "INSERT", "DELETE FROM");
2643
2644 /*
2645  * PREPARE TRANSACTION is missing on purpose. It's intended for transaction
2646  * managers, not for manual use in interactive sessions.
2647  */
2648
2649 /* REASSIGN OWNED BY xxx TO yyy */
2650         else if (Matches1("REASSIGN"))
2651                 COMPLETE_WITH_CONST("OWNED BY");
2652         else if (Matches2("REASSIGN", "OWNED"))
2653                 COMPLETE_WITH_CONST("BY");
2654         else if (Matches3("REASSIGN", "OWNED", "BY"))
2655                 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2656         else if (Matches4("REASSIGN", "OWNED", "BY", MatchAny))
2657                 COMPLETE_WITH_CONST("TO");
2658         else if (Matches5("REASSIGN", "OWNED", "BY", MatchAny, "TO"))
2659                 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2660
2661 /* REFRESH MATERIALIZED VIEW */
2662         else if (Matches1("REFRESH"))
2663                 COMPLETE_WITH_CONST("MATERIALIZED VIEW");
2664         else if (Matches2("REFRESH", "MATERIALIZED"))
2665                 COMPLETE_WITH_CONST("VIEW");
2666         else if (Matches3("REFRESH", "MATERIALIZED", "VIEW"))
2667                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews,
2668                                                                    " UNION SELECT 'CONCURRENTLY'");
2669         else if (Matches4("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY"))
2670                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
2671         else if (Matches4("REFRESH", "MATERIALIZED", "VIEW", MatchAny))
2672                 COMPLETE_WITH_CONST("WITH");
2673         else if (Matches5("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny))
2674                 COMPLETE_WITH_CONST("WITH");
2675         else if (Matches5("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH"))
2676                 COMPLETE_WITH_LIST2("NO DATA", "DATA");
2677         else if (Matches6("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH"))
2678                 COMPLETE_WITH_LIST2("NO DATA", "DATA");
2679         else if (Matches6("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH", "NO"))
2680                 COMPLETE_WITH_CONST("DATA");
2681         else if (Matches7("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH", "NO"))
2682                 COMPLETE_WITH_CONST("DATA");
2683
2684 /* REINDEX */
2685         else if (Matches1("REINDEX"))
2686                 COMPLETE_WITH_LIST5("TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE");
2687         else if (Matches2("REINDEX", "TABLE"))
2688                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
2689         else if (Matches2("REINDEX", "INDEX"))
2690                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
2691         else if (Matches2("REINDEX", "SCHEMA"))
2692                 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
2693         else if (Matches2("REINDEX", "SYSTEM|DATABASE"))
2694                 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
2695
2696 /* SECURITY LABEL */
2697         else if (Matches1("SECURITY"))
2698                 COMPLETE_WITH_CONST("LABEL");
2699         else if (Matches2("SECURITY", "LABEL"))
2700                 COMPLETE_WITH_LIST2("ON", "FOR");
2701         else if (Matches4("SECURITY", "LABEL", "FOR", MatchAny))
2702                 COMPLETE_WITH_CONST("ON");
2703         else if (Matches3("SECURITY", "LABEL", "ON") ||
2704                          Matches5("SECURITY", "LABEL", "FOR", MatchAny, "ON"))
2705         {
2706                 static const char *const list_SECURITY_LABEL[] =
2707                 {"TABLE", "COLUMN", "AGGREGATE", "DATABASE", "DOMAIN",
2708                         "EVENT TRIGGER", "FOREIGN TABLE", "FUNCTION", "LARGE OBJECT",
2709                         "MATERIALIZED VIEW", "LANGUAGE", "ROLE", "SCHEMA",
2710                 "SEQUENCE", "TABLESPACE", "TYPE", "VIEW", NULL};
2711
2712                 COMPLETE_WITH_LIST(list_SECURITY_LABEL);
2713         }
2714         else if (Matches5("SECURITY", "LABEL", "ON", MatchAny, MatchAny))
2715                 COMPLETE_WITH_CONST("IS");
2716
2717 /* SELECT */
2718         /* naah . . . */
2719
2720 /* SET, RESET, SHOW */
2721         /* Complete with a variable name */
2722         else if (TailMatches1("SET|RESET") && !TailMatches3("UPDATE", MatchAny, "SET"))
2723                 COMPLETE_WITH_QUERY(Query_for_list_of_set_vars);
2724         else if (Matches1("SHOW"))
2725                 COMPLETE_WITH_QUERY(Query_for_list_of_show_vars);
2726         /* Complete "SET TRANSACTION" */
2727         else if (Matches2("SET|BEGIN|START", "TRANSACTION") ||
2728                          Matches2("BEGIN", "WORK") ||
2729                   Matches5("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION"))
2730                 COMPLETE_WITH_LIST2("ISOLATION LEVEL", "READ");
2731         else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION") ||
2732                          Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION"))
2733                 COMPLETE_WITH_CONST("LEVEL");
2734         else if (Matches4("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL"))
2735                 COMPLETE_WITH_LIST3("READ", "REPEATABLE READ", "SERIALIZABLE");
2736         else if (Matches5("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "READ"))
2737                 COMPLETE_WITH_LIST2("UNCOMMITTED", "COMMITTED");
2738         else if (Matches5("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "REPEATABLE"))
2739                 COMPLETE_WITH_CONST("READ");
2740         else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "READ"))
2741                 COMPLETE_WITH_LIST2("ONLY", "WRITE");
2742         /* SET CONSTRAINTS */
2743         else if (Matches2("SET", "CONSTRAINTS"))
2744                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_constraints_with_schema, "UNION SELECT 'ALL'");
2745         /* Complete SET CONSTRAINTS <foo> with DEFERRED|IMMEDIATE */
2746         else if (Matches3("SET", "CONSTRAINTS", MatchAny))
2747                 COMPLETE_WITH_LIST2("DEFERRED", "IMMEDIATE");
2748         /* Complete SET ROLE */
2749         else if (Matches2("SET", "ROLE"))
2750                 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2751         /* Complete SET SESSION with AUTHORIZATION or CHARACTERISTICS... */
2752         else if (Matches2("SET", "SESSION"))
2753                 COMPLETE_WITH_LIST2("AUTHORIZATION", "CHARACTERISTICS AS TRANSACTION");
2754         /* Complete SET SESSION AUTHORIZATION with username */
2755         else if (Matches3("SET", "SESSION", "AUTHORIZATION"))
2756                 COMPLETE_WITH_QUERY(Query_for_list_of_roles " UNION SELECT 'DEFAULT'");
2757         /* Complete RESET SESSION with AUTHORIZATION */
2758         else if (Matches2("RESET", "SESSION"))
2759                 COMPLETE_WITH_CONST("AUTHORIZATION");
2760         /* Complete SET <var> with "TO" */
2761         else if (Matches2("SET", MatchAny))
2762                 COMPLETE_WITH_CONST("TO");
2763         /* Complete ALTER DATABASE|FUNCTION|ROLE|USER ... SET <name> */
2764         else if (HeadMatches2("ALTER", "DATABASE|FUNCTION|ROLE|USER") &&
2765                          TailMatches2("SET", MatchAny))
2766                 COMPLETE_WITH_LIST2("FROM CURRENT", "TO");
2767         /* Suggest possible variable values */
2768         else if (TailMatches3("SET", MatchAny, "TO|="))
2769         {
2770                 /* special cased code for individual GUCs */
2771                 if (TailMatches2("DateStyle", "TO|="))
2772                 {
2773                         static const char *const my_list[] =
2774                         {"ISO", "SQL", "Postgres", "German",
2775                                 "YMD", "DMY", "MDY",
2776                                 "US", "European", "NonEuropean",
2777                         "DEFAULT", NULL};
2778
2779                         COMPLETE_WITH_LIST(my_list);
2780                 }
2781                 else if (TailMatches2("search_path", "TO|="))
2782                         COMPLETE_WITH_QUERY(Query_for_list_of_schemas
2783                                                                 " AND nspname not like 'pg\\_toast%%' "
2784                                                                 " AND nspname not like 'pg\\_temp%%' "
2785                                                                 " UNION SELECT 'DEFAULT' ");
2786                 else
2787                 {
2788                         /* generic, type based, GUC support */
2789                         char       *guctype = get_guctype(prev2_wd);
2790
2791                         if (guctype && strcmp(guctype, "enum") == 0)
2792                         {
2793                                 char            querybuf[1024];
2794
2795                                 snprintf(querybuf, sizeof(querybuf), Query_for_enum, prev2_wd);
2796                                 COMPLETE_WITH_QUERY(querybuf);
2797                         }
2798                         else if (guctype && strcmp(guctype, "bool") == 0)
2799                                 COMPLETE_WITH_LIST9("on", "off", "true", "false", "yes", "no",
2800                                                                         "1", "0", "DEFAULT");
2801                         else
2802                                 COMPLETE_WITH_CONST("DEFAULT");
2803
2804                         if (guctype)
2805                                 free(guctype);
2806                 }
2807         }
2808
2809 /* START TRANSACTION */
2810         else if (Matches1("START"))
2811                 COMPLETE_WITH_CONST("TRANSACTION");
2812
2813 /* TABLE, but not TABLE embedded in other commands */
2814         else if (Matches1("TABLE"))
2815                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations, NULL);
2816
2817 /* TABLESAMPLE */
2818         else if (TailMatches1("TABLESAMPLE"))
2819                 COMPLETE_WITH_QUERY(Query_for_list_of_tablesample_methods);
2820         else if (TailMatches2("TABLESAMPLE", MatchAny))
2821                 COMPLETE_WITH_CONST("(");
2822
2823 /* TRUNCATE */
2824         else if (Matches1("TRUNCATE"))
2825                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2826
2827 /* UNLISTEN */
2828         else if (Matches1("UNLISTEN"))
2829                 COMPLETE_WITH_QUERY("SELECT pg_catalog.quote_ident(channel) FROM pg_catalog.pg_listening_channels() AS channel WHERE substring(pg_catalog.quote_ident(channel),1,%d)='%s' UNION SELECT '*'");
2830
2831 /* UPDATE --- can be inside EXPLAIN, RULE, etc */
2832         /* If prev. word is UPDATE suggest a list of tables */
2833         else if (TailMatches1("UPDATE"))
2834                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
2835         /* Complete UPDATE <table> with "SET" */
2836         else if (TailMatches2("UPDATE", MatchAny))
2837                 COMPLETE_WITH_CONST("SET");
2838         /* Complete UPDATE <table> SET with list of attributes */
2839         else if (TailMatches3("UPDATE", MatchAny, "SET"))
2840                 COMPLETE_WITH_ATTR(prev2_wd, "");
2841         /* UPDATE <table> SET <attr> = */
2842         else if (TailMatches4("UPDATE", MatchAny, "SET", MatchAny))
2843                 COMPLETE_WITH_CONST("=");
2844
2845 /* USER MAPPING */
2846         else if (Matches3("ALTER|CREATE|DROP", "USER", "MAPPING"))
2847                 COMPLETE_WITH_CONST("FOR");
2848         else if (Matches4("CREATE", "USER", "MAPPING", "FOR"))
2849                 COMPLETE_WITH_QUERY(Query_for_list_of_roles
2850                                                         " UNION SELECT 'CURRENT_USER'"
2851                                                         " UNION SELECT 'PUBLIC'"
2852                                                         " UNION SELECT 'USER'");
2853         else if (Matches4("ALTER|DROP", "USER", "MAPPING", "FOR"))
2854                 COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
2855         else if (Matches5("CREATE|ALTER|DROP", "USER", "MAPPING", "FOR", MatchAny))
2856                 COMPLETE_WITH_CONST("SERVER");
2857         else if (Matches7("CREATE|ALTER", "USER", "MAPPING", "FOR", MatchAny, "SERVER", MatchAny))
2858                 COMPLETE_WITH_CONST("OPTIONS");
2859
2860 /*
2861  * VACUUM [ FULL | FREEZE ] [ VERBOSE ] [ table ]
2862  * VACUUM [ FULL | FREEZE ] [ VERBOSE ] ANALYZE [ table [ (column [, ...] ) ] ]
2863  */
2864         else if (Matches1("VACUUM"))
2865                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
2866                                                                    " UNION SELECT 'FULL'"
2867                                                                    " UNION SELECT 'FREEZE'"
2868                                                                    " UNION SELECT 'ANALYZE'"
2869                                                                    " UNION SELECT 'VERBOSE'");
2870         else if (Matches2("VACUUM", "FULL|FREEZE"))
2871                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
2872                                                                    " UNION SELECT 'ANALYZE'"
2873                                                                    " UNION SELECT 'VERBOSE'");
2874         else if (Matches3("VACUUM", "FULL|FREEZE", "ANALYZE"))
2875                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
2876                                                                    " UNION SELECT 'VERBOSE'");
2877         else if (Matches3("VACUUM", "FULL|FREEZE", "VERBOSE"))
2878                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
2879                                                                    " UNION SELECT 'ANALYZE'");
2880         else if (Matches2("VACUUM", "VERBOSE"))
2881                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
2882                                                                    " UNION SELECT 'ANALYZE'");
2883         else if (Matches2("VACUUM", "ANALYZE"))
2884                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
2885                                                                    " UNION SELECT 'VERBOSE'");
2886         else if (HeadMatches1("VACUUM"))
2887                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
2888
2889 /* WITH [RECURSIVE] */
2890
2891         /*
2892          * Only match when WITH is the first word, as WITH may appear in many
2893          * other contexts.
2894          */
2895         else if (Matches1("WITH"))
2896                 COMPLETE_WITH_CONST("RECURSIVE");
2897
2898 /* ANALYZE */
2899         /* Complete with list of tables */
2900         else if (Matches1("ANALYZE"))
2901                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tmf, NULL);
2902
2903 /* WHERE */
2904         /* Simple case of the word before the where being the table name */
2905         else if (TailMatches2(MatchAny, "WHERE"))
2906                 COMPLETE_WITH_ATTR(prev2_wd, "");
2907
2908 /* ... FROM ... */
2909 /* TODO: also include SRF ? */
2910         else if (TailMatches1("FROM") && !Matches3("COPY|\\copy", MatchAny, "FROM"))
2911                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
2912
2913 /* ... JOIN ... */
2914         else if (TailMatches1("JOIN"))
2915                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
2916
2917 /* Backslash commands */
2918 /* TODO:  \dc \dd \dl */
2919         else if (TailMatchesCS1("\\?"))
2920                 COMPLETE_WITH_LIST_CS3("commands", "options", "variables");
2921         else if (TailMatchesCS1("\\connect|\\c"))
2922         {
2923                 if (!recognized_connection_string(text))
2924                         COMPLETE_WITH_QUERY(Query_for_list_of_databases);
2925         }
2926         else if (TailMatchesCS2("\\connect|\\c", MatchAny))
2927         {
2928                 if (!recognized_connection_string(prev_wd))
2929                         COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2930         }
2931         else if (TailMatchesCS1("\\da*"))
2932                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_aggregates, NULL);
2933         else if (TailMatchesCS1("\\db*"))
2934                 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
2935         else if (TailMatchesCS1("\\dD*"))
2936                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL);
2937         else if (TailMatchesCS1("\\des*"))
2938                 COMPLETE_WITH_QUERY(Query_for_list_of_servers);
2939         else if (TailMatchesCS1("\\deu*"))
2940                 COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
2941         else if (TailMatchesCS1("\\dew*"))
2942                 COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
2943         else if (TailMatchesCS1("\\df*"))
2944                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
2945
2946         else if (TailMatchesCS1("\\dFd*"))
2947                 COMPLETE_WITH_QUERY(Query_for_list_of_ts_dictionaries);
2948         else if (TailMatchesCS1("\\dFp*"))
2949                 COMPLETE_WITH_QUERY(Query_for_list_of_ts_parsers);
2950         else if (TailMatchesCS1("\\dFt*"))
2951                 COMPLETE_WITH_QUERY(Query_for_list_of_ts_templates);
2952         /* must be at end of \dF alternatives: */
2953         else if (TailMatchesCS1("\\dF*"))
2954                 COMPLETE_WITH_QUERY(Query_for_list_of_ts_configurations);
2955
2956         else if (TailMatchesCS1("\\di*"))
2957                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
2958         else if (TailMatchesCS1("\\dL*"))
2959                 COMPLETE_WITH_QUERY(Query_for_list_of_languages);
2960         else if (TailMatchesCS1("\\dn*"))
2961                 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
2962         else if (TailMatchesCS1("\\dp") || TailMatchesCS1("\\z"))
2963                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
2964         else if (TailMatchesCS1("\\ds*"))
2965                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences, NULL);
2966         else if (TailMatchesCS1("\\dt*"))
2967                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2968         else if (TailMatchesCS1("\\dT*"))
2969                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL);
2970         else if (TailMatchesCS1("\\du*") || TailMatchesCS1("\\dg*"))
2971                 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2972         else if (TailMatchesCS1("\\dv*"))
2973                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
2974         else if (TailMatchesCS1("\\dx*"))
2975                 COMPLETE_WITH_QUERY(Query_for_list_of_extensions);
2976         else if (TailMatchesCS1("\\dm*"))
2977                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
2978         else if (TailMatchesCS1("\\dE*"))
2979                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL);
2980         else if (TailMatchesCS1("\\dy*"))
2981                 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
2982
2983         /* must be at end of \d alternatives: */
2984         else if (TailMatchesCS1("\\d*"))
2985                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations, NULL);
2986
2987         else if (TailMatchesCS1("\\ef"))
2988                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
2989         else if (TailMatchesCS1("\\ev"))
2990                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
2991
2992         else if (TailMatchesCS1("\\encoding"))
2993                 COMPLETE_WITH_QUERY(Query_for_list_of_encodings);
2994         else if (TailMatchesCS1("\\h") || TailMatchesCS1("\\help"))
2995                 COMPLETE_WITH_LIST(sql_commands);
2996         else if (TailMatchesCS1("\\password"))
2997                 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2998         else if (TailMatchesCS1("\\pset"))
2999         {
3000                 static const char *const my_list[] =
3001                 {"border", "columns", "expanded", "fieldsep", "fieldsep_zero",
3002                         "footer", "format", "linestyle", "null", "numericlocale",
3003                         "pager", "recordsep", "recordsep_zero", "tableattr", "title",
3004                         "tuples_only", "unicode_border_linestyle",
3005                 "unicode_column_linestyle", "unicode_header_linestyle", NULL};
3006
3007                 COMPLETE_WITH_LIST_CS(my_list);
3008         }
3009         else if (TailMatchesCS2("\\pset", MatchAny))
3010         {
3011                 if (TailMatchesCS1("format"))
3012                 {
3013                         static const char *const my_list[] =
3014                         {"unaligned", "aligned", "wrapped", "html", "asciidoc",
3015                         "latex", "latex-longtable", "troff-ms", NULL};
3016
3017                         COMPLETE_WITH_LIST_CS(my_list);
3018                 }
3019                 else if (TailMatchesCS1("linestyle"))
3020                         COMPLETE_WITH_LIST_CS3("ascii", "old-ascii", "unicode");
3021                 else if (TailMatchesCS1("unicode_border_linestyle|"
3022                                                                 "unicode_column_linestyle|"
3023                                                                 "unicode_header_linestyle"))
3024                         COMPLETE_WITH_LIST_CS2("single", "double");
3025         }
3026         else if (TailMatchesCS1("\\unset"))
3027         {
3028                 matches = complete_from_variables(text, "", "", true);
3029         }
3030         else if (TailMatchesCS1("\\set"))
3031         {
3032                 matches = complete_from_variables(text, "", "", false);
3033         }
3034         else if (TailMatchesCS2("\\set", MatchAny))
3035         {
3036                 if (TailMatchesCS1("AUTOCOMMIT|ON_ERROR_STOP|QUIET|"
3037                                                    "SINGLELINE|SINGLESTEP"))
3038                         COMPLETE_WITH_LIST_CS2("on", "off");
3039                 else if (TailMatchesCS1("COMP_KEYWORD_CASE"))
3040                         COMPLETE_WITH_LIST_CS4("lower", "upper",
3041                                                                    "preserve-lower", "preserve-upper");
3042                 else if (TailMatchesCS1("ECHO"))
3043                         COMPLETE_WITH_LIST_CS4("errors", "queries", "all", "none");
3044                 else if (TailMatchesCS1("ECHO_HIDDEN"))
3045                         COMPLETE_WITH_LIST_CS3("noexec", "off", "on");
3046                 else if (TailMatchesCS1("HISTCONTROL"))
3047                         COMPLETE_WITH_LIST_CS4("ignorespace", "ignoredups",
3048                                                                    "ignoreboth", "none");
3049                 else if (TailMatchesCS1("ON_ERROR_ROLLBACK"))
3050                         COMPLETE_WITH_LIST_CS3("on", "off", "interactive");
3051                 else if (TailMatchesCS1("SHOW_CONTEXT"))
3052                         COMPLETE_WITH_LIST_CS3("never", "errors", "always");
3053                 else if (TailMatchesCS1("VERBOSITY"))
3054                         COMPLETE_WITH_LIST_CS3("default", "verbose", "terse");
3055         }
3056         else if (TailMatchesCS1("\\sf*"))
3057                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
3058         else if (TailMatchesCS1("\\sv*"))
3059                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
3060         else if (TailMatchesCS1("\\cd|\\e|\\edit|\\g|\\i|\\include|"
3061                                                         "\\ir|\\include_relative|\\o|\\out|"
3062                                                         "\\s|\\w|\\write|\\lo_import"))
3063         {
3064                 completion_charp = "\\";
3065                 matches = completion_matches(text, complete_from_files);
3066         }
3067
3068         /*
3069          * Finally, we look through the list of "things", such as TABLE, INDEX and
3070          * check if that was the previous word. If so, execute the query to get a
3071          * list of them.
3072          */
3073         else
3074         {
3075                 int                     i;
3076
3077                 for (i = 0; words_after_create[i].name; i++)
3078                 {
3079                         if (pg_strcasecmp(prev_wd, words_after_create[i].name) == 0)
3080                         {
3081                                 if (words_after_create[i].query)
3082                                         COMPLETE_WITH_QUERY(words_after_create[i].query);
3083                                 else if (words_after_create[i].squery)
3084                                         COMPLETE_WITH_SCHEMA_QUERY(*words_after_create[i].squery,
3085                                                                                            NULL);
3086                                 break;
3087                         }
3088                 }
3089         }
3090
3091         /*
3092          * If we still don't have anything to match we have to fabricate some sort
3093          * of default list. If we were to just return NULL, readline automatically
3094          * attempts filename completion, and that's usually no good.
3095          */
3096         if (matches == NULL)
3097         {
3098                 COMPLETE_WITH_CONST("");
3099 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
3100                 rl_completion_append_character = '\0';
3101 #endif
3102         }
3103
3104         /* free storage */
3105         free(previous_words);
3106         free(words_buffer);
3107
3108         /* Return our Grand List O' Matches */
3109         return matches;
3110 }
3111
3112
3113 /*
3114  * GENERATOR FUNCTIONS
3115  *
3116  * These functions do all the actual work of completing the input. They get
3117  * passed the text so far and the count how many times they have been called
3118  * so far with the same text.
3119  * If you read the above carefully, you'll see that these don't get called
3120  * directly but through the readline interface.
3121  * The return value is expected to be the full completion of the text, going
3122  * through a list each time, or NULL if there are no more matches. The string
3123  * will be free()'d by readline, so you must run it through strdup() or
3124  * something of that sort.
3125  */
3126
3127 /*
3128  * Common routine for create_command_generator and drop_command_generator.
3129  * Entries that have 'excluded' flags are not returned.
3130  */
3131 static char *
3132 create_or_drop_command_generator(const char *text, int state, bits32 excluded)
3133 {
3134         static int      list_index,
3135                                 string_length;
3136         const char *name;
3137
3138         /* If this is the first time for this completion, init some values */
3139         if (state == 0)
3140         {
3141                 list_index = 0;
3142                 string_length = strlen(text);
3143         }
3144
3145         /* find something that matches */
3146         while ((name = words_after_create[list_index++].name))
3147         {
3148                 if ((pg_strncasecmp(name, text, string_length) == 0) &&
3149                         !(words_after_create[list_index - 1].flags & excluded))
3150                         return pg_strdup_keyword_case(name, text);
3151         }
3152         /* if nothing matches, return NULL */
3153         return NULL;
3154 }
3155
3156 /*
3157  * This one gives you one from a list of things you can put after CREATE
3158  * as defined above.
3159  */
3160 static char *
3161 create_command_generator(const char *text, int state)
3162 {
3163         return create_or_drop_command_generator(text, state, THING_NO_CREATE);
3164 }
3165
3166 /*
3167  * This function gives you a list of things you can put after a DROP command.
3168  */
3169 static char *
3170 drop_command_generator(const char *text, int state)
3171 {
3172         return create_or_drop_command_generator(text, state, THING_NO_DROP);
3173 }
3174
3175 /* The following two functions are wrappers for _complete_from_query */
3176
3177 static char *
3178 complete_from_query(const char *text, int state)
3179 {
3180         return _complete_from_query(0, text, state);
3181 }
3182
3183 static char *
3184 complete_from_schema_query(const char *text, int state)
3185 {
3186         return _complete_from_query(1, text, state);
3187 }
3188
3189
3190 /*
3191  * This creates a list of matching things, according to a query pointed to
3192  * by completion_charp.
3193  * The query can be one of two kinds:
3194  *
3195  * 1. A simple query which must contain a %d and a %s, which will be replaced
3196  * by the string length of the text and the text itself. The query may also
3197  * have up to four more %s in it; the first two such will be replaced by the
3198  * value of completion_info_charp, the next two by the value of
3199  * completion_info_charp2.
3200  *
3201  * 2. A schema query used for completion of both schema and relation names.
3202  * These are more complex and must contain in the following order:
3203  * %d %s %d %s %d %s %s %d %s
3204  * where %d is the string length of the text and %s the text itself.
3205  *
3206  * It is assumed that strings should be escaped to become SQL literals
3207  * (that is, what is in the query is actually ... '%s' ...)
3208  *
3209  * See top of file for examples of both kinds of query.
3210  */
3211 static char *
3212 _complete_from_query(int is_schema_query, const char *text, int state)
3213 {
3214         static int      list_index,
3215                                 byte_length;
3216         static PGresult *result = NULL;
3217         /*
3218          * If this is the first time for this completion, we fetch a list of our
3219          * "things" from the backend.
3220          */
3221         if (state == 0)
3222         {
3223                 PQExpBufferData query_buffer;
3224                 char       *e_text;
3225                 char       *e_info_charp;
3226                 char       *e_info_charp2;
3227                 const char *pstr = text;
3228                 int                     char_length = 0;
3229
3230                 list_index = 0;
3231                 byte_length = strlen(text);
3232
3233                 /* Count length as number of characters (not bytes), for passing to substring */
3234                 while (*pstr)
3235                 {
3236                         char_length++;
3237                         pstr += PQmblen(pstr, pset.encoding);
3238                 }
3239
3240                 /* Free any prior result */
3241                 PQclear(result);
3242                 result = NULL;
3243
3244                 /* Set up suitably-escaped copies of textual inputs */
3245                 e_text = escape_string(text);
3246
3247                 if (completion_info_charp)
3248                         e_info_charp = escape_string(completion_info_charp);
3249                 else
3250                         e_info_charp = NULL;
3251
3252                 if (completion_info_charp2)
3253                         e_info_charp2 = escape_string(completion_info_charp2);
3254                 else
3255                         e_info_charp2 = NULL;
3256
3257                 initPQExpBuffer(&query_buffer);
3258
3259                 if (is_schema_query)
3260                 {
3261                         /* completion_squery gives us the pieces to assemble */
3262                         const char *qualresult = completion_squery->qualresult;
3263
3264                         if (qualresult == NULL)
3265                                 qualresult = completion_squery->result;
3266
3267                         /* Get unqualified names matching the input-so-far */
3268                         appendPQExpBuffer(&query_buffer, "SELECT %s FROM %s WHERE ",
3269                                                           completion_squery->result,
3270                                                           completion_squery->catname);
3271                         if (completion_squery->selcondition)
3272                                 appendPQExpBuffer(&query_buffer, "%s AND ",
3273                                                                   completion_squery->selcondition);
3274                         appendPQExpBuffer(&query_buffer, "substring(%s,1,%d)='%s'",
3275                                                           completion_squery->result,
3276                                                           char_length, e_text);
3277                         appendPQExpBuffer(&query_buffer, " AND %s",
3278                                                           completion_squery->viscondition);
3279
3280                         /*
3281                          * When fetching relation names, suppress system catalogs unless
3282                          * the input-so-far begins with "pg_".  This is a compromise
3283                          * between not offering system catalogs for completion at all, and
3284                          * having them swamp the result when the input is just "p".
3285                          */
3286                         if (strcmp(completion_squery->catname,
3287                                            "pg_catalog.pg_class c") == 0 &&
3288                                 strncmp(text, "pg_", 3) !=0)
3289                         {
3290                                 appendPQExpBufferStr(&query_buffer,
3291                                                                          " AND c.relnamespace <> (SELECT oid FROM"
3292                                    " pg_catalog.pg_namespace WHERE nspname = 'pg_catalog')");
3293                         }
3294
3295                         /*
3296                          * Add in matching schema names, but only if there is more than
3297                          * one potential match among schema names.
3298                          */
3299                         appendPQExpBuffer(&query_buffer, "\nUNION\n"
3300                                                    "SELECT pg_catalog.quote_ident(n.nspname) || '.' "
3301                                                           "FROM pg_catalog.pg_namespace n "
3302                                                           "WHERE substring(pg_catalog.quote_ident(n.nspname) || '.',1,%d)='%s'",
3303                                                           char_length, e_text);
3304                         appendPQExpBuffer(&query_buffer,
3305                                                           " AND (SELECT pg_catalog.count(*)"
3306                                                           " FROM pg_catalog.pg_namespace"
3307                         " WHERE substring(pg_catalog.quote_ident(nspname) || '.',1,%d) ="
3308                                                           " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(nspname))+1)) > 1",
3309                                                           char_length, e_text);
3310
3311                         /*
3312                          * Add in matching qualified names, but only if there is exactly
3313                          * one schema matching the input-so-far.
3314                          */
3315                         appendPQExpBuffer(&query_buffer, "\nUNION\n"
3316                                          "SELECT pg_catalog.quote_ident(n.nspname) || '.' || %s "
3317                                                           "FROM %s, pg_catalog.pg_namespace n "
3318                                                           "WHERE %s = n.oid AND ",
3319                                                           qualresult,
3320                                                           completion_squery->catname,
3321                                                           completion_squery->namespace);
3322                         if (completion_squery->selcondition)
3323                                 appendPQExpBuffer(&query_buffer, "%s AND ",
3324                                                                   completion_squery->selcondition);
3325                         appendPQExpBuffer(&query_buffer, "substring(pg_catalog.quote_ident(n.nspname) || '.' || %s,1,%d)='%s'",
3326                                                           qualresult,
3327                                                           char_length, e_text);
3328
3329                         /*
3330                          * This condition exploits the single-matching-schema rule to
3331                          * speed up the query
3332                          */
3333                         appendPQExpBuffer(&query_buffer,
3334                         " AND substring(pg_catalog.quote_ident(n.nspname) || '.',1,%d) ="
3335                                                           " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(n.nspname))+1)",
3336                                                           char_length, e_text);
3337                         appendPQExpBuffer(&query_buffer,
3338                                                           " AND (SELECT pg_catalog.count(*)"
3339                                                           " FROM pg_catalog.pg_namespace"
3340                         " WHERE substring(pg_catalog.quote_ident(nspname) || '.',1,%d) ="
3341                                                           " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(nspname))+1)) = 1",
3342                                                           char_length, e_text);
3343
3344                         /* If an addon query was provided, use it */
3345                         if (completion_charp)
3346                                 appendPQExpBuffer(&query_buffer, "\n%s", completion_charp);
3347                 }
3348                 else
3349                 {
3350                         /* completion_charp is an sprintf-style format string */
3351                         appendPQExpBuffer(&query_buffer, completion_charp,
3352                                                           char_length, e_text,
3353                                                           e_info_charp, e_info_charp,
3354                                                           e_info_charp2, e_info_charp2);
3355                 }
3356
3357                 /* Limit the number of records in the result */
3358                 appendPQExpBuffer(&query_buffer, "\nLIMIT %d",
3359                                                   completion_max_records);
3360
3361                 result = exec_query(query_buffer.data);
3362
3363                 termPQExpBuffer(&query_buffer);
3364                 free(e_text);
3365                 if (e_info_charp)
3366                         free(e_info_charp);
3367                 if (e_info_charp2)
3368                         free(e_info_charp2);
3369         }
3370
3371         /* Find something that matches */
3372         if (result && PQresultStatus(result) == PGRES_TUPLES_OK)
3373         {
3374                 const char *item;
3375
3376                 while (list_index < PQntuples(result) &&
3377                            (item = PQgetvalue(result, list_index++, 0)))
3378                         if (pg_strncasecmp(text, item, byte_length) == 0)
3379                                 return pg_strdup(item);
3380         }
3381
3382         /* If nothing matches, free the db structure and return null */
3383         PQclear(result);
3384         result = NULL;
3385         return NULL;
3386 }
3387
3388
3389 /*
3390  * This function returns in order one of a fixed, NULL pointer terminated list
3391  * of strings (if matching). This can be used if there are only a fixed number
3392  * SQL words that can appear at certain spot.
3393  */
3394 static char *
3395 complete_from_list(const char *text, int state)
3396 {
3397         static int      string_length,
3398                                 list_index,
3399                                 matches;
3400         static bool casesensitive;
3401         const char *item;
3402
3403         /* need to have a list */
3404         Assert(completion_charpp != NULL);
3405
3406         /* Initialization */
3407         if (state == 0)
3408         {
3409                 list_index = 0;
3410                 string_length = strlen(text);
3411                 casesensitive = completion_case_sensitive;
3412                 matches = 0;
3413         }
3414
3415         while ((item = completion_charpp[list_index++]))
3416         {
3417                 /* First pass is case sensitive */
3418                 if (casesensitive && strncmp(text, item, string_length) == 0)
3419                 {
3420                         matches++;
3421                         return pg_strdup(item);
3422                 }
3423
3424                 /* Second pass is case insensitive, don't bother counting matches */
3425                 if (!casesensitive && pg_strncasecmp(text, item, string_length) == 0)
3426                 {
3427                         if (completion_case_sensitive)
3428                                 return pg_strdup(item);
3429                         else
3430
3431                                 /*
3432                                  * If case insensitive matching was requested initially,
3433                                  * adjust the case according to setting.
3434                                  */
3435                                 return pg_strdup_keyword_case(item, text);
3436                 }
3437         }
3438
3439         /*
3440          * No matches found. If we're not case insensitive already, lets switch to
3441          * being case insensitive and try again
3442          */
3443         if (casesensitive && matches == 0)
3444         {
3445                 casesensitive = false;
3446                 list_index = 0;
3447                 state++;
3448                 return complete_from_list(text, state);
3449         }
3450
3451         /* If no more matches, return null. */
3452         return NULL;
3453 }
3454
3455
3456 /*
3457  * This function returns one fixed string the first time even if it doesn't
3458  * match what's there, and nothing the second time. This should be used if
3459  * there is only one possibility that can appear at a certain spot, so
3460  * misspellings will be overwritten.  The string to be passed must be in
3461  * completion_charp.
3462  */
3463 static char *
3464 complete_from_const(const char *text, int state)
3465 {
3466         Assert(completion_charp != NULL);
3467         if (state == 0)
3468         {
3469                 if (completion_case_sensitive)
3470                         return pg_strdup(completion_charp);
3471                 else
3472
3473                         /*
3474                          * If case insensitive matching was requested initially, adjust
3475                          * the case according to setting.
3476                          */
3477                         return pg_strdup_keyword_case(completion_charp, text);
3478         }
3479         else
3480                 return NULL;
3481 }
3482
3483
3484 /*
3485  * This function appends the variable name with prefix and suffix to
3486  * the variable names array.
3487  */
3488 static void
3489 append_variable_names(char ***varnames, int *nvars,
3490                                           int *maxvars, const char *varname,
3491                                           const char *prefix, const char *suffix)
3492 {
3493         if (*nvars >= *maxvars)
3494         {
3495                 *maxvars *= 2;
3496                 *varnames = (char **) pg_realloc(*varnames,
3497                                                                                  ((*maxvars) + 1) * sizeof(char *));
3498         }
3499
3500         (*varnames)[(*nvars)++] = psprintf("%s%s%s", prefix, varname, suffix);
3501 }
3502
3503
3504 /*
3505  * This function supports completion with the name of a psql variable.
3506  * The variable names can be prefixed and suffixed with additional text
3507  * to support quoting usages. If need_value is true, only the variables
3508  * that have the set values are picked up.
3509  */
3510 static char **
3511 complete_from_variables(const char *text, const char *prefix, const char *suffix,
3512                                                 bool need_value)
3513 {
3514         char      **matches;
3515         char      **varnames;
3516         int                     nvars = 0;
3517         int                     maxvars = 100;
3518         int                     i;
3519         struct _variable *ptr;
3520
3521         static const char *const known_varnames[] = {
3522                 "AUTOCOMMIT", "COMP_KEYWORD_CASE", "DBNAME", "ECHO", "ECHO_HIDDEN",
3523                 "ENCODING", "FETCH_COUNT", "HISTCONTROL", "HISTFILE", "HISTSIZE",
3524                 "HOST", "IGNOREEOF", "LASTOID", "ON_ERROR_ROLLBACK", "ON_ERROR_STOP",
3525                 "PORT", "PROMPT1", "PROMPT2", "PROMPT3", "QUIET",
3526                 "SHOW_CONTEXT", "SINGLELINE", "SINGLESTEP",
3527                 "USER", "VERBOSITY", NULL
3528         };
3529
3530         varnames = (char **) pg_malloc((maxvars + 1) * sizeof(char *));
3531
3532         if (!need_value)
3533         {
3534                 for (i = 0; known_varnames[i] && nvars < maxvars; i++)
3535                         append_variable_names(&varnames, &nvars, &maxvars,
3536                                                                   known_varnames[i], prefix, suffix);
3537         }
3538
3539         for (ptr = pset.vars->next; ptr; ptr = ptr->next)
3540         {
3541                 if (need_value && !(ptr->value))
3542                         continue;
3543                 for (i = 0; known_varnames[i]; i++)             /* remove duplicate entry */
3544                 {
3545                         if (strcmp(ptr->name, known_varnames[i]) == 0)
3546                                 continue;
3547                 }
3548                 append_variable_names(&varnames, &nvars, &maxvars, ptr->name,
3549                                                           prefix, suffix);
3550         }
3551
3552         varnames[nvars] = NULL;
3553         COMPLETE_WITH_LIST_CS((const char *const *) varnames);
3554
3555         for (i = 0; i < nvars; i++)
3556                 free(varnames[i]);
3557         free(varnames);
3558
3559         return matches;
3560 }
3561
3562
3563 /*
3564  * This function wraps rl_filename_completion_function() to strip quotes from
3565  * the input before searching for matches and to quote any matches for which
3566  * the consuming command will require it.
3567  */
3568 static char *
3569 complete_from_files(const char *text, int state)
3570 {
3571         static const char *unquoted_text;
3572         char       *unquoted_match;
3573         char       *ret = NULL;
3574
3575         if (state == 0)
3576         {
3577                 /* Initialization: stash the unquoted input. */
3578                 unquoted_text = strtokx(text, "", NULL, "'", *completion_charp,
3579                                                                 false, true, pset.encoding);
3580                 /* expect a NULL return for the empty string only */
3581                 if (!unquoted_text)
3582                 {
3583                         Assert(*text == '\0');
3584                         unquoted_text = text;
3585                 }
3586         }
3587
3588         unquoted_match = filename_completion_function(unquoted_text, state);
3589         if (unquoted_match)
3590         {
3591                 /*
3592                  * Caller sets completion_charp to a zero- or one-character string
3593                  * containing the escape character.  This is necessary since \copy has
3594                  * no escape character, but every other backslash command recognizes
3595                  * "\" as an escape character.  Since we have only two callers, don't
3596                  * bother providing a macro to simplify this.
3597                  */
3598                 ret = quote_if_needed(unquoted_match, " \t\r\n\"`",
3599                                                           '\'', *completion_charp, pset.encoding);
3600                 if (ret)
3601                         free(unquoted_match);
3602                 else
3603                         ret = unquoted_match;
3604         }
3605
3606         return ret;
3607 }
3608
3609
3610 /* HELPER FUNCTIONS */
3611
3612
3613 /*
3614  * Make a pg_strdup copy of s and convert the case according to
3615  * COMP_KEYWORD_CASE setting, using ref as the text that was already entered.
3616  */
3617 static char *
3618 pg_strdup_keyword_case(const char *s, const char *ref)
3619 {
3620         char       *ret,
3621                            *p;
3622         unsigned char first = ref[0];
3623
3624         ret = pg_strdup(s);
3625
3626         if (pset.comp_case == PSQL_COMP_CASE_LOWER ||
3627                 ((pset.comp_case == PSQL_COMP_CASE_PRESERVE_LOWER ||
3628            pset.comp_case == PSQL_COMP_CASE_PRESERVE_UPPER) && islower(first)) ||
3629                 (pset.comp_case == PSQL_COMP_CASE_PRESERVE_LOWER && !isalpha(first)))
3630         {
3631                 for (p = ret; *p; p++)
3632                         *p = pg_tolower((unsigned char) *p);
3633         }
3634         else
3635         {
3636                 for (p = ret; *p; p++)
3637                         *p = pg_toupper((unsigned char) *p);
3638         }
3639
3640         return ret;
3641 }
3642
3643
3644 /*
3645  * escape_string - Escape argument for use as string literal.
3646  *
3647  * The returned value has to be freed.
3648  */
3649 static char *
3650 escape_string(const char *text)
3651 {
3652         size_t          text_length;
3653         char       *result;
3654
3655         text_length = strlen(text);
3656
3657         result = pg_malloc(text_length * 2 + 1);
3658         PQescapeStringConn(pset.db, result, text, text_length, NULL);
3659
3660         return result;
3661 }
3662
3663
3664 /*
3665  * Execute a query and report any errors. This should be the preferred way of
3666  * talking to the database in this file.
3667  */
3668 static PGresult *
3669 exec_query(const char *query)
3670 {
3671         PGresult   *result;
3672
3673         if (query == NULL || !pset.db || PQstatus(pset.db) != CONNECTION_OK)
3674                 return NULL;
3675
3676         result = PQexec(pset.db, query);
3677
3678         if (PQresultStatus(result) != PGRES_TUPLES_OK)
3679         {
3680 #ifdef NOT_USED
3681                 psql_error("tab completion query failed: %s\nQuery was:\n%s\n",
3682                                    PQerrorMessage(pset.db), query);
3683 #endif
3684                 PQclear(result);
3685                 result = NULL;
3686         }
3687
3688         return result;
3689 }
3690
3691
3692 /*
3693  * Parse all the word(s) before point.
3694  *
3695  * Returns a malloc'd array of character pointers that point into the malloc'd
3696  * data array returned to *buffer; caller must free() both of these when done.
3697  * *nwords receives the number of words found, ie, the valid length of the
3698  * return array.
3699  *
3700  * Words are returned right to left, that is, previous_words[0] gets the last
3701  * word before point, previous_words[1] the next-to-last, etc.
3702  */
3703 static char **
3704 get_previous_words(int point, char **buffer, int *nwords)
3705 {
3706         char      **previous_words;
3707         char       *buf;
3708         char       *outptr;
3709         int                     words_found = 0;
3710         int                     i;
3711
3712         /*
3713          * If we have anything in tab_completion_query_buf, paste it together with
3714          * rl_line_buffer to construct the full query.  Otherwise we can just use
3715          * rl_line_buffer as the input string.
3716          */
3717         if (tab_completion_query_buf && tab_completion_query_buf->len > 0)
3718         {
3719                 i = tab_completion_query_buf->len;
3720                 buf = pg_malloc(point + i + 2);
3721                 memcpy(buf, tab_completion_query_buf->data, i);
3722                 buf[i++] = '\n';
3723                 memcpy(buf + i, rl_line_buffer, point);
3724                 i += point;
3725                 buf[i] = '\0';
3726                 /* Readjust point to reference appropriate offset in buf */
3727                 point = i;
3728         }
3729         else
3730                 buf = rl_line_buffer;
3731
3732         /*
3733          * Allocate an array of string pointers and a buffer to hold the strings
3734          * themselves.  The worst case is that the line contains only
3735          * non-whitespace WORD_BREAKS characters, making each one a separate word.
3736          * This is usually much more space than we need, but it's cheaper than
3737          * doing a separate malloc() for each word.
3738          */
3739         previous_words = (char **) pg_malloc(point * sizeof(char *));
3740         *buffer = outptr = (char *) pg_malloc(point * 2);
3741
3742         /*
3743          * First we look for a non-word char before the current point.  (This is
3744          * probably useless, if readline is on the same page as we are about what
3745          * is a word, but if so it's cheap.)
3746          */
3747         for (i = point - 1; i >= 0; i--)
3748         {
3749                 if (strchr(WORD_BREAKS, buf[i]))
3750                         break;
3751         }
3752         point = i;
3753
3754         /*
3755          * Now parse words, working backwards, until we hit start of line.  The
3756          * backwards scan has some interesting but intentional properties
3757          * concerning parenthesis handling.
3758          */
3759         while (point >= 0)
3760         {
3761                 int                     start,
3762                                         end;
3763                 bool            inquotes = false;
3764                 int                     parentheses = 0;
3765
3766                 /* now find the first non-space which then constitutes the end */
3767                 end = -1;
3768                 for (i = point; i >= 0; i--)
3769                 {
3770                         if (!isspace((unsigned char) buf[i]))
3771                         {
3772                                 end = i;
3773                                 break;
3774                         }
3775                 }
3776                 /* if no end found, we're done */
3777                 if (end < 0)
3778                         break;
3779
3780                 /*
3781                  * Otherwise we now look for the start.  The start is either the last
3782                  * character before any word-break character going backwards from the
3783                  * end, or it's simply character 0.  We also handle open quotes and
3784                  * parentheses.
3785                  */
3786                 for (start = end; start > 0; start--)
3787                 {
3788                         if (buf[start] == '"')
3789                                 inquotes = !inquotes;
3790                         if (!inquotes)
3791                         {
3792                                 if (buf[start] == ')')
3793                                         parentheses++;
3794                                 else if (buf[start] == '(')
3795                                 {
3796                                         if (--parentheses <= 0)
3797                                                 break;
3798                                 }
3799                                 else if (parentheses == 0 &&
3800                                                  strchr(WORD_BREAKS, buf[start - 1]))
3801                                         break;
3802                         }
3803                 }
3804
3805                 /* Return the word located at start to end inclusive */
3806                 previous_words[words_found++] = outptr;
3807                 i = end - start + 1;
3808                 memcpy(outptr, &buf[start], i);
3809                 outptr += i;
3810                 *outptr++ = '\0';
3811
3812                 /* Continue searching */
3813                 point = start - 1;
3814         }
3815
3816         /* Release parsing input workspace, if we made one above */
3817         if (buf != rl_line_buffer)
3818                 free(buf);
3819
3820         *nwords = words_found;
3821         return previous_words;
3822 }
3823
3824 /*
3825  * Look up the type for the GUC variable with the passed name.
3826  *
3827  * Returns NULL if the variable is unknown. Otherwise the returned string,
3828  * containing the type, has to be freed.
3829  */
3830 static char *
3831 get_guctype(const char *varname)
3832 {
3833         PQExpBufferData query_buffer;
3834         char       *e_varname;
3835         PGresult   *result;
3836         char       *guctype = NULL;
3837
3838         e_varname = escape_string(varname);
3839
3840         initPQExpBuffer(&query_buffer);
3841         appendPQExpBuffer(&query_buffer,
3842                                           "SELECT vartype FROM pg_catalog.pg_settings "
3843                                           "WHERE pg_catalog.lower(name) = pg_catalog.lower('%s')",
3844                                           e_varname);
3845
3846         result = exec_query(query_buffer.data);
3847         termPQExpBuffer(&query_buffer);
3848         free(e_varname);
3849
3850         if (PQresultStatus(result) == PGRES_TUPLES_OK && PQntuples(result) > 0)
3851                 guctype = pg_strdup(PQgetvalue(result, 0, 0));
3852
3853         PQclear(result);
3854
3855         return guctype;
3856 }
3857
3858 #ifdef NOT_USED
3859
3860 /*
3861  * Surround a string with single quotes. This works for both SQL and
3862  * psql internal. Currently disabled because it is reported not to
3863  * cooperate with certain versions of readline.
3864  */
3865 static char *
3866 quote_file_name(char *text, int match_type, char *quote_pointer)
3867 {
3868         char       *s;
3869         size_t          length;
3870
3871         (void) quote_pointer;           /* not used */
3872
3873         length = strlen(text) +(match_type == SINGLE_MATCH ? 3 : 2);
3874         s = pg_malloc(length);
3875         s[0] = '\'';
3876         strcpy(s + 1, text);
3877         if (match_type == SINGLE_MATCH)
3878                 s[length - 2] = '\'';
3879         s[length - 1] = '\0';
3880         return s;
3881 }
3882
3883 static char *
3884 dequote_file_name(char *text, char quote_char)
3885 {
3886         char       *s;
3887         size_t          length;
3888
3889         if (!quote_char)
3890                 return pg_strdup(text);
3891
3892         length = strlen(text);
3893         s = pg_malloc(length - 2 + 1);
3894         strlcpy(s, text +1, length - 2 + 1);
3895
3896         return s;
3897 }
3898 #endif   /* NOT_USED */
3899
3900 #endif   /* USE_READLINE */