LCOV - differential code coverage report
Current view: top level - src/bin/psql - tab-complete.in.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC CBC DUB
Current: c70b6db34ffeab48beef1fb4ce61bcad3772b8dd vs 06473f5a344df8c9594ead90a609b86f6724cff8 Lines: 28.2 % 2351 662 29 1660 662 8
Current Date: 2025-09-06 07:49:51 +0900 Functions: 97.4 % 38 37 1 37
Baseline: lcov-20250906-005545-baseline Branches: 27.8 % 1513 420 18 14 3 1058 12 2 406
Baseline Date: 2025-09-05 08:21:35 +0100 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(1,7] days: 0.0 % 1 0 1
(30,360] days: 38.7 % 261 101 28 132 101
(360..) days: 26.9 % 2089 561 1528 561
Function coverage date bins:
(30,360] days: 100.0 % 6 6 6
(360..) days: 96.9 % 32 31 1 31
Branch coverage date bins:
(30,360] days: 8.8 % 825 73 18 14 3 717 12 2 59
(360..) days: 50.4 % 688 347 341 347

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

Generated by: LCOV version 2.4-beta