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