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