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