]> granicus.if.org Git - postgresql/blob - src/bin/psql/tab-complete.c
Add tab completion for pager_min_lines to psql.
[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",
1278                 "\\copyright", "\\crosstabview",
1279                 "\\d", "\\da", "\\dA", "\\db", "\\dc", "\\dC", "\\dd", "\\ddp", "\\dD",
1280                 "\\des", "\\det", "\\deu", "\\dew", "\\dE", "\\df",
1281                 "\\dF", "\\dFd", "\\dFp", "\\dFt", "\\dg", "\\di", "\\dl", "\\dL",
1282                 "\\dm", "\\dn", "\\do", "\\dO", "\\dp", "\\drds", "\\ds", "\\dS",
1283                 "\\dt", "\\dT", "\\dv", "\\du", "\\dx", "\\dy",
1284                 "\\e", "\\echo", "\\ef", "\\encoding", "\\errverbose", "\\ev",
1285                 "\\f", "\\g", "\\gexec", "\\gset", "\\h", "\\help", "\\H", "\\i", "\\ir", "\\l",
1286                 "\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",
1287                 "\\o", "\\p", "\\password", "\\prompt", "\\pset", "\\q", "\\qecho", "\\r",
1288                 "\\s", "\\set", "\\setenv", "\\sf", "\\sv", "\\t", "\\T",
1289                 "\\timing", "\\unset", "\\x", "\\w", "\\watch", "\\z", "\\!", NULL
1290         };
1291
1292         (void) end;                                     /* "end" is not used */
1293
1294 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
1295         rl_completion_append_character = ' ';
1296 #endif
1297
1298         /* Clear a few things. */
1299         completion_charp = NULL;
1300         completion_charpp = NULL;
1301         completion_info_charp = NULL;
1302         completion_info_charp2 = NULL;
1303
1304         /*
1305          * Scan the input line to extract the words before our current position.
1306          * According to those we'll make some smart decisions on what the user is
1307          * probably intending to type.
1308          */
1309         previous_words = get_previous_words(start,
1310                                                                                 &words_buffer,
1311                                                                                 &previous_words_count);
1312
1313         /* If current word is a backslash command, offer completions for that */
1314         if (text[0] == '\\')
1315                 COMPLETE_WITH_LIST_CS(backslash_commands);
1316
1317         /* If current word is a variable interpolation, handle that case */
1318         else if (text[0] == ':' && text[1] != ':')
1319         {
1320                 if (text[1] == '\'')
1321                         matches = complete_from_variables(text, ":'", "'", true);
1322                 else if (text[1] == '"')
1323                         matches = complete_from_variables(text, ":\"", "\"", true);
1324                 else
1325                         matches = complete_from_variables(text, ":", "", true);
1326         }
1327
1328         /* If no previous word, suggest one of the basic sql commands */
1329         else if (previous_words_count == 0)
1330                 COMPLETE_WITH_LIST(sql_commands);
1331
1332 /* CREATE */
1333         /* complete with something you can create */
1334         else if (TailMatches1("CREATE"))
1335                 matches = completion_matches(text, create_command_generator);
1336
1337 /* DROP, but not DROP embedded in other commands */
1338         /* complete with something you can drop */
1339         else if (Matches1("DROP"))
1340                 matches = completion_matches(text, drop_command_generator);
1341
1342 /* ALTER */
1343
1344         /* ALTER TABLE */
1345         else if (Matches2("ALTER", "TABLE"))
1346                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
1347                                                                    "UNION SELECT 'ALL IN TABLESPACE'");
1348
1349         /* ALTER something */
1350         else if (Matches1("ALTER"))
1351         {
1352                 static const char *const list_ALTER[] =
1353                 {"AGGREGATE", "COLLATION", "CONVERSION", "DATABASE", "DEFAULT PRIVILEGES", "DOMAIN",
1354                         "EVENT TRIGGER", "EXTENSION", "FOREIGN DATA WRAPPER", "FOREIGN TABLE", "FUNCTION",
1355                         "GROUP", "INDEX", "LANGUAGE", "LARGE OBJECT", "MATERIALIZED VIEW", "OPERATOR",
1356                         "POLICY", "ROLE", "RULE", "SCHEMA", "SERVER", "SEQUENCE", "SYSTEM", "TABLE",
1357                         "TABLESPACE", "TEXT SEARCH", "TRIGGER", "TYPE",
1358                 "USER", "USER MAPPING FOR", "VIEW", NULL};
1359
1360                 COMPLETE_WITH_LIST(list_ALTER);
1361         }
1362         /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx */
1363         else if (TailMatches4("ALL", "IN", "TABLESPACE", MatchAny))
1364                 COMPLETE_WITH_LIST2("SET TABLESPACE", "OWNED BY");
1365         /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY */
1366         else if (TailMatches6("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY"))
1367                 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
1368         /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY xxx */
1369         else if (TailMatches7("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY", MatchAny))
1370                 COMPLETE_WITH_CONST("SET TABLESPACE");
1371         /* ALTER AGGREGATE,FUNCTION <name> */
1372         else if (Matches3("ALTER", "AGGREGATE|FUNCTION", MatchAny))
1373                 COMPLETE_WITH_CONST("(");
1374         /* ALTER AGGREGATE,FUNCTION <name> (...) */
1375         else if (Matches4("ALTER", "AGGREGATE|FUNCTION", MatchAny, MatchAny))
1376         {
1377                 if (ends_with(prev_wd, ')'))
1378                         COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1379                 else
1380                         COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
1381         }
1382
1383         /* ALTER SCHEMA <name> */
1384         else if (Matches3("ALTER", "SCHEMA", MatchAny))
1385                 COMPLETE_WITH_LIST2("OWNER TO", "RENAME TO");
1386
1387         /* ALTER COLLATION <name> */
1388         else if (Matches3("ALTER", "COLLATION", MatchAny))
1389                 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1390
1391         /* ALTER CONVERSION <name> */
1392         else if (Matches3("ALTER", "CONVERSION", MatchAny))
1393                 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1394
1395         /* ALTER DATABASE <name> */
1396         else if (Matches3("ALTER", "DATABASE", MatchAny))
1397                 COMPLETE_WITH_LIST7("RESET", "SET", "OWNER TO", "RENAME TO",
1398                                                         "IS_TEMPLATE", "ALLOW_CONNECTIONS",
1399                                                         "CONNECTION LIMIT");
1400
1401         /* ALTER EVENT TRIGGER */
1402         else if (Matches3("ALTER", "EVENT", "TRIGGER"))
1403                 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
1404
1405         /* ALTER EVENT TRIGGER <name> */
1406         else if (Matches4("ALTER", "EVENT", "TRIGGER", MatchAny))
1407                 COMPLETE_WITH_LIST4("DISABLE", "ENABLE", "OWNER TO", "RENAME TO");
1408
1409         /* ALTER EVENT TRIGGER <name> ENABLE */
1410         else if (Matches5("ALTER", "EVENT", "TRIGGER", MatchAny, "ENABLE"))
1411                 COMPLETE_WITH_LIST2("REPLICA", "ALWAYS");
1412
1413         /* ALTER EXTENSION <name> */
1414         else if (Matches3("ALTER", "EXTENSION", MatchAny))
1415                 COMPLETE_WITH_LIST4("ADD", "DROP", "UPDATE", "SET SCHEMA");
1416
1417         /* ALTER FOREIGN */
1418         else if (Matches2("ALTER", "FOREIGN"))
1419                 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
1420
1421         /* ALTER FOREIGN DATA WRAPPER <name> */
1422         else if (Matches5("ALTER", "FOREIGN", "DATA", "WRAPPER", MatchAny))
1423                 COMPLETE_WITH_LIST5("HANDLER", "VALIDATOR", "OPTIONS", "OWNER TO", "RENAME TO");
1424
1425         /* ALTER FOREIGN TABLE <name> */
1426         else if (Matches4("ALTER", "FOREIGN", "TABLE", MatchAny))
1427         {
1428                 static const char *const list_ALTER_FOREIGN_TABLE[] =
1429                 {"ADD", "ALTER", "DISABLE TRIGGER", "DROP", "ENABLE", "INHERIT",
1430                         "NO INHERIT", "OPTIONS", "OWNER TO", "RENAME", "SET",
1431                 "VALIDATE CONSTRAINT", NULL};
1432
1433                 COMPLETE_WITH_LIST(list_ALTER_FOREIGN_TABLE);
1434         }
1435
1436         /* ALTER INDEX */
1437         else if (Matches2("ALTER", "INDEX"))
1438                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
1439                                                                    "UNION SELECT 'ALL IN TABLESPACE'");
1440         /* ALTER INDEX <name> */
1441         else if (Matches3("ALTER", "INDEX", MatchAny))
1442                 COMPLETE_WITH_LIST4("OWNER TO", "RENAME TO", "SET", "RESET");
1443         /* ALTER INDEX <name> SET */
1444         else if (Matches4("ALTER", "INDEX", MatchAny, "SET"))
1445                 COMPLETE_WITH_LIST2("(", "TABLESPACE");
1446         /* ALTER INDEX <name> RESET */
1447         else if (Matches4("ALTER", "INDEX", MatchAny, "RESET"))
1448                 COMPLETE_WITH_CONST("(");
1449         /* ALTER INDEX <foo> SET|RESET ( */
1450         else if (Matches5("ALTER", "INDEX", MatchAny, "RESET", "("))
1451                 COMPLETE_WITH_LIST3("fillfactor", "fastupdate",
1452                                                         "gin_pending_list_limit");
1453         else if (Matches5("ALTER", "INDEX", MatchAny, "SET", "("))
1454                 COMPLETE_WITH_LIST3("fillfactor =", "fastupdate =",
1455                                                         "gin_pending_list_limit =");
1456
1457         /* ALTER LANGUAGE <name> */
1458         else if (Matches3("ALTER", "LANGUAGE", MatchAny))
1459                 COMPLETE_WITH_LIST2("OWNER_TO", "RENAME TO");
1460
1461         /* ALTER LARGE OBJECT <oid> */
1462         else if (Matches4("ALTER", "LARGE", "OBJECT", MatchAny))
1463                 COMPLETE_WITH_CONST("OWNER TO");
1464
1465         /* ALTER MATERIALIZED VIEW */
1466         else if (Matches3("ALTER", "MATERIALIZED", "VIEW"))
1467                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews,
1468                                                                    "UNION SELECT 'ALL IN TABLESPACE'");
1469
1470         /* ALTER USER,ROLE <name> */
1471         else if (Matches3("ALTER", "USER|ROLE", MatchAny) &&
1472                          !TailMatches2("USER", "MAPPING"))
1473         {
1474                 static const char *const list_ALTERUSER[] =
1475                 {"BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
1476                         "ENCRYPTED", "INHERIT", "LOGIN", "NOBYPASSRLS",
1477                         "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
1478                         "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD", "RENAME TO",
1479                         "REPLICATION", "RESET", "SET", "SUPERUSER", "UNENCRYPTED",
1480                 "VALID UNTIL", "WITH", NULL};
1481
1482                 COMPLETE_WITH_LIST(list_ALTERUSER);
1483         }
1484
1485         /* ALTER USER,ROLE <name> WITH */
1486         else if (Matches4("ALTER", "USER|ROLE", MatchAny, "WITH"))
1487         {
1488                 /* Similar to the above, but don't complete "WITH" again. */
1489                 static const char *const list_ALTERUSER_WITH[] =
1490                 {"BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
1491                         "ENCRYPTED", "INHERIT", "LOGIN", "NOBYPASSRLS",
1492                         "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
1493                         "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD", "RENAME TO",
1494                         "REPLICATION", "RESET", "SET", "SUPERUSER", "UNENCRYPTED",
1495                 "VALID UNTIL", NULL};
1496
1497                 COMPLETE_WITH_LIST(list_ALTERUSER_WITH);
1498         }
1499
1500         /* complete ALTER USER,ROLE <name> ENCRYPTED,UNENCRYPTED with PASSWORD */
1501         else if (Matches4("ALTER", "USER|ROLE", MatchAny, "ENCRYPTED|UNENCRYPTED"))
1502                 COMPLETE_WITH_CONST("PASSWORD");
1503         /* ALTER DEFAULT PRIVILEGES */
1504         else if (Matches3("ALTER", "DEFAULT", "PRIVILEGES"))
1505                 COMPLETE_WITH_LIST3("FOR ROLE", "FOR USER", "IN SCHEMA");
1506         /* ALTER DEFAULT PRIVILEGES FOR */
1507         else if (Matches4("ALTER", "DEFAULT", "PRIVILEGES", "FOR"))
1508                 COMPLETE_WITH_LIST2("ROLE", "USER");
1509         /* ALTER DEFAULT PRIVILEGES { FOR ROLE ... | IN SCHEMA ... } */
1510         else if (Matches6("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER", MatchAny) ||
1511                 Matches6("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA", MatchAny))
1512                 COMPLETE_WITH_LIST2("GRANT", "REVOKE");
1513         /* ALTER DOMAIN <name> */
1514         else if (Matches3("ALTER", "DOMAIN", MatchAny))
1515                 COMPLETE_WITH_LIST6("ADD", "DROP", "OWNER TO", "RENAME", "SET",
1516                                                         "VALIDATE CONSTRAINT");
1517         /* ALTER DOMAIN <sth> DROP */
1518         else if (Matches4("ALTER", "DOMAIN", MatchAny, "DROP"))
1519                 COMPLETE_WITH_LIST3("CONSTRAINT", "DEFAULT", "NOT NULL");
1520         /* ALTER DOMAIN <sth> DROP|RENAME|VALIDATE CONSTRAINT */
1521         else if (Matches5("ALTER", "DOMAIN", MatchAny, "DROP|RENAME|VALIDATE", "CONSTRAINT"))
1522         {
1523                 completion_info_charp = prev3_wd;
1524                 COMPLETE_WITH_QUERY(Query_for_constraint_of_type);
1525         }
1526         /* ALTER DOMAIN <sth> RENAME */
1527         else if (Matches4("ALTER", "DOMAIN", MatchAny, "RENAME"))
1528                 COMPLETE_WITH_LIST2("CONSTRAINT", "TO");
1529         /* ALTER DOMAIN <sth> RENAME CONSTRAINT <sth> */
1530         else if (Matches6("ALTER", "DOMAIN", MatchAny, "RENAME", "CONSTRAINT", MatchAny))
1531                 COMPLETE_WITH_CONST("TO");
1532
1533         /* ALTER DOMAIN <sth> SET */
1534         else if (Matches4("ALTER", "DOMAIN", MatchAny, "SET"))
1535                 COMPLETE_WITH_LIST3("DEFAULT", "NOT NULL", "SCHEMA");
1536         /* ALTER SEQUENCE <name> */
1537         else if (Matches3("ALTER", "SEQUENCE", MatchAny))
1538         {
1539                 static const char *const list_ALTERSEQUENCE[] =
1540                 {"INCREMENT", "MINVALUE", "MAXVALUE", "RESTART", "NO", "CACHE", "CYCLE",
1541                 "SET SCHEMA", "OWNED BY", "OWNER TO", "RENAME TO", NULL};
1542
1543                 COMPLETE_WITH_LIST(list_ALTERSEQUENCE);
1544         }
1545         /* ALTER SEQUENCE <name> NO */
1546         else if (Matches4("ALTER", "SEQUENCE", MatchAny, "NO"))
1547                 COMPLETE_WITH_LIST3("MINVALUE", "MAXVALUE", "CYCLE");
1548         /* ALTER SERVER <name> */
1549         else if (Matches3("ALTER", "SERVER", MatchAny))
1550                 COMPLETE_WITH_LIST4("VERSION", "OPTIONS", "OWNER TO", "RENAME TO");
1551         /* ALTER SERVER <name> VERSION <version> */
1552         else if (Matches5("ALTER", "SERVER", MatchAny, "VERSION", MatchAny))
1553                 COMPLETE_WITH_CONST("OPTIONS");
1554         /* ALTER SYSTEM SET, RESET, RESET ALL */
1555         else if (Matches2("ALTER", "SYSTEM"))
1556                 COMPLETE_WITH_LIST2("SET", "RESET");
1557         /* ALTER SYSTEM SET|RESET <name> */
1558         else if (Matches3("ALTER", "SYSTEM", "SET|RESET"))
1559                 COMPLETE_WITH_QUERY(Query_for_list_of_alter_system_set_vars);
1560         /* ALTER VIEW <name> */
1561         else if (Matches3("ALTER", "VIEW", MatchAny))
1562                 COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO",
1563                                                         "SET SCHEMA");
1564         /* ALTER MATERIALIZED VIEW <name> */
1565         else if (Matches4("ALTER", "MATERIALIZED", "VIEW", MatchAny))
1566                 COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO",
1567                                                         "SET SCHEMA");
1568
1569         /* ALTER POLICY <name> */
1570         else if (Matches2("ALTER", "POLICY"))
1571                 COMPLETE_WITH_QUERY(Query_for_list_of_policies);
1572         /* ALTER POLICY <name> ON */
1573         else if (Matches3("ALTER", "POLICY", MatchAny))
1574                 COMPLETE_WITH_CONST("ON");
1575         /* ALTER POLICY <name> ON <table> */
1576         else if (Matches4("ALTER", "POLICY", MatchAny, "ON"))
1577         {
1578                 completion_info_charp = prev2_wd;
1579                 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_policy);
1580         }
1581         /* ALTER POLICY <name> ON <table> - show options */
1582         else if (Matches5("ALTER", "POLICY", MatchAny, "ON", MatchAny))
1583                 COMPLETE_WITH_LIST4("RENAME TO", "TO", "USING (", "WITH CHECK (");
1584         /* ALTER POLICY <name> ON <table> TO <role> */
1585         else if (Matches6("ALTER", "POLICY", MatchAny, "ON", MatchAny, "TO"))
1586                 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
1587         /* ALTER POLICY <name> ON <table> USING ( */
1588         else if (Matches6("ALTER", "POLICY", MatchAny, "ON", MatchAny, "USING"))
1589                 COMPLETE_WITH_CONST("(");
1590         /* ALTER POLICY <name> ON <table> WITH CHECK ( */
1591         else if (Matches7("ALTER", "POLICY", MatchAny, "ON", MatchAny, "WITH", "CHECK"))
1592                 COMPLETE_WITH_CONST("(");
1593
1594         /* ALTER RULE <name>, add ON */
1595         else if (Matches3("ALTER", "RULE", MatchAny))
1596                 COMPLETE_WITH_CONST("ON");
1597
1598         /* If we have ALTER RULE <name> ON, then add the correct tablename */
1599         else if (Matches4("ALTER", "RULE", MatchAny, "ON"))
1600         {
1601                 completion_info_charp = prev2_wd;
1602                 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule);
1603         }
1604
1605         /* ALTER RULE <name> ON <name> */
1606         else if (Matches5("ALTER", "RULE", MatchAny, "ON", MatchAny))
1607                 COMPLETE_WITH_CONST("RENAME TO");
1608
1609         /* ALTER TRIGGER <name>, add ON */
1610         else if (Matches3("ALTER", "TRIGGER", MatchAny))
1611                 COMPLETE_WITH_CONST("ON");
1612
1613         else if (Matches4("ALTER", "TRIGGER", MatchAny, MatchAny))
1614         {
1615                 completion_info_charp = prev2_wd;
1616                 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger);
1617         }
1618
1619         /*
1620          * If we have ALTER TRIGGER <sth> ON, then add the correct tablename
1621          */
1622         else if (Matches4("ALTER", "TRIGGER", MatchAny, "ON"))
1623                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
1624
1625         /* ALTER TRIGGER <name> ON <name> */
1626         else if (Matches5("ALTER", "TRIGGER", MatchAny, "ON", MatchAny))
1627                 COMPLETE_WITH_CONST("RENAME TO");
1628
1629         /*
1630          * If we detect ALTER TABLE <name>, suggest sub commands
1631          */
1632         else if (Matches3("ALTER", "TABLE", MatchAny))
1633         {
1634                 static const char *const list_ALTER2[] =
1635                 {"ADD", "ALTER", "CLUSTER ON", "DISABLE", "DROP", "ENABLE", "INHERIT",
1636                         "NO INHERIT", "RENAME", "RESET", "OWNER TO", "SET",
1637                 "VALIDATE CONSTRAINT", "REPLICA IDENTITY", NULL};
1638
1639                 COMPLETE_WITH_LIST(list_ALTER2);
1640         }
1641         /* ALTER TABLE xxx ENABLE */
1642         else if (Matches4("ALTER", "TABLE", MatchAny, "ENABLE"))
1643                 COMPLETE_WITH_LIST5("ALWAYS", "REPLICA", "ROW LEVEL SECURITY", "RULE",
1644                                                         "TRIGGER");
1645         else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "REPLICA|ALWAYS"))
1646                 COMPLETE_WITH_LIST2("RULE", "TRIGGER");
1647         else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "RULE"))
1648         {
1649                 completion_info_charp = prev3_wd;
1650                 COMPLETE_WITH_QUERY(Query_for_rule_of_table);
1651         }
1652         else if (Matches6("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "RULE"))
1653         {
1654                 completion_info_charp = prev4_wd;
1655                 COMPLETE_WITH_QUERY(Query_for_rule_of_table);
1656         }
1657         else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "TRIGGER"))
1658         {
1659                 completion_info_charp = prev3_wd;
1660                 COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
1661         }
1662         else if (Matches6("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "TRIGGER"))
1663         {
1664                 completion_info_charp = prev4_wd;
1665                 COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
1666         }
1667         /* ALTER TABLE xxx INHERIT */
1668         else if (Matches4("ALTER", "TABLE", MatchAny, "INHERIT"))
1669                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
1670         /* ALTER TABLE xxx NO INHERIT */
1671         else if (Matches5("ALTER", "TABLE", MatchAny, "NO", "INHERIT"))
1672                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
1673         /* ALTER TABLE xxx DISABLE */
1674         else if (Matches4("ALTER", "TABLE", MatchAny, "DISABLE"))
1675                 COMPLETE_WITH_LIST3("ROW LEVEL SECURITY", "RULE", "TRIGGER");
1676         else if (Matches5("ALTER", "TABLE", MatchAny, "DISABLE", "RULE"))
1677         {
1678                 completion_info_charp = prev3_wd;
1679                 COMPLETE_WITH_QUERY(Query_for_rule_of_table);
1680         }
1681         else if (Matches5("ALTER", "TABLE", MatchAny, "DISABLE", "TRIGGER"))
1682         {
1683                 completion_info_charp = prev3_wd;
1684                 COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
1685         }
1686
1687         /* ALTER TABLE xxx ALTER */
1688         else if (Matches4("ALTER", "TABLE", MatchAny, "ALTER"))
1689                 COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT'");
1690
1691         /* ALTER TABLE xxx RENAME */
1692         else if (Matches4("ALTER", "TABLE", MatchAny, "RENAME"))
1693                 COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT' UNION SELECT 'TO'");
1694         else if (Matches5("ALTER", "TABLE", MatchAny, "ALTER|RENAME", "COLUMN"))
1695                 COMPLETE_WITH_ATTR(prev3_wd, "");
1696
1697         /* ALTER TABLE xxx RENAME yyy */
1698         else if (Matches5("ALTER", "TABLE", MatchAny, "RENAME", MatchAnyExcept("CONSTRAINT|TO")))
1699                 COMPLETE_WITH_CONST("TO");
1700
1701         /* ALTER TABLE xxx RENAME COLUMN/CONSTRAINT yyy */
1702         else if (Matches6("ALTER", "TABLE", MatchAny, "RENAME", "COLUMN|CONSTRAINT", MatchAnyExcept("TO")))
1703                 COMPLETE_WITH_CONST("TO");
1704
1705         /* If we have ALTER TABLE <sth> DROP, provide COLUMN or CONSTRAINT */
1706         else if (Matches4("ALTER", "TABLE", MatchAny, "DROP"))
1707                 COMPLETE_WITH_LIST2("COLUMN", "CONSTRAINT");
1708         /* If we have ALTER TABLE <sth> DROP COLUMN, provide list of columns */
1709         else if (Matches5("ALTER", "TABLE", MatchAny, "DROP", "COLUMN"))
1710                 COMPLETE_WITH_ATTR(prev3_wd, "");
1711
1712         /*
1713          * If we have ALTER TABLE <sth> ALTER|DROP|RENAME|VALIDATE CONSTRAINT,
1714          * provide list of constraints
1715          */
1716         else if (Matches5("ALTER", "TABLE", MatchAny, "ALTER|DROP|RENAME|VALIDATE", "CONSTRAINT"))
1717         {
1718                 completion_info_charp = prev3_wd;
1719                 COMPLETE_WITH_QUERY(Query_for_constraint_of_table);
1720         }
1721         /* ALTER TABLE ALTER [COLUMN] <foo> */
1722         else if (Matches6("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny) ||
1723                          Matches5("ALTER", "TABLE", MatchAny, "ALTER", MatchAny))
1724                 COMPLETE_WITH_LIST4("TYPE", "SET", "RESET", "DROP");
1725         /* ALTER TABLE ALTER [COLUMN] <foo> SET */
1726         else if (Matches7("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET") ||
1727                          Matches6("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET"))
1728                 COMPLETE_WITH_LIST5("(", "DEFAULT", "NOT NULL", "STATISTICS", "STORAGE");
1729         /* ALTER TABLE ALTER [COLUMN] <foo> SET ( */
1730         else if (Matches8("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "(") ||
1731                  Matches7("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "("))
1732                 COMPLETE_WITH_LIST2("n_distinct", "n_distinct_inherited");
1733         /* ALTER TABLE ALTER [COLUMN] <foo> SET STORAGE */
1734         else if (Matches8("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "STORAGE") ||
1735         Matches7("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "STORAGE"))
1736                 COMPLETE_WITH_LIST4("PLAIN", "EXTERNAL", "EXTENDED", "MAIN");
1737         /* ALTER TABLE ALTER [COLUMN] <foo> DROP */
1738         else if (Matches7("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "DROP") ||
1739                          Matches8("ALTER", "TABLE", MatchAny, "TABLE", MatchAny, "ALTER", MatchAny, "DROP"))
1740                 COMPLETE_WITH_LIST2("DEFAULT", "NOT NULL");
1741         else if (Matches4("ALTER", "TABLE", MatchAny, "CLUSTER"))
1742                 COMPLETE_WITH_CONST("ON");
1743         else if (Matches5("ALTER", "TABLE", MatchAny, "CLUSTER", "ON"))
1744         {
1745                 completion_info_charp = prev3_wd;
1746                 COMPLETE_WITH_QUERY(Query_for_index_of_table);
1747         }
1748         /* If we have ALTER TABLE <sth> SET, provide list of attributes and '(' */
1749         else if (Matches4("ALTER", "TABLE", MatchAny, "SET"))
1750                 COMPLETE_WITH_LIST7("(", "LOGGED", "SCHEMA", "TABLESPACE", "UNLOGGED",
1751                                                         "WITH", "WITHOUT");
1752
1753         /*
1754          * If we have ALTER TABLE <sth> SET TABLESPACE provide a list of
1755          * tablespaces
1756          */
1757         else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "TABLESPACE"))
1758                 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
1759         /* If we have ALTER TABLE <sth> SET WITH provide OIDS */
1760         else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "WITH"))
1761                 COMPLETE_WITH_CONST("OIDS");
1762         /* If we have ALTER TABLE <sth> SET WITHOUT provide CLUSTER or OIDS */
1763         else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "WITHOUT"))
1764                 COMPLETE_WITH_LIST2("CLUSTER", "OIDS");
1765         /* ALTER TABLE <foo> RESET */
1766         else if (Matches4("ALTER", "TABLE", MatchAny, "RESET"))
1767                 COMPLETE_WITH_CONST("(");
1768         /* ALTER TABLE <foo> SET|RESET ( */
1769         else if (Matches5("ALTER", "TABLE", MatchAny, "SET|RESET", "("))
1770         {
1771                 static const char *const list_TABLEOPTIONS[] =
1772                 {
1773                         "autovacuum_analyze_scale_factor",
1774                         "autovacuum_analyze_threshold",
1775                         "autovacuum_enabled",
1776                         "autovacuum_freeze_max_age",
1777                         "autovacuum_freeze_min_age",
1778                         "autovacuum_freeze_table_age",
1779                         "autovacuum_multixact_freeze_max_age",
1780                         "autovacuum_multixact_freeze_min_age",
1781                         "autovacuum_multixact_freeze_table_age",
1782                         "autovacuum_vacuum_cost_delay",
1783                         "autovacuum_vacuum_cost_limit",
1784                         "autovacuum_vacuum_scale_factor",
1785                         "autovacuum_vacuum_threshold",
1786                         "fillfactor",
1787                         "parallel_workers",
1788                         "log_autovacuum_min_duration",
1789                         "toast.autovacuum_enabled",
1790                         "toast.autovacuum_freeze_max_age",
1791                         "toast.autovacuum_freeze_min_age",
1792                         "toast.autovacuum_freeze_table_age",
1793                         "toast.autovacuum_multixact_freeze_max_age",
1794                         "toast.autovacuum_multixact_freeze_min_age",
1795                         "toast.autovacuum_multixact_freeze_table_age",
1796                         "toast.autovacuum_vacuum_cost_delay",
1797                         "toast.autovacuum_vacuum_cost_limit",
1798                         "toast.autovacuum_vacuum_scale_factor",
1799                         "toast.autovacuum_vacuum_threshold",
1800                         "toast.log_autovacuum_min_duration",
1801                         "user_catalog_table",
1802                         NULL
1803                 };
1804
1805                 COMPLETE_WITH_LIST(list_TABLEOPTIONS);
1806         }
1807         else if (Matches7("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING", "INDEX"))
1808         {
1809                 completion_info_charp = prev5_wd;
1810                 COMPLETE_WITH_QUERY(Query_for_index_of_table);
1811         }
1812         else if (Matches6("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING"))
1813                 COMPLETE_WITH_CONST("INDEX");
1814         else if (Matches5("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY"))
1815                 COMPLETE_WITH_LIST4("FULL", "NOTHING", "DEFAULT", "USING");
1816         else if (Matches4("ALTER", "TABLE", MatchAny, "REPLICA"))
1817                 COMPLETE_WITH_CONST("IDENTITY");
1818
1819         /* ALTER TABLESPACE <foo> with RENAME TO, OWNER TO, SET, RESET */
1820         else if (Matches3("ALTER", "TABLESPACE", MatchAny))
1821                 COMPLETE_WITH_LIST4("RENAME TO", "OWNER TO", "SET", "RESET");
1822         /* ALTER TABLESPACE <foo> SET|RESET */
1823         else if (Matches4("ALTER", "TABLESPACE", MatchAny, "SET|RESET"))
1824                 COMPLETE_WITH_CONST("(");
1825         /* ALTER TABLESPACE <foo> SET|RESET ( */
1826         else if (Matches5("ALTER", "TABLESPACE", MatchAny, "SET|RESET", "("))
1827                 COMPLETE_WITH_LIST3("seq_page_cost", "random_page_cost",
1828                                                         "effective_io_concurrency");
1829
1830         /* ALTER TEXT SEARCH */
1831         else if (Matches3("ALTER", "TEXT", "SEARCH"))
1832                 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
1833         else if (Matches5("ALTER", "TEXT", "SEARCH", "TEMPLATE|PARSER", MatchAny))
1834                 COMPLETE_WITH_LIST2("RENAME TO", "SET SCHEMA");
1835         else if (Matches5("ALTER", "TEXT", "SEARCH", "DICTIONARY", MatchAny))
1836                 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1837         else if (Matches5("ALTER", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
1838                 COMPLETE_WITH_LIST6("ADD MAPPING FOR", "ALTER MAPPING",
1839                                                         "DROP MAPPING FOR",
1840                                                         "OWNER TO", "RENAME TO", "SET SCHEMA");
1841
1842         /* complete ALTER TYPE <foo> with actions */
1843         else if (Matches3("ALTER", "TYPE", MatchAny))
1844                 COMPLETE_WITH_LIST7("ADD ATTRIBUTE", "ADD VALUE", "ALTER ATTRIBUTE",
1845                                                         "DROP ATTRIBUTE",
1846                                                         "OWNER TO", "RENAME", "SET SCHEMA");
1847         /* complete ALTER TYPE <foo> ADD with actions */
1848         else if (Matches4("ALTER", "TYPE", MatchAny, "ADD"))
1849                 COMPLETE_WITH_LIST2("ATTRIBUTE", "VALUE");
1850         /* ALTER TYPE <foo> RENAME      */
1851         else if (Matches4("ALTER", "TYPE", MatchAny, "RENAME"))
1852                 COMPLETE_WITH_LIST2("ATTRIBUTE", "TO");
1853         /* ALTER TYPE xxx RENAME ATTRIBUTE yyy */
1854         else if (Matches6("ALTER", "TYPE", MatchAny, "RENAME", "ATTRIBUTE", MatchAny))
1855                 COMPLETE_WITH_CONST("TO");
1856
1857         /*
1858          * If we have ALTER TYPE <sth> ALTER/DROP/RENAME ATTRIBUTE, provide list
1859          * of attributes
1860          */
1861         else if (Matches5("ALTER", "TYPE", MatchAny, "ALTER|DROP|RENAME", "ATTRIBUTE"))
1862                 COMPLETE_WITH_ATTR(prev3_wd, "");
1863         /* ALTER TYPE ALTER ATTRIBUTE <foo> */
1864         else if (Matches6("ALTER", "TYPE", MatchAny, "ALTER", "ATTRIBUTE", MatchAny))
1865                 COMPLETE_WITH_CONST("TYPE");
1866         /* complete ALTER GROUP <foo> */
1867         else if (Matches3("ALTER", "GROUP", MatchAny))
1868                 COMPLETE_WITH_LIST3("ADD USER", "DROP USER", "RENAME TO");
1869         /* complete ALTER GROUP <foo> ADD|DROP with USER */
1870         else if (Matches4("ALTER", "GROUP", MatchAny, "ADD|DROP"))
1871                 COMPLETE_WITH_CONST("USER");
1872         /* complete ALTER GROUP <foo> ADD|DROP USER with a user name */
1873         else if (Matches5("ALTER", "GROUP", MatchAny, "ADD|DROP", "USER"))
1874                 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
1875
1876 /* BEGIN, END, ABORT */
1877         else if (Matches1("BEGIN|END|ABORT"))
1878                 COMPLETE_WITH_LIST2("WORK", "TRANSACTION");
1879 /* COMMIT */
1880         else if (Matches1("COMMIT"))
1881                 COMPLETE_WITH_LIST3("WORK", "TRANSACTION", "PREPARED");
1882 /* RELEASE SAVEPOINT */
1883         else if (Matches1("RELEASE"))
1884                 COMPLETE_WITH_CONST("SAVEPOINT");
1885 /* ROLLBACK */
1886         else if (Matches1("ROLLBACK"))
1887                 COMPLETE_WITH_LIST4("WORK", "TRANSACTION", "TO SAVEPOINT", "PREPARED");
1888 /* CLUSTER */
1889         else if (Matches1("CLUSTER"))
1890                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, "UNION SELECT 'VERBOSE'");
1891         else if (Matches2("CLUSTER", "VERBOSE"))
1892                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
1893         /* If we have CLUSTER <sth>, then add "USING" */
1894         else if (Matches2("CLUSTER", MatchAnyExcept("VERBOSE|ON")))
1895                 COMPLETE_WITH_CONST("USING");
1896         /* If we have CLUSTER VERBOSE <sth>, then add "USING" */
1897         else if (Matches3("CLUSTER", "VERBOSE", MatchAny))
1898                 COMPLETE_WITH_CONST("USING");
1899         /* If we have CLUSTER <sth> USING, then add the index as well */
1900         else if (Matches3("CLUSTER", MatchAny, "USING") ||
1901                          Matches4("CLUSTER", "VERBOSE", MatchAny, "USING"))
1902         {
1903                 completion_info_charp = prev2_wd;
1904                 COMPLETE_WITH_QUERY(Query_for_index_of_table);
1905         }
1906
1907 /* COMMENT */
1908         else if (Matches1("COMMENT"))
1909                 COMPLETE_WITH_CONST("ON");
1910         else if (Matches2("COMMENT", "ON"))
1911         {
1912                 static const char *const list_COMMENT[] =
1913                 {"ACCESS METHOD", "CAST", "COLLATION", "CONVERSION", "DATABASE",
1914                         "EVENT TRIGGER", "EXTENSION",
1915                         "FOREIGN DATA WRAPPER", "FOREIGN TABLE",
1916                         "SERVER", "INDEX", "LANGUAGE", "POLICY", "RULE", "SCHEMA", "SEQUENCE",
1917                         "TABLE", "TYPE", "VIEW", "MATERIALIZED VIEW", "COLUMN", "AGGREGATE", "FUNCTION",
1918                         "OPERATOR", "TRIGGER", "CONSTRAINT", "DOMAIN", "LARGE OBJECT",
1919                 "TABLESPACE", "TEXT SEARCH", "ROLE", NULL};
1920
1921                 COMPLETE_WITH_LIST(list_COMMENT);
1922         }
1923         else if (Matches4("COMMENT", "ON", "ACCESS", "METHOD"))
1924                 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
1925         else if (Matches3("COMMENT", "ON", "FOREIGN"))
1926                 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
1927         else if (Matches4("COMMENT", "ON", "TEXT", "SEARCH"))
1928                 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
1929         else if (Matches3("COMMENT", "ON", "CONSTRAINT"))
1930                 COMPLETE_WITH_QUERY(Query_for_all_table_constraints);
1931         else if (Matches4("COMMENT", "ON", "CONSTRAINT", MatchAny))
1932                 COMPLETE_WITH_CONST("ON");
1933         else if (Matches5("COMMENT", "ON", "CONSTRAINT", MatchAny, "ON"))
1934         {
1935                 completion_info_charp = prev2_wd;
1936                 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_constraint);
1937         }
1938         else if (Matches4("COMMENT", "ON", "MATERIALIZED", "VIEW"))
1939                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
1940         else if (Matches4("COMMENT", "ON", "EVENT", "TRIGGER"))
1941                 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
1942         else if (Matches4("COMMENT", "ON", MatchAny, MatchAnyExcept("IS")) ||
1943                 Matches5("COMMENT", "ON", MatchAny, MatchAny, MatchAnyExcept("IS")) ||
1944                          Matches6("COMMENT", "ON", MatchAny, MatchAny, MatchAny, MatchAnyExcept("IS")))
1945                 COMPLETE_WITH_CONST("IS");
1946
1947 /* COPY */
1948
1949         /*
1950          * If we have COPY, offer list of tables or "(" (Also cover the analogous
1951          * backslash command).
1952          */
1953         else if (Matches1("COPY|\\copy"))
1954                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
1955                                                                    " UNION ALL SELECT '('");
1956         /* If we have COPY BINARY, complete with list of tables */
1957         else if (Matches2("COPY", "BINARY"))
1958                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
1959         /* If we have COPY (, complete it with legal commands */
1960         else if (Matches2("COPY|\\copy", "("))
1961                 COMPLETE_WITH_LIST7("SELECT", "TABLE", "VALUES", "INSERT", "UPDATE", "DELETE", "WITH");
1962         /* If we have COPY [BINARY] <sth>, complete it with "TO" or "FROM" */
1963         else if (Matches2("COPY|\\copy", MatchAny) ||
1964                          Matches3("COPY", "BINARY", MatchAny))
1965                 COMPLETE_WITH_LIST2("FROM", "TO");
1966         /* If we have COPY [BINARY] <sth> FROM|TO, complete with filename */
1967         else if (Matches3("COPY|\\copy", MatchAny, "FROM|TO") ||
1968                          Matches4("COPY", "BINARY", MatchAny, "FROM|TO"))
1969         {
1970                 completion_charp = "";
1971                 matches = completion_matches(text, complete_from_files);
1972         }
1973
1974         /* Handle COPY [BINARY] <sth> FROM|TO filename */
1975         else if (Matches4("COPY|\\copy", MatchAny, "FROM|TO", MatchAny) ||
1976                          Matches5("COPY", "BINARY", MatchAny, "FROM|TO", MatchAny))
1977                 COMPLETE_WITH_LIST6("BINARY", "OIDS", "DELIMITER", "NULL", "CSV",
1978                                                         "ENCODING");
1979
1980         /* Handle COPY [BINARY] <sth> FROM|TO filename CSV */
1981         else if (Matches5("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "CSV") ||
1982                          Matches6("COPY", "BINARY", MatchAny, "FROM|TO", MatchAny, "CSV"))
1983                 COMPLETE_WITH_LIST5("HEADER", "QUOTE", "ESCAPE", "FORCE QUOTE",
1984                                                         "FORCE NOT NULL");
1985
1986         /* CREATE ACCESS METHOD */
1987         /* Complete "CREATE ACCESS METHOD <name>" */
1988         else if (Matches4("CREATE", "ACCESS", "METHOD", MatchAny))
1989                 COMPLETE_WITH_CONST("TYPE");
1990         /* Complete "CREATE ACCESS METHOD <name> TYPE" */
1991         else if (Matches5("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE"))
1992                 COMPLETE_WITH_CONST("INDEX");
1993         /* Complete "CREATE ACCESS METHOD <name> TYPE <type>" */
1994         else if (Matches6("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE", MatchAny))
1995                 COMPLETE_WITH_CONST("HANDLER");
1996
1997         /* CREATE DATABASE */
1998         else if (Matches3("CREATE", "DATABASE", MatchAny))
1999                 COMPLETE_WITH_LIST9("OWNER", "TEMPLATE", "ENCODING", "TABLESPACE",
2000                                                         "IS_TEMPLATE",
2001                                                         "ALLOW_CONNECTIONS", "CONNECTION LIMIT",
2002                                                         "LC_COLLATE", "LC_CTYPE");
2003
2004         else if (Matches4("CREATE", "DATABASE", MatchAny, "TEMPLATE"))
2005                 COMPLETE_WITH_QUERY(Query_for_list_of_template_databases);
2006
2007         /* CREATE EXTENSION */
2008         /* Complete with available extensions rather than installed ones. */
2009         else if (Matches2("CREATE", "EXTENSION"))
2010                 COMPLETE_WITH_QUERY(Query_for_list_of_available_extensions);
2011         /* CREATE EXTENSION <name> */
2012         else if (Matches3("CREATE", "EXTENSION", MatchAny))
2013                 COMPLETE_WITH_LIST3("WITH SCHEMA", "CASCADE", "VERSION");
2014         /* CREATE EXTENSION <name> VERSION */
2015         else if (Matches4("CREATE", "EXTENSION", MatchAny, "VERSION"))
2016         {
2017                 completion_info_charp = prev2_wd;
2018                 COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions);
2019         }
2020
2021         /* CREATE FOREIGN */
2022         else if (Matches2("CREATE", "FOREIGN"))
2023                 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
2024
2025         /* CREATE FOREIGN DATA WRAPPER */
2026         else if (Matches5("CREATE", "FOREIGN", "DATA", "WRAPPER", MatchAny))
2027                 COMPLETE_WITH_LIST3("HANDLER", "VALIDATOR", "OPTIONS");
2028
2029         /* CREATE INDEX --- is allowed inside CREATE SCHEMA, so use TailMatches */
2030         /* First off we complete CREATE UNIQUE with "INDEX" */
2031         else if (TailMatches2("CREATE", "UNIQUE"))
2032                 COMPLETE_WITH_CONST("INDEX");
2033
2034         /*
2035          * If we have CREATE|UNIQUE INDEX, then add "ON", "CONCURRENTLY", and
2036          * existing indexes
2037          */
2038         else if (TailMatches2("CREATE|UNIQUE", "INDEX"))
2039                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
2040                                                                    " UNION SELECT 'ON'"
2041                                                                    " UNION SELECT 'CONCURRENTLY'");
2042         /* Complete ... INDEX|CONCURRENTLY [<name>] ON with a list of tables  */
2043         else if (TailMatches3("INDEX|CONCURRENTLY", MatchAny, "ON") ||
2044                          TailMatches2("INDEX|CONCURRENTLY", "ON"))
2045                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
2046
2047         /*
2048          * Complete CREATE|UNIQUE INDEX CONCURRENTLY with "ON" and existing
2049          * indexes
2050          */
2051         else if (TailMatches3("CREATE|UNIQUE", "INDEX", "CONCURRENTLY"))
2052                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
2053                                                                    " UNION SELECT 'ON'");
2054         /* Complete CREATE|UNIQUE INDEX [CONCURRENTLY] <sth> with "ON" */
2055         else if (TailMatches3("CREATE|UNIQUE", "INDEX", MatchAny) ||
2056                          TailMatches4("CREATE|UNIQUE", "INDEX", "CONCURRENTLY", MatchAny))
2057                 COMPLETE_WITH_CONST("ON");
2058
2059         /*
2060          * Complete INDEX <name> ON <table> with a list of table columns (which
2061          * should really be in parens)
2062          */
2063         else if (TailMatches4("INDEX", MatchAny, "ON", MatchAny) ||
2064                          TailMatches3("INDEX|CONCURRENTLY", "ON", MatchAny))
2065                 COMPLETE_WITH_LIST2("(", "USING");
2066         else if (TailMatches5("INDEX", MatchAny, "ON", MatchAny, "(") ||
2067                          TailMatches4("INDEX|CONCURRENTLY", "ON", MatchAny, "("))
2068                 COMPLETE_WITH_ATTR(prev2_wd, "");
2069         /* same if you put in USING */
2070         else if (TailMatches5("ON", MatchAny, "USING", MatchAny, "("))
2071                 COMPLETE_WITH_ATTR(prev4_wd, "");
2072         /* Complete USING with an index method */
2073         else if (TailMatches6("INDEX", MatchAny, MatchAny, "ON", MatchAny, "USING") ||
2074                          TailMatches5("INDEX", MatchAny, "ON", MatchAny, "USING") ||
2075                          TailMatches4("INDEX", "ON", MatchAny, "USING"))
2076                 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
2077         else if (TailMatches4("ON", MatchAny, "USING", MatchAny) &&
2078                          !TailMatches6("POLICY", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny) &&
2079                          !TailMatches4("FOR", MatchAny, MatchAny, MatchAny))
2080                 COMPLETE_WITH_CONST("(");
2081
2082         /* CREATE POLICY */
2083         /* Complete "CREATE POLICY <name> ON" */
2084         else if (Matches3("CREATE", "POLICY", MatchAny))
2085                 COMPLETE_WITH_CONST("ON");
2086         /* Complete "CREATE POLICY <name> ON <table>" */
2087         else if (Matches4("CREATE", "POLICY", MatchAny, "ON"))
2088                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2089         /* Complete "CREATE POLICY <name> ON <table> FOR|TO|USING|WITH CHECK" */
2090         else if (Matches5("CREATE", "POLICY", MatchAny, "ON", MatchAny))
2091                 COMPLETE_WITH_LIST4("FOR", "TO", "USING (", "WITH CHECK (");
2092         /* CREATE POLICY <name> ON <table> FOR ALL|SELECT|INSERT|UPDATE|DELETE */
2093         else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR"))
2094                 COMPLETE_WITH_LIST5("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
2095         /* Complete "CREATE POLICY <name> ON <table> FOR INSERT TO|WITH CHECK" */
2096         else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "INSERT"))
2097                 COMPLETE_WITH_LIST2("TO", "WITH CHECK (");
2098         /* Complete "CREATE POLICY <name> ON <table> FOR SELECT|DELETE TO|USING" */
2099         else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "SELECT|DELETE"))
2100                 COMPLETE_WITH_LIST2("TO", "USING (");
2101         /* CREATE POLICY <name> ON <table> FOR ALL|UPDATE TO|USING|WITH CHECK */
2102         else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "ALL|UPDATE"))
2103                 COMPLETE_WITH_LIST3("TO", "USING (", "WITH CHECK (");
2104         /* Complete "CREATE POLICY <name> ON <table> TO <role>" */
2105         else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "TO"))
2106                 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
2107         /* Complete "CREATE POLICY <name> ON <table> USING (" */
2108         else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "USING"))
2109                 COMPLETE_WITH_CONST("(");
2110
2111 /* CREATE RULE */
2112         /* Complete "CREATE RULE <sth>" with "AS ON" */
2113         else if (Matches3("CREATE", "RULE", MatchAny))
2114                 COMPLETE_WITH_CONST("AS ON");
2115         /* Complete "CREATE RULE <sth> AS" with "ON" */
2116         else if (Matches4("CREATE", "RULE", MatchAny, "AS"))
2117                 COMPLETE_WITH_CONST("ON");
2118         /* Complete "CREATE RULE <sth> AS ON" with SELECT|UPDATE|INSERT|DELETE */
2119         else if (Matches5("CREATE", "RULE", MatchAny, "AS", "ON"))
2120                 COMPLETE_WITH_LIST4("SELECT", "UPDATE", "INSERT", "DELETE");
2121         /* Complete "AS ON SELECT|UPDATE|INSERT|DELETE" with a "TO" */
2122         else if (TailMatches3("AS", "ON", "SELECT|UPDATE|INSERT|DELETE"))
2123                 COMPLETE_WITH_CONST("TO");
2124         /* Complete "AS ON <sth> TO" with a table name */
2125         else if (TailMatches4("AS", "ON", "SELECT|UPDATE|INSERT|DELETE", "TO"))
2126                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2127
2128 /* CREATE SEQUENCE --- is allowed inside CREATE SCHEMA, so use TailMatches */
2129         else if (TailMatches3("CREATE", "SEQUENCE", MatchAny) ||
2130                          TailMatches4("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny))
2131                 COMPLETE_WITH_LIST8("INCREMENT BY", "MINVALUE", "MAXVALUE", "NO", "CACHE",
2132                                                         "CYCLE", "OWNED BY", "START WITH");
2133         else if (TailMatches4("CREATE", "SEQUENCE", MatchAny, "NO") ||
2134                 TailMatches5("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny, "NO"))
2135                 COMPLETE_WITH_LIST3("MINVALUE", "MAXVALUE", "CYCLE");
2136
2137 /* CREATE SERVER <name> */
2138         else if (Matches3("CREATE", "SERVER", MatchAny))
2139                 COMPLETE_WITH_LIST3("TYPE", "VERSION", "FOREIGN DATA WRAPPER");
2140
2141 /* CREATE TABLE --- is allowed inside CREATE SCHEMA, so use TailMatches */
2142         /* Complete "CREATE TEMP/TEMPORARY" with the possible temp objects */
2143         else if (TailMatches2("CREATE", "TEMP|TEMPORARY"))
2144                 COMPLETE_WITH_LIST3("SEQUENCE", "TABLE", "VIEW");
2145         /* Complete "CREATE UNLOGGED" with TABLE or MATVIEW */
2146         else if (TailMatches2("CREATE", "UNLOGGED"))
2147                 COMPLETE_WITH_LIST2("TABLE", "MATERIALIZED VIEW");
2148
2149 /* CREATE TABLESPACE */
2150         else if (Matches3("CREATE", "TABLESPACE", MatchAny))
2151                 COMPLETE_WITH_LIST2("OWNER", "LOCATION");
2152         /* Complete CREATE TABLESPACE name OWNER name with "LOCATION" */
2153         else if (Matches5("CREATE", "TABLESPACE", MatchAny, "OWNER", MatchAny))
2154                 COMPLETE_WITH_CONST("LOCATION");
2155
2156 /* CREATE TEXT SEARCH */
2157         else if (Matches3("CREATE", "TEXT", "SEARCH"))
2158                 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2159         else if (Matches5("CREATE", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
2160                 COMPLETE_WITH_CONST("(");
2161
2162 /* CREATE TRIGGER --- is allowed inside CREATE SCHEMA, so use TailMatches */
2163         /* complete CREATE TRIGGER <name> with BEFORE,AFTER,INSTEAD OF */
2164         else if (TailMatches3("CREATE", "TRIGGER", MatchAny))
2165                 COMPLETE_WITH_LIST3("BEFORE", "AFTER", "INSTEAD OF");
2166         /* complete CREATE TRIGGER <name> BEFORE,AFTER with an event */
2167         else if (TailMatches4("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER"))
2168                 COMPLETE_WITH_LIST4("INSERT", "DELETE", "UPDATE", "TRUNCATE");
2169         /* complete CREATE TRIGGER <name> INSTEAD OF with an event */
2170         else if (TailMatches5("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF"))
2171                 COMPLETE_WITH_LIST3("INSERT", "DELETE", "UPDATE");
2172         /* complete CREATE TRIGGER <name> BEFORE,AFTER sth with OR,ON */
2173         else if (TailMatches5("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny) ||
2174           TailMatches6("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny))
2175                 COMPLETE_WITH_LIST2("ON", "OR");
2176
2177         /*
2178          * complete CREATE TRIGGER <name> BEFORE,AFTER event ON with a list of
2179          * tables
2180          */
2181         else if (TailMatches6("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny, "ON"))
2182                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2183         /* complete CREATE TRIGGER ... INSTEAD OF event ON with a list of views */
2184         else if (TailMatches7("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny, "ON"))
2185                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
2186         /* complete CREATE TRIGGER ... EXECUTE with PROCEDURE */
2187         else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches1("EXECUTE"))
2188                 COMPLETE_WITH_CONST("PROCEDURE");
2189
2190 /* CREATE ROLE,USER,GROUP <name> */
2191         else if (Matches3("CREATE", "ROLE|GROUP|USER", MatchAny) &&
2192                          !TailMatches2("USER", "MAPPING"))
2193         {
2194                 static const char *const list_CREATEROLE[] =
2195                 {"ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
2196                         "ENCRYPTED", "IN", "INHERIT", "LOGIN", "NOBYPASSRLS",
2197                         "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
2198                         "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
2199                         "REPLICATION", "ROLE", "SUPERUSER", "SYSID", "UNENCRYPTED",
2200                 "VALID UNTIL", "WITH", NULL};
2201
2202                 COMPLETE_WITH_LIST(list_CREATEROLE);
2203         }
2204
2205 /* CREATE ROLE,USER,GROUP <name> WITH */
2206         else if (Matches4("CREATE", "ROLE|GROUP|USER", MatchAny, "WITH"))
2207         {
2208                 /* Similar to the above, but don't complete "WITH" again. */
2209                 static const char *const list_CREATEROLE_WITH[] =
2210                 {"ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
2211                         "ENCRYPTED", "IN", "INHERIT", "LOGIN", "NOBYPASSRLS",
2212                         "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
2213                         "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
2214                         "REPLICATION", "ROLE", "SUPERUSER", "SYSID", "UNENCRYPTED",
2215                 "VALID UNTIL", NULL};
2216
2217                 COMPLETE_WITH_LIST(list_CREATEROLE_WITH);
2218         }
2219
2220         /*
2221          * complete CREATE ROLE,USER,GROUP <name> ENCRYPTED,UNENCRYPTED with
2222          * PASSWORD
2223          */
2224         else if (Matches4("CREATE", "ROLE|USER|GROUP", MatchAny, "ENCRYPTED|UNENCRYPTED"))
2225                 COMPLETE_WITH_CONST("PASSWORD");
2226         /* complete CREATE ROLE,USER,GROUP <name> IN with ROLE,GROUP */
2227         else if (Matches4("CREATE", "ROLE|USER|GROUP", MatchAny, "IN"))
2228                 COMPLETE_WITH_LIST2("GROUP", "ROLE");
2229
2230 /* CREATE VIEW --- is allowed inside CREATE SCHEMA, so use TailMatches */
2231         /* Complete CREATE VIEW <name> with AS */
2232         else if (TailMatches3("CREATE", "VIEW", MatchAny))
2233                 COMPLETE_WITH_CONST("AS");
2234         /* Complete "CREATE VIEW <sth> AS with "SELECT" */
2235         else if (TailMatches4("CREATE", "VIEW", MatchAny, "AS"))
2236                 COMPLETE_WITH_CONST("SELECT");
2237
2238 /* CREATE MATERIALIZED VIEW */
2239         else if (Matches2("CREATE", "MATERIALIZED"))
2240                 COMPLETE_WITH_CONST("VIEW");
2241         /* Complete CREATE MATERIALIZED VIEW <name> with AS */
2242         else if (Matches4("CREATE", "MATERIALIZED", "VIEW", MatchAny))
2243                 COMPLETE_WITH_CONST("AS");
2244         /* Complete "CREATE MATERIALIZED VIEW <sth> AS with "SELECT" */
2245         else if (Matches5("CREATE", "MATERIALIZED", "VIEW", MatchAny, "AS"))
2246                 COMPLETE_WITH_CONST("SELECT");
2247
2248 /* CREATE EVENT TRIGGER */
2249         else if (Matches2("CREATE", "EVENT"))
2250                 COMPLETE_WITH_CONST("TRIGGER");
2251         /* Complete CREATE EVENT TRIGGER <name> with ON */
2252         else if (Matches4("CREATE", "EVENT", "TRIGGER", MatchAny))
2253                 COMPLETE_WITH_CONST("ON");
2254         /* Complete CREATE EVENT TRIGGER <name> ON with event_type */
2255         else if (Matches5("CREATE", "EVENT", "TRIGGER", MatchAny, "ON"))
2256                 COMPLETE_WITH_LIST3("ddl_command_start", "ddl_command_end", "sql_drop");
2257
2258 /* DECLARE */
2259         else if (Matches2("DECLARE", MatchAny))
2260                 COMPLETE_WITH_LIST5("BINARY", "INSENSITIVE", "SCROLL", "NO SCROLL",
2261                                                         "CURSOR");
2262         else if (HeadMatches1("DECLARE") && TailMatches1("CURSOR"))
2263                 COMPLETE_WITH_LIST3("WITH HOLD", "WITHOUT HOLD", "FOR");
2264
2265 /* DELETE --- can be inside EXPLAIN, RULE, etc */
2266         /* ... despite which, only complete DELETE with FROM at start of line */
2267         else if (Matches1("DELETE"))
2268                 COMPLETE_WITH_CONST("FROM");
2269         /* Complete DELETE FROM with a list of tables */
2270         else if (TailMatches2("DELETE", "FROM"))
2271                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
2272         /* Complete DELETE FROM <table> */
2273         else if (TailMatches3("DELETE", "FROM", MatchAny))
2274                 COMPLETE_WITH_LIST2("USING", "WHERE");
2275         /* XXX: implement tab completion for DELETE ... USING */
2276
2277 /* DISCARD */
2278         else if (Matches1("DISCARD"))
2279                 COMPLETE_WITH_LIST4("ALL", "PLANS", "SEQUENCES", "TEMP");
2280
2281 /* DO */
2282         else if (Matches1("DO"))
2283                 COMPLETE_WITH_CONST("LANGUAGE");
2284
2285 /* DROP */
2286         /* Complete DROP object with CASCADE / RESTRICT */
2287         else if (Matches3("DROP",
2288                                           "COLLATION|CONVERSION|DOMAIN|EXTENSION|LANGUAGE|SCHEMA|SEQUENCE|SERVER|TABLE|TYPE|VIEW",
2289                                           MatchAny) ||
2290                          Matches4("DROP", "ACCESS", "METHOD", MatchAny) ||
2291                          (Matches4("DROP", "AGGREGATE|FUNCTION", MatchAny, MatchAny) &&
2292                           ends_with(prev_wd, ')')) ||
2293                          Matches4("DROP", "EVENT", "TRIGGER", MatchAny) ||
2294                          Matches5("DROP", "FOREIGN", "DATA", "WRAPPER", MatchAny) ||
2295                          Matches4("DROP", "FOREIGN", "TABLE", MatchAny) ||
2296                          Matches5("DROP", "TEXT", "SEARCH", "CONFIGURATION|DICTIONARY|PARSER|TEMPLATE", MatchAny))
2297                 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2298
2299         /* help completing some of the variants */
2300         else if (Matches3("DROP", "AGGREGATE|FUNCTION", MatchAny))
2301                 COMPLETE_WITH_CONST("(");
2302         else if (Matches4("DROP", "AGGREGATE|FUNCTION", MatchAny, "("))
2303                 COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
2304         else if (Matches2("DROP", "FOREIGN"))
2305                 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
2306
2307         /* DROP INDEX */
2308         else if (Matches2("DROP", "INDEX"))
2309                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
2310                                                                    " UNION SELECT 'CONCURRENTLY'");
2311         else if (Matches3("DROP", "INDEX", "CONCURRENTLY"))
2312                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
2313         else if (Matches3("DROP", "INDEX", MatchAny))
2314                 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2315         else if (Matches4("DROP", "INDEX", "CONCURRENTLY", MatchAny))
2316                 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2317
2318         /* DROP MATERIALIZED VIEW */
2319         else if (Matches2("DROP", "MATERIALIZED"))
2320                 COMPLETE_WITH_CONST("VIEW");
2321         else if (Matches3("DROP", "MATERIALIZED", "VIEW"))
2322                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
2323
2324         /* DROP OWNED BY */
2325         else if (Matches2("DROP", "OWNED"))
2326                 COMPLETE_WITH_CONST("BY");
2327         else if (Matches3("DROP", "OWNED", "BY"))
2328                 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2329
2330         else if (Matches3("DROP", "TEXT", "SEARCH"))
2331                 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2332
2333         /* DROP TRIGGER */
2334         else if (Matches3("DROP", "TRIGGER", MatchAny))
2335                 COMPLETE_WITH_CONST("ON");
2336         else if (Matches4("DROP", "TRIGGER", MatchAny, "ON"))
2337         {
2338                 completion_info_charp = prev2_wd;
2339                 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger);
2340         }
2341         else if (Matches5("DROP", "TRIGGER", MatchAny, "ON", MatchAny))
2342                 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2343
2344         /* DROP ACCESS METHOD */
2345         else if (Matches2("DROP", "ACCESS"))
2346                 COMPLETE_WITH_CONST("METHOD");
2347         else if (Matches3("DROP", "ACCESS", "METHOD"))
2348                 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
2349
2350         /* DROP EVENT TRIGGER */
2351         else if (Matches2("DROP", "EVENT"))
2352                 COMPLETE_WITH_CONST("TRIGGER");
2353         else if (Matches3("DROP", "EVENT", "TRIGGER"))
2354                 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
2355
2356         /* DROP POLICY <name>  */
2357         else if (Matches2("DROP", "POLICY"))
2358                 COMPLETE_WITH_QUERY(Query_for_list_of_policies);
2359         /* DROP POLICY <name> ON */
2360         else if (Matches3("DROP", "POLICY", MatchAny))
2361                 COMPLETE_WITH_CONST("ON");
2362         /* DROP POLICY <name> ON <table> */
2363         else if (Matches4("DROP", "POLICY", MatchAny, "ON"))
2364         {
2365                 completion_info_charp = prev2_wd;
2366                 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_policy);
2367         }
2368
2369         /* DROP RULE */
2370         else if (Matches3("DROP", "RULE", MatchAny))
2371                 COMPLETE_WITH_CONST("ON");
2372         else if (Matches4("DROP", "RULE", MatchAny, "ON"))
2373         {
2374                 completion_info_charp = prev2_wd;
2375                 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule);
2376         }
2377         else if (Matches5("DROP", "RULE", MatchAny, "ON", MatchAny))
2378                 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2379
2380 /* EXECUTE */
2381         else if (Matches1("EXECUTE"))
2382                 COMPLETE_WITH_QUERY(Query_for_list_of_prepared_statements);
2383
2384 /* EXPLAIN */
2385
2386         /*
2387          * Complete EXPLAIN [ANALYZE] [VERBOSE] with list of EXPLAIN-able commands
2388          */
2389         else if (Matches1("EXPLAIN"))
2390                 COMPLETE_WITH_LIST7("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE",
2391                                                         "ANALYZE", "VERBOSE");
2392         else if (Matches2("EXPLAIN", "ANALYZE"))
2393                 COMPLETE_WITH_LIST6("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE",
2394                                                         "VERBOSE");
2395         else if (Matches2("EXPLAIN", "VERBOSE") ||
2396                          Matches3("EXPLAIN", "ANALYZE", "VERBOSE"))
2397                 COMPLETE_WITH_LIST5("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE");
2398
2399 /* FETCH && MOVE */
2400         /* Complete FETCH with one of FORWARD, BACKWARD, RELATIVE */
2401         else if (Matches1("FETCH|MOVE"))
2402                 COMPLETE_WITH_LIST4("ABSOLUTE", "BACKWARD", "FORWARD", "RELATIVE");
2403         /* Complete FETCH <sth> with one of ALL, NEXT, PRIOR */
2404         else if (Matches2("FETCH|MOVE", MatchAny))
2405                 COMPLETE_WITH_LIST3("ALL", "NEXT", "PRIOR");
2406
2407         /*
2408          * Complete FETCH <sth1> <sth2> with "FROM" or "IN". These are equivalent,
2409          * but we may as well tab-complete both: perhaps some users prefer one
2410          * variant or the other.
2411          */
2412         else if (Matches3("FETCH|MOVE", MatchAny, MatchAny))
2413                 COMPLETE_WITH_LIST2("FROM", "IN");
2414
2415 /* FOREIGN DATA WRAPPER */
2416         /* applies in ALTER/DROP FDW and in CREATE SERVER */
2417         else if (TailMatches3("FOREIGN", "DATA", "WRAPPER") &&
2418                          !TailMatches4("CREATE", MatchAny, MatchAny, MatchAny))
2419                 COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
2420         /* applies in CREATE SERVER */
2421         else if (TailMatches4("FOREIGN", "DATA", "WRAPPER", MatchAny) &&
2422                          HeadMatches2("CREATE", "SERVER"))
2423                 COMPLETE_WITH_CONST("OPTIONS");
2424
2425 /* FOREIGN TABLE */
2426         else if (TailMatches2("FOREIGN", "TABLE") &&
2427                          !TailMatches3("CREATE", MatchAny, MatchAny))
2428                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL);
2429
2430 /* FOREIGN SERVER */
2431         else if (TailMatches2("FOREIGN", "SERVER"))
2432                 COMPLETE_WITH_QUERY(Query_for_list_of_servers);
2433
2434 /* GRANT && REVOKE --- is allowed inside CREATE SCHEMA, so use TailMatches */
2435         /* Complete GRANT/REVOKE with a list of roles and privileges */
2436         else if (TailMatches1("GRANT|REVOKE"))
2437                 COMPLETE_WITH_QUERY(Query_for_list_of_roles
2438                                                         " UNION SELECT 'SELECT'"
2439                                                         " UNION SELECT 'INSERT'"
2440                                                         " UNION SELECT 'UPDATE'"
2441                                                         " UNION SELECT 'DELETE'"
2442                                                         " UNION SELECT 'TRUNCATE'"
2443                                                         " UNION SELECT 'REFERENCES'"
2444                                                         " UNION SELECT 'TRIGGER'"
2445                                                         " UNION SELECT 'CREATE'"
2446                                                         " UNION SELECT 'CONNECT'"
2447                                                         " UNION SELECT 'TEMPORARY'"
2448                                                         " UNION SELECT 'EXECUTE'"
2449                                                         " UNION SELECT 'USAGE'"
2450                                                         " UNION SELECT 'ALL'");
2451
2452         /*
2453          * Complete GRANT/REVOKE <privilege> with "ON", GRANT/REVOKE <role> with
2454          * TO/FROM
2455          */
2456         else if (TailMatches2("GRANT|REVOKE", MatchAny))
2457         {
2458                 if (TailMatches1("SELECT|INSERT|UPDATE|DELETE|TRUNCATE|REFERENCES|TRIGGER|CREATE|CONNECT|TEMPORARY|TEMP|EXECUTE|USAGE|ALL"))
2459                         COMPLETE_WITH_CONST("ON");
2460                 else if (TailMatches2("GRANT", MatchAny))
2461                         COMPLETE_WITH_CONST("TO");
2462                 else
2463                         COMPLETE_WITH_CONST("FROM");
2464         }
2465
2466         /*
2467          * Complete GRANT/REVOKE <sth> ON with a list of tables, views, and
2468          * sequences.
2469          *
2470          * Keywords like DATABASE, FUNCTION, LANGUAGE and SCHEMA added to query
2471          * result via UNION; seems to work intuitively.
2472          *
2473          * Note: GRANT/REVOKE can get quite complex; tab-completion as implemented
2474          * here will only work if the privilege list contains exactly one
2475          * privilege.
2476          */
2477         else if (TailMatches3("GRANT|REVOKE", MatchAny, "ON"))
2478                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf,
2479                                                                    " UNION SELECT 'ALL FUNCTIONS IN SCHEMA'"
2480                                                                    " UNION SELECT 'ALL SEQUENCES IN SCHEMA'"
2481                                                                    " UNION SELECT 'ALL TABLES IN SCHEMA'"
2482                                                                    " UNION SELECT 'DATABASE'"
2483                                                                    " UNION SELECT 'DOMAIN'"
2484                                                                    " UNION SELECT 'FOREIGN DATA WRAPPER'"
2485                                                                    " UNION SELECT 'FOREIGN SERVER'"
2486                                                                    " UNION SELECT 'FUNCTION'"
2487                                                                    " UNION SELECT 'LANGUAGE'"
2488                                                                    " UNION SELECT 'LARGE OBJECT'"
2489                                                                    " UNION SELECT 'SCHEMA'"
2490                                                                    " UNION SELECT 'SEQUENCE'"
2491                                                                    " UNION SELECT 'TABLE'"
2492                                                                    " UNION SELECT 'TABLESPACE'"
2493                                                                    " UNION SELECT 'TYPE'");
2494
2495         else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", "ALL"))
2496                 COMPLETE_WITH_LIST3("FUNCTIONS IN SCHEMA", "SEQUENCES IN SCHEMA",
2497                                                         "TABLES IN SCHEMA");
2498
2499         else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", "FOREIGN"))
2500                 COMPLETE_WITH_LIST2("DATA WRAPPER", "SERVER");
2501
2502         /*
2503          * Complete "GRANT/REVOKE * ON DATABASE/DOMAIN/..." with a list of
2504          * appropriate objects.
2505          *
2506          * Complete "GRANT/REVOKE * ON *" with "TO/FROM".
2507          */
2508         else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", MatchAny))
2509         {
2510                 if (TailMatches1("DATABASE"))
2511                         COMPLETE_WITH_QUERY(Query_for_list_of_databases);
2512                 else if (TailMatches1("DOMAIN"))
2513                         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL);
2514                 else if (TailMatches1("FUNCTION"))
2515                         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
2516                 else if (TailMatches1("LANGUAGE"))
2517                         COMPLETE_WITH_QUERY(Query_for_list_of_languages);
2518                 else if (TailMatches1("SCHEMA"))
2519                         COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
2520                 else if (TailMatches1("SEQUENCE"))
2521                         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences, NULL);
2522                 else if (TailMatches1("TABLE"))
2523                         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
2524                 else if (TailMatches1("TABLESPACE"))
2525                         COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
2526                 else if (TailMatches1("TYPE"))
2527                         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL);
2528                 else if (TailMatches4("GRANT", MatchAny, MatchAny, MatchAny))
2529                         COMPLETE_WITH_CONST("TO");
2530                 else
2531                         COMPLETE_WITH_CONST("FROM");
2532         }
2533
2534         /*
2535          * Complete "GRANT/REVOKE ... TO/FROM" with username, PUBLIC,
2536          * CURRENT_USER, or SESSION_USER.
2537          */
2538         else if ((HeadMatches1("GRANT") && TailMatches1("TO")) ||
2539                          (HeadMatches1("REVOKE") && TailMatches1("FROM")))
2540                 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
2541
2542         /* Complete "GRANT/REVOKE ... ON * *" with TO/FROM */
2543         else if (HeadMatches1("GRANT") && TailMatches3("ON", MatchAny, MatchAny))
2544                 COMPLETE_WITH_CONST("TO");
2545         else if (HeadMatches1("REVOKE") && TailMatches3("ON", MatchAny, MatchAny))
2546                 COMPLETE_WITH_CONST("FROM");
2547
2548         /* Complete "GRANT/REVOKE * ON ALL * IN SCHEMA *" with TO/FROM */
2549         else if (TailMatches8("GRANT|REVOKE", MatchAny, "ON", "ALL", MatchAny, "IN", "SCHEMA", MatchAny))
2550         {
2551                 if (TailMatches8("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
2552                         COMPLETE_WITH_CONST("TO");
2553                 else
2554                         COMPLETE_WITH_CONST("FROM");
2555         }
2556
2557         /* Complete "GRANT/REVOKE * ON FOREIGN DATA WRAPPER *" with TO/FROM */
2558         else if (TailMatches7("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "DATA", "WRAPPER", MatchAny))
2559         {
2560                 if (TailMatches7("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
2561                         COMPLETE_WITH_CONST("TO");
2562                 else
2563                         COMPLETE_WITH_CONST("FROM");
2564         }
2565
2566         /* Complete "GRANT/REVOKE * ON FOREIGN SERVER *" with TO/FROM */
2567         else if (TailMatches6("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "SERVER", MatchAny))
2568         {
2569                 if (TailMatches6("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
2570                         COMPLETE_WITH_CONST("TO");
2571                 else
2572                         COMPLETE_WITH_CONST("FROM");
2573         }
2574
2575 /* GROUP BY */
2576         else if (TailMatches3("FROM", MatchAny, "GROUP"))
2577                 COMPLETE_WITH_CONST("BY");
2578
2579 /* IMPORT FOREIGN SCHEMA */
2580         else if (Matches1("IMPORT"))
2581                 COMPLETE_WITH_CONST("FOREIGN SCHEMA");
2582         else if (Matches2("IMPORT", "FOREIGN"))
2583                 COMPLETE_WITH_CONST("SCHEMA");
2584
2585 /* INSERT --- can be inside EXPLAIN, RULE, etc */
2586         /* Complete INSERT with "INTO" */
2587         else if (TailMatches1("INSERT"))
2588                 COMPLETE_WITH_CONST("INTO");
2589         /* Complete INSERT INTO with table names */
2590         else if (TailMatches2("INSERT", "INTO"))
2591                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
2592         /* Complete "INSERT INTO <table> (" with attribute names */
2593         else if (TailMatches4("INSERT", "INTO", MatchAny, "("))
2594                 COMPLETE_WITH_ATTR(prev2_wd, "");
2595
2596         /*
2597          * Complete INSERT INTO <table> with "(" or "VALUES" or "SELECT" or
2598          * "TABLE" or "DEFAULT VALUES"
2599          */
2600         else if (TailMatches3("INSERT", "INTO", MatchAny))
2601                 COMPLETE_WITH_LIST5("(", "DEFAULT VALUES", "SELECT", "TABLE", "VALUES");
2602
2603         /*
2604          * Complete INSERT INTO <table> (attribs) with "VALUES" or "SELECT" or
2605          * "TABLE"
2606          */
2607         else if (TailMatches4("INSERT", "INTO", MatchAny, MatchAny) &&
2608                          ends_with(prev_wd, ')'))
2609                 COMPLETE_WITH_LIST3("SELECT", "TABLE", "VALUES");
2610
2611         /* Insert an open parenthesis after "VALUES" */
2612         else if (TailMatches1("VALUES") && !TailMatches2("DEFAULT", "VALUES"))
2613                 COMPLETE_WITH_CONST("(");
2614
2615 /* LOCK */
2616         /* Complete LOCK [TABLE] with a list of tables */
2617         else if (Matches1("LOCK"))
2618                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
2619                                                                    " UNION SELECT 'TABLE'");
2620         else if (Matches2("LOCK", "TABLE"))
2621                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
2622
2623         /* For the following, handle the case of a single table only for now */
2624
2625         /* Complete LOCK [TABLE] <table> with "IN" */
2626         else if (Matches2("LOCK", MatchAnyExcept("TABLE")) ||
2627                          Matches3("LOCK", "TABLE", MatchAny))
2628                 COMPLETE_WITH_CONST("IN");
2629
2630         /* Complete LOCK [TABLE] <table> IN with a lock mode */
2631         else if (Matches3("LOCK", MatchAny, "IN") ||
2632                          Matches4("LOCK", "TABLE", MatchAny, "IN"))
2633                 COMPLETE_WITH_LIST8("ACCESS SHARE MODE",
2634                                                         "ROW SHARE MODE", "ROW EXCLUSIVE MODE",
2635                                                         "SHARE UPDATE EXCLUSIVE MODE", "SHARE MODE",
2636                                                         "SHARE ROW EXCLUSIVE MODE",
2637                                                         "EXCLUSIVE MODE", "ACCESS EXCLUSIVE MODE");
2638
2639 /* NOTIFY --- can be inside EXPLAIN, RULE, etc */
2640         else if (TailMatches1("NOTIFY"))
2641                 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'");
2642
2643 /* OPTIONS */
2644         else if (TailMatches1("OPTIONS"))
2645                 COMPLETE_WITH_CONST("(");
2646
2647 /* OWNER TO  - complete with available roles */
2648         else if (TailMatches2("OWNER", "TO"))
2649                 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2650
2651 /* ORDER BY */
2652         else if (TailMatches3("FROM", MatchAny, "ORDER"))
2653                 COMPLETE_WITH_CONST("BY");
2654         else if (TailMatches4("FROM", MatchAny, "ORDER", "BY"))
2655                 COMPLETE_WITH_ATTR(prev3_wd, "");
2656
2657 /* PREPARE xx AS */
2658         else if (Matches3("PREPARE", MatchAny, "AS"))
2659                 COMPLETE_WITH_LIST4("SELECT", "UPDATE", "INSERT", "DELETE FROM");
2660
2661 /*
2662  * PREPARE TRANSACTION is missing on purpose. It's intended for transaction
2663  * managers, not for manual use in interactive sessions.
2664  */
2665
2666 /* REASSIGN OWNED BY xxx TO yyy */
2667         else if (Matches1("REASSIGN"))
2668                 COMPLETE_WITH_CONST("OWNED BY");
2669         else if (Matches2("REASSIGN", "OWNED"))
2670                 COMPLETE_WITH_CONST("BY");
2671         else if (Matches3("REASSIGN", "OWNED", "BY"))
2672                 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2673         else if (Matches4("REASSIGN", "OWNED", "BY", MatchAny))
2674                 COMPLETE_WITH_CONST("TO");
2675         else if (Matches5("REASSIGN", "OWNED", "BY", MatchAny, "TO"))
2676                 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2677
2678 /* REFRESH MATERIALIZED VIEW */
2679         else if (Matches1("REFRESH"))
2680                 COMPLETE_WITH_CONST("MATERIALIZED VIEW");
2681         else if (Matches2("REFRESH", "MATERIALIZED"))
2682                 COMPLETE_WITH_CONST("VIEW");
2683         else if (Matches3("REFRESH", "MATERIALIZED", "VIEW"))
2684                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews,
2685                                                                    " UNION SELECT 'CONCURRENTLY'");
2686         else if (Matches4("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY"))
2687                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
2688         else if (Matches4("REFRESH", "MATERIALIZED", "VIEW", MatchAny))
2689                 COMPLETE_WITH_CONST("WITH");
2690         else if (Matches5("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny))
2691                 COMPLETE_WITH_CONST("WITH");
2692         else if (Matches5("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH"))
2693                 COMPLETE_WITH_LIST2("NO DATA", "DATA");
2694         else if (Matches6("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH"))
2695                 COMPLETE_WITH_LIST2("NO DATA", "DATA");
2696         else if (Matches6("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH", "NO"))
2697                 COMPLETE_WITH_CONST("DATA");
2698         else if (Matches7("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH", "NO"))
2699                 COMPLETE_WITH_CONST("DATA");
2700
2701 /* REINDEX */
2702         else if (Matches1("REINDEX"))
2703                 COMPLETE_WITH_LIST5("TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE");
2704         else if (Matches2("REINDEX", "TABLE"))
2705                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
2706         else if (Matches2("REINDEX", "INDEX"))
2707                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
2708         else if (Matches2("REINDEX", "SCHEMA"))
2709                 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
2710         else if (Matches2("REINDEX", "SYSTEM|DATABASE"))
2711                 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
2712
2713 /* SECURITY LABEL */
2714         else if (Matches1("SECURITY"))
2715                 COMPLETE_WITH_CONST("LABEL");
2716         else if (Matches2("SECURITY", "LABEL"))
2717                 COMPLETE_WITH_LIST2("ON", "FOR");
2718         else if (Matches4("SECURITY", "LABEL", "FOR", MatchAny))
2719                 COMPLETE_WITH_CONST("ON");
2720         else if (Matches3("SECURITY", "LABEL", "ON") ||
2721                          Matches5("SECURITY", "LABEL", "FOR", MatchAny, "ON"))
2722         {
2723                 static const char *const list_SECURITY_LABEL[] =
2724                 {"TABLE", "COLUMN", "AGGREGATE", "DATABASE", "DOMAIN",
2725                         "EVENT TRIGGER", "FOREIGN TABLE", "FUNCTION", "LARGE OBJECT",
2726                         "MATERIALIZED VIEW", "LANGUAGE", "ROLE", "SCHEMA",
2727                 "SEQUENCE", "TABLESPACE", "TYPE", "VIEW", NULL};
2728
2729                 COMPLETE_WITH_LIST(list_SECURITY_LABEL);
2730         }
2731         else if (Matches5("SECURITY", "LABEL", "ON", MatchAny, MatchAny))
2732                 COMPLETE_WITH_CONST("IS");
2733
2734 /* SELECT */
2735         /* naah . . . */
2736
2737 /* SET, RESET, SHOW */
2738         /* Complete with a variable name */
2739         else if (TailMatches1("SET|RESET") && !TailMatches3("UPDATE", MatchAny, "SET"))
2740                 COMPLETE_WITH_QUERY(Query_for_list_of_set_vars);
2741         else if (Matches1("SHOW"))
2742                 COMPLETE_WITH_QUERY(Query_for_list_of_show_vars);
2743         /* Complete "SET TRANSACTION" */
2744         else if (Matches2("SET|BEGIN|START", "TRANSACTION") ||
2745                          Matches2("BEGIN", "WORK") ||
2746                   Matches5("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION"))
2747                 COMPLETE_WITH_LIST2("ISOLATION LEVEL", "READ");
2748         else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION") ||
2749                          Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION"))
2750                 COMPLETE_WITH_CONST("LEVEL");
2751         else if (Matches4("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL"))
2752                 COMPLETE_WITH_LIST3("READ", "REPEATABLE READ", "SERIALIZABLE");
2753         else if (Matches5("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "READ"))
2754                 COMPLETE_WITH_LIST2("UNCOMMITTED", "COMMITTED");
2755         else if (Matches5("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "REPEATABLE"))
2756                 COMPLETE_WITH_CONST("READ");
2757         else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "READ"))
2758                 COMPLETE_WITH_LIST2("ONLY", "WRITE");
2759         /* SET CONSTRAINTS */
2760         else if (Matches2("SET", "CONSTRAINTS"))
2761                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_constraints_with_schema, "UNION SELECT 'ALL'");
2762         /* Complete SET CONSTRAINTS <foo> with DEFERRED|IMMEDIATE */
2763         else if (Matches3("SET", "CONSTRAINTS", MatchAny))
2764                 COMPLETE_WITH_LIST2("DEFERRED", "IMMEDIATE");
2765         /* Complete SET ROLE */
2766         else if (Matches2("SET", "ROLE"))
2767                 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2768         /* Complete SET SESSION with AUTHORIZATION or CHARACTERISTICS... */
2769         else if (Matches2("SET", "SESSION"))
2770                 COMPLETE_WITH_LIST2("AUTHORIZATION", "CHARACTERISTICS AS TRANSACTION");
2771         /* Complete SET SESSION AUTHORIZATION with username */
2772         else if (Matches3("SET", "SESSION", "AUTHORIZATION"))
2773                 COMPLETE_WITH_QUERY(Query_for_list_of_roles " UNION SELECT 'DEFAULT'");
2774         /* Complete RESET SESSION with AUTHORIZATION */
2775         else if (Matches2("RESET", "SESSION"))
2776                 COMPLETE_WITH_CONST("AUTHORIZATION");
2777         /* Complete SET <var> with "TO" */
2778         else if (Matches2("SET", MatchAny))
2779                 COMPLETE_WITH_CONST("TO");
2780         /* Complete ALTER DATABASE|FUNCTION|ROLE|USER ... SET <name> */
2781         else if (HeadMatches2("ALTER", "DATABASE|FUNCTION|ROLE|USER") &&
2782                          TailMatches2("SET", MatchAny))
2783                 COMPLETE_WITH_LIST2("FROM CURRENT", "TO");
2784         /* Suggest possible variable values */
2785         else if (TailMatches3("SET", MatchAny, "TO|="))
2786         {
2787                 /* special cased code for individual GUCs */
2788                 if (TailMatches2("DateStyle", "TO|="))
2789                 {
2790                         static const char *const my_list[] =
2791                         {"ISO", "SQL", "Postgres", "German",
2792                                 "YMD", "DMY", "MDY",
2793                                 "US", "European", "NonEuropean",
2794                         "DEFAULT", NULL};
2795
2796                         COMPLETE_WITH_LIST(my_list);
2797                 }
2798                 else if (TailMatches2("search_path", "TO|="))
2799                         COMPLETE_WITH_QUERY(Query_for_list_of_schemas
2800                                                                 " AND nspname not like 'pg\\_toast%%' "
2801                                                                 " AND nspname not like 'pg\\_temp%%' "
2802                                                                 " UNION SELECT 'DEFAULT' ");
2803                 else
2804                 {
2805                         /* generic, type based, GUC support */
2806                         char       *guctype = get_guctype(prev2_wd);
2807
2808                         if (guctype && strcmp(guctype, "enum") == 0)
2809                         {
2810                                 char            querybuf[1024];
2811
2812                                 snprintf(querybuf, sizeof(querybuf), Query_for_enum, prev2_wd);
2813                                 COMPLETE_WITH_QUERY(querybuf);
2814                         }
2815                         else if (guctype && strcmp(guctype, "bool") == 0)
2816                                 COMPLETE_WITH_LIST9("on", "off", "true", "false", "yes", "no",
2817                                                                         "1", "0", "DEFAULT");
2818                         else
2819                                 COMPLETE_WITH_CONST("DEFAULT");
2820
2821                         if (guctype)
2822                                 free(guctype);
2823                 }
2824         }
2825
2826 /* START TRANSACTION */
2827         else if (Matches1("START"))
2828                 COMPLETE_WITH_CONST("TRANSACTION");
2829
2830 /* TABLE, but not TABLE embedded in other commands */
2831         else if (Matches1("TABLE"))
2832                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations, NULL);
2833
2834 /* TABLESAMPLE */
2835         else if (TailMatches1("TABLESAMPLE"))
2836                 COMPLETE_WITH_QUERY(Query_for_list_of_tablesample_methods);
2837         else if (TailMatches2("TABLESAMPLE", MatchAny))
2838                 COMPLETE_WITH_CONST("(");
2839
2840 /* TRUNCATE */
2841         else if (Matches1("TRUNCATE"))
2842                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2843
2844 /* UNLISTEN */
2845         else if (Matches1("UNLISTEN"))
2846                 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 '*'");
2847
2848 /* UPDATE --- can be inside EXPLAIN, RULE, etc */
2849         /* If prev. word is UPDATE suggest a list of tables */
2850         else if (TailMatches1("UPDATE"))
2851                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
2852         /* Complete UPDATE <table> with "SET" */
2853         else if (TailMatches2("UPDATE", MatchAny))
2854                 COMPLETE_WITH_CONST("SET");
2855         /* Complete UPDATE <table> SET with list of attributes */
2856         else if (TailMatches3("UPDATE", MatchAny, "SET"))
2857                 COMPLETE_WITH_ATTR(prev2_wd, "");
2858         /* UPDATE <table> SET <attr> = */
2859         else if (TailMatches4("UPDATE", MatchAny, "SET", MatchAny))
2860                 COMPLETE_WITH_CONST("=");
2861
2862 /* USER MAPPING */
2863         else if (Matches3("ALTER|CREATE|DROP", "USER", "MAPPING"))
2864                 COMPLETE_WITH_CONST("FOR");
2865         else if (Matches4("CREATE", "USER", "MAPPING", "FOR"))
2866                 COMPLETE_WITH_QUERY(Query_for_list_of_roles
2867                                                         " UNION SELECT 'CURRENT_USER'"
2868                                                         " UNION SELECT 'PUBLIC'"
2869                                                         " UNION SELECT 'USER'");
2870         else if (Matches4("ALTER|DROP", "USER", "MAPPING", "FOR"))
2871                 COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
2872         else if (Matches5("CREATE|ALTER|DROP", "USER", "MAPPING", "FOR", MatchAny))
2873                 COMPLETE_WITH_CONST("SERVER");
2874         else if (Matches7("CREATE|ALTER", "USER", "MAPPING", "FOR", MatchAny, "SERVER", MatchAny))
2875                 COMPLETE_WITH_CONST("OPTIONS");
2876
2877 /*
2878  * VACUUM [ FULL | FREEZE ] [ VERBOSE ] [ table ]
2879  * VACUUM [ FULL | FREEZE ] [ VERBOSE ] ANALYZE [ table [ (column [, ...] ) ] ]
2880  */
2881         else if (Matches1("VACUUM"))
2882                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
2883                                                                    " UNION SELECT 'FULL'"
2884                                                                    " UNION SELECT 'FREEZE'"
2885                                                                    " UNION SELECT 'ANALYZE'"
2886                                                                    " UNION SELECT 'VERBOSE'");
2887         else if (Matches2("VACUUM", "FULL|FREEZE"))
2888                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
2889                                                                    " UNION SELECT 'ANALYZE'"
2890                                                                    " UNION SELECT 'VERBOSE'");
2891         else if (Matches3("VACUUM", "FULL|FREEZE", "ANALYZE"))
2892                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
2893                                                                    " UNION SELECT 'VERBOSE'");
2894         else if (Matches3("VACUUM", "FULL|FREEZE", "VERBOSE"))
2895                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
2896                                                                    " UNION SELECT 'ANALYZE'");
2897         else if (Matches2("VACUUM", "VERBOSE"))
2898                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
2899                                                                    " UNION SELECT 'ANALYZE'");
2900         else if (Matches2("VACUUM", "ANALYZE"))
2901                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
2902                                                                    " UNION SELECT 'VERBOSE'");
2903         else if (HeadMatches1("VACUUM"))
2904                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
2905
2906 /* WITH [RECURSIVE] */
2907
2908         /*
2909          * Only match when WITH is the first word, as WITH may appear in many
2910          * other contexts.
2911          */
2912         else if (Matches1("WITH"))
2913                 COMPLETE_WITH_CONST("RECURSIVE");
2914
2915 /* ANALYZE */
2916         /* Complete with list of tables */
2917         else if (Matches1("ANALYZE"))
2918                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tmf, NULL);
2919
2920 /* WHERE */
2921         /* Simple case of the word before the where being the table name */
2922         else if (TailMatches2(MatchAny, "WHERE"))
2923                 COMPLETE_WITH_ATTR(prev2_wd, "");
2924
2925 /* ... FROM ... */
2926 /* TODO: also include SRF ? */
2927         else if (TailMatches1("FROM") && !Matches3("COPY|\\copy", MatchAny, "FROM"))
2928                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
2929
2930 /* ... JOIN ... */
2931         else if (TailMatches1("JOIN"))
2932                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
2933
2934 /* Backslash commands */
2935 /* TODO:  \dc \dd \dl */
2936         else if (TailMatchesCS1("\\?"))
2937                 COMPLETE_WITH_LIST_CS3("commands", "options", "variables");
2938         else if (TailMatchesCS1("\\connect|\\c"))
2939         {
2940                 if (!recognized_connection_string(text))
2941                         COMPLETE_WITH_QUERY(Query_for_list_of_databases);
2942         }
2943         else if (TailMatchesCS2("\\connect|\\c", MatchAny))
2944         {
2945                 if (!recognized_connection_string(prev_wd))
2946                         COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2947         }
2948         else if (TailMatchesCS1("\\da*"))
2949                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_aggregates, NULL);
2950         else if (TailMatchesCS1("\\dA*"))
2951                 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
2952         else if (TailMatchesCS1("\\db*"))
2953                 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
2954         else if (TailMatchesCS1("\\dD*"))
2955                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL);
2956         else if (TailMatchesCS1("\\des*"))
2957                 COMPLETE_WITH_QUERY(Query_for_list_of_servers);
2958         else if (TailMatchesCS1("\\deu*"))
2959                 COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
2960         else if (TailMatchesCS1("\\dew*"))
2961                 COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
2962         else if (TailMatchesCS1("\\df*"))
2963                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
2964
2965         else if (TailMatchesCS1("\\dFd*"))
2966                 COMPLETE_WITH_QUERY(Query_for_list_of_ts_dictionaries);
2967         else if (TailMatchesCS1("\\dFp*"))
2968                 COMPLETE_WITH_QUERY(Query_for_list_of_ts_parsers);
2969         else if (TailMatchesCS1("\\dFt*"))
2970                 COMPLETE_WITH_QUERY(Query_for_list_of_ts_templates);
2971         /* must be at end of \dF alternatives: */
2972         else if (TailMatchesCS1("\\dF*"))
2973                 COMPLETE_WITH_QUERY(Query_for_list_of_ts_configurations);
2974
2975         else if (TailMatchesCS1("\\di*"))
2976                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
2977         else if (TailMatchesCS1("\\dL*"))
2978                 COMPLETE_WITH_QUERY(Query_for_list_of_languages);
2979         else if (TailMatchesCS1("\\dn*"))
2980                 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
2981         else if (TailMatchesCS1("\\dp") || TailMatchesCS1("\\z"))
2982                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
2983         else if (TailMatchesCS1("\\ds*"))
2984                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences, NULL);
2985         else if (TailMatchesCS1("\\dt*"))
2986                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2987         else if (TailMatchesCS1("\\dT*"))
2988                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL);
2989         else if (TailMatchesCS1("\\du*") || TailMatchesCS1("\\dg*"))
2990                 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2991         else if (TailMatchesCS1("\\dv*"))
2992                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
2993         else if (TailMatchesCS1("\\dx*"))
2994                 COMPLETE_WITH_QUERY(Query_for_list_of_extensions);
2995         else if (TailMatchesCS1("\\dm*"))
2996                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
2997         else if (TailMatchesCS1("\\dE*"))
2998                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL);
2999         else if (TailMatchesCS1("\\dy*"))
3000                 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
3001
3002         /* must be at end of \d alternatives: */
3003         else if (TailMatchesCS1("\\d*"))
3004                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations, NULL);
3005
3006         else if (TailMatchesCS1("\\ef"))
3007                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
3008         else if (TailMatchesCS1("\\ev"))
3009                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
3010
3011         else if (TailMatchesCS1("\\encoding"))
3012                 COMPLETE_WITH_QUERY(Query_for_list_of_encodings);
3013         else if (TailMatchesCS1("\\h") || TailMatchesCS1("\\help"))
3014                 COMPLETE_WITH_LIST(sql_commands);
3015         else if (TailMatchesCS1("\\password"))
3016                 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3017         else if (TailMatchesCS1("\\pset"))
3018         {
3019                 static const char *const my_list[] =
3020                 {"border", "columns", "expanded", "fieldsep", "fieldsep_zero",
3021                         "footer", "format", "linestyle", "null", "numericlocale",
3022                         "pager", "pager_min_lines", "recordsep", "recordsep_zero",
3023                         "tableattr", "title", "tuples_only", "unicode_border_linestyle",
3024                 "unicode_column_linestyle", "unicode_header_linestyle", NULL};
3025
3026                 COMPLETE_WITH_LIST_CS(my_list);
3027         }
3028         else if (TailMatchesCS2("\\pset", MatchAny))
3029         {
3030                 if (TailMatchesCS1("format"))
3031                 {
3032                         static const char *const my_list[] =
3033                         {"unaligned", "aligned", "wrapped", "html", "asciidoc",
3034                         "latex", "latex-longtable", "troff-ms", NULL};
3035
3036                         COMPLETE_WITH_LIST_CS(my_list);
3037                 }
3038                 else if (TailMatchesCS1("linestyle"))
3039                         COMPLETE_WITH_LIST_CS3("ascii", "old-ascii", "unicode");
3040                 else if (TailMatchesCS1("unicode_border_linestyle|"
3041                                                                 "unicode_column_linestyle|"
3042                                                                 "unicode_header_linestyle"))
3043                         COMPLETE_WITH_LIST_CS2("single", "double");
3044         }
3045         else if (TailMatchesCS1("\\unset"))
3046         {
3047                 matches = complete_from_variables(text, "", "", true);
3048         }
3049         else if (TailMatchesCS1("\\set"))
3050         {
3051                 matches = complete_from_variables(text, "", "", false);
3052         }
3053         else if (TailMatchesCS2("\\set", MatchAny))
3054         {
3055                 if (TailMatchesCS1("AUTOCOMMIT|ON_ERROR_STOP|QUIET|"
3056                                                    "SINGLELINE|SINGLESTEP"))
3057                         COMPLETE_WITH_LIST_CS2("on", "off");
3058                 else if (TailMatchesCS1("COMP_KEYWORD_CASE"))
3059                         COMPLETE_WITH_LIST_CS4("lower", "upper",
3060                                                                    "preserve-lower", "preserve-upper");
3061                 else if (TailMatchesCS1("ECHO"))
3062                         COMPLETE_WITH_LIST_CS4("errors", "queries", "all", "none");
3063                 else if (TailMatchesCS1("ECHO_HIDDEN"))
3064                         COMPLETE_WITH_LIST_CS3("noexec", "off", "on");
3065                 else if (TailMatchesCS1("HISTCONTROL"))
3066                         COMPLETE_WITH_LIST_CS4("ignorespace", "ignoredups",
3067                                                                    "ignoreboth", "none");
3068                 else if (TailMatchesCS1("ON_ERROR_ROLLBACK"))
3069                         COMPLETE_WITH_LIST_CS3("on", "off", "interactive");
3070                 else if (TailMatchesCS1("SHOW_CONTEXT"))
3071                         COMPLETE_WITH_LIST_CS3("never", "errors", "always");
3072                 else if (TailMatchesCS1("VERBOSITY"))
3073                         COMPLETE_WITH_LIST_CS3("default", "verbose", "terse");
3074         }
3075         else if (TailMatchesCS1("\\sf*"))
3076                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
3077         else if (TailMatchesCS1("\\sv*"))
3078                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
3079         else if (TailMatchesCS1("\\cd|\\e|\\edit|\\g|\\i|\\include|"
3080                                                         "\\ir|\\include_relative|\\o|\\out|"
3081                                                         "\\s|\\w|\\write|\\lo_import"))
3082         {
3083                 completion_charp = "\\";
3084                 matches = completion_matches(text, complete_from_files);
3085         }
3086
3087         /*
3088          * Finally, we look through the list of "things", such as TABLE, INDEX and
3089          * check if that was the previous word. If so, execute the query to get a
3090          * list of them.
3091          */
3092         else
3093         {
3094                 int                     i;
3095
3096                 for (i = 0; words_after_create[i].name; i++)
3097                 {
3098                         if (pg_strcasecmp(prev_wd, words_after_create[i].name) == 0)
3099                         {
3100                                 if (words_after_create[i].query)
3101                                         COMPLETE_WITH_QUERY(words_after_create[i].query);
3102                                 else if (words_after_create[i].squery)
3103                                         COMPLETE_WITH_SCHEMA_QUERY(*words_after_create[i].squery,
3104                                                                                            NULL);
3105                                 break;
3106                         }
3107                 }
3108         }
3109
3110         /*
3111          * If we still don't have anything to match we have to fabricate some sort
3112          * of default list. If we were to just return NULL, readline automatically
3113          * attempts filename completion, and that's usually no good.
3114          */
3115         if (matches == NULL)
3116         {
3117                 COMPLETE_WITH_CONST("");
3118 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
3119                 rl_completion_append_character = '\0';
3120 #endif
3121         }
3122
3123         /* free storage */
3124         free(previous_words);
3125         free(words_buffer);
3126
3127         /* Return our Grand List O' Matches */
3128         return matches;
3129 }
3130
3131
3132 /*
3133  * GENERATOR FUNCTIONS
3134  *
3135  * These functions do all the actual work of completing the input. They get
3136  * passed the text so far and the count how many times they have been called
3137  * so far with the same text.
3138  * If you read the above carefully, you'll see that these don't get called
3139  * directly but through the readline interface.
3140  * The return value is expected to be the full completion of the text, going
3141  * through a list each time, or NULL if there are no more matches. The string
3142  * will be free()'d by readline, so you must run it through strdup() or
3143  * something of that sort.
3144  */
3145
3146 /*
3147  * Common routine for create_command_generator and drop_command_generator.
3148  * Entries that have 'excluded' flags are not returned.
3149  */
3150 static char *
3151 create_or_drop_command_generator(const char *text, int state, bits32 excluded)
3152 {
3153         static int      list_index,
3154                                 string_length;
3155         const char *name;
3156
3157         /* If this is the first time for this completion, init some values */
3158         if (state == 0)
3159         {
3160                 list_index = 0;
3161                 string_length = strlen(text);
3162         }
3163
3164         /* find something that matches */
3165         while ((name = words_after_create[list_index++].name))
3166         {
3167                 if ((pg_strncasecmp(name, text, string_length) == 0) &&
3168                         !(words_after_create[list_index - 1].flags & excluded))
3169                         return pg_strdup_keyword_case(name, text);
3170         }
3171         /* if nothing matches, return NULL */
3172         return NULL;
3173 }
3174
3175 /*
3176  * This one gives you one from a list of things you can put after CREATE
3177  * as defined above.
3178  */
3179 static char *
3180 create_command_generator(const char *text, int state)
3181 {
3182         return create_or_drop_command_generator(text, state, THING_NO_CREATE);
3183 }
3184
3185 /*
3186  * This function gives you a list of things you can put after a DROP command.
3187  */
3188 static char *
3189 drop_command_generator(const char *text, int state)
3190 {
3191         return create_or_drop_command_generator(text, state, THING_NO_DROP);
3192 }
3193
3194 /* The following two functions are wrappers for _complete_from_query */
3195
3196 static char *
3197 complete_from_query(const char *text, int state)
3198 {
3199         return _complete_from_query(0, text, state);
3200 }
3201
3202 static char *
3203 complete_from_schema_query(const char *text, int state)
3204 {
3205         return _complete_from_query(1, text, state);
3206 }
3207
3208
3209 /*
3210  * This creates a list of matching things, according to a query pointed to
3211  * by completion_charp.
3212  * The query can be one of two kinds:
3213  *
3214  * 1. A simple query which must contain a %d and a %s, which will be replaced
3215  * by the string length of the text and the text itself. The query may also
3216  * have up to four more %s in it; the first two such will be replaced by the
3217  * value of completion_info_charp, the next two by the value of
3218  * completion_info_charp2.
3219  *
3220  * 2. A schema query used for completion of both schema and relation names.
3221  * These are more complex and must contain in the following order:
3222  * %d %s %d %s %d %s %s %d %s
3223  * where %d is the string length of the text and %s the text itself.
3224  *
3225  * It is assumed that strings should be escaped to become SQL literals
3226  * (that is, what is in the query is actually ... '%s' ...)
3227  *
3228  * See top of file for examples of both kinds of query.
3229  */
3230 static char *
3231 _complete_from_query(int is_schema_query, const char *text, int state)
3232 {
3233         static int      list_index,
3234                                 byte_length;
3235         static PGresult *result = NULL;
3236
3237         /*
3238          * If this is the first time for this completion, we fetch a list of our
3239          * "things" from the backend.
3240          */
3241         if (state == 0)
3242         {
3243                 PQExpBufferData query_buffer;
3244                 char       *e_text;
3245                 char       *e_info_charp;
3246                 char       *e_info_charp2;
3247                 const char *pstr = text;
3248                 int                     char_length = 0;
3249
3250                 list_index = 0;
3251                 byte_length = strlen(text);
3252
3253                 /*
3254                  * Count length as number of characters (not bytes), for passing to
3255                  * substring
3256                  */
3257                 while (*pstr)
3258                 {
3259                         char_length++;
3260                         pstr += PQmblen(pstr, pset.encoding);
3261                 }
3262
3263                 /* Free any prior result */
3264                 PQclear(result);
3265                 result = NULL;
3266
3267                 /* Set up suitably-escaped copies of textual inputs */
3268                 e_text = escape_string(text);
3269
3270                 if (completion_info_charp)
3271                         e_info_charp = escape_string(completion_info_charp);
3272                 else
3273                         e_info_charp = NULL;
3274
3275                 if (completion_info_charp2)
3276                         e_info_charp2 = escape_string(completion_info_charp2);
3277                 else
3278                         e_info_charp2 = NULL;
3279
3280                 initPQExpBuffer(&query_buffer);
3281
3282                 if (is_schema_query)
3283                 {
3284                         /* completion_squery gives us the pieces to assemble */
3285                         const char *qualresult = completion_squery->qualresult;
3286
3287                         if (qualresult == NULL)
3288                                 qualresult = completion_squery->result;
3289
3290                         /* Get unqualified names matching the input-so-far */
3291                         appendPQExpBuffer(&query_buffer, "SELECT %s FROM %s WHERE ",
3292                                                           completion_squery->result,
3293                                                           completion_squery->catname);
3294                         if (completion_squery->selcondition)
3295                                 appendPQExpBuffer(&query_buffer, "%s AND ",
3296                                                                   completion_squery->selcondition);
3297                         appendPQExpBuffer(&query_buffer, "substring(%s,1,%d)='%s'",
3298                                                           completion_squery->result,
3299                                                           char_length, e_text);
3300                         appendPQExpBuffer(&query_buffer, " AND %s",
3301                                                           completion_squery->viscondition);
3302
3303                         /*
3304                          * When fetching relation names, suppress system catalogs unless
3305                          * the input-so-far begins with "pg_".  This is a compromise
3306                          * between not offering system catalogs for completion at all, and
3307                          * having them swamp the result when the input is just "p".
3308                          */
3309                         if (strcmp(completion_squery->catname,
3310                                            "pg_catalog.pg_class c") == 0 &&
3311                                 strncmp(text, "pg_", 3) !=0)
3312                         {
3313                                 appendPQExpBufferStr(&query_buffer,
3314                                                                          " AND c.relnamespace <> (SELECT oid FROM"
3315                                    " pg_catalog.pg_namespace WHERE nspname = 'pg_catalog')");
3316                         }
3317
3318                         /*
3319                          * Add in matching schema names, but only if there is more than
3320                          * one potential match among schema names.
3321                          */
3322                         appendPQExpBuffer(&query_buffer, "\nUNION\n"
3323                                                    "SELECT pg_catalog.quote_ident(n.nspname) || '.' "
3324                                                           "FROM pg_catalog.pg_namespace n "
3325                                                           "WHERE substring(pg_catalog.quote_ident(n.nspname) || '.',1,%d)='%s'",
3326                                                           char_length, e_text);
3327                         appendPQExpBuffer(&query_buffer,
3328                                                           " AND (SELECT pg_catalog.count(*)"
3329                                                           " FROM pg_catalog.pg_namespace"
3330                         " WHERE substring(pg_catalog.quote_ident(nspname) || '.',1,%d) ="
3331                                                           " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(nspname))+1)) > 1",
3332                                                           char_length, e_text);
3333
3334                         /*
3335                          * Add in matching qualified names, but only if there is exactly
3336                          * one schema matching the input-so-far.
3337                          */
3338                         appendPQExpBuffer(&query_buffer, "\nUNION\n"
3339                                          "SELECT pg_catalog.quote_ident(n.nspname) || '.' || %s "
3340                                                           "FROM %s, pg_catalog.pg_namespace n "
3341                                                           "WHERE %s = n.oid AND ",
3342                                                           qualresult,
3343                                                           completion_squery->catname,
3344                                                           completion_squery->namespace);
3345                         if (completion_squery->selcondition)
3346                                 appendPQExpBuffer(&query_buffer, "%s AND ",
3347                                                                   completion_squery->selcondition);
3348                         appendPQExpBuffer(&query_buffer, "substring(pg_catalog.quote_ident(n.nspname) || '.' || %s,1,%d)='%s'",
3349                                                           qualresult,
3350                                                           char_length, e_text);
3351
3352                         /*
3353                          * This condition exploits the single-matching-schema rule to
3354                          * speed up the query
3355                          */
3356                         appendPQExpBuffer(&query_buffer,
3357                         " AND substring(pg_catalog.quote_ident(n.nspname) || '.',1,%d) ="
3358                                                           " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(n.nspname))+1)",
3359                                                           char_length, e_text);
3360                         appendPQExpBuffer(&query_buffer,
3361                                                           " AND (SELECT pg_catalog.count(*)"
3362                                                           " FROM pg_catalog.pg_namespace"
3363                         " WHERE substring(pg_catalog.quote_ident(nspname) || '.',1,%d) ="
3364                                                           " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(nspname))+1)) = 1",
3365                                                           char_length, e_text);
3366
3367                         /* If an addon query was provided, use it */
3368                         if (completion_charp)
3369                                 appendPQExpBuffer(&query_buffer, "\n%s", completion_charp);
3370                 }
3371                 else
3372                 {
3373                         /* completion_charp is an sprintf-style format string */
3374                         appendPQExpBuffer(&query_buffer, completion_charp,
3375                                                           char_length, e_text,
3376                                                           e_info_charp, e_info_charp,
3377                                                           e_info_charp2, e_info_charp2);
3378                 }
3379
3380                 /* Limit the number of records in the result */
3381                 appendPQExpBuffer(&query_buffer, "\nLIMIT %d",
3382                                                   completion_max_records);
3383
3384                 result = exec_query(query_buffer.data);
3385
3386                 termPQExpBuffer(&query_buffer);
3387                 free(e_text);
3388                 if (e_info_charp)
3389                         free(e_info_charp);
3390                 if (e_info_charp2)
3391                         free(e_info_charp2);
3392         }
3393
3394         /* Find something that matches */
3395         if (result && PQresultStatus(result) == PGRES_TUPLES_OK)
3396         {
3397                 const char *item;
3398
3399                 while (list_index < PQntuples(result) &&
3400                            (item = PQgetvalue(result, list_index++, 0)))
3401                         if (pg_strncasecmp(text, item, byte_length) == 0)
3402                                 return pg_strdup(item);
3403         }
3404
3405         /* If nothing matches, free the db structure and return null */
3406         PQclear(result);
3407         result = NULL;
3408         return NULL;
3409 }
3410
3411
3412 /*
3413  * This function returns in order one of a fixed, NULL pointer terminated list
3414  * of strings (if matching). This can be used if there are only a fixed number
3415  * SQL words that can appear at certain spot.
3416  */
3417 static char *
3418 complete_from_list(const char *text, int state)
3419 {
3420         static int      string_length,
3421                                 list_index,
3422                                 matches;
3423         static bool casesensitive;
3424         const char *item;
3425
3426         /* need to have a list */
3427         Assert(completion_charpp != NULL);
3428
3429         /* Initialization */
3430         if (state == 0)
3431         {
3432                 list_index = 0;
3433                 string_length = strlen(text);
3434                 casesensitive = completion_case_sensitive;
3435                 matches = 0;
3436         }
3437
3438         while ((item = completion_charpp[list_index++]))
3439         {
3440                 /* First pass is case sensitive */
3441                 if (casesensitive && strncmp(text, item, string_length) == 0)
3442                 {
3443                         matches++;
3444                         return pg_strdup(item);
3445                 }
3446
3447                 /* Second pass is case insensitive, don't bother counting matches */
3448                 if (!casesensitive && pg_strncasecmp(text, item, string_length) == 0)
3449                 {
3450                         if (completion_case_sensitive)
3451                                 return pg_strdup(item);
3452                         else
3453
3454                                 /*
3455                                  * If case insensitive matching was requested initially,
3456                                  * adjust the case according to setting.
3457                                  */
3458                                 return pg_strdup_keyword_case(item, text);
3459                 }
3460         }
3461
3462         /*
3463          * No matches found. If we're not case insensitive already, lets switch to
3464          * being case insensitive and try again
3465          */
3466         if (casesensitive && matches == 0)
3467         {
3468                 casesensitive = false;
3469                 list_index = 0;
3470                 state++;
3471                 return complete_from_list(text, state);
3472         }
3473
3474         /* If no more matches, return null. */
3475         return NULL;
3476 }
3477
3478
3479 /*
3480  * This function returns one fixed string the first time even if it doesn't
3481  * match what's there, and nothing the second time. This should be used if
3482  * there is only one possibility that can appear at a certain spot, so
3483  * misspellings will be overwritten.  The string to be passed must be in
3484  * completion_charp.
3485  */
3486 static char *
3487 complete_from_const(const char *text, int state)
3488 {
3489         Assert(completion_charp != NULL);
3490         if (state == 0)
3491         {
3492                 if (completion_case_sensitive)
3493                         return pg_strdup(completion_charp);
3494                 else
3495
3496                         /*
3497                          * If case insensitive matching was requested initially, adjust
3498                          * the case according to setting.
3499                          */
3500                         return pg_strdup_keyword_case(completion_charp, text);
3501         }
3502         else
3503                 return NULL;
3504 }
3505
3506
3507 /*
3508  * This function appends the variable name with prefix and suffix to
3509  * the variable names array.
3510  */
3511 static void
3512 append_variable_names(char ***varnames, int *nvars,
3513                                           int *maxvars, const char *varname,
3514                                           const char *prefix, const char *suffix)
3515 {
3516         if (*nvars >= *maxvars)
3517         {
3518                 *maxvars *= 2;
3519                 *varnames = (char **) pg_realloc(*varnames,
3520                                                                                  ((*maxvars) + 1) * sizeof(char *));
3521         }
3522
3523         (*varnames)[(*nvars)++] = psprintf("%s%s%s", prefix, varname, suffix);
3524 }
3525
3526
3527 /*
3528  * This function supports completion with the name of a psql variable.
3529  * The variable names can be prefixed and suffixed with additional text
3530  * to support quoting usages. If need_value is true, only the variables
3531  * that have the set values are picked up.
3532  */
3533 static char **
3534 complete_from_variables(const char *text, const char *prefix, const char *suffix,
3535                                                 bool need_value)
3536 {
3537         char      **matches;
3538         char      **varnames;
3539         int                     nvars = 0;
3540         int                     maxvars = 100;
3541         int                     i;
3542         struct _variable *ptr;
3543
3544         static const char *const known_varnames[] = {
3545                 "AUTOCOMMIT", "COMP_KEYWORD_CASE", "DBNAME", "ECHO", "ECHO_HIDDEN",
3546                 "ENCODING", "FETCH_COUNT", "HISTCONTROL", "HISTFILE", "HISTSIZE",
3547                 "HOST", "IGNOREEOF", "LASTOID", "ON_ERROR_ROLLBACK", "ON_ERROR_STOP",
3548                 "PORT", "PROMPT1", "PROMPT2", "PROMPT3", "QUIET",
3549                 "SHOW_CONTEXT", "SINGLELINE", "SINGLESTEP",
3550                 "USER", "VERBOSITY", NULL
3551         };
3552
3553         varnames = (char **) pg_malloc((maxvars + 1) * sizeof(char *));
3554
3555         if (!need_value)
3556         {
3557                 for (i = 0; known_varnames[i] && nvars < maxvars; i++)
3558                         append_variable_names(&varnames, &nvars, &maxvars,
3559                                                                   known_varnames[i], prefix, suffix);
3560         }
3561
3562         for (ptr = pset.vars->next; ptr; ptr = ptr->next)
3563         {
3564                 if (need_value && !(ptr->value))
3565                         continue;
3566                 for (i = 0; known_varnames[i]; i++)             /* remove duplicate entry */
3567                 {
3568                         if (strcmp(ptr->name, known_varnames[i]) == 0)
3569                                 continue;
3570                 }
3571                 append_variable_names(&varnames, &nvars, &maxvars, ptr->name,
3572                                                           prefix, suffix);
3573         }
3574
3575         varnames[nvars] = NULL;
3576         COMPLETE_WITH_LIST_CS((const char *const *) varnames);
3577
3578         for (i = 0; i < nvars; i++)
3579                 free(varnames[i]);
3580         free(varnames);
3581
3582         return matches;
3583 }
3584
3585
3586 /*
3587  * This function wraps rl_filename_completion_function() to strip quotes from
3588  * the input before searching for matches and to quote any matches for which
3589  * the consuming command will require it.
3590  */
3591 static char *
3592 complete_from_files(const char *text, int state)
3593 {
3594         static const char *unquoted_text;
3595         char       *unquoted_match;
3596         char       *ret = NULL;
3597
3598         if (state == 0)
3599         {
3600                 /* Initialization: stash the unquoted input. */
3601                 unquoted_text = strtokx(text, "", NULL, "'", *completion_charp,
3602                                                                 false, true, pset.encoding);
3603                 /* expect a NULL return for the empty string only */
3604                 if (!unquoted_text)
3605                 {
3606                         Assert(*text == '\0');
3607                         unquoted_text = text;
3608                 }
3609         }
3610
3611         unquoted_match = filename_completion_function(unquoted_text, state);
3612         if (unquoted_match)
3613         {
3614                 /*
3615                  * Caller sets completion_charp to a zero- or one-character string
3616                  * containing the escape character.  This is necessary since \copy has
3617                  * no escape character, but every other backslash command recognizes
3618                  * "\" as an escape character.  Since we have only two callers, don't
3619                  * bother providing a macro to simplify this.
3620                  */
3621                 ret = quote_if_needed(unquoted_match, " \t\r\n\"`",
3622                                                           '\'', *completion_charp, pset.encoding);
3623                 if (ret)
3624                         free(unquoted_match);
3625                 else
3626                         ret = unquoted_match;
3627         }
3628
3629         return ret;
3630 }
3631
3632
3633 /* HELPER FUNCTIONS */
3634
3635
3636 /*
3637  * Make a pg_strdup copy of s and convert the case according to
3638  * COMP_KEYWORD_CASE setting, using ref as the text that was already entered.
3639  */
3640 static char *
3641 pg_strdup_keyword_case(const char *s, const char *ref)
3642 {
3643         char       *ret,
3644                            *p;
3645         unsigned char first = ref[0];
3646
3647         ret = pg_strdup(s);
3648
3649         if (pset.comp_case == PSQL_COMP_CASE_LOWER ||
3650                 ((pset.comp_case == PSQL_COMP_CASE_PRESERVE_LOWER ||
3651            pset.comp_case == PSQL_COMP_CASE_PRESERVE_UPPER) && islower(first)) ||
3652                 (pset.comp_case == PSQL_COMP_CASE_PRESERVE_LOWER && !isalpha(first)))
3653         {
3654                 for (p = ret; *p; p++)
3655                         *p = pg_tolower((unsigned char) *p);
3656         }
3657         else
3658         {
3659                 for (p = ret; *p; p++)
3660                         *p = pg_toupper((unsigned char) *p);
3661         }
3662
3663         return ret;
3664 }
3665
3666
3667 /*
3668  * escape_string - Escape argument for use as string literal.
3669  *
3670  * The returned value has to be freed.
3671  */
3672 static char *
3673 escape_string(const char *text)
3674 {
3675         size_t          text_length;
3676         char       *result;
3677
3678         text_length = strlen(text);
3679
3680         result = pg_malloc(text_length * 2 + 1);
3681         PQescapeStringConn(pset.db, result, text, text_length, NULL);
3682
3683         return result;
3684 }
3685
3686
3687 /*
3688  * Execute a query and report any errors. This should be the preferred way of
3689  * talking to the database in this file.
3690  */
3691 static PGresult *
3692 exec_query(const char *query)
3693 {
3694         PGresult   *result;
3695
3696         if (query == NULL || !pset.db || PQstatus(pset.db) != CONNECTION_OK)
3697                 return NULL;
3698
3699         result = PQexec(pset.db, query);
3700
3701         if (PQresultStatus(result) != PGRES_TUPLES_OK)
3702         {
3703 #ifdef NOT_USED
3704                 psql_error("tab completion query failed: %s\nQuery was:\n%s\n",
3705                                    PQerrorMessage(pset.db), query);
3706 #endif
3707                 PQclear(result);
3708                 result = NULL;
3709         }
3710
3711         return result;
3712 }
3713
3714
3715 /*
3716  * Parse all the word(s) before point.
3717  *
3718  * Returns a malloc'd array of character pointers that point into the malloc'd
3719  * data array returned to *buffer; caller must free() both of these when done.
3720  * *nwords receives the number of words found, ie, the valid length of the
3721  * return array.
3722  *
3723  * Words are returned right to left, that is, previous_words[0] gets the last
3724  * word before point, previous_words[1] the next-to-last, etc.
3725  */
3726 static char **
3727 get_previous_words(int point, char **buffer, int *nwords)
3728 {
3729         char      **previous_words;
3730         char       *buf;
3731         char       *outptr;
3732         int                     words_found = 0;
3733         int                     i;
3734
3735         /*
3736          * If we have anything in tab_completion_query_buf, paste it together with
3737          * rl_line_buffer to construct the full query.  Otherwise we can just use
3738          * rl_line_buffer as the input string.
3739          */
3740         if (tab_completion_query_buf && tab_completion_query_buf->len > 0)
3741         {
3742                 i = tab_completion_query_buf->len;
3743                 buf = pg_malloc(point + i + 2);
3744                 memcpy(buf, tab_completion_query_buf->data, i);
3745                 buf[i++] = '\n';
3746                 memcpy(buf + i, rl_line_buffer, point);
3747                 i += point;
3748                 buf[i] = '\0';
3749                 /* Readjust point to reference appropriate offset in buf */
3750                 point = i;
3751         }
3752         else
3753                 buf = rl_line_buffer;
3754
3755         /*
3756          * Allocate an array of string pointers and a buffer to hold the strings
3757          * themselves.  The worst case is that the line contains only
3758          * non-whitespace WORD_BREAKS characters, making each one a separate word.
3759          * This is usually much more space than we need, but it's cheaper than
3760          * doing a separate malloc() for each word.
3761          */
3762         previous_words = (char **) pg_malloc(point * sizeof(char *));
3763         *buffer = outptr = (char *) pg_malloc(point * 2);
3764
3765         /*
3766          * First we look for a non-word char before the current point.  (This is
3767          * probably useless, if readline is on the same page as we are about what
3768          * is a word, but if so it's cheap.)
3769          */
3770         for (i = point - 1; i >= 0; i--)
3771         {
3772                 if (strchr(WORD_BREAKS, buf[i]))
3773                         break;
3774         }
3775         point = i;
3776
3777         /*
3778          * Now parse words, working backwards, until we hit start of line.  The
3779          * backwards scan has some interesting but intentional properties
3780          * concerning parenthesis handling.
3781          */
3782         while (point >= 0)
3783         {
3784                 int                     start,
3785                                         end;
3786                 bool            inquotes = false;
3787                 int                     parentheses = 0;
3788
3789                 /* now find the first non-space which then constitutes the end */
3790                 end = -1;
3791                 for (i = point; i >= 0; i--)
3792                 {
3793                         if (!isspace((unsigned char) buf[i]))
3794                         {
3795                                 end = i;
3796                                 break;
3797                         }
3798                 }
3799                 /* if no end found, we're done */
3800                 if (end < 0)
3801                         break;
3802
3803                 /*
3804                  * Otherwise we now look for the start.  The start is either the last
3805                  * character before any word-break character going backwards from the
3806                  * end, or it's simply character 0.  We also handle open quotes and
3807                  * parentheses.
3808                  */
3809                 for (start = end; start > 0; start--)
3810                 {
3811                         if (buf[start] == '"')
3812                                 inquotes = !inquotes;
3813                         if (!inquotes)
3814                         {
3815                                 if (buf[start] == ')')
3816                                         parentheses++;
3817                                 else if (buf[start] == '(')
3818                                 {
3819                                         if (--parentheses <= 0)
3820                                                 break;
3821                                 }
3822                                 else if (parentheses == 0 &&
3823                                                  strchr(WORD_BREAKS, buf[start - 1]))
3824                                         break;
3825                         }
3826                 }
3827
3828                 /* Return the word located at start to end inclusive */
3829                 previous_words[words_found++] = outptr;
3830                 i = end - start + 1;
3831                 memcpy(outptr, &buf[start], i);
3832                 outptr += i;
3833                 *outptr++ = '\0';
3834
3835                 /* Continue searching */
3836                 point = start - 1;
3837         }
3838
3839         /* Release parsing input workspace, if we made one above */
3840         if (buf != rl_line_buffer)
3841                 free(buf);
3842
3843         *nwords = words_found;
3844         return previous_words;
3845 }
3846
3847 /*
3848  * Look up the type for the GUC variable with the passed name.
3849  *
3850  * Returns NULL if the variable is unknown. Otherwise the returned string,
3851  * containing the type, has to be freed.
3852  */
3853 static char *
3854 get_guctype(const char *varname)
3855 {
3856         PQExpBufferData query_buffer;
3857         char       *e_varname;
3858         PGresult   *result;
3859         char       *guctype = NULL;
3860
3861         e_varname = escape_string(varname);
3862
3863         initPQExpBuffer(&query_buffer);
3864         appendPQExpBuffer(&query_buffer,
3865                                           "SELECT vartype FROM pg_catalog.pg_settings "
3866                                           "WHERE pg_catalog.lower(name) = pg_catalog.lower('%s')",
3867                                           e_varname);
3868
3869         result = exec_query(query_buffer.data);
3870         termPQExpBuffer(&query_buffer);
3871         free(e_varname);
3872
3873         if (PQresultStatus(result) == PGRES_TUPLES_OK && PQntuples(result) > 0)
3874                 guctype = pg_strdup(PQgetvalue(result, 0, 0));
3875
3876         PQclear(result);
3877
3878         return guctype;
3879 }
3880
3881 #ifdef NOT_USED
3882
3883 /*
3884  * Surround a string with single quotes. This works for both SQL and
3885  * psql internal. Currently disabled because it is reported not to
3886  * cooperate with certain versions of readline.
3887  */
3888 static char *
3889 quote_file_name(char *text, int match_type, char *quote_pointer)
3890 {
3891         char       *s;
3892         size_t          length;
3893
3894         (void) quote_pointer;           /* not used */
3895
3896         length = strlen(text) +(match_type == SINGLE_MATCH ? 3 : 2);
3897         s = pg_malloc(length);
3898         s[0] = '\'';
3899         strcpy(s + 1, text);
3900         if (match_type == SINGLE_MATCH)
3901                 s[length - 2] = '\'';
3902         s[length - 1] = '\0';
3903         return s;
3904 }
3905
3906 static char *
3907 dequote_file_name(char *text, char quote_char)
3908 {
3909         char       *s;
3910         size_t          length;
3911
3912         if (!quote_char)
3913                 return pg_strdup(text);
3914
3915         length = strlen(text);
3916         s = pg_malloc(length - 2 + 1);
3917         strlcpy(s, text +1, length - 2 + 1);
3918
3919         return s;
3920 }
3921 #endif   /* NOT_USED */
3922
3923 #endif   /* USE_READLINE */