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