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