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