Age Owner TLA Line data Source code
1 : /*
2 : * psql - the PostgreSQL interactive terminal
3 : *
4 : * Copyright (c) 2000-2023, 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 :
37 : #include "input.h"
38 : #include "tab-complete.h"
39 :
40 : /* If we don't have this, we might as well forget about the whole thing: */
41 : #ifdef USE_READLINE
42 :
43 : #include <ctype.h>
44 : #include <sys/stat.h>
45 :
46 : #include "catalog/pg_am_d.h"
47 : #include "catalog/pg_class_d.h"
48 : #include "common.h"
49 : #include "common/keywords.h"
50 : #include "libpq-fe.h"
51 : #include "mb/pg_wchar.h"
52 : #include "pqexpbuffer.h"
53 : #include "settings.h"
54 : #include "stringutils.h"
55 :
56 : /*
57 : * Ancient versions of libedit provide filename_completion_function()
58 : * instead of rl_filename_completion_function(). Likewise for
59 : * [rl_]completion_matches().
60 : */
61 : #ifndef HAVE_RL_FILENAME_COMPLETION_FUNCTION
62 : #define rl_filename_completion_function filename_completion_function
63 : #endif
64 :
65 : #ifndef HAVE_RL_COMPLETION_MATCHES
66 : #define rl_completion_matches completion_matches
67 : #endif
68 :
69 : /*
70 : * Currently we assume that rl_filename_dequoting_function exists if
71 : * rl_filename_quoting_function does. If that proves not to be the case,
72 : * we'd need to test for the former, or possibly both, in configure.
73 : */
74 : #ifdef HAVE_RL_FILENAME_QUOTING_FUNCTION
75 : #define USE_FILENAME_QUOTING_FUNCTIONS 1
76 : #endif
77 :
78 : /* word break characters */
79 : #define WORD_BREAKS "\t\n@$><=;|&{() "
80 :
81 : /*
82 : * Since readline doesn't let us pass any state through to the tab completion
83 : * callback, we have to use this global variable to let get_previous_words()
84 : * get at the previous lines of the current command. Ick.
85 : */
86 : PQExpBuffer tab_completion_query_buf = NULL;
87 :
88 : /*
89 : * In some situations, the query to find out what names are available to
90 : * complete with must vary depending on server version. We handle this by
91 : * storing a list of queries, each tagged with the minimum server version
92 : * it will work for. Each list must be stored in descending server version
93 : * order, so that the first satisfactory query is the one to use.
94 : *
95 : * When the query string is otherwise constant, an array of VersionedQuery
96 : * suffices. Terminate the array with an entry having min_server_version = 0.
97 : * That entry's query string can be a query that works in all supported older
98 : * server versions, or NULL to give up and do no completion.
99 : */
100 : typedef struct VersionedQuery
101 : {
102 : int min_server_version;
103 : const char *query;
104 : } VersionedQuery;
105 :
106 : /*
107 : * This struct is used to define "schema queries", which are custom-built
108 : * to obtain possibly-schema-qualified names of database objects. There is
109 : * enough similarity in the structure that we don't want to repeat it each
110 : * time. So we put the components of each query into this struct and
111 : * assemble them with the common boilerplate in _complete_from_query().
112 : *
113 : * We also use this struct to define queries that use completion_ref_object,
114 : * which is some object related to the one(s) we want to get the names of
115 : * (for example, the table we want the indexes of). In that usage the
116 : * objects we're completing might not have a schema of their own, but the
117 : * reference object almost always does (passed in completion_ref_schema).
118 : *
119 : * As with VersionedQuery, we can use an array of these if the query details
120 : * must vary across versions.
121 : */
122 : typedef struct SchemaQuery
123 : {
124 : /*
125 : * If not zero, minimum server version this struct applies to. If not
126 : * zero, there should be a following struct with a smaller minimum server
127 : * version; use catname == NULL in the last entry if we should do nothing.
128 : */
129 : int min_server_version;
130 :
131 : /*
132 : * Name of catalog or catalogs to be queried, with alias(es), eg.
133 : * "pg_catalog.pg_class c". Note that "pg_namespace n" and/or
134 : * "pg_namespace nr" will be added automatically when needed.
135 : */
136 : const char *catname;
137 :
138 : /*
139 : * Selection condition --- only rows meeting this condition are candidates
140 : * to display. If catname mentions multiple tables, include the necessary
141 : * join condition here. For example, this might look like "c.relkind = "
142 : * CppAsString2(RELKIND_RELATION). Write NULL (not an empty string) if
143 : * not needed.
144 : */
145 : const char *selcondition;
146 :
147 : /*
148 : * Visibility condition --- which rows are visible without schema
149 : * qualification? For example, "pg_catalog.pg_table_is_visible(c.oid)".
150 : * NULL if not needed.
151 : */
152 : const char *viscondition;
153 :
154 : /*
155 : * Namespace --- name of field to join to pg_namespace.oid when there is
156 : * schema qualification. For example, "c.relnamespace". NULL if we don't
157 : * want to join to pg_namespace (then any schema part in the input word
158 : * will be ignored).
159 : */
160 : const char *namespace;
161 :
162 : /*
163 : * Result --- the base object name to return. For example, "c.relname".
164 : */
165 : const char *result;
166 :
167 : /*
168 : * In some cases, it's difficult to keep the query from returning the same
169 : * object multiple times. Specify use_distinct to filter out duplicates.
170 : */
171 : bool use_distinct;
172 :
173 : /*
174 : * Additional literal strings (usually keywords) to be offered along with
175 : * the query results. Provide a NULL-terminated array of constant
176 : * strings, or NULL if none.
177 : */
178 : const char *const *keywords;
179 :
180 : /*
181 : * If this query uses completion_ref_object/completion_ref_schema,
182 : * populate the remaining fields, else leave them NULL. When using this
183 : * capability, catname must include the catalog that defines the
184 : * completion_ref_object, and selcondition must include the join condition
185 : * that connects it to the result's catalog.
186 : *
187 : * refname is the field that should be equated to completion_ref_object,
188 : * for example "cr.relname".
189 : */
190 : const char *refname;
191 :
192 : /*
193 : * Visibility condition to use when completion_ref_schema is not set. For
194 : * example, "pg_catalog.pg_table_is_visible(cr.oid)". NULL if not needed.
195 : */
196 : const char *refviscondition;
197 :
198 : /*
199 : * Name of field to join to pg_namespace.oid when completion_ref_schema is
200 : * set. For example, "cr.relnamespace". NULL if we don't want to
201 : * consider completion_ref_schema.
202 : */
203 : const char *refnamespace;
204 : } SchemaQuery;
205 :
206 :
207 : /* Store maximum number of records we want from database queries
208 : * (implemented via SELECT ... LIMIT xx).
209 : */
210 : static int completion_max_records;
211 :
212 : /*
213 : * Communication variables set by psql_completion (mostly in COMPLETE_WITH_FOO
214 : * macros) and then used by the completion callback functions. Ugly but there
215 : * is no better way.
216 : */
217 : static char completion_last_char; /* last char of input word */
218 : static const char *completion_charp; /* to pass a string */
219 : static const char *const *completion_charpp; /* to pass a list of strings */
220 : static const VersionedQuery *completion_vquery; /* to pass a VersionedQuery */
221 : static const SchemaQuery *completion_squery; /* to pass a SchemaQuery */
222 : static char *completion_ref_object; /* name of reference object */
223 : static char *completion_ref_schema; /* schema name of reference object */
224 : static bool completion_case_sensitive; /* completion is case sensitive */
225 : static bool completion_verbatim; /* completion is verbatim */
226 : static bool completion_force_quote; /* true to force-quote filenames */
227 :
228 : /*
229 : * A few macros to ease typing. You can use these to complete the given
230 : * string with
231 : * 1) The result from a query you pass it. (Perhaps one of those below?)
232 : * We support both simple and versioned queries.
233 : * 2) The result from a schema query you pass it.
234 : * We support both simple and versioned schema queries.
235 : * 3) The items from a null-pointer-terminated list (with or without
236 : * case-sensitive comparison); if the list is constant you can build it
237 : * with COMPLETE_WITH() or COMPLETE_WITH_CS(). The QUERY_LIST and
238 : * QUERY_PLUS forms combine such literal lists with a query result.
239 : * 4) The list of attributes of the given table (possibly schema-qualified).
240 : * 5) The list of arguments to the given function (possibly schema-qualified).
241 : *
242 : * The query is generally expected to return raw SQL identifiers; matching
243 : * to what the user typed is done in a quoting-aware fashion. If what is
244 : * returned is not SQL identifiers, use one of the VERBATIM forms, in which
245 : * case the query results are matched to the user's text without double-quote
246 : * processing (so if quoting is needed, you must provide it in the query
247 : * results).
248 : */
249 : #define COMPLETE_WITH_QUERY(query) \
250 : COMPLETE_WITH_QUERY_LIST(query, NULL)
251 :
252 : #define COMPLETE_WITH_QUERY_LIST(query, list) \
253 : do { \
254 : completion_charp = query; \
255 : completion_charpp = list; \
256 : completion_verbatim = false; \
257 : matches = rl_completion_matches(text, complete_from_query); \
258 : } while (0)
259 :
260 : #define COMPLETE_WITH_QUERY_PLUS(query, ...) \
261 : do { \
262 : static const char *const list[] = { __VA_ARGS__, NULL }; \
263 : COMPLETE_WITH_QUERY_LIST(query, list); \
264 : } while (0)
265 :
266 : #define COMPLETE_WITH_QUERY_VERBATIM(query) \
267 : COMPLETE_WITH_QUERY_VERBATIM_LIST(query, NULL)
268 :
269 : #define COMPLETE_WITH_QUERY_VERBATIM_LIST(query, list) \
270 : do { \
271 : completion_charp = query; \
272 : completion_charpp = list; \
273 : completion_verbatim = true; \
274 : matches = rl_completion_matches(text, complete_from_query); \
275 : } while (0)
276 :
277 : #define COMPLETE_WITH_QUERY_VERBATIM_PLUS(query, ...) \
278 : do { \
279 : static const char *const list[] = { __VA_ARGS__, NULL }; \
280 : COMPLETE_WITH_QUERY_VERBATIM_LIST(query, list); \
281 : } while (0)
282 :
283 : #define COMPLETE_WITH_VERSIONED_QUERY(query) \
284 : COMPLETE_WITH_VERSIONED_QUERY_LIST(query, NULL)
285 :
286 : #define COMPLETE_WITH_VERSIONED_QUERY_LIST(query, list) \
287 : do { \
288 : completion_vquery = query; \
289 : completion_charpp = list; \
290 : completion_verbatim = false; \
291 : matches = rl_completion_matches(text, complete_from_versioned_query); \
292 : } while (0)
293 :
294 : #define COMPLETE_WITH_VERSIONED_QUERY_PLUS(query, ...) \
295 : do { \
296 : static const char *const list[] = { __VA_ARGS__, NULL }; \
297 : COMPLETE_WITH_VERSIONED_QUERY_LIST(query, list); \
298 : } while (0)
299 :
300 : #define COMPLETE_WITH_SCHEMA_QUERY(query) \
301 : COMPLETE_WITH_SCHEMA_QUERY_LIST(query, NULL)
302 :
303 : #define COMPLETE_WITH_SCHEMA_QUERY_LIST(query, list) \
304 : do { \
305 : completion_squery = &(query); \
306 : completion_charpp = list; \
307 : completion_verbatim = false; \
308 : matches = rl_completion_matches(text, complete_from_schema_query); \
309 : } while (0)
310 :
311 : #define COMPLETE_WITH_SCHEMA_QUERY_PLUS(query, ...) \
312 : do { \
313 : static const char *const list[] = { __VA_ARGS__, NULL }; \
314 : COMPLETE_WITH_SCHEMA_QUERY_LIST(query, list); \
315 : } while (0)
316 :
317 : #define COMPLETE_WITH_SCHEMA_QUERY_VERBATIM(query) \
318 : do { \
319 : completion_squery = &(query); \
320 : completion_charpp = NULL; \
321 : completion_verbatim = true; \
322 : matches = rl_completion_matches(text, complete_from_schema_query); \
323 : } while (0)
324 :
325 : #define COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(query) \
326 : COMPLETE_WITH_VERSIONED_SCHEMA_QUERY_LIST(query, NULL)
327 :
328 : #define COMPLETE_WITH_VERSIONED_SCHEMA_QUERY_LIST(query, list) \
329 : do { \
330 : completion_squery = query; \
331 : completion_charpp = list; \
332 : completion_verbatim = false; \
333 : matches = rl_completion_matches(text, complete_from_versioned_schema_query); \
334 : } while (0)
335 :
336 : #define COMPLETE_WITH_VERSIONED_SCHEMA_QUERY_PLUS(query, ...) \
337 : do { \
338 : static const char *const list[] = { __VA_ARGS__, NULL }; \
339 : COMPLETE_WITH_VERSIONED_SCHEMA_QUERY_LIST(query, list); \
340 : } while (0)
341 :
342 : /*
343 : * Caution: COMPLETE_WITH_CONST is not for general-purpose use; you probably
344 : * want COMPLETE_WITH() with one element, instead.
345 : */
346 : #define COMPLETE_WITH_CONST(cs, con) \
347 : do { \
348 : completion_case_sensitive = (cs); \
349 : completion_charp = (con); \
350 : matches = rl_completion_matches(text, complete_from_const); \
351 : } while (0)
352 :
353 : #define COMPLETE_WITH_LIST_INT(cs, list) \
354 : do { \
355 : completion_case_sensitive = (cs); \
356 : completion_charpp = (list); \
357 : matches = rl_completion_matches(text, complete_from_list); \
358 : } while (0)
359 :
360 : #define COMPLETE_WITH_LIST(list) COMPLETE_WITH_LIST_INT(false, list)
361 : #define COMPLETE_WITH_LIST_CS(list) COMPLETE_WITH_LIST_INT(true, list)
362 :
363 : #define COMPLETE_WITH(...) \
364 : do { \
365 : static const char *const list[] = { __VA_ARGS__, NULL }; \
366 : COMPLETE_WITH_LIST(list); \
367 : } while (0)
368 :
369 : #define COMPLETE_WITH_CS(...) \
370 : do { \
371 : static const char *const list[] = { __VA_ARGS__, NULL }; \
372 : COMPLETE_WITH_LIST_CS(list); \
373 : } while (0)
374 :
375 : #define COMPLETE_WITH_ATTR(relation) \
376 : COMPLETE_WITH_ATTR_LIST(relation, NULL)
377 :
378 : #define COMPLETE_WITH_ATTR_LIST(relation, list) \
379 : do { \
380 : set_completion_reference(relation); \
381 : completion_squery = &(Query_for_list_of_attributes); \
382 : completion_charpp = list; \
383 : completion_verbatim = false; \
384 : matches = rl_completion_matches(text, complete_from_schema_query); \
385 : } while (0)
386 :
387 : #define COMPLETE_WITH_ATTR_PLUS(relation, ...) \
388 : do { \
389 : static const char *const list[] = { __VA_ARGS__, NULL }; \
390 : COMPLETE_WITH_ATTR_LIST(relation, list); \
391 : } while (0)
392 :
393 : /*
394 : * libedit will typically include the literal's leading single quote in
395 : * "text", while readline will not. Adapt our offered strings to fit.
396 : * But include a quote if there's not one just before "text", to get the
397 : * user off to the right start.
398 : */
399 : #define COMPLETE_WITH_ENUM_VALUE(type) \
400 : do { \
401 : set_completion_reference(type); \
402 : if (text[0] == '\'' || \
403 : start == 0 || rl_line_buffer[start - 1] != '\'') \
404 : completion_squery = &(Query_for_list_of_enum_values_quoted); \
405 : else \
406 : completion_squery = &(Query_for_list_of_enum_values_unquoted); \
407 : completion_charpp = NULL; \
408 : completion_verbatim = true; \
409 : matches = rl_completion_matches(text, complete_from_schema_query); \
410 : } while (0)
411 :
412 : /*
413 : * Timezone completion is mostly like enum label completion, but we work
414 : * a little harder since this is a more common use-case.
415 : */
416 : #define COMPLETE_WITH_TIMEZONE_NAME() \
417 : do { \
418 : static const char *const list[] = { "DEFAULT", NULL }; \
419 : if (text[0] == '\'') \
420 : completion_charp = Query_for_list_of_timezone_names_quoted_in; \
421 : else if (start == 0 || rl_line_buffer[start - 1] != '\'') \
422 : completion_charp = Query_for_list_of_timezone_names_quoted_out; \
423 : else \
424 : completion_charp = Query_for_list_of_timezone_names_unquoted; \
425 : completion_charpp = list; \
426 : completion_verbatim = true; \
427 : matches = rl_completion_matches(text, complete_from_query); \
428 : } while (0)
429 :
430 : #define COMPLETE_WITH_FUNCTION_ARG(function) \
431 : do { \
432 : set_completion_reference(function); \
433 : completion_squery = &(Query_for_list_of_arguments); \
434 : completion_charpp = NULL; \
435 : completion_verbatim = true; \
436 : matches = rl_completion_matches(text, complete_from_schema_query); \
437 : } while (0)
438 :
439 : /*
440 : * Assembly instructions for schema queries
441 : *
442 : * Note that toast tables are not included in those queries to avoid
443 : * unnecessary bloat in the completions generated.
444 : */
445 :
446 : static const SchemaQuery Query_for_constraint_of_table = {
447 : .catname = "pg_catalog.pg_constraint con, pg_catalog.pg_class c1",
448 : .selcondition = "con.conrelid=c1.oid",
449 : .result = "con.conname",
450 : .refname = "c1.relname",
451 : .refviscondition = "pg_catalog.pg_table_is_visible(c1.oid)",
452 : .refnamespace = "c1.relnamespace",
453 : };
454 :
455 : static const SchemaQuery Query_for_constraint_of_table_not_validated = {
456 : .catname = "pg_catalog.pg_constraint con, pg_catalog.pg_class c1",
457 : .selcondition = "con.conrelid=c1.oid and not con.convalidated",
458 : .result = "con.conname",
459 : .refname = "c1.relname",
460 : .refviscondition = "pg_catalog.pg_table_is_visible(c1.oid)",
461 : .refnamespace = "c1.relnamespace",
462 : };
463 :
464 : static const SchemaQuery Query_for_constraint_of_type = {
465 : .catname = "pg_catalog.pg_constraint con, pg_catalog.pg_type t",
466 : .selcondition = "con.contypid=t.oid",
467 : .result = "con.conname",
468 : .refname = "t.typname",
469 : .refviscondition = "pg_catalog.pg_type_is_visible(t.oid)",
470 : .refnamespace = "t.typnamespace",
471 : };
472 :
473 : static const SchemaQuery Query_for_index_of_table = {
474 : .catname = "pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_index i",
475 : .selcondition = "c1.oid=i.indrelid and i.indexrelid=c2.oid",
476 : .result = "c2.relname",
477 : .refname = "c1.relname",
478 : .refviscondition = "pg_catalog.pg_table_is_visible(c1.oid)",
479 : .refnamespace = "c1.relnamespace",
480 : };
481 :
482 : static const SchemaQuery Query_for_unique_index_of_table = {
483 : .catname = "pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_index i",
484 : .selcondition = "c1.oid=i.indrelid and i.indexrelid=c2.oid and i.indisunique",
485 : .result = "c2.relname",
486 : .refname = "c1.relname",
487 : .refviscondition = "pg_catalog.pg_table_is_visible(c1.oid)",
488 : .refnamespace = "c1.relnamespace",
489 : };
490 :
491 : static const SchemaQuery Query_for_list_of_aggregates[] = {
492 : {
493 : .min_server_version = 110000,
494 : .catname = "pg_catalog.pg_proc p",
495 : .selcondition = "p.prokind = 'a'",
496 : .viscondition = "pg_catalog.pg_function_is_visible(p.oid)",
497 : .namespace = "p.pronamespace",
498 : .result = "p.proname",
499 : },
500 : {
501 : .catname = "pg_catalog.pg_proc p",
502 : .selcondition = "p.proisagg",
503 : .viscondition = "pg_catalog.pg_function_is_visible(p.oid)",
504 : .namespace = "p.pronamespace",
505 : .result = "p.proname",
506 : }
507 : };
508 :
509 : static const SchemaQuery Query_for_list_of_arguments = {
510 : .catname = "pg_catalog.pg_proc p",
511 : .result = "pg_catalog.oidvectortypes(p.proargtypes)||')'",
512 : .refname = "p.proname",
513 : .refviscondition = "pg_catalog.pg_function_is_visible(p.oid)",
514 : .refnamespace = "p.pronamespace",
515 : };
516 :
517 : static const SchemaQuery Query_for_list_of_attributes = {
518 : .catname = "pg_catalog.pg_attribute a, pg_catalog.pg_class c",
519 : .selcondition = "c.oid = a.attrelid and a.attnum > 0 and not a.attisdropped",
520 : .result = "a.attname",
521 : .refname = "c.relname",
522 : .refviscondition = "pg_catalog.pg_table_is_visible(c.oid)",
523 : .refnamespace = "c.relnamespace",
524 : };
525 :
526 : static const SchemaQuery Query_for_list_of_attribute_numbers = {
527 : .catname = "pg_catalog.pg_attribute a, pg_catalog.pg_class c",
528 : .selcondition = "c.oid = a.attrelid and a.attnum > 0 and not a.attisdropped",
529 : .result = "a.attnum::pg_catalog.text",
530 : .refname = "c.relname",
531 : .refviscondition = "pg_catalog.pg_table_is_visible(c.oid)",
532 : .refnamespace = "c.relnamespace",
533 : };
534 :
535 : static const char *const Keywords_for_list_of_datatypes[] = {
536 : "bigint",
537 : "boolean",
538 : "character",
539 : "double precision",
540 : "integer",
541 : "real",
542 : "smallint",
543 :
544 : /*
545 : * Note: currently there's no value in offering the following multiword
546 : * type names, because tab completion cannot succeed for them: we can't
547 : * disambiguate until somewhere in the second word, at which point we
548 : * won't have the first word as context. ("double precision" does work,
549 : * as long as no other type name begins with "double".) Leave them out to
550 : * encourage users to use the PG-specific aliases, which we can complete.
551 : */
552 : #ifdef NOT_USED
553 : "bit varying",
554 : "character varying",
555 : "time with time zone",
556 : "time without time zone",
557 : "timestamp with time zone",
558 : "timestamp without time zone",
559 : #endif
560 : NULL
561 : };
562 :
563 : static const SchemaQuery Query_for_list_of_datatypes = {
564 : .catname = "pg_catalog.pg_type t",
565 : /* selcondition --- ignore table rowtypes and array types */
566 : .selcondition = "(t.typrelid = 0 "
567 : " OR (SELECT c.relkind = " CppAsString2(RELKIND_COMPOSITE_TYPE)
568 : " FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid)) "
569 : "AND t.typname !~ '^_'",
570 : .viscondition = "pg_catalog.pg_type_is_visible(t.oid)",
571 : .namespace = "t.typnamespace",
572 : .result = "t.typname",
573 : .keywords = Keywords_for_list_of_datatypes,
574 : };
575 :
576 : static const SchemaQuery Query_for_list_of_composite_datatypes = {
577 : .catname = "pg_catalog.pg_type t",
578 : /* selcondition --- only get composite types */
579 : .selcondition = "(SELECT c.relkind = " CppAsString2(RELKIND_COMPOSITE_TYPE)
580 : " FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid) "
581 : "AND t.typname !~ '^_'",
582 : .viscondition = "pg_catalog.pg_type_is_visible(t.oid)",
583 : .namespace = "t.typnamespace",
584 : .result = "t.typname",
585 : };
586 :
587 : static const SchemaQuery Query_for_list_of_domains = {
588 : .catname = "pg_catalog.pg_type t",
589 : .selcondition = "t.typtype = 'd'",
590 : .viscondition = "pg_catalog.pg_type_is_visible(t.oid)",
591 : .namespace = "t.typnamespace",
592 : .result = "t.typname",
593 : };
594 :
595 : static const SchemaQuery Query_for_list_of_enum_values_quoted = {
596 : .catname = "pg_catalog.pg_enum e, pg_catalog.pg_type t",
597 : .selcondition = "t.oid = e.enumtypid",
598 : .result = "pg_catalog.quote_literal(enumlabel)",
599 : .refname = "t.typname",
600 : .refviscondition = "pg_catalog.pg_type_is_visible(t.oid)",
601 : .refnamespace = "t.typnamespace",
602 : };
603 :
604 : static const SchemaQuery Query_for_list_of_enum_values_unquoted = {
605 : .catname = "pg_catalog.pg_enum e, pg_catalog.pg_type t",
606 : .selcondition = "t.oid = e.enumtypid",
607 : .result = "e.enumlabel",
608 : .refname = "t.typname",
609 : .refviscondition = "pg_catalog.pg_type_is_visible(t.oid)",
610 : .refnamespace = "t.typnamespace",
611 : };
612 :
613 : /* Note: this intentionally accepts aggregates as well as plain functions */
614 : static const SchemaQuery Query_for_list_of_functions[] = {
615 : {
616 : .min_server_version = 110000,
617 : .catname = "pg_catalog.pg_proc p",
618 : .selcondition = "p.prokind != 'p'",
619 : .viscondition = "pg_catalog.pg_function_is_visible(p.oid)",
620 : .namespace = "p.pronamespace",
621 : .result = "p.proname",
622 : },
623 : {
624 : .catname = "pg_catalog.pg_proc p",
625 : .viscondition = "pg_catalog.pg_function_is_visible(p.oid)",
626 : .namespace = "p.pronamespace",
627 : .result = "p.proname",
628 : }
629 : };
630 :
631 : static const SchemaQuery Query_for_list_of_procedures[] = {
632 : {
633 : .min_server_version = 110000,
634 : .catname = "pg_catalog.pg_proc p",
635 : .selcondition = "p.prokind = 'p'",
636 : .viscondition = "pg_catalog.pg_function_is_visible(p.oid)",
637 : .namespace = "p.pronamespace",
638 : .result = "p.proname",
639 : },
640 : {
641 : /* not supported in older versions */
642 : .catname = NULL,
643 : }
644 : };
645 :
646 : static const SchemaQuery Query_for_list_of_routines = {
647 : .catname = "pg_catalog.pg_proc p",
648 : .viscondition = "pg_catalog.pg_function_is_visible(p.oid)",
649 : .namespace = "p.pronamespace",
650 : .result = "p.proname",
651 : };
652 :
653 : static const SchemaQuery Query_for_list_of_sequences = {
654 : .catname = "pg_catalog.pg_class c",
655 : .selcondition = "c.relkind IN (" CppAsString2(RELKIND_SEQUENCE) ")",
656 : .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
657 : .namespace = "c.relnamespace",
658 : .result = "c.relname",
659 : };
660 :
661 : static const SchemaQuery Query_for_list_of_foreign_tables = {
662 : .catname = "pg_catalog.pg_class c",
663 : .selcondition = "c.relkind IN (" CppAsString2(RELKIND_FOREIGN_TABLE) ")",
664 : .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
665 : .namespace = "c.relnamespace",
666 : .result = "c.relname",
667 : };
668 :
669 : static const SchemaQuery Query_for_list_of_tables = {
670 : .catname = "pg_catalog.pg_class c",
671 : .selcondition =
672 : "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
673 : CppAsString2(RELKIND_PARTITIONED_TABLE) ")",
674 : .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
675 : .namespace = "c.relnamespace",
676 : .result = "c.relname",
677 : };
678 :
679 : static const SchemaQuery Query_for_list_of_partitioned_tables = {
680 : .catname = "pg_catalog.pg_class c",
681 : .selcondition = "c.relkind IN (" CppAsString2(RELKIND_PARTITIONED_TABLE) ")",
682 : .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
683 : .namespace = "c.relnamespace",
684 : .result = "c.relname",
685 : };
686 :
687 : static const SchemaQuery Query_for_list_of_tables_for_constraint = {
688 : .catname = "pg_catalog.pg_class c, pg_catalog.pg_constraint con",
689 : .selcondition = "c.oid=con.conrelid and c.relkind IN ("
690 : CppAsString2(RELKIND_RELATION) ", "
691 : CppAsString2(RELKIND_PARTITIONED_TABLE) ")",
692 : .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
693 : .namespace = "c.relnamespace",
694 : .result = "c.relname",
695 : .use_distinct = true,
696 : .refname = "con.conname",
697 : };
698 :
699 : static const SchemaQuery Query_for_list_of_tables_for_policy = {
700 : .catname = "pg_catalog.pg_class c, pg_catalog.pg_policy p",
701 : .selcondition = "c.oid=p.polrelid",
702 : .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
703 : .namespace = "c.relnamespace",
704 : .result = "c.relname",
705 : .use_distinct = true,
706 : .refname = "p.polname",
707 : };
708 :
709 : static const SchemaQuery Query_for_list_of_tables_for_rule = {
710 : .catname = "pg_catalog.pg_class c, pg_catalog.pg_rewrite r",
711 : .selcondition = "c.oid=r.ev_class",
712 : .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
713 : .namespace = "c.relnamespace",
714 : .result = "c.relname",
715 : .use_distinct = true,
716 : .refname = "r.rulename",
717 : };
718 :
719 : static const SchemaQuery Query_for_list_of_tables_for_trigger = {
720 : .catname = "pg_catalog.pg_class c, pg_catalog.pg_trigger t",
721 : .selcondition = "c.oid=t.tgrelid",
722 : .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
723 : .namespace = "c.relnamespace",
724 : .result = "c.relname",
725 : .use_distinct = true,
726 : .refname = "t.tgname",
727 : };
728 :
729 : static const SchemaQuery Query_for_list_of_ts_configurations = {
730 : .catname = "pg_catalog.pg_ts_config c",
731 : .viscondition = "pg_catalog.pg_ts_config_is_visible(c.oid)",
732 : .namespace = "c.cfgnamespace",
733 : .result = "c.cfgname",
734 : };
735 :
736 : static const SchemaQuery Query_for_list_of_ts_dictionaries = {
737 : .catname = "pg_catalog.pg_ts_dict d",
738 : .viscondition = "pg_catalog.pg_ts_dict_is_visible(d.oid)",
739 : .namespace = "d.dictnamespace",
740 : .result = "d.dictname",
741 : };
742 :
743 : static const SchemaQuery Query_for_list_of_ts_parsers = {
744 : .catname = "pg_catalog.pg_ts_parser p",
745 : .viscondition = "pg_catalog.pg_ts_parser_is_visible(p.oid)",
746 : .namespace = "p.prsnamespace",
747 : .result = "p.prsname",
748 : };
749 :
750 : static const SchemaQuery Query_for_list_of_ts_templates = {
751 : .catname = "pg_catalog.pg_ts_template t",
752 : .viscondition = "pg_catalog.pg_ts_template_is_visible(t.oid)",
753 : .namespace = "t.tmplnamespace",
754 : .result = "t.tmplname",
755 : };
756 :
757 : static const SchemaQuery Query_for_list_of_views = {
758 : .catname = "pg_catalog.pg_class c",
759 : .selcondition = "c.relkind IN (" CppAsString2(RELKIND_VIEW) ")",
760 : .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
761 : .namespace = "c.relnamespace",
762 : .result = "c.relname",
763 : };
764 :
765 : static const SchemaQuery Query_for_list_of_matviews = {
766 : .catname = "pg_catalog.pg_class c",
767 : .selcondition = "c.relkind IN (" CppAsString2(RELKIND_MATVIEW) ")",
768 : .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
769 : .namespace = "c.relnamespace",
770 : .result = "c.relname",
771 : };
772 :
773 : static const SchemaQuery Query_for_list_of_indexes = {
774 : .catname = "pg_catalog.pg_class c",
775 : .selcondition =
776 : "c.relkind IN (" CppAsString2(RELKIND_INDEX) ", "
777 : CppAsString2(RELKIND_PARTITIONED_INDEX) ")",
778 : .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
779 : .namespace = "c.relnamespace",
780 : .result = "c.relname",
781 : };
782 :
783 : static const SchemaQuery Query_for_list_of_partitioned_indexes = {
784 : .catname = "pg_catalog.pg_class c",
785 : .selcondition = "c.relkind = " CppAsString2(RELKIND_PARTITIONED_INDEX),
786 : .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
787 : .namespace = "c.relnamespace",
788 : .result = "c.relname",
789 : };
790 :
791 :
792 : /* All relations */
793 : static const SchemaQuery Query_for_list_of_relations = {
794 : .catname = "pg_catalog.pg_class c",
795 : .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
796 : .namespace = "c.relnamespace",
797 : .result = "c.relname",
798 : };
799 :
800 : /* partitioned relations */
801 : static const SchemaQuery Query_for_list_of_partitioned_relations = {
802 : .catname = "pg_catalog.pg_class c",
803 : .selcondition = "c.relkind IN (" CppAsString2(RELKIND_PARTITIONED_TABLE)
804 : ", " CppAsString2(RELKIND_PARTITIONED_INDEX) ")",
805 : .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
806 : .namespace = "c.relnamespace",
807 : .result = "c.relname",
808 : };
809 :
810 : static const SchemaQuery Query_for_list_of_operator_families = {
811 : .catname = "pg_catalog.pg_opfamily c",
812 : .viscondition = "pg_catalog.pg_opfamily_is_visible(c.oid)",
813 : .namespace = "c.opfnamespace",
814 : .result = "c.opfname",
815 : };
816 :
817 : /* Relations supporting INSERT, UPDATE or DELETE */
818 : static const SchemaQuery Query_for_list_of_updatables = {
819 : .catname = "pg_catalog.pg_class c",
820 : .selcondition =
821 : "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
822 : CppAsString2(RELKIND_FOREIGN_TABLE) ", "
823 : CppAsString2(RELKIND_VIEW) ", "
824 : CppAsString2(RELKIND_PARTITIONED_TABLE) ")",
825 : .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
826 : .namespace = "c.relnamespace",
827 : .result = "c.relname",
828 : };
829 :
830 : /* Relations supporting MERGE */
831 : static const SchemaQuery Query_for_list_of_mergetargets = {
832 : .catname = "pg_catalog.pg_class c",
833 : .selcondition =
834 : "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
835 : CppAsString2(RELKIND_PARTITIONED_TABLE) ") ",
836 : .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
837 : .namespace = "c.relnamespace",
838 : .result = "c.relname",
839 : };
840 :
841 : /* Relations supporting SELECT */
842 : static const SchemaQuery Query_for_list_of_selectables = {
843 : .catname = "pg_catalog.pg_class c",
844 : .selcondition =
845 : "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
846 : CppAsString2(RELKIND_SEQUENCE) ", "
847 : CppAsString2(RELKIND_VIEW) ", "
848 : CppAsString2(RELKIND_MATVIEW) ", "
849 : CppAsString2(RELKIND_FOREIGN_TABLE) ", "
850 : CppAsString2(RELKIND_PARTITIONED_TABLE) ")",
851 : .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
852 : .namespace = "c.relnamespace",
853 : .result = "c.relname",
854 : };
855 :
856 : /* Relations supporting TRUNCATE */
857 : static const SchemaQuery Query_for_list_of_truncatables = {
858 : .catname = "pg_catalog.pg_class c",
859 : .selcondition =
860 : "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
861 : CppAsString2(RELKIND_FOREIGN_TABLE) ", "
862 : CppAsString2(RELKIND_PARTITIONED_TABLE) ")",
863 : .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
864 : .namespace = "c.relnamespace",
865 : .result = "c.relname",
866 : };
867 :
868 : /* Relations supporting GRANT are currently same as those supporting SELECT */
869 : #define Query_for_list_of_grantables Query_for_list_of_selectables
870 :
871 : /* Relations supporting ANALYZE */
872 : static const SchemaQuery Query_for_list_of_analyzables = {
873 : .catname = "pg_catalog.pg_class c",
874 : .selcondition =
875 : "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
876 : CppAsString2(RELKIND_PARTITIONED_TABLE) ", "
877 : CppAsString2(RELKIND_MATVIEW) ", "
878 : CppAsString2(RELKIND_FOREIGN_TABLE) ")",
879 : .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
880 : .namespace = "c.relnamespace",
881 : .result = "c.relname",
882 : };
883 :
884 : /* Relations supporting index creation */
885 : static const SchemaQuery Query_for_list_of_indexables = {
886 : .catname = "pg_catalog.pg_class c",
887 : .selcondition =
888 : "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
889 : CppAsString2(RELKIND_PARTITIONED_TABLE) ", "
890 : CppAsString2(RELKIND_MATVIEW) ")",
891 : .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
892 : .namespace = "c.relnamespace",
893 : .result = "c.relname",
894 : };
895 :
896 : /*
897 : * Relations supporting VACUUM are currently same as those supporting
898 : * indexing.
899 : */
900 : #define Query_for_list_of_vacuumables Query_for_list_of_indexables
901 :
902 : /* Relations supporting CLUSTER */
903 : static const SchemaQuery Query_for_list_of_clusterables = {
904 : .catname = "pg_catalog.pg_class c",
905 : .selcondition =
906 : "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
907 : CppAsString2(RELKIND_PARTITIONED_TABLE) ", "
908 : CppAsString2(RELKIND_MATVIEW) ")",
909 : .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
910 : .namespace = "c.relnamespace",
911 : .result = "c.relname",
912 : };
913 :
914 : static const SchemaQuery Query_for_list_of_constraints_with_schema = {
915 : .catname = "pg_catalog.pg_constraint c",
916 : .selcondition = "c.conrelid <> 0",
917 : .namespace = "c.connamespace",
918 : .result = "c.conname",
919 : };
920 :
921 : static const SchemaQuery Query_for_list_of_statistics = {
922 : .catname = "pg_catalog.pg_statistic_ext s",
923 : .viscondition = "pg_catalog.pg_statistics_obj_is_visible(s.oid)",
924 : .namespace = "s.stxnamespace",
925 : .result = "s.stxname",
926 : };
927 :
928 : static const SchemaQuery Query_for_list_of_collations = {
929 : .catname = "pg_catalog.pg_collation c",
930 : .selcondition = "c.collencoding IN (-1, pg_catalog.pg_char_to_encoding(pg_catalog.getdatabaseencoding()))",
931 : .viscondition = "pg_catalog.pg_collation_is_visible(c.oid)",
932 : .namespace = "c.collnamespace",
933 : .result = "c.collname",
934 : };
935 :
936 : static const SchemaQuery Query_for_partition_of_table = {
937 : .catname = "pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_inherits i",
938 : .selcondition = "c1.oid=i.inhparent and i.inhrelid=c2.oid and c2.relispartition",
939 : .viscondition = "pg_catalog.pg_table_is_visible(c2.oid)",
940 : .namespace = "c2.relnamespace",
941 : .result = "c2.relname",
942 : .refname = "c1.relname",
943 : .refviscondition = "pg_catalog.pg_table_is_visible(c1.oid)",
944 : .refnamespace = "c1.relnamespace",
945 : };
946 :
947 : static const SchemaQuery Query_for_rule_of_table = {
948 : .catname = "pg_catalog.pg_rewrite r, pg_catalog.pg_class c1",
949 : .selcondition = "r.ev_class=c1.oid",
950 : .result = "r.rulename",
951 : .refname = "c1.relname",
952 : .refviscondition = "pg_catalog.pg_table_is_visible(c1.oid)",
953 : .refnamespace = "c1.relnamespace",
954 : };
955 :
956 : static const SchemaQuery Query_for_trigger_of_table = {
957 : .catname = "pg_catalog.pg_trigger t, pg_catalog.pg_class c1",
958 : .selcondition = "t.tgrelid=c1.oid and not t.tgisinternal",
959 : .result = "t.tgname",
960 : .refname = "c1.relname",
961 : .refviscondition = "pg_catalog.pg_table_is_visible(c1.oid)",
962 : .refnamespace = "c1.relnamespace",
963 : };
964 :
965 :
966 : /*
967 : * Queries to get lists of names of various kinds of things, possibly
968 : * restricted to names matching a partially entered name. Don't use
969 : * this method where the user might wish to enter a schema-qualified
970 : * name; make a SchemaQuery instead.
971 : *
972 : * In these queries, there must be a restriction clause of the form
973 : * output LIKE '%s'
974 : * where "output" is the same string that the query returns. The %s
975 : * will be replaced by a LIKE pattern to match the already-typed text.
976 : *
977 : * There can be a second '%s', which will be replaced by a suitably-escaped
978 : * version of the string provided in completion_ref_object. If there is a
979 : * third '%s', it will be replaced by a suitably-escaped version of the string
980 : * provided in completion_ref_schema. NOTE: using completion_ref_object
981 : * that way is usually the wrong thing, and using completion_ref_schema
982 : * that way is always the wrong thing. Make a SchemaQuery instead.
983 : */
984 :
985 : #define Query_for_list_of_template_databases \
986 : "SELECT d.datname "\
987 : " FROM pg_catalog.pg_database d "\
988 : " WHERE d.datname LIKE '%s' "\
989 : " AND (d.datistemplate OR pg_catalog.pg_has_role(d.datdba, 'USAGE'))"
990 :
991 : #define Query_for_list_of_databases \
992 : "SELECT datname FROM pg_catalog.pg_database "\
993 : " WHERE datname LIKE '%s'"
994 :
995 : #define Query_for_list_of_tablespaces \
996 : "SELECT spcname FROM pg_catalog.pg_tablespace "\
997 : " WHERE spcname LIKE '%s'"
998 :
999 : #define Query_for_list_of_encodings \
1000 : " SELECT DISTINCT pg_catalog.pg_encoding_to_char(conforencoding) "\
1001 : " FROM pg_catalog.pg_conversion "\
1002 : " WHERE pg_catalog.pg_encoding_to_char(conforencoding) LIKE pg_catalog.upper('%s')"
1003 :
1004 : #define Query_for_list_of_languages \
1005 : "SELECT lanname "\
1006 : " FROM pg_catalog.pg_language "\
1007 : " WHERE lanname != 'internal' "\
1008 : " AND lanname LIKE '%s'"
1009 :
1010 : #define Query_for_list_of_schemas \
1011 : "SELECT nspname FROM pg_catalog.pg_namespace "\
1012 : " WHERE nspname LIKE '%s'"
1013 :
1014 : /* Use COMPLETE_WITH_QUERY_VERBATIM with these queries for GUC names: */
1015 : #define Query_for_list_of_alter_system_set_vars \
1016 : "SELECT pg_catalog.lower(name) FROM pg_catalog.pg_settings "\
1017 : " WHERE context != 'internal' "\
1018 : " AND pg_catalog.lower(name) LIKE pg_catalog.lower('%s')"
1019 :
1020 : #define Query_for_list_of_set_vars \
1021 : "SELECT pg_catalog.lower(name) FROM pg_catalog.pg_settings "\
1022 : " WHERE context IN ('user', 'superuser') "\
1023 : " AND pg_catalog.lower(name) LIKE pg_catalog.lower('%s')"
1024 :
1025 : #define Query_for_list_of_show_vars \
1026 : "SELECT pg_catalog.lower(name) FROM pg_catalog.pg_settings "\
1027 : " WHERE pg_catalog.lower(name) LIKE pg_catalog.lower('%s')"
1028 :
1029 : #define Query_for_list_of_roles \
1030 : " SELECT rolname "\
1031 : " FROM pg_catalog.pg_roles "\
1032 : " WHERE rolname LIKE '%s'"
1033 :
1034 : /* add these to Query_for_list_of_roles in GRANT contexts */
1035 : #define Keywords_for_list_of_grant_roles \
1036 : "PUBLIC", "CURRENT_ROLE", "CURRENT_USER", "SESSION_USER"
1037 :
1038 : #define Query_for_all_table_constraints \
1039 : "SELECT conname "\
1040 : " FROM pg_catalog.pg_constraint c "\
1041 : " WHERE c.conrelid <> 0 "\
1042 : " and conname LIKE '%s'"
1043 :
1044 : #define Query_for_list_of_fdws \
1045 : " SELECT fdwname "\
1046 : " FROM pg_catalog.pg_foreign_data_wrapper "\
1047 : " WHERE fdwname LIKE '%s'"
1048 :
1049 : #define Query_for_list_of_servers \
1050 : " SELECT srvname "\
1051 : " FROM pg_catalog.pg_foreign_server "\
1052 : " WHERE srvname LIKE '%s'"
1053 :
1054 : #define Query_for_list_of_user_mappings \
1055 : " SELECT usename "\
1056 : " FROM pg_catalog.pg_user_mappings "\
1057 : " WHERE usename LIKE '%s'"
1058 :
1059 : #define Query_for_list_of_access_methods \
1060 : " SELECT amname "\
1061 : " FROM pg_catalog.pg_am "\
1062 : " WHERE amname LIKE '%s'"
1063 :
1064 : #define Query_for_list_of_index_access_methods \
1065 : " SELECT amname "\
1066 : " FROM pg_catalog.pg_am "\
1067 : " WHERE amname LIKE '%s' AND "\
1068 : " amtype=" CppAsString2(AMTYPE_INDEX)
1069 :
1070 : #define Query_for_list_of_table_access_methods \
1071 : " SELECT amname "\
1072 : " FROM pg_catalog.pg_am "\
1073 : " WHERE amname LIKE '%s' AND "\
1074 : " amtype=" CppAsString2(AMTYPE_TABLE)
1075 :
1076 : #define Query_for_list_of_extensions \
1077 : " SELECT extname "\
1078 : " FROM pg_catalog.pg_extension "\
1079 : " WHERE extname LIKE '%s'"
1080 :
1081 : #define Query_for_list_of_available_extensions \
1082 : " SELECT name "\
1083 : " FROM pg_catalog.pg_available_extensions "\
1084 : " WHERE name LIKE '%s' AND installed_version IS NULL"
1085 :
1086 : #define Query_for_list_of_available_extension_versions \
1087 : " SELECT version "\
1088 : " FROM pg_catalog.pg_available_extension_versions "\
1089 : " WHERE version LIKE '%s' AND name='%s'"
1090 :
1091 : #define Query_for_list_of_prepared_statements \
1092 : " SELECT name "\
1093 : " FROM pg_catalog.pg_prepared_statements "\
1094 : " WHERE name LIKE '%s'"
1095 :
1096 : #define Query_for_list_of_event_triggers \
1097 : " SELECT evtname "\
1098 : " FROM pg_catalog.pg_event_trigger "\
1099 : " WHERE evtname LIKE '%s'"
1100 :
1101 : #define Query_for_list_of_tablesample_methods \
1102 : " SELECT proname "\
1103 : " FROM pg_catalog.pg_proc "\
1104 : " WHERE prorettype = 'pg_catalog.tsm_handler'::pg_catalog.regtype AND "\
1105 : " proargtypes[0] = 'pg_catalog.internal'::pg_catalog.regtype AND "\
1106 : " proname LIKE '%s'"
1107 :
1108 : #define Query_for_list_of_policies \
1109 : " SELECT polname "\
1110 : " FROM pg_catalog.pg_policy "\
1111 : " WHERE polname LIKE '%s'"
1112 :
1113 : #define Query_for_values_of_enum_GUC \
1114 : " SELECT val FROM ( "\
1115 : " SELECT name, pg_catalog.unnest(enumvals) AS val "\
1116 : " FROM pg_catalog.pg_settings "\
1117 : " ) ss "\
1118 : " WHERE val LIKE '%s'"\
1119 : " and pg_catalog.lower(name)=pg_catalog.lower('%s')"
1120 :
1121 : #define Query_for_list_of_channels \
1122 : " SELECT channel "\
1123 : " FROM pg_catalog.pg_listening_channels() AS channel "\
1124 : " WHERE channel LIKE '%s'"
1125 :
1126 : #define Query_for_list_of_cursors \
1127 : " SELECT name "\
1128 : " FROM pg_catalog.pg_cursors "\
1129 : " WHERE name LIKE '%s'"
1130 :
1131 : #define Query_for_list_of_timezone_names_unquoted \
1132 : " SELECT name "\
1133 : " FROM pg_catalog.pg_timezone_names() "\
1134 : " WHERE pg_catalog.lower(name) LIKE pg_catalog.lower('%s')"
1135 :
1136 : #define Query_for_list_of_timezone_names_quoted_out \
1137 : "SELECT pg_catalog.quote_literal(name) AS name "\
1138 : " FROM pg_catalog.pg_timezone_names() "\
1139 : " WHERE pg_catalog.lower(name) LIKE pg_catalog.lower('%s')"
1140 :
1141 : #define Query_for_list_of_timezone_names_quoted_in \
1142 : "SELECT pg_catalog.quote_literal(name) AS name "\
1143 : " FROM pg_catalog.pg_timezone_names() "\
1144 : " WHERE pg_catalog.quote_literal(pg_catalog.lower(name)) LIKE pg_catalog.lower('%s')"
1145 :
1146 : /* Privilege options shared between GRANT and REVOKE */
1147 : #define Privilege_options_of_grant_and_revoke \
1148 : "SELECT", "INSERT", "UPDATE", "DELETE", "TRUNCATE", "REFERENCES", "TRIGGER", \
1149 : "CREATE", "CONNECT", "TEMPORARY", "EXECUTE", "USAGE", "SET", "ALTER SYSTEM", \
1150 : "MAINTAIN", "ALL"
1151 :
1152 : /* ALTER PROCEDURE options */
1153 : #define Alter_procedure_options \
1154 : "DEPENDS ON EXTENSION", "EXTERNAL SECURITY", "NO DEPENDS ON EXTENSION", \
1155 : "OWNER TO", "RENAME TO", "RESET", "SECURITY", "SET"
1156 :
1157 : /* ALTER ROUTINE options */
1158 : #define Alter_routine_options \
1159 : Alter_procedure_options, "COST", "IMMUTABLE", "LEAKPROOF", "NOT LEAKPROOF", \
1160 : "PARALLEL", "ROWS", "STABLE", "VOLATILE"
1161 :
1162 : /* ALTER FUNCTION options */
1163 : #define Alter_function_options \
1164 : Alter_routine_options, "CALLED ON NULL INPUT", "RETURNS NULL ON NULL INPUT", \
1165 : "STRICT", "SUPPORT"
1166 :
1167 : /*
1168 : * These object types were introduced later than our support cutoff of
1169 : * server version 9.2. We use the VersionedQuery infrastructure so that
1170 : * we don't send certain-to-fail queries to older servers.
1171 : */
1172 :
1173 : static const VersionedQuery Query_for_list_of_publications[] = {
1174 : {100000,
1175 : " SELECT pubname "
1176 : " FROM pg_catalog.pg_publication "
1177 : " WHERE pubname LIKE '%s'"
1178 : },
1179 : {0, NULL}
1180 : };
1181 :
1182 : static const VersionedQuery Query_for_list_of_subscriptions[] = {
1183 : {100000,
1184 : " SELECT s.subname "
1185 : " FROM pg_catalog.pg_subscription s, pg_catalog.pg_database d "
1186 : " WHERE s.subname LIKE '%s' "
1187 : " AND d.datname = pg_catalog.current_database() "
1188 : " AND s.subdbid = d.oid"
1189 : },
1190 : {0, NULL}
1191 : };
1192 :
1193 : /*
1194 : * This is a list of all "things" in Pgsql, which can show up after CREATE or
1195 : * DROP; and there is also a query to get a list of them.
1196 : */
1197 :
1198 : typedef struct
1199 : {
1200 : const char *name;
1201 : /* Provide at most one of these three types of query: */
1202 : const char *query; /* simple query, or NULL */
1203 : const VersionedQuery *vquery; /* versioned query, or NULL */
1204 : const SchemaQuery *squery; /* schema query, or NULL */
1205 : const char *const *keywords; /* keywords to be offered as well */
1206 : const bits32 flags; /* visibility flags, see below */
1207 : } pgsql_thing_t;
1208 :
1209 : #define THING_NO_CREATE (1 << 0) /* should not show up after CREATE */
1210 : #define THING_NO_DROP (1 << 1) /* should not show up after DROP */
1211 : #define THING_NO_ALTER (1 << 2) /* should not show up after ALTER */
1212 : #define THING_NO_SHOW (THING_NO_CREATE | THING_NO_DROP | THING_NO_ALTER)
1213 :
1214 : /* When we have DROP USER etc, also offer MAPPING FOR */
1215 : static const char *const Keywords_for_user_thing[] = {
1216 : "MAPPING FOR",
1217 : NULL
1218 : };
1219 :
1220 : static const pgsql_thing_t words_after_create[] = {
1221 : {"ACCESS METHOD", NULL, NULL, NULL, NULL, THING_NO_ALTER},
1222 : {"AGGREGATE", NULL, NULL, Query_for_list_of_aggregates},
1223 : {"CAST", NULL, NULL, NULL}, /* Casts have complex structures for names, so
1224 : * skip it */
1225 : {"COLLATION", NULL, NULL, &Query_for_list_of_collations},
1226 :
1227 : /*
1228 : * CREATE CONSTRAINT TRIGGER is not supported here because it is designed
1229 : * to be used only by pg_dump.
1230 : */
1231 : {"CONFIGURATION", NULL, NULL, &Query_for_list_of_ts_configurations, NULL, THING_NO_SHOW},
1232 : {"CONVERSION", "SELECT conname FROM pg_catalog.pg_conversion WHERE conname LIKE '%s'"},
1233 : {"DATABASE", Query_for_list_of_databases},
1234 : {"DEFAULT PRIVILEGES", NULL, NULL, NULL, NULL, THING_NO_CREATE | THING_NO_DROP},
1235 : {"DICTIONARY", NULL, NULL, &Query_for_list_of_ts_dictionaries, NULL, THING_NO_SHOW},
1236 : {"DOMAIN", NULL, NULL, &Query_for_list_of_domains},
1237 : {"EVENT TRIGGER", NULL, NULL, NULL},
1238 : {"EXTENSION", Query_for_list_of_extensions},
1239 : {"FOREIGN DATA WRAPPER", NULL, NULL, NULL},
1240 : {"FOREIGN TABLE", NULL, NULL, NULL},
1241 : {"FUNCTION", NULL, NULL, Query_for_list_of_functions},
1242 : {"GROUP", Query_for_list_of_roles},
1243 : {"INDEX", NULL, NULL, &Query_for_list_of_indexes},
1244 : {"LANGUAGE", Query_for_list_of_languages},
1245 : {"LARGE OBJECT", NULL, NULL, NULL, NULL, THING_NO_CREATE | THING_NO_DROP},
1246 : {"MATERIALIZED VIEW", NULL, NULL, &Query_for_list_of_matviews},
1247 : {"OPERATOR", NULL, NULL, NULL}, /* Querying for this is probably not such
1248 : * a good idea. */
1249 : {"OR REPLACE", NULL, NULL, NULL, NULL, THING_NO_DROP | THING_NO_ALTER},
1250 : {"OWNED", NULL, NULL, NULL, NULL, THING_NO_CREATE | THING_NO_ALTER}, /* for DROP OWNED BY ... */
1251 : {"PARSER", NULL, NULL, &Query_for_list_of_ts_parsers, NULL, THING_NO_SHOW},
1252 : {"POLICY", NULL, NULL, NULL},
1253 : {"PROCEDURE", NULL, NULL, Query_for_list_of_procedures},
1254 : {"PUBLICATION", NULL, Query_for_list_of_publications},
1255 : {"ROLE", Query_for_list_of_roles},
1256 : {"ROUTINE", NULL, NULL, &Query_for_list_of_routines, NULL, THING_NO_CREATE},
1257 : {"RULE", "SELECT rulename FROM pg_catalog.pg_rules WHERE rulename LIKE '%s'"},
1258 : {"SCHEMA", Query_for_list_of_schemas},
1259 : {"SEQUENCE", NULL, NULL, &Query_for_list_of_sequences},
1260 : {"SERVER", Query_for_list_of_servers},
1261 : {"STATISTICS", NULL, NULL, &Query_for_list_of_statistics},
1262 : {"SUBSCRIPTION", NULL, Query_for_list_of_subscriptions},
1263 : {"SYSTEM", NULL, NULL, NULL, NULL, THING_NO_CREATE | THING_NO_DROP},
1264 : {"TABLE", NULL, NULL, &Query_for_list_of_tables},
1265 : {"TABLESPACE", Query_for_list_of_tablespaces},
1266 : {"TEMP", NULL, NULL, NULL, NULL, THING_NO_DROP | THING_NO_ALTER}, /* for CREATE TEMP TABLE
1267 : * ... */
1268 : {"TEMPLATE", NULL, NULL, &Query_for_list_of_ts_templates, NULL, THING_NO_SHOW},
1269 : {"TEMPORARY", NULL, NULL, NULL, NULL, THING_NO_DROP | THING_NO_ALTER}, /* for CREATE TEMPORARY
1270 : * TABLE ... */
1271 : {"TEXT SEARCH", NULL, NULL, NULL},
1272 : {"TRANSFORM", NULL, NULL, NULL, NULL, THING_NO_ALTER},
1273 : {"TRIGGER", "SELECT tgname FROM pg_catalog.pg_trigger WHERE tgname LIKE '%s' AND NOT tgisinternal"},
1274 : {"TYPE", NULL, NULL, &Query_for_list_of_datatypes},
1275 : {"UNIQUE", NULL, NULL, NULL, NULL, THING_NO_DROP | THING_NO_ALTER}, /* for CREATE UNIQUE
1276 : * INDEX ... */
1277 : {"UNLOGGED", NULL, NULL, NULL, NULL, THING_NO_DROP | THING_NO_ALTER}, /* for CREATE UNLOGGED
1278 : * TABLE ... */
1279 : {"USER", Query_for_list_of_roles, NULL, NULL, Keywords_for_user_thing},
1280 : {"USER MAPPING FOR", NULL, NULL, NULL},
1281 : {"VIEW", NULL, NULL, &Query_for_list_of_views},
1282 : {NULL} /* end of list */
1283 : };
1284 :
1285 : /* Storage parameters for CREATE TABLE and ALTER TABLE */
1286 : static const char *const table_storage_parameters[] = {
1287 : "autovacuum_analyze_scale_factor",
1288 : "autovacuum_analyze_threshold",
1289 : "autovacuum_enabled",
1290 : "autovacuum_freeze_max_age",
1291 : "autovacuum_freeze_min_age",
1292 : "autovacuum_freeze_table_age",
1293 : "autovacuum_multixact_freeze_max_age",
1294 : "autovacuum_multixact_freeze_min_age",
1295 : "autovacuum_multixact_freeze_table_age",
1296 : "autovacuum_vacuum_cost_delay",
1297 : "autovacuum_vacuum_cost_limit",
1298 : "autovacuum_vacuum_insert_scale_factor",
1299 : "autovacuum_vacuum_insert_threshold",
1300 : "autovacuum_vacuum_scale_factor",
1301 : "autovacuum_vacuum_threshold",
1302 : "fillfactor",
1303 : "log_autovacuum_min_duration",
1304 : "parallel_workers",
1305 : "toast.autovacuum_enabled",
1306 : "toast.autovacuum_freeze_max_age",
1307 : "toast.autovacuum_freeze_min_age",
1308 : "toast.autovacuum_freeze_table_age",
1309 : "toast.autovacuum_multixact_freeze_max_age",
1310 : "toast.autovacuum_multixact_freeze_min_age",
1311 : "toast.autovacuum_multixact_freeze_table_age",
1312 : "toast.autovacuum_vacuum_cost_delay",
1313 : "toast.autovacuum_vacuum_cost_limit",
1314 : "toast.autovacuum_vacuum_insert_scale_factor",
1315 : "toast.autovacuum_vacuum_insert_threshold",
1316 : "toast.autovacuum_vacuum_scale_factor",
1317 : "toast.autovacuum_vacuum_threshold",
1318 : "toast.log_autovacuum_min_duration",
1319 : "toast.vacuum_index_cleanup",
1320 : "toast.vacuum_truncate",
1321 : "toast_tuple_target",
1322 : "user_catalog_table",
1323 : "vacuum_index_cleanup",
1324 : "vacuum_truncate",
1325 : NULL
1326 : };
1327 :
1328 :
1329 : /* Forward declaration of functions */
1330 : static char **psql_completion(const char *text, int start, int end);
1331 : static char *create_command_generator(const char *text, int state);
1332 : static char *drop_command_generator(const char *text, int state);
1333 : static char *alter_command_generator(const char *text, int state);
1334 : static char *complete_from_query(const char *text, int state);
1335 : static char *complete_from_versioned_query(const char *text, int state);
1336 : static char *complete_from_schema_query(const char *text, int state);
1337 : static char *complete_from_versioned_schema_query(const char *text, int state);
1338 : static char *_complete_from_query(const char *simple_query,
1339 : const SchemaQuery *schema_query,
1340 : const char *const *keywords,
1341 : bool verbatim,
1342 : const char *text, int state);
1343 : static void set_completion_reference(const char *word);
1344 : static void set_completion_reference_verbatim(const char *word);
1345 : static char *complete_from_list(const char *text, int state);
1346 : static char *complete_from_const(const char *text, int state);
1347 : static void append_variable_names(char ***varnames, int *nvars,
1348 : int *maxvars, const char *varname,
1349 : const char *prefix, const char *suffix);
1350 : static char **complete_from_variables(const char *text,
1351 : const char *prefix, const char *suffix, bool need_value);
1352 : static char *complete_from_files(const char *text, int state);
1353 :
1354 : static char *pg_strdup_keyword_case(const char *s, const char *ref);
1355 : static char *escape_string(const char *text);
1356 : static char *make_like_pattern(const char *word);
1357 : static void parse_identifier(const char *ident,
1358 : char **schemaname, char **objectname,
1359 : bool *schemaquoted, bool *objectquoted);
1360 : static char *requote_identifier(const char *schemaname, const char *objectname,
1361 : bool quote_schema, bool quote_object);
1362 : static bool identifier_needs_quotes(const char *ident);
1363 : static PGresult *exec_query(const char *query);
1364 :
1365 : static char **get_previous_words(int point, char **buffer, int *nwords);
1366 :
1367 : static char *get_guctype(const char *varname);
1368 :
1369 : #ifdef USE_FILENAME_QUOTING_FUNCTIONS
1370 : static char *quote_file_name(char *fname, int match_type, char *quote_pointer);
1371 : static char *dequote_file_name(char *fname, int quote_char);
1372 : #endif
1373 :
1374 :
1375 : /*
1376 : * Initialize the readline library for our purposes.
1377 : */
1378 : void
7101 tgl 1379 GIC 2 : initialize_readline(void)
1380 : {
6797 bruce 1381 2 : rl_readline_name = (char *) pset.progname;
3292 rhaas 1382 2 : rl_attempted_completion_function = psql_completion;
1383 :
1384 : #ifdef USE_FILENAME_QUOTING_FUNCTIONS
1172 tgl 1385 2 : rl_filename_quoting_function = quote_file_name;
1386 2 : rl_filename_dequoting_function = dequote_file_name;
1387 : #endif
1388 :
4799 itagaki.takahiro 1389 2 : rl_basic_word_break_characters = WORD_BREAKS;
1390 :
1391 : /*
1392 : * Ideally we'd include '"' in rl_completer_quote_characters too, which
1393 : * should allow us to complete quoted identifiers that include spaces.
1394 : * However, the library support for rl_completer_quote_characters is
1395 : * presently too inconsistent to want to mess with that. (Note in
1396 : * particular that libedit has this variable but completely ignores it.)
1397 : */
1172 tgl 1398 2 : rl_completer_quote_characters = "'";
1399 :
1172 tgl 1400 ECB : /*
1401 : * Set rl_filename_quote_characters to "all possible characters",
1402 : * otherwise Readline will skip filename quoting if it thinks a filename
1403 : * doesn't need quoting. Readline actually interprets this as bytes, so
1404 : * there are no encoding considerations here.
1405 : */
1406 : #ifdef HAVE_RL_FILENAME_QUOTE_CHARACTERS
1407 : {
1172 tgl 1408 GIC 2 : unsigned char *fqc = (unsigned char *) pg_malloc(256);
1409 :
1172 tgl 1410 CBC 512 : for (int i = 0; i < 255; i++)
1172 tgl 1411 GIC 510 : fqc[i] = (unsigned char) (i + 1);
1412 2 : fqc[255] = '\0';
1413 2 : rl_filename_quote_characters = (const char *) fqc;
1414 : }
1415 : #endif
1416 :
7101 1417 2 : completion_max_records = 1000;
1418 :
7101 tgl 1419 ECB : /*
1420 : * There is a variable rl_completion_query_items for this but apparently
1421 : * it's not defined everywhere.
1422 : */
7101 tgl 1423 GIC 2 : }
1424 :
1425 : /*
1426 : * Check if 'word' matches any of the '|'-separated strings in 'pattern',
1427 : * using case-insensitive or case-sensitive comparisons.
1428 : *
2668 tgl 1429 ECB : * If pattern is NULL, it's a wild card that matches any word.
1430 : * If pattern begins with '!', the result is negated, ie we check that 'word'
1431 : * does *not* match any alternative appearing in the rest of 'pattern'.
1661 1432 : * Any alternative can contain '*' which is a wild card, i.e., it can match
1433 : * any substring; however, we allow at most one '*' per alternative.
2668 1434 : *
1435 : * For readability, callers should use the macros MatchAny and MatchAnyExcept
1436 : * to invoke those two special cases for 'pattern'. (But '|' and '*' must
1437 : * just be written directly in patterns.)
1438 : */
1439 : #define MatchAny NULL
1440 : #define MatchAnyExcept(pattern) ("!" pattern)
1441 :
1442 : static bool
1661 tgl 1443 GIC 8924 : word_matches(const char *pattern,
1661 tgl 1444 ECB : const char *word,
1445 : bool case_sensitive)
1446 : {
1447 : size_t wordlen;
1448 :
1449 : #define cimatch(s1, s2, n) \
1450 : (case_sensitive ? strncmp(s1, s2, n) == 0 : pg_strncasecmp(s1, s2, n) == 0)
1451 :
1452 : /* NULL pattern matches anything. */
2668 tgl 1453 GIC 8924 : if (pattern == NULL)
1454 160 : return true;
1455 :
1456 : /* Handle negated patterns from the MatchAnyExcept macro. */
1457 8764 : if (*pattern == '!')
1661 tgl 1458 UIC 0 : return !word_matches(pattern + 1, word, case_sensitive);
1459 :
1460 : /* Else consider each alternative in the pattern. */
2668 tgl 1461 GIC 8764 : wordlen = strlen(word);
1462 : for (;;)
1463 764 : {
1661 tgl 1464 CBC 9528 : const char *star = NULL;
1465 : const char *c;
1466 :
1467 : /* Find end of current alternative, and locate any wild card. */
2668 tgl 1468 GIC 9528 : c = pattern;
1469 64171 : while (*c != '\0' && *c != '|')
1470 : {
1661 1471 54643 : if (*c == '*')
1472 397 : star = c;
2668 1473 54643 : c++;
1661 tgl 1474 ECB : }
1475 : /* Was there a wild card? */
1661 tgl 1476 GIC 9528 : if (star)
1477 : {
2651 tgl 1478 ECB : /* Yes, wildcard match? */
1661 tgl 1479 GBC 397 : size_t beforelen = star - pattern,
1661 tgl 1480 GIC 397 : afterlen = c - star - 1;
1481 :
1661 tgl 1482 CBC 786 : if (wordlen >= (beforelen + afterlen) &&
1661 tgl 1483 GIC 401 : cimatch(word, pattern, beforelen) &&
1661 tgl 1484 CBC 6 : cimatch(word + wordlen - afterlen, star + 1, afterlen))
2651 1485 6 : return true;
1486 : }
1487 : else
1488 : {
2651 tgl 1489 ECB : /* No, plain match? */
1661 tgl 1490 CBC 11593 : if (wordlen == (c - pattern) &&
1661 tgl 1491 GIC 2462 : cimatch(word, pattern, wordlen))
2651 tgl 1492 CBC 1277 : return true;
2651 tgl 1493 ECB : }
2668 1494 : /* Out of alternatives? */
2668 tgl 1495 GIC 8245 : if (*c == '\0')
1496 7481 : break;
2668 tgl 1497 ECB : /* Nope, try next alternative. */
2668 tgl 1498 GIC 764 : pattern = c + 1;
1499 : }
2668 tgl 1500 ECB :
2668 tgl 1501 CBC 7481 : return false;
1502 : }
2668 tgl 1503 ECB :
2651 1504 : /*
1661 1505 : * Implementation of TailMatches and TailMatchesCS macros: do the last N words
1506 : * in previous_words match the variadic arguments?
1507 : *
1508 : * The array indexing might look backwards, but remember that
1509 : * previous_words[0] contains the *last* word on the line, not the first.
1510 : */
2651 1511 : static bool
1661 tgl 1512 CBC 6537 : TailMatchesImpl(bool case_sensitive,
1661 tgl 1513 ECB : int previous_words_count, char **previous_words,
1514 : int narg,...)
1515 : {
1516 : va_list args;
1517 :
1661 tgl 1518 GIC 6537 : if (previous_words_count < narg)
1661 tgl 1519 CBC 4437 : return false;
1520 :
1661 tgl 1521 GIC 2100 : va_start(args, narg);
1661 tgl 1522 ECB :
1661 tgl 1523 GIC 2183 : for (int argno = 0; argno < narg; argno++)
1524 : {
1525 2150 : const char *arg = va_arg(args, const char *);
1526 :
1527 2150 : if (!word_matches(arg, previous_words[narg - argno - 1],
1528 : case_sensitive))
1529 : {
1530 2067 : va_end(args);
1531 2067 : return false;
1532 : }
1661 tgl 1533 ECB : }
1534 :
1661 tgl 1535 GIC 33 : va_end(args);
1536 :
1537 33 : return true;
1538 : }
2651 tgl 1539 ECB :
1540 : /*
1541 : * Implementation of Matches and MatchesCS macros: do all of the words
1661 1542 : * in previous_words match the variadic arguments?
1543 : */
2651 1544 : static bool
1661 tgl 1545 GIC 21442 : MatchesImpl(bool case_sensitive,
1661 tgl 1546 ECB : int previous_words_count, char **previous_words,
1547 : int narg,...)
2651 1548 : {
1549 : va_list args;
1550 :
1661 tgl 1551 CBC 21442 : if (previous_words_count != narg)
1552 18095 : return false;
1553 :
1661 tgl 1554 GIC 3347 : va_start(args, narg);
1555 :
1661 tgl 1556 CBC 4469 : for (int argno = 0; argno < narg; argno++)
1557 : {
1558 4441 : const char *arg = va_arg(args, const char *);
1559 :
1661 tgl 1560 GIC 4441 : if (!word_matches(arg, previous_words[narg - argno - 1],
1561 : case_sensitive))
1562 : {
1563 3319 : va_end(args);
1564 3319 : return false;
1565 : }
1661 tgl 1566 ECB : }
1567 :
1661 tgl 1568 GIC 28 : va_end(args);
1569 :
1570 28 : return true;
1571 : }
1661 tgl 1572 ECB :
1573 : /*
1574 : * Implementation of HeadMatches and HeadMatchesCS macros: do the first N
1575 : * words in previous_words match the variadic arguments?
1576 : */
1577 : static bool
1661 tgl 1578 GIC 3294 : HeadMatchesImpl(bool case_sensitive,
1661 tgl 1579 ECB : int previous_words_count, char **previous_words,
1580 : int narg,...)
1581 : {
1582 : va_list args;
1583 :
1661 tgl 1584 CBC 3294 : if (previous_words_count < narg)
1585 1197 : return false;
1586 :
1661 tgl 1587 GIC 2097 : va_start(args, narg);
1588 :
1661 tgl 1589 CBC 2335 : for (int argno = 0; argno < narg; argno++)
1590 : {
1591 2333 : const char *arg = va_arg(args, const char *);
1592 :
1661 tgl 1593 GIC 2333 : if (!word_matches(arg, previous_words[previous_words_count - argno - 1],
1594 : case_sensitive))
1595 : {
1596 2095 : va_end(args);
1597 2095 : return false;
1598 : }
1661 tgl 1599 ECB : }
1600 :
1661 tgl 1601 GIC 2 : va_end(args);
1602 :
1603 2 : return true;
1604 : }
2651 tgl 1605 ECB :
2668 1606 : /*
1607 : * Check if the final character of 's' is 'c'.
1608 : */
1609 : static bool
2668 tgl 1610 CBC 2 : ends_with(const char *s, char c)
1611 : {
1612 2 : size_t length = strlen(s);
1613 :
1614 2 : return (length > 0 && s[length - 1] == c);
1615 : }
1616 :
4564 tgl 1617 ECB : /*
1618 : * The completion function.
1619 : *
1620 : * According to readline spec this gets passed the text entered so far and its
1621 : * start and end positions in the readline buffer. The return value is some
1622 : * partially obscure list format that can be generated by readline's
1623 : * rl_completion_matches() function, so we don't have to worry about it.
1624 : */
1625 : static char **
3292 rhaas 1626 GIC 66 : psql_completion(const char *text, int start, int end)
1627 : {
1628 : /* This is the variable we'll return. */
8397 bruce 1629 66 : char **matches = NULL;
1630 :
2667 tgl 1631 ECB : /* Workspace for parsed words. */
1632 : char *words_buffer;
1633 :
1634 : /* This array will contain pointers to parsed words. */
1635 : char **previous_words;
1636 :
1637 : /* The number of words found on the input line. */
1638 : int previous_words_count;
1639 :
1640 : /*
1641 : * For compactness, we use these macros to reference previous_words[].
1642 : * Caution: do not access a previous_words[] entry without having checked
1643 : * previous_words_count to be sure it's valid. In most cases below, that
1644 : * check is implicit in a TailMatches() or similar macro, but in some
1645 : * places we have to check it explicitly.
1646 : */
4189 1647 : #define prev_wd (previous_words[0])
1648 : #define prev2_wd (previous_words[1])
1649 : #define prev3_wd (previous_words[2])
1650 : #define prev4_wd (previous_words[3])
1651 : #define prev5_wd (previous_words[4])
1652 : #define prev6_wd (previous_words[5])
1653 : #define prev7_wd (previous_words[6])
1654 : #define prev8_wd (previous_words[7])
1655 : #define prev9_wd (previous_words[8])
1656 :
1657 : /* Match the last N words before point, case-insensitively. */
1658 : #define TailMatches(...) \
1659 : TailMatchesImpl(false, previous_words_count, previous_words, \
1660 : VA_ARGS_NARGS(__VA_ARGS__), __VA_ARGS__)
1661 :
1662 : /* Match the last N words before point, case-sensitively. */
1663 : #define TailMatchesCS(...) \
1664 : TailMatchesImpl(true, previous_words_count, previous_words, \
1665 : VA_ARGS_NARGS(__VA_ARGS__), __VA_ARGS__)
1666 :
1667 : /* Match N words representing all of the line, case-insensitively. */
1668 : #define Matches(...) \
1669 : MatchesImpl(false, previous_words_count, previous_words, \
1670 : VA_ARGS_NARGS(__VA_ARGS__), __VA_ARGS__)
1671 :
1672 : /* Match N words representing all of the line, case-sensitively. */
1673 : #define MatchesCS(...) \
1674 : MatchesImpl(true, previous_words_count, previous_words, \
1675 : VA_ARGS_NARGS(__VA_ARGS__), __VA_ARGS__)
1676 :
1677 : /* Match the first N words on the line, case-insensitively. */
1678 : #define HeadMatches(...) \
1679 : HeadMatchesImpl(false, previous_words_count, previous_words, \
1680 : VA_ARGS_NARGS(__VA_ARGS__), __VA_ARGS__)
1681 :
1682 : /* Match the first N words on the line, case-sensitively. */
1683 : #define HeadMatchesCS(...) \
1684 : HeadMatchesImpl(true, previous_words_count, previous_words, \
1685 : VA_ARGS_NARGS(__VA_ARGS__), __VA_ARGS__)
1686 :
1687 : /* Known command-starting keywords. */
1688 : static const char *const sql_commands[] = {
1689 : "ABORT", "ALTER", "ANALYZE", "BEGIN", "CALL", "CHECKPOINT", "CLOSE", "CLUSTER",
1690 : "COMMENT", "COMMIT", "COPY", "CREATE", "DEALLOCATE", "DECLARE",
1691 : "DELETE FROM", "DISCARD", "DO", "DROP", "END", "EXECUTE", "EXPLAIN",
1692 : "FETCH", "GRANT", "IMPORT FOREIGN SCHEMA", "INSERT INTO", "LISTEN", "LOAD", "LOCK",
1693 : "MERGE INTO", "MOVE", "NOTIFY", "PREPARE",
1694 : "REASSIGN", "REFRESH MATERIALIZED VIEW", "REINDEX", "RELEASE",
1695 : "RESET", "REVOKE", "ROLLBACK",
1696 : "SAVEPOINT", "SECURITY LABEL", "SELECT", "SET", "SHOW", "START",
1697 : "TABLE", "TRUNCATE", "UNLISTEN", "UPDATE", "VACUUM", "VALUES", "WITH",
1698 : NULL
1699 : };
1700 :
1701 : /* psql's backslash commands. */
1702 : static const char *const backslash_commands[] = {
1703 : "\\a",
1704 : "\\bind",
1705 : "\\connect", "\\conninfo", "\\C", "\\cd", "\\copy",
1706 : "\\copyright", "\\crosstabview",
1707 : "\\d", "\\da", "\\dA", "\\dAc", "\\dAf", "\\dAo", "\\dAp",
1708 : "\\db", "\\dc", "\\dconfig", "\\dC", "\\dd", "\\ddp", "\\dD",
1709 : "\\des", "\\det", "\\deu", "\\dew", "\\dE", "\\df",
1710 : "\\dF", "\\dFd", "\\dFp", "\\dFt", "\\dg", "\\di", "\\dl", "\\dL",
1711 : "\\dm", "\\dn", "\\do", "\\dO", "\\dp", "\\dP", "\\dPi", "\\dPt",
1712 : "\\drds", "\\dRs", "\\dRp", "\\ds",
1713 : "\\dt", "\\dT", "\\dv", "\\du", "\\dx", "\\dX", "\\dy",
1714 : "\\echo", "\\edit", "\\ef", "\\elif", "\\else", "\\encoding",
1715 : "\\endif", "\\errverbose", "\\ev",
1716 : "\\f",
1717 : "\\g", "\\gdesc", "\\getenv", "\\gexec", "\\gset", "\\gx",
1718 : "\\help", "\\html",
1719 : "\\if", "\\include", "\\include_relative", "\\ir",
1720 : "\\list", "\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",
1721 : "\\out",
1722 : "\\password", "\\print", "\\prompt", "\\pset",
1723 : "\\qecho", "\\quit",
1724 : "\\reset",
1725 : "\\s", "\\set", "\\setenv", "\\sf", "\\sv",
1726 : "\\t", "\\T", "\\timing",
1727 : "\\unset",
1728 : "\\x",
1729 : "\\warn", "\\watch", "\\write",
1730 : "\\z",
1731 : "\\!", "\\?",
1732 : NULL
1733 : };
1734 :
1735 : /*
1736 : * Temporary workaround for a bug in recent (2019) libedit: it incorrectly
1737 : * de-escapes the input "text", causing us to fail to recognize backslash
1738 : * commands. So get the string to look at from rl_line_buffer instead.
1739 : */
1192 tgl 1740 GIC 66 : char *text_copy = pnstrdup(rl_line_buffer + start, end - start);
1741 66 : text = text_copy;
1742 :
1743 : /* Remember last char of the given input word. */
1172 1744 66 : completion_last_char = (end > start) ? text[end - start - 1] : '\0';
1745 :
1746 : /* We usually want the append character to be a space. */
8397 bruce 1747 66 : rl_completion_append_character = ' ';
1748 :
1749 : /* Clear a few things. */
1750 66 : completion_charp = NULL;
1751 66 : completion_charpp = NULL;
434 tgl 1752 66 : completion_vquery = NULL;
1753 66 : completion_squery = NULL;
1754 66 : completion_ref_object = NULL;
1755 66 : completion_ref_schema = NULL;
1756 :
1757 : /*
1758 : * Scan the input line to extract the words before our current position.
1759 : * According to those we'll make some smart decisions on what the user is
1760 : * probably intending to type.
1761 : */
2667 tgl 1762 CBC 66 : previous_words = get_previous_words(start,
2667 tgl 1763 ECB : &words_buffer,
1764 : &previous_words_count);
1765 :
2668 1766 : /* If current word is a backslash command, offer completions for that */
8397 bruce 1767 GIC 66 : if (text[0] == '\\')
4085 peter_e 1768 1 : COMPLETE_WITH_LIST_CS(backslash_commands);
8397 bruce 1769 ECB :
1770 : /* If current word is a variable interpolation, handle that case */
4440 rhaas 1771 GIC 65 : else if (text[0] == ':' && text[1] != ':')
4440 rhaas 1772 ECB : {
4440 rhaas 1773 CBC 1 : if (text[1] == '\'')
3162 fujii 1774 LBC 0 : matches = complete_from_variables(text, ":'", "'", true);
4440 rhaas 1775 CBC 1 : else if (text[1] == '"')
3162 fujii 1776 LBC 0 : matches = complete_from_variables(text, ":\"", "\"", true);
4440 rhaas 1777 ECB : else
3162 fujii 1778 GIC 1 : matches = complete_from_variables(text, ":", "", true);
1779 : }
1780 :
1781 : /* If no previous word, suggest one of the basic sql commands */
2668 tgl 1782 64 : else if (previous_words_count == 0)
8397 bruce 1783 2 : COMPLETE_WITH_LIST(sql_commands);
8535 bruce 1784 ECB :
1785 : /* CREATE */
1786 : /* complete with something you can create */
1661 tgl 1787 GIC 62 : else if (TailMatches("CREATE"))
1213 1788 1 : matches = rl_completion_matches(text, create_command_generator);
8535 bruce 1789 ECB :
1257 michael 1790 : /* complete with something you can create or replace */
1304 fujii 1791 GIC 61 : else if (TailMatches("CREATE", "OR", "REPLACE"))
1304 fujii 1792 UIC 0 : COMPLETE_WITH("FUNCTION", "PROCEDURE", "LANGUAGE", "RULE", "VIEW",
872 michael 1793 ECB : "AGGREGATE", "TRANSFORM", "TRIGGER");
1794 :
4189 tgl 1795 : /* DROP, but not DROP embedded in other commands */
6216 alvherre 1796 EUB : /* complete with something you can drop */
1661 tgl 1797 CBC 61 : else if (Matches("DROP"))
1213 tgl 1798 GBC 1 : matches = rl_completion_matches(text, drop_command_generator);
1799 :
8535 bruce 1800 ECB : /* ALTER */
1801 :
1802 : /* ALTER TABLE */
1661 tgl 1803 GIC 60 : else if (Matches("ALTER", "TABLE"))
434 tgl 1804 LBC 0 : COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_tables,
434 tgl 1805 ECB : "ALL IN TABLESPACE");
1806 :
1807 : /* ALTER something */
1661 tgl 1808 GIC 60 : else if (Matches("ALTER"))
1213 tgl 1809 LBC 0 : matches = rl_completion_matches(text, alter_command_generator);
2668 andres 1810 ECB : /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx */
1661 tgl 1811 GIC 60 : else if (TailMatches("ALL", "IN", "TABLESPACE", MatchAny))
1661 tgl 1812 UIC 0 : COMPLETE_WITH("SET TABLESPACE", "OWNED BY");
2668 andres 1813 ECB : /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY */
1661 tgl 1814 GBC 60 : else if (TailMatches("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY"))
3136 sfrost 1815 UIC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_roles);
1816 : /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY xxx */
1661 tgl 1817 GIC 60 : else if (TailMatches("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY", MatchAny))
1661 tgl 1818 UIC 0 : COMPLETE_WITH("SET TABLESPACE");
1956 peter_e 1819 ECB : /* ALTER AGGREGATE,FUNCTION,PROCEDURE,ROUTINE <name> */
1661 tgl 1820 CBC 60 : else if (Matches("ALTER", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny))
1661 tgl 1821 UIC 0 : COMPLETE_WITH("(");
1822 : /* ALTER AGGREGATE <name> (...) */
781 michael 1823 GIC 60 : else if (Matches("ALTER", "AGGREGATE", MatchAny, MatchAny))
1824 : {
2668 tgl 1825 LBC 0 : if (ends_with(prev_wd, ')'))
1661 tgl 1826 UBC 0 : COMPLETE_WITH("OWNER TO", "RENAME TO", "SET SCHEMA");
1827 : else
3930 magnus 1828 UIC 0 : COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
1829 : }
1830 : /* ALTER FUNCTION <name> (...) */
93 dean.a.rasheed 1831 GNC 60 : else if (Matches("ALTER", "FUNCTION", MatchAny, MatchAny))
1832 : {
93 dean.a.rasheed 1833 LBC 0 : if (ends_with(prev_wd, ')'))
93 dean.a.rasheed 1834 UNC 0 : COMPLETE_WITH(Alter_function_options);
93 dean.a.rasheed 1835 ECB : else
93 dean.a.rasheed 1836 UBC 0 : COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
1837 : }
1838 : /* ALTER PROCEDURE <name> (...) */
93 dean.a.rasheed 1839 GNC 60 : else if (Matches("ALTER", "PROCEDURE", MatchAny, MatchAny))
1840 : {
93 dean.a.rasheed 1841 UNC 0 : if (ends_with(prev_wd, ')'))
1842 0 : COMPLETE_WITH(Alter_procedure_options);
1843 : else
1844 0 : COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
1845 : }
1846 : /* ALTER ROUTINE <name> (...) */
93 dean.a.rasheed 1847 GNC 60 : else if (Matches("ALTER", "ROUTINE", MatchAny, MatchAny))
1848 : {
781 michael 1849 UNC 0 : if (ends_with(prev_wd, ')'))
93 dean.a.rasheed 1850 0 : COMPLETE_WITH(Alter_routine_options);
1851 : else
781 michael 1852 0 : COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
1853 : }
1854 : /* ALTER FUNCTION|ROUTINE <name> (...) PARALLEL */
93 dean.a.rasheed 1855 GNC 60 : else if (Matches("ALTER", "FUNCTION|ROUTINE", MatchAny, MatchAny, "PARALLEL"))
93 dean.a.rasheed 1856 UNC 0 : COMPLETE_WITH("RESTRICTED", "SAFE", "UNSAFE");
1857 : /* ALTER FUNCTION|PROCEDURE|ROUTINE <name> (...) [EXTERNAL] SECURITY */
93 dean.a.rasheed 1858 GNC 120 : else if (Matches("ALTER", "FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny, "SECURITY") ||
1859 60 : Matches("ALTER", "FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny, "EXTERNAL", "SECURITY"))
93 dean.a.rasheed 1860 UNC 0 : COMPLETE_WITH("DEFINER", "INVOKER");
1861 : /* ALTER FUNCTION|PROCEDURE|ROUTINE <name> (...) RESET */
93 dean.a.rasheed 1862 GNC 60 : else if (Matches("ALTER", "FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny, "RESET"))
93 dean.a.rasheed 1863 UNC 0 : COMPLETE_WITH_QUERY_VERBATIM_PLUS(Query_for_list_of_set_vars,
1864 : "ALL");
1865 : /* ALTER FUNCTION|PROCEDURE|ROUTINE <name> (...) SET */
93 dean.a.rasheed 1866 GNC 60 : else if (Matches("ALTER", "FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny, "SET"))
93 dean.a.rasheed 1867 UNC 0 : COMPLETE_WITH_QUERY_VERBATIM_PLUS(Query_for_list_of_set_vars,
1868 : "SCHEMA");
781 michael 1869 ECB :
2154 peter_e 1870 EUB : /* ALTER PUBLICATION <name> */
1661 tgl 1871 GIC 60 : else if (Matches("ALTER", "PUBLICATION", MatchAny))
529 akapila 1872 LBC 0 : COMPLETE_WITH("ADD", "DROP", "OWNER TO", "RENAME TO", "SET");
529 akapila 1873 EUB : /* ALTER PUBLICATION <name> ADD */
529 akapila 1874 GIC 60 : else if (Matches("ALTER", "PUBLICATION", MatchAny, "ADD"))
199 alvherre 1875 LBC 0 : COMPLETE_WITH("TABLES IN SCHEMA", "TABLE");
436 alvherre 1876 GIC 120 : else if (Matches("ALTER", "PUBLICATION", MatchAny, "ADD|SET", "TABLE") ||
436 alvherre 1877 GBC 60 : (HeadMatches("ALTER", "PUBLICATION", MatchAny, "ADD|SET", "TABLE") &&
436 alvherre 1878 UBC 0 : ends_with(prev_wd, ',')))
434 tgl 1879 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
332 tgl 1880 EUB :
1881 : /*
1882 : * "ALTER PUBLICATION <name> SET TABLE <name> WHERE (" - complete with
411 akapila 1883 ECB : * table attributes
1884 : *
411 akapila 1885 EUB : * "ALTER PUBLICATION <name> ADD TABLE <name> WHERE (" - complete with
1886 : * table attributes
1887 : */
411 akapila 1888 GBC 60 : else if (HeadMatches("ALTER", "PUBLICATION", MatchAny) && TailMatches("WHERE"))
411 akapila 1889 UIC 0 : COMPLETE_WITH("(");
411 akapila 1890 GIC 60 : else if (HeadMatches("ALTER", "PUBLICATION", MatchAny) && TailMatches("WHERE", "("))
411 akapila 1891 LBC 0 : COMPLETE_WITH_ATTR(prev3_wd);
411 akapila 1892 GIC 60 : else if (HeadMatches("ALTER", "PUBLICATION", MatchAny, "ADD|SET", "TABLE") &&
411 akapila 1893 UBC 0 : !TailMatches("WHERE", "(*)"))
1894 0 : COMPLETE_WITH(",", "WHERE (");
436 alvherre 1895 GIC 60 : else if (HeadMatches("ALTER", "PUBLICATION", MatchAny, "ADD|SET", "TABLE"))
436 alvherre 1896 UBC 0 : COMPLETE_WITH(",");
1897 : /* ALTER PUBLICATION <name> DROP */
529 akapila 1898 GIC 60 : else if (Matches("ALTER", "PUBLICATION", MatchAny, "DROP"))
199 alvherre 1899 LBC 0 : COMPLETE_WITH("TABLES IN SCHEMA", "TABLE");
1900 : /* ALTER PUBLICATION <name> SET */
1661 tgl 1901 GBC 60 : else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET"))
199 alvherre 1902 UBC 0 : COMPLETE_WITH("(", "TABLES IN SCHEMA", "TABLE");
191 alvherre 1903 GIC 60 : else if (Matches("ALTER", "PUBLICATION", MatchAny, "ADD|DROP|SET", "TABLES", "IN", "SCHEMA"))
434 tgl 1904 UBC 0 : COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_schemas
1905 : " AND nspname NOT LIKE E'pg\\\\_%%'",
1906 : "CURRENT_SCHEMA");
2154 peter_e 1907 ECB : /* ALTER PUBLICATION <name> SET ( */
1661 tgl 1908 GBC 60 : else if (HeadMatches("ALTER", "PUBLICATION", MatchAny) && TailMatches("SET", "("))
667 michael 1909 UIC 0 : COMPLETE_WITH("publish", "publish_via_partition_root");
2154 peter_e 1910 ECB : /* ALTER SUBSCRIPTION <name> */
1661 tgl 1911 CBC 60 : else if (Matches("ALTER", "SUBSCRIPTION", MatchAny))
1661 tgl 1912 UBC 0 : COMPLETE_WITH("CONNECTION", "ENABLE", "DISABLE", "OWNER TO",
1913 : "RENAME TO", "REFRESH PUBLICATION", "SET", "SKIP (",
733 peter 1914 ECB : "ADD PUBLICATION", "DROP PUBLICATION");
2154 peter_e 1915 EUB : /* ALTER SUBSCRIPTION <name> REFRESH PUBLICATION */
1661 tgl 1916 GIC 60 : else if (HeadMatches("ALTER", "SUBSCRIPTION", MatchAny) &&
1661 tgl 1917 UIC 0 : TailMatches("REFRESH", "PUBLICATION"))
1661 tgl 1918 LBC 0 : COMPLETE_WITH("WITH (");
2154 peter_e 1919 EUB : /* ALTER SUBSCRIPTION <name> REFRESH PUBLICATION WITH ( */
1661 tgl 1920 GIC 60 : else if (HeadMatches("ALTER", "SUBSCRIPTION", MatchAny) &&
1661 tgl 1921 UIC 0 : TailMatches("REFRESH", "PUBLICATION", "WITH", "("))
1922 0 : COMPLETE_WITH("copy_data");
2154 peter_e 1923 ECB : /* ALTER SUBSCRIPTION <name> SET */
1661 tgl 1924 GBC 60 : else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, "SET"))
1661 tgl 1925 UIC 0 : COMPLETE_WITH("(", "PUBLICATION");
2154 peter_e 1926 ECB : /* ALTER SUBSCRIPTION <name> SET ( */
1661 tgl 1927 GBC 60 : else if (HeadMatches("ALTER", "SUBSCRIPTION", MatchAny) && TailMatches("SET", "("))
2 akapila 1928 UNC 0 : COMPLETE_WITH("binary", "disable_on_error", "origin",
1929 : "password_required", "run_as_owner", "slot_name",
1930 : "streaming", "synchronous_commit");
383 akapila 1931 ECB : /* ALTER SUBSCRIPTION <name> SKIP ( */
383 akapila 1932 GBC 60 : else if (HeadMatches("ALTER", "SUBSCRIPTION", MatchAny) && TailMatches("SKIP", "("))
383 akapila 1933 UBC 0 : COMPLETE_WITH("lsn");
1934 : /* ALTER SUBSCRIPTION <name> SET PUBLICATION */
1661 tgl 1935 GIC 60 : else if (HeadMatches("ALTER", "SUBSCRIPTION", MatchAny) && TailMatches("SET", "PUBLICATION"))
1936 : {
1937 : /* complete with nothing here as this refers to remote publications */
1938 : }
1939 : /* ALTER SUBSCRIPTION <name> ADD|DROP|SET PUBLICATION <name> */
1940 60 : else if (HeadMatches("ALTER", "SUBSCRIPTION", MatchAny) &&
733 peter 1941 UIC 0 : TailMatches("ADD|DROP|SET", "PUBLICATION", MatchAny))
1661 tgl 1942 LBC 0 : COMPLETE_WITH("WITH (");
593 akapila 1943 EUB : /* ALTER SUBSCRIPTION <name> ADD|DROP|SET PUBLICATION <name> WITH ( */
1661 tgl 1944 CBC 60 : else if (HeadMatches("ALTER", "SUBSCRIPTION", MatchAny) &&
593 akapila 1945 UBC 0 : TailMatches("ADD|DROP|SET", "PUBLICATION", MatchAny, "WITH", "("))
1661 tgl 1946 LBC 0 : COMPLETE_WITH("copy_data", "refresh");
733 peter 1947 EUB :
4517 rhaas 1948 : /* ALTER SCHEMA <name> */
1661 tgl 1949 CBC 60 : else if (Matches("ALTER", "SCHEMA", MatchAny))
1661 tgl 1950 UBC 0 : COMPLETE_WITH("OWNER TO", "RENAME TO");
1951 :
4439 peter_e 1952 ECB : /* ALTER COLLATION <name> */
1661 tgl 1953 GBC 60 : else if (Matches("ALTER", "COLLATION", MatchAny))
437 peter 1954 UIC 0 : COMPLETE_WITH("OWNER TO", "REFRESH VERSION", "RENAME TO", "SET SCHEMA");
4439 peter_e 1955 ECB :
4517 rhaas 1956 EUB : /* ALTER CONVERSION <name> */
1661 tgl 1957 CBC 60 : else if (Matches("ALTER", "CONVERSION", MatchAny))
1661 tgl 1958 UBC 0 : COMPLETE_WITH("OWNER TO", "RENAME TO", "SET SCHEMA");
1959 :
1960 : /* ALTER DATABASE <name> */
1661 tgl 1961 GIC 60 : else if (Matches("ALTER", "DATABASE", MatchAny))
419 peter 1962 LBC 0 : COMPLETE_WITH("RESET", "SET", "OWNER TO", "REFRESH COLLATION VERSION", "RENAME TO",
1661 tgl 1963 EUB : "IS_TEMPLATE", "ALLOW_CONNECTIONS",
1964 : "CONNECTION LIMIT");
6805 bruce 1965 ECB :
1662 tgl 1966 EUB : /* ALTER DATABASE <name> SET TABLESPACE */
1661 tgl 1967 GIC 60 : else if (Matches("ALTER", "DATABASE", MatchAny, "SET", "TABLESPACE"))
1662 tgl 1968 UIC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
1969 :
3282 rhaas 1970 ECB : /* ALTER EVENT TRIGGER */
1661 tgl 1971 GBC 60 : else if (Matches("ALTER", "EVENT", "TRIGGER"))
3282 rhaas 1972 UBC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
1973 :
3282 rhaas 1974 ECB : /* ALTER EVENT TRIGGER <name> */
1661 tgl 1975 GBC 60 : else if (Matches("ALTER", "EVENT", "TRIGGER", MatchAny))
1661 tgl 1976 UBC 0 : COMPLETE_WITH("DISABLE", "ENABLE", "OWNER TO", "RENAME TO");
1977 :
3282 rhaas 1978 ECB : /* ALTER EVENT TRIGGER <name> ENABLE */
1661 tgl 1979 GBC 60 : else if (Matches("ALTER", "EVENT", "TRIGGER", MatchAny, "ENABLE"))
1661 tgl 1980 UIC 0 : COMPLETE_WITH("REPLICA", "ALWAYS");
3282 rhaas 1981 ECB :
4443 tgl 1982 EUB : /* ALTER EXTENSION <name> */
1661 tgl 1983 GIC 60 : else if (Matches("ALTER", "EXTENSION", MatchAny))
280 tgl 1984 UIC 0 : COMPLETE_WITH("ADD", "DROP", "UPDATE", "SET SCHEMA");
1985 :
1986 : /* ALTER EXTENSION <name> ADD|DROP */
87 michael 1987 GNC 60 : else if (Matches("ALTER", "EXTENSION", MatchAny, "ADD|DROP"))
87 michael 1988 UNC 0 : COMPLETE_WITH("ACCESS METHOD", "AGGREGATE", "CAST", "COLLATION",
1989 : "CONVERSION", "DOMAIN", "EVENT TRIGGER", "FOREIGN",
1990 : "FUNCTION", "MATERIALIZED VIEW", "OPERATOR",
1991 : "LANGUAGE", "PROCEDURE", "ROUTINE", "SCHEMA",
1992 : "SEQUENCE", "SERVER", "TABLE", "TEXT SEARCH",
1993 : "TRANSFORM FOR", "TYPE", "VIEW");
1994 :
1995 : /* ALTER EXTENSION <name> ADD|DROP FOREIGN */
87 michael 1996 GNC 60 : else if (Matches("ALTER", "EXTENSION", MatchAny, "ADD|DROP", "FOREIGN"))
87 michael 1997 UNC 0 : COMPLETE_WITH("DATA WRAPPER", "TABLE");
1998 :
1999 : /* ALTER EXTENSION <name> ADD|DROP OPERATOR */
87 michael 2000 GNC 60 : else if (Matches("ALTER", "EXTENSION", MatchAny, "ADD|DROP", "OPERATOR"))
87 michael 2001 UNC 0 : COMPLETE_WITH("CLASS", "FAMILY");
2002 :
2003 : /* ALTER EXTENSION <name> ADD|DROP TEXT SEARCH */
87 michael 2004 GNC 60 : else if (Matches("ALTER", "EXTENSION", MatchAny, "ADD|DROP", "TEXT", "SEARCH"))
87 michael 2005 UNC 0 : COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2006 :
2425 tgl 2007 ECB : /* ALTER EXTENSION <name> UPDATE */
1661 tgl 2008 GBC 60 : else if (Matches("ALTER", "EXTENSION", MatchAny, "UPDATE"))
292 tgl 2009 UIC 0 : COMPLETE_WITH("TO");
2425 tgl 2010 ECB :
2011 : /* ALTER EXTENSION <name> UPDATE TO */
1661 tgl 2012 GIC 60 : else if (Matches("ALTER", "EXTENSION", MatchAny, "UPDATE", "TO"))
2013 : {
434 tgl 2014 UIC 0 : set_completion_reference(prev3_wd);
292 tgl 2015 LBC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions);
2425 tgl 2016 EUB : }
2017 :
2018 : /* ALTER FOREIGN */
1661 tgl 2019 CBC 60 : else if (Matches("ALTER", "FOREIGN"))
1661 tgl 2020 UBC 0 : COMPLETE_WITH("DATA WRAPPER", "TABLE");
4481 rhaas 2021 EUB :
2022 : /* ALTER FOREIGN DATA WRAPPER <name> */
1661 tgl 2023 GIC 60 : else if (Matches("ALTER", "FOREIGN", "DATA", "WRAPPER", MatchAny))
496 michael 2024 LBC 0 : COMPLETE_WITH("HANDLER", "VALIDATOR", "NO",
496 michael 2025 EUB : "OPTIONS", "OWNER TO", "RENAME TO");
496 michael 2026 GIC 60 : else if (Matches("ALTER", "FOREIGN", "DATA", "WRAPPER", MatchAny, "NO"))
496 michael 2027 UIC 0 : COMPLETE_WITH("HANDLER", "VALIDATOR");
5224 peter_e 2028 ECB :
4481 rhaas 2029 EUB : /* ALTER FOREIGN TABLE <name> */
1661 tgl 2030 GIC 60 : else if (Matches("ALTER", "FOREIGN", "TABLE", MatchAny))
1661 tgl 2031 UIC 0 : COMPLETE_WITH("ADD", "ALTER", "DISABLE TRIGGER", "DROP", "ENABLE",
1661 tgl 2032 ECB : "INHERIT", "NO INHERIT", "OPTIONS", "OWNER TO",
1661 tgl 2033 EUB : "RENAME", "SET", "VALIDATE CONSTRAINT");
2034 :
2035 : /* ALTER INDEX */
1661 tgl 2036 CBC 60 : else if (Matches("ALTER", "INDEX"))
434 tgl 2037 UBC 0 : COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_indexes,
2038 : "ALL IN TABLESPACE");
2039 : /* ALTER INDEX <name> */
1661 tgl 2040 GIC 60 : else if (Matches("ALTER", "INDEX", MatchAny))
1661 tgl 2041 UIC 0 : COMPLETE_WITH("ALTER COLUMN", "OWNER TO", "RENAME TO", "SET",
781 michael 2042 ECB : "RESET", "ATTACH PARTITION",
702 tmunro 2043 EUB : "DEPENDS ON EXTENSION", "NO DEPENDS ON EXTENSION");
1661 tgl 2044 GIC 60 : else if (Matches("ALTER", "INDEX", MatchAny, "ATTACH"))
1661 tgl 2045 UIC 0 : COMPLETE_WITH("PARTITION");
1661 tgl 2046 CBC 60 : else if (Matches("ALTER", "INDEX", MatchAny, "ATTACH", "PARTITION"))
434 tgl 2047 UBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes);
2048 : /* ALTER INDEX <name> ALTER */
1566 michael 2049 GIC 60 : else if (Matches("ALTER", "INDEX", MatchAny, "ALTER"))
702 tmunro 2050 LBC 0 : COMPLETE_WITH("COLUMN");
1532 michael 2051 EUB : /* ALTER INDEX <name> ALTER COLUMN */
1532 michael 2052 GIC 60 : else if (Matches("ALTER", "INDEX", MatchAny, "ALTER", "COLUMN"))
2053 : {
434 tgl 2054 LBC 0 : set_completion_reference(prev3_wd);
434 tgl 2055 UBC 0 : COMPLETE_WITH_SCHEMA_QUERY_VERBATIM(Query_for_list_of_attribute_numbers);
2056 : }
2057 : /* ALTER INDEX <name> ALTER COLUMN <colnum> */
1661 tgl 2058 CBC 60 : else if (Matches("ALTER", "INDEX", MatchAny, "ALTER", "COLUMN", MatchAny))
1661 tgl 2059 UBC 0 : COMPLETE_WITH("SET STATISTICS");
2060 : /* ALTER INDEX <name> ALTER COLUMN <colnum> SET */
1566 michael 2061 GIC 60 : else if (Matches("ALTER", "INDEX", MatchAny, "ALTER", "COLUMN", MatchAny, "SET"))
1566 michael 2062 LBC 0 : COMPLETE_WITH("STATISTICS");
1566 michael 2063 EUB : /* ALTER INDEX <name> ALTER COLUMN <colnum> SET STATISTICS */
1566 michael 2064 GIC 60 : else if (Matches("ALTER", "INDEX", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "STATISTICS"))
2065 : {
2066 : /* Enforce no completion here, as an integer has to be specified */
2067 : }
2068 : /* ALTER INDEX <name> SET */
1661 tgl 2069 60 : else if (Matches("ALTER", "INDEX", MatchAny, "SET"))
1661 tgl 2070 UIC 0 : COMPLETE_WITH("(", "TABLESPACE");
4799 itagaki.takahiro 2071 ECB : /* ALTER INDEX <name> RESET */
1661 tgl 2072 GBC 60 : else if (Matches("ALTER", "INDEX", MatchAny, "RESET"))
1661 tgl 2073 UIC 0 : COMPLETE_WITH("(");
2074 : /* ALTER INDEX <foo> SET|RESET ( */
1661 tgl 2075 CBC 60 : else if (Matches("ALTER", "INDEX", MatchAny, "RESET", "("))
1545 tgl 2076 UBC 0 : COMPLETE_WITH("fillfactor",
2077 : "deduplicate_items", /* BTREE */
2078 : "fastupdate", "gin_pending_list_limit", /* GIN */
1661 tgl 2079 ECB : "buffering", /* GiST */
1661 tgl 2080 EUB : "pages_per_range", "autosummarize" /* BRIN */
2081 : );
1661 tgl 2082 GIC 60 : else if (Matches("ALTER", "INDEX", MatchAny, "SET", "("))
1545 tgl 2083 LBC 0 : COMPLETE_WITH("fillfactor =",
697 tgl 2084 EUB : "deduplicate_items =", /* BTREE */
2085 : "fastupdate =", "gin_pending_list_limit =", /* GIN */
2086 : "buffering =", /* GiST */
1661 tgl 2087 ECB : "pages_per_range =", "autosummarize =" /* BRIN */
2088 : );
702 tmunro 2089 GBC 60 : else if (Matches("ALTER", "INDEX", MatchAny, "NO", "DEPENDS"))
702 tmunro 2090 UBC 0 : COMPLETE_WITH("ON EXTENSION");
702 tmunro 2091 GIC 60 : else if (Matches("ALTER", "INDEX", MatchAny, "DEPENDS"))
702 tmunro 2092 UIC 0 : COMPLETE_WITH("ON EXTENSION");
2093 :
6773 neilc 2094 ECB : /* ALTER LANGUAGE <name> */
1661 tgl 2095 GBC 60 : else if (Matches("ALTER", "LANGUAGE", MatchAny))
1343 michael 2096 UIC 0 : COMPLETE_WITH("OWNER TO", "RENAME TO");
2097 :
4867 itagaki.takahiro 2098 ECB : /* ALTER LARGE OBJECT <oid> */
1661 tgl 2099 GBC 60 : else if (Matches("ALTER", "LARGE", "OBJECT", MatchAny))
1661 tgl 2100 UIC 0 : COMPLETE_WITH("OWNER TO");
4867 itagaki.takahiro 2101 ECB :
3689 kgrittn 2102 EUB : /* ALTER MATERIALIZED VIEW */
1661 tgl 2103 GIC 60 : else if (Matches("ALTER", "MATERIALIZED", "VIEW"))
434 tgl 2104 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_matviews,
434 tgl 2105 ECB : "ALL IN TABLESPACE");
3689 kgrittn 2106 EUB :
2107 : /* ALTER USER,ROLE <name> */
1661 tgl 2108 GIC 60 : else if (Matches("ALTER", "USER|ROLE", MatchAny) &&
1661 tgl 2109 UIC 0 : !TailMatches("USER", "MAPPING"))
2110 0 : COMPLETE_WITH("BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
1661 tgl 2111 ECB : "ENCRYPTED PASSWORD", "INHERIT", "LOGIN", "NOBYPASSRLS",
1661 tgl 2112 EUB : "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
2113 : "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
2114 : "RENAME TO", "REPLICATION", "RESET", "SET", "SUPERUSER",
1661 tgl 2115 ECB : "VALID UNTIL", "WITH");
6773 neilc 2116 EUB :
2117 : /* ALTER USER,ROLE <name> WITH */
1661 tgl 2118 GIC 60 : else if (Matches("ALTER", "USER|ROLE", MatchAny, "WITH"))
4008 peter_e 2119 ECB : /* Similar to the above, but don't complete "WITH" again. */
1661 tgl 2120 UBC 0 : COMPLETE_WITH("BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
1661 tgl 2121 ECB : "ENCRYPTED PASSWORD", "INHERIT", "LOGIN", "NOBYPASSRLS",
1661 tgl 2122 EUB : "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
2123 : "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
1661 tgl 2124 ECB : "RENAME TO", "REPLICATION", "RESET", "SET", "SUPERUSER",
1661 tgl 2125 EUB : "VALID UNTIL");
2126 :
4750 itagaki.takahiro 2127 ECB : /* ALTER DEFAULT PRIVILEGES */
1661 tgl 2128 GIC 60 : else if (Matches("ALTER", "DEFAULT", "PRIVILEGES"))
1661 tgl 2129 UBC 0 : COMPLETE_WITH("FOR ROLE", "IN SCHEMA");
4750 itagaki.takahiro 2130 EUB : /* ALTER DEFAULT PRIVILEGES FOR */
1661 tgl 2131 GIC 60 : else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "FOR"))
1661 tgl 2132 UIC 0 : COMPLETE_WITH("ROLE");
2298 sfrost 2133 ECB : /* ALTER DEFAULT PRIVILEGES IN */
1661 tgl 2134 GBC 60 : else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "IN"))
1661 tgl 2135 UIC 0 : COMPLETE_WITH("SCHEMA");
2298 sfrost 2136 ECB : /* ALTER DEFAULT PRIVILEGES FOR ROLE|USER ... */
1661 tgl 2137 GBC 60 : else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER",
2138 : MatchAny))
1661 tgl 2139 LBC 0 : COMPLETE_WITH("GRANT", "REVOKE", "IN SCHEMA");
2140 : /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... */
1661 tgl 2141 GIC 60 : else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
2142 : MatchAny))
1661 tgl 2143 UIC 0 : COMPLETE_WITH("GRANT", "REVOKE", "FOR ROLE");
2298 sfrost 2144 ECB : /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... FOR */
1661 tgl 2145 GBC 60 : else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
2146 : MatchAny, "FOR"))
1661 tgl 2147 LBC 0 : COMPLETE_WITH("ROLE");
2298 sfrost 2148 EUB : /* ALTER DEFAULT PRIVILEGES FOR ROLE|USER ... IN SCHEMA ... */
2149 : /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... FOR ROLE|USER ... */
1661 tgl 2150 CBC 60 : else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER",
1661 tgl 2151 GBC 60 : MatchAny, "IN", "SCHEMA", MatchAny) ||
1661 tgl 2152 GIC 60 : Matches("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
2153 : MatchAny, "FOR", "ROLE|USER", MatchAny))
1661 tgl 2154 UIC 0 : COMPLETE_WITH("GRANT", "REVOKE");
2155 : /* ALTER DOMAIN <name> */
1661 tgl 2156 GIC 60 : else if (Matches("ALTER", "DOMAIN", MatchAny))
1661 tgl 2157 LBC 0 : COMPLETE_WITH("ADD", "DROP", "OWNER TO", "RENAME", "SET",
1661 tgl 2158 EUB : "VALIDATE CONSTRAINT");
2159 : /* ALTER DOMAIN <sth> DROP */
1661 tgl 2160 GIC 60 : else if (Matches("ALTER", "DOMAIN", MatchAny, "DROP"))
1661 tgl 2161 UIC 0 : COMPLETE_WITH("CONSTRAINT", "DEFAULT", "NOT NULL");
2162 : /* ALTER DOMAIN <sth> DROP|RENAME|VALIDATE CONSTRAINT */
1661 tgl 2163 GIC 60 : else if (Matches("ALTER", "DOMAIN", MatchAny, "DROP|RENAME|VALIDATE", "CONSTRAINT"))
3859 peter_e 2164 ECB : {
434 tgl 2165 UBC 0 : set_completion_reference(prev3_wd);
434 tgl 2166 LBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_constraint_of_type);
3859 peter_e 2167 EUB : }
2168 : /* ALTER DOMAIN <sth> RENAME */
1661 tgl 2169 GIC 60 : else if (Matches("ALTER", "DOMAIN", MatchAny, "RENAME"))
1661 tgl 2170 LBC 0 : COMPLETE_WITH("CONSTRAINT", "TO");
4000 peter_e 2171 EUB : /* ALTER DOMAIN <sth> RENAME CONSTRAINT <sth> */
1661 tgl 2172 GIC 60 : else if (Matches("ALTER", "DOMAIN", MatchAny, "RENAME", "CONSTRAINT", MatchAny))
1661 tgl 2173 UIC 0 : COMPLETE_WITH("TO");
4000 peter_e 2174 ECB :
6806 bruce 2175 EUB : /* ALTER DOMAIN <sth> SET */
1661 tgl 2176 GIC 60 : else if (Matches("ALTER", "DOMAIN", MatchAny, "SET"))
1661 tgl 2177 UIC 0 : COMPLETE_WITH("DEFAULT", "NOT NULL", "SCHEMA");
6773 neilc 2178 ECB : /* ALTER SEQUENCE <name> */
1661 tgl 2179 GBC 60 : else if (Matches("ALTER", "SEQUENCE", MatchAny))
496 michael 2180 UIC 0 : COMPLETE_WITH("AS", "INCREMENT", "MINVALUE", "MAXVALUE", "RESTART",
2181 : "START", "NO", "CACHE", "CYCLE", "SET", "OWNED BY",
2182 : "OWNER TO", "RENAME TO");
496 michael 2183 ECB : /* ALTER SEQUENCE <name> AS */
496 michael 2184 GBC 60 : else if (TailMatches("ALTER", "SEQUENCE", MatchAny, "AS"))
496 michael 2185 UBC 0 : COMPLETE_WITH_CS("smallint", "integer", "bigint");
2186 : /* ALTER SEQUENCE <name> NO */
1661 tgl 2187 GIC 60 : else if (Matches("ALTER", "SEQUENCE", MatchAny, "NO"))
1661 tgl 2188 UIC 0 : COMPLETE_WITH("MINVALUE", "MAXVALUE", "CYCLE");
2189 : /* ALTER SEQUENCE <name> SET */
367 peter 2190 GIC 60 : else if (Matches("ALTER", "SEQUENCE", MatchAny, "SET"))
367 peter 2191 UIC 0 : COMPLETE_WITH("SCHEMA", "LOGGED", "UNLOGGED");
2192 : /* ALTER SERVER <name> */
1661 tgl 2193 CBC 60 : else if (Matches("ALTER", "SERVER", MatchAny))
1661 tgl 2194 UIC 0 : COMPLETE_WITH("VERSION", "OPTIONS", "OWNER TO", "RENAME TO");
2495 rhaas 2195 EUB : /* ALTER SERVER <name> VERSION <version> */
1661 tgl 2196 GIC 60 : else if (Matches("ALTER", "SERVER", MatchAny, "VERSION", MatchAny))
1661 tgl 2197 UIC 0 : COMPLETE_WITH("OPTIONS");
2198 : /* ALTER SYSTEM SET, RESET, RESET ALL */
1661 tgl 2199 GIC 60 : else if (Matches("ALTER", "SYSTEM"))
1661 tgl 2200 UIC 0 : COMPLETE_WITH("SET", "RESET");
1661 tgl 2201 GIC 60 : else if (Matches("ALTER", "SYSTEM", "SET|RESET"))
424 tgl 2202 UIC 0 : COMPLETE_WITH_QUERY_VERBATIM_PLUS(Query_for_list_of_alter_system_set_vars,
424 tgl 2203 ECB : "ALL");
1661 tgl 2204 GBC 60 : else if (Matches("ALTER", "SYSTEM", "SET", MatchAny))
1661 tgl 2205 UIC 0 : COMPLETE_WITH("TO");
5759 neilc 2206 ECB : /* ALTER VIEW <name> */
1661 tgl 2207 GBC 60 : else if (Matches("ALTER", "VIEW", MatchAny))
1235 fujii 2208 UIC 0 : COMPLETE_WITH("ALTER COLUMN", "OWNER TO", "RENAME",
1661 tgl 2209 ECB : "SET SCHEMA");
1235 fujii 2210 EUB : /* ALTER VIEW xxx RENAME */
1235 fujii 2211 GIC 60 : else if (Matches("ALTER", "VIEW", MatchAny, "RENAME"))
434 tgl 2212 LBC 0 : COMPLETE_WITH_ATTR_PLUS(prev2_wd, "COLUMN", "TO");
1235 fujii 2213 GIC 60 : else if (Matches("ALTER", "VIEW", MatchAny, "ALTER|RENAME", "COLUMN"))
434 tgl 2214 UBC 0 : COMPLETE_WITH_ATTR(prev3_wd);
2215 : /* ALTER VIEW xxx ALTER [ COLUMN ] yyy */
496 michael 2216 CBC 120 : else if (Matches("ALTER", "VIEW", MatchAny, "ALTER", MatchAny) ||
496 michael 2217 GIC 60 : Matches("ALTER", "VIEW", MatchAny, "ALTER", "COLUMN", MatchAny))
496 michael 2218 UBC 0 : COMPLETE_WITH("SET DEFAULT", "DROP DEFAULT");
2219 : /* ALTER VIEW xxx RENAME yyy */
1235 fujii 2220 CBC 60 : else if (Matches("ALTER", "VIEW", MatchAny, "RENAME", MatchAnyExcept("TO")))
1235 fujii 2221 UIC 0 : COMPLETE_WITH("TO");
1235 fujii 2222 EUB : /* ALTER VIEW xxx RENAME COLUMN yyy */
1235 fujii 2223 GIC 60 : else if (Matches("ALTER", "VIEW", MatchAny, "RENAME", "COLUMN", MatchAnyExcept("TO")))
1235 fujii 2224 UIC 0 : COMPLETE_WITH("TO");
1235 fujii 2225 ECB :
3689 kgrittn 2226 : /* ALTER MATERIALIZED VIEW <name> */
1661 tgl 2227 CBC 60 : else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny))
1235 fujii 2228 UIC 0 : COMPLETE_WITH("ALTER COLUMN", "CLUSTER ON", "DEPENDS ON EXTENSION",
781 michael 2229 EUB : "NO DEPENDS ON EXTENSION", "OWNER TO", "RENAME",
2230 : "RESET (", "SET");
1235 fujii 2231 ECB : /* ALTER MATERIALIZED VIEW xxx RENAME */
1235 fujii 2232 GBC 60 : else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny, "RENAME"))
434 tgl 2233 UIC 0 : COMPLETE_WITH_ATTR_PLUS(prev2_wd, "COLUMN", "TO");
1235 fujii 2234 GIC 60 : else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny, "ALTER|RENAME", "COLUMN"))
434 tgl 2235 LBC 0 : COMPLETE_WITH_ATTR(prev3_wd);
1235 fujii 2236 EUB : /* ALTER MATERIALIZED VIEW xxx RENAME yyy */
1235 fujii 2237 GIC 60 : else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny, "RENAME", MatchAnyExcept("TO")))
1235 fujii 2238 LBC 0 : COMPLETE_WITH("TO");
2239 : /* ALTER MATERIALIZED VIEW xxx RENAME COLUMN yyy */
1235 fujii 2240 GBC 60 : else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny, "RENAME", "COLUMN", MatchAnyExcept("TO")))
1235 fujii 2241 UBC 0 : COMPLETE_WITH("TO");
2242 : /* ALTER MATERIALIZED VIEW xxx SET */
1235 fujii 2243 GIC 60 : else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny, "SET"))
386 michael 2244 LBC 0 : COMPLETE_WITH("(", "ACCESS METHOD", "SCHEMA", "TABLESPACE", "WITHOUT CLUSTER");
386 michael 2245 EUB : /* ALTER MATERIALIZED VIEW xxx SET ACCESS METHOD */
386 michael 2246 GIC 60 : else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny, "SET", "ACCESS", "METHOD"))
386 michael 2247 LBC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_table_access_methods);
386 michael 2248 EUB :
2249 : /* ALTER POLICY <name> */
1661 tgl 2250 GIC 60 : else if (Matches("ALTER", "POLICY"))
2677 rhaas 2251 LBC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_policies);
3124 sfrost 2252 EUB : /* ALTER POLICY <name> ON */
1661 tgl 2253 GIC 60 : else if (Matches("ALTER", "POLICY", MatchAny))
1661 tgl 2254 LBC 0 : COMPLETE_WITH("ON");
3124 sfrost 2255 EUB : /* ALTER POLICY <name> ON <table> */
1661 tgl 2256 GIC 60 : else if (Matches("ALTER", "POLICY", MatchAny, "ON"))
2257 : {
434 tgl 2258 UIC 0 : set_completion_reference(prev2_wd);
434 tgl 2259 LBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables_for_policy);
2677 rhaas 2260 EUB : }
2261 : /* ALTER POLICY <name> ON <table> - show options */
1661 tgl 2262 CBC 60 : else if (Matches("ALTER", "POLICY", MatchAny, "ON", MatchAny))
1661 tgl 2263 UBC 0 : COMPLETE_WITH("RENAME TO", "TO", "USING (", "WITH CHECK (");
2264 : /* ALTER POLICY <name> ON <table> TO <role> */
1661 tgl 2265 CBC 60 : else if (Matches("ALTER", "POLICY", MatchAny, "ON", MatchAny, "TO"))
434 tgl 2266 UBC 0 : COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
2267 : Keywords_for_list_of_grant_roles);
3124 sfrost 2268 ECB : /* ALTER POLICY <name> ON <table> USING ( */
1661 tgl 2269 GBC 60 : else if (Matches("ALTER", "POLICY", MatchAny, "ON", MatchAny, "USING"))
1661 tgl 2270 UIC 0 : COMPLETE_WITH("(");
3124 sfrost 2271 ECB : /* ALTER POLICY <name> ON <table> WITH CHECK ( */
1661 tgl 2272 GBC 60 : else if (Matches("ALTER", "POLICY", MatchAny, "ON", MatchAny, "WITH", "CHECK"))
1661 tgl 2273 UIC 0 : COMPLETE_WITH("(");
3124 sfrost 2274 ECB :
3712 tgl 2275 EUB : /* ALTER RULE <name>, add ON */
1661 tgl 2276 CBC 60 : else if (Matches("ALTER", "RULE", MatchAny))
1661 tgl 2277 UBC 0 : COMPLETE_WITH("ON");
2278 :
3712 tgl 2279 ECB : /* If we have ALTER RULE <name> ON, then add the correct tablename */
1661 tgl 2280 GBC 60 : else if (Matches("ALTER", "RULE", MatchAny, "ON"))
2281 : {
434 tgl 2282 LBC 0 : set_completion_reference(prev2_wd);
434 tgl 2283 UBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables_for_rule);
2284 : }
2285 :
3712 tgl 2286 ECB : /* ALTER RULE <name> ON <name> */
1661 tgl 2287 GBC 60 : else if (Matches("ALTER", "RULE", MatchAny, "ON", MatchAny))
1661 tgl 2288 LBC 0 : COMPLETE_WITH("RENAME TO");
3712 tgl 2289 EUB :
2290 : /* ALTER STATISTICS <name> */
1661 tgl 2291 CBC 60 : else if (Matches("ALTER", "STATISTICS", MatchAny))
1307 tomas.vondra 2292 LBC 0 : COMPLETE_WITH("OWNER TO", "RENAME TO", "SET SCHEMA", "SET STATISTICS");
2293 : /* ALTER STATISTICS <name> SET */
167 michael 2294 GNC 60 : else if (Matches("ALTER", "STATISTICS", MatchAny, "SET"))
167 michael 2295 UNC 0 : COMPLETE_WITH("SCHEMA", "STATISTICS");
2158 alvherre 2296 EUB :
2297 : /* ALTER TRIGGER <name>, add ON */
1661 tgl 2298 CBC 60 : else if (Matches("ALTER", "TRIGGER", MatchAny))
1661 tgl 2299 UBC 0 : COMPLETE_WITH("ON");
2300 :
434 tgl 2301 CBC 60 : else if (Matches("ALTER", "TRIGGER", MatchAny, "ON"))
6773 neilc 2302 EUB : {
434 tgl 2303 UIC 0 : set_completion_reference(prev2_wd);
2304 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables_for_trigger);
6773 neilc 2305 ECB : }
7450 bruce 2306 EUB :
2307 : /* ALTER TRIGGER <name> ON <name> */
1661 tgl 2308 GIC 60 : else if (Matches("ALTER", "TRIGGER", MatchAny, "ON", MatchAny))
781 michael 2309 UIC 0 : COMPLETE_WITH("RENAME TO", "DEPENDS ON EXTENSION",
781 michael 2310 ECB : "NO DEPENDS ON EXTENSION");
6773 neilc 2311 EUB :
8053 bruce 2312 ECB : /*
4427 itagaki.takahiro 2313 EUB : * If we detect ALTER TABLE <name>, suggest sub commands
2314 : */
1661 tgl 2315 CBC 60 : else if (Matches("ALTER", "TABLE", MatchAny))
1661 tgl 2316 UBC 0 : COMPLETE_WITH("ADD", "ALTER", "CLUSTER ON", "DISABLE", "DROP",
2317 : "ENABLE", "INHERIT", "NO", "RENAME", "RESET",
1661 tgl 2318 ECB : "OWNER TO", "SET", "VALIDATE CONSTRAINT",
1661 tgl 2319 EUB : "REPLICA IDENTITY", "ATTACH PARTITION",
2320 : "DETACH PARTITION", "FORCE ROW LEVEL SECURITY",
2321 : "OF", "NOT OF");
587 michael 2322 ECB : /* ALTER TABLE xxx ADD */
587 michael 2323 GBC 60 : else if (Matches("ALTER", "TABLE", MatchAny, "ADD"))
2324 : {
586 michael 2325 ECB : /* make sure to keep this list and the !Matches() below in sync */
587 michael 2326 UBC 0 : COMPLETE_WITH("COLUMN", "CONSTRAINT", "CHECK", "UNIQUE", "PRIMARY KEY",
2327 : "EXCLUDE", "FOREIGN KEY");
2328 : }
363 drowley 2329 ECB : /* ALTER TABLE xxx ADD [COLUMN] yyy */
586 michael 2330 GBC 120 : else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "COLUMN", MatchAny) ||
586 michael 2331 GIC 60 : (Matches("ALTER", "TABLE", MatchAny, "ADD", MatchAny) &&
586 michael 2332 LBC 0 : !Matches("ALTER", "TABLE", MatchAny, "ADD", "COLUMN|CONSTRAINT|CHECK|UNIQUE|PRIMARY|EXCLUDE|FOREIGN")))
434 tgl 2333 UBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
2334 : /* ALTER TABLE xxx ADD CONSTRAINT yyy */
587 michael 2335 CBC 60 : else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "CONSTRAINT", MatchAny))
587 michael 2336 UIC 0 : COMPLETE_WITH("CHECK", "UNIQUE", "PRIMARY KEY", "EXCLUDE", "FOREIGN KEY");
587 michael 2337 EUB : /* ALTER TABLE xxx ADD [CONSTRAINT yyy] (PRIMARY KEY|UNIQUE) */
587 michael 2338 GBC 120 : else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "PRIMARY", "KEY") ||
587 michael 2339 GIC 120 : Matches("ALTER", "TABLE", MatchAny, "ADD", "UNIQUE") ||
2340 120 : Matches("ALTER", "TABLE", MatchAny, "ADD", "CONSTRAINT", MatchAny, "PRIMARY", "KEY") ||
587 michael 2341 CBC 60 : Matches("ALTER", "TABLE", MatchAny, "ADD", "CONSTRAINT", MatchAny, "UNIQUE"))
587 michael 2342 UBC 0 : COMPLETE_WITH("(", "USING INDEX");
2343 : /* ALTER TABLE xxx ADD PRIMARY KEY USING INDEX */
587 michael 2344 CBC 60 : else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "PRIMARY", "KEY", "USING", "INDEX"))
587 michael 2345 EUB : {
434 tgl 2346 UIC 0 : set_completion_reference(prev6_wd);
2347 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_unique_index_of_table);
587 michael 2348 ECB : }
587 michael 2349 EUB : /* ALTER TABLE xxx ADD UNIQUE USING INDEX */
587 michael 2350 GIC 60 : else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "UNIQUE", "USING", "INDEX"))
587 michael 2351 ECB : {
434 tgl 2352 UBC 0 : set_completion_reference(prev5_wd);
434 tgl 2353 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_unique_index_of_table);
2354 : }
587 michael 2355 ECB : /* ALTER TABLE xxx ADD CONSTRAINT yyy PRIMARY KEY USING INDEX */
587 michael 2356 GBC 60 : else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "CONSTRAINT", MatchAny,
2357 : "PRIMARY", "KEY", "USING", "INDEX"))
2358 : {
434 tgl 2359 LBC 0 : set_completion_reference(prev8_wd);
434 tgl 2360 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_unique_index_of_table);
587 michael 2361 EUB : }
2362 : /* ALTER TABLE xxx ADD CONSTRAINT yyy UNIQUE USING INDEX */
587 michael 2363 GIC 60 : else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "CONSTRAINT", MatchAny,
2364 : "UNIQUE", "USING", "INDEX"))
2365 : {
434 tgl 2366 LBC 0 : set_completion_reference(prev7_wd);
434 tgl 2367 UBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_unique_index_of_table);
2368 : }
2369 : /* ALTER TABLE xxx ENABLE */
1661 tgl 2370 CBC 60 : else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE"))
1661 tgl 2371 UBC 0 : COMPLETE_WITH("ALWAYS", "REPLICA", "ROW LEVEL SECURITY", "RULE",
2372 : "TRIGGER");
1661 tgl 2373 CBC 60 : else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE", "REPLICA|ALWAYS"))
1661 tgl 2374 UBC 0 : COMPLETE_WITH("RULE", "TRIGGER");
1661 tgl 2375 GIC 60 : else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE", "RULE"))
2376 : {
434 tgl 2377 LBC 0 : set_completion_reference(prev3_wd);
434 tgl 2378 UBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_rule_of_table);
2379 : }
1661 tgl 2380 CBC 60 : else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "RULE"))
2381 : {
434 tgl 2382 UBC 0 : set_completion_reference(prev4_wd);
2383 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_rule_of_table);
2384 : }
1661 tgl 2385 GIC 60 : else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE", "TRIGGER"))
2386 : {
434 tgl 2387 LBC 0 : set_completion_reference(prev3_wd);
434 tgl 2388 UBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_trigger_of_table);
2389 : }
1661 tgl 2390 GIC 60 : else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "TRIGGER"))
2391 : {
434 tgl 2392 UIC 0 : set_completion_reference(prev4_wd);
2393 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_trigger_of_table);
3212 heikki.linnakangas 2394 ECB : }
3909 rhaas 2395 EUB : /* ALTER TABLE xxx INHERIT */
1661 tgl 2396 GIC 60 : else if (Matches("ALTER", "TABLE", MatchAny, "INHERIT"))
434 tgl 2397 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
2398 : /* ALTER TABLE xxx NO */
897 michael 2399 GIC 60 : else if (Matches("ALTER", "TABLE", MatchAny, "NO"))
897 michael 2400 UIC 0 : COMPLETE_WITH("FORCE ROW LEVEL SECURITY", "INHERIT");
2401 : /* ALTER TABLE xxx NO INHERIT */
1661 tgl 2402 CBC 60 : else if (Matches("ALTER", "TABLE", MatchAny, "NO", "INHERIT"))
434 tgl 2403 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
2404 : /* ALTER TABLE xxx DISABLE */
1661 tgl 2405 GBC 60 : else if (Matches("ALTER", "TABLE", MatchAny, "DISABLE"))
1661 tgl 2406 UIC 0 : COMPLETE_WITH("ROW LEVEL SECURITY", "RULE", "TRIGGER");
1661 tgl 2407 GIC 60 : else if (Matches("ALTER", "TABLE", MatchAny, "DISABLE", "RULE"))
2408 : {
434 tgl 2409 LBC 0 : set_completion_reference(prev3_wd);
2410 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_rule_of_table);
3212 heikki.linnakangas 2411 EUB : }
1661 tgl 2412 GBC 60 : else if (Matches("ALTER", "TABLE", MatchAny, "DISABLE", "TRIGGER"))
2413 : {
434 tgl 2414 LBC 0 : set_completion_reference(prev3_wd);
434 tgl 2415 UBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_trigger_of_table);
2416 : }
5624 bruce 2417 ECB :
4000 peter_e 2418 : /* ALTER TABLE xxx ALTER */
1661 tgl 2419 CBC 60 : else if (Matches("ALTER", "TABLE", MatchAny, "ALTER"))
434 tgl 2420 LBC 0 : COMPLETE_WITH_ATTR_PLUS(prev2_wd, "COLUMN", "CONSTRAINT");
8535 bruce 2421 EUB :
2422 : /* ALTER TABLE xxx RENAME */
1661 tgl 2423 CBC 60 : else if (Matches("ALTER", "TABLE", MatchAny, "RENAME"))
434 tgl 2424 GIC 12 : COMPLETE_WITH_ATTR_PLUS(prev2_wd, "COLUMN", "CONSTRAINT", "TO");
1661 tgl 2425 GBC 48 : else if (Matches("ALTER", "TABLE", MatchAny, "ALTER|RENAME", "COLUMN"))
434 tgl 2426 UBC 0 : COMPLETE_WITH_ATTR(prev3_wd);
2427 :
2428 : /* ALTER TABLE xxx RENAME yyy */
1661 tgl 2429 CBC 48 : else if (Matches("ALTER", "TABLE", MatchAny, "RENAME", MatchAnyExcept("CONSTRAINT|TO")))
1661 tgl 2430 UIC 0 : COMPLETE_WITH("TO");
6773 neilc 2431 EUB :
4000 peter_e 2432 : /* ALTER TABLE xxx RENAME COLUMN/CONSTRAINT yyy */
1661 tgl 2433 GIC 48 : else if (Matches("ALTER", "TABLE", MatchAny, "RENAME", "COLUMN|CONSTRAINT", MatchAnyExcept("TO")))
1661 tgl 2434 UIC 0 : COMPLETE_WITH("TO");
6265 bruce 2435 ECB :
2436 : /* If we have ALTER TABLE <sth> DROP, provide COLUMN or CONSTRAINT */
1661 tgl 2437 GIC 48 : else if (Matches("ALTER", "TABLE", MatchAny, "DROP"))
1661 tgl 2438 UBC 0 : COMPLETE_WITH("COLUMN", "CONSTRAINT");
3859 peter_e 2439 EUB : /* If we have ALTER TABLE <sth> DROP COLUMN, provide list of columns */
1661 tgl 2440 GIC 48 : else if (Matches("ALTER", "TABLE", MatchAny, "DROP", "COLUMN"))
434 tgl 2441 UIC 0 : COMPLETE_WITH_ATTR(prev3_wd);
461 tgl 2442 ECB : /* ALTER TABLE <sth> ALTER|DROP|RENAME CONSTRAINT <constraint> */
461 tgl 2443 GIC 48 : else if (Matches("ALTER", "TABLE", MatchAny, "ALTER|DROP|RENAME", "CONSTRAINT"))
2444 : {
434 tgl 2445 GBC 3 : set_completion_reference(prev3_wd);
2446 3 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_constraint_of_table);
2447 : }
2448 : /* ALTER TABLE <sth> VALIDATE CONSTRAINT <non-validated constraint> */
461 tgl 2449 CBC 45 : else if (Matches("ALTER", "TABLE", MatchAny, "VALIDATE", "CONSTRAINT"))
461 tgl 2450 EUB : {
434 tgl 2451 UIC 0 : set_completion_reference(prev3_wd);
434 tgl 2452 LBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_constraint_of_table_not_validated);
461 tgl 2453 EUB : }
6773 neilc 2454 ECB : /* ALTER TABLE ALTER [COLUMN] <foo> */
1661 tgl 2455 GIC 90 : else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny) ||
1661 tgl 2456 GBC 45 : Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny))
1661 tgl 2457 UBC 0 : COMPLETE_WITH("TYPE", "SET", "RESET", "RESTART", "ADD", "DROP");
2458 : /* ALTER TABLE ALTER [COLUMN] <foo> ADD */
159 peter 2459 GNC 90 : else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "ADD") ||
2460 45 : Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "ADD"))
159 peter 2461 UNC 0 : COMPLETE_WITH("GENERATED");
2462 : /* ALTER TABLE ALTER [COLUMN] <foo> ADD GENERATED */
159 peter 2463 GNC 90 : else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "ADD", "GENERATED") ||
2464 45 : Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "ADD", "GENERATED"))
159 peter 2465 UNC 0 : COMPLETE_WITH("ALWAYS", "BY DEFAULT");
2466 : /* ALTER TABLE ALTER [COLUMN] <foo> ADD GENERATED */
159 peter 2467 GNC 90 : else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "ADD", "GENERATED", "ALWAYS") ||
2468 90 : Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "ADD", "GENERATED", "ALWAYS") ||
2469 90 : Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "ADD", "GENERATED", "BY", "DEFAULT") ||
2470 45 : Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "ADD", "GENERATED", "BY", "DEFAULT"))
159 peter 2471 UNC 0 : COMPLETE_WITH("AS IDENTITY");
2472 : /* ALTER TABLE ALTER [COLUMN] <foo> SET */
1661 tgl 2473 CBC 90 : else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET") ||
1661 tgl 2474 GIC 45 : Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET"))
159 peter 2475 UNC 0 : COMPLETE_WITH("(", "COMPRESSION", "DEFAULT", "GENERATED", "NOT NULL", "STATISTICS", "STORAGE",
2476 : /* a subset of ALTER SEQUENCE options */
2477 : "INCREMENT", "MINVALUE", "MAXVALUE", "START", "NO", "CACHE", "CYCLE");
4799 itagaki.takahiro 2478 EUB : /* ALTER TABLE ALTER [COLUMN] <foo> SET ( */
1661 tgl 2479 GIC 90 : else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "(") ||
1661 tgl 2480 CBC 45 : Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "("))
1661 tgl 2481 UIC 0 : COMPLETE_WITH("n_distinct", "n_distinct_inherited");
2482 : /* ALTER TABLE ALTER [COLUMN] <foo> SET COMPRESSION */
215 michael 2483 GNC 90 : else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "COMPRESSION") ||
2484 45 : Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "COMPRESSION"))
215 michael 2485 UNC 0 : COMPLETE_WITH("DEFAULT", "PGLZ", "LZ4");
2486 : /* ALTER TABLE ALTER [COLUMN] <foo> SET GENERATED */
159 peter 2487 GNC 90 : else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "GENERATED") ||
2488 45 : Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "GENERATED"))
159 peter 2489 UNC 0 : COMPLETE_WITH("ALWAYS", "BY DEFAULT");
2490 : /* ALTER TABLE ALTER [COLUMN] <foo> SET NO */
159 peter 2491 GNC 90 : else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "NO") ||
2492 45 : Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "NO"))
159 peter 2493 UNC 0 : COMPLETE_WITH("MINVALUE", "MAXVALUE", "CYCLE");
4799 itagaki.takahiro 2494 EUB : /* ALTER TABLE ALTER [COLUMN] <foo> SET STORAGE */
1661 tgl 2495 GBC 90 : else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "STORAGE") ||
1661 tgl 2496 GIC 45 : Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "STORAGE"))
150 tgl 2497 UNC 0 : COMPLETE_WITH("DEFAULT", "PLAIN", "EXTERNAL", "EXTENDED", "MAIN");
2498 : /* ALTER TABLE ALTER [COLUMN] <foo> SET STATISTICS */
1566 michael 2499 GBC 90 : else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "STATISTICS") ||
2500 45 : Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "STATISTICS"))
2501 : {
2502 : /* Enforce no completion here, as an integer has to be specified */
1566 michael 2503 ECB : }
4799 itagaki.takahiro 2504 EUB : /* ALTER TABLE ALTER [COLUMN] <foo> DROP */
1661 tgl 2505 GIC 90 : else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "DROP") ||
1661 tgl 2506 CBC 45 : Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "DROP"))
1181 peter 2507 UBC 0 : COMPLETE_WITH("DEFAULT", "EXPRESSION", "IDENTITY", "NOT NULL");
1661 tgl 2508 GIC 45 : else if (Matches("ALTER", "TABLE", MatchAny, "CLUSTER"))
1661 tgl 2509 LBC 0 : COMPLETE_WITH("ON");
1661 tgl 2510 GBC 45 : else if (Matches("ALTER", "TABLE", MatchAny, "CLUSTER", "ON"))
2511 : {
434 tgl 2512 LBC 0 : set_completion_reference(prev3_wd);
434 tgl 2513 UBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_index_of_table);
6806 bruce 2514 ECB : }
2515 : /* If we have ALTER TABLE <sth> SET, provide list of attributes and '(' */
1661 tgl 2516 GBC 45 : else if (Matches("ALTER", "TABLE", MatchAny, "SET"))
620 michael 2517 UBC 0 : COMPLETE_WITH("(", "ACCESS METHOD", "LOGGED", "SCHEMA",
2518 : "TABLESPACE", "UNLOGGED", "WITH", "WITHOUT");
620 michael 2519 ECB :
2520 : /*
619 michael 2521 EUB : * If we have ALTER TABLE <sth> SET ACCESS METHOD provide a list of table
620 2522 : * AMs.
2523 : */
620 michael 2524 GIC 45 : else if (Matches("ALTER", "TABLE", MatchAny, "SET", "ACCESS", "METHOD"))
620 michael 2525 UIC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_table_access_methods);
2652 tgl 2526 ECB :
2652 tgl 2527 EUB : /*
2528 : * If we have ALTER TABLE <sth> SET TABLESPACE provide a list of
2529 : * tablespaces
2652 tgl 2530 ECB : */
1661 tgl 2531 CBC 45 : else if (Matches("ALTER", "TABLE", MatchAny, "SET", "TABLESPACE"))
6806 bruce 2532 LBC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
2652 tgl 2533 EUB : /* If we have ALTER TABLE <sth> SET WITHOUT provide CLUSTER or OIDS */
1661 tgl 2534 GIC 45 : else if (Matches("ALTER", "TABLE", MatchAny, "SET", "WITHOUT"))
1661 tgl 2535 UIC 0 : COMPLETE_WITH("CLUSTER", "OIDS");
4799 itagaki.takahiro 2536 ECB : /* ALTER TABLE <foo> RESET */
1661 tgl 2537 GBC 45 : else if (Matches("ALTER", "TABLE", MatchAny, "RESET"))
1661 tgl 2538 UIC 0 : COMPLETE_WITH("(");
2539 : /* ALTER TABLE <foo> SET|RESET ( */
1661 tgl 2540 CBC 45 : else if (Matches("ALTER", "TABLE", MatchAny, "SET|RESET", "("))
1568 michael 2541 UBC 0 : COMPLETE_WITH_LIST(table_storage_parameters);
1661 tgl 2542 GIC 45 : else if (Matches("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING", "INDEX"))
2543 : {
434 tgl 2544 LBC 0 : set_completion_reference(prev5_wd);
434 tgl 2545 UBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_index_of_table);
2546 : }
1661 tgl 2547 CBC 45 : else if (Matches("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING"))
1661 tgl 2548 UBC 0 : COMPLETE_WITH("INDEX");
1661 tgl 2549 GIC 45 : else if (Matches("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY"))
1661 tgl 2550 LBC 0 : COMPLETE_WITH("FULL", "NOTHING", "DEFAULT", "USING");
1661 tgl 2551 GIC 45 : else if (Matches("ALTER", "TABLE", MatchAny, "REPLICA"))
1661 tgl 2552 LBC 0 : COMPLETE_WITH("IDENTITY");
2153 bruce 2553 ECB :
2554 : /*
2555 : * If we have ALTER TABLE <foo> ATTACH PARTITION, provide a list of
2233 rhaas 2556 : * tables.
2557 : */
1661 tgl 2558 GBC 45 : else if (Matches("ALTER", "TABLE", MatchAny, "ATTACH", "PARTITION"))
434 tgl 2559 UBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
2560 : /* Limited completion support for partition bound specification */
1661 tgl 2561 GIC 45 : else if (TailMatches("ATTACH", "PARTITION", MatchAny))
1661 tgl 2562 LBC 0 : COMPLETE_WITH("FOR VALUES", "DEFAULT");
1661 tgl 2563 CBC 45 : else if (TailMatches("FOR", "VALUES"))
1661 tgl 2564 UBC 0 : COMPLETE_WITH("FROM (", "IN (", "WITH (");
2565 :
2233 rhaas 2566 ECB : /*
2567 : * If we have ALTER TABLE <foo> DETACH PARTITION, provide a list of
2233 rhaas 2568 EUB : * partitions of <foo>.
2569 : */
1661 tgl 2570 CBC 45 : else if (Matches("ALTER", "TABLE", MatchAny, "DETACH", "PARTITION"))
2233 rhaas 2571 ECB : {
434 tgl 2572 UBC 0 : set_completion_reference(prev3_wd);
434 tgl 2573 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_partition_of_table);
2233 rhaas 2574 ECB : }
717 alvherre 2575 CBC 45 : else if (Matches("ALTER", "TABLE", MatchAny, "DETACH", "PARTITION", MatchAny))
717 alvherre 2576 LBC 0 : COMPLETE_WITH("CONCURRENTLY", "FINALIZE");
4799 itagaki.takahiro 2577 ECB :
2578 : /* ALTER TABLE <name> OF */
211 michael 2579 GNC 45 : else if (Matches("ALTER", "TABLE", MatchAny, "OF"))
211 michael 2580 UNC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_composite_datatypes);
2581 :
3136 sfrost 2582 EUB : /* ALTER TABLESPACE <foo> with RENAME TO, OWNER TO, SET, RESET */
1661 tgl 2583 GIC 45 : else if (Matches("ALTER", "TABLESPACE", MatchAny))
1661 tgl 2584 LBC 0 : COMPLETE_WITH("RENAME TO", "OWNER TO", "SET", "RESET");
4799 itagaki.takahiro 2585 ECB : /* ALTER TABLESPACE <foo> SET|RESET */
1661 tgl 2586 GBC 45 : else if (Matches("ALTER", "TABLESPACE", MatchAny, "SET|RESET"))
1661 tgl 2587 UIC 0 : COMPLETE_WITH("(");
2588 : /* ALTER TABLESPACE <foo> SET|RESET ( */
1661 tgl 2589 GIC 45 : else if (Matches("ALTER", "TABLESPACE", MatchAny, "SET|RESET", "("))
1661 tgl 2590 LBC 0 : COMPLETE_WITH("seq_page_cost", "random_page_cost",
1119 tmunro 2591 ECB : "effective_io_concurrency", "maintenance_io_concurrency");
4799 itagaki.takahiro 2592 EUB :
2593 : /* ALTER TEXT SEARCH */
1661 tgl 2594 CBC 45 : else if (Matches("ALTER", "TEXT", "SEARCH"))
1661 tgl 2595 LBC 0 : COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
1661 tgl 2596 GBC 45 : else if (Matches("ALTER", "TEXT", "SEARCH", "TEMPLATE|PARSER", MatchAny))
1661 tgl 2597 UIC 0 : COMPLETE_WITH("RENAME TO", "SET SCHEMA");
1661 tgl 2598 CBC 45 : else if (Matches("ALTER", "TEXT", "SEARCH", "DICTIONARY", MatchAny))
1128 tgl 2599 LBC 0 : COMPLETE_WITH("(", "OWNER TO", "RENAME TO", "SET SCHEMA");
1661 tgl 2600 GBC 45 : else if (Matches("ALTER", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
1661 tgl 2601 UIC 0 : COMPLETE_WITH("ADD MAPPING FOR", "ALTER MAPPING",
1661 tgl 2602 ECB : "DROP MAPPING FOR",
2603 : "OWNER TO", "RENAME TO", "SET SCHEMA");
5686 bruce 2604 EUB :
2605 : /* complete ALTER TYPE <foo> with actions */
1661 tgl 2606 CBC 45 : else if (Matches("ALTER", "TYPE", MatchAny))
1661 tgl 2607 LBC 0 : COMPLETE_WITH("ADD ATTRIBUTE", "ADD VALUE", "ALTER ATTRIBUTE",
1661 tgl 2608 EUB : "DROP ATTRIBUTE",
2609 : "OWNER TO", "RENAME", "SET SCHEMA", "SET (");
4427 itagaki.takahiro 2610 ECB : /* complete ALTER TYPE <foo> ADD with actions */
1661 tgl 2611 CBC 45 : else if (Matches("ALTER", "TYPE", MatchAny, "ADD"))
1661 tgl 2612 UIC 0 : COMPLETE_WITH("ATTRIBUTE", "VALUE");
2613 : /* ALTER TYPE <foo> RENAME */
1661 tgl 2614 GIC 45 : else if (Matches("ALTER", "TYPE", MatchAny, "RENAME"))
1661 tgl 2615 UIC 0 : COMPLETE_WITH("ATTRIBUTE", "TO", "VALUE");
2343 rhaas 2616 ECB : /* ALTER TYPE xxx RENAME (ATTRIBUTE|VALUE) yyy */
1661 tgl 2617 CBC 45 : else if (Matches("ALTER", "TYPE", MatchAny, "RENAME", "ATTRIBUTE|VALUE", MatchAny))
1661 tgl 2618 UBC 0 : COMPLETE_WITH("TO");
2153 bruce 2619 ECB :
4382 bruce 2620 EUB : /*
2652 tgl 2621 ECB : * If we have ALTER TYPE <sth> ALTER/DROP/RENAME ATTRIBUTE, provide list
2622 : * of attributes
4382 bruce 2623 EUB : */
1661 tgl 2624 GBC 45 : else if (Matches("ALTER", "TYPE", MatchAny, "ALTER|DROP|RENAME", "ATTRIBUTE"))
434 tgl 2625 UIC 0 : COMPLETE_WITH_ATTR(prev3_wd);
2626 : /* ALTER TYPE ALTER ATTRIBUTE <foo> */
1661 tgl 2627 CBC 45 : else if (Matches("ALTER", "TYPE", MatchAny, "ALTER", "ATTRIBUTE", MatchAny))
1661 tgl 2628 UBC 0 : COMPLETE_WITH("TYPE");
2629 : /* complete ALTER TYPE <sth> RENAME VALUE with list of enum values */
237 michael 2630 GNC 45 : else if (Matches("ALTER", "TYPE", MatchAny, "RENAME", "VALUE"))
2631 3 : COMPLETE_WITH_ENUM_VALUE(prev3_wd);
2632 : /* ALTER TYPE <foo> SET */
2633 42 : else if (Matches("ALTER", "TYPE", MatchAny, "SET"))
237 michael 2634 UNC 0 : COMPLETE_WITH("(", "SCHEMA");
2635 : /* complete ALTER TYPE <foo> SET ( with settable properties */
237 michael 2636 GNC 42 : else if (Matches("ALTER", "TYPE", MatchAny, "SET", "("))
237 michael 2637 UNC 0 : COMPLETE_WITH("ANALYZE", "RECEIVE", "SEND", "STORAGE", "SUBSCRIPT",
2638 : "TYPMOD_IN", "TYPMOD_OUT");
2639 :
2640 : /* complete ALTER GROUP <foo> */
1661 tgl 2641 GIC 42 : else if (Matches("ALTER", "GROUP", MatchAny))
1661 tgl 2642 UIC 0 : COMPLETE_WITH("ADD USER", "DROP USER", "RENAME TO");
2643 : /* complete ALTER GROUP <foo> ADD|DROP with USER */
1661 tgl 2644 GIC 42 : else if (Matches("ALTER", "GROUP", MatchAny, "ADD|DROP"))
1661 tgl 2645 UIC 0 : COMPLETE_WITH("USER");
2668 tgl 2646 ECB : /* complete ALTER GROUP <foo> ADD|DROP USER with a user name */
1661 tgl 2647 GBC 42 : else if (Matches("ALTER", "GROUP", MatchAny, "ADD|DROP", "USER"))
6447 tgl 2648 UIC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2649 :
1661 tgl 2650 ECB : /*
1661 tgl 2651 EUB : * ANALYZE [ ( option [, ...] ) ] [ table_and_columns [, ...] ]
2652 : * ANALYZE [ VERBOSE ] [ table_and_columns [, ...] ]
1661 tgl 2653 ECB : */
1661 tgl 2654 GBC 42 : else if (Matches("ANALYZE"))
434 tgl 2655 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_analyzables,
434 tgl 2656 ECB : "VERBOSE");
1495 michael 2657 GBC 42 : else if (HeadMatches("ANALYZE", "(*") &&
1495 michael 2658 CBC 2 : !HeadMatches("ANALYZE", "(*)"))
2659 : {
1495 michael 2660 EUB : /*
2661 : * This fires if we're in an unfinished parenthesized option list.
2662 : * get_previous_words treats a completed parenthesized option list as
1495 michael 2663 ECB : * one word, so the above test is correct.
1495 michael 2664 EUB : */
1495 michael 2665 CBC 2 : if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
2 drowley 2666 GNC 2 : COMPLETE_WITH("VERBOSE", "SKIP_LOCKED", "BUFFER_USAGE_LIMIT");
1417 fujii 2667 LBC 0 : else if (TailMatches("VERBOSE|SKIP_LOCKED"))
1417 fujii 2668 UBC 0 : COMPLETE_WITH("ON", "OFF");
2669 : }
1661 tgl 2670 GIC 40 : else if (HeadMatches("ANALYZE") && TailMatches("("))
2671 : /* "ANALYZE (" should be caught above, so assume we want columns */
434 tgl 2672 UIC 0 : COMPLETE_WITH_ATTR(prev2_wd);
1661 tgl 2673 GIC 40 : else if (HeadMatches("ANALYZE"))
434 tgl 2674 LBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_analyzables);
1661 tgl 2675 EUB :
2676 : /* BEGIN */
1661 tgl 2677 CBC 40 : else if (Matches("BEGIN"))
1661 tgl 2678 UBC 0 : COMPLETE_WITH("WORK", "TRANSACTION", "ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
2411 kgrittn 2679 ECB : /* END, ABORT */
1661 tgl 2680 GBC 40 : else if (Matches("END|ABORT"))
1477 peter 2681 UIC 0 : COMPLETE_WITH("AND", "WORK", "TRANSACTION");
2682 : /* COMMIT */
1661 tgl 2683 GIC 40 : else if (Matches("COMMIT"))
1477 peter 2684 UIC 0 : COMPLETE_WITH("AND", "WORK", "TRANSACTION", "PREPARED");
2685 : /* RELEASE SAVEPOINT */
1661 tgl 2686 CBC 40 : else if (Matches("RELEASE"))
1661 tgl 2687 UIC 0 : COMPLETE_WITH("SAVEPOINT");
2652 tgl 2688 EUB : /* ROLLBACK */
1661 tgl 2689 GBC 40 : else if (Matches("ROLLBACK"))
1477 peter 2690 UIC 0 : COMPLETE_WITH("AND", "WORK", "TRANSACTION", "TO SAVEPOINT", "PREPARED");
1477 peter 2691 CBC 40 : else if (Matches("ABORT|END|COMMIT|ROLLBACK", "AND"))
1477 peter 2692 UBC 0 : COMPLETE_WITH("CHAIN");
2693 : /* CALL */
1661 tgl 2694 GIC 40 : else if (Matches("CALL"))
434 tgl 2695 LBC 0 : COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_procedures);
1661 tgl 2696 GBC 40 : else if (Matches("CALL", MatchAny))
1661 tgl 2697 UIC 0 : COMPLETE_WITH("(");
2698 : /* CLOSE */
815 fujii 2699 CBC 40 : else if (Matches("CLOSE"))
434 tgl 2700 UBC 0 : COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_cursors,
2701 : "ALL");
8535 bruce 2702 ECB : /* CLUSTER */
1661 tgl 2703 GBC 40 : else if (Matches("CLUSTER"))
434 tgl 2704 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_clusterables,
434 tgl 2705 ECB : "VERBOSE");
857 michael 2706 GBC 80 : else if (Matches("CLUSTER", "VERBOSE") ||
857 michael 2707 GIC 40 : Matches("CLUSTER", "(*)"))
434 tgl 2708 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_clusterables);
2709 : /* If we have CLUSTER <sth>, then add "USING" */
857 michael 2710 CBC 40 : else if (Matches("CLUSTER", MatchAnyExcept("VERBOSE|ON|(|(*)")))
1661 tgl 2711 UBC 0 : COMPLETE_WITH("USING");
3884 rhaas 2712 ECB : /* If we have CLUSTER VERBOSE <sth>, then add "USING" */
857 michael 2713 GBC 40 : else if (Matches("CLUSTER", "VERBOSE|(*)", MatchAny))
1661 tgl 2714 LBC 0 : COMPLETE_WITH("USING");
2652 tgl 2715 EUB : /* If we have CLUSTER <sth> USING, then add the index as well */
1661 tgl 2716 CBC 80 : else if (Matches("CLUSTER", MatchAny, "USING") ||
857 michael 2717 GBC 40 : Matches("CLUSTER", "VERBOSE|(*)", MatchAny, "USING"))
2718 : {
434 tgl 2719 UIC 0 : set_completion_reference(prev2_wd);
2720 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_index_of_table);
2721 : }
857 michael 2722 CBC 40 : else if (HeadMatches("CLUSTER", "(*") &&
857 michael 2723 UBC 0 : !HeadMatches("CLUSTER", "(*)"))
2724 : {
2725 : /*
2726 : * This fires if we're in an unfinished parenthesized option list.
857 michael 2727 ECB : * get_previous_words treats a completed parenthesized option list as
857 michael 2728 EUB : * one word, so the above test is correct.
2729 : */
857 michael 2730 LBC 0 : if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
857 michael 2731 UBC 0 : COMPLETE_WITH("VERBOSE");
2732 : }
3884 rhaas 2733 ECB :
8323 peter_e 2734 EUB : /* COMMENT */
1661 tgl 2735 GIC 40 : else if (Matches("COMMENT"))
1661 tgl 2736 UIC 0 : COMPLETE_WITH("ON");
1661 tgl 2737 GIC 40 : else if (Matches("COMMENT", "ON"))
520 michael 2738 UIC 0 : COMPLETE_WITH("ACCESS METHOD", "AGGREGATE", "CAST", "COLLATION",
2739 : "COLUMN", "CONSTRAINT", "CONVERSION", "DATABASE",
520 michael 2740 ECB : "DOMAIN", "EXTENSION", "EVENT TRIGGER",
520 michael 2741 EUB : "FOREIGN DATA WRAPPER", "FOREIGN TABLE",
2742 : "FUNCTION", "INDEX", "LANGUAGE", "LARGE OBJECT",
520 michael 2743 ECB : "MATERIALIZED VIEW", "OPERATOR", "POLICY",
520 michael 2744 EUB : "PROCEDURE", "PROCEDURAL LANGUAGE", "PUBLICATION", "ROLE",
2745 : "ROUTINE", "RULE", "SCHEMA", "SEQUENCE", "SERVER",
520 michael 2746 ECB : "STATISTICS", "SUBSCRIPTION", "TABLE",
2747 : "TABLESPACE", "TEXT SEARCH", "TRANSFORM FOR",
2748 : "TRIGGER", "TYPE", "VIEW");
1661 tgl 2749 CBC 40 : else if (Matches("COMMENT", "ON", "ACCESS", "METHOD"))
2497 alvherre 2750 UBC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
1661 tgl 2751 GIC 40 : else if (Matches("COMMENT", "ON", "CONSTRAINT"))
3859 peter_e 2752 LBC 0 : COMPLETE_WITH_QUERY(Query_for_all_table_constraints);
1661 tgl 2753 GBC 40 : else if (Matches("COMMENT", "ON", "CONSTRAINT", MatchAny))
1661 tgl 2754 UIC 0 : COMPLETE_WITH("ON");
1661 tgl 2755 GIC 40 : else if (Matches("COMMENT", "ON", "CONSTRAINT", MatchAny, "ON"))
2756 : {
434 tgl 2757 CBC 1 : set_completion_reference(prev2_wd);
434 tgl 2758 GBC 1 : COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_tables_for_constraint,
2759 : "DOMAIN");
3859 peter_e 2760 ECB : }
520 michael 2761 GBC 39 : else if (Matches("COMMENT", "ON", "CONSTRAINT", MatchAny, "ON", "DOMAIN"))
434 tgl 2762 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains);
1661 tgl 2763 CBC 39 : else if (Matches("COMMENT", "ON", "EVENT", "TRIGGER"))
3282 rhaas 2764 UBC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
520 michael 2765 GIC 39 : else if (Matches("COMMENT", "ON", "FOREIGN"))
520 michael 2766 UIC 0 : COMPLETE_WITH("DATA WRAPPER", "TABLE");
520 michael 2767 GIC 39 : else if (Matches("COMMENT", "ON", "FOREIGN", "TABLE"))
434 tgl 2768 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables);
520 michael 2769 GIC 39 : else if (Matches("COMMENT", "ON", "MATERIALIZED", "VIEW"))
434 tgl 2770 LBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews);
520 michael 2771 GBC 39 : else if (Matches("COMMENT", "ON", "POLICY"))
520 michael 2772 UIC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_policies);
520 michael 2773 CBC 39 : else if (Matches("COMMENT", "ON", "POLICY", MatchAny))
520 michael 2774 LBC 0 : COMPLETE_WITH("ON");
520 michael 2775 GIC 39 : else if (Matches("COMMENT", "ON", "POLICY", MatchAny, "ON"))
2776 : {
434 tgl 2777 UIC 0 : set_completion_reference(prev2_wd);
2778 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables_for_policy);
2779 : }
520 michael 2780 GIC 39 : else if (Matches("COMMENT", "ON", "PROCEDURAL", "LANGUAGE"))
520 michael 2781 LBC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_languages);
520 michael 2782 CBC 39 : else if (Matches("COMMENT", "ON", "RULE", MatchAny))
520 michael 2783 UBC 0 : COMPLETE_WITH("ON");
520 michael 2784 GBC 39 : else if (Matches("COMMENT", "ON", "RULE", MatchAny, "ON"))
2785 : {
434 tgl 2786 LBC 0 : set_completion_reference(prev2_wd);
434 tgl 2787 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables_for_rule);
520 michael 2788 EUB : }
520 michael 2789 CBC 39 : else if (Matches("COMMENT", "ON", "TEXT", "SEARCH"))
520 michael 2790 UBC 0 : COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
520 michael 2791 GIC 39 : else if (Matches("COMMENT", "ON", "TEXT", "SEARCH", "CONFIGURATION"))
434 tgl 2792 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_ts_configurations);
520 michael 2793 CBC 39 : else if (Matches("COMMENT", "ON", "TEXT", "SEARCH", "DICTIONARY"))
434 tgl 2794 UBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_ts_dictionaries);
520 michael 2795 GIC 39 : else if (Matches("COMMENT", "ON", "TEXT", "SEARCH", "PARSER"))
434 tgl 2796 LBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_ts_parsers);
520 michael 2797 GBC 39 : else if (Matches("COMMENT", "ON", "TEXT", "SEARCH", "TEMPLATE"))
434 tgl 2798 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_ts_templates);
520 michael 2799 CBC 39 : else if (Matches("COMMENT", "ON", "TRANSFORM", "FOR"))
434 tgl 2800 UBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
520 michael 2801 GIC 39 : else if (Matches("COMMENT", "ON", "TRANSFORM", "FOR", MatchAny))
520 michael 2802 LBC 0 : COMPLETE_WITH("LANGUAGE");
520 michael 2803 GBC 39 : else if (Matches("COMMENT", "ON", "TRANSFORM", "FOR", MatchAny, "LANGUAGE"))
2804 : {
434 tgl 2805 LBC 0 : set_completion_reference(prev2_wd);
520 michael 2806 UBC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_languages);
520 michael 2807 ECB : }
520 michael 2808 GBC 39 : else if (Matches("COMMENT", "ON", "TRIGGER", MatchAny))
520 michael 2809 UIC 0 : COMPLETE_WITH("ON");
520 michael 2810 CBC 39 : else if (Matches("COMMENT", "ON", "TRIGGER", MatchAny, "ON"))
520 michael 2811 EUB : {
434 tgl 2812 LBC 0 : set_completion_reference(prev2_wd);
434 tgl 2813 UBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables_for_trigger);
2814 : }
1661 tgl 2815 CBC 78 : else if (Matches("COMMENT", "ON", MatchAny, MatchAnyExcept("IS")) ||
1661 tgl 2816 GBC 78 : Matches("COMMENT", "ON", MatchAny, MatchAny, MatchAnyExcept("IS")) ||
520 michael 2817 GIC 78 : Matches("COMMENT", "ON", MatchAny, MatchAny, MatchAny, MatchAnyExcept("IS")) ||
2818 39 : Matches("COMMENT", "ON", MatchAny, MatchAny, MatchAny, MatchAny, MatchAnyExcept("IS")))
1661 tgl 2819 LBC 0 : COMPLETE_WITH("IS");
8323 peter_e 2820 EUB :
2821 : /* COPY */
8397 bruce 2822 ECB :
2823 : /*
2636 peter_e 2824 EUB : * If we have COPY, offer list of tables or "(" (Also cover the analogous
2825 : * backslash command).
8397 bruce 2826 ECB : */
1661 tgl 2827 GBC 39 : else if (Matches("COPY|\\copy"))
434 tgl 2828 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_tables, "(");
992 michael 2829 ECB : /* Complete COPY ( with legal query commands */
1661 tgl 2830 GBC 39 : else if (Matches("COPY|\\copy", "("))
696 michael 2831 UIC 0 : COMPLETE_WITH("SELECT", "TABLE", "VALUES", "INSERT INTO", "UPDATE", "DELETE FROM", "WITH");
992 michael 2832 ECB : /* Complete COPY <sth> */
992 michael 2833 CBC 39 : else if (Matches("COPY|\\copy", MatchAny))
1661 tgl 2834 UIC 0 : COMPLETE_WITH("FROM", "TO");
992 michael 2835 EUB : /* Complete COPY <sth> FROM|TO with filename */
992 michael 2836 GBC 39 : else if (Matches("COPY", MatchAny, "FROM|TO"))
2837 : {
4058 alvherre 2838 CBC 4 : completion_charp = "";
1172 tgl 2839 GBC 4 : completion_force_quote = true; /* COPY requires quoted filename */
1213 tgl 2840 GIC 4 : matches = rl_completion_matches(text, complete_from_files);
2841 : }
1172 2842 35 : else if (Matches("\\copy", MatchAny, "FROM|TO"))
2843 : {
1172 tgl 2844 UIC 0 : completion_charp = "";
2845 0 : completion_force_quote = false;
1172 tgl 2846 UBC 0 : matches = rl_completion_matches(text, complete_from_files);
1172 tgl 2847 EUB : }
2848 :
2849 : /* Complete COPY <sth> TO <sth> */
992 michael 2850 GIC 35 : else if (Matches("COPY|\\copy", MatchAny, "TO", MatchAny))
992 michael 2851 LBC 0 : COMPLETE_WITH("WITH (");
992 michael 2852 EUB :
992 michael 2853 ECB : /* Complete COPY <sth> FROM <sth> */
992 michael 2854 GBC 35 : else if (Matches("COPY|\\copy", MatchAny, "FROM", MatchAny))
992 michael 2855 UIC 0 : COMPLETE_WITH("WITH (", "WHERE");
2856 :
2857 : /* Complete COPY <sth> FROM|TO filename WITH ( */
992 michael 2858 GIC 35 : else if (Matches("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "WITH", "("))
2859 1 : COMPLETE_WITH("FORMAT", "FREEZE", "DELIMITER", "NULL",
2860 : "HEADER", "QUOTE", "ESCAPE", "FORCE_QUOTE",
2861 : "FORCE_NOT_NULL", "FORCE_NULL", "ENCODING", "DEFAULT");
2862 :
2863 : /* Complete COPY <sth> FROM|TO filename WITH (FORMAT */
2864 34 : else if (Matches("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "WITH", "(", "FORMAT"))
992 michael 2865 LBC 0 : COMPLETE_WITH("binary", "csv", "text");
992 michael 2866 EUB :
992 michael 2867 ECB : /* Complete COPY <sth> FROM <sth> WITH (<options>) */
992 michael 2868 GBC 34 : else if (Matches("COPY|\\copy", MatchAny, "FROM", MatchAny, "WITH", MatchAny))
992 michael 2869 LBC 0 : COMPLETE_WITH("WHERE");
8535 bruce 2870 EUB :
2568 teodor 2871 ECB : /* CREATE ACCESS METHOD */
2872 : /* Complete "CREATE ACCESS METHOD <name>" */
1661 tgl 2873 CBC 34 : else if (Matches("CREATE", "ACCESS", "METHOD", MatchAny))
1661 tgl 2874 LBC 0 : COMPLETE_WITH("TYPE");
2875 : /* Complete "CREATE ACCESS METHOD <name> TYPE" */
1661 tgl 2876 GIC 34 : else if (Matches("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE"))
1406 michael 2877 LBC 0 : COMPLETE_WITH("INDEX", "TABLE");
2568 teodor 2878 EUB : /* Complete "CREATE ACCESS METHOD <name> TYPE <type>" */
1661 tgl 2879 CBC 34 : else if (Matches("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE", MatchAny))
1661 tgl 2880 UBC 0 : COMPLETE_WITH("HANDLER");
2568 teodor 2881 ECB :
776 tmunro 2882 EUB : /* CREATE COLLATION */
776 tmunro 2883 CBC 34 : else if (Matches("CREATE", "COLLATION", MatchAny))
776 tmunro 2884 UBC 0 : COMPLETE_WITH("(", "FROM");
776 tmunro 2885 CBC 34 : else if (Matches("CREATE", "COLLATION", MatchAny, "FROM"))
434 tgl 2886 UBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_collations);
776 tmunro 2887 CBC 34 : else if (HeadMatches("CREATE", "COLLATION", MatchAny, "(*"))
776 tmunro 2888 EUB : {
776 tmunro 2889 LBC 0 : if (TailMatches("(|*,"))
776 tmunro 2890 UBC 0 : COMPLETE_WITH("LOCALE =", "LC_COLLATE =", "LC_CTYPE =",
776 tmunro 2891 ECB : "PROVIDER =", "DETERMINISTIC =");
776 tmunro 2892 UIC 0 : else if (TailMatches("PROVIDER", "="))
776 tmunro 2893 UBC 0 : COMPLETE_WITH("libc", "icu");
2894 0 : else if (TailMatches("DETERMINISTIC", "="))
776 tmunro 2895 UIC 0 : COMPLETE_WITH("true", "false");
776 tmunro 2896 ECB : }
776 tmunro 2897 EUB :
6447 tgl 2898 ECB : /* CREATE DATABASE */
1661 tgl 2899 GBC 34 : else if (Matches("CREATE", "DATABASE", MatchAny))
1661 tgl 2900 LBC 0 : COMPLETE_WITH("OWNER", "TEMPLATE", "ENCODING", "TABLESPACE",
2901 : "IS_TEMPLATE", "STRATEGY",
1661 tgl 2902 EUB : "ALLOW_CONNECTIONS", "CONNECTION LIMIT",
388 peter 2903 : "LC_COLLATE", "LC_CTYPE", "LOCALE", "OID",
2904 : "LOCALE_PROVIDER", "ICU_LOCALE");
6447 tgl 2905 ECB :
1661 tgl 2906 GBC 34 : else if (Matches("CREATE", "DATABASE", MatchAny, "TEMPLATE"))
5686 bruce 2907 LBC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_template_databases);
376 rhaas 2908 GBC 34 : else if (Matches("CREATE", "DATABASE", MatchAny, "STRATEGY"))
376 rhaas 2909 LBC 0 : COMPLETE_WITH("WAL_LOG", "FILE_COPY");
5686 bruce 2910 EUB :
506 michael 2911 ECB : /* CREATE DOMAIN */
506 michael 2912 GBC 34 : else if (Matches("CREATE", "DOMAIN", MatchAny))
506 michael 2913 LBC 0 : COMPLETE_WITH("AS");
506 michael 2914 GBC 34 : else if (Matches("CREATE", "DOMAIN", MatchAny, "AS"))
434 tgl 2915 LBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
506 michael 2916 GBC 34 : else if (Matches("CREATE", "DOMAIN", MatchAny, "AS", MatchAny))
506 michael 2917 LBC 0 : COMPLETE_WITH("COLLATE", "DEFAULT", "CONSTRAINT",
506 michael 2918 EUB : "NOT NULL", "NULL", "CHECK (");
506 michael 2919 CBC 34 : else if (Matches("CREATE", "DOMAIN", MatchAny, "COLLATE"))
434 tgl 2920 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_collations);
506 michael 2921 EUB :
4443 tgl 2922 : /* CREATE EXTENSION */
2923 : /* Complete with available extensions rather than installed ones. */
1661 tgl 2924 CBC 34 : else if (Matches("CREATE", "EXTENSION"))
4443 tgl 2925 UBC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_available_extensions);
4443 tgl 2926 ECB : /* CREATE EXTENSION <name> */
1661 tgl 2927 GIC 34 : else if (Matches("CREATE", "EXTENSION", MatchAny))
1661 tgl 2928 UBC 0 : COMPLETE_WITH("WITH SCHEMA", "CASCADE", "VERSION");
2728 rhaas 2929 EUB : /* CREATE EXTENSION <name> VERSION */
1661 tgl 2930 GIC 34 : else if (Matches("CREATE", "EXTENSION", MatchAny, "VERSION"))
2728 rhaas 2931 ECB : {
434 tgl 2932 LBC 0 : set_completion_reference(prev2_wd);
292 2933 0 : COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions);
2728 rhaas 2934 ECB : }
4443 tgl 2935 EUB :
2936 : /* CREATE FOREIGN */
1661 tgl 2937 GIC 34 : else if (Matches("CREATE", "FOREIGN"))
1661 tgl 2938 UIC 0 : COMPLETE_WITH("DATA WRAPPER", "TABLE");
2939 :
2940 : /* CREATE FOREIGN DATA WRAPPER */
1661 tgl 2941 GIC 34 : else if (Matches("CREATE", "FOREIGN", "DATA", "WRAPPER", MatchAny))
1661 tgl 2942 UIC 0 : COMPLETE_WITH("HANDLER", "VALIDATOR", "OPTIONS");
5224 peter_e 2943 ECB :
449 fujii 2944 EUB : /* CREATE FOREIGN TABLE */
449 fujii 2945 GIC 34 : else if (Matches("CREATE", "FOREIGN", "TABLE", MatchAny))
449 fujii 2946 LBC 0 : COMPLETE_WITH("(", "PARTITION OF");
449 fujii 2947 EUB :
2948 : /* CREATE INDEX --- is allowed inside CREATE SCHEMA, so use TailMatches */
8397 bruce 2949 ECB : /* First off we complete CREATE UNIQUE with "INDEX" */
1661 tgl 2950 GBC 34 : else if (TailMatches("CREATE", "UNIQUE"))
1661 tgl 2951 UIC 0 : COMPLETE_WITH("INDEX");
2495 rhaas 2952 ECB :
2953 : /*
2954 : * If we have CREATE|UNIQUE INDEX, then add "ON", "CONCURRENTLY", and
2955 : * existing indexes
2956 : */
1661 tgl 2957 GIC 34 : else if (TailMatches("CREATE|UNIQUE", "INDEX"))
434 tgl 2958 LBC 0 : COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_indexes,
2959 : "ON", "CONCURRENTLY");
1809 tgl 2960 EUB :
1906 alvherre 2961 : /*
2962 : * Complete ... INDEX|CONCURRENTLY [<name>] ON with a list of relations
2963 : * that indexes can be created on
2964 : */
1661 tgl 2965 GIC 68 : else if (TailMatches("INDEX|CONCURRENTLY", MatchAny, "ON") ||
1661 tgl 2966 CBC 34 : TailMatches("INDEX|CONCURRENTLY", "ON"))
434 tgl 2967 UBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexables);
2968 :
2969 : /*
2495 rhaas 2970 ECB : * Complete CREATE|UNIQUE INDEX CONCURRENTLY with "ON" and existing
2495 rhaas 2971 EUB : * indexes
2972 : */
1661 tgl 2973 GIC 34 : else if (TailMatches("CREATE|UNIQUE", "INDEX", "CONCURRENTLY"))
434 tgl 2974 LBC 0 : COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_indexes,
434 tgl 2975 ECB : "ON");
2976 : /* Complete CREATE|UNIQUE INDEX [CONCURRENTLY] <sth> with "ON" */
1661 tgl 2977 GIC 68 : else if (TailMatches("CREATE|UNIQUE", "INDEX", MatchAny) ||
2978 34 : TailMatches("CREATE|UNIQUE", "INDEX", "CONCURRENTLY", MatchAny))
1661 tgl 2979 UIC 0 : COMPLETE_WITH("ON");
8397 bruce 2980 ECB :
8397 bruce 2981 EUB : /*
2982 : * Complete INDEX <name> ON <table> with a list of table columns (which
2983 : * should really be in parens)
8397 bruce 2984 ECB : */
1661 tgl 2985 GBC 68 : else if (TailMatches("INDEX", MatchAny, "ON", MatchAny) ||
1661 tgl 2986 GIC 34 : TailMatches("INDEX|CONCURRENTLY", "ON", MatchAny))
1661 tgl 2987 UIC 0 : COMPLETE_WITH("(", "USING");
1661 tgl 2988 GIC 68 : else if (TailMatches("INDEX", MatchAny, "ON", MatchAny, "(") ||
1661 tgl 2989 CBC 34 : TailMatches("INDEX|CONCURRENTLY", "ON", MatchAny, "("))
434 tgl 2990 UBC 0 : COMPLETE_WITH_ATTR(prev2_wd);
2991 : /* same if you put in USING */
1661 tgl 2992 CBC 34 : else if (TailMatches("ON", MatchAny, "USING", MatchAny, "("))
434 tgl 2993 UBC 0 : COMPLETE_WITH_ATTR(prev4_wd);
2994 : /* Complete USING with an index method */
1661 tgl 2995 CBC 68 : else if (TailMatches("INDEX", MatchAny, MatchAny, "ON", MatchAny, "USING") ||
1661 tgl 2996 GBC 68 : TailMatches("INDEX", MatchAny, "ON", MatchAny, "USING") ||
1661 tgl 2997 GIC 34 : TailMatches("INDEX", "ON", MatchAny, "USING"))
1406 michael 2998 UIC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_index_access_methods);
1661 tgl 2999 CBC 34 : else if (TailMatches("ON", MatchAny, "USING", MatchAny) &&
1661 tgl 3000 UBC 0 : !TailMatches("POLICY", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny) &&
1661 tgl 3001 LBC 0 : !TailMatches("FOR", MatchAny, MatchAny, MatchAny))
1661 tgl 3002 UBC 0 : COMPLETE_WITH("(");
8397 bruce 3003 ECB :
3004 : /* CREATE OR REPLACE */
1304 fujii 3005 GBC 34 : else if (Matches("CREATE", "OR"))
1304 fujii 3006 UBC 0 : COMPLETE_WITH("REPLACE");
3007 :
3124 sfrost 3008 EUB : /* CREATE POLICY */
3009 : /* Complete "CREATE POLICY <name> ON" */
1661 tgl 3010 GBC 34 : else if (Matches("CREATE", "POLICY", MatchAny))
1661 tgl 3011 UBC 0 : COMPLETE_WITH("ON");
3012 : /* Complete "CREATE POLICY <name> ON <table>" */
1661 tgl 3013 GIC 34 : else if (Matches("CREATE", "POLICY", MatchAny, "ON"))
434 tgl 3014 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
2316 sfrost 3015 ECB : /* Complete "CREATE POLICY <name> ON <table> AS|FOR|TO|USING|WITH CHECK" */
1661 tgl 3016 GBC 34 : else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny))
1661 tgl 3017 UIC 0 : COMPLETE_WITH("AS", "FOR", "TO", "USING (", "WITH CHECK (");
3018 : /* CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE */
1661 tgl 3019 GIC 34 : else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS"))
1661 tgl 3020 UIC 0 : COMPLETE_WITH("PERMISSIVE", "RESTRICTIVE");
3021 :
2153 bruce 3022 ECB : /*
2153 bruce 3023 EUB : * CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE
2153 bruce 3024 ECB : * FOR|TO|USING|WITH CHECK
2153 bruce 3025 EUB : */
1661 tgl 3026 GIC 34 : else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny))
1661 tgl 3027 UIC 0 : COMPLETE_WITH("FOR", "TO", "USING", "WITH CHECK");
2668 tgl 3028 ECB : /* CREATE POLICY <name> ON <table> FOR ALL|SELECT|INSERT|UPDATE|DELETE */
1661 tgl 3029 GBC 34 : else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR"))
1661 tgl 3030 LBC 0 : COMPLETE_WITH("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
3124 sfrost 3031 EUB : /* Complete "CREATE POLICY <name> ON <table> FOR INSERT TO|WITH CHECK" */
1661 tgl 3032 CBC 34 : else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "INSERT"))
1661 tgl 3033 UBC 0 : COMPLETE_WITH("TO", "WITH CHECK (");
3034 : /* Complete "CREATE POLICY <name> ON <table> FOR SELECT|DELETE TO|USING" */
1661 tgl 3035 CBC 34 : else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "SELECT|DELETE"))
1661 tgl 3036 UBC 0 : COMPLETE_WITH("TO", "USING (");
3037 : /* CREATE POLICY <name> ON <table> FOR ALL|UPDATE TO|USING|WITH CHECK */
1661 tgl 3038 GIC 34 : else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "ALL|UPDATE"))
1661 tgl 3039 UIC 0 : COMPLETE_WITH("TO", "USING (", "WITH CHECK (");
3124 sfrost 3040 ECB : /* Complete "CREATE POLICY <name> ON <table> TO <role>" */
1661 tgl 3041 GBC 34 : else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "TO"))
434 tgl 3042 UIC 0 : COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
434 tgl 3043 ECB : Keywords_for_list_of_grant_roles);
3124 sfrost 3044 EUB : /* Complete "CREATE POLICY <name> ON <table> USING (" */
1661 tgl 3045 GIC 34 : else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "USING"))
1661 tgl 3046 LBC 0 : COMPLETE_WITH("(");
3047 :
2153 bruce 3048 EUB : /*
3049 : * CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
3050 : * ALL|SELECT|INSERT|UPDATE|DELETE
3051 : */
1661 tgl 3052 GIC 34 : else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR"))
1661 tgl 3053 LBC 0 : COMPLETE_WITH("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
2153 bruce 3054 EUB :
3055 : /*
3056 : * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
2153 bruce 3057 ECB : * INSERT TO|WITH CHECK"
2153 bruce 3058 EUB : */
1661 tgl 3059 GIC 34 : else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "INSERT"))
1661 tgl 3060 UIC 0 : COMPLETE_WITH("TO", "WITH CHECK (");
2153 bruce 3061 ECB :
2153 bruce 3062 EUB : /*
3063 : * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
3064 : * SELECT|DELETE TO|USING"
3065 : */
1661 tgl 3066 CBC 34 : else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "SELECT|DELETE"))
1661 tgl 3067 UBC 0 : COMPLETE_WITH("TO", "USING (");
3068 :
3069 : /*
3070 : * CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
3071 : * ALL|UPDATE TO|USING|WITH CHECK
3072 : */
1661 tgl 3073 CBC 34 : else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "ALL|UPDATE"))
1661 tgl 3074 UBC 0 : COMPLETE_WITH("TO", "USING (", "WITH CHECK (");
3075 :
3076 : /*
3077 : * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE TO
3078 : * <role>"
3079 : */
1661 tgl 3080 GIC 34 : else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "TO"))
434 tgl 3081 LBC 0 : COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
434 tgl 3082 ECB : Keywords_for_list_of_grant_roles);
2153 bruce 3083 EUB :
3084 : /*
3085 : * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE
3086 : * USING ("
3087 : */
1661 tgl 3088 GIC 34 : else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "USING"))
1661 tgl 3089 LBC 0 : COMPLETE_WITH("(");
2316 sfrost 3090 EUB :
3091 :
3092 : /* CREATE PUBLICATION */
1661 tgl 3093 CBC 34 : else if (Matches("CREATE", "PUBLICATION", MatchAny))
199 alvherre 3094 LBC 0 : COMPLETE_WITH("FOR TABLE", "FOR ALL TABLES", "FOR TABLES IN SCHEMA", "WITH (");
1661 tgl 3095 GBC 34 : else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR"))
199 alvherre 3096 UIC 0 : COMPLETE_WITH("TABLE", "ALL TABLES", "TABLES IN SCHEMA");
585 fujii 3097 GIC 34 : else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL"))
191 alvherre 3098 UIC 0 : COMPLETE_WITH("TABLES");
367 tomas.vondra 3099 GIC 34 : else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES"))
191 alvherre 3100 UIC 0 : COMPLETE_WITH("WITH (");
191 alvherre 3101 CBC 34 : else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLES"))
191 alvherre 3102 LBC 0 : COMPLETE_WITH("IN SCHEMA");
367 tomas.vondra 3103 GBC 34 : else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLE", MatchAny) && !ends_with(prev_wd, ','))
411 akapila 3104 LBC 0 : COMPLETE_WITH("WHERE (", "WITH (");
585 fujii 3105 ECB : /* Complete "CREATE PUBLICATION <name> FOR TABLE" with "<table>, ..." */
585 fujii 3106 GBC 34 : else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLE"))
434 tgl 3107 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
529 akapila 3108 ECB :
411 akapila 3109 EUB : /*
3110 : * "CREATE PUBLICATION <name> FOR TABLE <name> WHERE (" - complete with
411 akapila 3111 ECB : * table attributes
3112 : */
411 akapila 3113 CBC 34 : else if (HeadMatches("CREATE", "PUBLICATION", MatchAny) && TailMatches("WHERE"))
411 akapila 3114 UBC 0 : COMPLETE_WITH("(");
411 akapila 3115 CBC 34 : else if (HeadMatches("CREATE", "PUBLICATION", MatchAny) && TailMatches("WHERE", "("))
411 akapila 3116 UBC 0 : COMPLETE_WITH_ATTR(prev3_wd);
411 akapila 3117 GBC 34 : else if (HeadMatches("CREATE", "PUBLICATION", MatchAny) && TailMatches("WHERE", "(*)"))
411 akapila 3118 UBC 0 : COMPLETE_WITH(" WITH (");
3119 :
3120 : /*
199 alvherre 3121 ECB : * Complete "CREATE PUBLICATION <name> FOR TABLES IN SCHEMA <schema>, ..."
529 akapila 3122 EUB : */
191 alvherre 3123 GIC 34 : else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLES", "IN", "SCHEMA"))
434 tgl 3124 UIC 0 : COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_schemas
3125 : " AND nspname NOT LIKE E'pg\\\\_%%'",
434 tgl 3126 ECB : "CURRENT_SCHEMA");
191 alvherre 3127 GBC 34 : else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLES", "IN", "SCHEMA", MatchAny) && (!ends_with(prev_wd, ',')))
529 akapila 3128 UIC 0 : COMPLETE_WITH("WITH (");
2271 peter_e 3129 ECB : /* Complete "CREATE PUBLICATION <name> [...] WITH" */
1661 tgl 3130 GBC 34 : else if (HeadMatches("CREATE", "PUBLICATION") && TailMatches("WITH", "("))
667 michael 3131 UIC 0 : COMPLETE_WITH("publish", "publish_via_partition_root");
2271 peter_e 3132 ECB :
8535 bruce 3133 EUB : /* CREATE RULE */
3134 : /* Complete "CREATE [ OR REPLACE ] RULE <sth>" with "AS ON" */
1304 fujii 3135 CBC 68 : else if (Matches("CREATE", "RULE", MatchAny) ||
1304 fujii 3136 GBC 34 : Matches("CREATE", "OR", "REPLACE", "RULE", MatchAny))
1661 tgl 3137 UIC 0 : COMPLETE_WITH("AS ON");
3138 : /* Complete "CREATE [ OR REPLACE ] RULE <sth> AS" with "ON" */
1304 fujii 3139 GIC 68 : else if (Matches("CREATE", "RULE", MatchAny, "AS") ||
3140 34 : Matches("CREATE", "OR", "REPLACE", "RULE", MatchAny, "AS"))
1661 tgl 3141 UIC 0 : COMPLETE_WITH("ON");
1213 tgl 3142 ECB :
1213 tgl 3143 EUB : /*
3144 : * Complete "CREATE [ OR REPLACE ] RULE <sth> AS ON" with
1213 tgl 3145 ECB : * SELECT|UPDATE|INSERT|DELETE
1213 tgl 3146 EUB : */
1304 fujii 3147 GIC 68 : else if (Matches("CREATE", "RULE", MatchAny, "AS", "ON") ||
1304 fujii 3148 CBC 34 : Matches("CREATE", "OR", "REPLACE", "RULE", MatchAny, "AS", "ON"))
1661 tgl 3149 UBC 0 : COMPLETE_WITH("SELECT", "UPDATE", "INSERT", "DELETE");
3150 : /* Complete "AS ON SELECT|UPDATE|INSERT|DELETE" with a "TO" */
1661 tgl 3151 CBC 34 : else if (TailMatches("AS", "ON", "SELECT|UPDATE|INSERT|DELETE"))
1661 tgl 3152 UBC 0 : COMPLETE_WITH("TO");
3153 : /* Complete "AS ON <sth> TO" with a table name */
1661 tgl 3154 CBC 34 : else if (TailMatches("AS", "ON", "SELECT|UPDATE|INSERT|DELETE", "TO"))
434 tgl 3155 UBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
3156 :
2652 tgl 3157 ECB : /* CREATE SEQUENCE --- is allowed inside CREATE SCHEMA, so use TailMatches */
1661 tgl 3158 GBC 68 : else if (TailMatches("CREATE", "SEQUENCE", MatchAny) ||
1661 tgl 3159 GIC 34 : TailMatches("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny))
506 michael 3160 UIC 0 : COMPLETE_WITH("AS", "INCREMENT BY", "MINVALUE", "MAXVALUE", "NO",
506 michael 3161 ECB : "CACHE", "CYCLE", "OWNED BY", "START WITH");
506 michael 3162 GBC 68 : else if (TailMatches("CREATE", "SEQUENCE", MatchAny, "AS") ||
506 michael 3163 GIC 34 : TailMatches("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny, "AS"))
506 michael 3164 UIC 0 : COMPLETE_WITH_CS("smallint", "integer", "bigint");
1661 tgl 3165 GIC 68 : else if (TailMatches("CREATE", "SEQUENCE", MatchAny, "NO") ||
3166 34 : TailMatches("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny, "NO"))
1661 tgl 3167 UIC 0 : COMPLETE_WITH("MINVALUE", "MAXVALUE", "CYCLE");
2805 rhaas 3168 ECB :
5224 peter_e 3169 EUB : /* CREATE SERVER <name> */
1661 tgl 3170 GIC 34 : else if (Matches("CREATE", "SERVER", MatchAny))
1661 tgl 3171 UIC 0 : COMPLETE_WITH("TYPE", "VERSION", "FOREIGN DATA WRAPPER");
3172 :
3173 : /* CREATE STATISTICS <name> */
1661 tgl 3174 GIC 34 : else if (Matches("CREATE", "STATISTICS", MatchAny))
1661 tgl 3175 LBC 0 : COMPLETE_WITH("(", "ON");
1661 tgl 3176 GBC 34 : else if (Matches("CREATE", "STATISTICS", MatchAny, "("))
1474 tomas.vondra 3177 UIC 0 : COMPLETE_WITH("ndistinct", "dependencies", "mcv");
1593 tomas.vondra 3178 GIC 34 : else if (Matches("CREATE", "STATISTICS", MatchAny, "(*)"))
1661 tgl 3179 UIC 0 : COMPLETE_WITH("ON");
1661 tgl 3180 GIC 34 : else if (HeadMatches("CREATE", "STATISTICS", MatchAny) &&
1661 tgl 3181 UIC 0 : TailMatches("FROM"))
434 tgl 3182 LBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
2158 alvherre 3183 EUB :
3184 : /* CREATE TABLE --- is allowed inside CREATE SCHEMA, so use TailMatches */
3185 : /* Complete "CREATE TEMP/TEMPORARY" with the possible temp objects */
1661 tgl 3186 GIC 34 : else if (TailMatches("CREATE", "TEMP|TEMPORARY"))
1661 tgl 3187 UIC 0 : COMPLETE_WITH("SEQUENCE", "TABLE", "VIEW");
3188 : /* Complete "CREATE UNLOGGED" with TABLE or MATVIEW */
1661 tgl 3189 CBC 34 : else if (TailMatches("CREATE", "UNLOGGED"))
1661 tgl 3190 UBC 0 : COMPLETE_WITH("TABLE", "MATERIALIZED VIEW");
3191 : /* Complete PARTITION BY with RANGE ( or LIST ( or ... */
1661 tgl 3192 GIC 34 : else if (TailMatches("PARTITION", "BY"))
1661 tgl 3193 UIC 0 : COMPLETE_WITH("RANGE (", "LIST (", "HASH (");
3194 : /* If we have xxx PARTITION OF, provide a list of partitioned tables */
1661 tgl 3195 GIC 34 : else if (TailMatches("PARTITION", "OF"))
434 tgl 3196 LBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_partitioned_tables);
2233 rhaas 3197 EUB : /* Limited completion support for partition bound specification */
1661 tgl 3198 GIC 34 : else if (TailMatches("PARTITION", "OF", MatchAny))
1661 tgl 3199 UIC 0 : COMPLETE_WITH("FOR VALUES", "DEFAULT");
3200 : /* Complete CREATE TABLE <name> with '(', OF or PARTITION OF */
1571 michael 3201 GIC 68 : else if (TailMatches("CREATE", "TABLE", MatchAny) ||
3202 34 : TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny))
1571 michael 3203 UIC 0 : COMPLETE_WITH("(", "OF", "PARTITION OF");
1571 michael 3204 ECB : /* Complete CREATE TABLE <name> OF with list of composite types */
1571 michael 3205 GBC 68 : else if (TailMatches("CREATE", "TABLE", MatchAny, "OF") ||
1571 michael 3206 GIC 34 : TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny, "OF"))
434 tgl 3207 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_composite_datatypes);
3208 : /* Complete CREATE TABLE name (...) with supported options */
1571 michael 3209 CBC 68 : else if (TailMatches("CREATE", "TABLE", MatchAny, "(*)") ||
1571 michael 3210 GBC 34 : TailMatches("CREATE", "UNLOGGED", "TABLE", MatchAny, "(*)"))
1406 michael 3211 LBC 0 : COMPLETE_WITH("INHERITS (", "PARTITION BY", "USING", "TABLESPACE", "WITH (");
1571 michael 3212 GBC 34 : else if (TailMatches("CREATE", "TEMP|TEMPORARY", "TABLE", MatchAny, "(*)"))
1571 michael 3213 LBC 0 : COMPLETE_WITH("INHERITS (", "ON COMMIT", "PARTITION BY",
1571 michael 3214 EUB : "TABLESPACE", "WITH (");
1406 michael 3215 ECB : /* Complete CREATE TABLE (...) USING with table access methods */
1406 michael 3216 GBC 68 : else if (TailMatches("CREATE", "TABLE", MatchAny, "(*)", "USING") ||
1406 michael 3217 CBC 34 : TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny, "(*)", "USING"))
1406 michael 3218 UBC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_table_access_methods);
1568 michael 3219 ECB : /* Complete CREATE TABLE (...) WITH with storage parameters */
1568 michael 3220 GBC 68 : else if (TailMatches("CREATE", "TABLE", MatchAny, "(*)", "WITH", "(") ||
1568 michael 3221 GIC 34 : TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny, "(*)", "WITH", "("))
1568 michael 3222 LBC 0 : COMPLETE_WITH_LIST(table_storage_parameters);
1571 michael 3223 EUB : /* Complete CREATE TABLE ON COMMIT with actions */
1571 michael 3224 GIC 34 : else if (TailMatches("CREATE", "TEMP|TEMPORARY", "TABLE", MatchAny, "(*)", "ON", "COMMIT"))
1571 michael 3225 UIC 0 : COMPLETE_WITH("DELETE ROWS", "DROP", "PRESERVE ROWS");
3226 :
3227 : /* CREATE TABLESPACE */
1661 tgl 3228 GIC 34 : else if (Matches("CREATE", "TABLESPACE", MatchAny))
1661 tgl 3229 LBC 0 : COMPLETE_WITH("OWNER", "LOCATION");
6732 peter_e 3230 EUB : /* Complete CREATE TABLESPACE name OWNER name with "LOCATION" */
1661 tgl 3231 CBC 34 : else if (Matches("CREATE", "TABLESPACE", MatchAny, "OWNER", MatchAny))
1661 tgl 3232 UBC 0 : COMPLETE_WITH("LOCATION");
6732 peter_e 3233 ECB :
5686 bruce 3234 EUB : /* CREATE TEXT SEARCH */
1661 tgl 3235 GIC 34 : else if (Matches("CREATE", "TEXT", "SEARCH"))
1661 tgl 3236 UIC 0 : COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
1128 tgl 3237 GIC 34 : else if (Matches("CREATE", "TEXT", "SEARCH", "CONFIGURATION|DICTIONARY|PARSER|TEMPLATE", MatchAny))
1661 tgl 3238 UIC 0 : COMPLETE_WITH("(");
5686 bruce 3239 ECB :
506 michael 3240 EUB : /* CREATE TRANSFORM */
506 michael 3241 GIC 68 : else if (Matches("CREATE", "TRANSFORM") ||
3242 34 : Matches("CREATE", "OR", "REPLACE", "TRANSFORM"))
506 michael 3243 LBC 0 : COMPLETE_WITH("FOR");
506 michael 3244 GBC 68 : else if (Matches("CREATE", "TRANSFORM", "FOR") ||
479 tgl 3245 GIC 34 : Matches("CREATE", "OR", "REPLACE", "TRANSFORM", "FOR"))
434 tgl 3246 LBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
506 michael 3247 GBC 68 : else if (Matches("CREATE", "TRANSFORM", "FOR", MatchAny) ||
506 michael 3248 GIC 34 : Matches("CREATE", "OR", "REPLACE", "TRANSFORM", "FOR", MatchAny))
506 michael 3249 UIC 0 : COMPLETE_WITH("LANGUAGE");
506 michael 3250 GIC 68 : else if (Matches("CREATE", "TRANSFORM", "FOR", MatchAny, "LANGUAGE") ||
506 michael 3251 CBC 34 : Matches("CREATE", "OR", "REPLACE", "TRANSFORM", "FOR", MatchAny, "LANGUAGE"))
506 michael 3252 ECB : {
434 tgl 3253 UBC 0 : set_completion_reference(prev2_wd);
506 michael 3254 UIC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_languages);
506 michael 3255 ECB : }
3256 :
2271 peter_e 3257 EUB : /* CREATE SUBSCRIPTION */
1661 tgl 3258 GIC 34 : else if (Matches("CREATE", "SUBSCRIPTION", MatchAny))
1661 tgl 3259 UIC 0 : COMPLETE_WITH("CONNECTION");
1661 tgl 3260 GIC 34 : else if (Matches("CREATE", "SUBSCRIPTION", MatchAny, "CONNECTION", MatchAny))
1661 tgl 3261 UIC 0 : COMPLETE_WITH("PUBLICATION");
1661 tgl 3262 GIC 34 : else if (Matches("CREATE", "SUBSCRIPTION", MatchAny, "CONNECTION",
1661 tgl 3263 ECB : MatchAny, "PUBLICATION"))
2228 peter_e 3264 : {
2228 peter_e 3265 EUB : /* complete with nothing here as this refers to remote publications */
3266 : }
1661 tgl 3267 CBC 34 : else if (HeadMatches("CREATE", "SUBSCRIPTION") && TailMatches("PUBLICATION", MatchAny))
1661 tgl 3268 UBC 0 : COMPLETE_WITH("WITH (");
3269 : /* Complete "CREATE SUBSCRIPTION <name> ... WITH ( <opt>" */
1661 tgl 3270 CBC 34 : else if (HeadMatches("CREATE", "SUBSCRIPTION") && TailMatches("WITH", "("))
667 michael 3271 UBC 0 : COMPLETE_WITH("binary", "connect", "copy_data", "create_slot",
3272 : "disable_on_error", "enabled", "origin",
3273 : "password_required", "run_as_owner", "slot_name",
3274 : "streaming", "synchronous_commit", "two_phase");
2271 peter_e 3275 ECB :
2652 tgl 3276 : /* CREATE TRIGGER --- is allowed inside CREATE SCHEMA, so use TailMatches */
872 michael 3277 EUB :
3278 : /*
872 michael 3279 ECB : * Complete CREATE [ OR REPLACE ] TRIGGER <name> with BEFORE|AFTER|INSTEAD
3280 : * OF.
872 michael 3281 EUB : */
872 michael 3282 CBC 68 : else if (TailMatches("CREATE", "TRIGGER", MatchAny) ||
3283 34 : TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny))
1661 tgl 3284 UBC 0 : COMPLETE_WITH("BEFORE", "AFTER", "INSTEAD OF");
3285 :
3286 : /*
872 michael 3287 ECB : * Complete CREATE [ OR REPLACE ] TRIGGER <name> BEFORE,AFTER with an
872 michael 3288 EUB : * event.
3289 : */
872 michael 3290 GIC 68 : else if (TailMatches("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER") ||
872 michael 3291 CBC 34 : TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "BEFORE|AFTER"))
1661 tgl 3292 UBC 0 : COMPLETE_WITH("INSERT", "DELETE", "UPDATE", "TRUNCATE");
872 michael 3293 ECB : /* Complete CREATE [ OR REPLACE ] TRIGGER <name> INSTEAD OF with an event */
872 michael 3294 GBC 68 : else if (TailMatches("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF") ||
872 michael 3295 CBC 34 : TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "INSTEAD", "OF"))
1661 tgl 3296 UBC 0 : COMPLETE_WITH("INSERT", "DELETE", "UPDATE");
872 michael 3297 ECB :
872 michael 3298 EUB : /*
3299 : * Complete CREATE [ OR REPLACE ] TRIGGER <name> BEFORE,AFTER sth with
3300 : * OR|ON.
3301 : */
1661 tgl 3302 GIC 68 : else if (TailMatches("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny) ||
872 michael 3303 CBC 68 : TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny) ||
872 michael 3304 GBC 68 : TailMatches("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny) ||
872 michael 3305 GIC 34 : TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny))
1661 tgl 3306 LBC 0 : COMPLETE_WITH("ON", "OR");
4790 bruce 3307 EUB :
3308 : /*
872 michael 3309 ECB : * Complete CREATE [ OR REPLACE ] TRIGGER <name> BEFORE,AFTER event ON
872 michael 3310 EUB : * with a list of tables. EXECUTE FUNCTION is the recommended grammar
3311 : * instead of EXECUTE PROCEDURE in version 11 and upwards.
4790 bruce 3312 ECB : */
872 michael 3313 GBC 68 : else if (TailMatches("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny, "ON") ||
872 michael 3314 GIC 34 : TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny, "ON"))
434 tgl 3315 LBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
872 michael 3316 EUB :
3317 : /*
872 michael 3318 ECB : * Complete CREATE [ OR REPLACE ] TRIGGER ... INSTEAD OF event ON with a
3319 : * list of views.
872 michael 3320 EUB : */
872 michael 3321 GIC 68 : else if (TailMatches("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny, "ON") ||
872 michael 3322 CBC 34 : TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny, "ON"))
434 tgl 3323 LBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views);
872 michael 3324 GBC 68 : else if ((HeadMatches("CREATE", "TRIGGER") ||
872 michael 3325 GIC 34 : HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) &&
872 michael 3326 LBC 0 : TailMatches("ON", MatchAny))
1626 michael 3327 ECB : {
1626 michael 3328 UBC 0 : if (pset.sversion >= 110000)
1626 michael 3329 LBC 0 : COMPLETE_WITH("NOT DEFERRABLE", "DEFERRABLE", "INITIALLY",
1626 michael 3330 EUB : "REFERENCING", "FOR", "WHEN (", "EXECUTE FUNCTION");
3331 : else
1626 michael 3332 UIC 0 : COMPLETE_WITH("NOT DEFERRABLE", "DEFERRABLE", "INITIALLY",
1626 michael 3333 ECB : "REFERENCING", "FOR", "WHEN (", "EXECUTE PROCEDURE");
3334 : }
872 michael 3335 GBC 68 : else if ((HeadMatches("CREATE", "TRIGGER") ||
872 michael 3336 GIC 34 : HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) &&
1661 tgl 3337 LBC 0 : (TailMatches("DEFERRABLE") || TailMatches("INITIALLY", "IMMEDIATE|DEFERRED")))
1626 michael 3338 ECB : {
1626 michael 3339 UBC 0 : if (pset.sversion >= 110000)
1626 michael 3340 UIC 0 : COMPLETE_WITH("REFERENCING", "FOR", "WHEN (", "EXECUTE FUNCTION");
1626 michael 3341 ECB : else
1626 michael 3342 UBC 0 : COMPLETE_WITH("REFERENCING", "FOR", "WHEN (", "EXECUTE PROCEDURE");
3343 : }
872 michael 3344 GIC 68 : else if ((HeadMatches("CREATE", "TRIGGER") ||
872 michael 3345 CBC 34 : HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) &&
872 michael 3346 UBC 0 : TailMatches("REFERENCING"))
1661 tgl 3347 UIC 0 : COMPLETE_WITH("OLD TABLE", "NEW TABLE");
872 michael 3348 CBC 68 : else if ((HeadMatches("CREATE", "TRIGGER") ||
872 michael 3349 GBC 34 : HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) &&
872 michael 3350 UIC 0 : TailMatches("OLD|NEW", "TABLE"))
1661 tgl 3351 0 : COMPLETE_WITH("AS");
872 michael 3352 CBC 68 : else if ((HeadMatches("CREATE", "TRIGGER") ||
872 michael 3353 GBC 34 : HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) &&
1661 tgl 3354 LBC 0 : (TailMatches("REFERENCING", "OLD", "TABLE", "AS", MatchAny) ||
1661 tgl 3355 UBC 0 : TailMatches("REFERENCING", "OLD", "TABLE", MatchAny)))
3356 : {
1626 michael 3357 UIC 0 : if (pset.sversion >= 110000)
1626 michael 3358 LBC 0 : COMPLETE_WITH("NEW TABLE", "FOR", "WHEN (", "EXECUTE FUNCTION");
1626 michael 3359 ECB : else
1626 michael 3360 UBC 0 : COMPLETE_WITH("NEW TABLE", "FOR", "WHEN (", "EXECUTE PROCEDURE");
1626 michael 3361 ECB : }
872 michael 3362 CBC 68 : else if ((HeadMatches("CREATE", "TRIGGER") ||
872 michael 3363 GBC 34 : HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) &&
1661 tgl 3364 LBC 0 : (TailMatches("REFERENCING", "NEW", "TABLE", "AS", MatchAny) ||
3365 0 : TailMatches("REFERENCING", "NEW", "TABLE", MatchAny)))
1626 michael 3366 EUB : {
1626 michael 3367 LBC 0 : if (pset.sversion >= 110000)
3368 0 : COMPLETE_WITH("OLD TABLE", "FOR", "WHEN (", "EXECUTE FUNCTION");
3369 : else
1626 michael 3370 UBC 0 : COMPLETE_WITH("OLD TABLE", "FOR", "WHEN (", "EXECUTE PROCEDURE");
1626 michael 3371 EUB : }
872 michael 3372 GIC 68 : else if ((HeadMatches("CREATE", "TRIGGER") ||
3373 34 : HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) &&
1661 tgl 3374 UIC 0 : (TailMatches("REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
1661 tgl 3375 LBC 0 : TailMatches("REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
1661 tgl 3376 UBC 0 : TailMatches("REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", MatchAny) ||
1661 tgl 3377 LBC 0 : TailMatches("REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", MatchAny)))
1626 michael 3378 EUB : {
1626 michael 3379 LBC 0 : if (pset.sversion >= 110000)
1626 michael 3380 UIC 0 : COMPLETE_WITH("FOR", "WHEN (", "EXECUTE FUNCTION");
3381 : else
3382 0 : COMPLETE_WITH("FOR", "WHEN (", "EXECUTE PROCEDURE");
3383 : }
872 michael 3384 CBC 68 : else if ((HeadMatches("CREATE", "TRIGGER") ||
872 michael 3385 GBC 34 : HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) &&
872 michael 3386 UIC 0 : TailMatches("FOR"))
1661 tgl 3387 LBC 0 : COMPLETE_WITH("EACH", "ROW", "STATEMENT");
872 michael 3388 GBC 68 : else if ((HeadMatches("CREATE", "TRIGGER") ||
872 michael 3389 GIC 34 : HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) &&
872 michael 3390 UIC 0 : TailMatches("FOR", "EACH"))
1661 tgl 3391 0 : COMPLETE_WITH("ROW", "STATEMENT");
872 michael 3392 GIC 68 : else if ((HeadMatches("CREATE", "TRIGGER") ||
3393 34 : HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) &&
1661 tgl 3394 UIC 0 : (TailMatches("FOR", "EACH", "ROW|STATEMENT") ||
3395 0 : TailMatches("FOR", "ROW|STATEMENT")))
3396 : {
1626 michael 3397 0 : if (pset.sversion >= 110000)
3398 0 : COMPLETE_WITH("WHEN (", "EXECUTE FUNCTION");
1626 michael 3399 ECB : else
1626 michael 3400 LBC 0 : COMPLETE_WITH("WHEN (", "EXECUTE PROCEDURE");
1626 michael 3401 EUB : }
872 michael 3402 GIC 68 : else if ((HeadMatches("CREATE", "TRIGGER") ||
3403 34 : HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) &&
872 michael 3404 UIC 0 : TailMatches("WHEN", "(*)"))
3405 : {
1626 3406 0 : if (pset.sversion >= 110000)
1626 michael 3407 LBC 0 : COMPLETE_WITH("EXECUTE FUNCTION");
1626 michael 3408 ECB : else
1626 michael 3409 UBC 0 : COMPLETE_WITH("EXECUTE PROCEDURE");
3410 : }
872 michael 3411 ECB :
3412 : /*
872 michael 3413 EUB : * Complete CREATE [ OR REPLACE ] TRIGGER ... EXECUTE with
3414 : * PROCEDURE|FUNCTION.
3415 : */
872 michael 3416 GIC 68 : else if ((HeadMatches("CREATE", "TRIGGER") ||
3417 34 : HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) &&
872 michael 3418 UIC 0 : TailMatches("EXECUTE"))
1626 michael 3419 ECB : {
1626 michael 3420 LBC 0 : if (pset.sversion >= 110000)
3421 0 : COMPLETE_WITH("FUNCTION");
1626 michael 3422 ECB : else
1626 michael 3423 UBC 0 : COMPLETE_WITH("PROCEDURE");
3424 : }
872 michael 3425 GIC 68 : else if ((HeadMatches("CREATE", "TRIGGER") ||
3426 34 : HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) &&
1626 michael 3427 UIC 0 : TailMatches("EXECUTE", "FUNCTION|PROCEDURE"))
434 tgl 3428 0 : COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_functions);
3429 :
4008 peter_e 3430 ECB : /* CREATE ROLE,USER,GROUP <name> */
1661 tgl 3431 CBC 34 : else if (Matches("CREATE", "ROLE|GROUP|USER", MatchAny) &&
1661 tgl 3432 UBC 0 : !TailMatches("USER", "MAPPING"))
1661 tgl 3433 UIC 0 : COMPLETE_WITH("ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB",
3434 : "CREATEROLE", "ENCRYPTED PASSWORD", "IN", "INHERIT",
3435 : "LOGIN", "NOBYPASSRLS",
3436 : "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
3437 : "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
1661 tgl 3438 ECB : "REPLICATION", "ROLE", "SUPERUSER", "SYSID",
3439 : "VALID UNTIL", "WITH");
6385 bruce 3440 EUB :
4008 peter_e 3441 ECB : /* CREATE ROLE,USER,GROUP <name> WITH */
1661 tgl 3442 CBC 34 : else if (Matches("CREATE", "ROLE|GROUP|USER", MatchAny, "WITH"))
4008 peter_e 3443 EUB : /* Similar to the above, but don't complete "WITH" again. */
1661 tgl 3444 UIC 0 : COMPLETE_WITH("ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB",
1661 tgl 3445 EUB : "CREATEROLE", "ENCRYPTED PASSWORD", "IN", "INHERIT",
3446 : "LOGIN", "NOBYPASSRLS",
3447 : "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
3448 : "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
3449 : "REPLICATION", "ROLE", "SUPERUSER", "SYSID",
3450 : "VALID UNTIL");
3451 :
6447 tgl 3452 ECB : /* complete CREATE ROLE,USER,GROUP <name> IN with ROLE,GROUP */
1661 tgl 3453 CBC 34 : else if (Matches("CREATE", "ROLE|USER|GROUP", MatchAny, "IN"))
1661 tgl 3454 UBC 0 : COMPLETE_WITH("GROUP", "ROLE");
3455 :
1366 tmunro 3456 EUB : /* CREATE TYPE */
1366 tmunro 3457 GBC 34 : else if (Matches("CREATE", "TYPE", MatchAny))
1366 tmunro 3458 UIC 0 : COMPLETE_WITH("(", "AS");
1366 tmunro 3459 GBC 34 : else if (Matches("CREATE", "TYPE", MatchAny, "AS"))
1366 tmunro 3460 UIC 0 : COMPLETE_WITH("ENUM", "RANGE", "(");
1366 tmunro 3461 CBC 34 : else if (HeadMatches("CREATE", "TYPE", MatchAny, "AS", "("))
1366 tmunro 3462 ECB : {
1366 tmunro 3463 UBC 0 : if (TailMatches("(|*,", MatchAny))
434 tgl 3464 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
1366 tmunro 3465 LBC 0 : else if (TailMatches("(|*,", MatchAny, MatchAnyExcept("*)")))
3466 0 : COMPLETE_WITH("COLLATE", ",", ")");
1366 tmunro 3467 EUB : }
1366 tmunro 3468 GBC 34 : else if (Matches("CREATE", "TYPE", MatchAny, "AS", "ENUM|RANGE"))
1366 tmunro 3469 LBC 0 : COMPLETE_WITH("(");
1366 tmunro 3470 CBC 34 : else if (HeadMatches("CREATE", "TYPE", MatchAny, "("))
1366 tmunro 3471 EUB : {
1366 tmunro 3472 UBC 0 : if (TailMatches("(|*,"))
1366 tmunro 3473 UIC 0 : COMPLETE_WITH("INPUT", "OUTPUT", "RECEIVE", "SEND",
676 tgl 3474 EUB : "TYPMOD_IN", "TYPMOD_OUT", "ANALYZE", "SUBSCRIPT",
1329 michael 3475 : "INTERNALLENGTH", "PASSEDBYVALUE", "ALIGNMENT",
3476 : "STORAGE", "LIKE", "CATEGORY", "PREFERRED",
1366 tmunro 3477 : "DEFAULT", "ELEMENT", "DELIMITER",
3478 : "COLLATABLE");
1366 tmunro 3479 LBC 0 : else if (TailMatches("(*|*,", MatchAnyExcept("*=")))
3480 0 : COMPLETE_WITH("=");
1366 tmunro 3481 UBC 0 : else if (TailMatches("=", MatchAnyExcept("*)")))
3482 0 : COMPLETE_WITH(",", ")");
3483 : }
1366 tmunro 3484 GBC 34 : else if (HeadMatches("CREATE", "TYPE", MatchAny, "AS", "RANGE", "("))
1366 tmunro 3485 EUB : {
1366 tmunro 3486 UIC 0 : if (TailMatches("(|*,"))
1366 tmunro 3487 UBC 0 : COMPLETE_WITH("SUBTYPE", "SUBTYPE_OPCLASS", "COLLATION",
3488 : "CANONICAL", "SUBTYPE_DIFF",
676 tgl 3489 ECB : "MULTIRANGE_TYPE_NAME");
1366 tmunro 3490 LBC 0 : else if (TailMatches("(*|*,", MatchAnyExcept("*=")))
1366 tmunro 3491 UBC 0 : COMPLETE_WITH("=");
3492 0 : else if (TailMatches("=", MatchAnyExcept("*)")))
3493 0 : COMPLETE_WITH(",", ")");
1366 tmunro 3494 EUB : }
3495 :
2652 tgl 3496 : /* CREATE VIEW --- is allowed inside CREATE SCHEMA, so use TailMatches */
1304 fujii 3497 : /* Complete CREATE [ OR REPLACE ] VIEW <name> with AS */
1304 fujii 3498 GIC 68 : else if (TailMatches("CREATE", "VIEW", MatchAny) ||
1304 fujii 3499 GBC 34 : TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny))
1661 tgl 3500 UIC 0 : COMPLETE_WITH("AS");
1304 fujii 3501 ECB : /* Complete "CREATE [ OR REPLACE ] VIEW <sth> AS with "SELECT" */
1304 fujii 3502 CBC 68 : else if (TailMatches("CREATE", "VIEW", MatchAny, "AS") ||
1304 fujii 3503 GBC 34 : TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "AS"))
1661 tgl 3504 UBC 0 : COMPLETE_WITH("SELECT");
8535 bruce 3505 ECB :
3689 kgrittn 3506 : /* CREATE MATERIALIZED VIEW */
1661 tgl 3507 GBC 34 : else if (Matches("CREATE", "MATERIALIZED"))
1661 tgl 3508 UBC 0 : COMPLETE_WITH("VIEW");
3689 kgrittn 3509 ECB : /* Complete CREATE MATERIALIZED VIEW <name> with AS */
1661 tgl 3510 CBC 34 : else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny))
1661 tgl 3511 UBC 0 : COMPLETE_WITH("AS");
3689 kgrittn 3512 EUB : /* Complete "CREATE MATERIALIZED VIEW <sth> AS with "SELECT" */
1661 tgl 3513 GIC 34 : else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny, "AS"))
1661 tgl 3514 UBC 0 : COMPLETE_WITH("SELECT");
3689 kgrittn 3515 EUB :
3516 : /* CREATE EVENT TRIGGER */
1661 tgl 3517 GBC 34 : else if (Matches("CREATE", "EVENT"))
1661 tgl 3518 UIC 0 : COMPLETE_WITH("TRIGGER");
3282 rhaas 3519 ECB : /* Complete CREATE EVENT TRIGGER <name> with ON */
1661 tgl 3520 CBC 34 : else if (Matches("CREATE", "EVENT", "TRIGGER", MatchAny))
1661 tgl 3521 UBC 0 : COMPLETE_WITH("ON");
3522 : /* Complete CREATE EVENT TRIGGER <name> ON with event_type */
1661 tgl 3523 GBC 34 : else if (Matches("CREATE", "EVENT", "TRIGGER", MatchAny, "ON"))
319 michael 3524 UBC 0 : COMPLETE_WITH("ddl_command_start", "ddl_command_end", "sql_drop",
3525 : "table_rewrite");
1595 tgl 3526 EUB :
3527 : /*
3528 : * Complete CREATE EVENT TRIGGER <name> ON <event_type>. EXECUTE FUNCTION
3529 : * is the recommended grammar instead of EXECUTE PROCEDURE in version 11
3530 : * and upwards.
3531 : */
1626 michael 3532 GIC 34 : else if (Matches("CREATE", "EVENT", "TRIGGER", MatchAny, "ON", MatchAny))
1626 michael 3533 ECB : {
1626 michael 3534 LBC 0 : if (pset.sversion >= 110000)
1626 michael 3535 UBC 0 : COMPLETE_WITH("WHEN TAG IN (", "EXECUTE FUNCTION");
3536 : else
3537 0 : COMPLETE_WITH("WHEN TAG IN (", "EXECUTE PROCEDURE");
1626 michael 3538 EUB : }
1626 michael 3539 GIC 34 : else if (HeadMatches("CREATE", "EVENT", "TRIGGER") &&
1626 michael 3540 UBC 0 : TailMatches("WHEN|AND", MatchAny, "IN", "(*)"))
3541 : {
1626 michael 3542 LBC 0 : if (pset.sversion >= 110000)
3543 0 : COMPLETE_WITH("EXECUTE FUNCTION");
1626 michael 3544 EUB : else
1626 michael 3545 UBC 0 : COMPLETE_WITH("EXECUTE PROCEDURE");
3546 : }
1626 michael 3547 GIC 34 : else if (HeadMatches("CREATE", "EVENT", "TRIGGER") &&
1626 michael 3548 LBC 0 : TailMatches("EXECUTE", "FUNCTION|PROCEDURE"))
434 tgl 3549 UBC 0 : COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_functions);
3282 rhaas 3550 EUB :
3551 : /* DEALLOCATE */
1661 tgl 3552 GIC 34 : else if (Matches("DEALLOCATE"))
434 tgl 3553 UIC 0 : COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_prepared_statements,
3554 : "ALL");
3555 :
3556 : /* DECLARE */
3557 :
3558 : /*
607 michael 3559 ECB : * Complete DECLARE <name> with one of BINARY, ASENSITIVE, INSENSITIVE,
3560 : * SCROLL, NO SCROLL, and CURSOR.
815 fujii 3561 EUB : */
1661 tgl 3562 GIC 34 : else if (Matches("DECLARE", MatchAny))
732 peter 3563 UIC 0 : COMPLETE_WITH("BINARY", "ASENSITIVE", "INSENSITIVE", "SCROLL", "NO SCROLL",
3564 : "CURSOR");
3565 :
3566 : /*
3567 : * Complete DECLARE ... <option> with other options. The PostgreSQL parser
3568 : * allows DECLARE options to be specified in any order. But the
3569 : * tab-completion follows the ordering of them that the SQL standard
815 fujii 3570 ECB : * provides, like the syntax of DECLARE command in the documentation
815 fujii 3571 EUB : * indicates.
3572 : */
815 fujii 3573 GIC 34 : else if (HeadMatches("DECLARE") && TailMatches("BINARY"))
607 michael 3574 LBC 0 : COMPLETE_WITH("ASENSITIVE", "INSENSITIVE", "SCROLL", "NO SCROLL", "CURSOR");
607 michael 3575 GBC 34 : else if (HeadMatches("DECLARE") && TailMatches("ASENSITIVE|INSENSITIVE"))
815 fujii 3576 LBC 0 : COMPLETE_WITH("SCROLL", "NO SCROLL", "CURSOR");
815 fujii 3577 GBC 34 : else if (HeadMatches("DECLARE") && TailMatches("SCROLL"))
815 fujii 3578 LBC 0 : COMPLETE_WITH("CURSOR");
3579 : /* Complete DECLARE ... [options] NO with SCROLL */
815 fujii 3580 GBC 34 : else if (HeadMatches("DECLARE") && TailMatches("NO"))
815 fujii 3581 UBC 0 : COMPLETE_WITH("SCROLL");
815 fujii 3582 EUB :
3583 : /*
3584 : * Complete DECLARE ... CURSOR with one of WITH HOLD, WITHOUT HOLD, and
815 fujii 3585 ECB : * FOR
815 fujii 3586 EUB : */
1661 tgl 3587 CBC 34 : else if (HeadMatches("DECLARE") && TailMatches("CURSOR"))
1661 tgl 3588 UIC 0 : COMPLETE_WITH("WITH HOLD", "WITHOUT HOLD", "FOR");
815 fujii 3589 EUB : /* Complete DECLARE ... CURSOR WITH|WITHOUT with HOLD */
815 fujii 3590 GBC 34 : else if (HeadMatches("DECLARE") && TailMatches("CURSOR", "WITH|WITHOUT"))
815 fujii 3591 UIC 0 : COMPLETE_WITH("HOLD");
3592 : /* Complete DECLARE ... CURSOR WITH|WITHOUT HOLD with FOR */
815 fujii 3593 GIC 34 : else if (HeadMatches("DECLARE") && TailMatches("CURSOR", "WITH|WITHOUT", "HOLD"))
815 fujii 3594 UIC 0 : COMPLETE_WITH("FOR");
3595 :
2652 tgl 3596 EUB : /* DELETE --- can be inside EXPLAIN, RULE, etc */
696 michael 3597 : /* Complete DELETE with "FROM" */
1661 tgl 3598 GBC 34 : else if (Matches("DELETE"))
1661 tgl 3599 UBC 0 : COMPLETE_WITH("FROM");
3600 : /* Complete DELETE FROM with a list of tables */
1661 tgl 3601 CBC 34 : else if (TailMatches("DELETE", "FROM"))
434 tgl 3602 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables);
6576 neilc 3603 EUB : /* Complete DELETE FROM <table> */
1661 tgl 3604 GBC 34 : else if (TailMatches("DELETE", "FROM", MatchAny))
1661 tgl 3605 UIC 0 : COMPLETE_WITH("USING", "WHERE");
3606 : /* XXX: implement tab completion for DELETE ... USING */
8535 bruce 3607 EUB :
5827 neilc 3608 : /* DISCARD */
1661 tgl 3609 GBC 34 : else if (Matches("DISCARD"))
1661 tgl 3610 UBC 0 : COMPLETE_WITH("ALL", "PLANS", "SEQUENCES", "TEMP");
3611 :
3612 : /* DO */
1661 tgl 3613 GIC 34 : else if (Matches("DO"))
1661 tgl 3614 UIC 0 : COMPLETE_WITH("LANGUAGE");
4801 itagaki.takahiro 3615 ECB :
2652 tgl 3616 : /* DROP */
2652 tgl 3617 EUB : /* Complete DROP object with CASCADE / RESTRICT */
1661 tgl 3618 GIC 34 : else if (Matches("DROP",
1661 tgl 3619 ECB : "COLLATION|CONVERSION|DOMAIN|EXTENSION|LANGUAGE|PUBLICATION|SCHEMA|SEQUENCE|SERVER|SUBSCRIPTION|STATISTICS|TABLE|TYPE|VIEW",
1661 tgl 3620 CBC 33 : MatchAny) ||
1661 tgl 3621 GBC 66 : Matches("DROP", "ACCESS", "METHOD", MatchAny) ||
1661 tgl 3622 GIC 33 : (Matches("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny) &&
2652 3623 33 : ends_with(prev_wd, ')')) ||
1661 tgl 3624 CBC 66 : Matches("DROP", "EVENT", "TRIGGER", MatchAny) ||
1661 tgl 3625 GBC 66 : Matches("DROP", "FOREIGN", "DATA", "WRAPPER", MatchAny) ||
1661 tgl 3626 GIC 66 : Matches("DROP", "FOREIGN", "TABLE", MatchAny) ||
1661 tgl 3627 CBC 33 : Matches("DROP", "TEXT", "SEARCH", "CONFIGURATION|DICTIONARY|PARSER|TEMPLATE", MatchAny))
1661 tgl 3628 GBC 1 : COMPLETE_WITH("CASCADE", "RESTRICT");
3629 :
2668 tgl 3630 ECB : /* help completing some of the variants */
1661 tgl 3631 GBC 33 : else if (Matches("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny))
1661 tgl 3632 UIC 0 : COMPLETE_WITH("(");
1661 tgl 3633 GIC 33 : else if (Matches("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny, "("))
2668 tgl 3634 LBC 0 : COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
1661 tgl 3635 GBC 33 : else if (Matches("DROP", "FOREIGN"))
1661 tgl 3636 UIC 0 : COMPLETE_WITH("DATA WRAPPER", "TABLE");
1244 akapila 3637 CBC 33 : else if (Matches("DROP", "DATABASE", MatchAny))
1244 akapila 3638 UBC 0 : COMPLETE_WITH("WITH (");
1244 akapila 3639 GIC 33 : else if (HeadMatches("DROP", "DATABASE") && (ends_with(prev_wd, '(')))
1244 akapila 3640 LBC 0 : COMPLETE_WITH("FORCE");
3689 kgrittn 3641 EUB :
3642 : /* DROP INDEX */
1661 tgl 3643 GIC 33 : else if (Matches("DROP", "INDEX"))
434 tgl 3644 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_indexes,
3645 : "CONCURRENTLY");
1661 tgl 3646 GIC 33 : else if (Matches("DROP", "INDEX", "CONCURRENTLY"))
434 tgl 3647 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes);
1661 tgl 3648 GIC 33 : else if (Matches("DROP", "INDEX", MatchAny))
1661 tgl 3649 LBC 0 : COMPLETE_WITH("CASCADE", "RESTRICT");
1661 tgl 3650 GIC 33 : else if (Matches("DROP", "INDEX", "CONCURRENTLY", MatchAny))
1661 tgl 3651 UBC 0 : COMPLETE_WITH("CASCADE", "RESTRICT");
2640 peter_e 3652 EUB :
3653 : /* DROP MATERIALIZED VIEW */
1661 tgl 3654 GBC 33 : else if (Matches("DROP", "MATERIALIZED"))
1661 tgl 3655 UIC 0 : COMPLETE_WITH("VIEW");
1661 tgl 3656 CBC 33 : else if (Matches("DROP", "MATERIALIZED", "VIEW"))
434 tgl 3657 UBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews);
494 michael 3658 GIC 33 : else if (Matches("DROP", "MATERIALIZED", "VIEW", MatchAny))
494 michael 3659 UBC 0 : COMPLETE_WITH("CASCADE", "RESTRICT");
3689 kgrittn 3660 EUB :
3661 : /* DROP OWNED BY */
1661 tgl 3662 GBC 33 : else if (Matches("DROP", "OWNED"))
1661 tgl 3663 UIC 0 : COMPLETE_WITH("BY");
1661 tgl 3664 CBC 33 : else if (Matches("DROP", "OWNED", "BY"))
6216 alvherre 3665 UBC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_roles);
494 michael 3666 GBC 33 : else if (Matches("DROP", "OWNED", "BY", MatchAny))
494 michael 3667 UIC 0 : COMPLETE_WITH("CASCADE", "RESTRICT");
3668 :
2215 peter_e 3669 ECB : /* DROP TEXT SEARCH */
1661 tgl 3670 GBC 33 : else if (Matches("DROP", "TEXT", "SEARCH"))
1661 tgl 3671 UIC 0 : COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
3672 :
3673 : /* DROP TRIGGER */
1661 tgl 3674 GIC 33 : else if (Matches("DROP", "TRIGGER", MatchAny))
1661 tgl 3675 UIC 0 : COMPLETE_WITH("ON");
1661 tgl 3676 GIC 33 : else if (Matches("DROP", "TRIGGER", MatchAny, "ON"))
3677 : {
434 tgl 3678 UIC 0 : set_completion_reference(prev2_wd);
434 tgl 3679 LBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables_for_trigger);
3212 heikki.linnakangas 3680 EUB : }
1661 tgl 3681 GIC 33 : else if (Matches("DROP", "TRIGGER", MatchAny, "ON", MatchAny))
1661 tgl 3682 UIC 0 : COMPLETE_WITH("CASCADE", "RESTRICT");
3683 :
3684 : /* DROP ACCESS METHOD */
1661 tgl 3685 GIC 33 : else if (Matches("DROP", "ACCESS"))
1661 tgl 3686 UIC 0 : COMPLETE_WITH("METHOD");
1661 tgl 3687 GIC 33 : else if (Matches("DROP", "ACCESS", "METHOD"))
2497 alvherre 3688 UIC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
3689 :
3282 rhaas 3690 ECB : /* DROP EVENT TRIGGER */
1661 tgl 3691 GBC 33 : else if (Matches("DROP", "EVENT"))
1661 tgl 3692 LBC 0 : COMPLETE_WITH("TRIGGER");
1661 tgl 3693 GBC 33 : else if (Matches("DROP", "EVENT", "TRIGGER"))
3282 rhaas 3694 LBC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
3282 rhaas 3695 EUB :
3696 : /* DROP POLICY <name> */
1661 tgl 3697 CBC 33 : else if (Matches("DROP", "POLICY"))
2820 alvherre 3698 UBC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_policies);
3699 : /* DROP POLICY <name> ON */
1661 tgl 3700 GIC 33 : else if (Matches("DROP", "POLICY", MatchAny))
1661 tgl 3701 UIC 0 : COMPLETE_WITH("ON");
3702 : /* DROP POLICY <name> ON <table> */
1661 tgl 3703 GIC 33 : else if (Matches("DROP", "POLICY", MatchAny, "ON"))
2820 alvherre 3704 ECB : {
434 tgl 3705 UBC 0 : set_completion_reference(prev2_wd);
434 tgl 3706 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables_for_policy);
2820 alvherre 3707 ECB : }
494 michael 3708 GBC 33 : else if (Matches("DROP", "POLICY", MatchAny, "ON", MatchAny))
494 michael 3709 UIC 0 : COMPLETE_WITH("CASCADE", "RESTRICT");
3124 sfrost 3710 ECB :
3212 heikki.linnakangas 3711 EUB : /* DROP RULE */
1661 tgl 3712 GIC 33 : else if (Matches("DROP", "RULE", MatchAny))
1661 tgl 3713 UIC 0 : COMPLETE_WITH("ON");
1661 tgl 3714 GIC 33 : else if (Matches("DROP", "RULE", MatchAny, "ON"))
3212 heikki.linnakangas 3715 ECB : {
434 tgl 3716 UBC 0 : set_completion_reference(prev2_wd);
434 tgl 3717 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables_for_rule);
3212 heikki.linnakangas 3718 ECB : }
1661 tgl 3719 GBC 33 : else if (Matches("DROP", "RULE", MatchAny, "ON", MatchAny))
1661 tgl 3720 UIC 0 : COMPLETE_WITH("CASCADE", "RESTRICT");
3212 heikki.linnakangas 3721 ECB :
494 michael 3722 EUB : /* DROP TRANSFORM */
494 michael 3723 GIC 33 : else if (Matches("DROP", "TRANSFORM"))
494 michael 3724 UIC 0 : COMPLETE_WITH("FOR");
494 michael 3725 GIC 33 : else if (Matches("DROP", "TRANSFORM", "FOR"))
434 tgl 3726 LBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
494 michael 3727 GBC 33 : else if (Matches("DROP", "TRANSFORM", "FOR", MatchAny))
494 michael 3728 UIC 0 : COMPLETE_WITH("LANGUAGE");
494 michael 3729 GIC 33 : else if (Matches("DROP", "TRANSFORM", "FOR", MatchAny, "LANGUAGE"))
494 michael 3730 ECB : {
434 tgl 3731 UBC 0 : set_completion_reference(prev2_wd);
494 michael 3732 UIC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_languages);
3733 : }
494 michael 3734 GIC 33 : else if (Matches("DROP", "TRANSFORM", "FOR", MatchAny, "LANGUAGE", MatchAny))
494 michael 3735 LBC 0 : COMPLETE_WITH("CASCADE", "RESTRICT");
3736 :
2668 tgl 3737 ECB : /* EXECUTE */
1661 tgl 3738 CBC 33 : else if (Matches("EXECUTE"))
4186 tgl 3739 LBC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_prepared_statements);
4186 tgl 3740 ECB :
1661 3741 : /*
3742 : * EXPLAIN [ ( option [, ...] ) ] statement
3743 : * EXPLAIN [ ANALYZE ] [ VERBOSE ] statement
3744 : */
1661 tgl 3745 CBC 33 : else if (Matches("EXPLAIN"))
696 michael 3746 UIC 0 : COMPLETE_WITH("SELECT", "INSERT INTO", "DELETE FROM", "UPDATE", "DECLARE",
3747 : "MERGE INTO", "EXECUTE", "ANALYZE", "VERBOSE");
1661 tgl 3748 CBC 33 : else if (HeadMatches("EXPLAIN", "(*") &&
1661 tgl 3749 UBC 0 : !HeadMatches("EXPLAIN", "(*)"))
1661 tgl 3750 ECB : {
1661 tgl 3751 EUB : /*
1661 tgl 3752 ECB : * This fires if we're in an unfinished parenthesized option list.
1661 tgl 3753 EUB : * get_previous_words treats a completed parenthesized option list as
1661 tgl 3754 ECB : * one word, so the above test is correct.
1661 tgl 3755 EUB : */
1661 tgl 3756 LBC 0 : if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
16 tgl 3757 UNC 0 : COMPLETE_WITH("ANALYZE", "VERBOSE", "COSTS", "SETTINGS", "GENERIC_PLAN",
3758 : "BUFFERS", "WAL", "TIMING", "SUMMARY", "FORMAT");
3759 0 : else if (TailMatches("ANALYZE|VERBOSE|COSTS|SETTINGS|GENERIC_PLAN|BUFFERS|WAL|TIMING|SUMMARY"))
1661 tgl 3760 LBC 0 : COMPLETE_WITH("ON", "OFF");
1661 tgl 3761 UBC 0 : else if (TailMatches("FORMAT"))
1661 tgl 3762 UIC 0 : COMPLETE_WITH("TEXT", "XML", "JSON", "YAML");
1661 tgl 3763 ECB : }
1661 tgl 3764 GBC 33 : else if (Matches("EXPLAIN", "ANALYZE"))
696 michael 3765 LBC 0 : COMPLETE_WITH("SELECT", "INSERT INTO", "DELETE FROM", "UPDATE", "DECLARE",
199 fujii 3766 EUB : "MERGE INTO", "EXECUTE", "VERBOSE");
1661 tgl 3767 CBC 66 : else if (Matches("EXPLAIN", "(*)") ||
1661 tgl 3768 GBC 66 : Matches("EXPLAIN", "VERBOSE") ||
1661 tgl 3769 GIC 33 : Matches("EXPLAIN", "ANALYZE", "VERBOSE"))
592 michael 3770 UIC 0 : COMPLETE_WITH("SELECT", "INSERT INTO", "DELETE FROM", "UPDATE", "DECLARE",
199 fujii 3771 ECB : "MERGE INTO", "EXECUTE");
8535 bruce 3772 EUB :
8535 bruce 3773 ECB : /* FETCH && MOVE */
906 fujii 3774 EUB :
906 fujii 3775 ECB : /*
906 fujii 3776 EUB : * Complete FETCH with one of ABSOLUTE, BACKWARD, FORWARD, RELATIVE, ALL,
3777 : * NEXT, PRIOR, FIRST, LAST, FROM, IN, and a list of cursors
3778 : */
1661 tgl 3779 CBC 33 : else if (Matches("FETCH|MOVE"))
434 tgl 3780 UBC 0 : COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_cursors,
434 tgl 3781 ECB : "ABSOLUTE",
434 tgl 3782 EUB : "BACKWARD",
434 tgl 3783 ECB : "FORWARD",
434 tgl 3784 EUB : "RELATIVE",
3785 : "ALL",
3786 : "NEXT",
434 tgl 3787 ECB : "PRIOR",
434 tgl 3788 EUB : "FIRST",
3789 : "LAST",
3790 : "FROM",
434 tgl 3791 ECB : "IN");
906 fujii 3792 EUB :
815 fujii 3793 ECB : /*
3794 : * Complete FETCH BACKWARD or FORWARD with one of ALL, FROM, IN, and a
815 fujii 3795 EUB : * list of cursors
3796 : */
906 fujii 3797 GIC 33 : else if (Matches("FETCH|MOVE", "BACKWARD|FORWARD"))
434 tgl 3798 LBC 0 : COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_cursors,
434 tgl 3799 EUB : "ALL",
3800 : "FROM",
3801 : "IN");
8397 bruce 3802 ECB :
8397 bruce 3803 EUB : /*
906 fujii 3804 ECB : * Complete FETCH <direction> with "FROM" or "IN". These are equivalent,
6385 bruce 3805 EUB : * but we may as well tab-complete both: perhaps some users prefer one
3806 : * variant or the other.
3807 : */
906 fujii 3808 CBC 33 : else if (Matches("FETCH|MOVE", "ABSOLUTE|BACKWARD|FORWARD|RELATIVE",
906 fujii 3809 GBC 33 : MatchAnyExcept("FROM|IN")) ||
906 fujii 3810 CBC 33 : Matches("FETCH|MOVE", "ALL|NEXT|PRIOR|FIRST|LAST"))
434 tgl 3811 UBC 0 : COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_cursors,
3812 : "FROM",
3813 : "IN");
815 fujii 3814 ECB : /* Complete FETCH <direction> "FROM" or "IN" with a list of cursors */
815 fujii 3815 GBC 33 : else if (HeadMatches("FETCH|MOVE") &&
815 fujii 3816 UIC 0 : TailMatches("FROM|IN"))
815 fujii 3817 LBC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_cursors);
8535 bruce 3818 EUB :
3819 : /* FOREIGN DATA WRAPPER */
5224 peter_e 3820 ECB : /* applies in ALTER/DROP FDW and in CREATE SERVER */
1661 tgl 3821 GIC 33 : else if (TailMatches("FOREIGN", "DATA", "WRAPPER") &&
1661 tgl 3822 UBC 0 : !TailMatches("CREATE", MatchAny, MatchAny, MatchAny))
5224 peter_e 3823 0 : COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
3824 : /* applies in CREATE SERVER */
1661 tgl 3825 CBC 33 : else if (TailMatches("FOREIGN", "DATA", "WRAPPER", MatchAny) &&
1661 tgl 3826 UBC 0 : HeadMatches("CREATE", "SERVER"))
1661 tgl 3827 UIC 0 : COMPLETE_WITH("OPTIONS");
3828 :
4481 rhaas 3829 ECB : /* FOREIGN TABLE */
1661 tgl 3830 GBC 33 : else if (TailMatches("FOREIGN", "TABLE") &&
1661 tgl 3831 LBC 0 : !TailMatches("CREATE", MatchAny, MatchAny))
434 tgl 3832 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables);
4481 rhaas 3833 EUB :
2769 fujii 3834 : /* FOREIGN SERVER */
1661 tgl 3835 GIC 33 : else if (TailMatches("FOREIGN", "SERVER"))
2769 fujii 3836 LBC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_servers);
2769 fujii 3837 EUB :
3838 : /*
3839 : * GRANT and REVOKE are allowed inside CREATE SCHEMA and
2298 sfrost 3840 ECB : * ALTER DEFAULT PRIVILEGES, so use TailMatches
2298 sfrost 3841 EUB : */
4096 peter_e 3842 ECB : /* Complete GRANT/REVOKE with a list of roles and privileges */
368 tgl 3843 GBC 66 : else if (TailMatches("GRANT|REVOKE") ||
118 michael 3844 GNC 33 : TailMatches("REVOKE", "ADMIN|GRANT|INHERIT|SET", "OPTION", "FOR"))
2154 tgl 3845 EUB : {
2298 sfrost 3846 ECB : /*
3847 : * With ALTER DEFAULT PRIVILEGES, restrict completion to grantable
2153 bruce 3848 EUB : * privileges (can't grant roles)
2298 sfrost 3849 : */
1661 tgl 3850 UIC 0 : if (HeadMatches("ALTER", "DEFAULT", "PRIVILEGES"))
1661 tgl 3851 LBC 0 : COMPLETE_WITH("SELECT", "INSERT", "UPDATE",
1661 tgl 3852 EUB : "DELETE", "TRUNCATE", "REFERENCES", "TRIGGER",
3853 : "CREATE", "EXECUTE", "USAGE", "MAINTAIN", "ALL");
142 michael 3854 UNC 0 : else if (TailMatches("GRANT"))
434 tgl 3855 LBC 0 : COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
3856 : Privilege_options_of_grant_and_revoke);
142 michael 3857 UNC 0 : else if (TailMatches("REVOKE"))
3858 0 : COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
3859 : Privilege_options_of_grant_and_revoke,
3860 : "GRANT OPTION FOR",
3861 : "ADMIN OPTION FOR",
3862 : "INHERIT OPTION FOR",
3863 : "SET OPTION FOR");
3864 0 : else if (TailMatches("REVOKE", "GRANT", "OPTION", "FOR"))
3865 0 : COMPLETE_WITH(Privilege_options_of_grant_and_revoke);
118 3866 0 : else if (TailMatches("REVOKE", "ADMIN|INHERIT|SET", "OPTION", "FOR"))
142 3867 0 : COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3868 : }
368 tgl 3869 EUB :
368 tgl 3870 GBC 66 : else if (TailMatches("GRANT|REVOKE", "ALTER") ||
368 tgl 3871 GIC 33 : TailMatches("REVOKE", "GRANT", "OPTION", "FOR", "ALTER"))
368 tgl 3872 LBC 0 : COMPLETE_WITH("SYSTEM");
368 tgl 3873 EUB :
118 michael 3874 GNC 33 : else if (TailMatches("REVOKE", "SET"))
118 michael 3875 UNC 0 : COMPLETE_WITH("ON PARAMETER", "OPTION FOR");
118 michael 3876 GNC 66 : else if (TailMatches("GRANT", "SET") ||
368 tgl 3877 CBC 66 : TailMatches("REVOKE", "GRANT", "OPTION", "FOR", "SET") ||
3878 66 : TailMatches("GRANT|REVOKE", "ALTER", "SYSTEM") ||
3879 33 : TailMatches("REVOKE", "GRANT", "OPTION", "FOR", "ALTER", "SYSTEM"))
368 tgl 3880 UBC 0 : COMPLETE_WITH("ON PARAMETER");
3881 :
368 tgl 3882 GIC 66 : else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "PARAMETER") ||
3883 66 : TailMatches("GRANT|REVOKE", MatchAny, MatchAny, "ON", "PARAMETER") ||
3884 66 : TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "PARAMETER") ||
3885 33 : TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, MatchAny, "ON", "PARAMETER"))
367 tgl 3886 UIC 0 : COMPLETE_WITH_QUERY_VERBATIM(Query_for_list_of_alter_system_set_vars);
3887 :
368 tgl 3888 GIC 66 : else if (TailMatches("GRANT", MatchAny, "ON", "PARAMETER", MatchAny) ||
368 tgl 3889 CBC 33 : TailMatches("GRANT", MatchAny, MatchAny, "ON", "PARAMETER", MatchAny))
368 tgl 3890 UBC 0 : COMPLETE_WITH("TO");
3891 :
368 tgl 3892 GIC 66 : else if (TailMatches("REVOKE", MatchAny, "ON", "PARAMETER", MatchAny) ||
3893 66 : TailMatches("REVOKE", MatchAny, MatchAny, "ON", "PARAMETER", MatchAny) ||
3894 66 : TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "PARAMETER", MatchAny) ||
3895 33 : TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, MatchAny, "ON", "PARAMETER", MatchAny))
368 tgl 3896 UIC 0 : COMPLETE_WITH("FROM");
3897 :
3898 : /*
3899 : * Complete GRANT/REVOKE <privilege> with "ON", GRANT/REVOKE <role> with
3900 : * TO/FROM
3901 : */
368 tgl 3902 GIC 66 : else if (TailMatches("GRANT|REVOKE", MatchAny) ||
3903 33 : TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny))
3904 : {
1661 tgl 3905 UIC 0 : if (TailMatches("SELECT|INSERT|UPDATE|DELETE|TRUNCATE|REFERENCES|TRIGGER|CREATE|CONNECT|TEMPORARY|TEMP|EXECUTE|USAGE|ALL"))
3906 0 : COMPLETE_WITH("ON");
1661 tgl 3907 LBC 0 : else if (TailMatches("GRANT", MatchAny))
1661 tgl 3908 UBC 0 : COMPLETE_WITH("TO");
3909 : else
1661 tgl 3910 UIC 0 : COMPLETE_WITH("FROM");
3911 : }
3912 :
3913 : /*
3914 : * Complete GRANT/REVOKE <sth> ON with a list of appropriate relations.
3915 : *
3916 : * Note: GRANT/REVOKE can get quite complex; tab-completion as implemented
3917 : * here will only work if the privilege list contains exactly one
2769 fujii 3918 ECB : * privilege.
8397 bruce 3919 : */
368 tgl 3920 CBC 66 : else if (TailMatches("GRANT|REVOKE", MatchAny, "ON") ||
368 tgl 3921 GBC 33 : TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON"))
3922 : {
3923 : /*
3924 : * With ALTER DEFAULT PRIVILEGES, restrict completion to the kinds of
2153 bruce 3925 ECB : * objects supported.
2298 sfrost 3926 EUB : */
1661 tgl 3927 UBC 0 : if (HeadMatches("ALTER", "DEFAULT", "PRIVILEGES"))
1661 tgl 3928 UIC 0 : COMPLETE_WITH("TABLES", "SEQUENCES", "FUNCTIONS", "PROCEDURES", "ROUTINES", "TYPES", "SCHEMAS");
3929 : else
434 3930 0 : COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_grantables,
434 tgl 3931 ECB : "ALL FUNCTIONS IN SCHEMA",
434 tgl 3932 EUB : "ALL PROCEDURES IN SCHEMA",
3933 : "ALL ROUTINES IN SCHEMA",
3934 : "ALL SEQUENCES IN SCHEMA",
191 alvherre 3935 ECB : "ALL TABLES IN SCHEMA",
434 tgl 3936 EUB : "DATABASE",
3937 : "DOMAIN",
3938 : "FOREIGN DATA WRAPPER",
3939 : "FOREIGN SERVER",
434 tgl 3940 ECB : "FUNCTION",
434 tgl 3941 EUB : "LANGUAGE",
3942 : "LARGE OBJECT",
3943 : "PARAMETER",
3944 : "PROCEDURE",
434 tgl 3945 ECB : "ROUTINE",
434 tgl 3946 EUB : "SCHEMA",
3947 : "SEQUENCE",
3948 : "TABLE",
3949 : "TABLESPACE",
3950 : "TYPE");
3951 : }
368 tgl 3952 GIC 66 : else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "ALL") ||
368 tgl 3953 CBC 33 : TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "ALL"))
1661 tgl 3954 LBC 0 : COMPLETE_WITH("FUNCTIONS IN SCHEMA",
3955 : "PROCEDURES IN SCHEMA",
3956 : "ROUTINES IN SCHEMA",
3957 : "SEQUENCES IN SCHEMA",
3958 : "TABLES IN SCHEMA");
368 tgl 3959 GIC 66 : else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "FOREIGN") ||
368 tgl 3960 GBC 33 : TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "FOREIGN"))
1661 tgl 3961 UBC 0 : COMPLETE_WITH("DATA WRAPPER", "SERVER");
3962 :
3963 : /*
2668 tgl 3964 EUB : * Complete "GRANT/REVOKE * ON DATABASE/DOMAIN/..." with a list of
2769 fujii 3965 : * appropriate objects.
3966 : *
2668 tgl 3967 : * Complete "GRANT/REVOKE * ON *" with "TO/FROM".
2769 fujii 3968 : */
368 tgl 3969 GIC 66 : else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", MatchAny) ||
3970 33 : TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", MatchAny))
3971 : {
1661 tgl 3972 UIC 0 : if (TailMatches("DATABASE"))
7318 bruce 3973 0 : COMPLETE_WITH_QUERY(Query_for_list_of_databases);
1661 tgl 3974 UBC 0 : else if (TailMatches("DOMAIN"))
434 3975 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains);
1661 3976 0 : else if (TailMatches("FUNCTION"))
434 3977 0 : COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_functions);
1661 tgl 3978 UIC 0 : else if (TailMatches("LANGUAGE"))
7318 bruce 3979 0 : COMPLETE_WITH_QUERY(Query_for_list_of_languages);
1661 tgl 3980 LBC 0 : else if (TailMatches("PROCEDURE"))
434 3981 0 : COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_procedures);
1661 tgl 3982 UBC 0 : else if (TailMatches("ROUTINE"))
434 tgl 3983 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_routines);
1661 tgl 3984 LBC 0 : else if (TailMatches("SCHEMA"))
7318 bruce 3985 UBC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
1661 tgl 3986 LBC 0 : else if (TailMatches("SEQUENCE"))
434 3987 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences);
1661 3988 0 : else if (TailMatches("TABLE"))
434 3989 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_grantables);
1661 tgl 3990 UBC 0 : else if (TailMatches("TABLESPACE"))
6806 bruce 3991 UIC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
1661 tgl 3992 LBC 0 : else if (TailMatches("TYPE"))
434 3993 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
1661 3994 0 : else if (TailMatches("GRANT", MatchAny, MatchAny, MatchAny))
3995 0 : COMPLETE_WITH("TO");
6535 neilc 3996 EUB : else
1661 tgl 3997 UIC 0 : COMPLETE_WITH("FROM");
7318 bruce 3998 ECB : }
8397 3999 :
2668 tgl 4000 EUB : /*
4001 : * Complete "GRANT/REVOKE ... TO/FROM" with username, PUBLIC,
718 michael 4002 ECB : * CURRENT_ROLE, CURRENT_USER, or SESSION_USER.
2668 tgl 4003 : */
1661 tgl 4004 CBC 66 : else if ((HeadMatches("GRANT") && TailMatches("TO")) ||
4005 33 : (HeadMatches("REVOKE") && TailMatches("FROM")))
434 tgl 4006 UBC 0 : COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
4007 : Keywords_for_list_of_grant_roles);
4008 :
4009 : /*
4010 : * Offer grant options after that.
4011 : */
368 tgl 4012 CBC 33 : else if (HeadMatches("GRANT") && TailMatches("TO", MatchAny))
142 michael 4013 UNC 0 : COMPLETE_WITH("WITH ADMIN",
4014 : "WITH INHERIT",
4015 : "WITH SET",
4016 : "WITH GRANT OPTION",
368 tgl 4017 EUB : "GRANTED BY");
368 tgl 4018 GBC 33 : else if (HeadMatches("GRANT") && TailMatches("TO", MatchAny, "WITH"))
142 michael 4019 UNC 0 : COMPLETE_WITH("ADMIN",
4020 : "INHERIT",
4021 : "SET",
368 tgl 4022 EUB : "GRANT OPTION");
142 michael 4023 GNC 33 : else if (HeadMatches("GRANT") &&
118 michael 4024 UNC 0 : (TailMatches("TO", MatchAny, "WITH", "ADMIN|INHERIT|SET")))
142 4025 0 : COMPLETE_WITH("OPTION", "TRUE", "FALSE");
368 tgl 4026 GIC 33 : else if (HeadMatches("GRANT") && TailMatches("TO", MatchAny, "WITH", MatchAny, "OPTION"))
368 tgl 4027 UBC 0 : COMPLETE_WITH("GRANTED BY");
368 tgl 4028 GIC 33 : else if (HeadMatches("GRANT") && TailMatches("TO", MatchAny, "WITH", MatchAny, "OPTION", "GRANTED", "BY"))
368 tgl 4029 UIC 0 : COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
4030 : Keywords_for_list_of_grant_roles);
4031 : /* Complete "ALTER DEFAULT PRIVILEGES ... GRANT/REVOKE ... TO/FROM */
1661 tgl 4032 GIC 33 : else if (HeadMatches("ALTER", "DEFAULT", "PRIVILEGES") && TailMatches("TO|FROM"))
434 tgl 4033 UIC 0 : COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
4034 : Keywords_for_list_of_grant_roles);
4035 : /* Complete "GRANT/REVOKE ... ON * *" with TO/FROM */
1661 tgl 4036 GIC 33 : else if (HeadMatches("GRANT") && TailMatches("ON", MatchAny, MatchAny))
1661 tgl 4037 LBC 0 : COMPLETE_WITH("TO");
1661 tgl 4038 CBC 33 : else if (HeadMatches("REVOKE") && TailMatches("ON", MatchAny, MatchAny))
1661 tgl 4039 UIC 0 : COMPLETE_WITH("FROM");
4040 :
4041 : /* Complete "GRANT/REVOKE * ON ALL * IN SCHEMA *" with TO/FROM */
368 tgl 4042 GIC 66 : else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "ALL", MatchAny, "IN", "SCHEMA", MatchAny) ||
4043 33 : TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "ALL", MatchAny, "IN", "SCHEMA", MatchAny))
4799 itagaki.takahiro 4044 EUB : {
1661 tgl 4045 UBC 0 : if (TailMatches("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
1661 tgl 4046 UIC 0 : COMPLETE_WITH("TO");
4799 itagaki.takahiro 4047 EUB : else
1661 tgl 4048 UIC 0 : COMPLETE_WITH("FROM");
4049 : }
4050 :
4051 : /* Complete "GRANT/REVOKE * ON FOREIGN DATA WRAPPER *" with TO/FROM */
368 tgl 4052 GIC 66 : else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "DATA", "WRAPPER", MatchAny) ||
4053 33 : TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "FOREIGN", "DATA", "WRAPPER", MatchAny))
4054 : {
1661 tgl 4055 UIC 0 : if (TailMatches("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
4056 0 : COMPLETE_WITH("TO");
4057 : else
4058 0 : COMPLETE_WITH("FROM");
4059 : }
4060 :
4061 : /* Complete "GRANT/REVOKE * ON FOREIGN SERVER *" with TO/FROM */
368 tgl 4062 GIC 66 : else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "SERVER", MatchAny) ||
4063 33 : TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "FOREIGN", "SERVER", MatchAny))
4064 : {
1661 tgl 4065 UIC 0 : if (TailMatches("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
4066 0 : COMPLETE_WITH("TO");
4067 : else
4068 0 : COMPLETE_WITH("FROM");
4799 itagaki.takahiro 4069 ECB : }
6535 neilc 4070 :
6535 neilc 4071 EUB : /* GROUP BY */
1661 tgl 4072 GIC 33 : else if (TailMatches("FROM", MatchAny, "GROUP"))
1661 tgl 4073 UIC 0 : COMPLETE_WITH("BY");
4074 :
4075 : /* IMPORT FOREIGN SCHEMA */
1661 tgl 4076 CBC 33 : else if (Matches("IMPORT"))
1661 tgl 4077 LBC 0 : COMPLETE_WITH("FOREIGN SCHEMA");
1661 tgl 4078 GBC 33 : else if (Matches("IMPORT", "FOREIGN"))
1661 tgl 4079 UIC 0 : COMPLETE_WITH("SCHEMA");
934 michael 4080 GIC 33 : else if (Matches("IMPORT", "FOREIGN", "SCHEMA", MatchAny))
934 michael 4081 UIC 0 : COMPLETE_WITH("EXCEPT (", "FROM SERVER", "LIMIT TO (");
934 michael 4082 GIC 66 : else if (TailMatches("LIMIT", "TO", "(*)") ||
4083 33 : TailMatches("EXCEPT", "(*)"))
934 michael 4084 UIC 0 : COMPLETE_WITH("FROM SERVER");
934 michael 4085 GIC 33 : else if (TailMatches("FROM", "SERVER", MatchAny))
934 michael 4086 LBC 0 : COMPLETE_WITH("INTO");
934 michael 4087 CBC 33 : else if (TailMatches("FROM", "SERVER", MatchAny, "INTO"))
934 michael 4088 UIC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
934 michael 4089 GBC 33 : else if (TailMatches("FROM", "SERVER", MatchAny, "INTO", MatchAny))
934 michael 4090 UBC 0 : COMPLETE_WITH("OPTIONS (");
3195 tgl 4091 EUB :
2652 4092 : /* INSERT --- can be inside EXPLAIN, RULE, etc */
377 alvherre 4093 : /* Complete NOT MATCHED THEN INSERT */
377 alvherre 4094 GBC 33 : else if (TailMatches("NOT", "MATCHED", "THEN", "INSERT"))
377 alvherre 4095 UBC 0 : COMPLETE_WITH("VALUES", "(");
8397 bruce 4096 EUB : /* Complete INSERT with "INTO" */
1661 tgl 4097 GBC 33 : else if (TailMatches("INSERT"))
1661 tgl 4098 UBC 0 : COMPLETE_WITH("INTO");
8397 bruce 4099 EUB : /* Complete INSERT INTO with table names */
1661 tgl 4100 GBC 33 : else if (TailMatches("INSERT", "INTO"))
434 tgl 4101 UBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables);
7558 bruce 4102 EUB : /* Complete "INSERT INTO <table> (" with attribute names */
1661 tgl 4103 GBC 33 : else if (TailMatches("INSERT", "INTO", MatchAny, "("))
434 tgl 4104 UBC 0 : COMPLETE_WITH_ATTR(prev2_wd);
7836 bruce 4105 EUB :
4106 : /*
4790 4107 : * Complete INSERT INTO <table> with "(" or "VALUES" or "SELECT" or
2194 peter_e 4108 : * "TABLE" or "DEFAULT VALUES" or "OVERRIDING"
7836 bruce 4109 : */
1661 tgl 4110 GBC 33 : else if (TailMatches("INSERT", "INTO", MatchAny))
1661 tgl 4111 UBC 0 : COMPLETE_WITH("(", "DEFAULT VALUES", "SELECT", "TABLE", "VALUES", "OVERRIDING");
5050 bruce 4112 EUB :
4113 : /*
4114 : * Complete INSERT INTO <table> (attribs) with "VALUES" or "SELECT" or
4115 : * "TABLE" or "OVERRIDING"
4116 : */
1661 tgl 4117 GIC 33 : else if (TailMatches("INSERT", "INTO", MatchAny, MatchAny) &&
2668 tgl 4118 UIC 0 : ends_with(prev_wd, ')'))
1661 4119 0 : COMPLETE_WITH("SELECT", "TABLE", "VALUES", "OVERRIDING");
4120 :
2194 peter_e 4121 ECB : /* Complete OVERRIDING */
1661 tgl 4122 CBC 33 : else if (TailMatches("OVERRIDING"))
1661 tgl 4123 UBC 0 : COMPLETE_WITH("SYSTEM VALUE", "USER VALUE");
4124 :
4125 : /* Complete after OVERRIDING clause */
1661 tgl 4126 GIC 33 : else if (TailMatches("OVERRIDING", MatchAny, "VALUE"))
1661 tgl 4127 UIC 0 : COMPLETE_WITH("SELECT", "TABLE", "VALUES");
4128 :
8397 bruce 4129 ECB : /* Insert an open parenthesis after "VALUES" */
1661 tgl 4130 GBC 33 : else if (TailMatches("VALUES") && !TailMatches("DEFAULT", "VALUES"))
1661 tgl 4131 UIC 0 : COMPLETE_WITH("(");
4132 :
4133 : /* LOCK */
4134 : /* Complete LOCK [TABLE] [ONLY] with a list of tables */
1661 tgl 4135 CBC 33 : else if (Matches("LOCK"))
434 tgl 4136 UBC 0 : COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_tables,
4137 : "TABLE", "ONLY");
1661 tgl 4138 GIC 33 : else if (Matches("LOCK", "TABLE"))
434 tgl 4139 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_tables,
434 tgl 4140 ECB : "ONLY");
551 fujii 4141 GBC 33 : else if (Matches("LOCK", "TABLE", "ONLY") || Matches("LOCK", "ONLY"))
434 tgl 4142 UBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
7558 bruce 4143 ECB : /* For the following, handle the case of a single table only for now */
7558 bruce 4144 EUB :
551 fujii 4145 ECB : /* Complete LOCK [TABLE] [ONLY] <table> with IN or NOWAIT */
551 fujii 4146 GBC 66 : else if (Matches("LOCK", MatchAnyExcept("TABLE|ONLY")) ||
551 fujii 4147 GIC 66 : Matches("LOCK", "TABLE", MatchAnyExcept("ONLY")) ||
4148 66 : Matches("LOCK", "ONLY", MatchAny) ||
551 fujii 4149 CBC 33 : Matches("LOCK", "TABLE", "ONLY", MatchAny))
551 fujii 4150 UBC 0 : COMPLETE_WITH("IN", "NOWAIT");
4151 :
4152 : /* Complete LOCK [TABLE] [ONLY] <table> IN with a lock mode */
551 fujii 4153 CBC 33 : else if (HeadMatches("LOCK") && TailMatches("IN"))
1661 tgl 4154 UBC 0 : COMPLETE_WITH("ACCESS SHARE MODE",
1661 tgl 4155 ECB : "ROW SHARE MODE", "ROW EXCLUSIVE MODE",
1661 tgl 4156 EUB : "SHARE UPDATE EXCLUSIVE MODE", "SHARE MODE",
4157 : "SHARE ROW EXCLUSIVE MODE",
4158 : "EXCLUSIVE MODE", "ACCESS EXCLUSIVE MODE");
8535 bruce 4159 ECB :
551 fujii 4160 : /*
4161 : * Complete LOCK [TABLE][ONLY] <table> IN ACCESS|ROW with rest of lock
551 fujii 4162 EUB : * mode
4163 : */
551 fujii 4164 GIC 33 : else if (HeadMatches("LOCK") && TailMatches("IN", "ACCESS|ROW"))
1661 tgl 4165 UBC 0 : COMPLETE_WITH("EXCLUSIVE MODE", "SHARE MODE");
4166 :
4167 : /* Complete LOCK [TABLE] [ONLY] <table> IN SHARE with rest of lock mode */
551 fujii 4168 GIC 33 : else if (HeadMatches("LOCK") && TailMatches("IN", "SHARE"))
1661 tgl 4169 LBC 0 : COMPLETE_WITH("MODE", "ROW EXCLUSIVE MODE",
1661 tgl 4170 ECB : "UPDATE EXCLUSIVE MODE");
4171 :
199 fujii 4172 EUB : /* Complete LOCK [TABLE] [ONLY] <table> [IN lockmode MODE] with "NOWAIT" */
199 fujii 4173 GBC 33 : else if (HeadMatches("LOCK") && TailMatches("MODE"))
199 fujii 4174 UIC 0 : COMPLETE_WITH("NOWAIT");
199 fujii 4175 EUB :
4176 : /* MERGE --- can be inside EXPLAIN */
377 alvherre 4177 GIC 33 : else if (TailMatches("MERGE"))
377 alvherre 4178 UIC 0 : COMPLETE_WITH("INTO");
377 alvherre 4179 CBC 33 : else if (TailMatches("MERGE", "INTO"))
377 alvherre 4180 LBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_mergetargets);
4181 :
199 fujii 4182 EUB : /* Complete MERGE INTO <table> [[AS] <alias>] with USING */
377 alvherre 4183 GBC 33 : else if (TailMatches("MERGE", "INTO", MatchAny))
377 alvherre 4184 UIC 0 : COMPLETE_WITH("USING", "AS");
199 fujii 4185 GBC 66 : else if (TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny) ||
199 fujii 4186 GIC 33 : TailMatches("MERGE", "INTO", MatchAny, MatchAnyExcept("USING|AS")))
377 alvherre 4187 UIC 0 : COMPLETE_WITH("USING");
4188 :
199 fujii 4189 ECB : /*
199 fujii 4190 EUB : * Complete MERGE INTO ... USING with a list of relations supporting
4191 : * SELECT
4192 : */
199 fujii 4193 CBC 66 : else if (TailMatches("MERGE", "INTO", MatchAny, "USING") ||
199 fujii 4194 GBC 66 : TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny, "USING") ||
199 fujii 4195 CBC 33 : TailMatches("MERGE", "INTO", MatchAny, MatchAny, "USING"))
199 fujii 4196 UBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_selectables);
199 fujii 4197 ECB :
199 fujii 4198 EUB : /*
199 fujii 4199 ECB : * Complete MERGE INTO <table> [[AS] <alias>] USING <relations> [[AS]
4200 : * alias] with ON
199 fujii 4201 EUB : */
199 fujii 4202 CBC 66 : else if (TailMatches("MERGE", "INTO", MatchAny, "USING", MatchAny) ||
199 fujii 4203 GBC 66 : TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny, "USING", MatchAny) ||
199 fujii 4204 CBC 33 : TailMatches("MERGE", "INTO", MatchAny, MatchAny, "USING", MatchAny))
199 fujii 4205 UBC 0 : COMPLETE_WITH("AS", "ON");
199 fujii 4206 CBC 66 : else if (TailMatches("MERGE", "INTO", MatchAny, "USING", MatchAny, "AS", MatchAny) ||
199 fujii 4207 GBC 66 : TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny, "USING", MatchAny, "AS", MatchAny) ||
199 fujii 4208 GIC 66 : TailMatches("MERGE", "INTO", MatchAny, MatchAny, "USING", MatchAny, "AS", MatchAny) ||
4209 66 : TailMatches("MERGE", "INTO", MatchAny, "USING", MatchAny, MatchAnyExcept("ON|AS")) ||
4210 66 : TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny, "USING", MatchAny, MatchAnyExcept("ON|AS")) ||
199 fujii 4211 CBC 33 : TailMatches("MERGE", "INTO", MatchAny, MatchAny, "USING", MatchAny, MatchAnyExcept("ON|AS")))
377 alvherre 4212 UBC 0 : COMPLETE_WITH("ON");
4213 :
199 fujii 4214 ECB : /* Complete MERGE INTO ... ON with target table attributes */
377 alvherre 4215 GBC 33 : else if (TailMatches("INTO", MatchAny, "USING", MatchAny, "ON"))
377 alvherre 4216 UIC 0 : COMPLETE_WITH_ATTR(prev4_wd);
377 alvherre 4217 CBC 33 : else if (TailMatches("INTO", MatchAny, "AS", MatchAny, "USING", MatchAny, "AS", MatchAny, "ON"))
377 alvherre 4218 UBC 0 : COMPLETE_WITH_ATTR(prev8_wd);
377 alvherre 4219 GIC 33 : else if (TailMatches("INTO", MatchAny, MatchAny, "USING", MatchAny, MatchAny, "ON"))
377 alvherre 4220 LBC 0 : COMPLETE_WITH_ATTR(prev6_wd);
199 fujii 4221 EUB :
4222 : /*
4223 : * Complete ... USING <relation> [[AS] alias] ON join condition
4224 : * (consisting of one or three words typically used) with WHEN [NOT]
4225 : * MATCHED
4226 : */
199 fujii 4227 CBC 66 : else if (TailMatches("USING", MatchAny, "ON", MatchAny) ||
199 fujii 4228 GBC 66 : TailMatches("USING", MatchAny, "AS", MatchAny, "ON", MatchAny) ||
199 fujii 4229 GIC 66 : TailMatches("USING", MatchAny, MatchAny, "ON", MatchAny) ||
4230 66 : TailMatches("USING", MatchAny, "ON", MatchAny, MatchAnyExcept("WHEN"), MatchAnyExcept("WHEN")) ||
4231 66 : TailMatches("USING", MatchAny, "AS", MatchAny, "ON", MatchAny, MatchAnyExcept("WHEN"), MatchAnyExcept("WHEN")) ||
4232 33 : TailMatches("USING", MatchAny, MatchAny, "ON", MatchAny, MatchAnyExcept("WHEN"), MatchAnyExcept("WHEN")))
377 alvherre 4233 UIC 0 : COMPLETE_WITH("WHEN MATCHED", "WHEN NOT MATCHED");
199 fujii 4234 CBC 66 : else if (TailMatches("USING", MatchAny, "ON", MatchAny, "WHEN") ||
199 fujii 4235 GBC 66 : TailMatches("USING", MatchAny, "AS", MatchAny, "ON", MatchAny, "WHEN") ||
4236 66 : TailMatches("USING", MatchAny, MatchAny, "ON", MatchAny, "WHEN") ||
199 fujii 4237 GIC 66 : TailMatches("USING", MatchAny, "ON", MatchAny, MatchAny, MatchAny, "WHEN") ||
4238 66 : TailMatches("USING", MatchAny, "AS", MatchAny, "ON", MatchAny, MatchAny, MatchAny, "WHEN") ||
199 fujii 4239 CBC 33 : TailMatches("USING", MatchAny, MatchAny, "ON", MatchAny, MatchAny, MatchAny, "WHEN"))
199 fujii 4240 UBC 0 : COMPLETE_WITH("MATCHED", "NOT MATCHED");
4241 :
4242 : /* Complete ... WHEN [NOT] MATCHED with THEN/AND */
199 fujii 4243 CBC 66 : else if (TailMatches("WHEN", "MATCHED") ||
199 fujii 4244 GBC 33 : TailMatches("WHEN", "NOT", "MATCHED"))
377 alvherre 4245 UIC 0 : COMPLETE_WITH("THEN", "AND");
4246 :
199 fujii 4247 ECB : /* Complete ... WHEN MATCHED THEN with UPDATE SET/DELETE/DO NOTHING */
377 alvherre 4248 GBC 33 : else if (TailMatches("WHEN", "MATCHED", "THEN"))
199 fujii 4249 UIC 0 : COMPLETE_WITH("UPDATE SET", "DELETE", "DO NOTHING");
4250 :
4251 : /* Complete ... WHEN NOT MATCHED THEN with INSERT/DO NOTHING */
377 alvherre 4252 CBC 33 : else if (TailMatches("WHEN", "NOT", "MATCHED", "THEN"))
377 alvherre 4253 UBC 0 : COMPLETE_WITH("INSERT", "DO NOTHING");
4254 :
2652 tgl 4255 ECB : /* NOTIFY --- can be inside EXPLAIN, RULE, etc */
1661 tgl 4256 GBC 33 : else if (TailMatches("NOTIFY"))
434 tgl 4257 UIC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_channels);
6535 neilc 4258 ECB :
5224 peter_e 4259 EUB : /* OPTIONS */
1661 tgl 4260 GIC 33 : else if (TailMatches("OPTIONS"))
1661 tgl 4261 UIC 0 : COMPLETE_WITH("(");
4262 :
6216 alvherre 4263 ECB : /* OWNER TO - complete with available roles */
1661 tgl 4264 CBC 33 : else if (TailMatches("OWNER", "TO"))
186 michael 4265 UNC 0 : COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
4266 : "CURRENT_ROLE",
4267 : "CURRENT_USER",
4268 : "SESSION_USER");
6535 neilc 4269 ECB :
6535 neilc 4270 EUB : /* ORDER BY */
1661 tgl 4271 GIC 33 : else if (TailMatches("FROM", MatchAny, "ORDER"))
1661 tgl 4272 UIC 0 : COMPLETE_WITH("BY");
1661 tgl 4273 CBC 33 : else if (TailMatches("FROM", MatchAny, "ORDER", "BY"))
434 tgl 4274 UBC 0 : COMPLETE_WITH_ATTR(prev3_wd);
4275 :
4276 : /* PREPARE xx AS */
1661 tgl 4277 GIC 33 : else if (Matches("PREPARE", MatchAny, "AS"))
696 michael 4278 UIC 0 : COMPLETE_WITH("SELECT", "UPDATE", "INSERT INTO", "DELETE FROM");
4279 :
4280 : /*
4281 : * PREPARE TRANSACTION is missing on purpose. It's intended for transaction
4282 : * managers, not for manual use in interactive sessions.
4283 : */
4822 heikki.linnakangas 4284 ECB :
6216 alvherre 4285 EUB : /* REASSIGN OWNED BY xxx TO yyy */
1661 tgl 4286 GIC 33 : else if (Matches("REASSIGN"))
1661 tgl 4287 UIC 0 : COMPLETE_WITH("OWNED BY");
1661 tgl 4288 CBC 33 : else if (Matches("REASSIGN", "OWNED"))
1661 tgl 4289 UBC 0 : COMPLETE_WITH("BY");
1661 tgl 4290 GIC 33 : else if (Matches("REASSIGN", "OWNED", "BY"))
6216 alvherre 4291 UIC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_roles);
1661 tgl 4292 GIC 33 : else if (Matches("REASSIGN", "OWNED", "BY", MatchAny))
1661 tgl 4293 LBC 0 : COMPLETE_WITH("TO");
1661 tgl 4294 GBC 33 : else if (Matches("REASSIGN", "OWNED", "BY", MatchAny, "TO"))
6216 alvherre 4295 UIC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_roles);
4296 :
3689 kgrittn 4297 ECB : /* REFRESH MATERIALIZED VIEW */
1661 tgl 4298 GBC 33 : else if (Matches("REFRESH"))
1661 tgl 4299 LBC 0 : COMPLETE_WITH("MATERIALIZED VIEW");
1661 tgl 4300 GBC 33 : else if (Matches("REFRESH", "MATERIALIZED"))
1661 tgl 4301 UIC 0 : COMPLETE_WITH("VIEW");
1661 tgl 4302 GIC 33 : else if (Matches("REFRESH", "MATERIALIZED", "VIEW"))
434 tgl 4303 LBC 0 : COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_matviews,
434 tgl 4304 EUB : "CONCURRENTLY");
1661 tgl 4305 CBC 33 : else if (Matches("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY"))
434 tgl 4306 LBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews);
1661 tgl 4307 GBC 33 : else if (Matches("REFRESH", "MATERIALIZED", "VIEW", MatchAny))
1661 tgl 4308 UIC 0 : COMPLETE_WITH("WITH");
1661 tgl 4309 GIC 33 : else if (Matches("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny))
1661 tgl 4310 UIC 0 : COMPLETE_WITH("WITH");
1661 tgl 4311 GIC 33 : else if (Matches("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH"))
1661 tgl 4312 UIC 0 : COMPLETE_WITH("NO DATA", "DATA");
1661 tgl 4313 CBC 33 : else if (Matches("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH"))
1661 tgl 4314 LBC 0 : COMPLETE_WITH("NO DATA", "DATA");
1661 tgl 4315 CBC 33 : else if (Matches("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH", "NO"))
1661 tgl 4316 UBC 0 : COMPLETE_WITH("DATA");
1661 tgl 4317 GIC 33 : else if (Matches("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH", "NO"))
1661 tgl 4318 UIC 0 : COMPLETE_WITH("DATA");
4319 :
4320 : /* REINDEX */
971 michael 4321 GIC 66 : else if (Matches("REINDEX") ||
971 michael 4322 CBC 33 : Matches("REINDEX", "(*)"))
1661 tgl 4323 LBC 0 : COMPLETE_WITH("TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE");
971 michael 4324 CBC 66 : else if (Matches("REINDEX", "TABLE") ||
971 michael 4325 GBC 33 : Matches("REINDEX", "(*)", "TABLE"))
434 tgl 4326 LBC 0 : COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_indexables,
434 tgl 4327 ECB : "CONCURRENTLY");
971 michael 4328 CBC 66 : else if (Matches("REINDEX", "INDEX") ||
4329 33 : Matches("REINDEX", "(*)", "INDEX"))
434 tgl 4330 LBC 0 : COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_indexes,
434 tgl 4331 ECB : "CONCURRENTLY");
971 michael 4332 GBC 66 : else if (Matches("REINDEX", "SCHEMA") ||
971 michael 4333 GIC 33 : Matches("REINDEX", "(*)", "SCHEMA"))
434 tgl 4334 UIC 0 : COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_schemas,
434 tgl 4335 ECB : "CONCURRENTLY");
971 michael 4336 GBC 66 : else if (Matches("REINDEX", "SYSTEM|DATABASE") ||
971 michael 4337 CBC 33 : Matches("REINDEX", "(*)", "SYSTEM|DATABASE"))
434 tgl 4338 UBC 0 : COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_databases,
434 tgl 4339 ECB : "CONCURRENTLY");
971 michael 4340 GBC 66 : else if (Matches("REINDEX", "TABLE", "CONCURRENTLY") ||
971 michael 4341 GIC 33 : Matches("REINDEX", "(*)", "TABLE", "CONCURRENTLY"))
434 tgl 4342 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexables);
971 michael 4343 GIC 66 : else if (Matches("REINDEX", "INDEX", "CONCURRENTLY") ||
4344 33 : Matches("REINDEX", "(*)", "INDEX", "CONCURRENTLY"))
434 tgl 4345 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes);
971 michael 4346 GIC 66 : else if (Matches("REINDEX", "SCHEMA", "CONCURRENTLY") ||
971 michael 4347 CBC 33 : Matches("REINDEX", "(*)", "SCHEMA", "CONCURRENTLY"))
1472 peter 4348 LBC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
971 michael 4349 CBC 66 : else if (Matches("REINDEX", "SYSTEM|DATABASE", "CONCURRENTLY") ||
4350 33 : Matches("REINDEX", "(*)", "SYSTEM|DATABASE", "CONCURRENTLY"))
2652 tgl 4351 LBC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_databases);
971 michael 4352 CBC 33 : else if (HeadMatches("REINDEX", "(*") &&
971 michael 4353 UBC 0 : !HeadMatches("REINDEX", "(*)"))
971 michael 4354 ECB : {
4355 : /*
4356 : * This fires if we're in an unfinished parenthesized option list.
4357 : * get_previous_words treats a completed parenthesized option list as
4358 : * one word, so the above test is correct.
4359 : */
971 michael 4360 UBC 0 : if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
794 michael 4361 UIC 0 : COMPLETE_WITH("CONCURRENTLY", "TABLESPACE", "VERBOSE");
4362 0 : else if (TailMatches("TABLESPACE"))
794 michael 4363 LBC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
971 michael 4364 ECB : }
8323 peter_e 4365 EUB :
4366 : /* SECURITY LABEL */
1661 tgl 4367 GIC 33 : else if (Matches("SECURITY"))
1661 tgl 4368 LBC 0 : COMPLETE_WITH("LABEL");
1661 tgl 4369 GBC 33 : else if (Matches("SECURITY", "LABEL"))
1661 tgl 4370 UIC 0 : COMPLETE_WITH("ON", "FOR");
1661 tgl 4371 GIC 33 : else if (Matches("SECURITY", "LABEL", "FOR", MatchAny))
1661 tgl 4372 LBC 0 : COMPLETE_WITH("ON");
1661 tgl 4373 GBC 66 : else if (Matches("SECURITY", "LABEL", "ON") ||
1661 tgl 4374 GIC 33 : Matches("SECURITY", "LABEL", "FOR", MatchAny, "ON"))
1661 tgl 4375 UIC 0 : COMPLETE_WITH("TABLE", "COLUMN", "AGGREGATE", "DATABASE", "DOMAIN",
1661 tgl 4376 ECB : "EVENT TRIGGER", "FOREIGN TABLE", "FUNCTION",
1661 tgl 4377 EUB : "LARGE OBJECT", "MATERIALIZED VIEW", "LANGUAGE",
4378 : "PUBLICATION", "PROCEDURE", "ROLE", "ROUTINE", "SCHEMA",
4379 : "SEQUENCE", "SUBSCRIPTION", "TABLESPACE", "TYPE", "VIEW");
1661 tgl 4380 CBC 33 : else if (Matches("SECURITY", "LABEL", "ON", MatchAny, MatchAny))
1661 tgl 4381 UBC 0 : COMPLETE_WITH("IS");
4382 :
4383 : /* SELECT */
8397 bruce 4384 ECB : /* naah . . . */
8535 bruce 4385 EUB :
4386 : /* SET, RESET, SHOW */
4387 : /* Complete with a variable name */
1661 tgl 4388 GIC 33 : else if (TailMatches("SET|RESET") && !TailMatches("UPDATE", MatchAny, "SET"))
424 4389 3 : COMPLETE_WITH_QUERY_VERBATIM_PLUS(Query_for_list_of_set_vars,
4390 : "CONSTRAINTS",
424 tgl 4391 ECB : "TRANSACTION",
424 tgl 4392 EUB : "SESSION",
424 tgl 4393 ECB : "ROLE",
424 tgl 4394 EUB : "TABLESPACE",
4395 : "ALL");
1661 tgl 4396 GIC 30 : else if (Matches("SHOW"))
424 tgl 4397 LBC 0 : COMPLETE_WITH_QUERY_VERBATIM_PLUS(Query_for_list_of_show_vars,
424 tgl 4398 EUB : "SESSION AUTHORIZATION",
4399 : "ALL");
432 tgl 4400 GIC 30 : else if (Matches("SHOW", "SESSION"))
432 tgl 4401 UIC 0 : COMPLETE_WITH("AUTHORIZATION");
4402 : /* Complete "SET TRANSACTION" */
1661 tgl 4403 GIC 30 : else if (Matches("SET", "TRANSACTION"))
1661 tgl 4404 UIC 0 : COMPLETE_WITH("SNAPSHOT", "ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
1661 tgl 4405 GIC 60 : else if (Matches("BEGIN|START", "TRANSACTION") ||
1661 tgl 4406 CBC 60 : Matches("BEGIN", "WORK") ||
1661 tgl 4407 GBC 60 : Matches("BEGIN") ||
1661 tgl 4408 CBC 30 : Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION"))
1661 tgl 4409 UBC 0 : COMPLETE_WITH("ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
1661 tgl 4410 CBC 60 : else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "NOT") ||
1661 tgl 4411 GBC 60 : Matches("BEGIN", "NOT") ||
1661 tgl 4412 CBC 30 : Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "NOT"))
1661 tgl 4413 UBC 0 : COMPLETE_WITH("DEFERRABLE");
1661 tgl 4414 CBC 60 : else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION") ||
1661 tgl 4415 GBC 60 : Matches("BEGIN", "ISOLATION") ||
1661 tgl 4416 GIC 30 : Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION"))
1661 tgl 4417 UIC 0 : COMPLETE_WITH("LEVEL");
1661 tgl 4418 CBC 60 : else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL") ||
1661 tgl 4419 GBC 60 : Matches("BEGIN", "ISOLATION", "LEVEL") ||
1661 tgl 4420 CBC 30 : Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL"))
1661 tgl 4421 UBC 0 : COMPLETE_WITH("READ", "REPEATABLE READ", "SERIALIZABLE");
1661 tgl 4422 CBC 60 : else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "READ") ||
1661 tgl 4423 GBC 60 : Matches("BEGIN", "ISOLATION", "LEVEL", "READ") ||
1661 tgl 4424 GIC 30 : Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "READ"))
1661 tgl 4425 LBC 0 : COMPLETE_WITH("UNCOMMITTED", "COMMITTED");
1661 tgl 4426 GBC 60 : else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "REPEATABLE") ||
1661 tgl 4427 CBC 60 : Matches("BEGIN", "ISOLATION", "LEVEL", "REPEATABLE") ||
1661 tgl 4428 GBC 30 : Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "REPEATABLE"))
1661 tgl 4429 LBC 0 : COMPLETE_WITH("READ");
1661 tgl 4430 GBC 60 : else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "READ") ||
1661 tgl 4431 CBC 60 : Matches("BEGIN", "READ") ||
1661 tgl 4432 GBC 30 : Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "READ"))
1661 tgl 4433 LBC 0 : COMPLETE_WITH("ONLY", "WRITE");
3859 peter_e 4434 EUB : /* SET CONSTRAINTS */
1661 tgl 4435 CBC 30 : else if (Matches("SET", "CONSTRAINTS"))
434 tgl 4436 UBC 0 : COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_constraints_with_schema,
434 tgl 4437 ECB : "ALL");
8323 peter_e 4438 EUB : /* Complete SET CONSTRAINTS <foo> with DEFERRED|IMMEDIATE */
1661 tgl 4439 GIC 30 : else if (Matches("SET", "CONSTRAINTS", MatchAny))
1661 tgl 4440 UIC 0 : COMPLETE_WITH("DEFERRED", "IMMEDIATE");
6447 tgl 4441 ECB : /* Complete SET ROLE */
1661 tgl 4442 CBC 30 : else if (Matches("SET", "ROLE"))
6447 tgl 4443 UBC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_roles);
8006 peter_e 4444 ECB : /* Complete SET SESSION with AUTHORIZATION or CHARACTERISTICS... */
1661 tgl 4445 CBC 30 : else if (Matches("SET", "SESSION"))
1661 tgl 4446 UBC 0 : COMPLETE_WITH("AUTHORIZATION", "CHARACTERISTICS AS TRANSACTION");
4447 : /* Complete SET SESSION AUTHORIZATION with username */
1661 tgl 4448 CBC 30 : else if (Matches("SET", "SESSION", "AUTHORIZATION"))
434 tgl 4449 LBC 0 : COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
434 tgl 4450 EUB : "DEFAULT");
4451 : /* Complete RESET SESSION with AUTHORIZATION */
1661 tgl 4452 CBC 30 : else if (Matches("RESET", "SESSION"))
1661 tgl 4453 LBC 0 : COMPLETE_WITH("AUTHORIZATION");
8397 bruce 4454 EUB : /* Complete SET <var> with "TO" */
1661 tgl 4455 GIC 30 : else if (Matches("SET", MatchAny))
1661 tgl 4456 CBC 2 : COMPLETE_WITH("TO");
1809 tgl 4457 ECB :
1809 tgl 4458 EUB : /*
4459 : * Complete ALTER DATABASE|FUNCTION|PROCEDURE|ROLE|ROUTINE|USER ... SET
1809 tgl 4460 ECB : * <name>
4461 : */
1661 tgl 4462 GBC 28 : else if (HeadMatches("ALTER", "DATABASE|FUNCTION|PROCEDURE|ROLE|ROUTINE|USER") &&
93 dean.a.rasheed 4463 LBC 0 : TailMatches("SET", MatchAny) &&
4464 0 : !TailMatches("SCHEMA"))
1661 tgl 4465 UBC 0 : COMPLETE_WITH("FROM CURRENT", "TO");
1377 tgl 4466 ECB :
4467 : /*
1377 tgl 4468 EUB : * Suggest possible variable values in SET variable TO|=, along with the
1377 tgl 4469 ECB : * preceding ALTER syntaxes.
4470 : */
1377 tgl 4471 GBC 28 : else if (TailMatches("SET", MatchAny, "TO|=") &&
1377 tgl 4472 CBC 4 : !TailMatches("UPDATE", MatchAny, "SET", MatchAny, "TO|="))
8397 bruce 4473 EUB : {
4474 : /* special cased code for individual GUCs */
1661 tgl 4475 GIC 4 : if (TailMatches("DateStyle", "TO|="))
1661 tgl 4476 UIC 0 : COMPLETE_WITH("ISO", "SQL", "Postgres", "German",
4477 : "YMD", "DMY", "MDY",
4478 : "US", "European", "NonEuropean",
4479 : "DEFAULT");
1661 tgl 4480 GBC 4 : else if (TailMatches("search_path", "TO|="))
434 tgl 4481 EUB : {
4482 : /* Here, we want to allow pg_catalog, so use narrower exclusion */
434 tgl 4483 UBC 0 : COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_schemas
4484 : " AND nspname NOT LIKE E'pg\\\\_toast%%'"
4485 : " AND nspname NOT LIKE E'pg\\\\_temp%%'",
4486 : "DEFAULT");
434 tgl 4487 ECB : }
385 tgl 4488 GBC 4 : else if (TailMatches("TimeZone", "TO|="))
385 tgl 4489 CBC 2 : COMPLETE_WITH_TIMEZONE_NAME();
8397 bruce 4490 EUB : else
8397 bruce 4491 ECB : {
2770 andres 4492 EUB : /* generic, type based, GUC support */
2770 andres 4493 CBC 2 : char *guctype = get_guctype(prev2_wd);
2770 andres 4494 ECB :
1377 tgl 4495 EUB : /*
4496 : * Note: if we don't recognize the GUC name, it's important to not
4497 : * offer any completions, as most likely we've misinterpreted the
4498 : * context and this isn't a GUC-setting command at all.
4499 : */
1377 tgl 4500 CBC 2 : if (guctype)
2770 andres 4501 EUB : {
1377 tgl 4502 GIC 2 : if (strcmp(guctype, "enum") == 0)
4503 : {
424 4504 2 : set_completion_reference_verbatim(prev2_wd);
434 4505 2 : COMPLETE_WITH_QUERY_PLUS(Query_for_values_of_enum_GUC,
4506 : "DEFAULT");
4507 : }
1377 tgl 4508 LBC 0 : else if (strcmp(guctype, "bool") == 0)
4509 0 : COMPLETE_WITH("on", "off", "true", "false", "yes", "no",
4510 : "1", "0", "DEFAULT");
4511 : else
1377 tgl 4512 UIC 0 : COMPLETE_WITH("DEFAULT");
4513 :
2770 andres 4514 GIC 2 : free(guctype);
4515 : }
8397 bruce 4516 ECB : }
8397 bruce 4517 EUB : }
4518 : /* Complete ALTER DATABASE|ROLE|USER ... SET ... TO ... USER SET */
121 akorotkov 4519 GNC 24 : else if (HeadMatches("ALTER", "DATABASE|ROLE|USER") &&
121 akorotkov 4520 UNC 0 : TailMatches("SET", MatchAny, "TO|=", MatchAny))
4521 0 : COMPLETE_WITH("USER SET");
4522 :
4523 : /* START TRANSACTION */
1661 tgl 4524 CBC 24 : else if (Matches("START"))
1661 tgl 4525 UBC 0 : COMPLETE_WITH("TRANSACTION");
4526 :
4185 magnus 4527 ECB : /* TABLE, but not TABLE embedded in other commands */
1661 tgl 4528 GBC 24 : else if (Matches("TABLE"))
434 tgl 4529 LBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_selectables);
4185 magnus 4530 ECB :
2848 rhaas 4531 : /* TABLESAMPLE */
1661 tgl 4532 CBC 24 : else if (TailMatches("TABLESAMPLE"))
2848 rhaas 4533 UBC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_tablesample_methods);
1661 tgl 4534 CBC 24 : else if (TailMatches("TABLESAMPLE", MatchAny))
1661 tgl 4535 LBC 0 : COMPLETE_WITH("(");
2848 rhaas 4536 ECB :
8323 peter_e 4537 EUB : /* TRUNCATE */
1661 tgl 4538 CBC 24 : else if (Matches("TRUNCATE"))
434 tgl 4539 LBC 0 : COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_truncatables,
434 tgl 4540 ECB : "TABLE", "ONLY");
773 fujii 4541 GBC 24 : else if (Matches("TRUNCATE", "TABLE"))
434 tgl 4542 LBC 0 : COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_truncatables,
434 tgl 4543 ECB : "ONLY");
773 fujii 4544 CBC 24 : else if (HeadMatches("TRUNCATE") && TailMatches("ONLY"))
434 tgl 4545 UBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_truncatables);
773 fujii 4546 CBC 48 : else if (Matches("TRUNCATE", MatchAny) ||
4547 48 : Matches("TRUNCATE", "TABLE|ONLY", MatchAny) ||
4548 24 : Matches("TRUNCATE", "TABLE", "ONLY", MatchAny))
773 fujii 4549 UBC 0 : COMPLETE_WITH("RESTART IDENTITY", "CONTINUE IDENTITY", "CASCADE", "RESTRICT");
773 fujii 4550 CBC 24 : else if (HeadMatches("TRUNCATE") && TailMatches("IDENTITY"))
773 fujii 4551 LBC 0 : COMPLETE_WITH("CASCADE", "RESTRICT");
8323 peter_e 4552 ECB :
8323 peter_e 4553 EUB : /* UNLISTEN */
1661 tgl 4554 CBC 24 : else if (Matches("UNLISTEN"))
434 tgl 4555 LBC 0 : COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_channels, "*");
8323 peter_e 4556 ECB :
2652 tgl 4557 EUB : /* UPDATE --- can be inside EXPLAIN, RULE, etc */
4558 : /* If prev. word is UPDATE suggest a list of tables */
1661 tgl 4559 CBC 24 : else if (TailMatches("UPDATE"))
434 tgl 4560 UBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables);
4561 : /* Complete UPDATE <table> with "SET" */
1661 tgl 4562 GIC 24 : else if (TailMatches("UPDATE", MatchAny))
1661 tgl 4563 LBC 0 : COMPLETE_WITH("SET");
2652 tgl 4564 EUB : /* Complete UPDATE <table> SET with list of attributes */
1661 tgl 4565 GIC 24 : else if (TailMatches("UPDATE", MatchAny, "SET"))
434 tgl 4566 LBC 0 : COMPLETE_WITH_ATTR(prev2_wd);
2652 tgl 4567 EUB : /* UPDATE <table> SET <attr> = */
1366 tmunro 4568 GIC 24 : else if (TailMatches("UPDATE", MatchAny, "SET", MatchAnyExcept("*=")))
1661 tgl 4569 LBC 0 : COMPLETE_WITH("=");
6535 neilc 4570 EUB :
4571 : /* USER MAPPING */
1661 tgl 4572 CBC 24 : else if (Matches("ALTER|CREATE|DROP", "USER", "MAPPING"))
1661 tgl 4573 UBC 0 : COMPLETE_WITH("FOR");
1661 tgl 4574 GIC 24 : else if (Matches("CREATE", "USER", "MAPPING", "FOR"))
434 tgl 4575 UIC 0 : COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
434 tgl 4576 ECB : "CURRENT_ROLE",
434 tgl 4577 EUB : "CURRENT_USER",
4578 : "PUBLIC",
434 tgl 4579 ECB : "USER");
1661 tgl 4580 CBC 24 : else if (Matches("ALTER|DROP", "USER", "MAPPING", "FOR"))
5224 peter_e 4581 UIC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
1661 tgl 4582 GIC 24 : else if (Matches("CREATE|ALTER|DROP", "USER", "MAPPING", "FOR", MatchAny))
1661 tgl 4583 UIC 0 : COMPLETE_WITH("SERVER");
1661 tgl 4584 GIC 24 : else if (Matches("CREATE|ALTER", "USER", "MAPPING", "FOR", MatchAny, "SERVER", MatchAny))
1661 tgl 4585 UIC 0 : COMPLETE_WITH("OPTIONS");
5224 peter_e 4586 ECB :
6535 neilc 4587 EUB : /*
1661 tgl 4588 : * VACUUM [ ( option [, ...] ) ] [ table_and_columns [, ...] ]
4589 : * VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ ANALYZE ] [ table_and_columns [, ...] ]
4590 : */
1661 tgl 4591 GIC 24 : else if (Matches("VACUUM"))
434 tgl 4592 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_vacuumables,
4593 : "FULL",
4594 : "FREEZE",
434 tgl 4595 ECB : "ANALYZE",
4596 : "VERBOSE");
1661 tgl 4597 GIC 24 : else if (Matches("VACUUM", "FULL"))
434 tgl 4598 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_vacuumables,
434 tgl 4599 ECB : "FREEZE",
434 tgl 4600 EUB : "ANALYZE",
4601 : "VERBOSE");
1661 tgl 4602 GIC 48 : else if (Matches("VACUUM", "FREEZE") ||
4603 24 : Matches("VACUUM", "FULL", "FREEZE"))
434 tgl 4604 LBC 0 : COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_vacuumables,
4605 : "VERBOSE",
4606 : "ANALYZE");
1661 tgl 4607 GBC 48 : else if (Matches("VACUUM", "VERBOSE") ||
1661 tgl 4608 GIC 48 : Matches("VACUUM", "FULL|FREEZE", "VERBOSE") ||
4609 24 : Matches("VACUUM", "FULL", "FREEZE", "VERBOSE"))
434 tgl 4610 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_vacuumables,
4611 : "ANALYZE");
1661 tgl 4612 CBC 24 : else if (HeadMatches("VACUUM", "(*") &&
1661 tgl 4613 LBC 0 : !HeadMatches("VACUUM", "(*)"))
4614 : {
4615 : /*
4616 : * This fires if we're in an unfinished parenthesized option list.
1661 tgl 4617 ECB : * get_previous_words treats a completed parenthesized option list as
4618 : * one word, so the above test is correct.
4619 : */
1661 tgl 4620 UIC 0 : if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
4621 0 : COMPLETE_WITH("FULL", "FREEZE", "ANALYZE", "VERBOSE",
4622 : "DISABLE_PAGE_SKIPPING", "SKIP_LOCKED",
4623 : "INDEX_CLEANUP", "PROCESS_MAIN", "PROCESS_TOAST",
4624 : "TRUNCATE", "PARALLEL", "SKIP_DATABASE_STATS",
4625 : "ONLY_DATABASE_STATS", "BUFFER_USAGE_LIMIT");
34 michael 4626 UNC 0 : else if (TailMatches("FULL|FREEZE|ANALYZE|VERBOSE|DISABLE_PAGE_SKIPPING|SKIP_LOCKED|PROCESS_MAIN|PROCESS_TOAST|TRUNCATE|SKIP_DATABASE_STATS|ONLY_DATABASE_STATS"))
1472 rhaas 4627 LBC 0 : COMPLETE_WITH("ON", "OFF");
660 pg 4628 UIC 0 : else if (TailMatches("INDEX_CLEANUP"))
660 pg 4629 LBC 0 : COMPLETE_WITH("AUTO", "ON", "OFF");
1661 tgl 4630 ECB : }
1661 tgl 4631 GIC 24 : else if (HeadMatches("VACUUM") && TailMatches("("))
4632 : /* "VACUUM (" should be caught above, so assume we want columns */
434 tgl 4633 UBC 0 : COMPLETE_WITH_ATTR(prev2_wd);
1661 tgl 4634 GBC 24 : else if (HeadMatches("VACUUM"))
434 tgl 4635 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_vacuumables);
4636 :
5300 tgl 4637 EUB : /* WITH [RECURSIVE] */
4638 :
3955 bruce 4639 ECB : /*
4640 : * Only match when WITH is the first word, as WITH may appear in many
4641 : * other contexts.
4642 : */
1661 tgl 4643 GIC 24 : else if (Matches("WITH"))
1661 tgl 4644 LBC 0 : COMPLETE_WITH("RECURSIVE");
5300 tgl 4645 EUB :
7558 bruce 4646 : /* WHERE */
4647 : /* Simple case of the word before the where being the table name */
1661 tgl 4648 GIC 24 : else if (TailMatches(MatchAny, "WHERE"))
434 tgl 4649 LBC 0 : COMPLETE_WITH_ATTR(prev2_wd);
7558 bruce 4650 EUB :
4651 : /* ... FROM ... */
4652 : /* TODO: also include SRF ? */
1661 tgl 4653 CBC 24 : else if (TailMatches("FROM") && !Matches("COPY|\\copy", MatchAny, "FROM"))
434 tgl 4654 GBC 14 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_selectables);
4655 :
4656 : /* ... JOIN ... */
1661 tgl 4657 CBC 10 : else if (TailMatches("JOIN"))
434 tgl 4658 UBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_selectables);
4420 heikki.linnakangas 4659 ECB :
8535 bruce 4660 EUB : /* Backslash commands */
4661 : /* TODO: \dc \dd \dl */
1661 tgl 4662 GIC 10 : else if (TailMatchesCS("\\?"))
1661 tgl 4663 LBC 0 : COMPLETE_WITH_CS("commands", "options", "variables");
1661 tgl 4664 GBC 10 : else if (TailMatchesCS("\\connect|\\c"))
4665 : {
2929 alvherre 4666 LBC 0 : if (!recognized_connection_string(text))
2929 alvherre 4667 UBC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_databases);
4668 : }
1661 tgl 4669 CBC 10 : else if (TailMatchesCS("\\connect|\\c", MatchAny))
2929 alvherre 4670 EUB : {
2929 alvherre 4671 LBC 0 : if (!recognized_connection_string(prev_wd))
4672 0 : COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2929 alvherre 4673 ECB : }
1661 tgl 4674 GBC 10 : else if (TailMatchesCS("\\da*"))
434 tgl 4675 LBC 0 : COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_aggregates);
1127 akorotkov 4676 GBC 20 : else if (TailMatchesCS("\\dAc*", MatchAny) ||
1127 akorotkov 4677 GIC 10 : TailMatchesCS("\\dAf*", MatchAny))
434 tgl 4678 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
1127 akorotkov 4679 CBC 20 : else if (TailMatchesCS("\\dAo*", MatchAny) ||
1127 akorotkov 4680 GBC 10 : TailMatchesCS("\\dAp*", MatchAny))
434 tgl 4681 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_operator_families);
1661 tgl 4682 GIC 10 : else if (TailMatchesCS("\\dA*"))
2497 alvherre 4683 UIC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
1661 tgl 4684 CBC 10 : else if (TailMatchesCS("\\db*"))
6806 bruce 4685 UBC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
367 tgl 4686 GIC 10 : else if (TailMatchesCS("\\dconfig*"))
367 tgl 4687 LBC 0 : COMPLETE_WITH_QUERY_VERBATIM(Query_for_list_of_show_vars);
1661 tgl 4688 GBC 10 : else if (TailMatchesCS("\\dD*"))
434 tgl 4689 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains);
1661 tgl 4690 CBC 10 : else if (TailMatchesCS("\\des*"))
5224 peter_e 4691 UBC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_servers);
1661 tgl 4692 GIC 10 : else if (TailMatchesCS("\\deu*"))
5224 peter_e 4693 LBC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
1661 tgl 4694 GBC 10 : else if (TailMatchesCS("\\dew*"))
5224 peter_e 4695 UIC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
1661 tgl 4696 GIC 10 : else if (TailMatchesCS("\\df*"))
434 tgl 4697 LBC 0 : COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_functions);
731 tgl 4698 GBC 10 : else if (HeadMatchesCS("\\df*"))
434 tgl 4699 LBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
2651 tgl 4700 EUB :
1661 tgl 4701 GIC 10 : else if (TailMatchesCS("\\dFd*"))
434 tgl 4702 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_ts_dictionaries);
1661 tgl 4703 GIC 10 : else if (TailMatchesCS("\\dFp*"))
434 tgl 4704 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_ts_parsers);
1661 tgl 4705 CBC 10 : else if (TailMatchesCS("\\dFt*"))
434 tgl 4706 UBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_ts_templates);
2651 tgl 4707 ECB : /* must be at end of \dF alternatives: */
1661 tgl 4708 GBC 10 : else if (TailMatchesCS("\\dF*"))
434 tgl 4709 LBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_ts_configurations);
5116 bruce 4710 EUB :
1661 tgl 4711 GIC 10 : else if (TailMatchesCS("\\di*"))
434 tgl 4712 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes);
1661 tgl 4713 GIC 10 : else if (TailMatchesCS("\\dL*"))
4462 rhaas 4714 UIC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_languages);
1661 tgl 4715 GIC 10 : else if (TailMatchesCS("\\dn*"))
7318 bruce 4716 LBC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
731 tgl 4717 EUB : /* no support for completing operators, but we can complete types: */
731 tgl 4718 GIC 10 : else if (HeadMatchesCS("\\do*", MatchAny))
434 tgl 4719 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
1661 tgl 4720 GIC 10 : else if (TailMatchesCS("\\dp") || TailMatchesCS("\\z"))
434 tgl 4721 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_grantables);
1463 alvherre 4722 CBC 10 : else if (TailMatchesCS("\\dPi*"))
434 tgl 4723 UBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_partitioned_indexes);
1463 alvherre 4724 GIC 10 : else if (TailMatchesCS("\\dPt*"))
434 tgl 4725 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_partitioned_tables);
1463 alvherre 4726 GIC 10 : else if (TailMatchesCS("\\dP*"))
434 tgl 4727 LBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_partitioned_relations);
186 michael 4728 GNC 10 : else if (TailMatchesCS("\\dRp*"))
186 michael 4729 UNC 0 : COMPLETE_WITH_VERSIONED_QUERY(Query_for_list_of_publications);
186 michael 4730 GNC 10 : else if (TailMatchesCS("\\dRs*"))
186 michael 4731 UNC 0 : COMPLETE_WITH_VERSIONED_QUERY(Query_for_list_of_subscriptions);
1661 tgl 4732 CBC 10 : else if (TailMatchesCS("\\ds*"))
434 tgl 4733 UBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences);
1661 tgl 4734 GIC 10 : else if (TailMatchesCS("\\dt*"))
434 tgl 4735 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
1661 tgl 4736 CBC 10 : else if (TailMatchesCS("\\dT*"))
434 tgl 4737 LBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
1661 tgl 4738 CBC 10 : else if (TailMatchesCS("\\du*") || TailMatchesCS("\\dg*"))
6447 tgl 4739 UBC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_roles);
1661 tgl 4740 GIC 10 : else if (TailMatchesCS("\\dv*"))
434 tgl 4741 LBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views);
1661 tgl 4742 GBC 10 : else if (TailMatchesCS("\\dx*"))
3524 magnus 4743 UIC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_extensions);
809 tomas.vondra 4744 GIC 10 : else if (TailMatchesCS("\\dX*"))
434 tgl 4745 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_statistics);
1661 tgl 4746 GIC 10 : else if (TailMatchesCS("\\dm*"))
434 tgl 4747 UIC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews);
1661 tgl 4748 GIC 10 : else if (TailMatchesCS("\\dE*"))
434 tgl 4749 UBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables);
1661 tgl 4750 GBC 10 : else if (TailMatchesCS("\\dy*"))
2833 fujii 4751 UIC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
4752 :
4753 : /* must be at end of \d alternatives: */
1661 tgl 4754 GIC 10 : else if (TailMatchesCS("\\d*"))
434 tgl 4755 UBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations);
5116 bruce 4756 EUB :
1661 tgl 4757 GBC 10 : else if (TailMatchesCS("\\ef"))
434 tgl 4758 UBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_routines);
1661 tgl 4759 GIC 10 : else if (TailMatchesCS("\\ev"))
434 tgl 4760 LBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views);
4761 :
1661 tgl 4762 GBC 10 : else if (TailMatchesCS("\\encoding"))
434 tgl 4763 LBC 0 : COMPLETE_WITH_QUERY_VERBATIM(Query_for_list_of_encodings);
1661 tgl 4764 GBC 10 : else if (TailMatchesCS("\\h|\\help"))
8397 bruce 4765 UIC 0 : COMPLETE_WITH_LIST(sql_commands);
1661 tgl 4766 GIC 10 : else if (TailMatchesCS("\\h|\\help", MatchAny))
4767 : {
1661 tgl 4768 UIC 0 : if (TailMatches("DROP"))
1213 4769 0 : matches = rl_completion_matches(text, drop_command_generator);
1661 4770 0 : else if (TailMatches("ALTER"))
1213 4771 0 : matches = rl_completion_matches(text, alter_command_generator);
2153 bruce 4772 ECB :
2153 bruce 4773 EUB : /*
4774 : * CREATE is recognized by tail match elsewhere, so doesn't need to be
4775 : * repeated here
4776 : */
2215 peter_e 4777 ECB : }
1661 tgl 4778 GBC 10 : else if (TailMatchesCS("\\h|\\help", MatchAny, MatchAny))
4779 : {
1661 tgl 4780 UIC 0 : if (TailMatches("CREATE|DROP", "ACCESS"))
4781 0 : COMPLETE_WITH("METHOD");
1661 tgl 4782 LBC 0 : else if (TailMatches("ALTER", "DEFAULT"))
4783 0 : COMPLETE_WITH("PRIVILEGES");
1661 tgl 4784 UIC 0 : else if (TailMatches("CREATE|ALTER|DROP", "EVENT"))
4785 0 : COMPLETE_WITH("TRIGGER");
1661 tgl 4786 LBC 0 : else if (TailMatches("CREATE|ALTER|DROP", "FOREIGN"))
1661 tgl 4787 UBC 0 : COMPLETE_WITH("DATA WRAPPER", "TABLE");
1661 tgl 4788 UIC 0 : else if (TailMatches("ALTER", "LARGE"))
4789 0 : COMPLETE_WITH("OBJECT");
4790 0 : else if (TailMatches("CREATE|ALTER|DROP", "MATERIALIZED"))
1661 tgl 4791 LBC 0 : COMPLETE_WITH("VIEW");
1661 tgl 4792 UBC 0 : else if (TailMatches("CREATE|ALTER|DROP", "TEXT"))
1661 tgl 4793 LBC 0 : COMPLETE_WITH("SEARCH");
1661 tgl 4794 UIC 0 : else if (TailMatches("CREATE|ALTER|DROP", "USER"))
1661 tgl 4795 UBC 0 : COMPLETE_WITH("MAPPING FOR");
2215 peter_e 4796 EUB : }
1661 tgl 4797 GIC 10 : else if (TailMatchesCS("\\h|\\help", MatchAny, MatchAny, MatchAny))
1661 tgl 4798 ECB : {
1661 tgl 4799 UIC 0 : if (TailMatches("CREATE|ALTER|DROP", "FOREIGN", "DATA"))
1661 tgl 4800 UBC 0 : COMPLETE_WITH("WRAPPER");
4801 0 : else if (TailMatches("CREATE|ALTER|DROP", "TEXT", "SEARCH"))
1661 tgl 4802 UIC 0 : COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
1661 tgl 4803 LBC 0 : else if (TailMatches("CREATE|ALTER|DROP", "USER", "MAPPING"))
1661 tgl 4804 UBC 0 : COMPLETE_WITH("FOR");
2215 peter_e 4805 ECB : }
1661 tgl 4806 CBC 10 : else if (TailMatchesCS("\\l*") && !TailMatchesCS("\\lo*"))
2425 tgl 4807 UBC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_databases);
1661 tgl 4808 CBC 10 : else if (TailMatchesCS("\\password"))
6321 peter_e 4809 LBC 0 : COMPLETE_WITH_QUERY(Query_for_list_of_roles);
1661 tgl 4810 GBC 10 : else if (TailMatchesCS("\\pset"))
1595 tgl 4811 LBC 0 : COMPLETE_WITH_CS("border", "columns", "csv_fieldsep", "expanded",
1661 tgl 4812 EUB : "fieldsep", "fieldsep_zero", "footer", "format",
1661 tgl 4813 ECB : "linestyle", "null", "numericlocale",
1661 tgl 4814 EUB : "pager", "pager_min_lines",
1661 tgl 4815 ECB : "recordsep", "recordsep_zero",
1661 tgl 4816 EUB : "tableattr", "title", "tuples_only",
1661 tgl 4817 ECB : "unicode_border_linestyle",
1661 tgl 4818 EUB : "unicode_column_linestyle",
4819 : "unicode_header_linestyle",
4820 : "xheader_width");
1661 tgl 4821 GBC 10 : else if (TailMatchesCS("\\pset", MatchAny))
1661 tgl 4822 ECB : {
1661 tgl 4823 UBC 0 : if (TailMatchesCS("format"))
1595 tgl 4824 LBC 0 : COMPLETE_WITH_CS("aligned", "asciidoc", "csv", "html", "latex",
1615 michael 4825 EUB : "latex-longtable", "troff-ms", "unaligned",
1615 michael 4826 ECB : "wrapped");
258 andrew 4827 UNC 0 : else if (TailMatchesCS("xheader_width"))
4828 0 : COMPLETE_WITH_CS("full", "column", "page");
1661 tgl 4829 UBC 0 : else if (TailMatchesCS("linestyle"))
1661 tgl 4830 LBC 0 : COMPLETE_WITH_CS("ascii", "old-ascii", "unicode");
1661 tgl 4831 UBC 0 : else if (TailMatchesCS("pager"))
1661 tgl 4832 UIC 0 : COMPLETE_WITH_CS("on", "off", "always");
1661 tgl 4833 LBC 0 : else if (TailMatchesCS("unicode_border_linestyle|"
1661 tgl 4834 EUB : "unicode_column_linestyle|"
1661 tgl 4835 ECB : "unicode_header_linestyle"))
1661 tgl 4836 UBC 0 : COMPLETE_WITH_CS("single", "double");
4407 rhaas 4837 ECB : }
1661 tgl 4838 GBC 10 : else if (TailMatchesCS("\\unset"))
3162 fujii 4839 UIC 0 : matches = complete_from_variables(text, "", "", true);
1661 tgl 4840 CBC 10 : else if (TailMatchesCS("\\set"))
3162 fujii 4841 GBC 1 : matches = complete_from_variables(text, "", "", false);
1661 tgl 4842 GIC 9 : else if (TailMatchesCS("\\set", MatchAny))
1661 tgl 4843 ECB : {
370 peter 4844 GBC 1 : if (TailMatchesCS("AUTOCOMMIT|ON_ERROR_STOP|QUIET|SHOW_ALL_RESULTS|"
1661 tgl 4845 ECB : "SINGLELINE|SINGLESTEP"))
1661 tgl 4846 UBC 0 : COMPLETE_WITH_CS("on", "off");
1661 tgl 4847 CBC 1 : else if (TailMatchesCS("COMP_KEYWORD_CASE"))
1661 tgl 4848 UBC 0 : COMPLETE_WITH_CS("lower", "upper",
4849 : "preserve-lower", "preserve-upper");
1661 tgl 4850 CBC 1 : else if (TailMatchesCS("ECHO"))
1661 tgl 4851 UBC 0 : COMPLETE_WITH_CS("errors", "queries", "all", "none");
1661 tgl 4852 CBC 1 : else if (TailMatchesCS("ECHO_HIDDEN"))
1661 tgl 4853 UBC 0 : COMPLETE_WITH_CS("noexec", "off", "on");
1661 tgl 4854 CBC 1 : else if (TailMatchesCS("HISTCONTROL"))
1661 tgl 4855 UBC 0 : COMPLETE_WITH_CS("ignorespace", "ignoredups",
1661 tgl 4856 ECB : "ignoreboth", "none");
1661 tgl 4857 GBC 1 : else if (TailMatchesCS("ON_ERROR_ROLLBACK"))
1661 tgl 4858 LBC 0 : COMPLETE_WITH_CS("on", "off", "interactive");
1661 tgl 4859 GBC 1 : else if (TailMatchesCS("SHOW_CONTEXT"))
1661 tgl 4860 LBC 0 : COMPLETE_WITH_CS("never", "errors", "always");
1661 tgl 4861 GBC 1 : else if (TailMatchesCS("VERBOSITY"))
1466 tgl 4862 CBC 1 : COMPLETE_WITH_CS("default", "verbose", "terse", "sqlstate");
4564 tgl 4863 EUB : }
1661 tgl 4864 CBC 8 : else if (TailMatchesCS("\\sf*"))
434 tgl 4865 UBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_routines);
1661 tgl 4866 CBC 8 : else if (TailMatchesCS("\\sv*"))
434 tgl 4867 UBC 0 : COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views);
1104 bruce 4868 CBC 8 : else if (TailMatchesCS("\\cd|\\e|\\edit|\\g|\\gx|\\i|\\include|"
1661 tgl 4869 EUB : "\\ir|\\include_relative|\\o|\\out|"
1661 tgl 4870 ECB : "\\s|\\w|\\write|\\lo_import"))
4058 alvherre 4871 EUB : {
4058 alvherre 4872 CBC 2 : completion_charp = "\\";
1172 tgl 4873 GBC 2 : completion_force_quote = false;
1213 tgl 4874 CBC 2 : matches = rl_completion_matches(text, complete_from_files);
4058 alvherre 4875 EUB : }
8397 bruce 4876 ECB :
6355 bruce 4877 EUB : /*
6355 bruce 4878 ECB : * Finally, we look through the list of "things", such as TABLE, INDEX and
6355 bruce 4879 EUB : * check if that was the previous word. If so, execute the query to get a
6355 bruce 4880 ECB : * list of them.
6355 bruce 4881 EUB : */
8397 bruce 4882 ECB : else
8397 bruce 4883 EUB : {
4884 : const pgsql_thing_t *wac;
4885 :
434 tgl 4886 CBC 248 : for (wac = words_after_create; wac->name != NULL; wac++)
7101 tgl 4887 EUB : {
434 tgl 4888 GIC 246 : if (pg_strcasecmp(prev_wd, wac->name) == 0)
8397 bruce 4889 ECB : {
434 tgl 4890 GBC 4 : if (wac->query)
434 tgl 4891 LBC 0 : COMPLETE_WITH_QUERY_LIST(wac->query,
434 tgl 4892 EUB : wac->keywords);
434 tgl 4893 GIC 4 : else if (wac->vquery)
434 tgl 4894 CBC 1 : COMPLETE_WITH_VERSIONED_QUERY_LIST(wac->vquery,
434 tgl 4895 EUB : wac->keywords);
434 tgl 4896 CBC 3 : else if (wac->squery)
434 tgl 4897 GBC 3 : COMPLETE_WITH_VERSIONED_SCHEMA_QUERY_LIST(wac->squery,
434 tgl 4898 ECB : wac->keywords);
8397 bruce 4899 GIC 4 : break;
8397 bruce 4900 EUB : }
7101 tgl 4901 : }
8397 bruce 4902 : }
4903 :
4904 : /*
4905 : * If we still don't have anything to match we have to fabricate some sort
4906 : * of default list. If we were to just return NULL, readline automatically
4907 : * attempts filename completion, and that's usually no good.
4908 : */
6355 bruce 4909 GIC 66 : if (matches == NULL)
6355 bruce 4910 ECB : {
1377 tgl 4911 GIC 2 : COMPLETE_WITH_CONST(true, "");
448 tgl 4912 EUB : /* Also, prevent Readline from appending stuff to the non-match */
6355 bruce 4913 GBC 2 : rl_completion_append_character = '\0';
448 tgl 4914 EUB : #ifdef HAVE_RL_COMPLETION_SUPPRESS_QUOTE
448 tgl 4915 GBC 2 : rl_completion_suppress_quote = 1;
8479 tgl 4916 EUB : #endif
6355 bruce 4917 : }
4918 :
4919 : /* free storage */
2667 tgl 4920 GBC 66 : free(previous_words);
4921 66 : free(words_buffer);
1192 4922 66 : free(text_copy);
297 peter 4923 GNC 66 : free(completion_ref_object);
434 tgl 4924 GBC 66 : completion_ref_object = NULL;
297 peter 4925 GNC 66 : free(completion_ref_schema);
434 tgl 4926 GIC 66 : completion_ref_schema = NULL;
6355 bruce 4927 ECB :
4928 : /* Return our Grand List O' Matches */
6355 bruce 4929 GBC 66 : return matches;
6355 bruce 4930 EUB : }
8535 4931 :
4932 :
4564 tgl 4933 : /*
4934 : * GENERATOR FUNCTIONS
4935 : *
4564 tgl 4936 ECB : * These functions do all the actual work of completing the input. They get
4564 tgl 4937 EUB : * passed the text so far and the count how many times they have been called
4564 tgl 4938 ECB : * so far with the same text.
4564 tgl 4939 EUB : * If you read the above carefully, you'll see that these don't get called
4564 tgl 4940 ECB : * directly but through the readline interface.
4564 tgl 4941 EUB : * The return value is expected to be the full completion of the text, going
4942 : * through a list each time, or NULL if there are no more matches. The string
4943 : * will be free()'d by readline, so you must run it through strdup() or
4944 : * something of that sort.
4945 : */
4946 :
4947 : /*
4948 : * Common routine for create_command_generator and drop_command_generator.
4949 : * Entries that have 'excluded' flags are not returned.
4950 : */
6355 bruce 4951 ECB : static char *
4427 itagaki.takahiro 4952 GIC 4 : create_or_drop_command_generator(const char *text, int state, bits32 excluded)
6355 bruce 4953 EUB : {
5624 4954 : static int list_index,
4955 : string_length;
4956 : const char *name;
6355 4957 :
4958 : /* If this is the first time for this completion, init some values */
6355 bruce 4959 GBC 4 : if (state == 0)
6355 bruce 4960 EUB : {
6355 bruce 4961 GBC 2 : list_index = 0;
4962 2 : string_length = strlen(text);
6355 bruce 4963 EUB : }
4964 :
4965 : /* find something that matches */
6355 bruce 4966 GBC 102 : while ((name = words_after_create[list_index++].name))
4967 : {
4564 tgl 4968 CBC 100 : if ((pg_strncasecmp(name, text, string_length) == 0) &&
4427 itagaki.takahiro 4969 GBC 2 : !(words_after_create[list_index - 1].flags & excluded))
3988 peter_e 4970 CBC 2 : return pg_strdup_keyword_case(name, text);
5686 bruce 4971 ECB : }
6355 4972 : /* if nothing matches, return NULL */
6355 bruce 4973 GIC 2 : return NULL;
6355 bruce 4974 ECB : }
4975 :
4427 itagaki.takahiro 4976 EUB : /*
4427 itagaki.takahiro 4977 ECB : * This one gives you one from a list of things you can put after CREATE
4427 itagaki.takahiro 4978 EUB : * as defined above.
4979 : */
4427 itagaki.takahiro 4980 ECB : static char *
4427 itagaki.takahiro 4981 GBC 2 : create_command_generator(const char *text, int state)
4427 itagaki.takahiro 4982 ECB : {
4427 itagaki.takahiro 4983 GBC 2 : return create_or_drop_command_generator(text, state, THING_NO_CREATE);
4427 itagaki.takahiro 4984 ECB : }
4427 itagaki.takahiro 4985 EUB :
4986 : /*
6216 alvherre 4987 ECB : * This function gives you a list of things you can put after a DROP command.
6216 alvherre 4988 EUB : */
6216 alvherre 4989 ECB : static char *
6216 alvherre 4990 GBC 2 : drop_command_generator(const char *text, int state)
6216 alvherre 4991 ECB : {
4427 itagaki.takahiro 4992 CBC 2 : return create_or_drop_command_generator(text, state, THING_NO_DROP);
4993 : }
8535 bruce 4994 ECB :
2215 peter_e 4995 EUB : /*
2215 peter_e 4996 ECB : * This function gives you a list of things you can put after an ALTER command.
2215 peter_e 4997 EUB : */
2215 peter_e 4998 ECB : static char *
2215 peter_e 4999 UIC 0 : alter_command_generator(const char *text, int state)
5000 : {
5001 0 : return create_or_drop_command_generator(text, state, THING_NO_ALTER);
2215 peter_e 5002 ECB : }
5003 :
1861 tgl 5004 : /*
5005 : * These functions generate lists using server queries.
5006 : * They are all wrappers for _complete_from_query.
5007 : */
5008 :
5009 : static char *
6355 bruce 5010 GIC 185 : complete_from_query(const char *text, int state)
5011 : {
5012 : /* query is assumed to work for any server version */
434 tgl 5013 185 : return _complete_from_query(completion_charp, NULL, completion_charpp,
5014 : completion_verbatim, text, state);
5015 : }
1861 tgl 5016 ECB :
5017 : static char *
1861 tgl 5018 CBC 2 : complete_from_versioned_query(const char *text, int state)
5019 : {
5020 2 : const VersionedQuery *vquery = completion_vquery;
1861 tgl 5021 EUB :
5022 : /* Find appropriate array element */
1861 tgl 5023 CBC 2 : while (pset.sversion < vquery->min_server_version)
1861 tgl 5024 LBC 0 : vquery++;
5025 : /* Fail completion if server is too old */
1861 tgl 5026 CBC 2 : if (vquery->query == NULL)
1861 tgl 5027 LBC 0 : return NULL;
5028 :
434 tgl 5029 CBC 2 : return _complete_from_query(vquery->query, NULL, completion_charpp,
5030 : completion_verbatim, text, state);
5031 : }
5032 :
5033 : static char *
6355 bruce 5034 GIC 86 : complete_from_schema_query(const char *text, int state)
5035 : {
5036 : /* query is assumed to work for any server version */
434 tgl 5037 86 : return _complete_from_query(NULL, completion_squery, completion_charpp,
5038 : completion_verbatim, text, state);
1861 tgl 5039 ECB : }
5040 :
5041 : static char *
1861 tgl 5042 GIC 8 : complete_from_versioned_schema_query(const char *text, int state)
1861 tgl 5043 ECB : {
1861 tgl 5044 GIC 8 : const SchemaQuery *squery = completion_squery;
1861 tgl 5045 ECB :
5046 : /* Find appropriate array element */
1861 tgl 5047 GIC 8 : while (pset.sversion < squery->min_server_version)
1861 tgl 5048 UIC 0 : squery++;
5049 : /* Fail completion if server is too old */
1861 tgl 5050 CBC 8 : if (squery->catname == NULL)
1861 tgl 5051 LBC 0 : return NULL;
1861 tgl 5052 ECB :
434 tgl 5053 CBC 8 : return _complete_from_query(NULL, squery, completion_charpp,
434 tgl 5054 ECB : completion_verbatim, text, state);
6355 bruce 5055 : }
7318 5056 :
5057 :
5058 : /*
1861 tgl 5059 : * This creates a list of matching things, according to a query described by
5060 : * the initial arguments. The caller has already done any work needed to
5061 : * select the appropriate query for the server's version.
5062 : *
5063 : * The query can be one of two kinds:
5064 : *
5065 : * 1. A simple query, which must contain a restriction clause of the form
5066 : * output LIKE '%s'
5067 : * where "output" is the same string that the query returns. The %s
5068 : * will be replaced by a LIKE pattern to match the already-typed text.
5069 : * There can be a second '%s', which will be replaced by a suitably-escaped
5070 : * version of the string provided in completion_ref_object. If there is a
5071 : * third '%s', it will be replaced by a suitably-escaped version of the string
5072 : * provided in completion_ref_schema. Those strings should be set up
5073 : * by calling set_completion_reference or set_completion_reference_verbatim.
5074 : * Simple queries should return a single column of matches. If "verbatim"
5075 : * is true, the matches are returned as-is; otherwise, they are taken to
5076 : * be SQL identifiers and quoted if necessary.
5077 : *
5078 : * 2. A schema query used for completion of both schema and relation names.
5079 : * This is represented by a SchemaQuery object; see that typedef for details.
5080 : *
5081 : * See top of file for examples of both kinds of query.
5082 : *
5083 : * In addition to the query itself, we accept a null-terminated array of
5084 : * literal keywords, which will be returned if they match the input-so-far
5085 : * (case insensitively). (These are in addition to keywords specified
5086 : * within the schema_query, if any.)
5087 : *
5088 : * If "verbatim" is true, then we use the given text as-is to match the
434 5089 : * query results; otherwise we parse it as a possibly-qualified identifier,
5090 : * and reconstruct suitable quoting afterward.
5091 : *
5092 : * "text" and "state" are supplied by Readline. "text" is the word we are
5093 : * trying to complete. "state" is zero on first call, nonzero later.
5094 : *
5095 : * readline will call this repeatedly with the same text and varying
5096 : * state. On each call, we are supposed to return a malloc'd string
5097 : * that is a candidate completion. Return NULL when done.
4564 5098 : */
6355 bruce 5099 : static char *
1861 tgl 5100 CBC 281 : _complete_from_query(const char *simple_query,
5101 : const SchemaQuery *schema_query,
5102 : const char *const *keywords,
434 tgl 5103 ECB : bool verbatim,
5104 : const char *text, int state)
5105 : {
5106 : static int list_index,
5107 : num_schema_only,
5108 : num_query_other,
5109 : num_keywords;
5110 : static PGresult *result = NULL;
5111 : static bool non_empty_object;
5112 : static bool schemaquoted;
5113 : static bool objectquoted;
5114 :
5115 : /*
5116 : * If this is the first time for this completion, we fetch a list of our
5117 : * "things" from the backend.
5118 : */
6355 bruce 5119 GIC 281 : if (state == 0)
6355 bruce 5120 ECB : {
5121 : PQExpBufferData query_buffer;
434 tgl 5122 : char *schemaname;
5123 : char *objectname;
5124 : char *e_object_like;
5125 : char *e_schemaname;
5126 : char *e_ref_object;
5127 : char *e_ref_schema;
5128 :
434 tgl 5129 EUB : /* Reset static state, ensuring no memory leaks */
6355 bruce 5130 GIC 44 : list_index = 0;
434 tgl 5131 GBC 44 : num_schema_only = 0;
432 tgl 5132 GIC 44 : num_query_other = 0;
5133 44 : num_keywords = 0;
434 5134 44 : PQclear(result);
5135 44 : result = NULL;
5136 :
5137 : /* Parse text, splitting into schema and object name if needed */
5138 44 : if (verbatim)
5139 : {
434 tgl 5140 CBC 8 : objectname = pg_strdup(text);
434 tgl 5141 GIC 8 : schemaname = NULL;
5142 : }
434 tgl 5143 ECB : else
5144 : {
434 tgl 5145 GIC 36 : parse_identifier(text,
5146 : &schemaname, &objectname,
5147 : &schemaquoted, &objectquoted);
2592 rhaas 5148 ECB : }
5149 :
434 tgl 5150 : /* Remember whether the user has typed anything in the object part */
434 tgl 5151 GIC 44 : non_empty_object = (*objectname != '\0');
5152 :
434 tgl 5153 ECB : /*
434 tgl 5154 EUB : * Convert objectname to a LIKE prefix pattern (e.g. 'foo%'), and set
5155 : * up suitably-escaped copies of all the strings we need.
434 tgl 5156 ECB : */
434 tgl 5157 GBC 44 : e_object_like = make_like_pattern(objectname);
5158 :
434 tgl 5159 CBC 44 : if (schemaname)
434 tgl 5160 GIC 3 : e_schemaname = escape_string(schemaname);
5161 : else
5162 41 : e_schemaname = NULL;
5163 :
434 tgl 5164 CBC 44 : if (completion_ref_object)
434 tgl 5165 GIC 21 : e_ref_object = escape_string(completion_ref_object);
5166 : else
434 tgl 5167 CBC 23 : e_ref_object = NULL;
5168 :
434 tgl 5169 GIC 44 : if (completion_ref_schema)
5170 1 : e_ref_schema = escape_string(completion_ref_schema);
5171 : else
434 tgl 5172 CBC 43 : e_ref_schema = NULL;
5173 :
6355 bruce 5174 44 : initPQExpBuffer(&query_buffer);
5175 :
1861 tgl 5176 GIC 44 : if (schema_query)
6355 bruce 5177 ECB : {
434 tgl 5178 GBC 36 : Assert(simple_query == NULL);
5179 :
6355 bruce 5180 ECB : /*
434 tgl 5181 EUB : * We issue different queries depending on whether the input is
5182 : * already qualified or not. schema_query gives us the pieces to
434 tgl 5183 ECB : * assemble.
5184 : */
434 tgl 5185 GIC 36 : if (schemaname == NULL || schema_query->namespace == NULL)
5186 : {
5187 : /* Get unqualified names matching the input-so-far */
5188 33 : appendPQExpBufferStr(&query_buffer, "SELECT ");
5189 33 : if (schema_query->use_distinct)
434 tgl 5190 UIC 0 : appendPQExpBufferStr(&query_buffer, "DISTINCT ");
434 tgl 5191 GIC 33 : appendPQExpBuffer(&query_buffer,
5192 : "%s, NULL::pg_catalog.text FROM %s",
5193 33 : schema_query->result,
5194 33 : schema_query->catname);
5195 33 : if (schema_query->refnamespace && completion_ref_schema)
5196 1 : appendPQExpBufferStr(&query_buffer,
5197 : ", pg_catalog.pg_namespace nr");
5198 33 : appendPQExpBufferStr(&query_buffer, " WHERE ");
5199 33 : if (schema_query->selcondition)
5200 33 : appendPQExpBuffer(&query_buffer, "%s AND ",
5201 33 : schema_query->selcondition);
5202 33 : appendPQExpBuffer(&query_buffer, "(%s) LIKE '%s'",
5203 33 : schema_query->result,
5204 : e_object_like);
5205 33 : if (schema_query->viscondition)
5206 15 : appendPQExpBuffer(&query_buffer, " AND %s",
5207 15 : schema_query->viscondition);
5208 33 : if (schema_query->refname)
5209 : {
5210 18 : Assert(completion_ref_object);
5211 18 : appendPQExpBuffer(&query_buffer, " AND %s = '%s'",
5212 18 : schema_query->refname, e_ref_object);
5213 18 : if (schema_query->refnamespace && completion_ref_schema)
5214 1 : appendPQExpBuffer(&query_buffer,
5215 : " AND %s = nr.oid AND nr.nspname = '%s'",
5216 1 : schema_query->refnamespace,
5217 : e_ref_schema);
5218 17 : else if (schema_query->refviscondition)
5219 17 : appendPQExpBuffer(&query_buffer,
5220 : " AND %s",
5221 17 : schema_query->refviscondition);
5222 : }
5223 :
5224 : /*
5225 : * When fetching relation names, suppress system catalogs
5226 : * unless the input-so-far begins with "pg_". This is a
5227 : * compromise between not offering system catalogs for
5228 : * completion at all, and having them swamp the result when
5229 : * the input is just "p".
434 tgl 5230 ECB : */
434 tgl 5231 GIC 33 : if (strcmp(schema_query->catname,
5232 14 : "pg_catalog.pg_class c") == 0 &&
5233 14 : strncmp(objectname, "pg_", 3) != 0)
5234 : {
5235 14 : appendPQExpBufferStr(&query_buffer,
5236 : " AND c.relnamespace <> (SELECT oid FROM"
5237 : " pg_catalog.pg_namespace WHERE nspname = 'pg_catalog')");
5238 : }
5239 :
5240 : /*
5241 : * If the target object type can be schema-qualified, add in
5242 : * schema names matching the input-so-far.
5243 : */
5244 33 : if (schema_query->namespace)
5245 : {
5246 15 : appendPQExpBuffer(&query_buffer, "\nUNION ALL\n"
5247 : "SELECT NULL::pg_catalog.text, n.nspname "
5248 : "FROM pg_catalog.pg_namespace n "
434 tgl 5249 ECB : "WHERE n.nspname LIKE '%s'",
5250 : e_object_like);
5251 :
5252 : /*
5253 : * Likewise, suppress system schemas unless the
5254 : * input-so-far begins with "pg_".
5255 : */
434 tgl 5256 GIC 15 : if (strncmp(objectname, "pg_", 3) != 0)
5257 15 : appendPQExpBufferStr(&query_buffer,
5258 : " AND n.nspname NOT LIKE E'pg\\\\_%'");
5259 :
434 tgl 5260 ECB : /*
5261 : * Since we're matching these schema names to the object
5262 : * name, handle their quoting using the object name's
5263 : * quoting state.
5264 : */
434 tgl 5265 CBC 15 : schemaquoted = objectquoted;
5266 : }
5267 : }
434 tgl 5268 ECB : else
5269 : {
5270 : /* Input is qualified, so produce only qualified names */
434 tgl 5271 CBC 3 : appendPQExpBufferStr(&query_buffer, "SELECT ");
434 tgl 5272 GIC 3 : if (schema_query->use_distinct)
5273 1 : appendPQExpBufferStr(&query_buffer, "DISTINCT ");
5274 3 : appendPQExpBuffer(&query_buffer, "%s, n.nspname "
434 tgl 5275 ECB : "FROM %s, pg_catalog.pg_namespace n",
434 tgl 5276 GIC 3 : schema_query->result,
5277 3 : schema_query->catname);
5278 3 : if (schema_query->refnamespace && completion_ref_schema)
434 tgl 5279 UIC 0 : appendPQExpBufferStr(&query_buffer,
5280 : ", pg_catalog.pg_namespace nr");
434 tgl 5281 CBC 3 : appendPQExpBuffer(&query_buffer, " WHERE %s = n.oid AND ",
434 tgl 5282 GIC 3 : schema_query->namespace);
5283 3 : if (schema_query->selcondition)
5284 3 : appendPQExpBuffer(&query_buffer, "%s AND ",
5285 3 : schema_query->selcondition);
5286 3 : appendPQExpBuffer(&query_buffer, "(%s) LIKE '%s' AND ",
434 tgl 5287 CBC 3 : schema_query->result,
5288 : e_object_like);
5289 3 : appendPQExpBuffer(&query_buffer, "n.nspname = '%s'",
434 tgl 5290 ECB : e_schemaname);
434 tgl 5291 GIC 3 : if (schema_query->refname)
434 tgl 5292 ECB : {
434 tgl 5293 GIC 1 : Assert(completion_ref_object);
434 tgl 5294 CBC 1 : appendPQExpBuffer(&query_buffer, " AND %s = '%s'",
5295 1 : schema_query->refname, e_ref_object);
434 tgl 5296 GIC 1 : if (schema_query->refnamespace && completion_ref_schema)
434 tgl 5297 LBC 0 : appendPQExpBuffer(&query_buffer,
5298 : " AND %s = nr.oid AND nr.nspname = '%s'",
5299 0 : schema_query->refnamespace,
434 tgl 5300 ECB : e_ref_schema);
434 tgl 5301 GIC 1 : else if (schema_query->refviscondition)
434 tgl 5302 LBC 0 : appendPQExpBuffer(&query_buffer,
5303 : " AND %s",
5304 0 : schema_query->refviscondition);
5305 : }
434 tgl 5306 ECB : }
5307 : }
6355 bruce 5308 : else
5309 : {
1861 tgl 5310 GIC 8 : Assert(simple_query);
5311 : /* simple_query is an sprintf-style format string */
5312 8 : appendPQExpBuffer(&query_buffer, simple_query,
5313 : e_object_like,
5314 : e_ref_object, e_ref_schema);
6355 bruce 5315 ECB : }
5316 :
5317 : /* Limit the number of records in the result */
6355 bruce 5318 CBC 44 : appendPQExpBuffer(&query_buffer, "\nLIMIT %d",
6355 bruce 5319 ECB : completion_max_records);
6355 bruce 5320 EUB :
434 tgl 5321 ECB : /* Finally, we can issue the query */
6355 bruce 5322 GIC 44 : result = exec_query(query_buffer.data);
6355 bruce 5323 ECB :
434 tgl 5324 : /* Clean up */
6355 bruce 5325 CBC 44 : termPQExpBuffer(&query_buffer);
261 tgl 5326 GNC 44 : free(schemaname);
5327 44 : free(objectname);
434 tgl 5328 CBC 44 : free(e_object_like);
297 peter 5329 GNC 44 : free(e_schemaname);
5330 44 : free(e_ref_object);
5331 44 : free(e_ref_schema);
6355 bruce 5332 ECB : }
5333 :
5334 : /* Return the next result, if any, but not if the query failed */
6355 bruce 5335 CBC 281 : if (result && PQresultStatus(result) == PGRES_TUPLES_OK)
6355 bruce 5336 ECB : {
434 tgl 5337 : int nskip;
6355 bruce 5338 :
434 tgl 5339 CBC 281 : while (list_index < PQntuples(result))
5340 : {
5341 212 : const char *item = NULL;
434 tgl 5342 GIC 212 : const char *nsp = NULL;
434 tgl 5343 ECB :
434 tgl 5344 CBC 212 : if (!PQgetisnull(result, list_index, 0))
434 tgl 5345 GIC 211 : item = PQgetvalue(result, list_index, 0);
434 tgl 5346 CBC 245 : if (PQnfields(result) > 1 &&
434 tgl 5347 GIC 33 : !PQgetisnull(result, list_index, 1))
5348 4 : nsp = PQgetvalue(result, list_index, 1);
5349 212 : list_index++;
5350 :
5351 : /* In verbatim mode, we return all the items as-is */
5352 212 : if (verbatim)
5353 : {
432 5354 181 : num_query_other++;
6355 bruce 5355 181 : return pg_strdup(item);
432 tgl 5356 ECB : }
434 5357 :
5358 : /*
5359 : * In normal mode, a name requiring quoting will be returned only
5360 : * if the input was empty or quoted. Otherwise the user might see
5361 : * completion inserting a quote she didn't type, which is
5362 : * surprising. This restriction also dodges some odd behaviors of
5363 : * some versions of readline/libedit.
5364 : */
434 tgl 5365 GIC 31 : if (non_empty_object)
5366 : {
5367 26 : if (item && !objectquoted && identifier_needs_quotes(item))
434 tgl 5368 UIC 0 : continue;
434 tgl 5369 CBC 26 : if (nsp && !schemaquoted && identifier_needs_quotes(nsp))
434 tgl 5370 UIC 0 : continue;
434 tgl 5371 ECB : }
5372 :
5373 : /* Count schema-only results for hack below */
434 tgl 5374 GIC 31 : if (item == NULL && nsp != NULL)
5375 1 : num_schema_only++;
5376 : else
432 5377 30 : num_query_other++;
5378 :
434 5379 31 : return requote_identifier(nsp, item, schemaquoted, objectquoted);
5380 : }
434 tgl 5381 ECB :
5382 : /*
5383 : * When the query result is exhausted, check for hard-wired keywords.
5384 : * These will only be returned if they match the input-so-far,
5385 : * ignoring case.
5386 : */
434 tgl 5387 GIC 69 : nskip = list_index - PQntuples(result);
5388 69 : if (schema_query && schema_query->keywords)
5389 : {
434 tgl 5390 CBC 2 : const char *const *itemp = schema_query->keywords;
5391 :
434 tgl 5392 GIC 9 : while (*itemp)
5393 : {
5394 8 : const char *item = *itemp++;
5395 :
434 tgl 5396 CBC 8 : if (nskip-- > 0)
5397 1 : continue;
5398 7 : list_index++;
5399 7 : if (pg_strncasecmp(text, item, strlen(text)) == 0)
5400 : {
432 5401 1 : num_keywords++;
424 5402 1 : return pg_strdup_keyword_case(item, text);
434 tgl 5403 ECB : }
434 tgl 5404 EUB : }
5405 : }
434 tgl 5406 CBC 68 : if (keywords)
434 tgl 5407 ECB : {
434 tgl 5408 CBC 44 : const char *const *itemp = keywords;
434 tgl 5409 ECB :
434 tgl 5410 CBC 115 : while (*itemp)
434 tgl 5411 ECB : {
434 tgl 5412 CBC 95 : const char *item = *itemp++;
5413 :
5414 95 : if (nskip-- > 0)
434 tgl 5415 GIC 36 : continue;
434 tgl 5416 CBC 59 : list_index++;
434 tgl 5417 GIC 59 : if (pg_strncasecmp(text, item, strlen(text)) == 0)
434 tgl 5418 ECB : {
432 tgl 5419 CBC 24 : num_keywords++;
424 5420 24 : return pg_strdup_keyword_case(item, text);
434 tgl 5421 ECB : }
434 tgl 5422 EUB : }
5423 : }
6355 bruce 5424 : }
5425 :
434 tgl 5426 ECB : /*
434 tgl 5427 EUB : * Hack: if we returned only bare schema names, don't let Readline add a
5428 : * space afterwards. Otherwise the schema will stop being part of the
5429 : * completion subject text, which is not what we want.
5430 : */
432 tgl 5431 GIC 44 : if (num_schema_only > 0 && num_query_other == 0 && num_keywords == 0)
434 5432 1 : rl_completion_append_character = '\0';
5433 :
5434 : /* No more matches, so free the result structure and return null */
6355 bruce 5435 CBC 44 : PQclear(result);
6355 bruce 5436 GIC 44 : result = NULL;
6355 bruce 5437 CBC 44 : return NULL;
5438 : }
5439 :
5440 :
5441 : /*
5442 : * Set up completion_ref_object and completion_ref_schema
434 tgl 5443 ECB : * by parsing the given word. These variables can then be
5444 : * used in a query passed to _complete_from_query.
5445 : */
5446 : static void
434 tgl 5447 CBC 19 : set_completion_reference(const char *word)
5448 : {
5449 : bool schemaquoted,
434 tgl 5450 ECB : objectquoted;
5451 :
434 tgl 5452 CBC 19 : parse_identifier(word,
434 tgl 5453 ECB : &completion_ref_schema, &completion_ref_object,
5454 : &schemaquoted, &objectquoted);
434 tgl 5455 CBC 19 : }
434 tgl 5456 ECB :
5457 : /*
5458 : * Set up completion_ref_object when it should just be
5459 : * the given word verbatim.
424 5460 : */
5461 : static void
424 tgl 5462 GIC 2 : set_completion_reference_verbatim(const char *word)
5463 : {
424 tgl 5464 CBC 2 : completion_ref_schema = NULL;
424 tgl 5465 GIC 2 : completion_ref_object = pg_strdup(word);
424 tgl 5466 CBC 2 : }
424 tgl 5467 ECB :
5468 :
4564 5469 : /*
5470 : * This function returns in order one of a fixed, NULL pointer terminated list
5471 : * of strings (if matching). This can be used if there are only a fixed number
5472 : * SQL words that can appear at certain spot.
5473 : */
6355 bruce 5474 : static char *
6355 bruce 5475 GIC 30 : complete_from_list(const char *text, int state)
5476 : {
6355 bruce 5477 ECB : static int string_length,
5478 : list_index,
5479 : matches;
5480 : static bool casesensitive;
5481 : const char *item;
5482 :
5483 : /* need to have a list */
3768 andrew 5484 GIC 30 : Assert(completion_charpp != NULL);
5485 :
5486 : /* Initialization */
6355 bruce 5487 30 : if (state == 0)
5488 : {
5489 12 : list_index = 0;
6355 bruce 5490 CBC 12 : string_length = strlen(text);
4085 peter_e 5491 GIC 12 : casesensitive = completion_case_sensitive;
6355 bruce 5492 CBC 12 : matches = 0;
6355 bruce 5493 EUB : }
6355 bruce 5494 ECB :
6355 bruce 5495 GBC 462 : while ((item = completion_charpp[list_index++]))
5496 : {
5497 : /* First pass is case sensitive */
6355 bruce 5498 GIC 419 : if (casesensitive && strncmp(text, item, string_length) == 0)
6355 bruce 5499 ECB : {
6355 bruce 5500 CBC 3 : matches++;
6355 bruce 5501 GIC 3 : return pg_strdup(item);
6355 bruce 5502 ECB : }
5503 :
5504 : /* Second pass is case insensitive, don't bother counting matches */
6355 bruce 5505 GIC 416 : if (!casesensitive && pg_strncasecmp(text, item, string_length) == 0)
5506 : {
4085 peter_e 5507 14 : if (completion_case_sensitive)
5508 1 : return pg_strdup(item);
5509 : else
5510 :
5511 : /*
3955 bruce 5512 ECB : * If case insensitive matching was requested initially,
5513 : * adjust the case according to setting.
5514 : */
3988 peter_e 5515 CBC 13 : return pg_strdup_keyword_case(item, text);
5516 : }
6355 bruce 5517 ECB : }
5518 :
5519 : /*
5520 : * No matches found. If we're not case insensitive already, lets switch to
5521 : * being case insensitive and try again
5522 : */
6355 bruce 5523 CBC 13 : if (casesensitive && matches == 0)
6355 bruce 5524 ECB : {
6355 bruce 5525 GIC 1 : casesensitive = false;
6355 bruce 5526 CBC 1 : list_index = 0;
5527 1 : state++;
6297 neilc 5528 GIC 1 : return complete_from_list(text, state);
5529 : }
5530 :
6355 bruce 5531 ECB : /* If no more matches, return null. */
6355 bruce 5532 GIC 12 : return NULL;
6355 bruce 5533 ECB : }
5534 :
8535 5535 :
5536 : /*
4564 tgl 5537 : * This function returns one fixed string the first time even if it doesn't
5538 : * match what's there, and nothing the second time. The string
1377 5539 : * to be used must be in completion_charp.
5540 : *
5541 : * If the given string is "", this has the effect of preventing readline
5542 : * from doing any completion. (Without this, readline tries to do filename
5543 : * completion which is seldom the right thing.)
5544 : *
5545 : * If the given string is not empty, readline will replace whatever the
5546 : * user typed with that string. This behavior might be useful if it's
5547 : * completely certain that we know what must appear at a certain spot,
5548 : * so that it's okay to overwrite misspellings. In practice, given the
5549 : * relatively lame parsing technology used in this file, the level of
5550 : * certainty is seldom that high, so that you probably don't want to
5551 : * use this. Use complete_from_list with a one-element list instead;
5552 : * that won't try to auto-correct "misspellings".
5553 : */
5554 : static char *
6355 bruce 5555 GIC 4 : complete_from_const(const char *text, int state)
6355 bruce 5556 ECB : {
3768 andrew 5557 CBC 4 : Assert(completion_charp != NULL);
6355 bruce 5558 GIC 4 : if (state == 0)
5559 : {
4085 peter_e 5560 CBC 2 : if (completion_case_sensitive)
5561 2 : return pg_strdup(completion_charp);
4085 peter_e 5562 ECB : else
5563 :
5564 : /*
5565 : * If case insensitive matching was requested initially, adjust
5566 : * the case according to setting.
5567 : */
3988 peter_e 5568 UIC 0 : return pg_strdup_keyword_case(completion_charp, text);
5569 : }
5570 : else
6355 bruce 5571 GIC 2 : return NULL;
6355 bruce 5572 ECB : }
5573 :
5574 :
5575 : /*
5576 : * This function appends the variable name with prefix and suffix to
3162 fujii 5577 : * the variable names array.
5578 : */
5579 : static void
3162 fujii 5580 CBC 75 : append_variable_names(char ***varnames, int *nvars,
5581 : int *maxvars, const char *varname,
5582 : const char *prefix, const char *suffix)
5583 : {
3162 fujii 5584 GIC 75 : if (*nvars >= *maxvars)
5585 : {
3162 fujii 5586 UIC 0 : *maxvars *= 2;
3064 tgl 5587 LBC 0 : *varnames = (char **) pg_realloc(*varnames,
3064 tgl 5588 UIC 0 : ((*maxvars) + 1) * sizeof(char *));
3162 fujii 5589 ECB : }
5590 :
3162 fujii 5591 CBC 75 : (*varnames)[(*nvars)++] = psprintf("%s%s%s", prefix, varname, suffix);
3162 fujii 5592 GIC 75 : }
5593 :
5594 :
5595 : /*
5596 : * This function supports completion with the name of a psql variable.
5597 : * The variable names can be prefixed and suffixed with additional text
5598 : * to support quoting usages. If need_value is true, only variables
5599 : * that are currently set are included; otherwise, special variables
2257 tgl 5600 ECB : * (those that have hooks) are included even if currently unset.
5601 : */
5602 : static char **
3162 fujii 5603 GIC 2 : complete_from_variables(const char *text, const char *prefix, const char *suffix,
5604 : bool need_value)
5605 : {
5606 : char **matches;
5607 : char **varnames;
4564 tgl 5608 2 : int nvars = 0;
4564 tgl 5609 CBC 2 : int maxvars = 100;
5610 : int i;
5611 : struct _variable *ptr;
4564 tgl 5612 ECB :
4086 peter_e 5613 GIC 2 : varnames = (char **) pg_malloc((maxvars + 1) * sizeof(char *));
4564 tgl 5614 ECB :
4564 tgl 5615 CBC 78 : for (ptr = pset.vars->next; ptr; ptr = ptr->next)
4564 tgl 5616 ECB : {
3162 fujii 5617 CBC 76 : if (need_value && !(ptr->value))
3162 fujii 5618 GIC 1 : continue;
5619 75 : append_variable_names(&varnames, &nvars, &maxvars, ptr->name,
3162 fujii 5620 ECB : prefix, suffix);
5621 : }
5622 :
4564 tgl 5623 CBC 2 : varnames[nvars] = NULL;
3955 bruce 5624 GIC 2 : COMPLETE_WITH_LIST_CS((const char *const *) varnames);
4564 tgl 5625 ECB :
4564 tgl 5626 CBC 77 : for (i = 0; i < nvars; i++)
4086 peter_e 5627 GIC 75 : free(varnames[i]);
4564 tgl 5628 2 : free(varnames);
5629 :
4564 tgl 5630 CBC 2 : return matches;
5631 : }
4564 tgl 5632 ECB :
8535 bruce 5633 :
5634 : /*
5635 : * This function wraps rl_filename_completion_function() to strip quotes from
5636 : * the input before searching for matches and to quote any matches for which
5637 : * the consuming command will require it.
5638 : *
5639 : * Caller must set completion_charp to a zero- or one-character string
1172 tgl 5640 : * containing the escape character. This is necessary since \copy has no
5641 : * escape character, but every other backslash command recognizes "\" as an
5642 : * escape character.
5643 : *
5644 : * Caller must also set completion_force_quote to indicate whether to force
5645 : * quotes around the result. (The SQL COPY command requires that.)
5646 : */
5647 : static char *
4058 alvherre 5648 CBC 16 : complete_from_files(const char *text, int state)
5649 : {
1172 tgl 5650 ECB : #ifdef USE_FILENAME_QUOTING_FUNCTIONS
5651 :
5652 : /*
5653 : * If we're using a version of Readline that supports filename quoting
5654 : * hooks, rely on those, and invoke rl_filename_completion_function()
5655 : * without messing with its arguments. Readline does stuff internally
5656 : * that does not work well at all if we try to handle dequoting here.
5657 : * Instead, Readline will call quote_file_name() and dequote_file_name()
5658 : * (see below) at appropriate times.
5659 : *
5660 : * ... or at least, mostly it will. There are some paths involving
5661 : * unmatched file names in which Readline never calls quote_file_name(),
5662 : * and if left to its own devices it will incorrectly append a quote
5663 : * anyway. Set rl_completion_suppress_quote to prevent that. If we do
5664 : * get to quote_file_name(), we'll clear this again. (Yes, this seems
5665 : * like it's working around Readline bugs.)
5666 : */
5667 : #ifdef HAVE_RL_COMPLETION_SUPPRESS_QUOTE
1172 tgl 5668 GIC 16 : rl_completion_suppress_quote = 1;
5669 : #endif
5670 :
5671 : /* If user typed a quote, force quoting (never remove user's quote) */
5672 16 : if (*text == '\'')
1172 tgl 5673 UIC 0 : completion_force_quote = true;
5674 :
1172 tgl 5675 GIC 16 : return rl_filename_completion_function(text, state);
5676 : #else
5677 :
5678 : /*
5679 : * Otherwise, we have to do the best we can.
1172 tgl 5680 ECB : */
5681 : static const char *unquoted_text;
4058 alvherre 5682 : char *unquoted_match;
5683 : char *ret = NULL;
5684 :
1172 tgl 5685 : /* If user typed a quote, force quoting (never remove user's quote) */
5686 : if (*text == '\'')
5687 : completion_force_quote = true;
5688 :
5689 : if (state == 0)
5690 : {
5691 : /* Initialization: stash the unquoted input. */
5692 : unquoted_text = strtokx(text, "", NULL, "'", *completion_charp,
4058 alvherre 5693 EUB : false, true, pset.encoding);
5694 : /* expect a NULL return for the empty string only */
5695 : if (!unquoted_text)
4058 alvherre 5696 ECB : {
5697 : Assert(*text == '\0');
5698 : unquoted_text = text;
5699 : }
5700 : }
5701 :
5702 : unquoted_match = rl_filename_completion_function(unquoted_text, state);
5703 : if (unquoted_match)
5704 : {
1172 tgl 5705 : struct stat statbuf;
5706 : bool is_dir = (stat(unquoted_match, &statbuf) == 0 &&
5707 : S_ISDIR(statbuf.st_mode) != 0);
5708 :
5709 : /* Re-quote the result, if needed. */
5710 : ret = quote_if_needed(unquoted_match, " \t\r\n\"`",
1172 tgl 5711 EUB : '\'', *completion_charp,
5712 : completion_force_quote,
5713 : pset.encoding);
5714 : if (ret)
5715 : free(unquoted_match);
4058 alvherre 5716 ECB : else
5717 : ret = unquoted_match;
5718 :
5719 : /*
5720 : * If it's a directory, replace trailing quote with a slash; this is
5721 : * usually more convenient. (If we didn't quote, leave this to
5722 : * libedit.)
5723 : */
5724 : if (*ret == '\'' && is_dir)
5725 : {
5726 : char *retend = ret + strlen(ret) - 1;
5727 :
1172 tgl 5728 : Assert(*retend == '\'');
5729 : *retend = '/';
5730 : /* Prevent libedit from adding a space, too */
5731 : rl_completion_append_character = '\0';
5732 : }
4058 alvherre 5733 : }
5734 :
5735 : return ret;
5736 : #endif /* USE_FILENAME_QUOTING_FUNCTIONS */
5737 : }
5738 :
5739 :
8535 bruce 5740 : /* HELPER FUNCTIONS */
5741 :
5742 :
4085 peter_e 5743 : /*
3988 5744 : * Make a pg_strdup copy of s and convert the case according to
5745 : * COMP_KEYWORD_CASE setting, using ref as the text that was already entered.
5746 : */
5747 : static char *
3988 peter_e 5748 CBC 40 : pg_strdup_keyword_case(const char *s, const char *ref)
4085 peter_e 5749 ECB : {
5750 : char *ret,
3955 bruce 5751 : *p;
4085 peter_e 5752 CBC 40 : unsigned char first = ref[0];
3988 peter_e 5753 ECB :
3988 peter_e 5754 GIC 40 : ret = pg_strdup(s);
3988 peter_e 5755 ECB :
3021 tgl 5756 GIC 40 : if (pset.comp_case == PSQL_COMP_CASE_LOWER ||
5757 34 : ((pset.comp_case == PSQL_COMP_CASE_PRESERVE_LOWER ||
2118 5758 34 : pset.comp_case == PSQL_COMP_CASE_PRESERVE_UPPER) && islower(first)) ||
3021 5759 26 : (pset.comp_case == PSQL_COMP_CASE_PRESERVE_LOWER && !isalpha(first)))
5760 : {
3988 peter_e 5761 122 : for (p = ret; *p; p++)
5762 108 : *p = pg_tolower((unsigned char) *p);
5763 : }
5764 : else
5765 : {
5766 241 : for (p = ret; *p; p++)
5767 215 : *p = pg_toupper((unsigned char) *p);
5768 : }
5769 :
5770 40 : return ret;
5771 : }
5772 :
4085 peter_e 5773 ECB :
5774 : /*
5775 : * escape_string - Escape argument for use as string literal.
5776 : *
5777 : * The returned value has to be freed.
5778 : */
5779 : static char *
2770 andres 5780 GIC 71 : escape_string(const char *text)
5781 : {
5782 : size_t text_length;
5783 : char *result;
5784 :
5785 71 : text_length = strlen(text);
5786 :
5787 71 : result = pg_malloc(text_length * 2 + 1);
5788 71 : PQescapeStringConn(pset.db, result, text, text_length, NULL);
5789 :
5790 71 : return result;
5791 : }
5792 :
2770 andres 5793 ECB :
5794 : /*
5795 : * make_like_pattern - Convert argument to a LIKE prefix pattern.
5796 : *
434 tgl 5797 : * We escape _ and % in the given text by backslashing, append a % to
434 tgl 5798 EUB : * represent "any subsequent characters", and then pass the string through
5799 : * escape_string() so it's ready to insert in a query. The result needs
434 tgl 5800 ECB : * to be freed.
5801 : */
5802 : static char *
434 tgl 5803 GIC 44 : make_like_pattern(const char *word)
5804 : {
5805 : char *result;
5806 44 : char *buffer = pg_malloc(strlen(word) * 2 + 2);
5807 44 : char *bptr = buffer;
5808 :
5809 180 : while (*word)
5810 : {
5811 136 : if (*word == '_' || *word == '%')
5812 2 : *bptr++ = '\\';
5813 136 : if (IS_HIGHBIT_SET(*word))
5814 : {
5815 : /*
5816 : * Transfer multibyte characters without further processing, to
5817 : * avoid getting confused in unsafe client encodings.
5818 : */
434 tgl 5819 UIC 0 : int chlen = PQmblenBounded(word, pset.encoding);
5820 :
5821 0 : while (chlen-- > 0)
5822 0 : *bptr++ = *word++;
5823 : }
5824 : else
434 tgl 5825 GIC 136 : *bptr++ = *word++;
5826 : }
5827 44 : *bptr++ = '%';
5828 44 : *bptr = '\0';
5829 :
5830 44 : result = escape_string(buffer);
5831 44 : free(buffer);
5832 44 : return result;
5833 : }
5834 :
5835 :
5836 : /*
5837 : * parse_identifier - Parse a possibly-schema-qualified SQL identifier.
5838 : *
5839 : * This involves splitting off the schema name if present, de-quoting,
5840 : * and downcasing any unquoted text. We are a bit laxer than the backend
5841 : * in that we allow just portions of a name to be quoted --- that's because
5842 : * psql metacommands have traditionally behaved that way.
5843 : *
5844 : * Outputs are a malloc'd schema name (NULL if none), malloc'd object name,
5845 : * and booleans telling whether any part of the schema and object name was
5846 : * double-quoted.
5847 : */
5848 : static void
5849 55 : parse_identifier(const char *ident,
5850 : char **schemaname, char **objectname,
5851 : bool *schemaquoted, bool *objectquoted)
5852 : {
5853 55 : size_t buflen = strlen(ident) + 1;
5854 55 : bool enc_is_single_byte = (pg_encoding_max_length(pset.encoding) == 1);
5855 : char *sname;
5856 : char *oname;
5857 : char *optr;
5858 : bool inquotes;
5859 :
5860 : /* Initialize, making a certainly-large-enough output buffer */
5861 55 : sname = NULL;
5862 55 : oname = pg_malloc(buflen);
5863 55 : *schemaquoted = *objectquoted = false;
5864 : /* Scan */
5865 55 : optr = oname;
5866 55 : inquotes = false;
5867 268 : while (*ident)
5868 : {
5869 213 : unsigned char ch = (unsigned char) *ident++;
5870 :
5871 213 : if (ch == '"')
5872 : {
434 tgl 5873 CBC 7 : if (inquotes && *ident == '"')
5874 : {
5875 : /* two quote marks within a quoted identifier = emit quote */
434 tgl 5876 UIC 0 : *optr++ = '"';
434 tgl 5877 LBC 0 : ident++;
5878 : }
434 tgl 5879 ECB : else
5880 : {
434 tgl 5881 CBC 7 : inquotes = !inquotes;
5882 7 : *objectquoted = true;
434 tgl 5883 ECB : }
5884 : }
434 tgl 5885 GIC 206 : else if (ch == '.' && !inquotes)
434 tgl 5886 ECB : {
5887 : /* Found a schema name, transfer it to sname / *schemaquoted */
434 tgl 5888 GIC 4 : *optr = '\0';
5889 4 : free(sname); /* drop any catalog name */
5890 4 : sname = oname;
434 tgl 5891 CBC 4 : oname = pg_malloc(buflen);
5892 4 : optr = oname;
434 tgl 5893 GIC 4 : *schemaquoted = *objectquoted;
5894 4 : *objectquoted = false;
434 tgl 5895 ECB : }
434 tgl 5896 GIC 202 : else if (!enc_is_single_byte && IS_HIGHBIT_SET(ch))
434 tgl 5897 UIC 0 : {
5898 : /*
5899 : * Transfer multibyte characters without further processing. They
5900 : * wouldn't be affected by our downcasing rule anyway, and this
5901 : * avoids possibly doing the wrong thing in unsafe client
5902 : * encodings.
5903 : */
5904 0 : int chlen = PQmblenBounded(ident - 1, pset.encoding);
434 tgl 5905 ECB :
434 tgl 5906 UIC 0 : *optr++ = (char) ch;
5907 0 : while (--chlen > 0)
5908 0 : *optr++ = *ident++;
5909 : }
434 tgl 5910 ECB : else
5911 : {
434 tgl 5912 CBC 202 : if (!inquotes)
434 tgl 5913 ECB : {
5914 : /*
5915 : * This downcasing transformation should match the backend's
5916 : * downcase_identifier() as best we can. We do not know the
5917 : * backend's locale, though, so it's necessarily approximate.
5918 : * We assume that psql is operating in the same locale and
5919 : * encoding as the backend.
5920 : */
434 tgl 5921 GIC 178 : if (ch >= 'A' && ch <= 'Z')
5922 28 : ch += 'a' - 'A';
5923 150 : else if (enc_is_single_byte && IS_HIGHBIT_SET(ch) && isupper(ch))
434 tgl 5924 UIC 0 : ch = tolower(ch);
5925 : }
434 tgl 5926 GIC 202 : *optr++ = (char) ch;
5927 : }
434 tgl 5928 ECB : }
5929 :
434 tgl 5930 GIC 55 : *optr = '\0';
434 tgl 5931 CBC 55 : *schemaname = sname;
5932 55 : *objectname = oname;
434 tgl 5933 GIC 55 : }
434 tgl 5934 ECB :
5935 :
5936 : /*
5937 : * requote_identifier - Reconstruct a possibly-schema-qualified SQL identifier.
5938 : *
5939 : * Build a malloc'd string containing the identifier, with quoting applied
5940 : * as necessary. This is more or less the inverse of parse_identifier;
5941 : * in particular, if an input component was quoted, we'll quote the output
5942 : * even when that isn't strictly required.
5943 : *
434 tgl 5944 EUB : * Unlike parse_identifier, we handle the case where a schema and no
5945 : * object name is provided, producing just "schema.".
5946 : */
5947 : static char *
434 tgl 5948 GIC 31 : requote_identifier(const char *schemaname, const char *objectname,
5949 : bool quote_schema, bool quote_object)
434 tgl 5950 ECB : {
5951 : char *result;
434 tgl 5952 CBC 31 : size_t buflen = 1; /* count the trailing \0 */
434 tgl 5953 ECB : char *ptr;
5954 :
5955 : /*
5956 : * We could use PQescapeIdentifier for some of this, but not all, and it
5957 : * adds more notational cruft than it seems worth.
5958 : */
434 tgl 5959 GIC 31 : if (schemaname)
5960 : {
5961 4 : buflen += strlen(schemaname) + 1; /* +1 for the dot */
5962 4 : if (!quote_schema)
5963 4 : quote_schema = identifier_needs_quotes(schemaname);
5964 4 : if (quote_schema)
5965 : {
434 tgl 5966 UIC 0 : buflen += 2; /* account for quote marks */
5967 0 : for (const char *p = schemaname; *p; p++)
5968 : {
5969 0 : if (*p == '"')
5970 0 : buflen++;
5971 : }
5972 : }
5973 : }
434 tgl 5974 CBC 31 : if (objectname)
5975 : {
434 tgl 5976 GIC 30 : buflen += strlen(objectname);
5977 30 : if (!quote_object)
434 tgl 5978 CBC 22 : quote_object = identifier_needs_quotes(objectname);
5979 30 : if (quote_object)
5980 : {
434 tgl 5981 GIC 8 : buflen += 2; /* account for quote marks */
5982 73 : for (const char *p = objectname; *p; p++)
5983 : {
5984 65 : if (*p == '"')
434 tgl 5985 UIC 0 : buflen++;
434 tgl 5986 ECB : }
5987 : }
5988 : }
434 tgl 5989 GIC 31 : result = pg_malloc(buflen);
434 tgl 5990 CBC 31 : ptr = result;
5991 31 : if (schemaname)
434 tgl 5992 ECB : {
434 tgl 5993 GIC 4 : if (quote_schema)
434 tgl 5994 LBC 0 : *ptr++ = '"';
434 tgl 5995 GIC 28 : for (const char *p = schemaname; *p; p++)
434 tgl 5996 ECB : {
434 tgl 5997 GIC 24 : *ptr++ = *p;
434 tgl 5998 CBC 24 : if (*p == '"')
434 tgl 5999 UIC 0 : *ptr++ = '"';
6000 : }
434 tgl 6001 GBC 4 : if (quote_schema)
434 tgl 6002 UBC 0 : *ptr++ = '"';
434 tgl 6003 GIC 4 : *ptr++ = '.';
6004 : }
6005 31 : if (objectname)
434 tgl 6006 ECB : {
434 tgl 6007 CBC 30 : if (quote_object)
434 tgl 6008 GIC 8 : *ptr++ = '"';
6009 264 : for (const char *p = objectname; *p; p++)
434 tgl 6010 ECB : {
434 tgl 6011 GIC 234 : *ptr++ = *p;
6012 234 : if (*p == '"')
434 tgl 6013 LBC 0 : *ptr++ = '"';
434 tgl 6014 ECB : }
434 tgl 6015 CBC 30 : if (quote_object)
6016 8 : *ptr++ = '"';
434 tgl 6017 ECB : }
434 tgl 6018 CBC 31 : *ptr = '\0';
6019 31 : return result;
6020 : }
434 tgl 6021 ECB :
434 tgl 6022 EUB :
6023 : /*
6024 : * Detect whether an identifier must be double-quoted.
6025 : *
6026 : * Note we'll quote anything that's not ASCII; the backend's quote_ident()
6027 : * does the same. Perhaps this could be relaxed in future.
6028 : */
6029 : static bool
434 tgl 6030 GIC 46 : identifier_needs_quotes(const char *ident)
434 tgl 6031 EUB : {
6032 : int kwnum;
6033 :
6034 : /* Check syntax. */
434 tgl 6035 GIC 46 : if (!((ident[0] >= 'a' && ident[0] <= 'z') || ident[0] == '_'))
434 tgl 6036 UIC 0 : return true;
434 tgl 6037 CBC 46 : if (strspn(ident, "abcdefghijklmnopqrstuvwxyz0123456789_") != strlen(ident))
434 tgl 6038 UIC 0 : return true;
6039 :
6040 : /*
6041 : * Check for keyword. We quote keywords except for unreserved ones.
6042 : *
6043 : * It is possible that our keyword list doesn't quite agree with the
6044 : * server's, but this should be close enough for tab-completion purposes.
6045 : *
434 tgl 6046 ECB : * Note: ScanKeywordLookup() does case-insensitive comparison, but that's
6047 : * fine, since we already know we have all-lower-case.
6048 : */
434 tgl 6049 GBC 46 : kwnum = ScanKeywordLookup(ident, &ScanKeywords);
6050 :
434 tgl 6051 CBC 46 : if (kwnum >= 0 && ScanKeywordCategories[kwnum] != UNRESERVED_KEYWORD)
434 tgl 6052 UIC 0 : return true;
6053 :
434 tgl 6054 GIC 46 : return false;
434 tgl 6055 ECB : }
6056 :
6057 :
6058 : /*
6059 : * Execute a query, returning NULL if there was any error.
6060 : * This should be the preferred way of talking to the database in this file.
6061 : */
6062 : static PGresult *
6355 bruce 6063 GIC 46 : exec_query(const char *query)
6064 : {
6065 : PGresult *result;
6066 :
6067 46 : if (query == NULL || !pset.db || PQstatus(pset.db) != CONNECTION_OK)
6355 bruce 6068 UIC 0 : return NULL;
6069 :
6355 bruce 6070 GIC 46 : result = PQexec(pset.db, query);
6071 :
5349 tgl 6072 46 : if (PQresultStatus(result) != PGRES_TUPLES_OK)
6355 bruce 6073 ECB : {
6074 : /*
6075 : * Printing an error while the user is typing would be quite annoying,
6076 : * so we don't. This does complicate debugging of this code; but you
434 tgl 6077 : * can look in the server log instead.
6078 : */
6079 : #ifdef NOT_USED
6080 : pg_log_error("tab completion query failed: %s\nQuery was:\n%s",
6081 : PQerrorMessage(pset.db), query);
6082 : #endif
6355 bruce 6083 UIC 0 : PQclear(result);
6355 bruce 6084 LBC 0 : result = NULL;
6085 : }
8397 bruce 6086 ECB :
6355 bruce 6087 CBC 46 : return result;
6355 bruce 6088 ECB : }
8535 6089 :
6090 :
6535 neilc 6091 EUB : /*
2667 tgl 6092 : * Parse all the word(s) before point.
6093 : *
6094 : * Returns a malloc'd array of character pointers that point into the malloc'd
6095 : * data array returned to *buffer; caller must free() both of these when done.
6096 : * *nwords receives the number of words found, ie, the valid length of the
6097 : * return array.
6098 : *
2667 tgl 6099 ECB : * Words are returned right to left, that is, previous_words[0] gets the last
6100 : * word before point, previous_words[1] the next-to-last, etc.
6535 neilc 6101 : */
2667 tgl 6102 : static char **
2667 tgl 6103 CBC 66 : get_previous_words(int point, char **buffer, int *nwords)
6355 bruce 6104 ECB : {
6105 : char **previous_words;
2667 tgl 6106 : char *buf;
2666 6107 : char *outptr;
2668 tgl 6108 GIC 66 : int words_found = 0;
4189 tgl 6109 ECB : int i;
4799 itagaki.takahiro 6110 EUB :
6111 : /*
6112 : * If we have anything in tab_completion_query_buf, paste it together with
6113 : * rl_line_buffer to construct the full query. Otherwise we can just use
2666 tgl 6114 ECB : * rl_line_buffer as the input string.
2667 6115 : */
2666 tgl 6116 CBC 66 : if (tab_completion_query_buf && tab_completion_query_buf->len > 0)
6117 : {
6118 3 : i = tab_completion_query_buf->len;
2666 tgl 6119 GBC 3 : buf = pg_malloc(point + i + 2);
2666 tgl 6120 CBC 3 : memcpy(buf, tab_completion_query_buf->data, i);
2667 tgl 6121 GIC 3 : buf[i++] = '\n';
2666 tgl 6122 CBC 3 : memcpy(buf + i, rl_line_buffer, point);
6123 3 : i += point;
2666 tgl 6124 GBC 3 : buf[i] = '\0';
6125 : /* Readjust point to reference appropriate offset in buf */
2666 tgl 6126 CBC 3 : point = i;
2667 tgl 6127 EUB : }
2666 tgl 6128 ECB : else
2666 tgl 6129 GIC 63 : buf = rl_line_buffer;
2667 tgl 6130 ECB :
6131 : /*
2666 6132 : * Allocate an array of string pointers and a buffer to hold the strings
6133 : * themselves. The worst case is that the line contains only
6134 : * non-whitespace WORD_BREAKS characters, making each one a separate word.
6135 : * This is usually much more space than we need, but it's cheaper than
6136 : * doing a separate malloc() for each word.
2667 6137 : */
2666 tgl 6138 GBC 66 : previous_words = (char **) pg_malloc(point * sizeof(char *));
2666 tgl 6139 GIC 66 : *buffer = outptr = (char *) pg_malloc(point * 2);
2667 tgl 6140 ECB :
6141 : /*
6142 : * First we look for a non-word char before the current point. (This is
6143 : * probably useless, if readline is on the same page as we are about what
6144 : * is a word, but if so it's cheap.)
6145 : */
4799 itagaki.takahiro 6146 GIC 72 : for (i = point - 1; i >= 0; i--)
6147 : {
6148 69 : if (strchr(WORD_BREAKS, buf[i]))
6149 63 : break;
6150 : }
6151 66 : point = i;
6152 :
6153 : /*
6154 : * Now parse words, working backwards, until we hit start of line. The
2667 tgl 6155 ECB : * backwards scan has some interesting but intentional properties
6156 : * concerning parenthesis handling.
6157 : */
2667 tgl 6158 GIC 253 : while (point >= 0)
6159 : {
4189 tgl 6160 ECB : int start,
4189 tgl 6161 EUB : end;
2667 tgl 6162 CBC 187 : bool inquotes = false;
2667 tgl 6163 GBC 187 : int parentheses = 0;
6164 :
6165 : /* now find the first non-space which then constitutes the end */
4189 tgl 6166 GIC 187 : end = -1;
4799 itagaki.takahiro 6167 380 : for (i = point; i >= 0; i--)
6168 : {
4189 tgl 6169 380 : if (!isspace((unsigned char) buf[i]))
6170 : {
6355 bruce 6171 187 : end = i;
6172 187 : break;
6173 : }
4189 tgl 6174 ECB : }
6175 : /* if no end found, we're done */
2667 tgl 6176 CBC 187 : if (end < 0)
2667 tgl 6177 UBC 0 : break;
6178 :
6355 bruce 6179 ECB : /*
6180 : * Otherwise we now look for the start. The start is either the last
6181 : * character before any word-break character going backwards from the
6182 : * end, or it's simply character 0. We also handle open quotes and
6183 : * parentheses.
6184 : */
2667 tgl 6185 GIC 938 : for (start = end; start > 0; start--)
6186 : {
6187 875 : if (buf[start] == '"')
2667 tgl 6188 CBC 2 : inquotes = !inquotes;
2667 tgl 6189 GIC 875 : if (!inquotes)
6190 : {
6191 870 : if (buf[start] == ')')
2667 tgl 6192 LBC 0 : parentheses++;
2667 tgl 6193 GBC 870 : else if (buf[start] == '(')
6194 : {
2667 tgl 6195 CBC 3 : if (--parentheses <= 0)
4799 itagaki.takahiro 6196 GIC 3 : break;
4799 itagaki.takahiro 6197 ECB : }
2667 tgl 6198 GIC 867 : else if (parentheses == 0 &&
6199 867 : strchr(WORD_BREAKS, buf[start - 1]))
6200 121 : break;
6201 : }
6202 : }
6203 :
6204 : /* Return the word located at start to end inclusive */
2666 6205 187 : previous_words[words_found++] = outptr;
6206 187 : i = end - start + 1;
6207 187 : memcpy(outptr, &buf[start], i);
2666 tgl 6208 GBC 187 : outptr += i;
6209 187 : *outptr++ = '\0';
6210 :
6211 : /* Continue searching */
2667 tgl 6212 CBC 187 : point = start - 1;
6213 : }
6214 :
6215 : /* Release parsing input workspace, if we made one above */
2666 tgl 6216 GIC 66 : if (buf != rl_line_buffer)
6217 3 : free(buf);
6218 :
2667 6219 66 : *nwords = words_found;
6220 66 : return previous_words;
6221 : }
6222 :
6223 : /*
6224 : * Look up the type for the GUC variable with the passed name.
6225 : *
6226 : * Returns NULL if the variable is unknown. Otherwise the returned string,
6227 : * containing the type, has to be freed.
2770 andres 6228 ECB : */
6229 : static char *
2770 andres 6230 GIC 2 : get_guctype(const char *varname)
6231 : {
6232 : PQExpBufferData query_buffer;
2770 andres 6233 ECB : char *e_varname;
6234 : PGresult *result;
2770 andres 6235 GIC 2 : char *guctype = NULL;
6236 :
6237 2 : e_varname = escape_string(varname);
6238 :
6239 2 : initPQExpBuffer(&query_buffer);
6240 2 : appendPQExpBuffer(&query_buffer,
2770 andres 6241 ECB : "SELECT vartype FROM pg_catalog.pg_settings "
6242 : "WHERE pg_catalog.lower(name) = pg_catalog.lower('%s')",
6243 : e_varname);
6244 :
2770 andres 6245 CBC 2 : result = exec_query(query_buffer.data);
6246 2 : termPQExpBuffer(&query_buffer);
6247 2 : free(e_varname);
2770 andres 6248 ECB :
2770 andres 6249 CBC 2 : if (PQresultStatus(result) == PGRES_TUPLES_OK && PQntuples(result) > 0)
2770 andres 6250 GIC 2 : guctype = pg_strdup(PQgetvalue(result, 0, 0));
2770 andres 6251 ECB :
2770 andres 6252 GIC 2 : PQclear(result);
6253 :
2770 andres 6254 CBC 2 : return guctype;
6255 : }
6256 :
6257 : #ifdef USE_FILENAME_QUOTING_FUNCTIONS
6258 :
6259 : /*
6260 : * Quote a filename according to SQL rules, returning a malloc'd string.
6261 : * completion_charp must point to escape character or '\0', and
6262 : * completion_force_quote must be set correctly, as per comments for
1172 tgl 6263 ECB : * complete_from_files().
8482 peter_e 6264 : */
6265 : static char *
1172 tgl 6266 GIC 5 : quote_file_name(char *fname, int match_type, char *quote_pointer)
6267 : {
6268 : char *s;
6269 : struct stat statbuf;
6270 :
1172 tgl 6271 ECB : /* Quote if needed. */
1172 tgl 6272 GIC 5 : s = quote_if_needed(fname, " \t\r\n\"`",
1172 tgl 6273 CBC 5 : '\'', *completion_charp,
1172 tgl 6274 ECB : completion_force_quote,
6275 : pset.encoding);
1172 tgl 6276 CBC 5 : if (!s)
1172 tgl 6277 GIC 2 : s = pg_strdup(fname);
6278 :
6279 : /*
6280 : * However, some of the time we have to strip the trailing quote from what
6281 : * we send back. Never strip the trailing quote if the user already typed
6282 : * one; otherwise, suppress the trailing quote if we have multiple/no
1172 tgl 6283 ECB : * matches (because we don't want to add a quote if the input is seemingly
6284 : * unfinished), or if the input was already quoted (because Readline will
6285 : * do arguably-buggy things otherwise), or if the file does not exist, or
6286 : * if it's a directory.
6287 : */
1172 tgl 6288 CBC 5 : if (*s == '\'' &&
1172 tgl 6289 GIC 3 : completion_last_char != '\'' &&
6290 1 : (match_type != SINGLE_MATCH ||
1172 tgl 6291 CBC 2 : (quote_pointer && *quote_pointer == '\'') ||
6292 1 : stat(fname, &statbuf) != 0 ||
1172 tgl 6293 GIC 1 : S_ISDIR(statbuf.st_mode)))
1172 tgl 6294 ECB : {
1172 tgl 6295 GIC 2 : char *send = s + strlen(s) - 1;
1172 tgl 6296 ECB :
1172 tgl 6297 CBC 2 : Assert(*send == '\'');
1172 tgl 6298 GIC 2 : *send = '\0';
6299 : }
6300 :
1172 tgl 6301 ECB : /*
1172 tgl 6302 EUB : * And now we can let Readline do its thing with possibly adding a quote
6303 : * on its own accord. (This covers some additional cases beyond those
6304 : * dealt with above.)
6305 : */
6306 : #ifdef HAVE_RL_COMPLETION_SUPPRESS_QUOTE
1172 tgl 6307 GIC 5 : rl_completion_suppress_quote = 0;
6308 : #endif
6309 :
1172 tgl 6310 ECB : /*
6311 : * If user typed a leading quote character other than single quote (i.e.,
6312 : * double quote), zap it, so that we replace it with the correct single
6313 : * quote.
6314 : */
1172 tgl 6315 GIC 5 : if (quote_pointer && *quote_pointer != '\'')
1172 tgl 6316 CBC 4 : *quote_pointer = '\0';
6355 bruce 6317 EUB :
6355 bruce 6318 CBC 5 : return s;
6319 : }
6355 bruce 6320 ECB :
1172 tgl 6321 : /*
6322 : * Dequote a filename, if it's quoted.
6323 : * completion_charp must point to escape character or '\0', as per
6324 : * comments for complete_from_files().
6325 : */
6326 : static char *
1172 tgl 6327 GIC 12 : dequote_file_name(char *fname, int quote_char)
6328 : {
6329 : char *unquoted_fname;
1172 tgl 6330 ECB :
6331 : /*
6332 : * If quote_char is set, it's not included in "fname". We have to add it
6333 : * or strtokx will not interpret the string correctly (notably, it won't
6334 : * recognize escapes).
6335 : */
1172 tgl 6336 GIC 12 : if (quote_char == '\'')
1172 tgl 6337 ECB : {
1172 tgl 6338 GIC 6 : char *workspace = (char *) pg_malloc(strlen(fname) + 2);
6339 :
6340 6 : workspace[0] = quote_char;
1172 tgl 6341 CBC 6 : strcpy(workspace + 1, fname);
6342 6 : unquoted_fname = strtokx(workspace, "", NULL, "'", *completion_charp,
6343 : false, true, pset.encoding);
6344 6 : free(workspace);
1172 tgl 6345 ECB : }
6346 : else
1172 tgl 6347 GIC 6 : unquoted_fname = strtokx(fname, "", NULL, "'", *completion_charp,
6348 : false, true, pset.encoding);
6349 :
6350 : /* expect a NULL return for the empty string only */
6351 12 : if (!unquoted_fname)
6352 : {
1172 tgl 6353 UIC 0 : Assert(*fname == '\0');
6354 0 : unquoted_fname = fname;
1172 tgl 6355 ECB : }
6356 :
6357 : /* readline expects a malloc'd result that it is to free */
1172 tgl 6358 GIC 12 : return pg_strdup(unquoted_fname);
6359 : }
1172 tgl 6360 ECB :
6361 : #endif /* USE_FILENAME_QUOTING_FUNCTIONS */
7833 bruce 6362 :
6363 : #endif /* USE_READLINE */
|