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