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