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