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