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