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