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