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