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