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