LCOV - differential code coverage report
Current view: top level - src/bin/psql - tab-complete.c (source / functions) Coverage Total Hit UNC UBC GNC CBC DUB DCB
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 60.1 % 2420 1454 46 920 49 1405 13 5
Current Date: 2024-04-14 14:21:10 Functions: 97.1 % 34 33 1 2 31
Baseline: 16@8cea358b128 Branches: 48.3 % 2596 1254 64 1278 48 1206
Baseline Date: 2024-04-14 14:21:09 Line coverage date bins:
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed [..60] days: 45.8 % 24 11 13 11
(60,120] days: 55.6 % 9 5 4 5
(120,180] days: 55.0 % 40 22 18 22
(180,240] days: 50.0 % 6 3 3 3
(240..) days: 60.4 % 2341 1413 8 920 8 1405
Function coverage date bins:
(240..) days: 97.1 % 34 33 1 2 31
Branch coverage date bins:
[..60] days: 36.7 % 30 11 19 11
(60,120] days: 50.0 % 10 5 5 5
(120,180] days: 50.0 % 44 22 22 22
(180,240] days: 25.0 % 12 3 9 3
(240..) days: 48.5 % 2500 1213 9 1278 7 1206

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*
                                  2                 :                :  * psql - the PostgreSQL interactive terminal
                                  3                 :                :  *
                                  4                 :                :  * Copyright (c) 2000-2024, PostgreSQL Global Development Group
                                  5                 :                :  *
                                  6                 :                :  * src/bin/psql/tab-complete.c
                                  7                 :                :  */
                                  8                 :                : 
                                  9                 :                : /*----------------------------------------------------------------------
                                 10                 :                :  * This file implements a somewhat more sophisticated readline "TAB
                                 11                 :                :  * completion" in psql. It is not intended to be AI, to replace
                                 12                 :                :  * learning SQL, or to relieve you from thinking about what you're
                                 13                 :                :  * doing. Also it does not always give you all the syntactically legal
                                 14                 :                :  * completions, only those that are the most common or the ones that
                                 15                 :                :  * the programmer felt most like implementing.
                                 16                 :                :  *
                                 17                 :                :  * CAVEAT: Tab completion causes queries to be sent to the backend.
                                 18                 :                :  * The number of tuples returned gets limited, in most default
                                 19                 :                :  * installations to 1000, but if you still don't like this prospect,
                                 20                 :                :  * you can turn off tab completion in your ~/.inputrc (or else
                                 21                 :                :  * ${INPUTRC}) file so:
                                 22                 :                :  *
                                 23                 :                :  *   $if psql
                                 24                 :                :  *   set disable-completion on
                                 25                 :                :  *   $endif
                                 26                 :                :  *
                                 27                 :                :  * See `man 3 readline' or `info readline' for the full details.
                                 28                 :                :  *
                                 29                 :                :  * BUGS:
                                 30                 :                :  * - Quotes, parentheses, and other funny characters are not handled
                                 31                 :                :  *   all that gracefully.
                                 32                 :                :  *----------------------------------------------------------------------
                                 33                 :                :  */
                                 34                 :                : 
                                 35                 :                : #include "postgres_fe.h"
                                 36                 :                : 
                                 37                 :                : #include "input.h"
                                 38                 :                : #include "tab-complete.h"
                                 39                 :                : 
                                 40                 :                : /* If we don't have this, we might as well forget about the whole thing: */
                                 41                 :                : #ifdef USE_READLINE
                                 42                 :                : 
                                 43                 :                : #include <ctype.h>
                                 44                 :                : #include <sys/stat.h>
                                 45                 :                : 
                                 46                 :                : #include "catalog/pg_am_d.h"
                                 47                 :                : #include "catalog/pg_class_d.h"
                                 48                 :                : #include "common.h"
                                 49                 :                : #include "common/keywords.h"
                                 50                 :                : #include "libpq-fe.h"
                                 51                 :                : #include "mb/pg_wchar.h"
                                 52                 :                : #include "pqexpbuffer.h"
                                 53                 :                : #include "settings.h"
                                 54                 :                : #include "stringutils.h"
                                 55                 :                : 
                                 56                 :                : /*
                                 57                 :                :  * Ancient versions of libedit provide filename_completion_function()
                                 58                 :                :  * instead of rl_filename_completion_function().  Likewise for
                                 59                 :                :  * [rl_]completion_matches().
                                 60                 :                :  */
                                 61                 :                : #ifndef HAVE_RL_FILENAME_COMPLETION_FUNCTION
                                 62                 :                : #define rl_filename_completion_function filename_completion_function
                                 63                 :                : #endif
                                 64                 :                : 
                                 65                 :                : #ifndef HAVE_RL_COMPLETION_MATCHES
                                 66                 :                : #define rl_completion_matches completion_matches
                                 67                 :                : #endif
                                 68                 :                : 
                                 69                 :                : /*
                                 70                 :                :  * Currently we assume that rl_filename_dequoting_function exists if
                                 71                 :                :  * rl_filename_quoting_function does.  If that proves not to be the case,
                                 72                 :                :  * we'd need to test for the former, or possibly both, in configure.
                                 73                 :                :  */
                                 74                 :                : #ifdef HAVE_RL_FILENAME_QUOTING_FUNCTION
                                 75                 :                : #define USE_FILENAME_QUOTING_FUNCTIONS 1
                                 76                 :                : #endif
                                 77                 :                : 
                                 78                 :                : /* word break characters */
                                 79                 :                : #define WORD_BREAKS     "\t\n@><=;|&() "
                                 80                 :                : 
                                 81                 :                : /*
                                 82                 :                :  * Since readline doesn't let us pass any state through to the tab completion
                                 83                 :                :  * callback, we have to use this global variable to let get_previous_words()
                                 84                 :                :  * get at the previous lines of the current command.  Ick.
                                 85                 :                :  */
                                 86                 :                : PQExpBuffer tab_completion_query_buf = NULL;
                                 87                 :                : 
                                 88                 :                : /*
                                 89                 :                :  * In some situations, the query to find out what names are available to
                                 90                 :                :  * complete with must vary depending on server version.  We handle this by
                                 91                 :                :  * storing a list of queries, each tagged with the minimum server version
                                 92                 :                :  * it will work for.  Each list must be stored in descending server version
                                 93                 :                :  * order, so that the first satisfactory query is the one to use.
                                 94                 :                :  *
                                 95                 :                :  * When the query string is otherwise constant, an array of VersionedQuery
                                 96                 :                :  * suffices.  Terminate the array with an entry having min_server_version = 0.
                                 97                 :                :  * That entry's query string can be a query that works in all supported older
                                 98                 :                :  * server versions, or NULL to give up and do no completion.
                                 99                 :                :  */
                                100                 :                : typedef struct VersionedQuery
                                101                 :                : {
                                102                 :                :     int         min_server_version;
                                103                 :                :     const char *query;
                                104                 :                : } VersionedQuery;
                                105                 :                : 
                                106                 :                : /*
                                107                 :                :  * This struct is used to define "schema queries", which are custom-built
                                108                 :                :  * to obtain possibly-schema-qualified names of database objects.  There is
                                109                 :                :  * enough similarity in the structure that we don't want to repeat it each
                                110                 :                :  * time.  So we put the components of each query into this struct and
                                111                 :                :  * assemble them with the common boilerplate in _complete_from_query().
                                112                 :                :  *
                                113                 :                :  * We also use this struct to define queries that use completion_ref_object,
                                114                 :                :  * which is some object related to the one(s) we want to get the names of
                                115                 :                :  * (for example, the table we want the indexes of).  In that usage the
                                116                 :                :  * objects we're completing might not have a schema of their own, but the
                                117                 :                :  * reference object almost always does (passed in completion_ref_schema).
                                118                 :                :  *
                                119                 :                :  * As with VersionedQuery, we can use an array of these if the query details
                                120                 :                :  * must vary across versions.
                                121                 :                :  */
                                122                 :                : typedef struct SchemaQuery
                                123                 :                : {
                                124                 :                :     /*
                                125                 :                :      * If not zero, minimum server version this struct applies to.  If not
                                126                 :                :      * zero, there should be a following struct with a smaller minimum server
                                127                 :                :      * version; use catname == NULL in the last entry if we should do nothing.
                                128                 :                :      */
                                129                 :                :     int         min_server_version;
                                130                 :                : 
                                131                 :                :     /*
                                132                 :                :      * Name of catalog or catalogs to be queried, with alias(es), eg.
                                133                 :                :      * "pg_catalog.pg_class c".  Note that "pg_namespace n" and/or
                                134                 :                :      * "pg_namespace nr" will be added automatically when needed.
                                135                 :                :      */
                                136                 :                :     const char *catname;
                                137                 :                : 
                                138                 :                :     /*
                                139                 :                :      * Selection condition --- only rows meeting this condition are candidates
                                140                 :                :      * to display.  If catname mentions multiple tables, include the necessary
                                141                 :                :      * join condition here.  For example, this might look like "c.relkind = "
                                142                 :                :      * CppAsString2(RELKIND_RELATION).  Write NULL (not an empty string) if
                                143                 :                :      * not needed.
                                144                 :                :      */
                                145                 :                :     const char *selcondition;
                                146                 :                : 
                                147                 :                :     /*
                                148                 :                :      * Visibility condition --- which rows are visible without schema
                                149                 :                :      * qualification?  For example, "pg_catalog.pg_table_is_visible(c.oid)".
                                150                 :                :      * NULL if not needed.
                                151                 :                :      */
                                152                 :                :     const char *viscondition;
                                153                 :                : 
                                154                 :                :     /*
                                155                 :                :      * Namespace --- name of field to join to pg_namespace.oid when there is
                                156                 :                :      * schema qualification.  For example, "c.relnamespace".  NULL if we don't
                                157                 :                :      * want to join to pg_namespace (then any schema part in the input word
                                158                 :                :      * will be ignored).
                                159                 :                :      */
                                160                 :                :     const char *namespace;
                                161                 :                : 
                                162                 :                :     /*
                                163                 :                :      * Result --- the base object name to return.  For example, "c.relname".
                                164                 :                :      */
                                165                 :                :     const char *result;
                                166                 :                : 
                                167                 :                :     /*
                                168                 :                :      * In some cases, it's difficult to keep the query from returning the same
                                169                 :                :      * object multiple times.  Specify use_distinct to filter out duplicates.
                                170                 :                :      */
                                171                 :                :     bool        use_distinct;
                                172                 :                : 
                                173                 :                :     /*
                                174                 :                :      * Additional literal strings (usually keywords) to be offered along with
                                175                 :                :      * the query results.  Provide a NULL-terminated array of constant
                                176                 :                :      * strings, or NULL if none.
                                177                 :                :      */
                                178                 :                :     const char *const *keywords;
                                179                 :                : 
                                180                 :                :     /*
                                181                 :                :      * If this query uses completion_ref_object/completion_ref_schema,
                                182                 :                :      * populate the remaining fields, else leave them NULL.  When using this
                                183                 :                :      * capability, catname must include the catalog that defines the
                                184                 :                :      * completion_ref_object, and selcondition must include the join condition
                                185                 :                :      * that connects it to the result's catalog.
                                186                 :                :      *
                                187                 :                :      * refname is the field that should be equated to completion_ref_object,
                                188                 :                :      * for example "cr.relname".
                                189                 :                :      */
                                190                 :                :     const char *refname;
                                191                 :                : 
                                192                 :                :     /*
                                193                 :                :      * Visibility condition to use when completion_ref_schema is not set.  For
                                194                 :                :      * example, "pg_catalog.pg_table_is_visible(cr.oid)".  NULL if not needed.
                                195                 :                :      */
                                196                 :                :     const char *refviscondition;
                                197                 :                : 
                                198                 :                :     /*
                                199                 :                :      * Name of field to join to pg_namespace.oid when completion_ref_schema is
                                200                 :                :      * set.  For example, "cr.relnamespace".  NULL if we don't want to
                                201                 :                :      * consider completion_ref_schema.
                                202                 :                :      */
                                203                 :                :     const char *refnamespace;
                                204                 :                : } SchemaQuery;
                                205                 :                : 
                                206                 :                : 
                                207                 :                : /* Store maximum number of records we want from database queries
                                208                 :                :  * (implemented via SELECT ... LIMIT xx).
                                209                 :                :  */
                                210                 :                : static int  completion_max_records;
                                211                 :                : 
                                212                 :                : /*
                                213                 :                :  * Communication variables set by psql_completion (mostly in COMPLETE_WITH_FOO
                                214                 :                :  * macros) and then used by the completion callback functions.  Ugly but there
                                215                 :                :  * is no better way.
                                216                 :                :  */
                                217                 :                : static char completion_last_char;   /* last char of input word */
                                218                 :                : static const char *completion_charp;    /* to pass a string */
                                219                 :                : static const char *const *completion_charpp;    /* to pass a list of strings */
                                220                 :                : static const VersionedQuery *completion_vquery; /* to pass a VersionedQuery */
                                221                 :                : static const SchemaQuery *completion_squery;    /* to pass a SchemaQuery */
                                222                 :                : static char *completion_ref_object; /* name of reference object */
                                223                 :                : static char *completion_ref_schema; /* schema name of reference object */
                                224                 :                : static bool completion_case_sensitive;  /* completion is case sensitive */
                                225                 :                : static bool completion_verbatim;    /* completion is verbatim */
                                226                 :                : static bool completion_force_quote; /* true to force-quote filenames */
                                227                 :                : 
                                228                 :                : /*
                                229                 :                :  * A few macros to ease typing. You can use these to complete the given
                                230                 :                :  * string with
                                231                 :                :  * 1) The result from a query you pass it. (Perhaps one of those below?)
                                232                 :                :  *    We support both simple and versioned queries.
                                233                 :                :  * 2) The result from a schema query you pass it.
                                234                 :                :  *    We support both simple and versioned schema queries.
                                235                 :                :  * 3) The items from a null-pointer-terminated list (with or without
                                236                 :                :  *    case-sensitive comparison); if the list is constant you can build it
                                237                 :                :  *    with COMPLETE_WITH() or COMPLETE_WITH_CS().  The QUERY_LIST and
                                238                 :                :  *    QUERY_PLUS forms combine such literal lists with a query result.
                                239                 :                :  * 4) The list of attributes of the given table (possibly schema-qualified).
                                240                 :                :  * 5) The list of arguments to the given function (possibly schema-qualified).
                                241                 :                :  *
                                242                 :                :  * The query is generally expected to return raw SQL identifiers; matching
                                243                 :                :  * to what the user typed is done in a quoting-aware fashion.  If what is
                                244                 :                :  * returned is not SQL identifiers, use one of the VERBATIM forms, in which
                                245                 :                :  * case the query results are matched to the user's text without double-quote
                                246                 :                :  * processing (so if quoting is needed, you must provide it in the query
                                247                 :                :  * results).
                                248                 :                :  */
                                249                 :                : #define COMPLETE_WITH_QUERY(query) \
                                250                 :                :     COMPLETE_WITH_QUERY_LIST(query, NULL)
                                251                 :                : 
                                252                 :                : #define COMPLETE_WITH_QUERY_LIST(query, list) \
                                253                 :                : do { \
                                254                 :                :     completion_charp = query; \
                                255                 :                :     completion_charpp = list; \
                                256                 :                :     completion_verbatim = false; \
                                257                 :                :     matches = rl_completion_matches(text, complete_from_query); \
                                258                 :                : } while (0)
                                259                 :                : 
                                260                 :                : #define COMPLETE_WITH_QUERY_PLUS(query, ...) \
                                261                 :                : do { \
                                262                 :                :     static const char *const list[] = { __VA_ARGS__, NULL }; \
                                263                 :                :     COMPLETE_WITH_QUERY_LIST(query, list); \
                                264                 :                : } while (0)
                                265                 :                : 
                                266                 :                : #define COMPLETE_WITH_QUERY_VERBATIM(query) \
                                267                 :                :     COMPLETE_WITH_QUERY_VERBATIM_LIST(query, NULL)
                                268                 :                : 
                                269                 :                : #define COMPLETE_WITH_QUERY_VERBATIM_LIST(query, list) \
                                270                 :                : do { \
                                271                 :                :     completion_charp = query; \
                                272                 :                :     completion_charpp = list; \
                                273                 :                :     completion_verbatim = true; \
                                274                 :                :     matches = rl_completion_matches(text, complete_from_query); \
                                275                 :                : } while (0)
                                276                 :                : 
                                277                 :                : #define COMPLETE_WITH_QUERY_VERBATIM_PLUS(query, ...) \
                                278                 :                : do { \
                                279                 :                :     static const char *const list[] = { __VA_ARGS__, NULL }; \
                                280                 :                :     COMPLETE_WITH_QUERY_VERBATIM_LIST(query, list); \
                                281                 :                : } while (0)
                                282                 :                : 
                                283                 :                : #define COMPLETE_WITH_VERSIONED_QUERY(query) \
                                284                 :                :     COMPLETE_WITH_VERSIONED_QUERY_LIST(query, NULL)
                                285                 :                : 
                                286                 :                : #define COMPLETE_WITH_VERSIONED_QUERY_LIST(query, list) \
                                287                 :                : do { \
                                288                 :                :     completion_vquery = query; \
                                289                 :                :     completion_charpp = list; \
                                290                 :                :     completion_verbatim = false; \
                                291                 :                :     matches = rl_completion_matches(text, complete_from_versioned_query); \
                                292                 :                : } while (0)
                                293                 :                : 
                                294                 :                : #define COMPLETE_WITH_VERSIONED_QUERY_PLUS(query, ...) \
                                295                 :                : do { \
                                296                 :                :     static const char *const list[] = { __VA_ARGS__, NULL }; \
                                297                 :                :     COMPLETE_WITH_VERSIONED_QUERY_LIST(query, list); \
                                298                 :                : } while (0)
                                299                 :                : 
                                300                 :                : #define COMPLETE_WITH_SCHEMA_QUERY(query) \
                                301                 :                :     COMPLETE_WITH_SCHEMA_QUERY_LIST(query, NULL)
                                302                 :                : 
                                303                 :                : #define COMPLETE_WITH_SCHEMA_QUERY_LIST(query, list) \
                                304                 :                : do { \
                                305                 :                :     completion_squery = &(query); \
                                306                 :                :     completion_charpp = list; \
                                307                 :                :     completion_verbatim = false; \
                                308                 :                :     matches = rl_completion_matches(text, complete_from_schema_query); \
                                309                 :                : } while (0)
                                310                 :                : 
                                311                 :                : #define COMPLETE_WITH_SCHEMA_QUERY_PLUS(query, ...) \
                                312                 :                : do { \
                                313                 :                :     static const char *const list[] = { __VA_ARGS__, NULL }; \
                                314                 :                :     COMPLETE_WITH_SCHEMA_QUERY_LIST(query, list); \
                                315                 :                : } while (0)
                                316                 :                : 
                                317                 :                : #define COMPLETE_WITH_SCHEMA_QUERY_VERBATIM(query) \
                                318                 :                : do { \
                                319                 :                :     completion_squery = &(query); \
                                320                 :                :     completion_charpp = NULL; \
                                321                 :                :     completion_verbatim = true; \
                                322                 :                :     matches = rl_completion_matches(text, complete_from_schema_query); \
                                323                 :                : } while (0)
                                324                 :                : 
                                325                 :                : #define COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(query) \
                                326                 :                :     COMPLETE_WITH_VERSIONED_SCHEMA_QUERY_LIST(query, NULL)
                                327                 :                : 
                                328                 :                : #define COMPLETE_WITH_VERSIONED_SCHEMA_QUERY_LIST(query, list) \
                                329                 :                : do { \
                                330                 :                :     completion_squery = query; \
                                331                 :                :     completion_charpp = list; \
                                332                 :                :     completion_verbatim = false; \
                                333                 :                :     matches = rl_completion_matches(text, complete_from_versioned_schema_query); \
                                334                 :                : } while (0)
                                335                 :                : 
                                336                 :                : #define COMPLETE_WITH_VERSIONED_SCHEMA_QUERY_PLUS(query, ...) \
                                337                 :                : do { \
                                338                 :                :     static const char *const list[] = { __VA_ARGS__, NULL }; \
                                339                 :                :     COMPLETE_WITH_VERSIONED_SCHEMA_QUERY_LIST(query, list); \
                                340                 :                : } while (0)
                                341                 :                : 
                                342                 :                : /*
                                343                 :                :  * Caution: COMPLETE_WITH_CONST is not for general-purpose use; you probably
                                344                 :                :  * want COMPLETE_WITH() with one element, instead.
                                345                 :                :  */
                                346                 :                : #define COMPLETE_WITH_CONST(cs, con) \
                                347                 :                : do { \
                                348                 :                :     completion_case_sensitive = (cs); \
                                349                 :                :     completion_charp = (con); \
                                350                 :                :     matches = rl_completion_matches(text, complete_from_const); \
                                351                 :                : } while (0)
                                352                 :                : 
                                353                 :                : #define COMPLETE_WITH_LIST_INT(cs, list) \
                                354                 :                : do { \
                                355                 :                :     completion_case_sensitive = (cs); \
                                356                 :                :     completion_charpp = (list); \
                                357                 :                :     matches = rl_completion_matches(text, complete_from_list); \
                                358                 :                : } while (0)
                                359                 :                : 
                                360                 :                : #define COMPLETE_WITH_LIST(list) COMPLETE_WITH_LIST_INT(false, list)
                                361                 :                : #define COMPLETE_WITH_LIST_CS(list) COMPLETE_WITH_LIST_INT(true, list)
                                362                 :                : 
                                363                 :                : #define COMPLETE_WITH(...) \
                                364                 :                : do { \
                                365                 :                :     static const char *const list[] = { __VA_ARGS__, NULL }; \
                                366                 :                :     COMPLETE_WITH_LIST(list); \
                                367                 :                : } while (0)
                                368                 :                : 
                                369                 :                : #define COMPLETE_WITH_CS(...) \
                                370                 :                : do { \
                                371                 :                :     static const char *const list[] = { __VA_ARGS__, NULL }; \
                                372                 :                :     COMPLETE_WITH_LIST_CS(list); \
                                373                 :                : } while (0)
                                374                 :                : 
                                375                 :                : #define COMPLETE_WITH_ATTR(relation) \
                                376                 :                :     COMPLETE_WITH_ATTR_LIST(relation, NULL)
                                377                 :                : 
                                378                 :                : #define COMPLETE_WITH_ATTR_LIST(relation, list) \
                                379                 :                : do { \
                                380                 :                :     set_completion_reference(relation); \
                                381                 :                :     completion_squery = &(Query_for_list_of_attributes); \
                                382                 :                :     completion_charpp = list; \
                                383                 :                :     completion_verbatim = false; \
                                384                 :                :     matches = rl_completion_matches(text, complete_from_schema_query); \
                                385                 :                : } while (0)
                                386                 :                : 
                                387                 :                : #define COMPLETE_WITH_ATTR_PLUS(relation, ...) \
                                388                 :                : do { \
                                389                 :                :     static const char *const list[] = { __VA_ARGS__, NULL }; \
                                390                 :                :     COMPLETE_WITH_ATTR_LIST(relation, list); \
                                391                 :                : } while (0)
                                392                 :                : 
                                393                 :                : /*
                                394                 :                :  * libedit will typically include the literal's leading single quote in
                                395                 :                :  * "text", while readline will not.  Adapt our offered strings to fit.
                                396                 :                :  * But include a quote if there's not one just before "text", to get the
                                397                 :                :  * user off to the right start.
                                398                 :                :  */
                                399                 :                : #define COMPLETE_WITH_ENUM_VALUE(type) \
                                400                 :                : do { \
                                401                 :                :     set_completion_reference(type); \
                                402                 :                :     if (text[0] == '\'' || \
                                403                 :                :         start == 0 || rl_line_buffer[start - 1] != '\'') \
                                404                 :                :         completion_squery = &(Query_for_list_of_enum_values_quoted); \
                                405                 :                :     else \
                                406                 :                :         completion_squery = &(Query_for_list_of_enum_values_unquoted); \
                                407                 :                :     completion_charpp = NULL; \
                                408                 :                :     completion_verbatim = true; \
                                409                 :                :     matches = rl_completion_matches(text, complete_from_schema_query); \
                                410                 :                : } while (0)
                                411                 :                : 
                                412                 :                : /*
                                413                 :                :  * Timezone completion is mostly like enum label completion, but we work
                                414                 :                :  * a little harder since this is a more common use-case.
                                415                 :                :  */
                                416                 :                : #define COMPLETE_WITH_TIMEZONE_NAME() \
                                417                 :                : do { \
                                418                 :                :     static const char *const list[] = { "DEFAULT", NULL }; \
                                419                 :                :     if (text[0] == '\'') \
                                420                 :                :         completion_charp = Query_for_list_of_timezone_names_quoted_in; \
                                421                 :                :     else if (start == 0 || rl_line_buffer[start - 1] != '\'') \
                                422                 :                :         completion_charp = Query_for_list_of_timezone_names_quoted_out; \
                                423                 :                :     else \
                                424                 :                :         completion_charp = Query_for_list_of_timezone_names_unquoted; \
                                425                 :                :     completion_charpp = list;                             \
                                426                 :                :     completion_verbatim = true; \
                                427                 :                :     matches = rl_completion_matches(text, complete_from_query); \
                                428                 :                : } while (0)
                                429                 :                : 
                                430                 :                : #define COMPLETE_WITH_FUNCTION_ARG(function) \
                                431                 :                : do { \
                                432                 :                :     set_completion_reference(function); \
                                433                 :                :     completion_squery = &(Query_for_list_of_arguments); \
                                434                 :                :     completion_charpp = NULL; \
                                435                 :                :     completion_verbatim = true; \
                                436                 :                :     matches = rl_completion_matches(text, complete_from_schema_query); \
                                437                 :                : } while (0)
                                438                 :                : 
                                439                 :                : /*
                                440                 :                :  * Assembly instructions for schema queries
                                441                 :                :  *
                                442                 :                :  * Note that toast tables are not included in those queries to avoid
                                443                 :                :  * unnecessary bloat in the completions generated.
                                444                 :                :  */
                                445                 :                : 
                                446                 :                : static const SchemaQuery Query_for_constraint_of_table = {
                                447                 :                :     .catname = "pg_catalog.pg_constraint con, pg_catalog.pg_class c1",
                                448                 :                :     .selcondition = "con.conrelid=c1.oid",
                                449                 :                :     .result = "con.conname",
                                450                 :                :     .refname = "c1.relname",
                                451                 :                :     .refviscondition = "pg_catalog.pg_table_is_visible(c1.oid)",
                                452                 :                :     .refnamespace = "c1.relnamespace",
                                453                 :                : };
                                454                 :                : 
                                455                 :                : static const SchemaQuery Query_for_constraint_of_table_not_validated = {
                                456                 :                :     .catname = "pg_catalog.pg_constraint con, pg_catalog.pg_class c1",
                                457                 :                :     .selcondition = "con.conrelid=c1.oid and not con.convalidated",
                                458                 :                :     .result = "con.conname",
                                459                 :                :     .refname = "c1.relname",
                                460                 :                :     .refviscondition = "pg_catalog.pg_table_is_visible(c1.oid)",
                                461                 :                :     .refnamespace = "c1.relnamespace",
                                462                 :                : };
                                463                 :                : 
                                464                 :                : static const SchemaQuery Query_for_constraint_of_type = {
                                465                 :                :     .catname = "pg_catalog.pg_constraint con, pg_catalog.pg_type t",
                                466                 :                :     .selcondition = "con.contypid=t.oid",
                                467                 :                :     .result = "con.conname",
                                468                 :                :     .refname = "t.typname",
                                469                 :                :     .refviscondition = "pg_catalog.pg_type_is_visible(t.oid)",
                                470                 :                :     .refnamespace = "t.typnamespace",
                                471                 :                : };
                                472                 :                : 
                                473                 :                : static const SchemaQuery Query_for_index_of_table = {
                                474                 :                :     .catname = "pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_index i",
                                475                 :                :     .selcondition = "c1.oid=i.indrelid and i.indexrelid=c2.oid",
                                476                 :                :     .result = "c2.relname",
                                477                 :                :     .refname = "c1.relname",
                                478                 :                :     .refviscondition = "pg_catalog.pg_table_is_visible(c1.oid)",
                                479                 :                :     .refnamespace = "c1.relnamespace",
                                480                 :                : };
                                481                 :                : 
                                482                 :                : static const SchemaQuery Query_for_unique_index_of_table = {
                                483                 :                :     .catname = "pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_index i",
                                484                 :                :     .selcondition = "c1.oid=i.indrelid and i.indexrelid=c2.oid and i.indisunique",
                                485                 :                :     .result = "c2.relname",
                                486                 :                :     .refname = "c1.relname",
                                487                 :                :     .refviscondition = "pg_catalog.pg_table_is_visible(c1.oid)",
                                488                 :                :     .refnamespace = "c1.relnamespace",
                                489                 :                : };
                                490                 :                : 
                                491                 :                : static const SchemaQuery Query_for_list_of_aggregates[] = {
                                492                 :                :     {
                                493                 :                :         .min_server_version = 110000,
                                494                 :                :         .catname = "pg_catalog.pg_proc p",
                                495                 :                :         .selcondition = "p.prokind = 'a'",
                                496                 :                :         .viscondition = "pg_catalog.pg_function_is_visible(p.oid)",
                                497                 :                :         .namespace = "p.pronamespace",
                                498                 :                :         .result = "p.proname",
                                499                 :                :     },
                                500                 :                :     {
                                501                 :                :         .catname = "pg_catalog.pg_proc p",
                                502                 :                :         .selcondition = "p.proisagg",
                                503                 :                :         .viscondition = "pg_catalog.pg_function_is_visible(p.oid)",
                                504                 :                :         .namespace = "p.pronamespace",
                                505                 :                :         .result = "p.proname",
                                506                 :                :     }
                                507                 :                : };
                                508                 :                : 
                                509                 :                : static const SchemaQuery Query_for_list_of_arguments = {
                                510                 :                :     .catname = "pg_catalog.pg_proc p",
                                511                 :                :     .result = "pg_catalog.oidvectortypes(p.proargtypes)||')'",
                                512                 :                :     .refname = "p.proname",
                                513                 :                :     .refviscondition = "pg_catalog.pg_function_is_visible(p.oid)",
                                514                 :                :     .refnamespace = "p.pronamespace",
                                515                 :                : };
                                516                 :                : 
                                517                 :                : static const SchemaQuery Query_for_list_of_attributes = {
                                518                 :                :     .catname = "pg_catalog.pg_attribute a, pg_catalog.pg_class c",
                                519                 :                :     .selcondition = "c.oid = a.attrelid and a.attnum > 0 and not a.attisdropped",
                                520                 :                :     .result = "a.attname",
                                521                 :                :     .refname = "c.relname",
                                522                 :                :     .refviscondition = "pg_catalog.pg_table_is_visible(c.oid)",
                                523                 :                :     .refnamespace = "c.relnamespace",
                                524                 :                : };
                                525                 :                : 
                                526                 :                : static const SchemaQuery Query_for_list_of_attribute_numbers = {
                                527                 :                :     .catname = "pg_catalog.pg_attribute a, pg_catalog.pg_class c",
                                528                 :                :     .selcondition = "c.oid = a.attrelid and a.attnum > 0 and not a.attisdropped",
                                529                 :                :     .result = "a.attnum::pg_catalog.text",
                                530                 :                :     .refname = "c.relname",
                                531                 :                :     .refviscondition = "pg_catalog.pg_table_is_visible(c.oid)",
                                532                 :                :     .refnamespace = "c.relnamespace",
                                533                 :                : };
                                534                 :                : 
                                535                 :                : static const char *const Keywords_for_list_of_datatypes[] = {
                                536                 :                :     "bigint",
                                537                 :                :     "boolean",
                                538                 :                :     "character",
                                539                 :                :     "double precision",
                                540                 :                :     "integer",
                                541                 :                :     "real",
                                542                 :                :     "smallint",
                                543                 :                : 
                                544                 :                :     /*
                                545                 :                :      * Note: currently there's no value in offering the following multiword
                                546                 :                :      * type names, because tab completion cannot succeed for them: we can't
                                547                 :                :      * disambiguate until somewhere in the second word, at which point we
                                548                 :                :      * won't have the first word as context.  ("double precision" does work,
                                549                 :                :      * as long as no other type name begins with "double".)  Leave them out to
                                550                 :                :      * encourage users to use the PG-specific aliases, which we can complete.
                                551                 :                :      */
                                552                 :                : #ifdef NOT_USED
                                553                 :                :     "bit varying",
                                554                 :                :     "character varying",
                                555                 :                :     "time with time zone",
                                556                 :                :     "time without time zone",
                                557                 :                :     "timestamp with time zone",
                                558                 :                :     "timestamp without time zone",
                                559                 :                : #endif
                                560                 :                :     NULL
                                561                 :                : };
                                562                 :                : 
                                563                 :                : static const SchemaQuery Query_for_list_of_datatypes = {
                                564                 :                :     .catname = "pg_catalog.pg_type t",
                                565                 :                :     /* selcondition --- ignore table rowtypes and array types */
                                566                 :                :     .selcondition = "(t.typrelid = 0 "
                                567                 :                :     " OR (SELECT c.relkind = " CppAsString2(RELKIND_COMPOSITE_TYPE)
                                568                 :                :     "     FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid)) "
                                569                 :                :     "AND t.typname !~ '^_'",
                                570                 :                :     .viscondition = "pg_catalog.pg_type_is_visible(t.oid)",
                                571                 :                :     .namespace = "t.typnamespace",
                                572                 :                :     .result = "t.typname",
                                573                 :                :     .keywords = Keywords_for_list_of_datatypes,
                                574                 :                : };
                                575                 :                : 
                                576                 :                : static const SchemaQuery Query_for_list_of_composite_datatypes = {
                                577                 :                :     .catname = "pg_catalog.pg_type t",
                                578                 :                :     /* selcondition --- only get composite types */
                                579                 :                :     .selcondition = "(SELECT c.relkind = " CppAsString2(RELKIND_COMPOSITE_TYPE)
                                580                 :                :     " FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid) "
                                581                 :                :     "AND t.typname !~ '^_'",
                                582                 :                :     .viscondition = "pg_catalog.pg_type_is_visible(t.oid)",
                                583                 :                :     .namespace = "t.typnamespace",
                                584                 :                :     .result = "t.typname",
                                585                 :                : };
                                586                 :                : 
                                587                 :                : static const SchemaQuery Query_for_list_of_domains = {
                                588                 :                :     .catname = "pg_catalog.pg_type t",
                                589                 :                :     .selcondition = "t.typtype = 'd'",
                                590                 :                :     .viscondition = "pg_catalog.pg_type_is_visible(t.oid)",
                                591                 :                :     .namespace = "t.typnamespace",
                                592                 :                :     .result = "t.typname",
                                593                 :                : };
                                594                 :                : 
                                595                 :                : static const SchemaQuery Query_for_list_of_enum_values_quoted = {
                                596                 :                :     .catname = "pg_catalog.pg_enum e, pg_catalog.pg_type t",
                                597                 :                :     .selcondition = "t.oid = e.enumtypid",
                                598                 :                :     .result = "pg_catalog.quote_literal(enumlabel)",
                                599                 :                :     .refname = "t.typname",
                                600                 :                :     .refviscondition = "pg_catalog.pg_type_is_visible(t.oid)",
                                601                 :                :     .refnamespace = "t.typnamespace",
                                602                 :                : };
                                603                 :                : 
                                604                 :                : static const SchemaQuery Query_for_list_of_enum_values_unquoted = {
                                605                 :                :     .catname = "pg_catalog.pg_enum e, pg_catalog.pg_type t",
                                606                 :                :     .selcondition = "t.oid = e.enumtypid",
                                607                 :                :     .result = "e.enumlabel",
                                608                 :                :     .refname = "t.typname",
                                609                 :                :     .refviscondition = "pg_catalog.pg_type_is_visible(t.oid)",
                                610                 :                :     .refnamespace = "t.typnamespace",
                                611                 :                : };
                                612                 :                : 
                                613                 :                : /* Note: this intentionally accepts aggregates as well as plain functions */
                                614                 :                : static const SchemaQuery Query_for_list_of_functions[] = {
                                615                 :                :     {
                                616                 :                :         .min_server_version = 110000,
                                617                 :                :         .catname = "pg_catalog.pg_proc p",
                                618                 :                :         .selcondition = "p.prokind != 'p'",
                                619                 :                :         .viscondition = "pg_catalog.pg_function_is_visible(p.oid)",
                                620                 :                :         .namespace = "p.pronamespace",
                                621                 :                :         .result = "p.proname",
                                622                 :                :     },
                                623                 :                :     {
                                624                 :                :         .catname = "pg_catalog.pg_proc p",
                                625                 :                :         .viscondition = "pg_catalog.pg_function_is_visible(p.oid)",
                                626                 :                :         .namespace = "p.pronamespace",
                                627                 :                :         .result = "p.proname",
                                628                 :                :     }
                                629                 :                : };
                                630                 :                : 
                                631                 :                : static const SchemaQuery Query_for_list_of_procedures[] = {
                                632                 :                :     {
                                633                 :                :         .min_server_version = 110000,
                                634                 :                :         .catname = "pg_catalog.pg_proc p",
                                635                 :                :         .selcondition = "p.prokind = 'p'",
                                636                 :                :         .viscondition = "pg_catalog.pg_function_is_visible(p.oid)",
                                637                 :                :         .namespace = "p.pronamespace",
                                638                 :                :         .result = "p.proname",
                                639                 :                :     },
                                640                 :                :     {
                                641                 :                :         /* not supported in older versions */
                                642                 :                :         .catname = NULL,
                                643                 :                :     }
                                644                 :                : };
                                645                 :                : 
                                646                 :                : static const SchemaQuery Query_for_list_of_routines = {
                                647                 :                :     .catname = "pg_catalog.pg_proc p",
                                648                 :                :     .viscondition = "pg_catalog.pg_function_is_visible(p.oid)",
                                649                 :                :     .namespace = "p.pronamespace",
                                650                 :                :     .result = "p.proname",
                                651                 :                : };
                                652                 :                : 
                                653                 :                : static const SchemaQuery Query_for_list_of_sequences = {
                                654                 :                :     .catname = "pg_catalog.pg_class c",
                                655                 :                :     .selcondition = "c.relkind IN (" CppAsString2(RELKIND_SEQUENCE) ")",
                                656                 :                :     .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
                                657                 :                :     .namespace = "c.relnamespace",
                                658                 :                :     .result = "c.relname",
                                659                 :                : };
                                660                 :                : 
                                661                 :                : static const SchemaQuery Query_for_list_of_foreign_tables = {
                                662                 :                :     .catname = "pg_catalog.pg_class c",
                                663                 :                :     .selcondition = "c.relkind IN (" CppAsString2(RELKIND_FOREIGN_TABLE) ")",
                                664                 :                :     .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
                                665                 :                :     .namespace = "c.relnamespace",
                                666                 :                :     .result = "c.relname",
                                667                 :                : };
                                668                 :                : 
                                669                 :                : static const SchemaQuery Query_for_list_of_tables = {
                                670                 :                :     .catname = "pg_catalog.pg_class c",
                                671                 :                :     .selcondition =
                                672                 :                :     "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
                                673                 :                :     CppAsString2(RELKIND_PARTITIONED_TABLE) ")",
                                674                 :                :     .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
                                675                 :                :     .namespace = "c.relnamespace",
                                676                 :                :     .result = "c.relname",
                                677                 :                : };
                                678                 :                : 
                                679                 :                : static const SchemaQuery Query_for_list_of_partitioned_tables = {
                                680                 :                :     .catname = "pg_catalog.pg_class c",
                                681                 :                :     .selcondition = "c.relkind IN (" CppAsString2(RELKIND_PARTITIONED_TABLE) ")",
                                682                 :                :     .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
                                683                 :                :     .namespace = "c.relnamespace",
                                684                 :                :     .result = "c.relname",
                                685                 :                : };
                                686                 :                : 
                                687                 :                : static const SchemaQuery Query_for_list_of_tables_for_constraint = {
                                688                 :                :     .catname = "pg_catalog.pg_class c, pg_catalog.pg_constraint con",
                                689                 :                :     .selcondition = "c.oid=con.conrelid and c.relkind IN ("
                                690                 :                :     CppAsString2(RELKIND_RELATION) ", "
                                691                 :                :     CppAsString2(RELKIND_PARTITIONED_TABLE) ")",
                                692                 :                :     .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
                                693                 :                :     .namespace = "c.relnamespace",
                                694                 :                :     .result = "c.relname",
                                695                 :                :     .use_distinct = true,
                                696                 :                :     .refname = "con.conname",
                                697                 :                : };
                                698                 :                : 
                                699                 :                : static const SchemaQuery Query_for_list_of_tables_for_policy = {
                                700                 :                :     .catname = "pg_catalog.pg_class c, pg_catalog.pg_policy p",
                                701                 :                :     .selcondition = "c.oid=p.polrelid",
                                702                 :                :     .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
                                703                 :                :     .namespace = "c.relnamespace",
                                704                 :                :     .result = "c.relname",
                                705                 :                :     .use_distinct = true,
                                706                 :                :     .refname = "p.polname",
                                707                 :                : };
                                708                 :                : 
                                709                 :                : static const SchemaQuery Query_for_list_of_tables_for_rule = {
                                710                 :                :     .catname = "pg_catalog.pg_class c, pg_catalog.pg_rewrite r",
                                711                 :                :     .selcondition = "c.oid=r.ev_class",
                                712                 :                :     .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
                                713                 :                :     .namespace = "c.relnamespace",
                                714                 :                :     .result = "c.relname",
                                715                 :                :     .use_distinct = true,
                                716                 :                :     .refname = "r.rulename",
                                717                 :                : };
                                718                 :                : 
                                719                 :                : static const SchemaQuery Query_for_list_of_tables_for_trigger = {
                                720                 :                :     .catname = "pg_catalog.pg_class c, pg_catalog.pg_trigger t",
                                721                 :                :     .selcondition = "c.oid=t.tgrelid",
                                722                 :                :     .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
                                723                 :                :     .namespace = "c.relnamespace",
                                724                 :                :     .result = "c.relname",
                                725                 :                :     .use_distinct = true,
                                726                 :                :     .refname = "t.tgname",
                                727                 :                : };
                                728                 :                : 
                                729                 :                : static const SchemaQuery Query_for_list_of_ts_configurations = {
                                730                 :                :     .catname = "pg_catalog.pg_ts_config c",
                                731                 :                :     .viscondition = "pg_catalog.pg_ts_config_is_visible(c.oid)",
                                732                 :                :     .namespace = "c.cfgnamespace",
                                733                 :                :     .result = "c.cfgname",
                                734                 :                : };
                                735                 :                : 
                                736                 :                : static const SchemaQuery Query_for_list_of_ts_dictionaries = {
                                737                 :                :     .catname = "pg_catalog.pg_ts_dict d",
                                738                 :                :     .viscondition = "pg_catalog.pg_ts_dict_is_visible(d.oid)",
                                739                 :                :     .namespace = "d.dictnamespace",
                                740                 :                :     .result = "d.dictname",
                                741                 :                : };
                                742                 :                : 
                                743                 :                : static const SchemaQuery Query_for_list_of_ts_parsers = {
                                744                 :                :     .catname = "pg_catalog.pg_ts_parser p",
                                745                 :                :     .viscondition = "pg_catalog.pg_ts_parser_is_visible(p.oid)",
                                746                 :                :     .namespace = "p.prsnamespace",
                                747                 :                :     .result = "p.prsname",
                                748                 :                : };
                                749                 :                : 
                                750                 :                : static const SchemaQuery Query_for_list_of_ts_templates = {
                                751                 :                :     .catname = "pg_catalog.pg_ts_template t",
                                752                 :                :     .viscondition = "pg_catalog.pg_ts_template_is_visible(t.oid)",
                                753                 :                :     .namespace = "t.tmplnamespace",
                                754                 :                :     .result = "t.tmplname",
                                755                 :                : };
                                756                 :                : 
                                757                 :                : static const SchemaQuery Query_for_list_of_views = {
                                758                 :                :     .catname = "pg_catalog.pg_class c",
                                759                 :                :     .selcondition = "c.relkind IN (" CppAsString2(RELKIND_VIEW) ")",
                                760                 :                :     .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
                                761                 :                :     .namespace = "c.relnamespace",
                                762                 :                :     .result = "c.relname",
                                763                 :                : };
                                764                 :                : 
                                765                 :                : static const SchemaQuery Query_for_list_of_matviews = {
                                766                 :                :     .catname = "pg_catalog.pg_class c",
                                767                 :                :     .selcondition = "c.relkind IN (" CppAsString2(RELKIND_MATVIEW) ")",
                                768                 :                :     .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
                                769                 :                :     .namespace = "c.relnamespace",
                                770                 :                :     .result = "c.relname",
                                771                 :                : };
                                772                 :                : 
                                773                 :                : static const SchemaQuery Query_for_list_of_indexes = {
                                774                 :                :     .catname = "pg_catalog.pg_class c",
                                775                 :                :     .selcondition =
                                776                 :                :     "c.relkind IN (" CppAsString2(RELKIND_INDEX) ", "
                                777                 :                :     CppAsString2(RELKIND_PARTITIONED_INDEX) ")",
                                778                 :                :     .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
                                779                 :                :     .namespace = "c.relnamespace",
                                780                 :                :     .result = "c.relname",
                                781                 :                : };
                                782                 :                : 
                                783                 :                : static const SchemaQuery Query_for_list_of_partitioned_indexes = {
                                784                 :                :     .catname = "pg_catalog.pg_class c",
                                785                 :                :     .selcondition = "c.relkind = " CppAsString2(RELKIND_PARTITIONED_INDEX),
                                786                 :                :     .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
                                787                 :                :     .namespace = "c.relnamespace",
                                788                 :                :     .result = "c.relname",
                                789                 :                : };
                                790                 :                : 
                                791                 :                : 
                                792                 :                : /* All relations */
                                793                 :                : static const SchemaQuery Query_for_list_of_relations = {
                                794                 :                :     .catname = "pg_catalog.pg_class c",
                                795                 :                :     .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
                                796                 :                :     .namespace = "c.relnamespace",
                                797                 :                :     .result = "c.relname",
                                798                 :                : };
                                799                 :                : 
                                800                 :                : /* partitioned relations */
                                801                 :                : static const SchemaQuery Query_for_list_of_partitioned_relations = {
                                802                 :                :     .catname = "pg_catalog.pg_class c",
                                803                 :                :     .selcondition = "c.relkind IN (" CppAsString2(RELKIND_PARTITIONED_TABLE)
                                804                 :                :     ", " CppAsString2(RELKIND_PARTITIONED_INDEX) ")",
                                805                 :                :     .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
                                806                 :                :     .namespace = "c.relnamespace",
                                807                 :                :     .result = "c.relname",
                                808                 :                : };
                                809                 :                : 
                                810                 :                : static const SchemaQuery Query_for_list_of_operator_families = {
                                811                 :                :     .catname = "pg_catalog.pg_opfamily c",
                                812                 :                :     .viscondition = "pg_catalog.pg_opfamily_is_visible(c.oid)",
                                813                 :                :     .namespace = "c.opfnamespace",
                                814                 :                :     .result = "c.opfname",
                                815                 :                : };
                                816                 :                : 
                                817                 :                : /* Relations supporting INSERT, UPDATE or DELETE */
                                818                 :                : static const SchemaQuery Query_for_list_of_updatables = {
                                819                 :                :     .catname = "pg_catalog.pg_class c",
                                820                 :                :     .selcondition =
                                821                 :                :     "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
                                822                 :                :     CppAsString2(RELKIND_FOREIGN_TABLE) ", "
                                823                 :                :     CppAsString2(RELKIND_VIEW) ", "
                                824                 :                :     CppAsString2(RELKIND_PARTITIONED_TABLE) ")",
                                825                 :                :     .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
                                826                 :                :     .namespace = "c.relnamespace",
                                827                 :                :     .result = "c.relname",
                                828                 :                : };
                                829                 :                : 
                                830                 :                : /* Relations supporting MERGE */
                                831                 :                : static const SchemaQuery Query_for_list_of_mergetargets = {
                                832                 :                :     .catname = "pg_catalog.pg_class c",
                                833                 :                :     .selcondition =
                                834                 :                :     "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
                                835                 :                :     CppAsString2(RELKIND_VIEW) ", "
                                836                 :                :     CppAsString2(RELKIND_PARTITIONED_TABLE) ") ",
                                837                 :                :     .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
                                838                 :                :     .namespace = "c.relnamespace",
                                839                 :                :     .result = "c.relname",
                                840                 :                : };
                                841                 :                : 
                                842                 :                : /* Relations supporting SELECT */
                                843                 :                : static const SchemaQuery Query_for_list_of_selectables = {
                                844                 :                :     .catname = "pg_catalog.pg_class c",
                                845                 :                :     .selcondition =
                                846                 :                :     "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
                                847                 :                :     CppAsString2(RELKIND_SEQUENCE) ", "
                                848                 :                :     CppAsString2(RELKIND_VIEW) ", "
                                849                 :                :     CppAsString2(RELKIND_MATVIEW) ", "
                                850                 :                :     CppAsString2(RELKIND_FOREIGN_TABLE) ", "
                                851                 :                :     CppAsString2(RELKIND_PARTITIONED_TABLE) ")",
                                852                 :                :     .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
                                853                 :                :     .namespace = "c.relnamespace",
                                854                 :                :     .result = "c.relname",
                                855                 :                : };
                                856                 :                : 
                                857                 :                : /* Relations supporting TRUNCATE */
                                858                 :                : static const SchemaQuery Query_for_list_of_truncatables = {
                                859                 :                :     .catname = "pg_catalog.pg_class c",
                                860                 :                :     .selcondition =
                                861                 :                :     "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
                                862                 :                :     CppAsString2(RELKIND_FOREIGN_TABLE) ", "
                                863                 :                :     CppAsString2(RELKIND_PARTITIONED_TABLE) ")",
                                864                 :                :     .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
                                865                 :                :     .namespace = "c.relnamespace",
                                866                 :                :     .result = "c.relname",
                                867                 :                : };
                                868                 :                : 
                                869                 :                : /* Relations supporting GRANT are currently same as those supporting SELECT */
                                870                 :                : #define Query_for_list_of_grantables Query_for_list_of_selectables
                                871                 :                : 
                                872                 :                : /* Relations supporting ANALYZE */
                                873                 :                : static const SchemaQuery Query_for_list_of_analyzables = {
                                874                 :                :     .catname = "pg_catalog.pg_class c",
                                875                 :                :     .selcondition =
                                876                 :                :     "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
                                877                 :                :     CppAsString2(RELKIND_PARTITIONED_TABLE) ", "
                                878                 :                :     CppAsString2(RELKIND_MATVIEW) ", "
                                879                 :                :     CppAsString2(RELKIND_FOREIGN_TABLE) ")",
                                880                 :                :     .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
                                881                 :                :     .namespace = "c.relnamespace",
                                882                 :                :     .result = "c.relname",
                                883                 :                : };
                                884                 :                : 
                                885                 :                : /* Relations supporting index creation */
                                886                 :                : static const SchemaQuery Query_for_list_of_indexables = {
                                887                 :                :     .catname = "pg_catalog.pg_class c",
                                888                 :                :     .selcondition =
                                889                 :                :     "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
                                890                 :                :     CppAsString2(RELKIND_PARTITIONED_TABLE) ", "
                                891                 :                :     CppAsString2(RELKIND_MATVIEW) ")",
                                892                 :                :     .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
                                893                 :                :     .namespace = "c.relnamespace",
                                894                 :                :     .result = "c.relname",
                                895                 :                : };
                                896                 :                : 
                                897                 :                : /*
                                898                 :                :  * Relations supporting VACUUM are currently same as those supporting
                                899                 :                :  * indexing.
                                900                 :                :  */
                                901                 :                : #define Query_for_list_of_vacuumables Query_for_list_of_indexables
                                902                 :                : 
                                903                 :                : /* Relations supporting CLUSTER */
                                904                 :                : static const SchemaQuery Query_for_list_of_clusterables = {
                                905                 :                :     .catname = "pg_catalog.pg_class c",
                                906                 :                :     .selcondition =
                                907                 :                :     "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
                                908                 :                :     CppAsString2(RELKIND_PARTITIONED_TABLE) ", "
                                909                 :                :     CppAsString2(RELKIND_MATVIEW) ")",
                                910                 :                :     .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
                                911                 :                :     .namespace = "c.relnamespace",
                                912                 :                :     .result = "c.relname",
                                913                 :                : };
                                914                 :                : 
                                915                 :                : static const SchemaQuery Query_for_list_of_constraints_with_schema = {
                                916                 :                :     .catname = "pg_catalog.pg_constraint c",
                                917                 :                :     .selcondition = "c.conrelid <> 0",
                                918                 :                :     .namespace = "c.connamespace",
                                919                 :                :     .result = "c.conname",
                                920                 :                : };
                                921                 :                : 
                                922                 :                : static const SchemaQuery Query_for_list_of_statistics = {
                                923                 :                :     .catname = "pg_catalog.pg_statistic_ext s",
                                924                 :                :     .viscondition = "pg_catalog.pg_statistics_obj_is_visible(s.oid)",
                                925                 :                :     .namespace = "s.stxnamespace",
                                926                 :                :     .result = "s.stxname",
                                927                 :                : };
                                928                 :                : 
                                929                 :                : static const SchemaQuery Query_for_list_of_collations = {
                                930                 :                :     .catname = "pg_catalog.pg_collation c",
                                931                 :                :     .selcondition = "c.collencoding IN (-1, pg_catalog.pg_char_to_encoding(pg_catalog.getdatabaseencoding()))",
                                932                 :                :     .viscondition = "pg_catalog.pg_collation_is_visible(c.oid)",
                                933                 :                :     .namespace = "c.collnamespace",
                                934                 :                :     .result = "c.collname",
                                935                 :                : };
                                936                 :                : 
                                937                 :                : static const SchemaQuery Query_for_partition_of_table = {
                                938                 :                :     .catname = "pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_inherits i",
                                939                 :                :     .selcondition = "c1.oid=i.inhparent and i.inhrelid=c2.oid and c2.relispartition",
                                940                 :                :     .viscondition = "pg_catalog.pg_table_is_visible(c2.oid)",
                                941                 :                :     .namespace = "c2.relnamespace",
                                942                 :                :     .result = "c2.relname",
                                943                 :                :     .refname = "c1.relname",
                                944                 :                :     .refviscondition = "pg_catalog.pg_table_is_visible(c1.oid)",
                                945                 :                :     .refnamespace = "c1.relnamespace",
                                946                 :                : };
                                947                 :                : 
                                948                 :                : static const SchemaQuery Query_for_rule_of_table = {
                                949                 :                :     .catname = "pg_catalog.pg_rewrite r, pg_catalog.pg_class c1",
                                950                 :                :     .selcondition = "r.ev_class=c1.oid",
                                951                 :                :     .result = "r.rulename",
                                952                 :                :     .refname = "c1.relname",
                                953                 :                :     .refviscondition = "pg_catalog.pg_table_is_visible(c1.oid)",
                                954                 :                :     .refnamespace = "c1.relnamespace",
                                955                 :                : };
                                956                 :                : 
                                957                 :                : static const SchemaQuery Query_for_trigger_of_table = {
                                958                 :                :     .catname = "pg_catalog.pg_trigger t, pg_catalog.pg_class c1",
                                959                 :                :     .selcondition = "t.tgrelid=c1.oid and not t.tgisinternal",
                                960                 :                :     .result = "t.tgname",
                                961                 :                :     .refname = "c1.relname",
                                962                 :                :     .refviscondition = "pg_catalog.pg_table_is_visible(c1.oid)",
                                963                 :                :     .refnamespace = "c1.relnamespace",
                                964                 :                : };
                                965                 :                : 
                                966                 :                : 
                                967                 :                : /*
                                968                 :                :  * Queries to get lists of names of various kinds of things, possibly
                                969                 :                :  * restricted to names matching a partially entered name.  Don't use
                                970                 :                :  * this method where the user might wish to enter a schema-qualified
                                971                 :                :  * name; make a SchemaQuery instead.
                                972                 :                :  *
                                973                 :                :  * In these queries, there must be a restriction clause of the form
                                974                 :                :  *      output LIKE '%s'
                                975                 :                :  * where "output" is the same string that the query returns.  The %s
                                976                 :                :  * will be replaced by a LIKE pattern to match the already-typed text.
                                977                 :                :  *
                                978                 :                :  * There can be a second '%s', which will be replaced by a suitably-escaped
                                979                 :                :  * version of the string provided in completion_ref_object.  If there is a
                                980                 :                :  * third '%s', it will be replaced by a suitably-escaped version of the string
                                981                 :                :  * provided in completion_ref_schema.  NOTE: using completion_ref_object
                                982                 :                :  * that way is usually the wrong thing, and using completion_ref_schema
                                983                 :                :  * that way is always the wrong thing.  Make a SchemaQuery instead.
                                984                 :                :  */
                                985                 :                : 
                                986                 :                : #define Query_for_list_of_template_databases \
                                987                 :                : "SELECT d.datname "\
                                988                 :                : "  FROM pg_catalog.pg_database d "\
                                989                 :                : " WHERE d.datname LIKE '%s' "\
                                990                 :                : "   AND (d.datistemplate OR pg_catalog.pg_has_role(d.datdba, 'USAGE'))"
                                991                 :                : 
                                992                 :                : #define Query_for_list_of_databases \
                                993                 :                : "SELECT datname FROM pg_catalog.pg_database "\
                                994                 :                : " WHERE datname LIKE '%s'"
                                995                 :                : 
                                996                 :                : #define Query_for_list_of_tablespaces \
                                997                 :                : "SELECT spcname FROM pg_catalog.pg_tablespace "\
                                998                 :                : " WHERE spcname LIKE '%s'"
                                999                 :                : 
                               1000                 :                : #define Query_for_list_of_encodings \
                               1001                 :                : " SELECT DISTINCT pg_catalog.pg_encoding_to_char(conforencoding) "\
                               1002                 :                : "   FROM pg_catalog.pg_conversion "\
                               1003                 :                : "  WHERE pg_catalog.pg_encoding_to_char(conforencoding) LIKE pg_catalog.upper('%s')"
                               1004                 :                : 
                               1005                 :                : #define Query_for_list_of_languages \
                               1006                 :                : "SELECT lanname "\
                               1007                 :                : "  FROM pg_catalog.pg_language "\
                               1008                 :                : " WHERE lanname != 'internal' "\
                               1009                 :                : "   AND lanname LIKE '%s'"
                               1010                 :                : 
                               1011                 :                : #define Query_for_list_of_schemas \
                               1012                 :                : "SELECT nspname FROM pg_catalog.pg_namespace "\
                               1013                 :                : " WHERE nspname LIKE '%s'"
                               1014                 :                : 
                               1015                 :                : /* Use COMPLETE_WITH_QUERY_VERBATIM with these queries for GUC names: */
                               1016                 :                : #define Query_for_list_of_alter_system_set_vars \
                               1017                 :                : "SELECT pg_catalog.lower(name) FROM pg_catalog.pg_settings "\
                               1018                 :                : " WHERE context != 'internal' "\
                               1019                 :                : "   AND pg_catalog.lower(name) LIKE pg_catalog.lower('%s')"
                               1020                 :                : 
                               1021                 :                : #define Query_for_list_of_set_vars \
                               1022                 :                : "SELECT pg_catalog.lower(name) FROM pg_catalog.pg_settings "\
                               1023                 :                : " WHERE context IN ('user', 'superuser') "\
                               1024                 :                : "   AND pg_catalog.lower(name) LIKE pg_catalog.lower('%s')"
                               1025                 :                : 
                               1026                 :                : #define Query_for_list_of_show_vars \
                               1027                 :                : "SELECT pg_catalog.lower(name) FROM pg_catalog.pg_settings "\
                               1028                 :                : " WHERE pg_catalog.lower(name) LIKE pg_catalog.lower('%s')"
                               1029                 :                : 
                               1030                 :                : #define Query_for_list_of_roles \
                               1031                 :                : " SELECT rolname "\
                               1032                 :                : "   FROM pg_catalog.pg_roles "\
                               1033                 :                : "  WHERE rolname LIKE '%s'"
                               1034                 :                : 
                               1035                 :                : /* add these to Query_for_list_of_roles in OWNER contexts */
                               1036                 :                : #define Keywords_for_list_of_owner_roles \
                               1037                 :                : "CURRENT_ROLE", "CURRENT_USER", "SESSION_USER"
                               1038                 :                : 
                               1039                 :                : /* add these to Query_for_list_of_roles in GRANT contexts */
                               1040                 :                : #define Keywords_for_list_of_grant_roles \
                               1041                 :                : Keywords_for_list_of_owner_roles, "PUBLIC"
                               1042                 :                : 
                               1043                 :                : #define Query_for_all_table_constraints \
                               1044                 :                : "SELECT conname "\
                               1045                 :                : "  FROM pg_catalog.pg_constraint c "\
                               1046                 :                : " WHERE c.conrelid <> 0 "\
                               1047                 :                : "       and conname LIKE '%s'"
                               1048                 :                : 
                               1049                 :                : #define Query_for_list_of_fdws \
                               1050                 :                : " SELECT fdwname "\
                               1051                 :                : "   FROM pg_catalog.pg_foreign_data_wrapper "\
                               1052                 :                : "  WHERE fdwname LIKE '%s'"
                               1053                 :                : 
                               1054                 :                : #define Query_for_list_of_servers \
                               1055                 :                : " SELECT srvname "\
                               1056                 :                : "   FROM pg_catalog.pg_foreign_server "\
                               1057                 :                : "  WHERE srvname LIKE '%s'"
                               1058                 :                : 
                               1059                 :                : #define Query_for_list_of_user_mappings \
                               1060                 :                : " SELECT usename "\
                               1061                 :                : "   FROM pg_catalog.pg_user_mappings "\
                               1062                 :                : "  WHERE usename LIKE '%s'"
                               1063                 :                : 
                               1064                 :                : #define Query_for_list_of_access_methods \
                               1065                 :                : " SELECT amname "\
                               1066                 :                : "   FROM pg_catalog.pg_am "\
                               1067                 :                : "  WHERE amname LIKE '%s'"
                               1068                 :                : 
                               1069                 :                : #define Query_for_list_of_index_access_methods \
                               1070                 :                : " SELECT amname "\
                               1071                 :                : "   FROM pg_catalog.pg_am "\
                               1072                 :                : "  WHERE amname LIKE '%s' AND "\
                               1073                 :                : "   amtype=" CppAsString2(AMTYPE_INDEX)
                               1074                 :                : 
                               1075                 :                : #define Query_for_list_of_table_access_methods \
                               1076                 :                : " SELECT amname "\
                               1077                 :                : "   FROM pg_catalog.pg_am "\
                               1078                 :                : "  WHERE amname LIKE '%s' AND "\
                               1079                 :                : "   amtype=" CppAsString2(AMTYPE_TABLE)
                               1080                 :                : 
                               1081                 :                : #define Query_for_list_of_extensions \
                               1082                 :                : " SELECT extname "\
                               1083                 :                : "   FROM pg_catalog.pg_extension "\
                               1084                 :                : "  WHERE extname LIKE '%s'"
                               1085                 :                : 
                               1086                 :                : #define Query_for_list_of_available_extensions \
                               1087                 :                : " SELECT name "\
                               1088                 :                : "   FROM pg_catalog.pg_available_extensions "\
                               1089                 :                : "  WHERE name LIKE '%s' AND installed_version IS NULL"
                               1090                 :                : 
                               1091                 :                : #define Query_for_list_of_available_extension_versions \
                               1092                 :                : " SELECT version "\
                               1093                 :                : "   FROM pg_catalog.pg_available_extension_versions "\
                               1094                 :                : "  WHERE version LIKE '%s' AND name='%s'"
                               1095                 :                : 
                               1096                 :                : #define Query_for_list_of_prepared_statements \
                               1097                 :                : " SELECT name "\
                               1098                 :                : "   FROM pg_catalog.pg_prepared_statements "\
                               1099                 :                : "  WHERE name LIKE '%s'"
                               1100                 :                : 
                               1101                 :                : #define Query_for_list_of_event_triggers \
                               1102                 :                : " SELECT evtname "\
                               1103                 :                : "   FROM pg_catalog.pg_event_trigger "\
                               1104                 :                : "  WHERE evtname LIKE '%s'"
                               1105                 :                : 
                               1106                 :                : #define Query_for_list_of_tablesample_methods \
                               1107                 :                : " SELECT proname "\
                               1108                 :                : "   FROM pg_catalog.pg_proc "\
                               1109                 :                : "  WHERE prorettype = 'pg_catalog.tsm_handler'::pg_catalog.regtype AND "\
                               1110                 :                : "        proargtypes[0] = 'pg_catalog.internal'::pg_catalog.regtype AND "\
                               1111                 :                : "        proname LIKE '%s'"
                               1112                 :                : 
                               1113                 :                : #define Query_for_list_of_policies \
                               1114                 :                : " SELECT polname "\
                               1115                 :                : "   FROM pg_catalog.pg_policy "\
                               1116                 :                : "  WHERE polname LIKE '%s'"
                               1117                 :                : 
                               1118                 :                : #define Query_for_values_of_enum_GUC \
                               1119                 :                : " SELECT val FROM ( "\
                               1120                 :                : "   SELECT name, pg_catalog.unnest(enumvals) AS val "\
                               1121                 :                : "     FROM pg_catalog.pg_settings "\
                               1122                 :                : "    ) ss "\
                               1123                 :                : "  WHERE val LIKE '%s'"\
                               1124                 :                : "        and pg_catalog.lower(name)=pg_catalog.lower('%s')"
                               1125                 :                : 
                               1126                 :                : #define Query_for_list_of_channels \
                               1127                 :                : " SELECT channel "\
                               1128                 :                : "   FROM pg_catalog.pg_listening_channels() AS channel "\
                               1129                 :                : "  WHERE channel LIKE '%s'"
                               1130                 :                : 
                               1131                 :                : #define Query_for_list_of_cursors \
                               1132                 :                : " SELECT name "\
                               1133                 :                : "   FROM pg_catalog.pg_cursors "\
                               1134                 :                : "  WHERE name LIKE '%s'"
                               1135                 :                : 
                               1136                 :                : #define Query_for_list_of_timezone_names_unquoted \
                               1137                 :                : " SELECT name "\
                               1138                 :                : "   FROM pg_catalog.pg_timezone_names() "\
                               1139                 :                : "  WHERE pg_catalog.lower(name) LIKE pg_catalog.lower('%s')"
                               1140                 :                : 
                               1141                 :                : #define Query_for_list_of_timezone_names_quoted_out \
                               1142                 :                : "SELECT pg_catalog.quote_literal(name) AS name "\
                               1143                 :                : "  FROM pg_catalog.pg_timezone_names() "\
                               1144                 :                : " WHERE pg_catalog.lower(name) LIKE pg_catalog.lower('%s')"
                               1145                 :                : 
                               1146                 :                : #define Query_for_list_of_timezone_names_quoted_in \
                               1147                 :                : "SELECT pg_catalog.quote_literal(name) AS name "\
                               1148                 :                : "  FROM pg_catalog.pg_timezone_names() "\
                               1149                 :                : " WHERE pg_catalog.quote_literal(pg_catalog.lower(name)) LIKE pg_catalog.lower('%s')"
                               1150                 :                : 
                               1151                 :                : /* Privilege options shared between GRANT and REVOKE */
                               1152                 :                : #define Privilege_options_of_grant_and_revoke \
                               1153                 :                : "SELECT", "INSERT", "UPDATE", "DELETE", "TRUNCATE", "REFERENCES", "TRIGGER", \
                               1154                 :                : "CREATE", "CONNECT", "TEMPORARY", "EXECUTE", "USAGE", "SET", "ALTER SYSTEM", \
                               1155                 :                : "MAINTAIN", "ALL"
                               1156                 :                : 
                               1157                 :                : /* ALTER PROCEDURE options */
                               1158                 :                : #define Alter_procedure_options \
                               1159                 :                : "DEPENDS ON EXTENSION", "EXTERNAL SECURITY", "NO DEPENDS ON EXTENSION", \
                               1160                 :                : "OWNER TO", "RENAME TO", "RESET", "SECURITY", "SET"
                               1161                 :                : 
                               1162                 :                : /* ALTER ROUTINE options */
                               1163                 :                : #define Alter_routine_options \
                               1164                 :                : Alter_procedure_options, "COST", "IMMUTABLE", "LEAKPROOF", "NOT LEAKPROOF", \
                               1165                 :                : "PARALLEL", "ROWS", "STABLE", "VOLATILE"
                               1166                 :                : 
                               1167                 :                : /* ALTER FUNCTION options */
                               1168                 :                : #define Alter_function_options \
                               1169                 :                : Alter_routine_options, "CALLED ON NULL INPUT", "RETURNS NULL ON NULL INPUT", \
                               1170                 :                : "STRICT", "SUPPORT"
                               1171                 :                : 
                               1172                 :                : /*
                               1173                 :                :  * These object types were introduced later than our support cutoff of
                               1174                 :                :  * server version 9.2.  We use the VersionedQuery infrastructure so that
                               1175                 :                :  * we don't send certain-to-fail queries to older servers.
                               1176                 :                :  */
                               1177                 :                : 
                               1178                 :                : static const VersionedQuery Query_for_list_of_publications[] = {
                               1179                 :                :     {100000,
                               1180                 :                :         " SELECT pubname "
                               1181                 :                :         "   FROM pg_catalog.pg_publication "
                               1182                 :                :         "  WHERE pubname LIKE '%s'"
                               1183                 :                :     },
                               1184                 :                :     {0, NULL}
                               1185                 :                : };
                               1186                 :                : 
                               1187                 :                : static const VersionedQuery Query_for_list_of_subscriptions[] = {
                               1188                 :                :     {100000,
                               1189                 :                :         " SELECT s.subname "
                               1190                 :                :         "   FROM pg_catalog.pg_subscription s, pg_catalog.pg_database d "
                               1191                 :                :         "  WHERE s.subname LIKE '%s' "
                               1192                 :                :         "    AND d.datname = pg_catalog.current_database() "
                               1193                 :                :         "    AND s.subdbid = d.oid"
                               1194                 :                :     },
                               1195                 :                :     {0, NULL}
                               1196                 :                : };
                               1197                 :                : 
                               1198                 :                : /*
                               1199                 :                :  * This is a list of all "things" in Pgsql, which can show up after CREATE or
                               1200                 :                :  * DROP; and there is also a query to get a list of them.
                               1201                 :                :  */
                               1202                 :                : 
                               1203                 :                : typedef struct
                               1204                 :                : {
                               1205                 :                :     const char *name;
                               1206                 :                :     /* Provide at most one of these three types of query: */
                               1207                 :                :     const char *query;          /* simple query, or NULL */
                               1208                 :                :     const VersionedQuery *vquery;   /* versioned query, or NULL */
                               1209                 :                :     const SchemaQuery *squery;  /* schema query, or NULL */
                               1210                 :                :     const char *const *keywords;    /* keywords to be offered as well */
                               1211                 :                :     const bits32 flags;         /* visibility flags, see below */
                               1212                 :                : } pgsql_thing_t;
                               1213                 :                : 
                               1214                 :                : #define THING_NO_CREATE     (1 << 0)  /* should not show up after CREATE */
                               1215                 :                : #define THING_NO_DROP       (1 << 1)  /* should not show up after DROP */
                               1216                 :                : #define THING_NO_ALTER      (1 << 2)  /* should not show up after ALTER */
                               1217                 :                : #define THING_NO_SHOW       (THING_NO_CREATE | THING_NO_DROP | THING_NO_ALTER)
                               1218                 :                : 
                               1219                 :                : /* When we have DROP USER etc, also offer MAPPING FOR */
                               1220                 :                : static const char *const Keywords_for_user_thing[] = {
                               1221                 :                :     "MAPPING FOR",
                               1222                 :                :     NULL
                               1223                 :                : };
                               1224                 :                : 
                               1225                 :                : static const pgsql_thing_t words_after_create[] = {
                               1226                 :                :     {"ACCESS METHOD", NULL, NULL, NULL, NULL, THING_NO_ALTER},
                               1227                 :                :     {"AGGREGATE", NULL, NULL, Query_for_list_of_aggregates},
                               1228                 :                :     {"CAST", NULL, NULL, NULL}, /* Casts have complex structures for names, so
                               1229                 :                :                                  * skip it */
                               1230                 :                :     {"COLLATION", NULL, NULL, &Query_for_list_of_collations},
                               1231                 :                : 
                               1232                 :                :     /*
                               1233                 :                :      * CREATE CONSTRAINT TRIGGER is not supported here because it is designed
                               1234                 :                :      * to be used only by pg_dump.
                               1235                 :                :      */
                               1236                 :                :     {"CONFIGURATION", NULL, NULL, &Query_for_list_of_ts_configurations, NULL, THING_NO_SHOW},
                               1237                 :                :     {"CONVERSION", "SELECT conname FROM pg_catalog.pg_conversion WHERE conname LIKE '%s'"},
                               1238                 :                :     {"DATABASE", Query_for_list_of_databases},
                               1239                 :                :     {"DEFAULT PRIVILEGES", NULL, NULL, NULL, NULL, THING_NO_CREATE | THING_NO_DROP},
                               1240                 :                :     {"DICTIONARY", NULL, NULL, &Query_for_list_of_ts_dictionaries, NULL, THING_NO_SHOW},
                               1241                 :                :     {"DOMAIN", NULL, NULL, &Query_for_list_of_domains},
                               1242                 :                :     {"EVENT TRIGGER", NULL, NULL, NULL},
                               1243                 :                :     {"EXTENSION", Query_for_list_of_extensions},
                               1244                 :                :     {"FOREIGN DATA WRAPPER", NULL, NULL, NULL},
                               1245                 :                :     {"FOREIGN TABLE", NULL, NULL, NULL},
                               1246                 :                :     {"FUNCTION", NULL, NULL, Query_for_list_of_functions},
                               1247                 :                :     {"GROUP", Query_for_list_of_roles},
                               1248                 :                :     {"INDEX", NULL, NULL, &Query_for_list_of_indexes},
                               1249                 :                :     {"LANGUAGE", Query_for_list_of_languages},
                               1250                 :                :     {"LARGE OBJECT", NULL, NULL, NULL, NULL, THING_NO_CREATE | THING_NO_DROP},
                               1251                 :                :     {"MATERIALIZED VIEW", NULL, NULL, &Query_for_list_of_matviews},
                               1252                 :                :     {"OPERATOR", NULL, NULL, NULL}, /* Querying for this is probably not such
                               1253                 :                :                                      * a good idea. */
                               1254                 :                :     {"OR REPLACE", NULL, NULL, NULL, NULL, THING_NO_DROP | THING_NO_ALTER},
                               1255                 :                :     {"OWNED", NULL, NULL, NULL, NULL, THING_NO_CREATE | THING_NO_ALTER},  /* for DROP OWNED BY ... */
                               1256                 :                :     {"PARSER", NULL, NULL, &Query_for_list_of_ts_parsers, NULL, THING_NO_SHOW},
                               1257                 :                :     {"POLICY", NULL, NULL, NULL},
                               1258                 :                :     {"PROCEDURE", NULL, NULL, Query_for_list_of_procedures},
                               1259                 :                :     {"PUBLICATION", NULL, Query_for_list_of_publications},
                               1260                 :                :     {"ROLE", Query_for_list_of_roles},
                               1261                 :                :     {"ROUTINE", NULL, NULL, &Query_for_list_of_routines, NULL, THING_NO_CREATE},
                               1262                 :                :     {"RULE", "SELECT rulename FROM pg_catalog.pg_rules WHERE rulename LIKE '%s'"},
                               1263                 :                :     {"SCHEMA", Query_for_list_of_schemas},
                               1264                 :                :     {"SEQUENCE", NULL, NULL, &Query_for_list_of_sequences},
                               1265                 :                :     {"SERVER", Query_for_list_of_servers},
                               1266                 :                :     {"STATISTICS", NULL, NULL, &Query_for_list_of_statistics},
                               1267                 :                :     {"SUBSCRIPTION", NULL, Query_for_list_of_subscriptions},
                               1268                 :                :     {"SYSTEM", NULL, NULL, NULL, NULL, THING_NO_CREATE | THING_NO_DROP},
                               1269                 :                :     {"TABLE", NULL, NULL, &Query_for_list_of_tables},
                               1270                 :                :     {"TABLESPACE", Query_for_list_of_tablespaces},
                               1271                 :                :     {"TEMP", NULL, NULL, NULL, NULL, THING_NO_DROP | THING_NO_ALTER}, /* for CREATE TEMP TABLE
                               1272                 :                :                                                                          * ... */
                               1273                 :                :     {"TEMPLATE", NULL, NULL, &Query_for_list_of_ts_templates, NULL, THING_NO_SHOW},
                               1274                 :                :     {"TEMPORARY", NULL, NULL, NULL, NULL, THING_NO_DROP | THING_NO_ALTER},    /* for CREATE TEMPORARY
                               1275                 :                :                                                                              * TABLE ... */
                               1276                 :                :     {"TEXT SEARCH", NULL, NULL, NULL},
                               1277                 :                :     {"TRANSFORM", NULL, NULL, NULL, NULL, THING_NO_ALTER},
                               1278                 :                :     {"TRIGGER", "SELECT tgname FROM pg_catalog.pg_trigger WHERE tgname LIKE '%s' AND NOT tgisinternal"},
                               1279                 :                :     {"TYPE", NULL, NULL, &Query_for_list_of_datatypes},
                               1280                 :                :     {"UNIQUE", NULL, NULL, NULL, NULL, THING_NO_DROP | THING_NO_ALTER}, /* for CREATE UNIQUE
                               1281                 :                :                                                                          * INDEX ... */
                               1282                 :                :     {"UNLOGGED", NULL, NULL, NULL, NULL, THING_NO_DROP | THING_NO_ALTER}, /* for CREATE UNLOGGED
                               1283                 :                :                                                                              * TABLE ... */
                               1284                 :                :     {"USER", Query_for_list_of_roles, NULL, NULL, Keywords_for_user_thing},
                               1285                 :                :     {"USER MAPPING FOR", NULL, NULL, NULL},
                               1286                 :                :     {"VIEW", NULL, NULL, &Query_for_list_of_views},
                               1287                 :                :     {NULL}                      /* end of list */
                               1288                 :                : };
                               1289                 :                : 
                               1290                 :                : /* Storage parameters for CREATE TABLE and ALTER TABLE */
                               1291                 :                : static const char *const table_storage_parameters[] = {
                               1292                 :                :     "autovacuum_analyze_scale_factor",
                               1293                 :                :     "autovacuum_analyze_threshold",
                               1294                 :                :     "autovacuum_enabled",
                               1295                 :                :     "autovacuum_freeze_max_age",
                               1296                 :                :     "autovacuum_freeze_min_age",
                               1297                 :                :     "autovacuum_freeze_table_age",
                               1298                 :                :     "autovacuum_multixact_freeze_max_age",
                               1299                 :                :     "autovacuum_multixact_freeze_min_age",
                               1300                 :                :     "autovacuum_multixact_freeze_table_age",
                               1301                 :                :     "autovacuum_vacuum_cost_delay",
                               1302                 :                :     "autovacuum_vacuum_cost_limit",
                               1303                 :                :     "autovacuum_vacuum_insert_scale_factor",
                               1304                 :                :     "autovacuum_vacuum_insert_threshold",
                               1305                 :                :     "autovacuum_vacuum_scale_factor",
                               1306                 :                :     "autovacuum_vacuum_threshold",
                               1307                 :                :     "fillfactor",
                               1308                 :                :     "log_autovacuum_min_duration",
                               1309                 :                :     "parallel_workers",
                               1310                 :                :     "toast.autovacuum_enabled",
                               1311                 :                :     "toast.autovacuum_freeze_max_age",
                               1312                 :                :     "toast.autovacuum_freeze_min_age",
                               1313                 :                :     "toast.autovacuum_freeze_table_age",
                               1314                 :                :     "toast.autovacuum_multixact_freeze_max_age",
                               1315                 :                :     "toast.autovacuum_multixact_freeze_min_age",
                               1316                 :                :     "toast.autovacuum_multixact_freeze_table_age",
                               1317                 :                :     "toast.autovacuum_vacuum_cost_delay",
                               1318                 :                :     "toast.autovacuum_vacuum_cost_limit",
                               1319                 :                :     "toast.autovacuum_vacuum_insert_scale_factor",
                               1320                 :                :     "toast.autovacuum_vacuum_insert_threshold",
                               1321                 :                :     "toast.autovacuum_vacuum_scale_factor",
                               1322                 :                :     "toast.autovacuum_vacuum_threshold",
                               1323                 :                :     "toast.log_autovacuum_min_duration",
                               1324                 :                :     "toast.vacuum_index_cleanup",
                               1325                 :                :     "toast.vacuum_truncate",
                               1326                 :                :     "toast_tuple_target",
                               1327                 :                :     "user_catalog_table",
                               1328                 :                :     "vacuum_index_cleanup",
                               1329                 :                :     "vacuum_truncate",
                               1330                 :                :     NULL
                               1331                 :                : };
                               1332                 :                : 
                               1333                 :                : /* Optional parameters for CREATE VIEW and ALTER VIEW */
                               1334                 :                : static const char *const view_optional_parameters[] = {
                               1335                 :                :     "check_option",
                               1336                 :                :     "security_barrier",
                               1337                 :                :     "security_invoker",
                               1338                 :                :     NULL
                               1339                 :                : };
                               1340                 :                : 
                               1341                 :                : /* Forward declaration of functions */
                               1342                 :                : static char **psql_completion(const char *text, int start, int end);
                               1343                 :                : static char *create_command_generator(const char *text, int state);
                               1344                 :                : static char *drop_command_generator(const char *text, int state);
                               1345                 :                : static char *alter_command_generator(const char *text, int state);
                               1346                 :                : static char *complete_from_query(const char *text, int state);
                               1347                 :                : static char *complete_from_versioned_query(const char *text, int state);
                               1348                 :                : static char *complete_from_schema_query(const char *text, int state);
                               1349                 :                : static char *complete_from_versioned_schema_query(const char *text, int state);
                               1350                 :                : static char *_complete_from_query(const char *simple_query,
                               1351                 :                :                                   const SchemaQuery *schema_query,
                               1352                 :                :                                   const char *const *keywords,
                               1353                 :                :                                   bool verbatim,
                               1354                 :                :                                   const char *text, int state);
                               1355                 :                : static void set_completion_reference(const char *word);
                               1356                 :                : static void set_completion_reference_verbatim(const char *word);
                               1357                 :                : static char *complete_from_list(const char *text, int state);
                               1358                 :                : static char *complete_from_const(const char *text, int state);
                               1359                 :                : static void append_variable_names(char ***varnames, int *nvars,
                               1360                 :                :                                   int *maxvars, const char *varname,
                               1361                 :                :                                   const char *prefix, const char *suffix);
                               1362                 :                : static char **complete_from_variables(const char *text,
                               1363                 :                :                                       const char *prefix, const char *suffix, bool need_value);
                               1364                 :                : static char *complete_from_files(const char *text, int state);
                               1365                 :                : 
                               1366                 :                : static char *pg_strdup_keyword_case(const char *s, const char *ref);
                               1367                 :                : static char *escape_string(const char *text);
                               1368                 :                : static char *make_like_pattern(const char *word);
                               1369                 :                : static void parse_identifier(const char *ident,
                               1370                 :                :                              char **schemaname, char **objectname,
                               1371                 :                :                              bool *schemaquoted, bool *objectquoted);
                               1372                 :                : static char *requote_identifier(const char *schemaname, const char *objectname,
                               1373                 :                :                                 bool quote_schema, bool quote_object);
                               1374                 :                : static bool identifier_needs_quotes(const char *ident);
                               1375                 :                : static PGresult *exec_query(const char *query);
                               1376                 :                : 
                               1377                 :                : static char **get_previous_words(int point, char **buffer, int *nwords);
                               1378                 :                : 
                               1379                 :                : static char *get_guctype(const char *varname);
                               1380                 :                : 
                               1381                 :                : #ifdef USE_FILENAME_QUOTING_FUNCTIONS
                               1382                 :                : static char *quote_file_name(char *fname, int match_type, char *quote_pointer);
                               1383                 :                : static char *dequote_file_name(char *fname, int quote_char);
                               1384                 :                : #endif
                               1385                 :                : 
                               1386                 :                : 
                               1387                 :                : /*
                               1388                 :                :  * Initialize the readline library for our purposes.
                               1389                 :                :  */
                               1390                 :                : void
 7472 tgl@sss.pgh.pa.us        1391                 :CBC           2 : initialize_readline(void)
                               1392                 :                : {
 7168 bruce@momjian.us         1393                 :              2 :     rl_readline_name = (char *) pset.progname;
 3663 rhaas@postgresql.org     1394                 :              2 :     rl_attempted_completion_function = psql_completion;
                               1395                 :                : 
                               1396                 :                : #ifdef USE_FILENAME_QUOTING_FUNCTIONS
 1543 tgl@sss.pgh.pa.us        1397                 :              2 :     rl_filename_quoting_function = quote_file_name;
                               1398                 :              2 :     rl_filename_dequoting_function = dequote_file_name;
                               1399                 :                : #endif
                               1400                 :                : 
 5170 itagaki.takahiro@gma     1401                 :              2 :     rl_basic_word_break_characters = WORD_BREAKS;
                               1402                 :                : 
                               1403                 :                :     /*
                               1404                 :                :      * Ideally we'd include '"' in rl_completer_quote_characters too, which
                               1405                 :                :      * should allow us to complete quoted identifiers that include spaces.
                               1406                 :                :      * However, the library support for rl_completer_quote_characters is
                               1407                 :                :      * presently too inconsistent to want to mess with that.  (Note in
                               1408                 :                :      * particular that libedit has this variable but completely ignores it.)
                               1409                 :                :      */
 1543 tgl@sss.pgh.pa.us        1410                 :              2 :     rl_completer_quote_characters = "'";
                               1411                 :                : 
                               1412                 :                :     /*
                               1413                 :                :      * Set rl_filename_quote_characters to "all possible characters",
                               1414                 :                :      * otherwise Readline will skip filename quoting if it thinks a filename
                               1415                 :                :      * doesn't need quoting.  Readline actually interprets this as bytes, so
                               1416                 :                :      * there are no encoding considerations here.
                               1417                 :                :      */
                               1418                 :                : #ifdef HAVE_RL_FILENAME_QUOTE_CHARACTERS
                               1419                 :                :     {
                               1420                 :              2 :         unsigned char *fqc = (unsigned char *) pg_malloc(256);
                               1421                 :                : 
                               1422         [ +  + ]:            512 :         for (int i = 0; i < 255; i++)
                               1423                 :            510 :             fqc[i] = (unsigned char) (i + 1);
                               1424                 :              2 :         fqc[255] = '\0';
                               1425                 :              2 :         rl_filename_quote_characters = (const char *) fqc;
                               1426                 :                :     }
                               1427                 :                : #endif
                               1428                 :                : 
 7472                          1429                 :              2 :     completion_max_records = 1000;
                               1430                 :                : 
                               1431                 :                :     /*
                               1432                 :                :      * There is a variable rl_completion_query_items for this but apparently
                               1433                 :                :      * it's not defined everywhere.
                               1434                 :                :      */
                               1435                 :              2 : }
                               1436                 :                : 
                               1437                 :                : /*
                               1438                 :                :  * Check if 'word' matches any of the '|'-separated strings in 'pattern',
                               1439                 :                :  * using case-insensitive or case-sensitive comparisons.
                               1440                 :                :  *
                               1441                 :                :  * If pattern is NULL, it's a wild card that matches any word.
                               1442                 :                :  * If pattern begins with '!', the result is negated, ie we check that 'word'
                               1443                 :                :  * does *not* match any alternative appearing in the rest of 'pattern'.
                               1444                 :                :  * Any alternative can contain '*' which is a wild card, i.e., it can match
                               1445                 :                :  * any substring; however, we allow at most one '*' per alternative.
                               1446                 :                :  *
                               1447                 :                :  * For readability, callers should use the macros MatchAny and MatchAnyExcept
                               1448                 :                :  * to invoke those two special cases for 'pattern'.  (But '|' and '*' must
                               1449                 :                :  * just be written directly in patterns.)
                               1450                 :                :  */
                               1451                 :                : #define MatchAny  NULL
                               1452                 :                : #define MatchAnyExcept(pattern)  ("!" pattern)
                               1453                 :                : 
                               1454                 :                : static bool
 2032                          1455                 :           9052 : word_matches(const char *pattern,
                               1456                 :                :              const char *word,
                               1457                 :                :              bool case_sensitive)
                               1458                 :                : {
                               1459                 :                :     size_t      wordlen;
                               1460                 :                : 
                               1461                 :                : #define cimatch(s1, s2, n) \
                               1462                 :                :     (case_sensitive ? strncmp(s1, s2, n) == 0 : pg_strncasecmp(s1, s2, n) == 0)
                               1463                 :                : 
                               1464                 :                :     /* NULL pattern matches anything. */
 3039                          1465         [ +  + ]:           9052 :     if (pattern == NULL)
                               1466                 :            160 :         return true;
                               1467                 :                : 
                               1468                 :                :     /* Handle negated patterns from the MatchAnyExcept macro. */
                               1469         [ -  + ]:           8892 :     if (*pattern == '!')
 2032 tgl@sss.pgh.pa.us        1470                 :UBC           0 :         return !word_matches(pattern + 1, word, case_sensitive);
                               1471                 :                : 
                               1472                 :                :     /* Else consider each alternative in the pattern. */
 3039 tgl@sss.pgh.pa.us        1473                 :CBC        8892 :     wordlen = strlen(word);
                               1474                 :                :     for (;;)
                               1475                 :            764 :     {
 2032                          1476                 :           9656 :         const char *star = NULL;
                               1477                 :                :         const char *c;
                               1478                 :                : 
                               1479                 :                :         /* Find end of current alternative, and locate any wild card. */
 3039                          1480                 :           9656 :         c = pattern;
                               1481   [ +  +  +  + ]:          64926 :         while (*c != '\0' && *c != '|')
                               1482                 :                :         {
 2032                          1483         [ +  + ]:          55270 :             if (*c == '*')
                               1484                 :            407 :                 star = c;
 3039                          1485                 :          55270 :             c++;
                               1486                 :                :         }
                               1487                 :                :         /* Was there a wild card? */
 2032                          1488         [ +  + ]:           9656 :         if (star)
                               1489                 :                :         {
                               1490                 :                :             /* Yes, wildcard match? */
                               1491                 :            407 :             size_t      beforelen = star - pattern,
                               1492                 :            407 :                         afterlen = c - star - 1;
                               1493                 :                : 
                               1494   [ +  +  +  +  :            806 :             if (wordlen >= (beforelen + afterlen) &&
                                              +  + ]
                               1495   [ +  +  +  - ]:            411 :                 cimatch(word, pattern, beforelen) &&
                               1496                 :              6 :                 cimatch(word + wordlen - afterlen, star + 1, afterlen))
 3022                          1497                 :              6 :                 return true;
                               1498                 :                :         }
                               1499                 :                :         else
                               1500                 :                :         {
                               1501                 :                :             /* No, plain match? */
 2032                          1502   [ +  +  +  +  :          11774 :             if (wordlen == (c - pattern) &&
                                              +  + ]
                               1503                 :           2525 :                 cimatch(word, pattern, wordlen))
 3022                          1504                 :           1309 :                 return true;
                               1505                 :                :         }
                               1506                 :                :         /* Out of alternatives? */
 3039                          1507         [ +  + ]:           8341 :         if (*c == '\0')
                               1508                 :           7577 :             break;
                               1509                 :                :         /* Nope, try next alternative. */
                               1510                 :            764 :         pattern = c + 1;
                               1511                 :                :     }
                               1512                 :                : 
                               1513                 :           7577 :     return false;
                               1514                 :                : }
                               1515                 :                : 
                               1516                 :                : /*
                               1517                 :                :  * Implementation of TailMatches and TailMatchesCS macros: do the last N words
                               1518                 :                :  * in previous_words match the variadic arguments?
                               1519                 :                :  *
                               1520                 :                :  * The array indexing might look backwards, but remember that
                               1521                 :                :  * previous_words[0] contains the *last* word on the line, not the first.
                               1522                 :                :  */
                               1523                 :                : static bool
 2032                          1524                 :           7243 : TailMatchesImpl(bool case_sensitive,
                               1525                 :                :                 int previous_words_count, char **previous_words,
                               1526                 :                :                 int narg,...)
                               1527                 :                : {
                               1528                 :                :     va_list     args;
                               1529                 :                : 
                               1530         [ +  + ]:           7243 :     if (previous_words_count < narg)
                               1531                 :           5123 :         return false;
                               1532                 :                : 
                               1533                 :           2120 :     va_start(args, narg);
                               1534                 :                : 
                               1535         [ +  + ]:           2203 :     for (int argno = 0; argno < narg; argno++)
                               1536                 :                :     {
                               1537                 :           2170 :         const char *arg = va_arg(args, const char *);
                               1538                 :                : 
                               1539         [ +  + ]:           2170 :         if (!word_matches(arg, previous_words[narg - argno - 1],
                               1540                 :                :                           case_sensitive))
                               1541                 :                :         {
                               1542                 :           2087 :             va_end(args);
                               1543                 :           2087 :             return false;
                               1544                 :                :         }
                               1545                 :                :     }
                               1546                 :                : 
                               1547                 :             33 :     va_end(args);
                               1548                 :                : 
                               1549                 :             33 :     return true;
                               1550                 :                : }
                               1551                 :                : 
                               1552                 :                : /*
                               1553                 :                :  * Implementation of Matches and MatchesCS macros: do all of the words
                               1554                 :                :  * in previous_words match the variadic arguments?
                               1555                 :                :  */
                               1556                 :                : static bool
                               1557                 :          22254 : MatchesImpl(bool case_sensitive,
                               1558                 :                :             int previous_words_count, char **previous_words,
                               1559                 :                :             int narg,...)
                               1560                 :                : {
                               1561                 :                :     va_list     args;
                               1562                 :                : 
                               1563         [ +  + ]:          22254 :     if (previous_words_count != narg)
                               1564                 :          18830 :         return false;
                               1565                 :                : 
                               1566                 :           3424 :     va_start(args, narg);
                               1567                 :                : 
                               1568         [ +  + ]:           4578 :     for (int argno = 0; argno < narg; argno++)
                               1569                 :                :     {
                               1570                 :           4550 :         const char *arg = va_arg(args, const char *);
                               1571                 :                : 
                               1572         [ +  + ]:           4550 :         if (!word_matches(arg, previous_words[narg - argno - 1],
                               1573                 :                :                           case_sensitive))
                               1574                 :                :         {
                               1575                 :           3396 :             va_end(args);
                               1576                 :           3396 :             return false;
                               1577                 :                :         }
                               1578                 :                :     }
                               1579                 :                : 
                               1580                 :             28 :     va_end(args);
                               1581                 :                : 
                               1582                 :             28 :     return true;
                               1583                 :                : }
                               1584                 :                : 
                               1585                 :                : /*
                               1586                 :                :  * Implementation of HeadMatches and HeadMatchesCS macros: do the first N
                               1587                 :                :  * words in previous_words match the variadic arguments?
                               1588                 :                :  */
                               1589                 :                : static bool
                               1590                 :           3304 : HeadMatchesImpl(bool case_sensitive,
                               1591                 :                :                 int previous_words_count, char **previous_words,
                               1592                 :                :                 int narg,...)
                               1593                 :                : {
                               1594                 :                :     va_list     args;
                               1595                 :                : 
                               1596         [ +  + ]:           3304 :     if (previous_words_count < narg)
                               1597                 :           1208 :         return false;
                               1598                 :                : 
                               1599                 :           2096 :     va_start(args, narg);
                               1600                 :                : 
                               1601         [ +  + ]:           2334 :     for (int argno = 0; argno < narg; argno++)
                               1602                 :                :     {
                               1603                 :           2332 :         const char *arg = va_arg(args, const char *);
                               1604                 :                : 
                               1605         [ +  + ]:           2332 :         if (!word_matches(arg, previous_words[previous_words_count - argno - 1],
                               1606                 :                :                           case_sensitive))
                               1607                 :                :         {
                               1608                 :           2094 :             va_end(args);
                               1609                 :           2094 :             return false;
                               1610                 :                :         }
                               1611                 :                :     }
                               1612                 :                : 
                               1613                 :              2 :     va_end(args);
                               1614                 :                : 
                               1615                 :              2 :     return true;
                               1616                 :                : }
                               1617                 :                : 
                               1618                 :                : /*
                               1619                 :                :  * Check if the final character of 's' is 'c'.
                               1620                 :                :  */
                               1621                 :                : static bool
 3039                          1622                 :              2 : ends_with(const char *s, char c)
                               1623                 :                : {
                               1624                 :              2 :     size_t      length = strlen(s);
                               1625                 :                : 
                               1626   [ +  -  +  - ]:              2 :     return (length > 0 && s[length - 1] == c);
                               1627                 :                : }
                               1628                 :                : 
                               1629                 :                : /*
                               1630                 :                :  * The completion function.
                               1631                 :                :  *
                               1632                 :                :  * According to readline spec this gets passed the text entered so far and its
                               1633                 :                :  * start and end positions in the readline buffer. The return value is some
                               1634                 :                :  * partially obscure list format that can be generated by readline's
                               1635                 :                :  * rl_completion_matches() function, so we don't have to worry about it.
                               1636                 :                :  */
                               1637                 :                : static char **
 3663 rhaas@postgresql.org     1638                 :             67 : psql_completion(const char *text, int start, int end)
                               1639                 :                : {
                               1640                 :                :     /* This is the variable we'll return. */
 8768 bruce@momjian.us         1641                 :             67 :     char      **matches = NULL;
                               1642                 :                : 
                               1643                 :                :     /* Workspace for parsed words. */
                               1644                 :                :     char       *words_buffer;
                               1645                 :                : 
                               1646                 :                :     /* This array will contain pointers to parsed words. */
                               1647                 :                :     char      **previous_words;
                               1648                 :                : 
                               1649                 :                :     /* The number of words found on the input line. */
                               1650                 :                :     int         previous_words_count;
                               1651                 :                : 
                               1652                 :                :     /*
                               1653                 :                :      * For compactness, we use these macros to reference previous_words[].
                               1654                 :                :      * Caution: do not access a previous_words[] entry without having checked
                               1655                 :                :      * previous_words_count to be sure it's valid.  In most cases below, that
                               1656                 :                :      * check is implicit in a TailMatches() or similar macro, but in some
                               1657                 :                :      * places we have to check it explicitly.
                               1658                 :                :      */
                               1659                 :                : #define prev_wd   (previous_words[0])
                               1660                 :                : #define prev2_wd  (previous_words[1])
                               1661                 :                : #define prev3_wd  (previous_words[2])
                               1662                 :                : #define prev4_wd  (previous_words[3])
                               1663                 :                : #define prev5_wd  (previous_words[4])
                               1664                 :                : #define prev6_wd  (previous_words[5])
                               1665                 :                : #define prev7_wd  (previous_words[6])
                               1666                 :                : #define prev8_wd  (previous_words[7])
                               1667                 :                : #define prev9_wd  (previous_words[8])
                               1668                 :                : 
                               1669                 :                :     /* Match the last N words before point, case-insensitively. */
                               1670                 :                : #define TailMatches(...) \
                               1671                 :                :     TailMatchesImpl(false, previous_words_count, previous_words, \
                               1672                 :                :                     VA_ARGS_NARGS(__VA_ARGS__), __VA_ARGS__)
                               1673                 :                : 
                               1674                 :                :     /* Match the last N words before point, case-sensitively. */
                               1675                 :                : #define TailMatchesCS(...) \
                               1676                 :                :     TailMatchesImpl(true, previous_words_count, previous_words, \
                               1677                 :                :                     VA_ARGS_NARGS(__VA_ARGS__), __VA_ARGS__)
                               1678                 :                : 
                               1679                 :                :     /* Match N words representing all of the line, case-insensitively. */
                               1680                 :                : #define Matches(...) \
                               1681                 :                :     MatchesImpl(false, previous_words_count, previous_words, \
                               1682                 :                :                 VA_ARGS_NARGS(__VA_ARGS__), __VA_ARGS__)
                               1683                 :                : 
                               1684                 :                :     /* Match N words representing all of the line, case-sensitively. */
                               1685                 :                : #define MatchesCS(...) \
                               1686                 :                :     MatchesImpl(true, previous_words_count, previous_words, \
                               1687                 :                :                 VA_ARGS_NARGS(__VA_ARGS__), __VA_ARGS__)
                               1688                 :                : 
                               1689                 :                :     /* Match the first N words on the line, case-insensitively. */
                               1690                 :                : #define HeadMatches(...) \
                               1691                 :                :     HeadMatchesImpl(false, previous_words_count, previous_words, \
                               1692                 :                :                     VA_ARGS_NARGS(__VA_ARGS__), __VA_ARGS__)
                               1693                 :                : 
                               1694                 :                :     /* Match the first N words on the line, case-sensitively. */
                               1695                 :                : #define HeadMatchesCS(...) \
                               1696                 :                :     HeadMatchesImpl(true, previous_words_count, previous_words, \
                               1697                 :                :                     VA_ARGS_NARGS(__VA_ARGS__), __VA_ARGS__)
                               1698                 :                : 
                               1699                 :                :     /* Known command-starting keywords. */
                               1700                 :                :     static const char *const sql_commands[] = {
                               1701                 :                :         "ABORT", "ALTER", "ANALYZE", "BEGIN", "CALL", "CHECKPOINT", "CLOSE", "CLUSTER",
                               1702                 :                :         "COMMENT", "COMMIT", "COPY", "CREATE", "DEALLOCATE", "DECLARE",
                               1703                 :                :         "DELETE FROM", "DISCARD", "DO", "DROP", "END", "EXECUTE", "EXPLAIN",
                               1704                 :                :         "FETCH", "GRANT", "IMPORT FOREIGN SCHEMA", "INSERT INTO", "LISTEN", "LOAD", "LOCK",
                               1705                 :                :         "MERGE INTO", "MOVE", "NOTIFY", "PREPARE",
                               1706                 :                :         "REASSIGN", "REFRESH MATERIALIZED VIEW", "REINDEX", "RELEASE",
                               1707                 :                :         "RESET", "REVOKE", "ROLLBACK",
                               1708                 :                :         "SAVEPOINT", "SECURITY LABEL", "SELECT", "SET", "SHOW", "START",
                               1709                 :                :         "TABLE", "TRUNCATE", "UNLISTEN", "UPDATE", "VACUUM", "VALUES", "WITH",
                               1710                 :                :         NULL
                               1711                 :                :     };
                               1712                 :                : 
                               1713                 :                :     /* psql's backslash commands. */
                               1714                 :                :     static const char *const backslash_commands[] = {
                               1715                 :                :         "\\a",
                               1716                 :                :         "\\bind",
                               1717                 :                :         "\\connect", "\\conninfo", "\\C", "\\cd", "\\copy",
                               1718                 :                :         "\\copyright", "\\crosstabview",
                               1719                 :                :         "\\d", "\\da", "\\dA", "\\dAc", "\\dAf", "\\dAo", "\\dAp",
                               1720                 :                :         "\\db", "\\dc", "\\dconfig", "\\dC", "\\dd", "\\ddp", "\\dD",
                               1721                 :                :         "\\des", "\\det", "\\deu", "\\dew", "\\dE", "\\df",
                               1722                 :                :         "\\dF", "\\dFd", "\\dFp", "\\dFt", "\\dg", "\\di", "\\dl", "\\dL",
                               1723                 :                :         "\\dm", "\\dn", "\\do", "\\dO", "\\dp", "\\dP", "\\dPi", "\\dPt",
                               1724                 :                :         "\\drds", "\\drg", "\\dRs", "\\dRp", "\\ds",
                               1725                 :                :         "\\dt", "\\dT", "\\dv", "\\du", "\\dx", "\\dX", "\\dy",
                               1726                 :                :         "\\echo", "\\edit", "\\ef", "\\elif", "\\else", "\\encoding",
                               1727                 :                :         "\\endif", "\\errverbose", "\\ev",
                               1728                 :                :         "\\f",
                               1729                 :                :         "\\g", "\\gdesc", "\\getenv", "\\gexec", "\\gset", "\\gx",
                               1730                 :                :         "\\help", "\\html",
                               1731                 :                :         "\\if", "\\include", "\\include_relative", "\\ir",
                               1732                 :                :         "\\list", "\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",
                               1733                 :                :         "\\out",
                               1734                 :                :         "\\password", "\\print", "\\prompt", "\\pset",
                               1735                 :                :         "\\qecho", "\\quit",
                               1736                 :                :         "\\reset",
                               1737                 :                :         "\\s", "\\set", "\\setenv", "\\sf", "\\sv",
                               1738                 :                :         "\\t", "\\T", "\\timing",
                               1739                 :                :         "\\unset",
                               1740                 :                :         "\\x",
                               1741                 :                :         "\\warn", "\\watch", "\\write",
                               1742                 :                :         "\\z",
                               1743                 :                :         "\\!", "\\?",
                               1744                 :                :         NULL
                               1745                 :                :     };
                               1746                 :                : 
                               1747                 :                :     /*
                               1748                 :                :      * Temporary workaround for a bug in recent (2019) libedit: it incorrectly
                               1749                 :                :      * de-escapes the input "text", causing us to fail to recognize backslash
                               1750                 :                :      * commands.  So get the string to look at from rl_line_buffer instead.
                               1751                 :                :      */
 1563 tgl@sss.pgh.pa.us        1752                 :             67 :     char       *text_copy = pnstrdup(rl_line_buffer + start, end - start);
                               1753                 :             67 :     text = text_copy;
                               1754                 :                : 
                               1755                 :                :     /* Remember last char of the given input word. */
 1543                          1756         [ +  + ]:             67 :     completion_last_char = (end > start) ? text[end - start - 1] : '\0';
                               1757                 :                : 
                               1758                 :                :     /* We usually want the append character to be a space. */
 8768 bruce@momjian.us         1759                 :             67 :     rl_completion_append_character = ' ';
                               1760                 :                : 
                               1761                 :                :     /* Clear a few things. */
                               1762                 :             67 :     completion_charp = NULL;
                               1763                 :             67 :     completion_charpp = NULL;
  805 tgl@sss.pgh.pa.us        1764                 :             67 :     completion_vquery = NULL;
                               1765                 :             67 :     completion_squery = NULL;
                               1766                 :             67 :     completion_ref_object = NULL;
                               1767                 :             67 :     completion_ref_schema = NULL;
                               1768                 :                : 
                               1769                 :                :     /*
                               1770                 :                :      * Scan the input line to extract the words before our current position.
                               1771                 :                :      * According to those we'll make some smart decisions on what the user is
                               1772                 :                :      * probably intending to type.
                               1773                 :                :      */
 3038                          1774                 :             67 :     previous_words = get_previous_words(start,
                               1775                 :                :                                         &words_buffer,
                               1776                 :                :                                         &previous_words_count);
                               1777                 :                : 
                               1778                 :                :     /* If current word is a backslash command, offer completions for that */
 8768 bruce@momjian.us         1779         [ +  + ]:             67 :     if (text[0] == '\\')
 4456 peter_e@gmx.net          1780                 :              1 :         COMPLETE_WITH_LIST_CS(backslash_commands);
                               1781                 :                : 
                               1782                 :                :     /* If current word is a variable interpolation, handle that case */
 4811 rhaas@postgresql.org     1783   [ +  +  +  - ]:             66 :     else if (text[0] == ':' && text[1] != ':')
                               1784                 :                :     {
                               1785         [ -  + ]:              2 :         if (text[1] == '\'')
 3533 fujii@postgresql.org     1786                 :UBC           0 :             matches = complete_from_variables(text, ":'", "'", true);
 4811 rhaas@postgresql.org     1787         [ -  + ]:CBC           2 :         else if (text[1] == '"')
 3533 fujii@postgresql.org     1788                 :UBC           0 :             matches = complete_from_variables(text, ":\"", "\"", true);
   29 akorotkov@postgresql     1789   [ +  +  +  - ]:GNC           2 :         else if (text[1] == '{' && text[2] == '?')
                               1790                 :              1 :             matches = complete_from_variables(text, ":{?", "}", true);
                               1791                 :                :         else
 3533 fujii@postgresql.org     1792                 :CBC           1 :             matches = complete_from_variables(text, ":", "", true);
                               1793                 :                :     }
                               1794                 :                : 
                               1795                 :                :     /* If no previous word, suggest one of the basic sql commands */
 3039 tgl@sss.pgh.pa.us        1796         [ +  + ]:             64 :     else if (previous_words_count == 0)
 8768 bruce@momjian.us         1797                 :              2 :         COMPLETE_WITH_LIST(sql_commands);
                               1798                 :                : 
                               1799                 :                : /* CREATE */
                               1800                 :                :     /* complete with something you can create */
 2032 tgl@sss.pgh.pa.us        1801         [ +  + ]:             62 :     else if (TailMatches("CREATE"))
                               1802                 :                :     {
                               1803                 :                :         /* only some object types can be created as part of CREATE SCHEMA */
  289 michael@paquier.xyz      1804         [ -  + ]:GNC           1 :         if (HeadMatches("CREATE", "SCHEMA"))
  289 michael@paquier.xyz      1805                 :UNC           0 :             COMPLETE_WITH("TABLE", "VIEW", "INDEX", "SEQUENCE", "TRIGGER",
                               1806                 :                :             /* for INDEX and TABLE/SEQUENCE, respectively */
                               1807                 :                :                           "UNIQUE", "UNLOGGED");
                               1808                 :                :         else
  289 michael@paquier.xyz      1809                 :GNC           1 :             matches = rl_completion_matches(text, create_command_generator);
                               1810                 :                :     }
                               1811                 :                :     /* complete with something you can create or replace */
 1675 fujii@postgresql.org     1812         [ -  + ]:CBC          61 :     else if (TailMatches("CREATE", "OR", "REPLACE"))
 1675 fujii@postgresql.org     1813                 :UBC           0 :         COMPLETE_WITH("FUNCTION", "PROCEDURE", "LANGUAGE", "RULE", "VIEW",
                               1814                 :                :                       "AGGREGATE", "TRANSFORM", "TRIGGER");
                               1815                 :                : 
                               1816                 :                : /* DROP, but not DROP embedded in other commands */
                               1817                 :                :     /* complete with something you can drop */
 2032 tgl@sss.pgh.pa.us        1818         [ +  + ]:CBC          61 :     else if (Matches("DROP"))
 1584                          1819                 :              1 :         matches = rl_completion_matches(text, drop_command_generator);
                               1820                 :                : 
                               1821                 :                : /* ALTER */
                               1822                 :                : 
                               1823                 :                :     /* ALTER TABLE */
 2032                          1824         [ -  + ]:             60 :     else if (Matches("ALTER", "TABLE"))
  805 tgl@sss.pgh.pa.us        1825                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_tables,
                               1826                 :                :                                         "ALL IN TABLESPACE");
                               1827                 :                : 
                               1828                 :                :     /* ALTER something */
 2032 tgl@sss.pgh.pa.us        1829         [ -  + ]:CBC          60 :     else if (Matches("ALTER"))
 1584 tgl@sss.pgh.pa.us        1830                 :UBC           0 :         matches = rl_completion_matches(text, alter_command_generator);
                               1831                 :                :     /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx */
 2032 tgl@sss.pgh.pa.us        1832         [ -  + ]:CBC          60 :     else if (TailMatches("ALL", "IN", "TABLESPACE", MatchAny))
 2032 tgl@sss.pgh.pa.us        1833                 :UBC           0 :         COMPLETE_WITH("SET TABLESPACE", "OWNED BY");
                               1834                 :                :     /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY */
 2032 tgl@sss.pgh.pa.us        1835         [ -  + ]:CBC          60 :     else if (TailMatches("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY"))
 3507 sfrost@snowman.net       1836                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_roles);
                               1837                 :                :     /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY xxx */
 2032 tgl@sss.pgh.pa.us        1838         [ -  + ]:CBC          60 :     else if (TailMatches("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY", MatchAny))
 2032 tgl@sss.pgh.pa.us        1839                 :UBC           0 :         COMPLETE_WITH("SET TABLESPACE");
                               1840                 :                :     /* ALTER AGGREGATE,FUNCTION,PROCEDURE,ROUTINE <name> */
 2032 tgl@sss.pgh.pa.us        1841         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny))
 2032 tgl@sss.pgh.pa.us        1842                 :UBC           0 :         COMPLETE_WITH("(");
                               1843                 :                :     /* ALTER AGGREGATE <name> (...) */
 1152 michael@paquier.xyz      1844         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "AGGREGATE", MatchAny, MatchAny))
                               1845                 :                :     {
 3039 tgl@sss.pgh.pa.us        1846         [ #  # ]:UBC           0 :         if (ends_with(prev_wd, ')'))
 2032                          1847                 :              0 :             COMPLETE_WITH("OWNER TO", "RENAME TO", "SET SCHEMA");
                               1848                 :                :         else
 4301 magnus@hagander.net      1849                 :              0 :             COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
                               1850                 :                :     }
                               1851                 :                :     /* ALTER FUNCTION <name> (...) */
  464 dean.a.rasheed@gmail     1852         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "FUNCTION", MatchAny, MatchAny))
                               1853                 :                :     {
  464 dean.a.rasheed@gmail     1854         [ #  # ]:UBC           0 :         if (ends_with(prev_wd, ')'))
                               1855                 :              0 :             COMPLETE_WITH(Alter_function_options);
                               1856                 :                :         else
                               1857                 :              0 :             COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
                               1858                 :                :     }
                               1859                 :                :     /* ALTER PROCEDURE <name> (...) */
  464 dean.a.rasheed@gmail     1860         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "PROCEDURE", MatchAny, MatchAny))
                               1861                 :                :     {
  464 dean.a.rasheed@gmail     1862         [ #  # ]:UBC           0 :         if (ends_with(prev_wd, ')'))
                               1863                 :              0 :             COMPLETE_WITH(Alter_procedure_options);
                               1864                 :                :         else
                               1865                 :              0 :             COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
                               1866                 :                :     }
                               1867                 :                :     /* ALTER ROUTINE <name> (...) */
  464 dean.a.rasheed@gmail     1868         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "ROUTINE", MatchAny, MatchAny))
                               1869                 :                :     {
 1152 michael@paquier.xyz      1870         [ #  # ]:UBC           0 :         if (ends_with(prev_wd, ')'))
  464 dean.a.rasheed@gmail     1871                 :              0 :             COMPLETE_WITH(Alter_routine_options);
                               1872                 :                :         else
 1152 michael@paquier.xyz      1873                 :              0 :             COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
                               1874                 :                :     }
                               1875                 :                :     /* ALTER FUNCTION|ROUTINE <name> (...) PARALLEL */
  464 dean.a.rasheed@gmail     1876         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "FUNCTION|ROUTINE", MatchAny, MatchAny, "PARALLEL"))
  464 dean.a.rasheed@gmail     1877                 :UBC           0 :         COMPLETE_WITH("RESTRICTED", "SAFE", "UNSAFE");
                               1878                 :                :     /* ALTER FUNCTION|PROCEDURE|ROUTINE <name> (...) [EXTERNAL] SECURITY */
  464 dean.a.rasheed@gmail     1879   [ +  -  -  + ]:CBC         120 :     else if (Matches("ALTER", "FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny, "SECURITY") ||
                               1880                 :             60 :              Matches("ALTER", "FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny, "EXTERNAL", "SECURITY"))
  464 dean.a.rasheed@gmail     1881                 :UBC           0 :         COMPLETE_WITH("DEFINER", "INVOKER");
                               1882                 :                :     /* ALTER FUNCTION|PROCEDURE|ROUTINE <name> (...) RESET */
  464 dean.a.rasheed@gmail     1883         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny, "RESET"))
  464 dean.a.rasheed@gmail     1884                 :UBC           0 :         COMPLETE_WITH_QUERY_VERBATIM_PLUS(Query_for_list_of_set_vars,
                               1885                 :                :                                           "ALL");
                               1886                 :                :     /* ALTER FUNCTION|PROCEDURE|ROUTINE <name> (...) SET */
  464 dean.a.rasheed@gmail     1887         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny, "SET"))
  464 dean.a.rasheed@gmail     1888                 :UBC           0 :         COMPLETE_WITH_QUERY_VERBATIM_PLUS(Query_for_list_of_set_vars,
                               1889                 :                :                                           "SCHEMA");
                               1890                 :                : 
                               1891                 :                :     /* ALTER PUBLICATION <name> */
 2032 tgl@sss.pgh.pa.us        1892         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "PUBLICATION", MatchAny))
  900 akapila@postgresql.o     1893                 :UBC           0 :         COMPLETE_WITH("ADD", "DROP", "OWNER TO", "RENAME TO", "SET");
                               1894                 :                :     /* ALTER PUBLICATION <name> ADD */
  900 akapila@postgresql.o     1895         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "PUBLICATION", MatchAny, "ADD"))
  570 alvherre@alvh.no-ip.     1896                 :UBC           0 :         COMPLETE_WITH("TABLES IN SCHEMA", "TABLE");
  807 alvherre@alvh.no-ip.     1897   [ +  -  -  + ]:CBC         120 :     else if (Matches("ALTER", "PUBLICATION", MatchAny, "ADD|SET", "TABLE") ||
                               1898         [ -  - ]:             60 :              (HeadMatches("ALTER", "PUBLICATION", MatchAny, "ADD|SET", "TABLE") &&
  807 alvherre@alvh.no-ip.     1899                 :UBC           0 :               ends_with(prev_wd, ',')))
  805 tgl@sss.pgh.pa.us        1900                 :              0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
                               1901                 :                : 
                               1902                 :                :     /*
                               1903                 :                :      * "ALTER PUBLICATION <name> SET TABLE <name> WHERE (" - complete with
                               1904                 :                :      * table attributes
                               1905                 :                :      *
                               1906                 :                :      * "ALTER PUBLICATION <name> ADD TABLE <name> WHERE (" - complete with
                               1907                 :                :      * table attributes
                               1908                 :                :      */
  782 akapila@postgresql.o     1909   [ -  +  -  - ]:CBC          60 :     else if (HeadMatches("ALTER", "PUBLICATION", MatchAny) && TailMatches("WHERE"))
  782 akapila@postgresql.o     1910                 :UBC           0 :         COMPLETE_WITH("(");
  782 akapila@postgresql.o     1911   [ -  +  -  - ]:CBC          60 :     else if (HeadMatches("ALTER", "PUBLICATION", MatchAny) && TailMatches("WHERE", "("))
  782 akapila@postgresql.o     1912                 :UBC           0 :         COMPLETE_WITH_ATTR(prev3_wd);
  782 akapila@postgresql.o     1913         [ -  + ]:CBC          60 :     else if (HeadMatches("ALTER", "PUBLICATION", MatchAny, "ADD|SET", "TABLE") &&
  782 akapila@postgresql.o     1914         [ #  # ]:UBC           0 :              !TailMatches("WHERE", "(*)"))
                               1915                 :              0 :         COMPLETE_WITH(",", "WHERE (");
  807 alvherre@alvh.no-ip.     1916         [ -  + ]:CBC          60 :     else if (HeadMatches("ALTER", "PUBLICATION", MatchAny, "ADD|SET", "TABLE"))
  807 alvherre@alvh.no-ip.     1917                 :UBC           0 :         COMPLETE_WITH(",");
                               1918                 :                :     /* ALTER PUBLICATION <name> DROP */
  900 akapila@postgresql.o     1919         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "PUBLICATION", MatchAny, "DROP"))
  570 alvherre@alvh.no-ip.     1920                 :UBC           0 :         COMPLETE_WITH("TABLES IN SCHEMA", "TABLE");
                               1921                 :                :     /* ALTER PUBLICATION <name> SET */
 2032 tgl@sss.pgh.pa.us        1922         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET"))
  570 alvherre@alvh.no-ip.     1923                 :UBC           0 :         COMPLETE_WITH("(", "TABLES IN SCHEMA", "TABLE");
  562 alvherre@alvh.no-ip.     1924         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "PUBLICATION", MatchAny, "ADD|DROP|SET", "TABLES", "IN", "SCHEMA"))
  805 tgl@sss.pgh.pa.us        1925                 :UBC           0 :         COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_schemas
                               1926                 :                :                                  " AND nspname NOT LIKE E'pg\\\\_%%'",
                               1927                 :                :                                  "CURRENT_SCHEMA");
                               1928                 :                :     /* ALTER PUBLICATION <name> SET ( */
 2032 tgl@sss.pgh.pa.us        1929   [ -  +  -  - ]:CBC          60 :     else if (HeadMatches("ALTER", "PUBLICATION", MatchAny) && TailMatches("SET", "("))
 1038 michael@paquier.xyz      1930                 :UBC           0 :         COMPLETE_WITH("publish", "publish_via_partition_root");
                               1931                 :                :     /* ALTER SUBSCRIPTION <name> */
 2032 tgl@sss.pgh.pa.us        1932         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "SUBSCRIPTION", MatchAny))
 2032 tgl@sss.pgh.pa.us        1933                 :UBC           0 :         COMPLETE_WITH("CONNECTION", "ENABLE", "DISABLE", "OWNER TO",
                               1934                 :                :                       "RENAME TO", "REFRESH PUBLICATION", "SET", "SKIP (",
                               1935                 :                :                       "ADD PUBLICATION", "DROP PUBLICATION");
                               1936                 :                :     /* ALTER SUBSCRIPTION <name> REFRESH PUBLICATION */
 2032 tgl@sss.pgh.pa.us        1937   [ -  +  -  - ]:CBC          60 :     else if (HeadMatches("ALTER", "SUBSCRIPTION", MatchAny) &&
 2032 tgl@sss.pgh.pa.us        1938                 :UBC           0 :              TailMatches("REFRESH", "PUBLICATION"))
                               1939                 :              0 :         COMPLETE_WITH("WITH (");
                               1940                 :                :     /* ALTER SUBSCRIPTION <name> REFRESH PUBLICATION WITH ( */
 2032 tgl@sss.pgh.pa.us        1941   [ -  +  -  - ]:CBC          60 :     else if (HeadMatches("ALTER", "SUBSCRIPTION", MatchAny) &&
 2032 tgl@sss.pgh.pa.us        1942                 :UBC           0 :              TailMatches("REFRESH", "PUBLICATION", "WITH", "("))
                               1943                 :              0 :         COMPLETE_WITH("copy_data");
                               1944                 :                :     /* ALTER SUBSCRIPTION <name> SET */
 2032 tgl@sss.pgh.pa.us        1945         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, "SET"))
 2032 tgl@sss.pgh.pa.us        1946                 :UBC           0 :         COMPLETE_WITH("(", "PUBLICATION");
                               1947                 :                :     /* ALTER SUBSCRIPTION <name> SET ( */
 2032 tgl@sss.pgh.pa.us        1948   [ -  +  -  - ]:CBC          60 :     else if (HeadMatches("ALTER", "SUBSCRIPTION", MatchAny) && TailMatches("SET", "("))
   75 akapila@postgresql.o     1949                 :UNC           0 :         COMPLETE_WITH("binary", "disable_on_error", "failover", "origin",
                               1950                 :                :                       "password_required", "run_as_owner", "slot_name",
                               1951                 :                :                       "streaming", "synchronous_commit");
                               1952                 :                :     /* ALTER SUBSCRIPTION <name> SKIP ( */
  754 akapila@postgresql.o     1953   [ -  +  -  - ]:CBC          60 :     else if (HeadMatches("ALTER", "SUBSCRIPTION", MatchAny) && TailMatches("SKIP", "("))
  754 akapila@postgresql.o     1954                 :UBC           0 :         COMPLETE_WITH("lsn");
                               1955                 :                :     /* ALTER SUBSCRIPTION <name> SET PUBLICATION */
 2032 tgl@sss.pgh.pa.us        1956   [ -  +  -  - ]:CBC          60 :     else if (HeadMatches("ALTER", "SUBSCRIPTION", MatchAny) && TailMatches("SET", "PUBLICATION"))
                               1957                 :                :     {
                               1958                 :                :         /* complete with nothing here as this refers to remote publications */
                               1959                 :                :     }
                               1960                 :                :     /* ALTER SUBSCRIPTION <name> ADD|DROP|SET PUBLICATION <name> */
                               1961   [ -  +  -  - ]:             60 :     else if (HeadMatches("ALTER", "SUBSCRIPTION", MatchAny) &&
 1104 peter@eisentraut.org     1962                 :UBC           0 :              TailMatches("ADD|DROP|SET", "PUBLICATION", MatchAny))
 2032 tgl@sss.pgh.pa.us        1963                 :              0 :         COMPLETE_WITH("WITH (");
                               1964                 :                :     /* ALTER SUBSCRIPTION <name> ADD|DROP|SET PUBLICATION <name> WITH ( */
 2032 tgl@sss.pgh.pa.us        1965   [ -  +  -  - ]:CBC          60 :     else if (HeadMatches("ALTER", "SUBSCRIPTION", MatchAny) &&
  964 akapila@postgresql.o     1966                 :UBC           0 :              TailMatches("ADD|DROP|SET", "PUBLICATION", MatchAny, "WITH", "("))
 2032 tgl@sss.pgh.pa.us        1967                 :              0 :         COMPLETE_WITH("copy_data", "refresh");
                               1968                 :                : 
                               1969                 :                :     /* ALTER SCHEMA <name> */
 2032 tgl@sss.pgh.pa.us        1970         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "SCHEMA", MatchAny))
 2032 tgl@sss.pgh.pa.us        1971                 :UBC           0 :         COMPLETE_WITH("OWNER TO", "RENAME TO");
                               1972                 :                : 
                               1973                 :                :     /* ALTER COLLATION <name> */
 2032 tgl@sss.pgh.pa.us        1974         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "COLLATION", MatchAny))
  808 peter@eisentraut.org     1975                 :UBC           0 :         COMPLETE_WITH("OWNER TO", "REFRESH VERSION", "RENAME TO", "SET SCHEMA");
                               1976                 :                : 
                               1977                 :                :     /* ALTER CONVERSION <name> */
 2032 tgl@sss.pgh.pa.us        1978         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "CONVERSION", MatchAny))
 2032 tgl@sss.pgh.pa.us        1979                 :UBC           0 :         COMPLETE_WITH("OWNER TO", "RENAME TO", "SET SCHEMA");
                               1980                 :                : 
                               1981                 :                :     /* ALTER DATABASE <name> */
 2032 tgl@sss.pgh.pa.us        1982         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "DATABASE", MatchAny))
  790 peter@eisentraut.org     1983                 :UBC           0 :         COMPLETE_WITH("RESET", "SET", "OWNER TO", "REFRESH COLLATION VERSION", "RENAME TO",
                               1984                 :                :                       "IS_TEMPLATE", "ALLOW_CONNECTIONS",
                               1985                 :                :                       "CONNECTION LIMIT");
                               1986                 :                : 
                               1987                 :                :     /* ALTER DATABASE <name> SET TABLESPACE */
 2032 tgl@sss.pgh.pa.us        1988         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "DATABASE", MatchAny, "SET", "TABLESPACE"))
 2033 tgl@sss.pgh.pa.us        1989                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
                               1990                 :                : 
                               1991                 :                :     /* ALTER EVENT TRIGGER */
 2032 tgl@sss.pgh.pa.us        1992         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "EVENT", "TRIGGER"))
 3653 rhaas@postgresql.org     1993                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
                               1994                 :                : 
                               1995                 :                :     /* ALTER EVENT TRIGGER <name> */
 2032 tgl@sss.pgh.pa.us        1996         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "EVENT", "TRIGGER", MatchAny))
 2032 tgl@sss.pgh.pa.us        1997                 :UBC           0 :         COMPLETE_WITH("DISABLE", "ENABLE", "OWNER TO", "RENAME TO");
                               1998                 :                : 
                               1999                 :                :     /* ALTER EVENT TRIGGER <name> ENABLE */
 2032 tgl@sss.pgh.pa.us        2000         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "EVENT", "TRIGGER", MatchAny, "ENABLE"))
 2032 tgl@sss.pgh.pa.us        2001                 :UBC           0 :         COMPLETE_WITH("REPLICA", "ALWAYS");
                               2002                 :                : 
                               2003                 :                :     /* ALTER EXTENSION <name> */
 2032 tgl@sss.pgh.pa.us        2004         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "EXTENSION", MatchAny))
  651 tgl@sss.pgh.pa.us        2005                 :UBC           0 :         COMPLETE_WITH("ADD", "DROP", "UPDATE", "SET SCHEMA");
                               2006                 :                : 
                               2007                 :                :     /* ALTER EXTENSION <name> ADD|DROP */
  458 michael@paquier.xyz      2008         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "EXTENSION", MatchAny, "ADD|DROP"))
  458 michael@paquier.xyz      2009                 :UBC           0 :         COMPLETE_WITH("ACCESS METHOD", "AGGREGATE", "CAST", "COLLATION",
                               2010                 :                :                       "CONVERSION", "DOMAIN", "EVENT TRIGGER", "FOREIGN",
                               2011                 :                :                       "FUNCTION", "MATERIALIZED VIEW", "OPERATOR",
                               2012                 :                :                       "LANGUAGE", "PROCEDURE", "ROUTINE", "SCHEMA",
                               2013                 :                :                       "SEQUENCE", "SERVER", "TABLE", "TEXT SEARCH",
                               2014                 :                :                       "TRANSFORM FOR", "TYPE", "VIEW");
                               2015                 :                : 
                               2016                 :                :     /* ALTER EXTENSION <name> ADD|DROP FOREIGN */
  458 michael@paquier.xyz      2017         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "EXTENSION", MatchAny, "ADD|DROP", "FOREIGN"))
  458 michael@paquier.xyz      2018                 :UBC           0 :         COMPLETE_WITH("DATA WRAPPER", "TABLE");
                               2019                 :                : 
                               2020                 :                :     /* ALTER EXTENSION <name> ADD|DROP OPERATOR */
  458 michael@paquier.xyz      2021         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "EXTENSION", MatchAny, "ADD|DROP", "OPERATOR"))
  458 michael@paquier.xyz      2022                 :UBC           0 :         COMPLETE_WITH("CLASS", "FAMILY");
                               2023                 :                : 
                               2024                 :                :     /* ALTER EXTENSION <name> ADD|DROP TEXT SEARCH */
  458 michael@paquier.xyz      2025         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "EXTENSION", MatchAny, "ADD|DROP", "TEXT", "SEARCH"))
  458 michael@paquier.xyz      2026                 :UBC           0 :         COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
                               2027                 :                : 
                               2028                 :                :     /* ALTER EXTENSION <name> UPDATE */
 2032 tgl@sss.pgh.pa.us        2029         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "EXTENSION", MatchAny, "UPDATE"))
  663 tgl@sss.pgh.pa.us        2030                 :UBC           0 :         COMPLETE_WITH("TO");
                               2031                 :                : 
                               2032                 :                :     /* ALTER EXTENSION <name> UPDATE TO */
 2032 tgl@sss.pgh.pa.us        2033         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "EXTENSION", MatchAny, "UPDATE", "TO"))
                               2034                 :                :     {
  805 tgl@sss.pgh.pa.us        2035                 :UBC           0 :         set_completion_reference(prev3_wd);
  663                          2036                 :              0 :         COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions);
                               2037                 :                :     }
                               2038                 :                : 
                               2039                 :                :     /* ALTER FOREIGN */
 2032 tgl@sss.pgh.pa.us        2040         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "FOREIGN"))
 2032 tgl@sss.pgh.pa.us        2041                 :UBC           0 :         COMPLETE_WITH("DATA WRAPPER", "TABLE");
                               2042                 :                : 
                               2043                 :                :     /* ALTER FOREIGN DATA WRAPPER <name> */
 2032 tgl@sss.pgh.pa.us        2044         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "FOREIGN", "DATA", "WRAPPER", MatchAny))
  867 michael@paquier.xyz      2045                 :UBC           0 :         COMPLETE_WITH("HANDLER", "VALIDATOR", "NO",
                               2046                 :                :                       "OPTIONS", "OWNER TO", "RENAME TO");
  867 michael@paquier.xyz      2047         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "FOREIGN", "DATA", "WRAPPER", MatchAny, "NO"))
  867 michael@paquier.xyz      2048                 :UBC           0 :         COMPLETE_WITH("HANDLER", "VALIDATOR");
                               2049                 :                : 
                               2050                 :                :     /* ALTER FOREIGN TABLE <name> */
 2032 tgl@sss.pgh.pa.us        2051         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "FOREIGN", "TABLE", MatchAny))
 2032 tgl@sss.pgh.pa.us        2052                 :UBC           0 :         COMPLETE_WITH("ADD", "ALTER", "DISABLE TRIGGER", "DROP", "ENABLE",
                               2053                 :                :                       "INHERIT", "NO INHERIT", "OPTIONS", "OWNER TO",
                               2054                 :                :                       "RENAME", "SET", "VALIDATE CONSTRAINT");
                               2055                 :                : 
                               2056                 :                :     /* ALTER INDEX */
 2032 tgl@sss.pgh.pa.us        2057         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "INDEX"))
  805 tgl@sss.pgh.pa.us        2058                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_indexes,
                               2059                 :                :                                         "ALL IN TABLESPACE");
                               2060                 :                :     /* ALTER INDEX <name> */
 2032 tgl@sss.pgh.pa.us        2061         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "INDEX", MatchAny))
 2032 tgl@sss.pgh.pa.us        2062                 :UBC           0 :         COMPLETE_WITH("ALTER COLUMN", "OWNER TO", "RENAME TO", "SET",
                               2063                 :                :                       "RESET", "ATTACH PARTITION",
                               2064                 :                :                       "DEPENDS ON EXTENSION", "NO DEPENDS ON EXTENSION");
 2032 tgl@sss.pgh.pa.us        2065         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "INDEX", MatchAny, "ATTACH"))
 2032 tgl@sss.pgh.pa.us        2066                 :UBC           0 :         COMPLETE_WITH("PARTITION");
 2032 tgl@sss.pgh.pa.us        2067         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "INDEX", MatchAny, "ATTACH", "PARTITION"))
  805 tgl@sss.pgh.pa.us        2068                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes);
                               2069                 :                :     /* ALTER INDEX <name> ALTER */
 1937 michael@paquier.xyz      2070         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "INDEX", MatchAny, "ALTER"))
 1073 tmunro@postgresql.or     2071                 :UBC           0 :         COMPLETE_WITH("COLUMN");
                               2072                 :                :     /* ALTER INDEX <name> ALTER COLUMN */
 1903 michael@paquier.xyz      2073         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "INDEX", MatchAny, "ALTER", "COLUMN"))
                               2074                 :                :     {
  805 tgl@sss.pgh.pa.us        2075                 :UBC           0 :         set_completion_reference(prev3_wd);
                               2076                 :              0 :         COMPLETE_WITH_SCHEMA_QUERY_VERBATIM(Query_for_list_of_attribute_numbers);
                               2077                 :                :     }
                               2078                 :                :     /* ALTER INDEX <name> ALTER COLUMN <colnum> */
 2032 tgl@sss.pgh.pa.us        2079         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "INDEX", MatchAny, "ALTER", "COLUMN", MatchAny))
 2032 tgl@sss.pgh.pa.us        2080                 :UBC           0 :         COMPLETE_WITH("SET STATISTICS");
                               2081                 :                :     /* ALTER INDEX <name> ALTER COLUMN <colnum> SET */
 1937 michael@paquier.xyz      2082         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "INDEX", MatchAny, "ALTER", "COLUMN", MatchAny, "SET"))
 1937 michael@paquier.xyz      2083                 :UBC           0 :         COMPLETE_WITH("STATISTICS");
                               2084                 :                :     /* ALTER INDEX <name> ALTER COLUMN <colnum> SET STATISTICS */
 1937 michael@paquier.xyz      2085         [ +  - ]:CBC          60 :     else if (Matches("ALTER", "INDEX", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "STATISTICS"))
                               2086                 :                :     {
                               2087                 :                :         /* Enforce no completion here, as an integer has to be specified */
                               2088                 :                :     }
                               2089                 :                :     /* ALTER INDEX <name> SET */
 2032 tgl@sss.pgh.pa.us        2090         [ -  + ]:             60 :     else if (Matches("ALTER", "INDEX", MatchAny, "SET"))
 2032 tgl@sss.pgh.pa.us        2091                 :UBC           0 :         COMPLETE_WITH("(", "TABLESPACE");
                               2092                 :                :     /* ALTER INDEX <name> RESET */
 2032 tgl@sss.pgh.pa.us        2093         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "INDEX", MatchAny, "RESET"))
 2032 tgl@sss.pgh.pa.us        2094                 :UBC           0 :         COMPLETE_WITH("(");
                               2095                 :                :     /* ALTER INDEX <foo> SET|RESET ( */
 2032 tgl@sss.pgh.pa.us        2096         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "INDEX", MatchAny, "RESET", "("))
 1916 tgl@sss.pgh.pa.us        2097                 :UBC           0 :         COMPLETE_WITH("fillfactor",
                               2098                 :                :                       "deduplicate_items",    /* BTREE */
                               2099                 :                :                       "fastupdate", "gin_pending_list_limit",   /* GIN */
                               2100                 :                :                       "buffering",    /* GiST */
                               2101                 :                :                       "pages_per_range", "autosummarize"    /* BRIN */
                               2102                 :                :             );
 2032 tgl@sss.pgh.pa.us        2103         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "INDEX", MatchAny, "SET", "("))
 1916 tgl@sss.pgh.pa.us        2104                 :UBC           0 :         COMPLETE_WITH("fillfactor =",
                               2105                 :                :                       "deduplicate_items =",  /* BTREE */
                               2106                 :                :                       "fastupdate =", "gin_pending_list_limit =",   /* GIN */
                               2107                 :                :                       "buffering =",  /* GiST */
                               2108                 :                :                       "pages_per_range =", "autosummarize ="    /* BRIN */
                               2109                 :                :             );
 1073 tmunro@postgresql.or     2110         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "INDEX", MatchAny, "NO", "DEPENDS"))
 1073 tmunro@postgresql.or     2111                 :UBC           0 :         COMPLETE_WITH("ON EXTENSION");
 1073 tmunro@postgresql.or     2112         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "INDEX", MatchAny, "DEPENDS"))
 1073 tmunro@postgresql.or     2113                 :UBC           0 :         COMPLETE_WITH("ON EXTENSION");
                               2114                 :                : 
                               2115                 :                :     /* ALTER LANGUAGE <name> */
 2032 tgl@sss.pgh.pa.us        2116         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "LANGUAGE", MatchAny))
 1714 michael@paquier.xyz      2117                 :UBC           0 :         COMPLETE_WITH("OWNER TO", "RENAME TO");
                               2118                 :                : 
                               2119                 :                :     /* ALTER LARGE OBJECT <oid> */
 2032 tgl@sss.pgh.pa.us        2120         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "LARGE", "OBJECT", MatchAny))
 2032 tgl@sss.pgh.pa.us        2121                 :UBC           0 :         COMPLETE_WITH("OWNER TO");
                               2122                 :                : 
                               2123                 :                :     /* ALTER MATERIALIZED VIEW */
 2032 tgl@sss.pgh.pa.us        2124         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "MATERIALIZED", "VIEW"))
  805 tgl@sss.pgh.pa.us        2125                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_matviews,
                               2126                 :                :                                         "ALL IN TABLESPACE");
                               2127                 :                : 
                               2128                 :                :     /* ALTER USER,ROLE <name> */
 2032 tgl@sss.pgh.pa.us        2129         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "USER|ROLE", MatchAny) &&
 2032 tgl@sss.pgh.pa.us        2130         [ #  # ]:UBC           0 :              !TailMatches("USER", "MAPPING"))
                               2131                 :              0 :         COMPLETE_WITH("BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
                               2132                 :                :                       "ENCRYPTED PASSWORD", "INHERIT", "LOGIN", "NOBYPASSRLS",
                               2133                 :                :                       "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
                               2134                 :                :                       "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
                               2135                 :                :                       "RENAME TO", "REPLICATION", "RESET", "SET", "SUPERUSER",
                               2136                 :                :                       "VALID UNTIL", "WITH");
                               2137                 :                : 
                               2138                 :                :     /* ALTER USER,ROLE <name> WITH */
 2032 tgl@sss.pgh.pa.us        2139         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "USER|ROLE", MatchAny, "WITH"))
                               2140                 :                :         /* Similar to the above, but don't complete "WITH" again. */
 2032 tgl@sss.pgh.pa.us        2141                 :UBC           0 :         COMPLETE_WITH("BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
                               2142                 :                :                       "ENCRYPTED PASSWORD", "INHERIT", "LOGIN", "NOBYPASSRLS",
                               2143                 :                :                       "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
                               2144                 :                :                       "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
                               2145                 :                :                       "RENAME TO", "REPLICATION", "RESET", "SET", "SUPERUSER",
                               2146                 :                :                       "VALID UNTIL");
                               2147                 :                : 
                               2148                 :                :     /* ALTER DEFAULT PRIVILEGES */
 2032 tgl@sss.pgh.pa.us        2149         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "DEFAULT", "PRIVILEGES"))
    6 msawada@postgresql.o     2150                 :UNC           0 :         COMPLETE_WITH("FOR", "GRANT", "IN SCHEMA", "REVOKE");
                               2151                 :                :     /* ALTER DEFAULT PRIVILEGES FOR */
 2032 tgl@sss.pgh.pa.us        2152         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "FOR"))
 2032 tgl@sss.pgh.pa.us        2153                 :UBC           0 :         COMPLETE_WITH("ROLE");
                               2154                 :                :     /* ALTER DEFAULT PRIVILEGES IN */
 2032 tgl@sss.pgh.pa.us        2155         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "IN"))
 2032 tgl@sss.pgh.pa.us        2156                 :UBC           0 :         COMPLETE_WITH("SCHEMA");
                               2157                 :                :     /* ALTER DEFAULT PRIVILEGES FOR ROLE|USER ... */
 2032 tgl@sss.pgh.pa.us        2158         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER",
                               2159                 :                :                      MatchAny))
 2032 tgl@sss.pgh.pa.us        2160                 :UBC           0 :         COMPLETE_WITH("GRANT", "REVOKE", "IN SCHEMA");
                               2161                 :                :     /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... */
 2032 tgl@sss.pgh.pa.us        2162         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
                               2163                 :                :                      MatchAny))
 2032 tgl@sss.pgh.pa.us        2164                 :UBC           0 :         COMPLETE_WITH("GRANT", "REVOKE", "FOR ROLE");
                               2165                 :                :     /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... FOR */
 2032 tgl@sss.pgh.pa.us        2166         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
                               2167                 :                :                      MatchAny, "FOR"))
 2032 tgl@sss.pgh.pa.us        2168                 :UBC           0 :         COMPLETE_WITH("ROLE");
                               2169                 :                :     /* ALTER DEFAULT PRIVILEGES FOR ROLE|USER ... IN SCHEMA ... */
                               2170                 :                :     /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... FOR ROLE|USER ... */
 2032 tgl@sss.pgh.pa.us        2171         [ +  - ]:CBC          60 :     else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER",
                               2172         [ -  + ]:             60 :                      MatchAny, "IN", "SCHEMA", MatchAny) ||
                               2173                 :             60 :              Matches("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
                               2174                 :                :                      MatchAny, "FOR", "ROLE|USER", MatchAny))
 2032 tgl@sss.pgh.pa.us        2175                 :UBC           0 :         COMPLETE_WITH("GRANT", "REVOKE");
                               2176                 :                :     /* ALTER DOMAIN <name> */
 2032 tgl@sss.pgh.pa.us        2177         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "DOMAIN", MatchAny))
 2032 tgl@sss.pgh.pa.us        2178                 :UBC           0 :         COMPLETE_WITH("ADD", "DROP", "OWNER TO", "RENAME", "SET",
                               2179                 :                :                       "VALIDATE CONSTRAINT");
                               2180                 :                :     /* ALTER DOMAIN <sth> DROP */
 2032 tgl@sss.pgh.pa.us        2181         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "DOMAIN", MatchAny, "DROP"))
 2032 tgl@sss.pgh.pa.us        2182                 :UBC           0 :         COMPLETE_WITH("CONSTRAINT", "DEFAULT", "NOT NULL");
                               2183                 :                :     /* ALTER DOMAIN <sth> DROP|RENAME|VALIDATE CONSTRAINT */
 2032 tgl@sss.pgh.pa.us        2184         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "DOMAIN", MatchAny, "DROP|RENAME|VALIDATE", "CONSTRAINT"))
                               2185                 :                :     {
  805 tgl@sss.pgh.pa.us        2186                 :UBC           0 :         set_completion_reference(prev3_wd);
                               2187                 :              0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_constraint_of_type);
                               2188                 :                :     }
                               2189                 :                :     /* ALTER DOMAIN <sth> RENAME */
 2032 tgl@sss.pgh.pa.us        2190         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "DOMAIN", MatchAny, "RENAME"))
 2032 tgl@sss.pgh.pa.us        2191                 :UBC           0 :         COMPLETE_WITH("CONSTRAINT", "TO");
                               2192                 :                :     /* ALTER DOMAIN <sth> RENAME CONSTRAINT <sth> */
 2032 tgl@sss.pgh.pa.us        2193         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "DOMAIN", MatchAny, "RENAME", "CONSTRAINT", MatchAny))
 2032 tgl@sss.pgh.pa.us        2194                 :UBC           0 :         COMPLETE_WITH("TO");
                               2195                 :                : 
                               2196                 :                :     /* ALTER DOMAIN <sth> SET */
 2032 tgl@sss.pgh.pa.us        2197         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "DOMAIN", MatchAny, "SET"))
 2032 tgl@sss.pgh.pa.us        2198                 :UBC           0 :         COMPLETE_WITH("DEFAULT", "NOT NULL", "SCHEMA");
                               2199                 :                :     /* ALTER SEQUENCE <name> */
 2032 tgl@sss.pgh.pa.us        2200         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "SEQUENCE", MatchAny))
  867 michael@paquier.xyz      2201                 :UBC           0 :         COMPLETE_WITH("AS", "INCREMENT", "MINVALUE", "MAXVALUE", "RESTART",
                               2202                 :                :                       "START", "NO", "CACHE", "CYCLE", "SET", "OWNED BY",
                               2203                 :                :                       "OWNER TO", "RENAME TO");
                               2204                 :                :     /* ALTER SEQUENCE <name> AS */
  867 michael@paquier.xyz      2205         [ -  + ]:CBC          60 :     else if (TailMatches("ALTER", "SEQUENCE", MatchAny, "AS"))
  867 michael@paquier.xyz      2206                 :UBC           0 :         COMPLETE_WITH_CS("smallint", "integer", "bigint");
                               2207                 :                :     /* ALTER SEQUENCE <name> NO */
 2032 tgl@sss.pgh.pa.us        2208         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "SEQUENCE", MatchAny, "NO"))
 2032 tgl@sss.pgh.pa.us        2209                 :UBC           0 :         COMPLETE_WITH("MINVALUE", "MAXVALUE", "CYCLE");
                               2210                 :                :     /* ALTER SEQUENCE <name> SET */
  738 peter@eisentraut.org     2211         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "SEQUENCE", MatchAny, "SET"))
  738 peter@eisentraut.org     2212                 :UBC           0 :         COMPLETE_WITH("SCHEMA", "LOGGED", "UNLOGGED");
                               2213                 :                :     /* ALTER SERVER <name> */
 2032 tgl@sss.pgh.pa.us        2214         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "SERVER", MatchAny))
 2032 tgl@sss.pgh.pa.us        2215                 :UBC           0 :         COMPLETE_WITH("VERSION", "OPTIONS", "OWNER TO", "RENAME TO");
                               2216                 :                :     /* ALTER SERVER <name> VERSION <version> */
 2032 tgl@sss.pgh.pa.us        2217         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "SERVER", MatchAny, "VERSION", MatchAny))
 2032 tgl@sss.pgh.pa.us        2218                 :UBC           0 :         COMPLETE_WITH("OPTIONS");
                               2219                 :                :     /* ALTER SYSTEM SET, RESET, RESET ALL */
 2032 tgl@sss.pgh.pa.us        2220         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "SYSTEM"))
 2032 tgl@sss.pgh.pa.us        2221                 :UBC           0 :         COMPLETE_WITH("SET", "RESET");
 2032 tgl@sss.pgh.pa.us        2222         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "SYSTEM", "SET|RESET"))
  795 tgl@sss.pgh.pa.us        2223                 :UBC           0 :         COMPLETE_WITH_QUERY_VERBATIM_PLUS(Query_for_list_of_alter_system_set_vars,
                               2224                 :                :                                           "ALL");
 2032 tgl@sss.pgh.pa.us        2225         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "SYSTEM", "SET", MatchAny))
 2032 tgl@sss.pgh.pa.us        2226                 :UBC           0 :         COMPLETE_WITH("TO");
                               2227                 :                :     /* ALTER VIEW <name> */
 2032 tgl@sss.pgh.pa.us        2228         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "VIEW", MatchAny))
  138 dean.a.rasheed@gmail     2229                 :UNC           0 :         COMPLETE_WITH("ALTER COLUMN", "OWNER TO", "RENAME", "RESET", "SET");
                               2230                 :                :     /* ALTER VIEW xxx RENAME */
 1606 fujii@postgresql.org     2231         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "VIEW", MatchAny, "RENAME"))
  805 tgl@sss.pgh.pa.us        2232                 :UBC           0 :         COMPLETE_WITH_ATTR_PLUS(prev2_wd, "COLUMN", "TO");
 1606 fujii@postgresql.org     2233         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "VIEW", MatchAny, "ALTER|RENAME", "COLUMN"))
  805 tgl@sss.pgh.pa.us        2234                 :UBC           0 :         COMPLETE_WITH_ATTR(prev3_wd);
                               2235                 :                :     /* ALTER VIEW xxx ALTER [ COLUMN ] yyy */
  867 michael@paquier.xyz      2236   [ +  -  -  + ]:CBC         120 :     else if (Matches("ALTER", "VIEW", MatchAny, "ALTER", MatchAny) ||
                               2237                 :             60 :              Matches("ALTER", "VIEW", MatchAny, "ALTER", "COLUMN", MatchAny))
  867 michael@paquier.xyz      2238                 :UBC           0 :         COMPLETE_WITH("SET DEFAULT", "DROP DEFAULT");
                               2239                 :                :     /* ALTER VIEW xxx RENAME yyy */
 1606 fujii@postgresql.org     2240         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "VIEW", MatchAny, "RENAME", MatchAnyExcept("TO")))
 1606 fujii@postgresql.org     2241                 :UBC           0 :         COMPLETE_WITH("TO");
                               2242                 :                :     /* ALTER VIEW xxx RENAME COLUMN yyy */
 1606 fujii@postgresql.org     2243         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "VIEW", MatchAny, "RENAME", "COLUMN", MatchAnyExcept("TO")))
 1606 fujii@postgresql.org     2244                 :UBC           0 :         COMPLETE_WITH("TO");
                               2245                 :                :     /* ALTER VIEW xxx RESET ( */
  138 dean.a.rasheed@gmail     2246         [ -  + ]:GNC          60 :     else if (Matches("ALTER", "VIEW", MatchAny, "RESET"))
  138 dean.a.rasheed@gmail     2247                 :UNC           0 :         COMPLETE_WITH("(");
                               2248                 :                :     /* Complete ALTER VIEW xxx SET with "(" or "SCHEMA" */
  138 dean.a.rasheed@gmail     2249         [ -  + ]:GNC          60 :     else if (Matches("ALTER", "VIEW", MatchAny, "SET"))
  138 dean.a.rasheed@gmail     2250                 :UNC           0 :         COMPLETE_WITH("(", "SCHEMA");
                               2251                 :                :     /* ALTER VIEW xxx SET|RESET ( yyy [= zzz] ) */
  138 dean.a.rasheed@gmail     2252         [ -  + ]:GNC          60 :     else if (Matches("ALTER", "VIEW", MatchAny, "SET|RESET", "("))
  138 dean.a.rasheed@gmail     2253                 :UNC           0 :         COMPLETE_WITH_LIST(view_optional_parameters);
  138 dean.a.rasheed@gmail     2254         [ -  + ]:GNC          60 :     else if (Matches("ALTER", "VIEW", MatchAny, "SET", "(", MatchAny))
  138 dean.a.rasheed@gmail     2255                 :UNC           0 :         COMPLETE_WITH("=");
  138 dean.a.rasheed@gmail     2256         [ -  + ]:GNC          60 :     else if (Matches("ALTER", "VIEW", MatchAny, "SET", "(", "check_option", "="))
  138 dean.a.rasheed@gmail     2257                 :UNC           0 :         COMPLETE_WITH("local", "cascaded");
  138 dean.a.rasheed@gmail     2258         [ -  + ]:GNC          60 :     else if (Matches("ALTER", "VIEW", MatchAny, "SET", "(", "security_barrier|security_invoker", "="))
  138 dean.a.rasheed@gmail     2259                 :UNC           0 :         COMPLETE_WITH("true", "false");
                               2260                 :                : 
                               2261                 :                :     /* ALTER MATERIALIZED VIEW <name> */
 2032 tgl@sss.pgh.pa.us        2262         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny))
 1606 fujii@postgresql.org     2263                 :UBC           0 :         COMPLETE_WITH("ALTER COLUMN", "CLUSTER ON", "DEPENDS ON EXTENSION",
                               2264                 :                :                       "NO DEPENDS ON EXTENSION", "OWNER TO", "RENAME",
                               2265                 :                :                       "RESET (", "SET");
                               2266                 :                :     /* ALTER MATERIALIZED VIEW xxx RENAME */
 1606 fujii@postgresql.org     2267         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny, "RENAME"))
  805 tgl@sss.pgh.pa.us        2268                 :UBC           0 :         COMPLETE_WITH_ATTR_PLUS(prev2_wd, "COLUMN", "TO");
 1606 fujii@postgresql.org     2269         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny, "ALTER|RENAME", "COLUMN"))
  805 tgl@sss.pgh.pa.us        2270                 :UBC           0 :         COMPLETE_WITH_ATTR(prev3_wd);
                               2271                 :                :     /* ALTER MATERIALIZED VIEW xxx RENAME yyy */
 1606 fujii@postgresql.org     2272         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny, "RENAME", MatchAnyExcept("TO")))
 1606 fujii@postgresql.org     2273                 :UBC           0 :         COMPLETE_WITH("TO");
                               2274                 :                :     /* ALTER MATERIALIZED VIEW xxx RENAME COLUMN yyy */
 1606 fujii@postgresql.org     2275         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny, "RENAME", "COLUMN", MatchAnyExcept("TO")))
 1606 fujii@postgresql.org     2276                 :UBC           0 :         COMPLETE_WITH("TO");
                               2277                 :                :     /* ALTER MATERIALIZED VIEW xxx SET */
 1606 fujii@postgresql.org     2278         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny, "SET"))
  757 michael@paquier.xyz      2279                 :UBC           0 :         COMPLETE_WITH("(", "ACCESS METHOD", "SCHEMA", "TABLESPACE", "WITHOUT CLUSTER");
                               2280                 :                :     /* ALTER MATERIALIZED VIEW xxx SET ACCESS METHOD */
  757 michael@paquier.xyz      2281         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny, "SET", "ACCESS", "METHOD"))
  757 michael@paquier.xyz      2282                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_table_access_methods);
                               2283                 :                : 
                               2284                 :                :     /* ALTER POLICY <name> */
 2032 tgl@sss.pgh.pa.us        2285         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "POLICY"))
 3048 rhaas@postgresql.org     2286                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_policies);
                               2287                 :                :     /* ALTER POLICY <name> ON */
 2032 tgl@sss.pgh.pa.us        2288         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "POLICY", MatchAny))
 2032 tgl@sss.pgh.pa.us        2289                 :UBC           0 :         COMPLETE_WITH("ON");
                               2290                 :                :     /* ALTER POLICY <name> ON <table> */
 2032 tgl@sss.pgh.pa.us        2291         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "POLICY", MatchAny, "ON"))
                               2292                 :                :     {
  805 tgl@sss.pgh.pa.us        2293                 :UBC           0 :         set_completion_reference(prev2_wd);
                               2294                 :              0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables_for_policy);
                               2295                 :                :     }
                               2296                 :                :     /* ALTER POLICY <name> ON <table> - show options */
 2032 tgl@sss.pgh.pa.us        2297         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "POLICY", MatchAny, "ON", MatchAny))
 2032 tgl@sss.pgh.pa.us        2298                 :UBC           0 :         COMPLETE_WITH("RENAME TO", "TO", "USING (", "WITH CHECK (");
                               2299                 :                :     /* ALTER POLICY <name> ON <table> TO <role> */
 2032 tgl@sss.pgh.pa.us        2300         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "POLICY", MatchAny, "ON", MatchAny, "TO"))
  805 tgl@sss.pgh.pa.us        2301                 :UBC           0 :         COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
                               2302                 :                :                                  Keywords_for_list_of_grant_roles);
                               2303                 :                :     /* ALTER POLICY <name> ON <table> USING ( */
 2032 tgl@sss.pgh.pa.us        2304         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "POLICY", MatchAny, "ON", MatchAny, "USING"))
 2032 tgl@sss.pgh.pa.us        2305                 :UBC           0 :         COMPLETE_WITH("(");
                               2306                 :                :     /* ALTER POLICY <name> ON <table> WITH CHECK ( */
 2032 tgl@sss.pgh.pa.us        2307         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "POLICY", MatchAny, "ON", MatchAny, "WITH", "CHECK"))
 2032 tgl@sss.pgh.pa.us        2308                 :UBC           0 :         COMPLETE_WITH("(");
                               2309                 :                : 
                               2310                 :                :     /* ALTER RULE <name>, add ON */
 2032 tgl@sss.pgh.pa.us        2311         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "RULE", MatchAny))
 2032 tgl@sss.pgh.pa.us        2312                 :UBC           0 :         COMPLETE_WITH("ON");
                               2313                 :                : 
                               2314                 :                :     /* If we have ALTER RULE <name> ON, then add the correct tablename */
 2032 tgl@sss.pgh.pa.us        2315         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "RULE", MatchAny, "ON"))
                               2316                 :                :     {
  805 tgl@sss.pgh.pa.us        2317                 :UBC           0 :         set_completion_reference(prev2_wd);
                               2318                 :              0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables_for_rule);
                               2319                 :                :     }
                               2320                 :                : 
                               2321                 :                :     /* ALTER RULE <name> ON <name> */
 2032 tgl@sss.pgh.pa.us        2322         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "RULE", MatchAny, "ON", MatchAny))
 2032 tgl@sss.pgh.pa.us        2323                 :UBC           0 :         COMPLETE_WITH("RENAME TO");
                               2324                 :                : 
                               2325                 :                :     /* ALTER STATISTICS <name> */
 2032 tgl@sss.pgh.pa.us        2326         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "STATISTICS", MatchAny))
 1678 tomas.vondra@postgre     2327                 :UBC           0 :         COMPLETE_WITH("OWNER TO", "RENAME TO", "SET SCHEMA", "SET STATISTICS");
                               2328                 :                :     /* ALTER STATISTICS <name> SET */
  538 michael@paquier.xyz      2329         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "STATISTICS", MatchAny, "SET"))
  538 michael@paquier.xyz      2330                 :UBC           0 :         COMPLETE_WITH("SCHEMA", "STATISTICS");
                               2331                 :                : 
                               2332                 :                :     /* ALTER TRIGGER <name>, add ON */
 2032 tgl@sss.pgh.pa.us        2333         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "TRIGGER", MatchAny))
 2032 tgl@sss.pgh.pa.us        2334                 :UBC           0 :         COMPLETE_WITH("ON");
                               2335                 :                : 
  805 tgl@sss.pgh.pa.us        2336         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "TRIGGER", MatchAny, "ON"))
                               2337                 :                :     {
  805 tgl@sss.pgh.pa.us        2338                 :UBC           0 :         set_completion_reference(prev2_wd);
                               2339                 :              0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables_for_trigger);
                               2340                 :                :     }
                               2341                 :                : 
                               2342                 :                :     /* ALTER TRIGGER <name> ON <name> */
 2032 tgl@sss.pgh.pa.us        2343         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "TRIGGER", MatchAny, "ON", MatchAny))
 1152 michael@paquier.xyz      2344                 :UBC           0 :         COMPLETE_WITH("RENAME TO", "DEPENDS ON EXTENSION",
                               2345                 :                :                       "NO DEPENDS ON EXTENSION");
                               2346                 :                : 
                               2347                 :                :     /*
                               2348                 :                :      * If we detect ALTER TABLE <name>, suggest sub commands
                               2349                 :                :      */
 2032 tgl@sss.pgh.pa.us        2350         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "TABLE", MatchAny))
 2032 tgl@sss.pgh.pa.us        2351                 :UBC           0 :         COMPLETE_WITH("ADD", "ALTER", "CLUSTER ON", "DISABLE", "DROP",
                               2352                 :                :                       "ENABLE", "INHERIT", "NO", "RENAME", "RESET",
                               2353                 :                :                       "OWNER TO", "SET", "VALIDATE CONSTRAINT",
                               2354                 :                :                       "REPLICA IDENTITY", "ATTACH PARTITION",
                               2355                 :                :                       "DETACH PARTITION", "FORCE ROW LEVEL SECURITY",
                               2356                 :                :                       "OF", "NOT OF");
                               2357                 :                :     /* ALTER TABLE xxx ADD */
  958 michael@paquier.xyz      2358         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "TABLE", MatchAny, "ADD"))
                               2359                 :                :     {
                               2360                 :                :         /* make sure to keep this list and the !Matches() below in sync */
  958 michael@paquier.xyz      2361                 :UBC           0 :         COMPLETE_WITH("COLUMN", "CONSTRAINT", "CHECK", "UNIQUE", "PRIMARY KEY",
                               2362                 :                :                       "EXCLUDE", "FOREIGN KEY");
                               2363                 :                :     }
                               2364                 :                :     /* ALTER TABLE xxx ADD [COLUMN] yyy */
  957 michael@paquier.xyz      2365   [ +  -  -  + ]:CBC         120 :     else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "COLUMN", MatchAny) ||
  957 michael@paquier.xyz      2366                 :UBC           0 :              (Matches("ALTER", "TABLE", MatchAny, "ADD", MatchAny) &&
                               2367         [ #  # ]:              0 :               !Matches("ALTER", "TABLE", MatchAny, "ADD", "COLUMN|CONSTRAINT|CHECK|UNIQUE|PRIMARY|EXCLUDE|FOREIGN")))
  805 tgl@sss.pgh.pa.us        2368                 :              0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
                               2369                 :                :     /* ALTER TABLE xxx ADD CONSTRAINT yyy */
  958 michael@paquier.xyz      2370         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "CONSTRAINT", MatchAny))
  958 michael@paquier.xyz      2371                 :UBC           0 :         COMPLETE_WITH("CHECK", "UNIQUE", "PRIMARY KEY", "EXCLUDE", "FOREIGN KEY");
                               2372                 :                :     /* ALTER TABLE xxx ADD [CONSTRAINT yyy] (PRIMARY KEY|UNIQUE) */
  958 michael@paquier.xyz      2373   [ +  -  +  - ]:CBC         120 :     else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "PRIMARY", "KEY") ||
                               2374         [ +  - ]:            120 :              Matches("ALTER", "TABLE", MatchAny, "ADD", "UNIQUE") ||
                               2375         [ -  + ]:            120 :              Matches("ALTER", "TABLE", MatchAny, "ADD", "CONSTRAINT", MatchAny, "PRIMARY", "KEY") ||
                               2376                 :             60 :              Matches("ALTER", "TABLE", MatchAny, "ADD", "CONSTRAINT", MatchAny, "UNIQUE"))
  958 michael@paquier.xyz      2377                 :UBC           0 :         COMPLETE_WITH("(", "USING INDEX");
                               2378                 :                :     /* ALTER TABLE xxx ADD PRIMARY KEY USING INDEX */
  958 michael@paquier.xyz      2379         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "PRIMARY", "KEY", "USING", "INDEX"))
                               2380                 :                :     {
  805 tgl@sss.pgh.pa.us        2381                 :UBC           0 :         set_completion_reference(prev6_wd);
                               2382                 :              0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_unique_index_of_table);
                               2383                 :                :     }
                               2384                 :                :     /* ALTER TABLE xxx ADD UNIQUE USING INDEX */
  958 michael@paquier.xyz      2385         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "UNIQUE", "USING", "INDEX"))
                               2386                 :                :     {
  805 tgl@sss.pgh.pa.us        2387                 :UBC           0 :         set_completion_reference(prev5_wd);
                               2388                 :              0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_unique_index_of_table);
                               2389                 :                :     }
                               2390                 :                :     /* ALTER TABLE xxx ADD CONSTRAINT yyy PRIMARY KEY USING INDEX */
  958 michael@paquier.xyz      2391         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "CONSTRAINT", MatchAny,
                               2392                 :                :                      "PRIMARY", "KEY", "USING", "INDEX"))
                               2393                 :                :     {
  805 tgl@sss.pgh.pa.us        2394                 :UBC           0 :         set_completion_reference(prev8_wd);
                               2395                 :              0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_unique_index_of_table);
                               2396                 :                :     }
                               2397                 :                :     /* ALTER TABLE xxx ADD CONSTRAINT yyy UNIQUE USING INDEX */
  958 michael@paquier.xyz      2398         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "CONSTRAINT", MatchAny,
                               2399                 :                :                      "UNIQUE", "USING", "INDEX"))
                               2400                 :                :     {
  805 tgl@sss.pgh.pa.us        2401                 :UBC           0 :         set_completion_reference(prev7_wd);
                               2402                 :              0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_unique_index_of_table);
                               2403                 :                :     }
                               2404                 :                :     /* ALTER TABLE xxx ENABLE */
 2032 tgl@sss.pgh.pa.us        2405         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE"))
 2032 tgl@sss.pgh.pa.us        2406                 :UBC           0 :         COMPLETE_WITH("ALWAYS", "REPLICA", "ROW LEVEL SECURITY", "RULE",
                               2407                 :                :                       "TRIGGER");
 2032 tgl@sss.pgh.pa.us        2408         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE", "REPLICA|ALWAYS"))
 2032 tgl@sss.pgh.pa.us        2409                 :UBC           0 :         COMPLETE_WITH("RULE", "TRIGGER");
 2032 tgl@sss.pgh.pa.us        2410         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE", "RULE"))
                               2411                 :                :     {
  805 tgl@sss.pgh.pa.us        2412                 :UBC           0 :         set_completion_reference(prev3_wd);
                               2413                 :              0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_rule_of_table);
                               2414                 :                :     }
 2032 tgl@sss.pgh.pa.us        2415         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "RULE"))
                               2416                 :                :     {
  805 tgl@sss.pgh.pa.us        2417                 :UBC           0 :         set_completion_reference(prev4_wd);
                               2418                 :              0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_rule_of_table);
                               2419                 :                :     }
 2032 tgl@sss.pgh.pa.us        2420         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE", "TRIGGER"))
                               2421                 :                :     {
  805 tgl@sss.pgh.pa.us        2422                 :UBC           0 :         set_completion_reference(prev3_wd);
                               2423                 :              0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_trigger_of_table);
                               2424                 :                :     }
 2032 tgl@sss.pgh.pa.us        2425         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "TRIGGER"))
                               2426                 :                :     {
  805 tgl@sss.pgh.pa.us        2427                 :UBC           0 :         set_completion_reference(prev4_wd);
                               2428                 :              0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_trigger_of_table);
                               2429                 :                :     }
                               2430                 :                :     /* ALTER TABLE xxx INHERIT */
 2032 tgl@sss.pgh.pa.us        2431         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "TABLE", MatchAny, "INHERIT"))
  805 tgl@sss.pgh.pa.us        2432                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
                               2433                 :                :     /* ALTER TABLE xxx NO */
 1268 michael@paquier.xyz      2434         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "TABLE", MatchAny, "NO"))
 1268 michael@paquier.xyz      2435                 :UBC           0 :         COMPLETE_WITH("FORCE ROW LEVEL SECURITY", "INHERIT");
                               2436                 :                :     /* ALTER TABLE xxx NO INHERIT */
 2032 tgl@sss.pgh.pa.us        2437         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "TABLE", MatchAny, "NO", "INHERIT"))
  805 tgl@sss.pgh.pa.us        2438                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
                               2439                 :                :     /* ALTER TABLE xxx DISABLE */
 2032 tgl@sss.pgh.pa.us        2440         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "TABLE", MatchAny, "DISABLE"))
 2032 tgl@sss.pgh.pa.us        2441                 :UBC           0 :         COMPLETE_WITH("ROW LEVEL SECURITY", "RULE", "TRIGGER");
 2032 tgl@sss.pgh.pa.us        2442         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "TABLE", MatchAny, "DISABLE", "RULE"))
                               2443                 :                :     {
  805 tgl@sss.pgh.pa.us        2444                 :UBC           0 :         set_completion_reference(prev3_wd);
                               2445                 :              0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_rule_of_table);
                               2446                 :                :     }
 2032 tgl@sss.pgh.pa.us        2447         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "TABLE", MatchAny, "DISABLE", "TRIGGER"))
                               2448                 :                :     {
  805 tgl@sss.pgh.pa.us        2449                 :UBC           0 :         set_completion_reference(prev3_wd);
                               2450                 :              0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_trigger_of_table);
                               2451                 :                :     }
                               2452                 :                : 
                               2453                 :                :     /* ALTER TABLE xxx ALTER */
 2032 tgl@sss.pgh.pa.us        2454         [ -  + ]:CBC          60 :     else if (Matches("ALTER", "TABLE", MatchAny, "ALTER"))
  805 tgl@sss.pgh.pa.us        2455                 :UBC           0 :         COMPLETE_WITH_ATTR_PLUS(prev2_wd, "COLUMN", "CONSTRAINT");
                               2456                 :                : 
                               2457                 :                :     /* ALTER TABLE xxx RENAME */
 2032 tgl@sss.pgh.pa.us        2458         [ +  + ]:CBC          60 :     else if (Matches("ALTER", "TABLE", MatchAny, "RENAME"))
  805                          2459                 :             12 :         COMPLETE_WITH_ATTR_PLUS(prev2_wd, "COLUMN", "CONSTRAINT", "TO");
 2032                          2460         [ -  + ]:             48 :     else if (Matches("ALTER", "TABLE", MatchAny, "ALTER|RENAME", "COLUMN"))
  805 tgl@sss.pgh.pa.us        2461                 :UBC           0 :         COMPLETE_WITH_ATTR(prev3_wd);
                               2462                 :                : 
                               2463                 :                :     /* ALTER TABLE xxx RENAME yyy */
 2032 tgl@sss.pgh.pa.us        2464         [ -  + ]:CBC          48 :     else if (Matches("ALTER", "TABLE", MatchAny, "RENAME", MatchAnyExcept("CONSTRAINT|TO")))
 2032 tgl@sss.pgh.pa.us        2465                 :UBC           0 :         COMPLETE_WITH("TO");
                               2466                 :                : 
                               2467                 :                :     /* ALTER TABLE xxx RENAME COLUMN/CONSTRAINT yyy */
 2032 tgl@sss.pgh.pa.us        2468         [ -  + ]:CBC          48 :     else if (Matches("ALTER", "TABLE", MatchAny, "RENAME", "COLUMN|CONSTRAINT", MatchAnyExcept("TO")))
 2032 tgl@sss.pgh.pa.us        2469                 :UBC           0 :         COMPLETE_WITH("TO");
                               2470                 :                : 
                               2471                 :                :     /* If we have ALTER TABLE <sth> DROP, provide COLUMN or CONSTRAINT */
 2032 tgl@sss.pgh.pa.us        2472         [ -  + ]:CBC          48 :     else if (Matches("ALTER", "TABLE", MatchAny, "DROP"))
 2032 tgl@sss.pgh.pa.us        2473                 :UBC           0 :         COMPLETE_WITH("COLUMN", "CONSTRAINT");
                               2474                 :                :     /* If we have ALTER TABLE <sth> DROP COLUMN, provide list of columns */
 2032 tgl@sss.pgh.pa.us        2475         [ -  + ]:CBC          48 :     else if (Matches("ALTER", "TABLE", MatchAny, "DROP", "COLUMN"))
  805 tgl@sss.pgh.pa.us        2476                 :UBC           0 :         COMPLETE_WITH_ATTR(prev3_wd);
                               2477                 :                :     /* ALTER TABLE <sth> ALTER|DROP|RENAME CONSTRAINT <constraint> */
  832 tgl@sss.pgh.pa.us        2478         [ +  + ]:CBC          48 :     else if (Matches("ALTER", "TABLE", MatchAny, "ALTER|DROP|RENAME", "CONSTRAINT"))
                               2479                 :                :     {
  805                          2480                 :              3 :         set_completion_reference(prev3_wd);
                               2481                 :              3 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_constraint_of_table);
                               2482                 :                :     }
                               2483                 :                :     /* ALTER TABLE <sth> VALIDATE CONSTRAINT <non-validated constraint> */
  832                          2484         [ -  + ]:             45 :     else if (Matches("ALTER", "TABLE", MatchAny, "VALIDATE", "CONSTRAINT"))
                               2485                 :                :     {
  805 tgl@sss.pgh.pa.us        2486                 :UBC           0 :         set_completion_reference(prev3_wd);
                               2487                 :              0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_constraint_of_table_not_validated);
                               2488                 :                :     }
                               2489                 :                :     /* ALTER TABLE ALTER [COLUMN] <foo> */
 2032 tgl@sss.pgh.pa.us        2490   [ +  -  -  + ]:CBC          90 :     else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny) ||
                               2491                 :             45 :              Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny))
 2032 tgl@sss.pgh.pa.us        2492                 :UBC           0 :         COMPLETE_WITH("TYPE", "SET", "RESET", "RESTART", "ADD", "DROP");
                               2493                 :                :     /* ALTER TABLE ALTER [COLUMN] <foo> ADD */
  530 peter@eisentraut.org     2494   [ +  -  -  + ]:CBC          90 :     else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "ADD") ||
                               2495                 :             45 :              Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "ADD"))
  530 peter@eisentraut.org     2496                 :UBC           0 :         COMPLETE_WITH("GENERATED");
                               2497                 :                :     /* ALTER TABLE ALTER [COLUMN] <foo> ADD GENERATED */
  530 peter@eisentraut.org     2498   [ +  -  -  + ]:CBC          90 :     else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "ADD", "GENERATED") ||
                               2499                 :             45 :              Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "ADD", "GENERATED"))
  530 peter@eisentraut.org     2500                 :UBC           0 :         COMPLETE_WITH("ALWAYS", "BY DEFAULT");
                               2501                 :                :     /* ALTER TABLE ALTER [COLUMN] <foo> ADD GENERATED */
  530 peter@eisentraut.org     2502   [ +  -  +  - ]:CBC          90 :     else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "ADD", "GENERATED", "ALWAYS") ||
                               2503         [ +  - ]:             90 :              Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "ADD", "GENERATED", "ALWAYS") ||
                               2504         [ -  + ]:             90 :              Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "ADD", "GENERATED", "BY", "DEFAULT") ||
                               2505                 :             45 :              Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "ADD", "GENERATED", "BY", "DEFAULT"))
  530 peter@eisentraut.org     2506                 :UBC           0 :         COMPLETE_WITH("AS IDENTITY");
                               2507                 :                :     /* ALTER TABLE ALTER [COLUMN] <foo> SET */
 2032 tgl@sss.pgh.pa.us        2508   [ +  -  -  + ]:CBC          90 :     else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET") ||
                               2509                 :             45 :              Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET"))
   17 msawada@postgresql.o     2510                 :UNC           0 :         COMPLETE_WITH("(", "COMPRESSION", "DATA TYPE", "DEFAULT", "EXPRESSION", "GENERATED", "NOT NULL",
                               2511                 :                :                       "STATISTICS", "STORAGE",
                               2512                 :                :         /* a subset of ALTER SEQUENCE options */
                               2513                 :                :                       "INCREMENT", "MINVALUE", "MAXVALUE", "START", "NO", "CACHE", "CYCLE");
                               2514                 :                :     /* ALTER TABLE ALTER [COLUMN] <foo> SET ( */
 2032 tgl@sss.pgh.pa.us        2515   [ +  -  -  + ]:CBC          90 :     else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "(") ||
                               2516                 :             45 :              Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "("))
 2032 tgl@sss.pgh.pa.us        2517                 :UBC           0 :         COMPLETE_WITH("n_distinct", "n_distinct_inherited");
                               2518                 :                :     /* ALTER TABLE ALTER [COLUMN] <foo> SET COMPRESSION */
  586 michael@paquier.xyz      2519   [ +  -  -  + ]:CBC          90 :     else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "COMPRESSION") ||
                               2520                 :             45 :              Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "COMPRESSION"))
  586 michael@paquier.xyz      2521                 :UBC           0 :         COMPLETE_WITH("DEFAULT", "PGLZ", "LZ4");
                               2522                 :                :     /* ALTER TABLE ALTER [COLUMN] <foo> SET EXPRESSION */
  101 peter@eisentraut.org     2523   [ +  -  -  + ]:GNC          90 :     else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "EXPRESSION") ||
                               2524                 :             45 :              Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "EXPRESSION"))
  101 peter@eisentraut.org     2525                 :UNC           0 :         COMPLETE_WITH("AS");
                               2526                 :                :     /* ALTER TABLE ALTER [COLUMN] <foo> SET EXPRESSION AS */
  101 peter@eisentraut.org     2527   [ +  -  -  + ]:GNC          90 :     else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "EXPRESSION", "AS") ||
                               2528                 :             45 :              Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "EXPRESSION", "AS"))
  101 peter@eisentraut.org     2529                 :UNC           0 :         COMPLETE_WITH("(");
                               2530                 :                :     /* ALTER TABLE ALTER [COLUMN] <foo> SET GENERATED */
  530 peter@eisentraut.org     2531   [ +  -  -  + ]:CBC          90 :     else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "GENERATED") ||
                               2532                 :             45 :              Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "GENERATED"))
  530 peter@eisentraut.org     2533                 :UBC           0 :         COMPLETE_WITH("ALWAYS", "BY DEFAULT");
                               2534                 :                :     /* ALTER TABLE ALTER [COLUMN] <foo> SET NO */
  530 peter@eisentraut.org     2535   [ +  -  -  + ]:CBC          90 :     else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "NO") ||
                               2536                 :             45 :              Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "NO"))
  530 peter@eisentraut.org     2537                 :UBC           0 :         COMPLETE_WITH("MINVALUE", "MAXVALUE", "CYCLE");
                               2538                 :                :     /* ALTER TABLE ALTER [COLUMN] <foo> SET STORAGE */
 2032 tgl@sss.pgh.pa.us        2539   [ +  -  -  + ]:CBC          90 :     else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "STORAGE") ||
                               2540                 :             45 :              Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "STORAGE"))
  521 tgl@sss.pgh.pa.us        2541                 :UBC           0 :         COMPLETE_WITH("DEFAULT", "PLAIN", "EXTERNAL", "EXTENDED", "MAIN");
                               2542                 :                :     /* ALTER TABLE ALTER [COLUMN] <foo> SET STATISTICS */
 1937 michael@paquier.xyz      2543   [ +  -  +  - ]:CBC          90 :     else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "STATISTICS") ||
                               2544                 :             45 :              Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "STATISTICS"))
                               2545                 :                :     {
                               2546                 :                :         /* Enforce no completion here, as an integer has to be specified */
                               2547                 :                :     }
                               2548                 :                :     /* ALTER TABLE ALTER [COLUMN] <foo> DROP */
 2032 tgl@sss.pgh.pa.us        2549   [ +  -  -  + ]:             90 :     else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "DROP") ||
                               2550                 :             45 :              Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "DROP"))
 1552 peter@eisentraut.org     2551                 :UBC           0 :         COMPLETE_WITH("DEFAULT", "EXPRESSION", "IDENTITY", "NOT NULL");
 2032 tgl@sss.pgh.pa.us        2552         [ -  + ]:CBC          45 :     else if (Matches("ALTER", "TABLE", MatchAny, "CLUSTER"))
 2032 tgl@sss.pgh.pa.us        2553                 :UBC           0 :         COMPLETE_WITH("ON");
 2032 tgl@sss.pgh.pa.us        2554         [ -  + ]:CBC          45 :     else if (Matches("ALTER", "TABLE", MatchAny, "CLUSTER", "ON"))
                               2555                 :                :     {
  805 tgl@sss.pgh.pa.us        2556                 :UBC           0 :         set_completion_reference(prev3_wd);
                               2557                 :              0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_index_of_table);
                               2558                 :                :     }
                               2559                 :                :     /* If we have ALTER TABLE <sth> SET, provide list of attributes and '(' */
 2032 tgl@sss.pgh.pa.us        2560         [ -  + ]:CBC          45 :     else if (Matches("ALTER", "TABLE", MatchAny, "SET"))
  991 michael@paquier.xyz      2561                 :UBC           0 :         COMPLETE_WITH("(", "ACCESS METHOD", "LOGGED", "SCHEMA",
                               2562                 :                :                       "TABLESPACE", "UNLOGGED", "WITH", "WITHOUT");
                               2563                 :                : 
                               2564                 :                :     /*
                               2565                 :                :      * If we have ALTER TABLE <sth> SET ACCESS METHOD provide a list of table
                               2566                 :                :      * AMs.
                               2567                 :                :      */
  991 michael@paquier.xyz      2568         [ -  + ]:CBC          45 :     else if (Matches("ALTER", "TABLE", MatchAny, "SET", "ACCESS", "METHOD"))
   37 michael@paquier.xyz      2569                 :UNC           0 :         COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_table_access_methods,
                               2570                 :                :                                  "DEFAULT");
                               2571                 :                : 
                               2572                 :                :     /*
                               2573                 :                :      * If we have ALTER TABLE <sth> SET TABLESPACE provide a list of
                               2574                 :                :      * tablespaces
                               2575                 :                :      */
 2032 tgl@sss.pgh.pa.us        2576         [ -  + ]:CBC          45 :     else if (Matches("ALTER", "TABLE", MatchAny, "SET", "TABLESPACE"))
 7177 bruce@momjian.us         2577                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
                               2578                 :                :     /* If we have ALTER TABLE <sth> SET WITHOUT provide CLUSTER or OIDS */
 2032 tgl@sss.pgh.pa.us        2579         [ -  + ]:CBC          45 :     else if (Matches("ALTER", "TABLE", MatchAny, "SET", "WITHOUT"))
 2032 tgl@sss.pgh.pa.us        2580                 :UBC           0 :         COMPLETE_WITH("CLUSTER", "OIDS");
                               2581                 :                :     /* ALTER TABLE <foo> RESET */
 2032 tgl@sss.pgh.pa.us        2582         [ -  + ]:CBC          45 :     else if (Matches("ALTER", "TABLE", MatchAny, "RESET"))
 2032 tgl@sss.pgh.pa.us        2583                 :UBC           0 :         COMPLETE_WITH("(");
                               2584                 :                :     /* ALTER TABLE <foo> SET|RESET ( */
 2032 tgl@sss.pgh.pa.us        2585         [ -  + ]:CBC          45 :     else if (Matches("ALTER", "TABLE", MatchAny, "SET|RESET", "("))
 1939 michael@paquier.xyz      2586                 :UBC           0 :         COMPLETE_WITH_LIST(table_storage_parameters);
 2032 tgl@sss.pgh.pa.us        2587         [ -  + ]:CBC          45 :     else if (Matches("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING", "INDEX"))
                               2588                 :                :     {
  805 tgl@sss.pgh.pa.us        2589                 :UBC           0 :         set_completion_reference(prev5_wd);
                               2590                 :              0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_index_of_table);
                               2591                 :                :     }
 2032 tgl@sss.pgh.pa.us        2592         [ -  + ]:CBC          45 :     else if (Matches("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING"))
 2032 tgl@sss.pgh.pa.us        2593                 :UBC           0 :         COMPLETE_WITH("INDEX");
 2032 tgl@sss.pgh.pa.us        2594         [ -  + ]:CBC          45 :     else if (Matches("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY"))
 2032 tgl@sss.pgh.pa.us        2595                 :UBC           0 :         COMPLETE_WITH("FULL", "NOTHING", "DEFAULT", "USING");
 2032 tgl@sss.pgh.pa.us        2596         [ -  + ]:CBC          45 :     else if (Matches("ALTER", "TABLE", MatchAny, "REPLICA"))
 2032 tgl@sss.pgh.pa.us        2597                 :UBC           0 :         COMPLETE_WITH("IDENTITY");
                               2598                 :                : 
                               2599                 :                :     /*
                               2600                 :                :      * If we have ALTER TABLE <foo> ATTACH PARTITION, provide a list of
                               2601                 :                :      * tables.
                               2602                 :                :      */
 2032 tgl@sss.pgh.pa.us        2603         [ -  + ]:CBC          45 :     else if (Matches("ALTER", "TABLE", MatchAny, "ATTACH", "PARTITION"))
  805 tgl@sss.pgh.pa.us        2604                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
                               2605                 :                :     /* Limited completion support for partition bound specification */
 2032 tgl@sss.pgh.pa.us        2606         [ -  + ]:CBC          45 :     else if (TailMatches("ATTACH", "PARTITION", MatchAny))
 2032 tgl@sss.pgh.pa.us        2607                 :UBC           0 :         COMPLETE_WITH("FOR VALUES", "DEFAULT");
 2032 tgl@sss.pgh.pa.us        2608         [ -  + ]:CBC          45 :     else if (TailMatches("FOR", "VALUES"))
 2032 tgl@sss.pgh.pa.us        2609                 :UBC           0 :         COMPLETE_WITH("FROM (", "IN (", "WITH (");
                               2610                 :                : 
                               2611                 :                :     /*
                               2612                 :                :      * If we have ALTER TABLE <foo> DETACH PARTITION, provide a list of
                               2613                 :                :      * partitions of <foo>.
                               2614                 :                :      */
 2032 tgl@sss.pgh.pa.us        2615         [ -  + ]:CBC          45 :     else if (Matches("ALTER", "TABLE", MatchAny, "DETACH", "PARTITION"))
                               2616                 :                :     {
  805 tgl@sss.pgh.pa.us        2617                 :UBC           0 :         set_completion_reference(prev3_wd);
                               2618                 :              0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_partition_of_table);
                               2619                 :                :     }
 1088 alvherre@alvh.no-ip.     2620         [ -  + ]:CBC          45 :     else if (Matches("ALTER", "TABLE", MatchAny, "DETACH", "PARTITION", MatchAny))
 1088 alvherre@alvh.no-ip.     2621                 :UBC           0 :         COMPLETE_WITH("CONCURRENTLY", "FINALIZE");
                               2622                 :                : 
                               2623                 :                :     /* ALTER TABLE <name> OF */
  582 michael@paquier.xyz      2624         [ -  + ]:CBC          45 :     else if (Matches("ALTER", "TABLE", MatchAny, "OF"))
  582 michael@paquier.xyz      2625                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_composite_datatypes);
                               2626                 :                : 
                               2627                 :                :     /* ALTER TABLESPACE <foo> with RENAME TO, OWNER TO, SET, RESET */
 2032 tgl@sss.pgh.pa.us        2628         [ -  + ]:CBC          45 :     else if (Matches("ALTER", "TABLESPACE", MatchAny))
 2032 tgl@sss.pgh.pa.us        2629                 :UBC           0 :         COMPLETE_WITH("RENAME TO", "OWNER TO", "SET", "RESET");
                               2630                 :                :     /* ALTER TABLESPACE <foo> SET|RESET */
 2032 tgl@sss.pgh.pa.us        2631         [ -  + ]:CBC          45 :     else if (Matches("ALTER", "TABLESPACE", MatchAny, "SET|RESET"))
 2032 tgl@sss.pgh.pa.us        2632                 :UBC           0 :         COMPLETE_WITH("(");
                               2633                 :                :     /* ALTER TABLESPACE <foo> SET|RESET ( */
 2032 tgl@sss.pgh.pa.us        2634         [ -  + ]:CBC          45 :     else if (Matches("ALTER", "TABLESPACE", MatchAny, "SET|RESET", "("))
 2032 tgl@sss.pgh.pa.us        2635                 :UBC           0 :         COMPLETE_WITH("seq_page_cost", "random_page_cost",
                               2636                 :                :                       "effective_io_concurrency", "maintenance_io_concurrency");
                               2637                 :                : 
                               2638                 :                :     /* ALTER TEXT SEARCH */
 2032 tgl@sss.pgh.pa.us        2639         [ -  + ]:CBC          45 :     else if (Matches("ALTER", "TEXT", "SEARCH"))
 2032 tgl@sss.pgh.pa.us        2640                 :UBC           0 :         COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
 2032 tgl@sss.pgh.pa.us        2641         [ -  + ]:CBC          45 :     else if (Matches("ALTER", "TEXT", "SEARCH", "TEMPLATE|PARSER", MatchAny))
 2032 tgl@sss.pgh.pa.us        2642                 :UBC           0 :         COMPLETE_WITH("RENAME TO", "SET SCHEMA");
 2032 tgl@sss.pgh.pa.us        2643         [ -  + ]:CBC          45 :     else if (Matches("ALTER", "TEXT", "SEARCH", "DICTIONARY", MatchAny))
 1499 tgl@sss.pgh.pa.us        2644                 :UBC           0 :         COMPLETE_WITH("(", "OWNER TO", "RENAME TO", "SET SCHEMA");
 2032 tgl@sss.pgh.pa.us        2645         [ -  + ]:CBC          45 :     else if (Matches("ALTER", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
 2032 tgl@sss.pgh.pa.us        2646                 :UBC           0 :         COMPLETE_WITH("ADD MAPPING FOR", "ALTER MAPPING",
                               2647                 :                :                       "DROP MAPPING FOR",
                               2648                 :                :                       "OWNER TO", "RENAME TO", "SET SCHEMA");
                               2649                 :                : 
                               2650                 :                :     /* complete ALTER TYPE <foo> with actions */
 2032 tgl@sss.pgh.pa.us        2651         [ -  + ]:CBC          45 :     else if (Matches("ALTER", "TYPE", MatchAny))
 2032 tgl@sss.pgh.pa.us        2652                 :UBC           0 :         COMPLETE_WITH("ADD ATTRIBUTE", "ADD VALUE", "ALTER ATTRIBUTE",
                               2653                 :                :                       "DROP ATTRIBUTE",
                               2654                 :                :                       "OWNER TO", "RENAME", "SET SCHEMA", "SET (");
                               2655                 :                :     /* complete ALTER TYPE <foo> ADD with actions */
 2032 tgl@sss.pgh.pa.us        2656         [ -  + ]:CBC          45 :     else if (Matches("ALTER", "TYPE", MatchAny, "ADD"))
 2032 tgl@sss.pgh.pa.us        2657                 :UBC           0 :         COMPLETE_WITH("ATTRIBUTE", "VALUE");
                               2658                 :                :     /* ALTER TYPE <foo> RENAME    */
 2032 tgl@sss.pgh.pa.us        2659         [ -  + ]:CBC          45 :     else if (Matches("ALTER", "TYPE", MatchAny, "RENAME"))
 2032 tgl@sss.pgh.pa.us        2660                 :UBC           0 :         COMPLETE_WITH("ATTRIBUTE", "TO", "VALUE");
                               2661                 :                :     /* ALTER TYPE xxx RENAME (ATTRIBUTE|VALUE) yyy */
 2032 tgl@sss.pgh.pa.us        2662         [ -  + ]:CBC          45 :     else if (Matches("ALTER", "TYPE", MatchAny, "RENAME", "ATTRIBUTE|VALUE", MatchAny))
 2032 tgl@sss.pgh.pa.us        2663                 :UBC           0 :         COMPLETE_WITH("TO");
                               2664                 :                : 
                               2665                 :                :     /*
                               2666                 :                :      * If we have ALTER TYPE <sth> ALTER/DROP/RENAME ATTRIBUTE, provide list
                               2667                 :                :      * of attributes
                               2668                 :                :      */
 2032 tgl@sss.pgh.pa.us        2669         [ -  + ]:CBC          45 :     else if (Matches("ALTER", "TYPE", MatchAny, "ALTER|DROP|RENAME", "ATTRIBUTE"))
  805 tgl@sss.pgh.pa.us        2670                 :UBC           0 :         COMPLETE_WITH_ATTR(prev3_wd);
                               2671                 :                :     /* ALTER TYPE ALTER ATTRIBUTE <foo> */
 2032 tgl@sss.pgh.pa.us        2672         [ -  + ]:CBC          45 :     else if (Matches("ALTER", "TYPE", MatchAny, "ALTER", "ATTRIBUTE", MatchAny))
 2032 tgl@sss.pgh.pa.us        2673                 :UBC           0 :         COMPLETE_WITH("TYPE");
                               2674                 :                :     /* complete ALTER TYPE <sth> RENAME VALUE with list of enum values */
  608 michael@paquier.xyz      2675         [ +  + ]:CBC          45 :     else if (Matches("ALTER", "TYPE", MatchAny, "RENAME", "VALUE"))
                               2676   [ +  -  +  -  :              3 :         COMPLETE_WITH_ENUM_VALUE(prev3_wd);
                                              -  + ]
                               2677                 :                :     /* ALTER TYPE <foo> SET */
                               2678         [ -  + ]:             42 :     else if (Matches("ALTER", "TYPE", MatchAny, "SET"))
  608 michael@paquier.xyz      2679                 :UBC           0 :         COMPLETE_WITH("(", "SCHEMA");
                               2680                 :                :     /* complete ALTER TYPE <foo> SET ( with settable properties */
  608 michael@paquier.xyz      2681         [ -  + ]:CBC          42 :     else if (Matches("ALTER", "TYPE", MatchAny, "SET", "("))
  608 michael@paquier.xyz      2682                 :UBC           0 :         COMPLETE_WITH("ANALYZE", "RECEIVE", "SEND", "STORAGE", "SUBSCRIPT",
                               2683                 :                :                       "TYPMOD_IN", "TYPMOD_OUT");
                               2684                 :                : 
                               2685                 :                :     /* complete ALTER GROUP <foo> */
 2032 tgl@sss.pgh.pa.us        2686         [ -  + ]:CBC          42 :     else if (Matches("ALTER", "GROUP", MatchAny))
 2032 tgl@sss.pgh.pa.us        2687                 :UBC           0 :         COMPLETE_WITH("ADD USER", "DROP USER", "RENAME TO");
                               2688                 :                :     /* complete ALTER GROUP <foo> ADD|DROP with USER */
 2032 tgl@sss.pgh.pa.us        2689         [ -  + ]:CBC          42 :     else if (Matches("ALTER", "GROUP", MatchAny, "ADD|DROP"))
 2032 tgl@sss.pgh.pa.us        2690                 :UBC           0 :         COMPLETE_WITH("USER");
                               2691                 :                :     /* complete ALTER GROUP <foo> ADD|DROP USER with a user name */
 2032 tgl@sss.pgh.pa.us        2692         [ -  + ]:CBC          42 :     else if (Matches("ALTER", "GROUP", MatchAny, "ADD|DROP", "USER"))
 6818 tgl@sss.pgh.pa.us        2693                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_roles);
                               2694                 :                : 
                               2695                 :                : /*
                               2696                 :                :  * ANALYZE [ ( option [, ...] ) ] [ table_and_columns [, ...] ]
                               2697                 :                :  * ANALYZE [ VERBOSE ] [ table_and_columns [, ...] ]
                               2698                 :                :  */
 2032 tgl@sss.pgh.pa.us        2699         [ -  + ]:CBC          42 :     else if (Matches("ANALYZE"))
  805 tgl@sss.pgh.pa.us        2700                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_analyzables,
                               2701                 :                :                                         "VERBOSE");
 1866 michael@paquier.xyz      2702         [ +  + ]:CBC          42 :     else if (HeadMatches("ANALYZE", "(*") &&
                               2703         [ +  - ]:              2 :              !HeadMatches("ANALYZE", "(*)"))
                               2704                 :                :     {
                               2705                 :                :         /*
                               2706                 :                :          * This fires if we're in an unfinished parenthesized option list.
                               2707                 :                :          * get_previous_words treats a completed parenthesized option list as
                               2708                 :                :          * one word, so the above test is correct.
                               2709                 :                :          */
                               2710   [ -  +  -  - ]:              4 :         if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
  373 drowley@postgresql.o     2711                 :              2 :             COMPLETE_WITH("VERBOSE", "SKIP_LOCKED", "BUFFER_USAGE_LIMIT");
 1788 fujii@postgresql.org     2712         [ #  # ]:UBC           0 :         else if (TailMatches("VERBOSE|SKIP_LOCKED"))
                               2713                 :              0 :             COMPLETE_WITH("ON", "OFF");
                               2714                 :                :     }
 2032 tgl@sss.pgh.pa.us        2715   [ -  +  -  - ]:CBC          40 :     else if (HeadMatches("ANALYZE") && TailMatches("("))
                               2716                 :                :         /* "ANALYZE (" should be caught above, so assume we want columns */
  805 tgl@sss.pgh.pa.us        2717                 :UBC           0 :         COMPLETE_WITH_ATTR(prev2_wd);
 2032 tgl@sss.pgh.pa.us        2718         [ -  + ]:CBC          40 :     else if (HeadMatches("ANALYZE"))
  805 tgl@sss.pgh.pa.us        2719                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_analyzables);
                               2720                 :                : 
                               2721                 :                : /* BEGIN */
 2032 tgl@sss.pgh.pa.us        2722         [ -  + ]:CBC          40 :     else if (Matches("BEGIN"))
 2032 tgl@sss.pgh.pa.us        2723                 :UBC           0 :         COMPLETE_WITH("WORK", "TRANSACTION", "ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
                               2724                 :                : /* END, ABORT */
 2032 tgl@sss.pgh.pa.us        2725         [ -  + ]:CBC          40 :     else if (Matches("END|ABORT"))
 1848 peter@eisentraut.org     2726                 :UBC           0 :         COMPLETE_WITH("AND", "WORK", "TRANSACTION");
                               2727                 :                : /* COMMIT */
 2032 tgl@sss.pgh.pa.us        2728         [ -  + ]:CBC          40 :     else if (Matches("COMMIT"))
 1848 peter@eisentraut.org     2729                 :UBC           0 :         COMPLETE_WITH("AND", "WORK", "TRANSACTION", "PREPARED");
                               2730                 :                : /* RELEASE SAVEPOINT */
 2032 tgl@sss.pgh.pa.us        2731         [ -  + ]:CBC          40 :     else if (Matches("RELEASE"))
 2032 tgl@sss.pgh.pa.us        2732                 :UBC           0 :         COMPLETE_WITH("SAVEPOINT");
                               2733                 :                : /* ROLLBACK */
 2032 tgl@sss.pgh.pa.us        2734         [ -  + ]:CBC          40 :     else if (Matches("ROLLBACK"))
 1848 peter@eisentraut.org     2735                 :UBC           0 :         COMPLETE_WITH("AND", "WORK", "TRANSACTION", "TO SAVEPOINT", "PREPARED");
 1848 peter@eisentraut.org     2736         [ -  + ]:CBC          40 :     else if (Matches("ABORT|END|COMMIT|ROLLBACK", "AND"))
 1848 peter@eisentraut.org     2737                 :UBC           0 :         COMPLETE_WITH("CHAIN");
                               2738                 :                : /* CALL */
 2032 tgl@sss.pgh.pa.us        2739         [ -  + ]:CBC          40 :     else if (Matches("CALL"))
  805 tgl@sss.pgh.pa.us        2740                 :UBC           0 :         COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_procedures);
 2032 tgl@sss.pgh.pa.us        2741         [ -  + ]:CBC          40 :     else if (Matches("CALL", MatchAny))
 2032 tgl@sss.pgh.pa.us        2742                 :UBC           0 :         COMPLETE_WITH("(");
                               2743                 :                : /* CLOSE */
 1186 fujii@postgresql.org     2744         [ -  + ]:CBC          40 :     else if (Matches("CLOSE"))
  805 tgl@sss.pgh.pa.us        2745                 :UBC           0 :         COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_cursors,
                               2746                 :                :                                  "ALL");
                               2747                 :                : /* CLUSTER */
 2032 tgl@sss.pgh.pa.us        2748         [ -  + ]:CBC          40 :     else if (Matches("CLUSTER"))
  805 tgl@sss.pgh.pa.us        2749                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_clusterables,
                               2750                 :                :                                         "VERBOSE");
 1228 michael@paquier.xyz      2751   [ +  -  -  + ]:CBC          80 :     else if (Matches("CLUSTER", "VERBOSE") ||
                               2752                 :             40 :              Matches("CLUSTER", "(*)"))
  805 tgl@sss.pgh.pa.us        2753                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_clusterables);
                               2754                 :                :     /* If we have CLUSTER <sth>, then add "USING" */
 1228 michael@paquier.xyz      2755         [ -  + ]:CBC          40 :     else if (Matches("CLUSTER", MatchAnyExcept("VERBOSE|ON|(|(*)")))
 2032 tgl@sss.pgh.pa.us        2756                 :UBC           0 :         COMPLETE_WITH("USING");
                               2757                 :                :     /* If we have CLUSTER VERBOSE <sth>, then add "USING" */
 1228 michael@paquier.xyz      2758         [ -  + ]:CBC          40 :     else if (Matches("CLUSTER", "VERBOSE|(*)", MatchAny))
 2032 tgl@sss.pgh.pa.us        2759                 :UBC           0 :         COMPLETE_WITH("USING");
                               2760                 :                :     /* If we have CLUSTER <sth> USING, then add the index as well */
 2032 tgl@sss.pgh.pa.us        2761   [ +  -  -  + ]:CBC          80 :     else if (Matches("CLUSTER", MatchAny, "USING") ||
 1228 michael@paquier.xyz      2762                 :             40 :              Matches("CLUSTER", "VERBOSE|(*)", MatchAny, "USING"))
                               2763                 :                :     {
  805 tgl@sss.pgh.pa.us        2764                 :UBC           0 :         set_completion_reference(prev2_wd);
                               2765                 :              0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_index_of_table);
                               2766                 :                :     }
 1228 michael@paquier.xyz      2767         [ -  + ]:CBC          40 :     else if (HeadMatches("CLUSTER", "(*") &&
 1228 michael@paquier.xyz      2768         [ #  # ]:UBC           0 :              !HeadMatches("CLUSTER", "(*)"))
                               2769                 :                :     {
                               2770                 :                :         /*
                               2771                 :                :          * This fires if we're in an unfinished parenthesized option list.
                               2772                 :                :          * get_previous_words treats a completed parenthesized option list as
                               2773                 :                :          * one word, so the above test is correct.
                               2774                 :                :          */
                               2775   [ #  #  #  # ]:              0 :         if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
                               2776                 :              0 :             COMPLETE_WITH("VERBOSE");
                               2777                 :                :     }
                               2778                 :                : 
                               2779                 :                : /* COMMENT */
 2032 tgl@sss.pgh.pa.us        2780         [ -  + ]:CBC          40 :     else if (Matches("COMMENT"))
 2032 tgl@sss.pgh.pa.us        2781                 :UBC           0 :         COMPLETE_WITH("ON");
 2032 tgl@sss.pgh.pa.us        2782         [ -  + ]:CBC          40 :     else if (Matches("COMMENT", "ON"))
  891 michael@paquier.xyz      2783                 :UBC           0 :         COMPLETE_WITH("ACCESS METHOD", "AGGREGATE", "CAST", "COLLATION",
                               2784                 :                :                       "COLUMN", "CONSTRAINT", "CONVERSION", "DATABASE",
                               2785                 :                :                       "DOMAIN", "EXTENSION", "EVENT TRIGGER",
                               2786                 :                :                       "FOREIGN DATA WRAPPER", "FOREIGN TABLE",
                               2787                 :                :                       "FUNCTION", "INDEX", "LANGUAGE", "LARGE OBJECT",
                               2788                 :                :                       "MATERIALIZED VIEW", "OPERATOR", "POLICY",
                               2789                 :                :                       "PROCEDURE", "PROCEDURAL LANGUAGE", "PUBLICATION", "ROLE",
                               2790                 :                :                       "ROUTINE", "RULE", "SCHEMA", "SEQUENCE", "SERVER",
                               2791                 :                :                       "STATISTICS", "SUBSCRIPTION", "TABLE",
                               2792                 :                :                       "TABLESPACE", "TEXT SEARCH", "TRANSFORM FOR",
                               2793                 :                :                       "TRIGGER", "TYPE", "VIEW");
 2032 tgl@sss.pgh.pa.us        2794         [ -  + ]:CBC          40 :     else if (Matches("COMMENT", "ON", "ACCESS", "METHOD"))
 2868 alvherre@alvh.no-ip.     2795                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
 2032 tgl@sss.pgh.pa.us        2796         [ -  + ]:CBC          40 :     else if (Matches("COMMENT", "ON", "CONSTRAINT"))
 4230 peter_e@gmx.net          2797                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_all_table_constraints);
 2032 tgl@sss.pgh.pa.us        2798         [ -  + ]:CBC          40 :     else if (Matches("COMMENT", "ON", "CONSTRAINT", MatchAny))
 2032 tgl@sss.pgh.pa.us        2799                 :UBC           0 :         COMPLETE_WITH("ON");
 2032 tgl@sss.pgh.pa.us        2800         [ +  + ]:CBC          40 :     else if (Matches("COMMENT", "ON", "CONSTRAINT", MatchAny, "ON"))
                               2801                 :                :     {
  805                          2802                 :              1 :         set_completion_reference(prev2_wd);
                               2803                 :              1 :         COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_tables_for_constraint,
                               2804                 :                :                                         "DOMAIN");
                               2805                 :                :     }
  891 michael@paquier.xyz      2806         [ -  + ]:             39 :     else if (Matches("COMMENT", "ON", "CONSTRAINT", MatchAny, "ON", "DOMAIN"))
  805 tgl@sss.pgh.pa.us        2807                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains);
 2032 tgl@sss.pgh.pa.us        2808         [ -  + ]:CBC          39 :     else if (Matches("COMMENT", "ON", "EVENT", "TRIGGER"))
 3653 rhaas@postgresql.org     2809                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
  891 michael@paquier.xyz      2810         [ -  + ]:CBC          39 :     else if (Matches("COMMENT", "ON", "FOREIGN"))
  891 michael@paquier.xyz      2811                 :UBC           0 :         COMPLETE_WITH("DATA WRAPPER", "TABLE");
  891 michael@paquier.xyz      2812         [ -  + ]:CBC          39 :     else if (Matches("COMMENT", "ON", "FOREIGN", "TABLE"))
  805 tgl@sss.pgh.pa.us        2813                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables);
  891 michael@paquier.xyz      2814         [ -  + ]:CBC          39 :     else if (Matches("COMMENT", "ON", "MATERIALIZED", "VIEW"))
  805 tgl@sss.pgh.pa.us        2815                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews);
  891 michael@paquier.xyz      2816         [ -  + ]:CBC          39 :     else if (Matches("COMMENT", "ON", "POLICY"))
  891 michael@paquier.xyz      2817                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_policies);
  891 michael@paquier.xyz      2818         [ -  + ]:CBC          39 :     else if (Matches("COMMENT", "ON", "POLICY", MatchAny))
  891 michael@paquier.xyz      2819                 :UBC           0 :         COMPLETE_WITH("ON");
  891 michael@paquier.xyz      2820         [ -  + ]:CBC          39 :     else if (Matches("COMMENT", "ON", "POLICY", MatchAny, "ON"))
                               2821                 :                :     {
  805 tgl@sss.pgh.pa.us        2822                 :UBC           0 :         set_completion_reference(prev2_wd);
                               2823                 :              0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables_for_policy);
                               2824                 :                :     }
  891 michael@paquier.xyz      2825         [ -  + ]:CBC          39 :     else if (Matches("COMMENT", "ON", "PROCEDURAL", "LANGUAGE"))
  891 michael@paquier.xyz      2826                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_languages);
  891 michael@paquier.xyz      2827         [ -  + ]:CBC          39 :     else if (Matches("COMMENT", "ON", "RULE", MatchAny))
  891 michael@paquier.xyz      2828                 :UBC           0 :         COMPLETE_WITH("ON");
  891 michael@paquier.xyz      2829         [ -  + ]:CBC          39 :     else if (Matches("COMMENT", "ON", "RULE", MatchAny, "ON"))
                               2830                 :                :     {
  805 tgl@sss.pgh.pa.us        2831                 :UBC           0 :         set_completion_reference(prev2_wd);
                               2832                 :              0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables_for_rule);
                               2833                 :                :     }
  891 michael@paquier.xyz      2834         [ -  + ]:CBC          39 :     else if (Matches("COMMENT", "ON", "TEXT", "SEARCH"))
  891 michael@paquier.xyz      2835                 :UBC           0 :         COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
  891 michael@paquier.xyz      2836         [ -  + ]:CBC          39 :     else if (Matches("COMMENT", "ON", "TEXT", "SEARCH", "CONFIGURATION"))
  805 tgl@sss.pgh.pa.us        2837                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_ts_configurations);
  891 michael@paquier.xyz      2838         [ -  + ]:CBC          39 :     else if (Matches("COMMENT", "ON", "TEXT", "SEARCH", "DICTIONARY"))
  805 tgl@sss.pgh.pa.us        2839                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_ts_dictionaries);
  891 michael@paquier.xyz      2840         [ -  + ]:CBC          39 :     else if (Matches("COMMENT", "ON", "TEXT", "SEARCH", "PARSER"))
  805 tgl@sss.pgh.pa.us        2841                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_ts_parsers);
  891 michael@paquier.xyz      2842         [ -  + ]:CBC          39 :     else if (Matches("COMMENT", "ON", "TEXT", "SEARCH", "TEMPLATE"))
  805 tgl@sss.pgh.pa.us        2843                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_ts_templates);
  891 michael@paquier.xyz      2844         [ -  + ]:CBC          39 :     else if (Matches("COMMENT", "ON", "TRANSFORM", "FOR"))
  805 tgl@sss.pgh.pa.us        2845                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
  891 michael@paquier.xyz      2846         [ -  + ]:CBC          39 :     else if (Matches("COMMENT", "ON", "TRANSFORM", "FOR", MatchAny))
  891 michael@paquier.xyz      2847                 :UBC           0 :         COMPLETE_WITH("LANGUAGE");
  891 michael@paquier.xyz      2848         [ -  + ]:CBC          39 :     else if (Matches("COMMENT", "ON", "TRANSFORM", "FOR", MatchAny, "LANGUAGE"))
                               2849                 :                :     {
  805 tgl@sss.pgh.pa.us        2850                 :UBC           0 :         set_completion_reference(prev2_wd);
  891 michael@paquier.xyz      2851                 :              0 :         COMPLETE_WITH_QUERY(Query_for_list_of_languages);
                               2852                 :                :     }
  891 michael@paquier.xyz      2853         [ -  + ]:CBC          39 :     else if (Matches("COMMENT", "ON", "TRIGGER", MatchAny))
  891 michael@paquier.xyz      2854                 :UBC           0 :         COMPLETE_WITH("ON");
  891 michael@paquier.xyz      2855         [ -  + ]:CBC          39 :     else if (Matches("COMMENT", "ON", "TRIGGER", MatchAny, "ON"))
                               2856                 :                :     {
  805 tgl@sss.pgh.pa.us        2857                 :UBC           0 :         set_completion_reference(prev2_wd);
                               2858                 :              0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables_for_trigger);
                               2859                 :                :     }
 2032 tgl@sss.pgh.pa.us        2860   [ +  -  +  - ]:CBC          78 :     else if (Matches("COMMENT", "ON", MatchAny, MatchAnyExcept("IS")) ||
                               2861         [ +  - ]:             78 :              Matches("COMMENT", "ON", MatchAny, MatchAny, MatchAnyExcept("IS")) ||
  891 michael@paquier.xyz      2862         [ -  + ]:             78 :              Matches("COMMENT", "ON", MatchAny, MatchAny, MatchAny, MatchAnyExcept("IS")) ||
                               2863                 :             39 :              Matches("COMMENT", "ON", MatchAny, MatchAny, MatchAny, MatchAny, MatchAnyExcept("IS")))
 2032 tgl@sss.pgh.pa.us        2864                 :UBC           0 :         COMPLETE_WITH("IS");
                               2865                 :                : 
                               2866                 :                : /* COPY */
                               2867                 :                : 
                               2868                 :                :     /*
                               2869                 :                :      * If we have COPY, offer list of tables or "(" (Also cover the analogous
                               2870                 :                :      * backslash command).
                               2871                 :                :      */
 2032 tgl@sss.pgh.pa.us        2872         [ -  + ]:CBC          39 :     else if (Matches("COPY|\\copy"))
  805 tgl@sss.pgh.pa.us        2873                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_tables, "(");
                               2874                 :                :     /* Complete COPY ( with legal query commands */
 2032 tgl@sss.pgh.pa.us        2875         [ -  + ]:CBC          39 :     else if (Matches("COPY|\\copy", "("))
 1067 michael@paquier.xyz      2876                 :UBC           0 :         COMPLETE_WITH("SELECT", "TABLE", "VALUES", "INSERT INTO", "UPDATE", "DELETE FROM", "WITH");
                               2877                 :                :     /* Complete COPY <sth> */
 1363 michael@paquier.xyz      2878         [ -  + ]:CBC          39 :     else if (Matches("COPY|\\copy", MatchAny))
 2032 tgl@sss.pgh.pa.us        2879                 :UBC           0 :         COMPLETE_WITH("FROM", "TO");
                               2880                 :                :     /* Complete COPY <sth> FROM|TO with filename */
 1363 michael@paquier.xyz      2881         [ +  + ]:CBC          39 :     else if (Matches("COPY", MatchAny, "FROM|TO"))
                               2882                 :                :     {
 4429 alvherre@alvh.no-ip.     2883                 :              4 :         completion_charp = "";
 1543 tgl@sss.pgh.pa.us        2884                 :              4 :         completion_force_quote = true;  /* COPY requires quoted filename */
 1584                          2885                 :              4 :         matches = rl_completion_matches(text, complete_from_files);
                               2886                 :                :     }
 1543                          2887         [ -  + ]:             35 :     else if (Matches("\\copy", MatchAny, "FROM|TO"))
                               2888                 :                :     {
 1543 tgl@sss.pgh.pa.us        2889                 :UBC           0 :         completion_charp = "";
                               2890                 :              0 :         completion_force_quote = false;
                               2891                 :              0 :         matches = rl_completion_matches(text, complete_from_files);
                               2892                 :                :     }
                               2893                 :                : 
                               2894                 :                :     /* Complete COPY <sth> TO <sth> */
 1363 michael@paquier.xyz      2895         [ -  + ]:CBC          35 :     else if (Matches("COPY|\\copy", MatchAny, "TO", MatchAny))
 1363 michael@paquier.xyz      2896                 :UBC           0 :         COMPLETE_WITH("WITH (");
                               2897                 :                : 
                               2898                 :                :     /* Complete COPY <sth> FROM <sth> */
 1363 michael@paquier.xyz      2899         [ -  + ]:CBC          35 :     else if (Matches("COPY|\\copy", MatchAny, "FROM", MatchAny))
 1363 michael@paquier.xyz      2900                 :UBC           0 :         COMPLETE_WITH("WITH (", "WHERE");
                               2901                 :                : 
                               2902                 :                :     /* Complete COPY <sth> FROM|TO filename WITH ( */
 1363 michael@paquier.xyz      2903         [ +  + ]:CBC          35 :     else if (Matches("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "WITH", "("))
                               2904                 :              1 :         COMPLETE_WITH("FORMAT", "FREEZE", "DELIMITER", "NULL",
                               2905                 :                :                       "HEADER", "QUOTE", "ESCAPE", "FORCE_QUOTE",
                               2906                 :                :                       "FORCE_NOT_NULL", "FORCE_NULL", "ENCODING", "DEFAULT",
                               2907                 :                :                       "ON_ERROR", "LOG_VERBOSITY");
                               2908                 :                : 
                               2909                 :                :     /* Complete COPY <sth> FROM|TO filename WITH (FORMAT */
                               2910         [ -  + ]:             34 :     else if (Matches("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "WITH", "(", "FORMAT"))
 1363 michael@paquier.xyz      2911                 :UBC           0 :         COMPLETE_WITH("binary", "csv", "text");
                               2912                 :                : 
                               2913                 :                :     /* Complete COPY <sth> FROM filename WITH (ON_ERROR */
   86 akorotkov@postgresql     2914         [ -  + ]:GNC          34 :     else if (Matches("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "WITH", "(", "ON_ERROR"))
   86 akorotkov@postgresql     2915                 :UNC           0 :         COMPLETE_WITH("stop", "ignore");
                               2916                 :                : 
                               2917                 :                :     /* Complete COPY <sth> FROM filename WITH (LOG_VERBOSITY */
   13 msawada@postgresql.o     2918         [ -  + ]:GNC          34 :     else if (Matches("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "WITH", "(", "LOG_VERBOSITY"))
   13 msawada@postgresql.o     2919                 :UNC           0 :         COMPLETE_WITH("default", "verbose");
                               2920                 :                : 
                               2921                 :                :     /* Complete COPY <sth> FROM <sth> WITH (<options>) */
 1363 michael@paquier.xyz      2922         [ -  + ]:CBC          34 :     else if (Matches("COPY|\\copy", MatchAny, "FROM", MatchAny, "WITH", MatchAny))
 1363 michael@paquier.xyz      2923                 :UBC           0 :         COMPLETE_WITH("WHERE");
                               2924                 :                : 
                               2925                 :                :     /* CREATE ACCESS METHOD */
                               2926                 :                :     /* Complete "CREATE ACCESS METHOD <name>" */
 2032 tgl@sss.pgh.pa.us        2927         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "ACCESS", "METHOD", MatchAny))
 2032 tgl@sss.pgh.pa.us        2928                 :UBC           0 :         COMPLETE_WITH("TYPE");
                               2929                 :                :     /* Complete "CREATE ACCESS METHOD <name> TYPE" */
 2032 tgl@sss.pgh.pa.us        2930         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE"))
 1777 michael@paquier.xyz      2931                 :UBC           0 :         COMPLETE_WITH("INDEX", "TABLE");
                               2932                 :                :     /* Complete "CREATE ACCESS METHOD <name> TYPE <type>" */
 2032 tgl@sss.pgh.pa.us        2933         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE", MatchAny))
 2032 tgl@sss.pgh.pa.us        2934                 :UBC           0 :         COMPLETE_WITH("HANDLER");
                               2935                 :                : 
                               2936                 :                :     /* CREATE COLLATION */
 1147 tmunro@postgresql.or     2937         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "COLLATION", MatchAny))
 1147 tmunro@postgresql.or     2938                 :UBC           0 :         COMPLETE_WITH("(", "FROM");
 1147 tmunro@postgresql.or     2939         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "COLLATION", MatchAny, "FROM"))
  805 tgl@sss.pgh.pa.us        2940                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_collations);
 1147 tmunro@postgresql.or     2941         [ -  + ]:CBC          34 :     else if (HeadMatches("CREATE", "COLLATION", MatchAny, "(*"))
                               2942                 :                :     {
 1147 tmunro@postgresql.or     2943         [ #  # ]:UBC           0 :         if (TailMatches("(|*,"))
                               2944                 :              0 :             COMPLETE_WITH("LOCALE =", "LC_COLLATE =", "LC_CTYPE =",
                               2945                 :                :                           "PROVIDER =", "DETERMINISTIC =");
                               2946         [ #  # ]:              0 :         else if (TailMatches("PROVIDER", "="))
                               2947                 :              0 :             COMPLETE_WITH("libc", "icu");
                               2948         [ #  # ]:              0 :         else if (TailMatches("DETERMINISTIC", "="))
                               2949                 :              0 :             COMPLETE_WITH("true", "false");
                               2950                 :                :     }
                               2951                 :                : 
                               2952                 :                :     /* CREATE DATABASE */
 2032 tgl@sss.pgh.pa.us        2953         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "DATABASE", MatchAny))
 2032 tgl@sss.pgh.pa.us        2954                 :UBC           0 :         COMPLETE_WITH("OWNER", "TEMPLATE", "ENCODING", "TABLESPACE",
                               2955                 :                :                       "IS_TEMPLATE", "STRATEGY",
                               2956                 :                :                       "ALLOW_CONNECTIONS", "CONNECTION LIMIT",
                               2957                 :                :                       "LC_COLLATE", "LC_CTYPE", "LOCALE", "OID",
                               2958                 :                :                       "LOCALE_PROVIDER", "ICU_LOCALE");
                               2959                 :                : 
 2032 tgl@sss.pgh.pa.us        2960         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "DATABASE", MatchAny, "TEMPLATE"))
 6057 bruce@momjian.us         2961                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_template_databases);
  747 rhaas@postgresql.org     2962         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "DATABASE", MatchAny, "STRATEGY"))
  747 rhaas@postgresql.org     2963                 :UBC           0 :         COMPLETE_WITH("WAL_LOG", "FILE_COPY");
                               2964                 :                : 
                               2965                 :                :     /* CREATE DOMAIN */
  877 michael@paquier.xyz      2966         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "DOMAIN", MatchAny))
  877 michael@paquier.xyz      2967                 :UBC           0 :         COMPLETE_WITH("AS");
  877 michael@paquier.xyz      2968         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "DOMAIN", MatchAny, "AS"))
  805 tgl@sss.pgh.pa.us        2969                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
  877 michael@paquier.xyz      2970         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "DOMAIN", MatchAny, "AS", MatchAny))
  877 michael@paquier.xyz      2971                 :UBC           0 :         COMPLETE_WITH("COLLATE", "DEFAULT", "CONSTRAINT",
                               2972                 :                :                       "NOT NULL", "NULL", "CHECK (");
  877 michael@paquier.xyz      2973         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "DOMAIN", MatchAny, "COLLATE"))
  805 tgl@sss.pgh.pa.us        2974                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_collations);
                               2975                 :                : 
                               2976                 :                :     /* CREATE EXTENSION */
                               2977                 :                :     /* Complete with available extensions rather than installed ones. */
 2032 tgl@sss.pgh.pa.us        2978         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "EXTENSION"))
 4814 tgl@sss.pgh.pa.us        2979                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_available_extensions);
                               2980                 :                :     /* CREATE EXTENSION <name> */
 2032 tgl@sss.pgh.pa.us        2981         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "EXTENSION", MatchAny))
 2032 tgl@sss.pgh.pa.us        2982                 :UBC           0 :         COMPLETE_WITH("WITH SCHEMA", "CASCADE", "VERSION");
                               2983                 :                :     /* CREATE EXTENSION <name> VERSION */
 2032 tgl@sss.pgh.pa.us        2984         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "EXTENSION", MatchAny, "VERSION"))
                               2985                 :                :     {
  805 tgl@sss.pgh.pa.us        2986                 :UBC           0 :         set_completion_reference(prev2_wd);
  663                          2987                 :              0 :         COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions);
                               2988                 :                :     }
                               2989                 :                : 
                               2990                 :                :     /* CREATE FOREIGN */
 2032 tgl@sss.pgh.pa.us        2991         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "FOREIGN"))
 2032 tgl@sss.pgh.pa.us        2992                 :UBC           0 :         COMPLETE_WITH("DATA WRAPPER", "TABLE");
                               2993                 :                : 
                               2994                 :                :     /* CREATE FOREIGN DATA WRAPPER */
 2032 tgl@sss.pgh.pa.us        2995         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "FOREIGN", "DATA", "WRAPPER", MatchAny))
 2032 tgl@sss.pgh.pa.us        2996                 :UBC           0 :         COMPLETE_WITH("HANDLER", "VALIDATOR", "OPTIONS");
                               2997                 :                : 
                               2998                 :                :     /* CREATE FOREIGN TABLE */
  820 fujii@postgresql.org     2999         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "FOREIGN", "TABLE", MatchAny))
  820 fujii@postgresql.org     3000                 :UBC           0 :         COMPLETE_WITH("(", "PARTITION OF");
                               3001                 :                : 
                               3002                 :                :     /* CREATE INDEX --- is allowed inside CREATE SCHEMA, so use TailMatches */
                               3003                 :                :     /* First off we complete CREATE UNIQUE with "INDEX" */
 2032 tgl@sss.pgh.pa.us        3004         [ -  + ]:CBC          34 :     else if (TailMatches("CREATE", "UNIQUE"))
 2032 tgl@sss.pgh.pa.us        3005                 :UBC           0 :         COMPLETE_WITH("INDEX");
                               3006                 :                : 
                               3007                 :                :     /*
                               3008                 :                :      * If we have CREATE|UNIQUE INDEX, then add "ON", "CONCURRENTLY", and
                               3009                 :                :      * existing indexes
                               3010                 :                :      */
 2032 tgl@sss.pgh.pa.us        3011         [ -  + ]:CBC          34 :     else if (TailMatches("CREATE|UNIQUE", "INDEX"))
  805 tgl@sss.pgh.pa.us        3012                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_indexes,
                               3013                 :                :                                         "ON", "CONCURRENTLY");
                               3014                 :                : 
                               3015                 :                :     /*
                               3016                 :                :      * Complete ... INDEX|CONCURRENTLY [<name>] ON with a list of relations
                               3017                 :                :      * that indexes can be created on
                               3018                 :                :      */
 2032 tgl@sss.pgh.pa.us        3019   [ +  -  -  + ]:CBC          68 :     else if (TailMatches("INDEX|CONCURRENTLY", MatchAny, "ON") ||
                               3020                 :             34 :              TailMatches("INDEX|CONCURRENTLY", "ON"))
  805 tgl@sss.pgh.pa.us        3021                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexables);
                               3022                 :                : 
                               3023                 :                :     /*
                               3024                 :                :      * Complete CREATE|UNIQUE INDEX CONCURRENTLY with "ON" and existing
                               3025                 :                :      * indexes
                               3026                 :                :      */
 2032 tgl@sss.pgh.pa.us        3027         [ -  + ]:CBC          34 :     else if (TailMatches("CREATE|UNIQUE", "INDEX", "CONCURRENTLY"))
  805 tgl@sss.pgh.pa.us        3028                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_indexes,
                               3029                 :                :                                         "ON");
                               3030                 :                :     /* Complete CREATE|UNIQUE INDEX [CONCURRENTLY] <sth> with "ON" */
 2032 tgl@sss.pgh.pa.us        3031   [ +  -  -  + ]:CBC          68 :     else if (TailMatches("CREATE|UNIQUE", "INDEX", MatchAny) ||
                               3032                 :             34 :              TailMatches("CREATE|UNIQUE", "INDEX", "CONCURRENTLY", MatchAny))
 2032 tgl@sss.pgh.pa.us        3033                 :UBC           0 :         COMPLETE_WITH("ON");
                               3034                 :                : 
                               3035                 :                :     /*
                               3036                 :                :      * Complete INDEX <name> ON <table> with a list of table columns (which
                               3037                 :                :      * should really be in parens)
                               3038                 :                :      */
 2032 tgl@sss.pgh.pa.us        3039   [ +  -  -  + ]:CBC          68 :     else if (TailMatches("INDEX", MatchAny, "ON", MatchAny) ||
                               3040                 :             34 :              TailMatches("INDEX|CONCURRENTLY", "ON", MatchAny))
 2032 tgl@sss.pgh.pa.us        3041                 :UBC           0 :         COMPLETE_WITH("(", "USING");
 2032 tgl@sss.pgh.pa.us        3042   [ +  -  -  + ]:CBC          68 :     else if (TailMatches("INDEX", MatchAny, "ON", MatchAny, "(") ||
                               3043                 :             34 :              TailMatches("INDEX|CONCURRENTLY", "ON", MatchAny, "("))
  805 tgl@sss.pgh.pa.us        3044                 :UBC           0 :         COMPLETE_WITH_ATTR(prev2_wd);
                               3045                 :                :     /* same if you put in USING */
 2032 tgl@sss.pgh.pa.us        3046         [ -  + ]:CBC          34 :     else if (TailMatches("ON", MatchAny, "USING", MatchAny, "("))
  805 tgl@sss.pgh.pa.us        3047                 :UBC           0 :         COMPLETE_WITH_ATTR(prev4_wd);
                               3048                 :                :     /* Complete USING with an index method */
 2032 tgl@sss.pgh.pa.us        3049   [ +  -  +  - ]:CBC          68 :     else if (TailMatches("INDEX", MatchAny, MatchAny, "ON", MatchAny, "USING") ||
                               3050         [ -  + ]:             68 :              TailMatches("INDEX", MatchAny, "ON", MatchAny, "USING") ||
                               3051                 :             34 :              TailMatches("INDEX", "ON", MatchAny, "USING"))
 1777 michael@paquier.xyz      3052                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_index_access_methods);
 2032 tgl@sss.pgh.pa.us        3053         [ -  + ]:CBC          34 :     else if (TailMatches("ON", MatchAny, "USING", MatchAny) &&
 2032 tgl@sss.pgh.pa.us        3054         [ #  # ]:UBC           0 :              !TailMatches("POLICY", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny) &&
                               3055         [ #  # ]:              0 :              !TailMatches("FOR", MatchAny, MatchAny, MatchAny))
                               3056                 :              0 :         COMPLETE_WITH("(");
                               3057                 :                : 
                               3058                 :                :     /* CREATE OR REPLACE */
 1675 fujii@postgresql.org     3059         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "OR"))
 1675 fujii@postgresql.org     3060                 :UBC           0 :         COMPLETE_WITH("REPLACE");
                               3061                 :                : 
                               3062                 :                :     /* CREATE POLICY */
                               3063                 :                :     /* Complete "CREATE POLICY <name> ON" */
 2032 tgl@sss.pgh.pa.us        3064         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "POLICY", MatchAny))
 2032 tgl@sss.pgh.pa.us        3065                 :UBC           0 :         COMPLETE_WITH("ON");
                               3066                 :                :     /* Complete "CREATE POLICY <name> ON <table>" */
 2032 tgl@sss.pgh.pa.us        3067         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "POLICY", MatchAny, "ON"))
  805 tgl@sss.pgh.pa.us        3068                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
                               3069                 :                :     /* Complete "CREATE POLICY <name> ON <table> AS|FOR|TO|USING|WITH CHECK" */
 2032 tgl@sss.pgh.pa.us        3070         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny))
 2032 tgl@sss.pgh.pa.us        3071                 :UBC           0 :         COMPLETE_WITH("AS", "FOR", "TO", "USING (", "WITH CHECK (");
                               3072                 :                :     /* CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE */
 2032 tgl@sss.pgh.pa.us        3073         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS"))
 2032 tgl@sss.pgh.pa.us        3074                 :UBC           0 :         COMPLETE_WITH("PERMISSIVE", "RESTRICTIVE");
                               3075                 :                : 
                               3076                 :                :     /*
                               3077                 :                :      * CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE
                               3078                 :                :      * FOR|TO|USING|WITH CHECK
                               3079                 :                :      */
 2032 tgl@sss.pgh.pa.us        3080         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny))
 2032 tgl@sss.pgh.pa.us        3081                 :UBC           0 :         COMPLETE_WITH("FOR", "TO", "USING", "WITH CHECK");
                               3082                 :                :     /* CREATE POLICY <name> ON <table> FOR ALL|SELECT|INSERT|UPDATE|DELETE */
 2032 tgl@sss.pgh.pa.us        3083         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR"))
 2032 tgl@sss.pgh.pa.us        3084                 :UBC           0 :         COMPLETE_WITH("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
                               3085                 :                :     /* Complete "CREATE POLICY <name> ON <table> FOR INSERT TO|WITH CHECK" */
 2032 tgl@sss.pgh.pa.us        3086         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "INSERT"))
 2032 tgl@sss.pgh.pa.us        3087                 :UBC           0 :         COMPLETE_WITH("TO", "WITH CHECK (");
                               3088                 :                :     /* Complete "CREATE POLICY <name> ON <table> FOR SELECT|DELETE TO|USING" */
 2032 tgl@sss.pgh.pa.us        3089         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "SELECT|DELETE"))
 2032 tgl@sss.pgh.pa.us        3090                 :UBC           0 :         COMPLETE_WITH("TO", "USING (");
                               3091                 :                :     /* CREATE POLICY <name> ON <table> FOR ALL|UPDATE TO|USING|WITH CHECK */
 2032 tgl@sss.pgh.pa.us        3092         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "ALL|UPDATE"))
 2032 tgl@sss.pgh.pa.us        3093                 :UBC           0 :         COMPLETE_WITH("TO", "USING (", "WITH CHECK (");
                               3094                 :                :     /* Complete "CREATE POLICY <name> ON <table> TO <role>" */
 2032 tgl@sss.pgh.pa.us        3095         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "TO"))
  805 tgl@sss.pgh.pa.us        3096                 :UBC           0 :         COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
                               3097                 :                :                                  Keywords_for_list_of_grant_roles);
                               3098                 :                :     /* Complete "CREATE POLICY <name> ON <table> USING (" */
 2032 tgl@sss.pgh.pa.us        3099         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "USING"))
 2032 tgl@sss.pgh.pa.us        3100                 :UBC           0 :         COMPLETE_WITH("(");
                               3101                 :                : 
                               3102                 :                :     /*
                               3103                 :                :      * CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
                               3104                 :                :      * ALL|SELECT|INSERT|UPDATE|DELETE
                               3105                 :                :      */
 2032 tgl@sss.pgh.pa.us        3106         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR"))
 2032 tgl@sss.pgh.pa.us        3107                 :UBC           0 :         COMPLETE_WITH("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
                               3108                 :                : 
                               3109                 :                :     /*
                               3110                 :                :      * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
                               3111                 :                :      * INSERT TO|WITH CHECK"
                               3112                 :                :      */
 2032 tgl@sss.pgh.pa.us        3113         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "INSERT"))
 2032 tgl@sss.pgh.pa.us        3114                 :UBC           0 :         COMPLETE_WITH("TO", "WITH CHECK (");
                               3115                 :                : 
                               3116                 :                :     /*
                               3117                 :                :      * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
                               3118                 :                :      * SELECT|DELETE TO|USING"
                               3119                 :                :      */
 2032 tgl@sss.pgh.pa.us        3120         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "SELECT|DELETE"))
 2032 tgl@sss.pgh.pa.us        3121                 :UBC           0 :         COMPLETE_WITH("TO", "USING (");
                               3122                 :                : 
                               3123                 :                :     /*
                               3124                 :                :      * CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
                               3125                 :                :      * ALL|UPDATE TO|USING|WITH CHECK
                               3126                 :                :      */
 2032 tgl@sss.pgh.pa.us        3127         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "ALL|UPDATE"))
 2032 tgl@sss.pgh.pa.us        3128                 :UBC           0 :         COMPLETE_WITH("TO", "USING (", "WITH CHECK (");
                               3129                 :                : 
                               3130                 :                :     /*
                               3131                 :                :      * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE TO
                               3132                 :                :      * <role>"
                               3133                 :                :      */
 2032 tgl@sss.pgh.pa.us        3134         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "TO"))
  805 tgl@sss.pgh.pa.us        3135                 :UBC           0 :         COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
                               3136                 :                :                                  Keywords_for_list_of_grant_roles);
                               3137                 :                : 
                               3138                 :                :     /*
                               3139                 :                :      * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE
                               3140                 :                :      * USING ("
                               3141                 :                :      */
 2032 tgl@sss.pgh.pa.us        3142         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "USING"))
 2032 tgl@sss.pgh.pa.us        3143                 :UBC           0 :         COMPLETE_WITH("(");
                               3144                 :                : 
                               3145                 :                : 
                               3146                 :                : /* CREATE PUBLICATION */
 2032 tgl@sss.pgh.pa.us        3147         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "PUBLICATION", MatchAny))
  570 alvherre@alvh.no-ip.     3148                 :UBC           0 :         COMPLETE_WITH("FOR TABLE", "FOR ALL TABLES", "FOR TABLES IN SCHEMA", "WITH (");
 2032 tgl@sss.pgh.pa.us        3149         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR"))
  570 alvherre@alvh.no-ip.     3150                 :UBC           0 :         COMPLETE_WITH("TABLE", "ALL TABLES", "TABLES IN SCHEMA");
  956 fujii@postgresql.org     3151         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL"))
  562 alvherre@alvh.no-ip.     3152                 :UBC           0 :         COMPLETE_WITH("TABLES");
  738 tomas.vondra@postgre     3153         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES"))
  562 alvherre@alvh.no-ip.     3154                 :UBC           0 :         COMPLETE_WITH("WITH (");
  562 alvherre@alvh.no-ip.     3155         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLES"))
  562 alvherre@alvh.no-ip.     3156                 :UBC           0 :         COMPLETE_WITH("IN SCHEMA");
  738 tomas.vondra@postgre     3157   [ -  +  -  - ]:CBC          34 :     else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLE", MatchAny) && !ends_with(prev_wd, ','))
  782 akapila@postgresql.o     3158                 :UBC           0 :         COMPLETE_WITH("WHERE (", "WITH (");
                               3159                 :                :     /* Complete "CREATE PUBLICATION <name> FOR TABLE" with "<table>, ..." */
  956 fujii@postgresql.org     3160         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLE"))
  805 tgl@sss.pgh.pa.us        3161                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
                               3162                 :                : 
                               3163                 :                :     /*
                               3164                 :                :      * "CREATE PUBLICATION <name> FOR TABLE <name> WHERE (" - complete with
                               3165                 :                :      * table attributes
                               3166                 :                :      */
  782 akapila@postgresql.o     3167   [ -  +  -  - ]:CBC          34 :     else if (HeadMatches("CREATE", "PUBLICATION", MatchAny) && TailMatches("WHERE"))
  782 akapila@postgresql.o     3168                 :UBC           0 :         COMPLETE_WITH("(");
  782 akapila@postgresql.o     3169   [ -  +  -  - ]:CBC          34 :     else if (HeadMatches("CREATE", "PUBLICATION", MatchAny) && TailMatches("WHERE", "("))
  782 akapila@postgresql.o     3170                 :UBC           0 :         COMPLETE_WITH_ATTR(prev3_wd);
  782 akapila@postgresql.o     3171   [ -  +  -  - ]:CBC          34 :     else if (HeadMatches("CREATE", "PUBLICATION", MatchAny) && TailMatches("WHERE", "(*)"))
  782 akapila@postgresql.o     3172                 :UBC           0 :         COMPLETE_WITH(" WITH (");
                               3173                 :                : 
                               3174                 :                :     /*
                               3175                 :                :      * Complete "CREATE PUBLICATION <name> FOR TABLES IN SCHEMA <schema>, ..."
                               3176                 :                :      */
  562 alvherre@alvh.no-ip.     3177         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLES", "IN", "SCHEMA"))
  805 tgl@sss.pgh.pa.us        3178                 :UBC           0 :         COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_schemas
                               3179                 :                :                                  " AND nspname NOT LIKE E'pg\\\\_%%'",
                               3180                 :                :                                  "CURRENT_SCHEMA");
  562 alvherre@alvh.no-ip.     3181   [ -  +  -  - ]:CBC          34 :     else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLES", "IN", "SCHEMA", MatchAny) && (!ends_with(prev_wd, ',')))
  900 akapila@postgresql.o     3182                 :UBC           0 :         COMPLETE_WITH("WITH (");
                               3183                 :                :     /* Complete "CREATE PUBLICATION <name> [...] WITH" */
 2032 tgl@sss.pgh.pa.us        3184   [ -  +  -  - ]:CBC          34 :     else if (HeadMatches("CREATE", "PUBLICATION") && TailMatches("WITH", "("))
 1038 michael@paquier.xyz      3185                 :UBC           0 :         COMPLETE_WITH("publish", "publish_via_partition_root");
                               3186                 :                : 
                               3187                 :                : /* CREATE RULE */
                               3188                 :                :     /* Complete "CREATE [ OR REPLACE ] RULE <sth>" with "AS ON" */
 1675 fujii@postgresql.org     3189   [ +  -  -  + ]:CBC          68 :     else if (Matches("CREATE", "RULE", MatchAny) ||
                               3190                 :             34 :              Matches("CREATE", "OR", "REPLACE", "RULE", MatchAny))
 2032 tgl@sss.pgh.pa.us        3191                 :UBC           0 :         COMPLETE_WITH("AS ON");
                               3192                 :                :     /* Complete "CREATE [ OR REPLACE ] RULE <sth> AS" with "ON" */
 1675 fujii@postgresql.org     3193   [ +  -  -  + ]:CBC          68 :     else if (Matches("CREATE", "RULE", MatchAny, "AS") ||
                               3194                 :             34 :              Matches("CREATE", "OR", "REPLACE", "RULE", MatchAny, "AS"))
 2032 tgl@sss.pgh.pa.us        3195                 :UBC           0 :         COMPLETE_WITH("ON");
                               3196                 :                : 
                               3197                 :                :     /*
                               3198                 :                :      * Complete "CREATE [ OR REPLACE ] RULE <sth> AS ON" with
                               3199                 :                :      * SELECT|UPDATE|INSERT|DELETE
                               3200                 :                :      */
 1675 fujii@postgresql.org     3201   [ +  -  -  + ]:CBC          68 :     else if (Matches("CREATE", "RULE", MatchAny, "AS", "ON") ||
                               3202                 :             34 :              Matches("CREATE", "OR", "REPLACE", "RULE", MatchAny, "AS", "ON"))
 2032 tgl@sss.pgh.pa.us        3203                 :UBC           0 :         COMPLETE_WITH("SELECT", "UPDATE", "INSERT", "DELETE");
                               3204                 :                :     /* Complete "AS ON SELECT|UPDATE|INSERT|DELETE" with a "TO" */
 2032 tgl@sss.pgh.pa.us        3205         [ -  + ]:CBC          34 :     else if (TailMatches("AS", "ON", "SELECT|UPDATE|INSERT|DELETE"))
 2032 tgl@sss.pgh.pa.us        3206                 :UBC           0 :         COMPLETE_WITH("TO");
                               3207                 :                :     /* Complete "AS ON <sth> TO" with a table name */
 2032 tgl@sss.pgh.pa.us        3208         [ -  + ]:CBC          34 :     else if (TailMatches("AS", "ON", "SELECT|UPDATE|INSERT|DELETE", "TO"))
  805 tgl@sss.pgh.pa.us        3209                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
                               3210                 :                : 
                               3211                 :                : /* CREATE SCHEMA [ <name> ] [ AUTHORIZATION ] */
  289 michael@paquier.xyz      3212         [ -  + ]:GNC          34 :     else if (Matches("CREATE", "SCHEMA"))
  289 michael@paquier.xyz      3213                 :UNC           0 :         COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_schemas,
                               3214                 :                :                                  "AUTHORIZATION");
  289 michael@paquier.xyz      3215   [ +  -  -  + ]:GNC          68 :     else if (Matches("CREATE", "SCHEMA", "AUTHORIZATION") ||
                               3216                 :             34 :              Matches("CREATE", "SCHEMA", MatchAny, "AUTHORIZATION"))
  289 michael@paquier.xyz      3217                 :UNC           0 :         COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
                               3218                 :                :                                  Keywords_for_list_of_owner_roles);
  289 michael@paquier.xyz      3219   [ +  -  -  + ]:GNC          68 :     else if (Matches("CREATE", "SCHEMA", "AUTHORIZATION", MatchAny) ||
                               3220                 :             34 :              Matches("CREATE", "SCHEMA", MatchAny, "AUTHORIZATION", MatchAny))
  289 michael@paquier.xyz      3221                 :UNC           0 :         COMPLETE_WITH("CREATE", "GRANT");
  289 michael@paquier.xyz      3222         [ -  + ]:GNC          34 :     else if (Matches("CREATE", "SCHEMA", MatchAny))
  289 michael@paquier.xyz      3223                 :UNC           0 :         COMPLETE_WITH("AUTHORIZATION", "CREATE", "GRANT");
                               3224                 :                : 
                               3225                 :                : /* CREATE SEQUENCE --- is allowed inside CREATE SCHEMA, so use TailMatches */
 2032 tgl@sss.pgh.pa.us        3226   [ +  -  -  + ]:CBC          68 :     else if (TailMatches("CREATE", "SEQUENCE", MatchAny) ||
                               3227                 :             34 :              TailMatches("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny))
  877 michael@paquier.xyz      3228                 :UBC           0 :         COMPLETE_WITH("AS", "INCREMENT BY", "MINVALUE", "MAXVALUE", "NO",
                               3229                 :                :                       "CACHE", "CYCLE", "OWNED BY", "START WITH");
  877 michael@paquier.xyz      3230   [ +  -  -  + ]:CBC          68 :     else if (TailMatches("CREATE", "SEQUENCE", MatchAny, "AS") ||
                               3231                 :             34 :              TailMatches("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny, "AS"))
  877 michael@paquier.xyz      3232                 :UBC           0 :         COMPLETE_WITH_CS("smallint", "integer", "bigint");
 2032 tgl@sss.pgh.pa.us        3233   [ +  -  -  + ]:CBC          68 :     else if (TailMatches("CREATE", "SEQUENCE", MatchAny, "NO") ||
                               3234                 :             34 :              TailMatches("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny, "NO"))
 2032 tgl@sss.pgh.pa.us        3235                 :UBC           0 :         COMPLETE_WITH("MINVALUE", "MAXVALUE", "CYCLE");
                               3236                 :                : 
                               3237                 :                : /* CREATE SERVER <name> */
 2032 tgl@sss.pgh.pa.us        3238         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "SERVER", MatchAny))
 2032 tgl@sss.pgh.pa.us        3239                 :UBC           0 :         COMPLETE_WITH("TYPE", "VERSION", "FOREIGN DATA WRAPPER");
                               3240                 :                : 
                               3241                 :                : /* CREATE STATISTICS <name> */
 2032 tgl@sss.pgh.pa.us        3242         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "STATISTICS", MatchAny))
 2032 tgl@sss.pgh.pa.us        3243                 :UBC           0 :         COMPLETE_WITH("(", "ON");
 2032 tgl@sss.pgh.pa.us        3244         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "STATISTICS", MatchAny, "("))
 1845 tomas.vondra@postgre     3245                 :UBC           0 :         COMPLETE_WITH("ndistinct", "dependencies", "mcv");
 1964 tomas.vondra@postgre     3246         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "STATISTICS", MatchAny, "(*)"))
 2032 tgl@sss.pgh.pa.us        3247                 :UBC           0 :         COMPLETE_WITH("ON");
 2032 tgl@sss.pgh.pa.us        3248   [ -  +  -  - ]:CBC          34 :     else if (HeadMatches("CREATE", "STATISTICS", MatchAny) &&
 2032 tgl@sss.pgh.pa.us        3249                 :UBC           0 :              TailMatches("FROM"))
  805                          3250                 :              0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
                               3251                 :                : 
                               3252                 :                : /* CREATE TABLE --- is allowed inside CREATE SCHEMA, so use TailMatches */
                               3253                 :                :     /* Complete "CREATE TEMP/TEMPORARY" with the possible temp objects */
 2032 tgl@sss.pgh.pa.us        3254         [ -  + ]:CBC          34 :     else if (TailMatches("CREATE", "TEMP|TEMPORARY"))
 2032 tgl@sss.pgh.pa.us        3255                 :UBC           0 :         COMPLETE_WITH("SEQUENCE", "TABLE", "VIEW");
                               3256                 :                :     /* Complete "CREATE UNLOGGED" with TABLE, SEQUENCE or MATVIEW */
 2032 tgl@sss.pgh.pa.us        3257         [ -  + ]:CBC          34 :     else if (TailMatches("CREATE", "UNLOGGED"))
                               3258                 :                :     {
                               3259                 :                :         /* but not MATVIEW in CREATE SCHEMA */
  289 michael@paquier.xyz      3260         [ #  # ]:UNC           0 :         if (HeadMatches("CREATE", "SCHEMA"))
                               3261                 :              0 :             COMPLETE_WITH("TABLE", "SEQUENCE");
                               3262                 :                :         else
                               3263                 :              0 :             COMPLETE_WITH("TABLE", "SEQUENCE", "MATERIALIZED VIEW");
                               3264                 :                :     }
                               3265                 :                :     /* Complete PARTITION BY with RANGE ( or LIST ( or ... */
 2032 tgl@sss.pgh.pa.us        3266         [ -  + ]:CBC          34 :     else if (TailMatches("PARTITION", "BY"))
 2032 tgl@sss.pgh.pa.us        3267                 :UBC           0 :         COMPLETE_WITH("RANGE (", "LIST (", "HASH (");
                               3268                 :                :     /* If we have xxx PARTITION OF, provide a list of partitioned tables */
 2032 tgl@sss.pgh.pa.us        3269         [ -  + ]:CBC          34 :     else if (TailMatches("PARTITION", "OF"))
  805 tgl@sss.pgh.pa.us        3270                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_partitioned_tables);
                               3271                 :                :     /* Limited completion support for partition bound specification */
 2032 tgl@sss.pgh.pa.us        3272         [ -  + ]:CBC          34 :     else if (TailMatches("PARTITION", "OF", MatchAny))
 2032 tgl@sss.pgh.pa.us        3273                 :UBC           0 :         COMPLETE_WITH("FOR VALUES", "DEFAULT");
                               3274                 :                :     /* Complete CREATE TABLE <name> with '(', AS, OF or PARTITION OF */
 1942 michael@paquier.xyz      3275   [ +  -  -  + ]:CBC          68 :     else if (TailMatches("CREATE", "TABLE", MatchAny) ||
                               3276                 :             34 :              TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny))
  150 michael@paquier.xyz      3277                 :UNC           0 :         COMPLETE_WITH("(", "AS", "OF", "PARTITION OF");
                               3278                 :                :     /* Complete CREATE TABLE <name> OF with list of composite types */
 1942 michael@paquier.xyz      3279   [ +  -  -  + ]:CBC          68 :     else if (TailMatches("CREATE", "TABLE", MatchAny, "OF") ||
                               3280                 :             34 :              TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny, "OF"))
  805 tgl@sss.pgh.pa.us        3281                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_composite_datatypes);
                               3282                 :                :     /* Complete CREATE TABLE <name> [ (...) ] AS with list of keywords */
  150 michael@paquier.xyz      3283   [ +  -  +  - ]:GNC          68 :     else if (TailMatches("CREATE", "TABLE", MatchAny, "AS") ||
                               3284         [ +  - ]:             68 :              TailMatches("CREATE", "TABLE", MatchAny, "(*)", "AS") ||
                               3285         [ -  + ]:             68 :              TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny, "AS") ||
                               3286                 :             34 :              TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny, "(*)", "AS"))
  150 michael@paquier.xyz      3287                 :UNC           0 :         COMPLETE_WITH("EXECUTE", "SELECT", "TABLE", "VALUES", "WITH");
                               3288                 :                :     /* Complete CREATE TABLE name (...) with supported options */
 1942 michael@paquier.xyz      3289   [ +  -  -  + ]:CBC          68 :     else if (TailMatches("CREATE", "TABLE", MatchAny, "(*)") ||
                               3290                 :             34 :              TailMatches("CREATE", "UNLOGGED", "TABLE", MatchAny, "(*)"))
  150 michael@paquier.xyz      3291                 :UNC           0 :         COMPLETE_WITH("AS", "INHERITS (", "PARTITION BY", "USING", "TABLESPACE", "WITH (");
 1942 michael@paquier.xyz      3292         [ -  + ]:CBC          34 :     else if (TailMatches("CREATE", "TEMP|TEMPORARY", "TABLE", MatchAny, "(*)"))
  150 michael@paquier.xyz      3293                 :UNC           0 :         COMPLETE_WITH("AS", "INHERITS (", "ON COMMIT", "PARTITION BY",
                               3294                 :                :                       "TABLESPACE", "WITH (");
                               3295                 :                :     /* Complete CREATE TABLE (...) USING with table access methods */
 1777 michael@paquier.xyz      3296   [ +  -  -  + ]:CBC          68 :     else if (TailMatches("CREATE", "TABLE", MatchAny, "(*)", "USING") ||
                               3297                 :             34 :              TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny, "(*)", "USING"))
 1777 michael@paquier.xyz      3298                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_table_access_methods);
                               3299                 :                :     /* Complete CREATE TABLE (...) WITH with storage parameters */
 1939 michael@paquier.xyz      3300   [ +  -  -  + ]:CBC          68 :     else if (TailMatches("CREATE", "TABLE", MatchAny, "(*)", "WITH", "(") ||
                               3301                 :             34 :              TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny, "(*)", "WITH", "("))
 1939 michael@paquier.xyz      3302                 :UBC           0 :         COMPLETE_WITH_LIST(table_storage_parameters);
                               3303                 :                :     /* Complete CREATE TABLE ON COMMIT with actions */
 1942 michael@paquier.xyz      3304         [ -  + ]:CBC          34 :     else if (TailMatches("CREATE", "TEMP|TEMPORARY", "TABLE", MatchAny, "(*)", "ON", "COMMIT"))
 1942 michael@paquier.xyz      3305                 :UBC           0 :         COMPLETE_WITH("DELETE ROWS", "DROP", "PRESERVE ROWS");
                               3306                 :                : 
                               3307                 :                : /* CREATE TABLESPACE */
 2032 tgl@sss.pgh.pa.us        3308         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "TABLESPACE", MatchAny))
 2032 tgl@sss.pgh.pa.us        3309                 :UBC           0 :         COMPLETE_WITH("OWNER", "LOCATION");
                               3310                 :                :     /* Complete CREATE TABLESPACE name OWNER name with "LOCATION" */
 2032 tgl@sss.pgh.pa.us        3311         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "TABLESPACE", MatchAny, "OWNER", MatchAny))
 2032 tgl@sss.pgh.pa.us        3312                 :UBC           0 :         COMPLETE_WITH("LOCATION");
                               3313                 :                : 
                               3314                 :                : /* CREATE TEXT SEARCH */
 2032 tgl@sss.pgh.pa.us        3315         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "TEXT", "SEARCH"))
 2032 tgl@sss.pgh.pa.us        3316                 :UBC           0 :         COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
 1499 tgl@sss.pgh.pa.us        3317         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "TEXT", "SEARCH", "CONFIGURATION|DICTIONARY|PARSER|TEMPLATE", MatchAny))
 2032 tgl@sss.pgh.pa.us        3318                 :UBC           0 :         COMPLETE_WITH("(");
                               3319                 :                : 
                               3320                 :                : /* CREATE TRANSFORM */
  877 michael@paquier.xyz      3321   [ +  -  -  + ]:CBC          68 :     else if (Matches("CREATE", "TRANSFORM") ||
                               3322                 :             34 :              Matches("CREATE", "OR", "REPLACE", "TRANSFORM"))
  877 michael@paquier.xyz      3323                 :UBC           0 :         COMPLETE_WITH("FOR");
  877 michael@paquier.xyz      3324   [ +  -  -  + ]:CBC          68 :     else if (Matches("CREATE", "TRANSFORM", "FOR") ||
  850 tgl@sss.pgh.pa.us        3325                 :             34 :              Matches("CREATE", "OR", "REPLACE", "TRANSFORM", "FOR"))
  805 tgl@sss.pgh.pa.us        3326                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
  877 michael@paquier.xyz      3327   [ +  -  -  + ]:CBC          68 :     else if (Matches("CREATE", "TRANSFORM", "FOR", MatchAny) ||
                               3328                 :             34 :              Matches("CREATE", "OR", "REPLACE", "TRANSFORM", "FOR", MatchAny))
  877 michael@paquier.xyz      3329                 :UBC           0 :         COMPLETE_WITH("LANGUAGE");
  877 michael@paquier.xyz      3330   [ +  -  -  + ]:CBC          68 :     else if (Matches("CREATE", "TRANSFORM", "FOR", MatchAny, "LANGUAGE") ||
                               3331                 :             34 :              Matches("CREATE", "OR", "REPLACE", "TRANSFORM", "FOR", MatchAny, "LANGUAGE"))
                               3332                 :                :     {
  805 tgl@sss.pgh.pa.us        3333                 :UBC           0 :         set_completion_reference(prev2_wd);
  877 michael@paquier.xyz      3334                 :              0 :         COMPLETE_WITH_QUERY(Query_for_list_of_languages);
                               3335                 :                :     }
                               3336                 :                : 
                               3337                 :                : /* CREATE SUBSCRIPTION */
 2032 tgl@sss.pgh.pa.us        3338         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "SUBSCRIPTION", MatchAny))
 2032 tgl@sss.pgh.pa.us        3339                 :UBC           0 :         COMPLETE_WITH("CONNECTION");
 2032 tgl@sss.pgh.pa.us        3340         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "SUBSCRIPTION", MatchAny, "CONNECTION", MatchAny))
 2032 tgl@sss.pgh.pa.us        3341                 :UBC           0 :         COMPLETE_WITH("PUBLICATION");
 2032 tgl@sss.pgh.pa.us        3342         [ +  - ]:CBC          34 :     else if (Matches("CREATE", "SUBSCRIPTION", MatchAny, "CONNECTION",
                               3343                 :                :                      MatchAny, "PUBLICATION"))
                               3344                 :                :     {
                               3345                 :                :         /* complete with nothing here as this refers to remote publications */
                               3346                 :                :     }
                               3347   [ -  +  -  - ]:             34 :     else if (HeadMatches("CREATE", "SUBSCRIPTION") && TailMatches("PUBLICATION", MatchAny))
 2032 tgl@sss.pgh.pa.us        3348                 :UBC           0 :         COMPLETE_WITH("WITH (");
                               3349                 :                :     /* Complete "CREATE SUBSCRIPTION <name> ...  WITH ( <opt>" */
 2032 tgl@sss.pgh.pa.us        3350   [ -  +  -  - ]:CBC          34 :     else if (HeadMatches("CREATE", "SUBSCRIPTION") && TailMatches("WITH", "("))
 1038 michael@paquier.xyz      3351                 :UBC           0 :         COMPLETE_WITH("binary", "connect", "copy_data", "create_slot",
                               3352                 :                :                       "disable_on_error", "enabled", "failover", "origin",
                               3353                 :                :                       "password_required", "run_as_owner", "slot_name",
                               3354                 :                :                       "streaming", "synchronous_commit", "two_phase");
                               3355                 :                : 
                               3356                 :                : /* CREATE TRIGGER --- is allowed inside CREATE SCHEMA, so use TailMatches */
                               3357                 :                : 
                               3358                 :                :     /*
                               3359                 :                :      * Complete CREATE [ OR REPLACE ] TRIGGER <name> with BEFORE|AFTER|INSTEAD
                               3360                 :                :      * OF.
                               3361                 :                :      */
 1243 michael@paquier.xyz      3362   [ +  -  -  + ]:CBC          68 :     else if (TailMatches("CREATE", "TRIGGER", MatchAny) ||
                               3363                 :             34 :              TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny))
 2032 tgl@sss.pgh.pa.us        3364                 :UBC           0 :         COMPLETE_WITH("BEFORE", "AFTER", "INSTEAD OF");
                               3365                 :                : 
                               3366                 :                :     /*
                               3367                 :                :      * Complete CREATE [ OR REPLACE ] TRIGGER <name> BEFORE,AFTER with an
                               3368                 :                :      * event.
                               3369                 :                :      */
 1243 michael@paquier.xyz      3370   [ +  -  -  + ]:CBC          68 :     else if (TailMatches("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER") ||
                               3371                 :             34 :              TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "BEFORE|AFTER"))
 2032 tgl@sss.pgh.pa.us        3372                 :UBC           0 :         COMPLETE_WITH("INSERT", "DELETE", "UPDATE", "TRUNCATE");
                               3373                 :                :     /* Complete CREATE [ OR REPLACE ] TRIGGER <name> INSTEAD OF with an event */
 1243 michael@paquier.xyz      3374   [ +  -  -  + ]:CBC          68 :     else if (TailMatches("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF") ||
                               3375                 :             34 :              TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "INSTEAD", "OF"))
 2032 tgl@sss.pgh.pa.us        3376                 :UBC           0 :         COMPLETE_WITH("INSERT", "DELETE", "UPDATE");
                               3377                 :                : 
                               3378                 :                :     /*
                               3379                 :                :      * Complete CREATE [ OR REPLACE ] TRIGGER <name> BEFORE,AFTER sth with
                               3380                 :                :      * OR|ON.
                               3381                 :                :      */
 2032 tgl@sss.pgh.pa.us        3382   [ +  -  +  - ]:CBC          68 :     else if (TailMatches("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny) ||
 1243 michael@paquier.xyz      3383         [ +  - ]:             68 :              TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny) ||
                               3384         [ -  + ]:             68 :              TailMatches("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny) ||
                               3385                 :             34 :              TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny))
 2032 tgl@sss.pgh.pa.us        3386                 :UBC           0 :         COMPLETE_WITH("ON", "OR");
                               3387                 :                : 
                               3388                 :                :     /*
                               3389                 :                :      * Complete CREATE [ OR REPLACE ] TRIGGER <name> BEFORE,AFTER event ON
                               3390                 :                :      * with a list of tables.  EXECUTE FUNCTION is the recommended grammar
                               3391                 :                :      * instead of EXECUTE PROCEDURE in version 11 and upwards.
                               3392                 :                :      */
 1243 michael@paquier.xyz      3393   [ +  -  -  + ]:CBC          68 :     else if (TailMatches("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny, "ON") ||
                               3394                 :             34 :              TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny, "ON"))
  805 tgl@sss.pgh.pa.us        3395                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
                               3396                 :                : 
                               3397                 :                :     /*
                               3398                 :                :      * Complete CREATE [ OR REPLACE ] TRIGGER ... INSTEAD OF event ON with a
                               3399                 :                :      * list of views.
                               3400                 :                :      */
 1243 michael@paquier.xyz      3401   [ +  -  -  + ]:CBC          68 :     else if (TailMatches("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny, "ON") ||
                               3402                 :             34 :              TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny, "ON"))
  805 tgl@sss.pgh.pa.us        3403                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views);
 1243 michael@paquier.xyz      3404   [ +  -  -  + ]:CBC          68 :     else if ((HeadMatches("CREATE", "TRIGGER") ||
                               3405         [ -  - ]:             34 :               HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) &&
 1243 michael@paquier.xyz      3406                 :UBC           0 :              TailMatches("ON", MatchAny))
                               3407                 :                :     {
 1997                          3408         [ #  # ]:              0 :         if (pset.sversion >= 110000)
                               3409                 :              0 :             COMPLETE_WITH("NOT DEFERRABLE", "DEFERRABLE", "INITIALLY",
                               3410                 :                :                           "REFERENCING", "FOR", "WHEN (", "EXECUTE FUNCTION");
                               3411                 :                :         else
                               3412                 :              0 :             COMPLETE_WITH("NOT DEFERRABLE", "DEFERRABLE", "INITIALLY",
                               3413                 :                :                           "REFERENCING", "FOR", "WHEN (", "EXECUTE PROCEDURE");
                               3414                 :                :     }
 1243 michael@paquier.xyz      3415   [ +  -  -  + ]:CBC          68 :     else if ((HeadMatches("CREATE", "TRIGGER") ||
                               3416         [ -  - ]:             34 :               HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) &&
 2032 tgl@sss.pgh.pa.us        3417         [ #  # ]:UBC           0 :              (TailMatches("DEFERRABLE") || TailMatches("INITIALLY", "IMMEDIATE|DEFERRED")))
                               3418                 :                :     {
 1997 michael@paquier.xyz      3419         [ #  # ]:              0 :         if (pset.sversion >= 110000)
                               3420                 :              0 :             COMPLETE_WITH("REFERENCING", "FOR", "WHEN (", "EXECUTE FUNCTION");
                               3421                 :                :         else
                               3422                 :              0 :             COMPLETE_WITH("REFERENCING", "FOR", "WHEN (", "EXECUTE PROCEDURE");
                               3423                 :                :     }
 1243 michael@paquier.xyz      3424   [ +  -  -  + ]:CBC          68 :     else if ((HeadMatches("CREATE", "TRIGGER") ||
                               3425         [ -  - ]:             34 :               HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) &&
 1243 michael@paquier.xyz      3426                 :UBC           0 :              TailMatches("REFERENCING"))
 2032 tgl@sss.pgh.pa.us        3427                 :              0 :         COMPLETE_WITH("OLD TABLE", "NEW TABLE");
 1243 michael@paquier.xyz      3428   [ +  -  -  + ]:CBC          68 :     else if ((HeadMatches("CREATE", "TRIGGER") ||
                               3429         [ -  - ]:             34 :               HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) &&
 1243 michael@paquier.xyz      3430                 :UBC           0 :              TailMatches("OLD|NEW", "TABLE"))
 2032 tgl@sss.pgh.pa.us        3431                 :              0 :         COMPLETE_WITH("AS");
 1243 michael@paquier.xyz      3432   [ +  -  -  + ]:CBC          68 :     else if ((HeadMatches("CREATE", "TRIGGER") ||
                               3433         [ -  - ]:             34 :               HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) &&
 2032 tgl@sss.pgh.pa.us        3434         [ #  # ]:UBC           0 :              (TailMatches("REFERENCING", "OLD", "TABLE", "AS", MatchAny) ||
                               3435                 :              0 :               TailMatches("REFERENCING", "OLD", "TABLE", MatchAny)))
                               3436                 :                :     {
 1997 michael@paquier.xyz      3437         [ #  # ]:              0 :         if (pset.sversion >= 110000)
                               3438                 :              0 :             COMPLETE_WITH("NEW TABLE", "FOR", "WHEN (", "EXECUTE FUNCTION");
                               3439                 :                :         else
                               3440                 :              0 :             COMPLETE_WITH("NEW TABLE", "FOR", "WHEN (", "EXECUTE PROCEDURE");
                               3441                 :                :     }
 1243 michael@paquier.xyz      3442   [ +  -  -  + ]:CBC          68 :     else if ((HeadMatches("CREATE", "TRIGGER") ||
                               3443         [ -  - ]:             34 :               HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) &&
 2032 tgl@sss.pgh.pa.us        3444         [ #  # ]:UBC           0 :              (TailMatches("REFERENCING", "NEW", "TABLE", "AS", MatchAny) ||
                               3445                 :              0 :               TailMatches("REFERENCING", "NEW", "TABLE", MatchAny)))
                               3446                 :                :     {
 1997 michael@paquier.xyz      3447         [ #  # ]:              0 :         if (pset.sversion >= 110000)
                               3448                 :              0 :             COMPLETE_WITH("OLD TABLE", "FOR", "WHEN (", "EXECUTE FUNCTION");
                               3449                 :                :         else
                               3450                 :              0 :             COMPLETE_WITH("OLD TABLE", "FOR", "WHEN (", "EXECUTE PROCEDURE");
                               3451                 :                :     }
 1243 michael@paquier.xyz      3452   [ +  -  -  + ]:CBC          68 :     else if ((HeadMatches("CREATE", "TRIGGER") ||
                               3453         [ -  - ]:             34 :               HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) &&
 2032 tgl@sss.pgh.pa.us        3454         [ #  # ]:UBC           0 :              (TailMatches("REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
                               3455         [ #  # ]:              0 :               TailMatches("REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
                               3456         [ #  # ]:              0 :               TailMatches("REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", MatchAny) ||
                               3457                 :              0 :               TailMatches("REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", MatchAny)))
                               3458                 :                :     {
 1997 michael@paquier.xyz      3459         [ #  # ]:              0 :         if (pset.sversion >= 110000)
                               3460                 :              0 :             COMPLETE_WITH("FOR", "WHEN (", "EXECUTE FUNCTION");
                               3461                 :                :         else
                               3462                 :              0 :             COMPLETE_WITH("FOR", "WHEN (", "EXECUTE PROCEDURE");
                               3463                 :                :     }
 1243 michael@paquier.xyz      3464   [ +  -  -  + ]:CBC          68 :     else if ((HeadMatches("CREATE", "TRIGGER") ||
                               3465         [ -  - ]:             34 :               HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) &&
 1243 michael@paquier.xyz      3466                 :UBC           0 :              TailMatches("FOR"))
 2032 tgl@sss.pgh.pa.us        3467                 :              0 :         COMPLETE_WITH("EACH", "ROW", "STATEMENT");
 1243 michael@paquier.xyz      3468   [ +  -  -  + ]:CBC          68 :     else if ((HeadMatches("CREATE", "TRIGGER") ||
                               3469         [ -  - ]:             34 :               HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) &&
 1243 michael@paquier.xyz      3470                 :UBC           0 :              TailMatches("FOR", "EACH"))
 2032 tgl@sss.pgh.pa.us        3471                 :              0 :         COMPLETE_WITH("ROW", "STATEMENT");
 1243 michael@paquier.xyz      3472   [ +  -  -  + ]:CBC          68 :     else if ((HeadMatches("CREATE", "TRIGGER") ||
                               3473         [ -  - ]:             34 :               HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) &&
 2032 tgl@sss.pgh.pa.us        3474         [ #  # ]:UBC           0 :              (TailMatches("FOR", "EACH", "ROW|STATEMENT") ||
                               3475                 :              0 :               TailMatches("FOR", "ROW|STATEMENT")))
                               3476                 :                :     {
 1997 michael@paquier.xyz      3477         [ #  # ]:              0 :         if (pset.sversion >= 110000)
                               3478                 :              0 :             COMPLETE_WITH("WHEN (", "EXECUTE FUNCTION");
                               3479                 :                :         else
                               3480                 :              0 :             COMPLETE_WITH("WHEN (", "EXECUTE PROCEDURE");
                               3481                 :                :     }
 1243 michael@paquier.xyz      3482   [ +  -  -  + ]:CBC          68 :     else if ((HeadMatches("CREATE", "TRIGGER") ||
                               3483         [ -  - ]:             34 :               HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) &&
 1243 michael@paquier.xyz      3484                 :UBC           0 :              TailMatches("WHEN", "(*)"))
                               3485                 :                :     {
 1997                          3486         [ #  # ]:              0 :         if (pset.sversion >= 110000)
                               3487                 :              0 :             COMPLETE_WITH("EXECUTE FUNCTION");
                               3488                 :                :         else
                               3489                 :              0 :             COMPLETE_WITH("EXECUTE PROCEDURE");
                               3490                 :                :     }
                               3491                 :                : 
                               3492                 :                :     /*
                               3493                 :                :      * Complete CREATE [ OR REPLACE ] TRIGGER ... EXECUTE with
                               3494                 :                :      * PROCEDURE|FUNCTION.
                               3495                 :                :      */
 1243 michael@paquier.xyz      3496   [ +  -  -  + ]:CBC          68 :     else if ((HeadMatches("CREATE", "TRIGGER") ||
                               3497         [ -  - ]:             34 :               HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) &&
 1243 michael@paquier.xyz      3498                 :UBC           0 :              TailMatches("EXECUTE"))
                               3499                 :                :     {
 1997                          3500         [ #  # ]:              0 :         if (pset.sversion >= 110000)
                               3501                 :              0 :             COMPLETE_WITH("FUNCTION");
                               3502                 :                :         else
                               3503                 :              0 :             COMPLETE_WITH("PROCEDURE");
                               3504                 :                :     }
 1243 michael@paquier.xyz      3505   [ +  -  -  + ]:CBC          68 :     else if ((HeadMatches("CREATE", "TRIGGER") ||
                               3506         [ -  - ]:             34 :               HeadMatches("CREATE", "OR", "REPLACE", "TRIGGER")) &&
 1997 michael@paquier.xyz      3507                 :UBC           0 :              TailMatches("EXECUTE", "FUNCTION|PROCEDURE"))
  805 tgl@sss.pgh.pa.us        3508                 :              0 :         COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_functions);
                               3509                 :                : 
                               3510                 :                : /* CREATE ROLE,USER,GROUP <name> */
 2032 tgl@sss.pgh.pa.us        3511         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "ROLE|GROUP|USER", MatchAny) &&
 2032 tgl@sss.pgh.pa.us        3512         [ #  # ]:UBC           0 :              !TailMatches("USER", "MAPPING"))
                               3513                 :              0 :         COMPLETE_WITH("ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB",
                               3514                 :                :                       "CREATEROLE", "ENCRYPTED PASSWORD", "IN", "INHERIT",
                               3515                 :                :                       "LOGIN", "NOBYPASSRLS",
                               3516                 :                :                       "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
                               3517                 :                :                       "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
                               3518                 :                :                       "REPLICATION", "ROLE", "SUPERUSER", "SYSID",
                               3519                 :                :                       "VALID UNTIL", "WITH");
                               3520                 :                : 
                               3521                 :                : /* CREATE ROLE,USER,GROUP <name> WITH */
 2032 tgl@sss.pgh.pa.us        3522         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "ROLE|GROUP|USER", MatchAny, "WITH"))
                               3523                 :                :         /* Similar to the above, but don't complete "WITH" again. */
 2032 tgl@sss.pgh.pa.us        3524                 :UBC           0 :         COMPLETE_WITH("ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB",
                               3525                 :                :                       "CREATEROLE", "ENCRYPTED PASSWORD", "IN", "INHERIT",
                               3526                 :                :                       "LOGIN", "NOBYPASSRLS",
                               3527                 :                :                       "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
                               3528                 :                :                       "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
                               3529                 :                :                       "REPLICATION", "ROLE", "SUPERUSER", "SYSID",
                               3530                 :                :                       "VALID UNTIL");
                               3531                 :                : 
                               3532                 :                :     /* complete CREATE ROLE,USER,GROUP <name> IN with ROLE,GROUP */
 2032 tgl@sss.pgh.pa.us        3533         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "ROLE|USER|GROUP", MatchAny, "IN"))
 2032 tgl@sss.pgh.pa.us        3534                 :UBC           0 :         COMPLETE_WITH("GROUP", "ROLE");
                               3535                 :                : 
                               3536                 :                : /* CREATE TYPE */
 1737 tmunro@postgresql.or     3537         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "TYPE", MatchAny))
 1737 tmunro@postgresql.or     3538                 :UBC           0 :         COMPLETE_WITH("(", "AS");
 1737 tmunro@postgresql.or     3539         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "TYPE", MatchAny, "AS"))
 1737 tmunro@postgresql.or     3540                 :UBC           0 :         COMPLETE_WITH("ENUM", "RANGE", "(");
 1737 tmunro@postgresql.or     3541         [ -  + ]:CBC          34 :     else if (HeadMatches("CREATE", "TYPE", MatchAny, "AS", "("))
                               3542                 :                :     {
 1737 tmunro@postgresql.or     3543         [ #  # ]:UBC           0 :         if (TailMatches("(|*,", MatchAny))
  805 tgl@sss.pgh.pa.us        3544                 :              0 :             COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
 1737 tmunro@postgresql.or     3545         [ #  # ]:              0 :         else if (TailMatches("(|*,", MatchAny, MatchAnyExcept("*)")))
                               3546                 :              0 :             COMPLETE_WITH("COLLATE", ",", ")");
                               3547                 :                :     }
 1737 tmunro@postgresql.or     3548         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "TYPE", MatchAny, "AS", "ENUM|RANGE"))
 1737 tmunro@postgresql.or     3549                 :UBC           0 :         COMPLETE_WITH("(");
 1737 tmunro@postgresql.or     3550         [ -  + ]:CBC          34 :     else if (HeadMatches("CREATE", "TYPE", MatchAny, "("))
                               3551                 :                :     {
 1737 tmunro@postgresql.or     3552         [ #  # ]:UBC           0 :         if (TailMatches("(|*,"))
                               3553                 :              0 :             COMPLETE_WITH("INPUT", "OUTPUT", "RECEIVE", "SEND",
                               3554                 :                :                           "TYPMOD_IN", "TYPMOD_OUT", "ANALYZE", "SUBSCRIPT",
                               3555                 :                :                           "INTERNALLENGTH", "PASSEDBYVALUE", "ALIGNMENT",
                               3556                 :                :                           "STORAGE", "LIKE", "CATEGORY", "PREFERRED",
                               3557                 :                :                           "DEFAULT", "ELEMENT", "DELIMITER",
                               3558                 :                :                           "COLLATABLE");
                               3559         [ #  # ]:              0 :         else if (TailMatches("(*|*,", MatchAnyExcept("*=")))
                               3560                 :              0 :             COMPLETE_WITH("=");
                               3561         [ #  # ]:              0 :         else if (TailMatches("=", MatchAnyExcept("*)")))
                               3562                 :              0 :             COMPLETE_WITH(",", ")");
                               3563                 :                :     }
 1737 tmunro@postgresql.or     3564         [ -  + ]:CBC          34 :     else if (HeadMatches("CREATE", "TYPE", MatchAny, "AS", "RANGE", "("))
                               3565                 :                :     {
 1737 tmunro@postgresql.or     3566         [ #  # ]:UBC           0 :         if (TailMatches("(|*,"))
                               3567                 :              0 :             COMPLETE_WITH("SUBTYPE", "SUBTYPE_OPCLASS", "COLLATION",
                               3568                 :                :                           "CANONICAL", "SUBTYPE_DIFF",
                               3569                 :                :                           "MULTIRANGE_TYPE_NAME");
                               3570         [ #  # ]:              0 :         else if (TailMatches("(*|*,", MatchAnyExcept("*=")))
                               3571                 :              0 :             COMPLETE_WITH("=");
                               3572         [ #  # ]:              0 :         else if (TailMatches("=", MatchAnyExcept("*)")))
                               3573                 :              0 :             COMPLETE_WITH(",", ")");
                               3574                 :                :     }
                               3575                 :                : 
                               3576                 :                : /* CREATE VIEW --- is allowed inside CREATE SCHEMA, so use TailMatches */
                               3577                 :                :     /* Complete CREATE [ OR REPLACE ] VIEW <name> with AS or WITH */
 1675 fujii@postgresql.org     3578   [ +  -  -  + ]:CBC          68 :     else if (TailMatches("CREATE", "VIEW", MatchAny) ||
                               3579                 :             34 :              TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny))
  138 dean.a.rasheed@gmail     3580                 :UNC           0 :         COMPLETE_WITH("AS", "WITH");
                               3581                 :                :     /* Complete "CREATE [ OR REPLACE ] VIEW <sth> AS with "SELECT" */
 1675 fujii@postgresql.org     3582   [ +  -  -  + ]:CBC          68 :     else if (TailMatches("CREATE", "VIEW", MatchAny, "AS") ||
                               3583                 :             34 :              TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "AS"))
 2032 tgl@sss.pgh.pa.us        3584                 :UBC           0 :         COMPLETE_WITH("SELECT");
                               3585                 :                :     /* CREATE [ OR REPLACE ] VIEW <name> WITH ( yyy [= zzz] ) */
  138 dean.a.rasheed@gmail     3586   [ +  -  -  + ]:GNC          68 :     else if (TailMatches("CREATE", "VIEW", MatchAny, "WITH") ||
                               3587                 :             34 :              TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "WITH"))
  138 dean.a.rasheed@gmail     3588                 :UNC           0 :         COMPLETE_WITH("(");
  138 dean.a.rasheed@gmail     3589   [ +  -  -  + ]:GNC          68 :     else if (TailMatches("CREATE", "VIEW", MatchAny, "WITH", "(") ||
                               3590                 :             34 :              TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "WITH", "("))
  138 dean.a.rasheed@gmail     3591                 :UNC           0 :         COMPLETE_WITH_LIST(view_optional_parameters);
  138 dean.a.rasheed@gmail     3592   [ +  -  -  + ]:GNC          68 :     else if (TailMatches("CREATE", "VIEW", MatchAny, "WITH", "(", "check_option") ||
                               3593                 :             34 :              TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "WITH", "(", "check_option"))
  138 dean.a.rasheed@gmail     3594                 :UNC           0 :         COMPLETE_WITH("=");
  138 dean.a.rasheed@gmail     3595   [ +  -  -  + ]:GNC          68 :     else if (TailMatches("CREATE", "VIEW", MatchAny, "WITH", "(", "check_option", "=") ||
                               3596                 :             34 :              TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "WITH", "(", "check_option", "="))
  138 dean.a.rasheed@gmail     3597                 :UNC           0 :         COMPLETE_WITH("local", "cascaded");
                               3598                 :                :     /* CREATE [ OR REPLACE ] VIEW <name> WITH ( ... ) AS */
  138 dean.a.rasheed@gmail     3599   [ +  -  -  + ]:GNC          68 :     else if (TailMatches("CREATE", "VIEW", MatchAny, "WITH", "(*)") ||
                               3600                 :             34 :              TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "WITH", "(*)"))
  138 dean.a.rasheed@gmail     3601                 :UNC           0 :         COMPLETE_WITH("AS");
                               3602                 :                :     /* CREATE [ OR REPLACE ] VIEW <name> WITH ( ... ) AS SELECT */
  138 dean.a.rasheed@gmail     3603   [ +  -  -  + ]:GNC          68 :     else if (TailMatches("CREATE", "VIEW", MatchAny, "WITH", "(*)", "AS") ||
                               3604                 :             34 :              TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "WITH", "(*)", "AS"))
  138 dean.a.rasheed@gmail     3605                 :UNC           0 :         COMPLETE_WITH("SELECT");
                               3606                 :                : 
                               3607                 :                : /* CREATE MATERIALIZED VIEW */
 2032 tgl@sss.pgh.pa.us        3608         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "MATERIALIZED"))
 2032 tgl@sss.pgh.pa.us        3609                 :UBC           0 :         COMPLETE_WITH("VIEW");
                               3610                 :                :     /* Complete CREATE MATERIALIZED VIEW <name> with AS */
 2032 tgl@sss.pgh.pa.us        3611         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny))
 2032 tgl@sss.pgh.pa.us        3612                 :UBC           0 :         COMPLETE_WITH("AS");
                               3613                 :                :     /* Complete "CREATE MATERIALIZED VIEW <sth> AS with "SELECT" */
 2032 tgl@sss.pgh.pa.us        3614         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny, "AS"))
 2032 tgl@sss.pgh.pa.us        3615                 :UBC           0 :         COMPLETE_WITH("SELECT");
                               3616                 :                : 
                               3617                 :                : /* CREATE EVENT TRIGGER */
 2032 tgl@sss.pgh.pa.us        3618         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "EVENT"))
 2032 tgl@sss.pgh.pa.us        3619                 :UBC           0 :         COMPLETE_WITH("TRIGGER");
                               3620                 :                :     /* Complete CREATE EVENT TRIGGER <name> with ON */
 2032 tgl@sss.pgh.pa.us        3621         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "EVENT", "TRIGGER", MatchAny))
 2032 tgl@sss.pgh.pa.us        3622                 :UBC           0 :         COMPLETE_WITH("ON");
                               3623                 :                :     /* Complete CREATE EVENT TRIGGER <name> ON with event_type */
 2032 tgl@sss.pgh.pa.us        3624         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "EVENT", "TRIGGER", MatchAny, "ON"))
  181 akorotkov@postgresql     3625                 :UNC           0 :         COMPLETE_WITH("ddl_command_start", "ddl_command_end", "login",
                               3626                 :                :                       "sql_drop", "table_rewrite");
                               3627                 :                : 
                               3628                 :                :     /*
                               3629                 :                :      * Complete CREATE EVENT TRIGGER <name> ON <event_type>.  EXECUTE FUNCTION
                               3630                 :                :      * is the recommended grammar instead of EXECUTE PROCEDURE in version 11
                               3631                 :                :      * and upwards.
                               3632                 :                :      */
 1997 michael@paquier.xyz      3633         [ -  + ]:CBC          34 :     else if (Matches("CREATE", "EVENT", "TRIGGER", MatchAny, "ON", MatchAny))
                               3634                 :                :     {
 1997 michael@paquier.xyz      3635         [ #  # ]:UBC           0 :         if (pset.sversion >= 110000)
                               3636                 :              0 :             COMPLETE_WITH("WHEN TAG IN (", "EXECUTE FUNCTION");
                               3637                 :                :         else
                               3638                 :              0 :             COMPLETE_WITH("WHEN TAG IN (", "EXECUTE PROCEDURE");
                               3639                 :                :     }
 1997 michael@paquier.xyz      3640   [ -  +  -  - ]:CBC          34 :     else if (HeadMatches("CREATE", "EVENT", "TRIGGER") &&
 1997 michael@paquier.xyz      3641                 :UBC           0 :              TailMatches("WHEN|AND", MatchAny, "IN", "(*)"))
                               3642                 :                :     {
                               3643         [ #  # ]:              0 :         if (pset.sversion >= 110000)
                               3644                 :              0 :             COMPLETE_WITH("EXECUTE FUNCTION");
                               3645                 :                :         else
                               3646                 :              0 :             COMPLETE_WITH("EXECUTE PROCEDURE");
                               3647                 :                :     }
 1997 michael@paquier.xyz      3648   [ -  +  -  - ]:CBC          34 :     else if (HeadMatches("CREATE", "EVENT", "TRIGGER") &&
 1997 michael@paquier.xyz      3649                 :UBC           0 :              TailMatches("EXECUTE", "FUNCTION|PROCEDURE"))
  805 tgl@sss.pgh.pa.us        3650                 :              0 :         COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_functions);
                               3651                 :                : 
                               3652                 :                : /* DEALLOCATE */
 2032 tgl@sss.pgh.pa.us        3653         [ -  + ]:CBC          34 :     else if (Matches("DEALLOCATE"))
  805 tgl@sss.pgh.pa.us        3654                 :UBC           0 :         COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_prepared_statements,
                               3655                 :                :                                  "ALL");
                               3656                 :                : 
                               3657                 :                : /* DECLARE */
                               3658                 :                : 
                               3659                 :                :     /*
                               3660                 :                :      * Complete DECLARE <name> with one of BINARY, ASENSITIVE, INSENSITIVE,
                               3661                 :                :      * SCROLL, NO SCROLL, and CURSOR.
                               3662                 :                :      */
 2032 tgl@sss.pgh.pa.us        3663         [ -  + ]:CBC          34 :     else if (Matches("DECLARE", MatchAny))
 1103 peter@eisentraut.org     3664                 :UBC           0 :         COMPLETE_WITH("BINARY", "ASENSITIVE", "INSENSITIVE", "SCROLL", "NO SCROLL",
                               3665                 :                :                       "CURSOR");
                               3666                 :                : 
                               3667                 :                :     /*
                               3668                 :                :      * Complete DECLARE ... <option> with other options. The PostgreSQL parser
                               3669                 :                :      * allows DECLARE options to be specified in any order. But the
                               3670                 :                :      * tab-completion follows the ordering of them that the SQL standard
                               3671                 :                :      * provides, like the syntax of DECLARE command in the documentation
                               3672                 :                :      * indicates.
                               3673                 :                :      */
 1186 fujii@postgresql.org     3674   [ -  +  -  - ]:CBC          34 :     else if (HeadMatches("DECLARE") && TailMatches("BINARY"))
  978 michael@paquier.xyz      3675                 :UBC           0 :         COMPLETE_WITH("ASENSITIVE", "INSENSITIVE", "SCROLL", "NO SCROLL", "CURSOR");
  978 michael@paquier.xyz      3676   [ -  +  -  - ]:CBC          34 :     else if (HeadMatches("DECLARE") && TailMatches("ASENSITIVE|INSENSITIVE"))
 1186 fujii@postgresql.org     3677                 :UBC           0 :         COMPLETE_WITH("SCROLL", "NO SCROLL", "CURSOR");
 1186 fujii@postgresql.org     3678   [ -  +  -  - ]:CBC          34 :     else if (HeadMatches("DECLARE") && TailMatches("SCROLL"))
 1186 fujii@postgresql.org     3679                 :UBC           0 :         COMPLETE_WITH("CURSOR");
                               3680                 :                :     /* Complete DECLARE ... [options] NO with SCROLL */
 1186 fujii@postgresql.org     3681   [ -  +  -  - ]:CBC          34 :     else if (HeadMatches("DECLARE") && TailMatches("NO"))
 1186 fujii@postgresql.org     3682                 :UBC           0 :         COMPLETE_WITH("SCROLL");
                               3683                 :                : 
                               3684                 :                :     /*
                               3685                 :                :      * Complete DECLARE ... CURSOR with one of WITH HOLD, WITHOUT HOLD, and
                               3686                 :                :      * FOR
                               3687                 :                :      */
 2032 tgl@sss.pgh.pa.us        3688   [ -  +  -  - ]:CBC          34 :     else if (HeadMatches("DECLARE") && TailMatches("CURSOR"))
 2032 tgl@sss.pgh.pa.us        3689                 :UBC           0 :         COMPLETE_WITH("WITH HOLD", "WITHOUT HOLD", "FOR");
                               3690                 :                :     /* Complete DECLARE ... CURSOR WITH|WITHOUT with HOLD */
 1186 fujii@postgresql.org     3691   [ -  +  -  - ]:CBC          34 :     else if (HeadMatches("DECLARE") && TailMatches("CURSOR", "WITH|WITHOUT"))
 1186 fujii@postgresql.org     3692                 :UBC           0 :         COMPLETE_WITH("HOLD");
                               3693                 :                :     /* Complete DECLARE ... CURSOR WITH|WITHOUT HOLD with FOR */
 1186 fujii@postgresql.org     3694   [ -  +  -  - ]:CBC          34 :     else if (HeadMatches("DECLARE") && TailMatches("CURSOR", "WITH|WITHOUT", "HOLD"))
 1186 fujii@postgresql.org     3695                 :UBC           0 :         COMPLETE_WITH("FOR");
                               3696                 :                : 
                               3697                 :                : /* DELETE --- can be inside EXPLAIN, RULE, etc */
                               3698                 :                :     /* Complete DELETE with "FROM" */
 2032 tgl@sss.pgh.pa.us        3699         [ -  + ]:CBC          34 :     else if (Matches("DELETE"))
 2032 tgl@sss.pgh.pa.us        3700                 :UBC           0 :         COMPLETE_WITH("FROM");
                               3701                 :                :     /* Complete DELETE FROM with a list of tables */
 2032 tgl@sss.pgh.pa.us        3702         [ -  + ]:CBC          34 :     else if (TailMatches("DELETE", "FROM"))
  805 tgl@sss.pgh.pa.us        3703                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables);
                               3704                 :                :     /* Complete DELETE FROM <table> */
 2032 tgl@sss.pgh.pa.us        3705         [ -  + ]:CBC          34 :     else if (TailMatches("DELETE", "FROM", MatchAny))
 2032 tgl@sss.pgh.pa.us        3706                 :UBC           0 :         COMPLETE_WITH("USING", "WHERE");
                               3707                 :                :     /* XXX: implement tab completion for DELETE ... USING */
                               3708                 :                : 
                               3709                 :                : /* DISCARD */
 2032 tgl@sss.pgh.pa.us        3710         [ -  + ]:CBC          34 :     else if (Matches("DISCARD"))
 2032 tgl@sss.pgh.pa.us        3711                 :UBC           0 :         COMPLETE_WITH("ALL", "PLANS", "SEQUENCES", "TEMP");
                               3712                 :                : 
                               3713                 :                : /* DO */
 2032 tgl@sss.pgh.pa.us        3714         [ -  + ]:CBC          34 :     else if (Matches("DO"))
 2032 tgl@sss.pgh.pa.us        3715                 :UBC           0 :         COMPLETE_WITH("LANGUAGE");
                               3716                 :                : 
                               3717                 :                : /* DROP */
                               3718                 :                :     /* Complete DROP object with CASCADE / RESTRICT */
 2032 tgl@sss.pgh.pa.us        3719         [ +  + ]:CBC          34 :     else if (Matches("DROP",
                               3720                 :                :                      "COLLATION|CONVERSION|DOMAIN|EXTENSION|LANGUAGE|PUBLICATION|SCHEMA|SEQUENCE|SERVER|SUBSCRIPTION|STATISTICS|TABLE|TYPE|VIEW",
                               3721         [ +  - ]:             33 :                      MatchAny) ||
                               3722         [ -  + ]:             66 :              Matches("DROP", "ACCESS", "METHOD", MatchAny) ||
                               3723         [ -  - ]:             33 :              (Matches("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny) &&
 3023                          3724         [ +  - ]:             33 :               ends_with(prev_wd, ')')) ||
 2032                          3725         [ +  - ]:             66 :              Matches("DROP", "EVENT", "TRIGGER", MatchAny) ||
                               3726         [ +  - ]:             66 :              Matches("DROP", "FOREIGN", "DATA", "WRAPPER", MatchAny) ||
                               3727         [ -  + ]:             66 :              Matches("DROP", "FOREIGN", "TABLE", MatchAny) ||
                               3728                 :             33 :              Matches("DROP", "TEXT", "SEARCH", "CONFIGURATION|DICTIONARY|PARSER|TEMPLATE", MatchAny))
                               3729                 :              1 :         COMPLETE_WITH("CASCADE", "RESTRICT");
                               3730                 :                : 
                               3731                 :                :     /* help completing some of the variants */
                               3732         [ -  + ]:             33 :     else if (Matches("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny))
 2032 tgl@sss.pgh.pa.us        3733                 :UBC           0 :         COMPLETE_WITH("(");
 2032 tgl@sss.pgh.pa.us        3734         [ -  + ]:CBC          33 :     else if (Matches("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny, "("))
 3039 tgl@sss.pgh.pa.us        3735                 :UBC           0 :         COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
 2032 tgl@sss.pgh.pa.us        3736         [ -  + ]:CBC          33 :     else if (Matches("DROP", "FOREIGN"))
 2032 tgl@sss.pgh.pa.us        3737                 :UBC           0 :         COMPLETE_WITH("DATA WRAPPER", "TABLE");
 1615 akapila@postgresql.o     3738         [ -  + ]:CBC          33 :     else if (Matches("DROP", "DATABASE", MatchAny))
 1615 akapila@postgresql.o     3739                 :UBC           0 :         COMPLETE_WITH("WITH (");
 1615 akapila@postgresql.o     3740   [ -  +  -  - ]:CBC          33 :     else if (HeadMatches("DROP", "DATABASE") && (ends_with(prev_wd, '(')))
 1615 akapila@postgresql.o     3741                 :UBC           0 :         COMPLETE_WITH("FORCE");
                               3742                 :                : 
                               3743                 :                :     /* DROP INDEX */
 2032 tgl@sss.pgh.pa.us        3744         [ -  + ]:CBC          33 :     else if (Matches("DROP", "INDEX"))
  805 tgl@sss.pgh.pa.us        3745                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_indexes,
                               3746                 :                :                                         "CONCURRENTLY");
 2032 tgl@sss.pgh.pa.us        3747         [ -  + ]:CBC          33 :     else if (Matches("DROP", "INDEX", "CONCURRENTLY"))
  805 tgl@sss.pgh.pa.us        3748                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes);
 2032 tgl@sss.pgh.pa.us        3749         [ -  + ]:CBC          33 :     else if (Matches("DROP", "INDEX", MatchAny))
 2032 tgl@sss.pgh.pa.us        3750                 :UBC           0 :         COMPLETE_WITH("CASCADE", "RESTRICT");
 2032 tgl@sss.pgh.pa.us        3751         [ -  + ]:CBC          33 :     else if (Matches("DROP", "INDEX", "CONCURRENTLY", MatchAny))
 2032 tgl@sss.pgh.pa.us        3752                 :UBC           0 :         COMPLETE_WITH("CASCADE", "RESTRICT");
                               3753                 :                : 
                               3754                 :                :     /* DROP MATERIALIZED VIEW */
 2032 tgl@sss.pgh.pa.us        3755         [ -  + ]:CBC          33 :     else if (Matches("DROP", "MATERIALIZED"))
 2032 tgl@sss.pgh.pa.us        3756                 :UBC           0 :         COMPLETE_WITH("VIEW");
 2032 tgl@sss.pgh.pa.us        3757         [ -  + ]:CBC          33 :     else if (Matches("DROP", "MATERIALIZED", "VIEW"))
  805 tgl@sss.pgh.pa.us        3758                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews);
  865 michael@paquier.xyz      3759         [ -  + ]:CBC          33 :     else if (Matches("DROP", "MATERIALIZED", "VIEW", MatchAny))
  865 michael@paquier.xyz      3760                 :UBC           0 :         COMPLETE_WITH("CASCADE", "RESTRICT");
                               3761                 :                : 
                               3762                 :                :     /* DROP OWNED BY */
 2032 tgl@sss.pgh.pa.us        3763         [ -  + ]:CBC          33 :     else if (Matches("DROP", "OWNED"))
 2032 tgl@sss.pgh.pa.us        3764                 :UBC           0 :         COMPLETE_WITH("BY");
 2032 tgl@sss.pgh.pa.us        3765         [ -  + ]:CBC          33 :     else if (Matches("DROP", "OWNED", "BY"))
 6587 alvherre@alvh.no-ip.     3766                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_roles);
  865 michael@paquier.xyz      3767         [ -  + ]:CBC          33 :     else if (Matches("DROP", "OWNED", "BY", MatchAny))
  865 michael@paquier.xyz      3768                 :UBC           0 :         COMPLETE_WITH("CASCADE", "RESTRICT");
                               3769                 :                : 
                               3770                 :                :     /* DROP TEXT SEARCH */
 2032 tgl@sss.pgh.pa.us        3771         [ -  + ]:CBC          33 :     else if (Matches("DROP", "TEXT", "SEARCH"))
 2032 tgl@sss.pgh.pa.us        3772                 :UBC           0 :         COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
                               3773                 :                : 
                               3774                 :                :     /* DROP TRIGGER */
 2032 tgl@sss.pgh.pa.us        3775         [ -  + ]:CBC          33 :     else if (Matches("DROP", "TRIGGER", MatchAny))
 2032 tgl@sss.pgh.pa.us        3776                 :UBC           0 :         COMPLETE_WITH("ON");
 2032 tgl@sss.pgh.pa.us        3777         [ -  + ]:CBC          33 :     else if (Matches("DROP", "TRIGGER", MatchAny, "ON"))
                               3778                 :                :     {
  805 tgl@sss.pgh.pa.us        3779                 :UBC           0 :         set_completion_reference(prev2_wd);
                               3780                 :              0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables_for_trigger);
                               3781                 :                :     }
 2032 tgl@sss.pgh.pa.us        3782         [ -  + ]:CBC          33 :     else if (Matches("DROP", "TRIGGER", MatchAny, "ON", MatchAny))
 2032 tgl@sss.pgh.pa.us        3783                 :UBC           0 :         COMPLETE_WITH("CASCADE", "RESTRICT");
                               3784                 :                : 
                               3785                 :                :     /* DROP ACCESS METHOD */
 2032 tgl@sss.pgh.pa.us        3786         [ -  + ]:CBC          33 :     else if (Matches("DROP", "ACCESS"))
 2032 tgl@sss.pgh.pa.us        3787                 :UBC           0 :         COMPLETE_WITH("METHOD");
 2032 tgl@sss.pgh.pa.us        3788         [ -  + ]:CBC          33 :     else if (Matches("DROP", "ACCESS", "METHOD"))
 2868 alvherre@alvh.no-ip.     3789                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
                               3790                 :                : 
                               3791                 :                :     /* DROP EVENT TRIGGER */
 2032 tgl@sss.pgh.pa.us        3792         [ -  + ]:CBC          33 :     else if (Matches("DROP", "EVENT"))
 2032 tgl@sss.pgh.pa.us        3793                 :UBC           0 :         COMPLETE_WITH("TRIGGER");
 2032 tgl@sss.pgh.pa.us        3794         [ -  + ]:CBC          33 :     else if (Matches("DROP", "EVENT", "TRIGGER"))
 3653 rhaas@postgresql.org     3795                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
                               3796                 :                : 
                               3797                 :                :     /* DROP POLICY <name>  */
 2032 tgl@sss.pgh.pa.us        3798         [ -  + ]:CBC          33 :     else if (Matches("DROP", "POLICY"))
 3191 alvherre@alvh.no-ip.     3799                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_policies);
                               3800                 :                :     /* DROP POLICY <name> ON */
 2032 tgl@sss.pgh.pa.us        3801         [ -  + ]:CBC          33 :     else if (Matches("DROP", "POLICY", MatchAny))
 2032 tgl@sss.pgh.pa.us        3802                 :UBC           0 :         COMPLETE_WITH("ON");
                               3803                 :                :     /* DROP POLICY <name> ON <table> */
 2032 tgl@sss.pgh.pa.us        3804         [ -  + ]:CBC          33 :     else if (Matches("DROP", "POLICY", MatchAny, "ON"))
                               3805                 :                :     {
  805 tgl@sss.pgh.pa.us        3806                 :UBC           0 :         set_completion_reference(prev2_wd);
                               3807                 :              0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables_for_policy);
                               3808                 :                :     }
  865 michael@paquier.xyz      3809         [ -  + ]:CBC          33 :     else if (Matches("DROP", "POLICY", MatchAny, "ON", MatchAny))
  865 michael@paquier.xyz      3810                 :UBC           0 :         COMPLETE_WITH("CASCADE", "RESTRICT");
                               3811                 :                : 
                               3812                 :                :     /* DROP RULE */
 2032 tgl@sss.pgh.pa.us        3813         [ -  + ]:CBC          33 :     else if (Matches("DROP", "RULE", MatchAny))
 2032 tgl@sss.pgh.pa.us        3814                 :UBC           0 :         COMPLETE_WITH("ON");
 2032 tgl@sss.pgh.pa.us        3815         [ -  + ]:CBC          33 :     else if (Matches("DROP", "RULE", MatchAny, "ON"))
                               3816                 :                :     {
  805 tgl@sss.pgh.pa.us        3817                 :UBC           0 :         set_completion_reference(prev2_wd);
                               3818                 :              0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables_for_rule);
                               3819                 :                :     }
 2032 tgl@sss.pgh.pa.us        3820         [ -  + ]:CBC          33 :     else if (Matches("DROP", "RULE", MatchAny, "ON", MatchAny))
 2032 tgl@sss.pgh.pa.us        3821                 :UBC           0 :         COMPLETE_WITH("CASCADE", "RESTRICT");
                               3822                 :                : 
                               3823                 :                :     /* DROP TRANSFORM */
  865 michael@paquier.xyz      3824         [ -  + ]:CBC          33 :     else if (Matches("DROP", "TRANSFORM"))
  865 michael@paquier.xyz      3825                 :UBC           0 :         COMPLETE_WITH("FOR");
  865 michael@paquier.xyz      3826         [ -  + ]:CBC          33 :     else if (Matches("DROP", "TRANSFORM", "FOR"))
  805 tgl@sss.pgh.pa.us        3827                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
  865 michael@paquier.xyz      3828         [ -  + ]:CBC          33 :     else if (Matches("DROP", "TRANSFORM", "FOR", MatchAny))
  865 michael@paquier.xyz      3829                 :UBC           0 :         COMPLETE_WITH("LANGUAGE");
  865 michael@paquier.xyz      3830         [ -  + ]:CBC          33 :     else if (Matches("DROP", "TRANSFORM", "FOR", MatchAny, "LANGUAGE"))
                               3831                 :                :     {
  805 tgl@sss.pgh.pa.us        3832                 :UBC           0 :         set_completion_reference(prev2_wd);
  865 michael@paquier.xyz      3833                 :              0 :         COMPLETE_WITH_QUERY(Query_for_list_of_languages);
                               3834                 :                :     }
  865 michael@paquier.xyz      3835         [ -  + ]:CBC          33 :     else if (Matches("DROP", "TRANSFORM", "FOR", MatchAny, "LANGUAGE", MatchAny))
  865 michael@paquier.xyz      3836                 :UBC           0 :         COMPLETE_WITH("CASCADE", "RESTRICT");
                               3837                 :                : 
                               3838                 :                : /* EXECUTE */
 2032 tgl@sss.pgh.pa.us        3839         [ -  + ]:CBC          33 :     else if (Matches("EXECUTE"))
 4557 tgl@sss.pgh.pa.us        3840                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_prepared_statements);
                               3841                 :                : 
                               3842                 :                : /*
                               3843                 :                :  * EXPLAIN [ ( option [, ...] ) ] statement
                               3844                 :                :  * EXPLAIN [ ANALYZE ] [ VERBOSE ] statement
                               3845                 :                :  */
 2032 tgl@sss.pgh.pa.us        3846         [ -  + ]:CBC          33 :     else if (Matches("EXPLAIN"))
 1067 michael@paquier.xyz      3847                 :UBC           0 :         COMPLETE_WITH("SELECT", "INSERT INTO", "DELETE FROM", "UPDATE", "DECLARE",
                               3848                 :                :                       "MERGE INTO", "EXECUTE", "ANALYZE", "VERBOSE");
 2032 tgl@sss.pgh.pa.us        3849         [ -  + ]:CBC          33 :     else if (HeadMatches("EXPLAIN", "(*") &&
 2032 tgl@sss.pgh.pa.us        3850         [ #  # ]:UBC           0 :              !HeadMatches("EXPLAIN", "(*)"))
                               3851                 :                :     {
                               3852                 :                :         /*
                               3853                 :                :          * This fires if we're in an unfinished parenthesized option list.
                               3854                 :                :          * get_previous_words treats a completed parenthesized option list as
                               3855                 :                :          * one word, so the above test is correct.
                               3856                 :                :          */
                               3857   [ #  #  #  # ]:              0 :         if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
  387                          3858                 :              0 :             COMPLETE_WITH("ANALYZE", "VERBOSE", "COSTS", "SETTINGS", "GENERIC_PLAN",
                               3859                 :                :                           "BUFFERS", "WAL", "TIMING", "SUMMARY", "FORMAT");
                               3860         [ #  # ]:              0 :         else if (TailMatches("ANALYZE|VERBOSE|COSTS|SETTINGS|GENERIC_PLAN|BUFFERS|WAL|TIMING|SUMMARY"))
 2032                          3861                 :              0 :             COMPLETE_WITH("ON", "OFF");
                               3862         [ #  # ]:              0 :         else if (TailMatches("FORMAT"))
                               3863                 :              0 :             COMPLETE_WITH("TEXT", "XML", "JSON", "YAML");
                               3864                 :                :     }
 2032 tgl@sss.pgh.pa.us        3865         [ -  + ]:CBC          33 :     else if (Matches("EXPLAIN", "ANALYZE"))
 1067 michael@paquier.xyz      3866                 :UBC           0 :         COMPLETE_WITH("SELECT", "INSERT INTO", "DELETE FROM", "UPDATE", "DECLARE",
                               3867                 :                :                       "MERGE INTO", "EXECUTE", "VERBOSE");
 2032 tgl@sss.pgh.pa.us        3868   [ +  -  +  - ]:CBC          66 :     else if (Matches("EXPLAIN", "(*)") ||
                               3869         [ -  + ]:             66 :              Matches("EXPLAIN", "VERBOSE") ||
                               3870                 :             33 :              Matches("EXPLAIN", "ANALYZE", "VERBOSE"))
  963 michael@paquier.xyz      3871                 :UBC           0 :         COMPLETE_WITH("SELECT", "INSERT INTO", "DELETE FROM", "UPDATE", "DECLARE",
                               3872                 :                :                       "MERGE INTO", "EXECUTE");
                               3873                 :                : 
                               3874                 :                : /* FETCH && MOVE */
                               3875                 :                : 
                               3876                 :                :     /*
                               3877                 :                :      * Complete FETCH with one of ABSOLUTE, BACKWARD, FORWARD, RELATIVE, ALL,
                               3878                 :                :      * NEXT, PRIOR, FIRST, LAST, FROM, IN, and a list of cursors
                               3879                 :                :      */
 2032 tgl@sss.pgh.pa.us        3880         [ -  + ]:CBC          33 :     else if (Matches("FETCH|MOVE"))
  805 tgl@sss.pgh.pa.us        3881                 :UBC           0 :         COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_cursors,
                               3882                 :                :                                  "ABSOLUTE",
                               3883                 :                :                                  "BACKWARD",
                               3884                 :                :                                  "FORWARD",
                               3885                 :                :                                  "RELATIVE",
                               3886                 :                :                                  "ALL",
                               3887                 :                :                                  "NEXT",
                               3888                 :                :                                  "PRIOR",
                               3889                 :                :                                  "FIRST",
                               3890                 :                :                                  "LAST",
                               3891                 :                :                                  "FROM",
                               3892                 :                :                                  "IN");
                               3893                 :                : 
                               3894                 :                :     /*
                               3895                 :                :      * Complete FETCH BACKWARD or FORWARD with one of ALL, FROM, IN, and a
                               3896                 :                :      * list of cursors
                               3897                 :                :      */
 1277 fujii@postgresql.org     3898         [ -  + ]:CBC          33 :     else if (Matches("FETCH|MOVE", "BACKWARD|FORWARD"))
  805 tgl@sss.pgh.pa.us        3899                 :UBC           0 :         COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_cursors,
                               3900                 :                :                                  "ALL",
                               3901                 :                :                                  "FROM",
                               3902                 :                :                                  "IN");
                               3903                 :                : 
                               3904                 :                :     /*
                               3905                 :                :      * Complete FETCH <direction> with "FROM" or "IN". These are equivalent,
                               3906                 :                :      * but we may as well tab-complete both: perhaps some users prefer one
                               3907                 :                :      * variant or the other.
                               3908                 :                :      */
 1277 fujii@postgresql.org     3909         [ +  - ]:CBC          33 :     else if (Matches("FETCH|MOVE", "ABSOLUTE|BACKWARD|FORWARD|RELATIVE",
                               3910         [ -  + ]:             33 :                      MatchAnyExcept("FROM|IN")) ||
                               3911                 :             33 :              Matches("FETCH|MOVE", "ALL|NEXT|PRIOR|FIRST|LAST"))
  805 tgl@sss.pgh.pa.us        3912                 :UBC           0 :         COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_cursors,
                               3913                 :                :                                  "FROM",
                               3914                 :                :                                  "IN");
                               3915                 :                :     /* Complete FETCH <direction> "FROM" or "IN" with a list of cursors */
 1186 fujii@postgresql.org     3916   [ -  +  -  - ]:CBC          33 :     else if (HeadMatches("FETCH|MOVE") &&
 1186 fujii@postgresql.org     3917                 :UBC           0 :              TailMatches("FROM|IN"))
                               3918                 :              0 :         COMPLETE_WITH_QUERY(Query_for_list_of_cursors);
                               3919                 :                : 
                               3920                 :                : /* FOREIGN DATA WRAPPER */
                               3921                 :                :     /* applies in ALTER/DROP FDW and in CREATE SERVER */
 2032 tgl@sss.pgh.pa.us        3922         [ -  + ]:CBC          33 :     else if (TailMatches("FOREIGN", "DATA", "WRAPPER") &&
 2032 tgl@sss.pgh.pa.us        3923         [ #  # ]:UBC           0 :              !TailMatches("CREATE", MatchAny, MatchAny, MatchAny))
 5595 peter_e@gmx.net          3924                 :              0 :         COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
                               3925                 :                :     /* applies in CREATE SERVER */
 2032 tgl@sss.pgh.pa.us        3926   [ -  +  -  - ]:CBC          33 :     else if (TailMatches("FOREIGN", "DATA", "WRAPPER", MatchAny) &&
 2032 tgl@sss.pgh.pa.us        3927                 :UBC           0 :              HeadMatches("CREATE", "SERVER"))
                               3928                 :              0 :         COMPLETE_WITH("OPTIONS");
                               3929                 :                : 
                               3930                 :                : /* FOREIGN TABLE */
 2032 tgl@sss.pgh.pa.us        3931         [ -  + ]:CBC          33 :     else if (TailMatches("FOREIGN", "TABLE") &&
 2032 tgl@sss.pgh.pa.us        3932         [ #  # ]:UBC           0 :              !TailMatches("CREATE", MatchAny, MatchAny))
  805                          3933                 :              0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables);
                               3934                 :                : 
                               3935                 :                : /* FOREIGN SERVER */
 2032 tgl@sss.pgh.pa.us        3936         [ -  + ]:CBC          33 :     else if (TailMatches("FOREIGN", "SERVER"))
 3140 fujii@postgresql.org     3937                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_servers);
                               3938                 :                : 
                               3939                 :                : /*
                               3940                 :                :  * GRANT and REVOKE are allowed inside CREATE SCHEMA and
                               3941                 :                :  * ALTER DEFAULT PRIVILEGES, so use TailMatches
                               3942                 :                :  */
                               3943                 :                :     /* Complete GRANT/REVOKE with a list of roles and privileges */
  739 tgl@sss.pgh.pa.us        3944   [ +  -  -  + ]:CBC          66 :     else if (TailMatches("GRANT|REVOKE") ||
  489 michael@paquier.xyz      3945                 :             33 :              TailMatches("REVOKE", "ADMIN|GRANT|INHERIT|SET", "OPTION", "FOR"))
                               3946                 :                :     {
                               3947                 :                :         /*
                               3948                 :                :          * With ALTER DEFAULT PRIVILEGES, restrict completion to grantable
                               3949                 :                :          * privileges (can't grant roles)
                               3950                 :                :          */
 2032 tgl@sss.pgh.pa.us        3951         [ #  # ]:UBC           0 :         if (HeadMatches("ALTER", "DEFAULT", "PRIVILEGES"))
                               3952                 :                :         {
    6 msawada@postgresql.o     3953   [ #  #  #  # ]:UNC           0 :             if (TailMatches("GRANT") ||
                               3954                 :              0 :                 TailMatches("REVOKE", "GRANT", "OPTION", "FOR"))
                               3955                 :              0 :                 COMPLETE_WITH("SELECT", "INSERT", "UPDATE",
                               3956                 :                :                               "DELETE", "TRUNCATE", "REFERENCES", "TRIGGER",
                               3957                 :                :                               "CREATE", "EXECUTE", "USAGE", "MAINTAIN", "ALL");
                               3958         [ #  # ]:              0 :             else if (TailMatches("REVOKE"))
                               3959                 :              0 :                 COMPLETE_WITH("SELECT", "INSERT", "UPDATE",
                               3960                 :                :                               "DELETE", "TRUNCATE", "REFERENCES", "TRIGGER",
                               3961                 :                :                               "CREATE", "EXECUTE", "USAGE", "MAINTAIN", "ALL",
                               3962                 :                :                               "GRANT OPTION FOR");
                               3963                 :                :         }
  513 michael@paquier.xyz      3964         [ #  # ]:UBC           0 :         else if (TailMatches("GRANT"))
  805 tgl@sss.pgh.pa.us        3965                 :              0 :             COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
                               3966                 :                :                                      Privilege_options_of_grant_and_revoke);
  513 michael@paquier.xyz      3967         [ #  # ]:              0 :         else if (TailMatches("REVOKE"))
                               3968                 :              0 :             COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
                               3969                 :                :                                      Privilege_options_of_grant_and_revoke,
                               3970                 :                :                                      "GRANT OPTION FOR",
                               3971                 :                :                                      "ADMIN OPTION FOR",
                               3972                 :                :                                      "INHERIT OPTION FOR",
                               3973                 :                :                                      "SET OPTION FOR");
                               3974         [ #  # ]:              0 :         else if (TailMatches("REVOKE", "GRANT", "OPTION", "FOR"))
                               3975                 :              0 :             COMPLETE_WITH(Privilege_options_of_grant_and_revoke);
  489                          3976         [ #  # ]:              0 :         else if (TailMatches("REVOKE", "ADMIN|INHERIT|SET", "OPTION", "FOR"))
  513                          3977                 :              0 :             COMPLETE_WITH_QUERY(Query_for_list_of_roles);
                               3978                 :                :     }
                               3979                 :                : 
  739 tgl@sss.pgh.pa.us        3980   [ +  -  -  + ]:CBC          66 :     else if (TailMatches("GRANT|REVOKE", "ALTER") ||
                               3981                 :             33 :              TailMatches("REVOKE", "GRANT", "OPTION", "FOR", "ALTER"))
  739 tgl@sss.pgh.pa.us        3982                 :UBC           0 :         COMPLETE_WITH("SYSTEM");
                               3983                 :                : 
  489 michael@paquier.xyz      3984         [ -  + ]:CBC          33 :     else if (TailMatches("REVOKE", "SET"))
  489 michael@paquier.xyz      3985                 :UBC           0 :         COMPLETE_WITH("ON PARAMETER", "OPTION FOR");
  489 michael@paquier.xyz      3986   [ +  -  +  - ]:CBC          66 :     else if (TailMatches("GRANT", "SET") ||
  739 tgl@sss.pgh.pa.us        3987         [ +  - ]:             66 :              TailMatches("REVOKE", "GRANT", "OPTION", "FOR", "SET") ||
                               3988         [ -  + ]:             66 :              TailMatches("GRANT|REVOKE", "ALTER", "SYSTEM") ||
                               3989                 :             33 :              TailMatches("REVOKE", "GRANT", "OPTION", "FOR", "ALTER", "SYSTEM"))
  739 tgl@sss.pgh.pa.us        3990                 :UBC           0 :         COMPLETE_WITH("ON PARAMETER");
                               3991                 :                : 
  739 tgl@sss.pgh.pa.us        3992   [ +  -  +  - ]:CBC          66 :     else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "PARAMETER") ||
                               3993         [ +  - ]:             66 :              TailMatches("GRANT|REVOKE", MatchAny, MatchAny, "ON", "PARAMETER") ||
                               3994         [ -  + ]:             66 :              TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "PARAMETER") ||
                               3995                 :             33 :              TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, MatchAny, "ON", "PARAMETER"))
  738 tgl@sss.pgh.pa.us        3996                 :UBC           0 :         COMPLETE_WITH_QUERY_VERBATIM(Query_for_list_of_alter_system_set_vars);
                               3997                 :                : 
  739 tgl@sss.pgh.pa.us        3998   [ +  -  -  + ]:CBC          66 :     else if (TailMatches("GRANT", MatchAny, "ON", "PARAMETER", MatchAny) ||
                               3999                 :             33 :              TailMatches("GRANT", MatchAny, MatchAny, "ON", "PARAMETER", MatchAny))
  739 tgl@sss.pgh.pa.us        4000                 :UBC           0 :         COMPLETE_WITH("TO");
                               4001                 :                : 
  739 tgl@sss.pgh.pa.us        4002   [ +  -  +  - ]:CBC          66 :     else if (TailMatches("REVOKE", MatchAny, "ON", "PARAMETER", MatchAny) ||
                               4003         [ +  - ]:             66 :              TailMatches("REVOKE", MatchAny, MatchAny, "ON", "PARAMETER", MatchAny) ||
                               4004         [ -  + ]:             66 :              TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "PARAMETER", MatchAny) ||
                               4005                 :             33 :              TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, MatchAny, "ON", "PARAMETER", MatchAny))
  739 tgl@sss.pgh.pa.us        4006                 :UBC           0 :         COMPLETE_WITH("FROM");
                               4007                 :                : 
                               4008                 :                :     /*
                               4009                 :                :      * Complete GRANT/REVOKE <privilege> with "ON", GRANT/REVOKE <role> with
                               4010                 :                :      * TO/FROM
                               4011                 :                :      */
  739 tgl@sss.pgh.pa.us        4012   [ +  -  -  + ]:CBC          66 :     else if (TailMatches("GRANT|REVOKE", MatchAny) ||
                               4013                 :             33 :              TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny))
                               4014                 :                :     {
   32 nathan@postgresql.or     4015         [ #  # ]:UNC           0 :         if (TailMatches("SELECT|INSERT|UPDATE|DELETE|TRUNCATE|REFERENCES|TRIGGER|CREATE|CONNECT|TEMPORARY|TEMP|EXECUTE|USAGE|MAINTAIN|ALL"))
 2032 tgl@sss.pgh.pa.us        4016                 :UBC           0 :             COMPLETE_WITH("ON");
                               4017         [ #  # ]:              0 :         else if (TailMatches("GRANT", MatchAny))
                               4018                 :              0 :             COMPLETE_WITH("TO");
                               4019                 :                :         else
                               4020                 :              0 :             COMPLETE_WITH("FROM");
                               4021                 :                :     }
                               4022                 :                : 
                               4023                 :                :     /*
                               4024                 :                :      * Complete GRANT/REVOKE <sth> ON with a list of appropriate relations.
                               4025                 :                :      *
                               4026                 :                :      * Note: GRANT/REVOKE can get quite complex; tab-completion as implemented
                               4027                 :                :      * here will only work if the privilege list contains exactly one
                               4028                 :                :      * privilege.
                               4029                 :                :      */
  739 tgl@sss.pgh.pa.us        4030   [ +  -  -  + ]:CBC          66 :     else if (TailMatches("GRANT|REVOKE", MatchAny, "ON") ||
                               4031                 :             33 :              TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON"))
                               4032                 :                :     {
                               4033                 :                :         /*
                               4034                 :                :          * With ALTER DEFAULT PRIVILEGES, restrict completion to the kinds of
                               4035                 :                :          * objects supported.
                               4036                 :                :          */
 2032 tgl@sss.pgh.pa.us        4037         [ #  # ]:UBC           0 :         if (HeadMatches("ALTER", "DEFAULT", "PRIVILEGES"))
                               4038                 :              0 :             COMPLETE_WITH("TABLES", "SEQUENCES", "FUNCTIONS", "PROCEDURES", "ROUTINES", "TYPES", "SCHEMAS");
                               4039                 :                :         else
  805                          4040                 :              0 :             COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_grantables,
                               4041                 :                :                                             "ALL FUNCTIONS IN SCHEMA",
                               4042                 :                :                                             "ALL PROCEDURES IN SCHEMA",
                               4043                 :                :                                             "ALL ROUTINES IN SCHEMA",
                               4044                 :                :                                             "ALL SEQUENCES IN SCHEMA",
                               4045                 :                :                                             "ALL TABLES IN SCHEMA",
                               4046                 :                :                                             "DATABASE",
                               4047                 :                :                                             "DOMAIN",
                               4048                 :                :                                             "FOREIGN DATA WRAPPER",
                               4049                 :                :                                             "FOREIGN SERVER",
                               4050                 :                :                                             "FUNCTION",
                               4051                 :                :                                             "LANGUAGE",
                               4052                 :                :                                             "LARGE OBJECT",
                               4053                 :                :                                             "PARAMETER",
                               4054                 :                :                                             "PROCEDURE",
                               4055                 :                :                                             "ROUTINE",
                               4056                 :                :                                             "SCHEMA",
                               4057                 :                :                                             "SEQUENCE",
                               4058                 :                :                                             "TABLE",
                               4059                 :                :                                             "TABLESPACE",
                               4060                 :                :                                             "TYPE");
                               4061                 :                :     }
  739 tgl@sss.pgh.pa.us        4062   [ +  -  -  + ]:CBC          66 :     else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "ALL") ||
                               4063                 :             33 :              TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "ALL"))
 2032 tgl@sss.pgh.pa.us        4064                 :UBC           0 :         COMPLETE_WITH("FUNCTIONS IN SCHEMA",
                               4065                 :                :                       "PROCEDURES IN SCHEMA",
                               4066                 :                :                       "ROUTINES IN SCHEMA",
                               4067                 :                :                       "SEQUENCES IN SCHEMA",
                               4068                 :                :                       "TABLES IN SCHEMA");
  739 tgl@sss.pgh.pa.us        4069   [ +  -  -  + ]:CBC          66 :     else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "FOREIGN") ||
                               4070                 :             33 :              TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "FOREIGN"))
 2032 tgl@sss.pgh.pa.us        4071                 :UBC           0 :         COMPLETE_WITH("DATA WRAPPER", "SERVER");
                               4072                 :                : 
                               4073                 :                :     /*
                               4074                 :                :      * Complete "GRANT/REVOKE * ON DATABASE/DOMAIN/..." with a list of
                               4075                 :                :      * appropriate objects.
                               4076                 :                :      *
                               4077                 :                :      * Complete "GRANT/REVOKE * ON *" with "TO/FROM".
                               4078                 :                :      */
  739 tgl@sss.pgh.pa.us        4079   [ +  -  -  + ]:CBC          66 :     else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", MatchAny) ||
                               4080                 :             33 :              TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", MatchAny))
                               4081                 :                :     {
 2032 tgl@sss.pgh.pa.us        4082         [ #  # ]:UBC           0 :         if (TailMatches("DATABASE"))
 7689 bruce@momjian.us         4083                 :              0 :             COMPLETE_WITH_QUERY(Query_for_list_of_databases);
 2032 tgl@sss.pgh.pa.us        4084         [ #  # ]:              0 :         else if (TailMatches("DOMAIN"))
  805                          4085                 :              0 :             COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains);
 2032                          4086         [ #  # ]:              0 :         else if (TailMatches("FUNCTION"))
  805                          4087                 :              0 :             COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_functions);
 2032                          4088         [ #  # ]:              0 :         else if (TailMatches("LANGUAGE"))
 7689 bruce@momjian.us         4089                 :              0 :             COMPLETE_WITH_QUERY(Query_for_list_of_languages);
 2032 tgl@sss.pgh.pa.us        4090         [ #  # ]:              0 :         else if (TailMatches("PROCEDURE"))
  805                          4091                 :              0 :             COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_procedures);
 2032                          4092         [ #  # ]:              0 :         else if (TailMatches("ROUTINE"))
  805                          4093                 :              0 :             COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_routines);
 2032                          4094         [ #  # ]:              0 :         else if (TailMatches("SCHEMA"))
 7689 bruce@momjian.us         4095                 :              0 :             COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
 2032 tgl@sss.pgh.pa.us        4096         [ #  # ]:              0 :         else if (TailMatches("SEQUENCE"))
  805                          4097                 :              0 :             COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences);
 2032                          4098         [ #  # ]:              0 :         else if (TailMatches("TABLE"))
  805                          4099                 :              0 :             COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_grantables);
 2032                          4100         [ #  # ]:              0 :         else if (TailMatches("TABLESPACE"))
 7177 bruce@momjian.us         4101                 :              0 :             COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
 2032 tgl@sss.pgh.pa.us        4102         [ #  # ]:              0 :         else if (TailMatches("TYPE"))
  805                          4103                 :              0 :             COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
 2032                          4104         [ #  # ]:              0 :         else if (TailMatches("GRANT", MatchAny, MatchAny, MatchAny))
                               4105                 :              0 :             COMPLETE_WITH("TO");
                               4106                 :                :         else
                               4107                 :              0 :             COMPLETE_WITH("FROM");
                               4108                 :                :     }
                               4109                 :                : 
                               4110                 :                :     /*
                               4111                 :                :      * Complete "GRANT/REVOKE ... TO/FROM" with username, PUBLIC,
                               4112                 :                :      * CURRENT_ROLE, CURRENT_USER, or SESSION_USER.
                               4113                 :                :      */
 2032 tgl@sss.pgh.pa.us        4114   [ -  +  -  -  :CBC          66 :     else if ((HeadMatches("GRANT") && TailMatches("TO")) ||
                                              -  + ]
                               4115         [ -  - ]:             33 :              (HeadMatches("REVOKE") && TailMatches("FROM")))
  805 tgl@sss.pgh.pa.us        4116                 :UBC           0 :         COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
                               4117                 :                :                                  Keywords_for_list_of_grant_roles);
                               4118                 :                : 
                               4119                 :                :     /*
                               4120                 :                :      * Offer grant options after that.
                               4121                 :                :      */
  739 tgl@sss.pgh.pa.us        4122   [ -  +  -  - ]:CBC          33 :     else if (HeadMatches("GRANT") && TailMatches("TO", MatchAny))
  513 michael@paquier.xyz      4123                 :UBC           0 :         COMPLETE_WITH("WITH ADMIN",
                               4124                 :                :                       "WITH INHERIT",
                               4125                 :                :                       "WITH SET",
                               4126                 :                :                       "WITH GRANT OPTION",
                               4127                 :                :                       "GRANTED BY");
  739 tgl@sss.pgh.pa.us        4128   [ -  +  -  - ]:CBC          33 :     else if (HeadMatches("GRANT") && TailMatches("TO", MatchAny, "WITH"))
  513 michael@paquier.xyz      4129                 :UBC           0 :         COMPLETE_WITH("ADMIN",
                               4130                 :                :                       "INHERIT",
                               4131                 :                :                       "SET",
                               4132                 :                :                       "GRANT OPTION");
  513 michael@paquier.xyz      4133   [ -  +  -  - ]:CBC          33 :     else if (HeadMatches("GRANT") &&
  489 michael@paquier.xyz      4134                 :UBC           0 :              (TailMatches("TO", MatchAny, "WITH", "ADMIN|INHERIT|SET")))
  513                          4135                 :              0 :         COMPLETE_WITH("OPTION", "TRUE", "FALSE");
  739 tgl@sss.pgh.pa.us        4136   [ -  +  -  - ]:CBC          33 :     else if (HeadMatches("GRANT") && TailMatches("TO", MatchAny, "WITH", MatchAny, "OPTION"))
  739 tgl@sss.pgh.pa.us        4137                 :UBC           0 :         COMPLETE_WITH("GRANTED BY");
  739 tgl@sss.pgh.pa.us        4138   [ -  +  -  - ]:CBC          33 :     else if (HeadMatches("GRANT") && TailMatches("TO", MatchAny, "WITH", MatchAny, "OPTION", "GRANTED", "BY"))
  739 tgl@sss.pgh.pa.us        4139                 :UBC           0 :         COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
                               4140                 :                :                                  Keywords_for_list_of_grant_roles);
                               4141                 :                :     /* Complete "ALTER DEFAULT PRIVILEGES ... GRANT/REVOKE ... TO/FROM */
 2032 tgl@sss.pgh.pa.us        4142   [ -  +  -  - ]:CBC          33 :     else if (HeadMatches("ALTER", "DEFAULT", "PRIVILEGES") && TailMatches("TO|FROM"))
  805 tgl@sss.pgh.pa.us        4143                 :UBC           0 :         COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
                               4144                 :                :                                  Keywords_for_list_of_grant_roles);
                               4145                 :                :     /* Offer WITH GRANT OPTION after that */
    6 msawada@postgresql.o     4146   [ -  +  -  - ]:GNC          33 :     else if (HeadMatches("ALTER", "DEFAULT", "PRIVILEGES") && TailMatches("TO", MatchAny))
    6 msawada@postgresql.o     4147                 :UNC           0 :         COMPLETE_WITH("WITH GRANT OPTION");
                               4148                 :                :     /* Complete "GRANT/REVOKE ... ON * *" with TO/FROM */
 2032 tgl@sss.pgh.pa.us        4149   [ -  +  -  - ]:CBC          33 :     else if (HeadMatches("GRANT") && TailMatches("ON", MatchAny, MatchAny))
 2032 tgl@sss.pgh.pa.us        4150                 :UBC           0 :         COMPLETE_WITH("TO");
 2032 tgl@sss.pgh.pa.us        4151   [ -  +  -  - ]:CBC          33 :     else if (HeadMatches("REVOKE") && TailMatches("ON", MatchAny, MatchAny))
 2032 tgl@sss.pgh.pa.us        4152                 :UBC           0 :         COMPLETE_WITH("FROM");
                               4153                 :                : 
                               4154                 :                :     /* Complete "GRANT/REVOKE * ON ALL * IN SCHEMA *" with TO/FROM */
  739 tgl@sss.pgh.pa.us        4155   [ +  -  -  + ]:CBC          66 :     else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "ALL", MatchAny, "IN", "SCHEMA", MatchAny) ||
                               4156                 :             33 :              TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "ALL", MatchAny, "IN", "SCHEMA", MatchAny))
                               4157                 :                :     {
 2032 tgl@sss.pgh.pa.us        4158         [ #  # ]:UBC           0 :         if (TailMatches("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
                               4159                 :              0 :             COMPLETE_WITH("TO");
                               4160                 :                :         else
                               4161                 :              0 :             COMPLETE_WITH("FROM");
                               4162                 :                :     }
                               4163                 :                : 
                               4164                 :                :     /* Complete "GRANT/REVOKE * ON FOREIGN DATA WRAPPER *" with TO/FROM */
  739 tgl@sss.pgh.pa.us        4165   [ +  -  -  + ]:CBC          66 :     else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "DATA", "WRAPPER", MatchAny) ||
                               4166                 :             33 :              TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "FOREIGN", "DATA", "WRAPPER", MatchAny))
                               4167                 :                :     {
 2032 tgl@sss.pgh.pa.us        4168         [ #  # ]:UBC           0 :         if (TailMatches("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
                               4169                 :              0 :             COMPLETE_WITH("TO");
                               4170                 :                :         else
                               4171                 :              0 :             COMPLETE_WITH("FROM");
                               4172                 :                :     }
                               4173                 :                : 
                               4174                 :                :     /* Complete "GRANT/REVOKE * ON FOREIGN SERVER *" with TO/FROM */
  739 tgl@sss.pgh.pa.us        4175   [ +  -  -  + ]:CBC          66 :     else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "SERVER", MatchAny) ||
                               4176                 :             33 :              TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "FOREIGN", "SERVER", MatchAny))
                               4177                 :                :     {
 2032 tgl@sss.pgh.pa.us        4178         [ #  # ]:UBC           0 :         if (TailMatches("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
                               4179                 :              0 :             COMPLETE_WITH("TO");
                               4180                 :                :         else
                               4181                 :              0 :             COMPLETE_WITH("FROM");
                               4182                 :                :     }
                               4183                 :                : 
                               4184                 :                : /* GROUP BY */
 2032 tgl@sss.pgh.pa.us        4185         [ -  + ]:CBC          33 :     else if (TailMatches("FROM", MatchAny, "GROUP"))
 2032 tgl@sss.pgh.pa.us        4186                 :UBC           0 :         COMPLETE_WITH("BY");
                               4187                 :                : 
                               4188                 :                : /* IMPORT FOREIGN SCHEMA */
 2032 tgl@sss.pgh.pa.us        4189         [ -  + ]:CBC          33 :     else if (Matches("IMPORT"))
 2032 tgl@sss.pgh.pa.us        4190                 :UBC           0 :         COMPLETE_WITH("FOREIGN SCHEMA");
 2032 tgl@sss.pgh.pa.us        4191         [ -  + ]:CBC          33 :     else if (Matches("IMPORT", "FOREIGN"))
 2032 tgl@sss.pgh.pa.us        4192                 :UBC           0 :         COMPLETE_WITH("SCHEMA");
 1305 michael@paquier.xyz      4193         [ -  + ]:CBC          33 :     else if (Matches("IMPORT", "FOREIGN", "SCHEMA", MatchAny))
 1305 michael@paquier.xyz      4194                 :UBC           0 :         COMPLETE_WITH("EXCEPT (", "FROM SERVER", "LIMIT TO (");
 1305 michael@paquier.xyz      4195   [ +  -  -  + ]:CBC          66 :     else if (TailMatches("LIMIT", "TO", "(*)") ||
                               4196                 :             33 :              TailMatches("EXCEPT", "(*)"))
 1305 michael@paquier.xyz      4197                 :UBC           0 :         COMPLETE_WITH("FROM SERVER");
 1305 michael@paquier.xyz      4198         [ -  + ]:CBC          33 :     else if (TailMatches("FROM", "SERVER", MatchAny))
 1305 michael@paquier.xyz      4199                 :UBC           0 :         COMPLETE_WITH("INTO");
 1305 michael@paquier.xyz      4200         [ -  + ]:CBC          33 :     else if (TailMatches("FROM", "SERVER", MatchAny, "INTO"))
 1305 michael@paquier.xyz      4201                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
 1305 michael@paquier.xyz      4202         [ -  + ]:CBC          33 :     else if (TailMatches("FROM", "SERVER", MatchAny, "INTO", MatchAny))
 1305 michael@paquier.xyz      4203                 :UBC           0 :         COMPLETE_WITH("OPTIONS (");
                               4204                 :                : 
                               4205                 :                : /* INSERT --- can be inside EXPLAIN, RULE, etc */
                               4206                 :                :     /* Complete NOT MATCHED THEN INSERT */
  748 alvherre@alvh.no-ip.     4207         [ -  + ]:CBC          33 :     else if (TailMatches("NOT", "MATCHED", "THEN", "INSERT"))
  748 alvherre@alvh.no-ip.     4208                 :UBC           0 :         COMPLETE_WITH("VALUES", "(");
                               4209                 :                :     /* Complete INSERT with "INTO" */
 2032 tgl@sss.pgh.pa.us        4210         [ -  + ]:CBC          33 :     else if (TailMatches("INSERT"))
 2032 tgl@sss.pgh.pa.us        4211                 :UBC           0 :         COMPLETE_WITH("INTO");
                               4212                 :                :     /* Complete INSERT INTO with table names */
 2032 tgl@sss.pgh.pa.us        4213         [ -  + ]:CBC          33 :     else if (TailMatches("INSERT", "INTO"))
  805 tgl@sss.pgh.pa.us        4214                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables);
                               4215                 :                :     /* Complete "INSERT INTO <table> (" with attribute names */
 2032 tgl@sss.pgh.pa.us        4216         [ -  + ]:CBC          33 :     else if (TailMatches("INSERT", "INTO", MatchAny, "("))
  805 tgl@sss.pgh.pa.us        4217                 :UBC           0 :         COMPLETE_WITH_ATTR(prev2_wd);
                               4218                 :                : 
                               4219                 :                :     /*
                               4220                 :                :      * Complete INSERT INTO <table> with "(" or "VALUES" or "SELECT" or
                               4221                 :                :      * "TABLE" or "DEFAULT VALUES" or "OVERRIDING"
                               4222                 :                :      */
 2032 tgl@sss.pgh.pa.us        4223         [ -  + ]:CBC          33 :     else if (TailMatches("INSERT", "INTO", MatchAny))
 2032 tgl@sss.pgh.pa.us        4224                 :UBC           0 :         COMPLETE_WITH("(", "DEFAULT VALUES", "SELECT", "TABLE", "VALUES", "OVERRIDING");
                               4225                 :                : 
                               4226                 :                :     /*
                               4227                 :                :      * Complete INSERT INTO <table> (attribs) with "VALUES" or "SELECT" or
                               4228                 :                :      * "TABLE" or "OVERRIDING"
                               4229                 :                :      */
 2032 tgl@sss.pgh.pa.us        4230   [ -  +  -  - ]:CBC          33 :     else if (TailMatches("INSERT", "INTO", MatchAny, MatchAny) &&
 3039 tgl@sss.pgh.pa.us        4231                 :UBC           0 :              ends_with(prev_wd, ')'))
 2032                          4232                 :              0 :         COMPLETE_WITH("SELECT", "TABLE", "VALUES", "OVERRIDING");
                               4233                 :                : 
                               4234                 :                :     /* Complete OVERRIDING */
 2032 tgl@sss.pgh.pa.us        4235         [ -  + ]:CBC          33 :     else if (TailMatches("OVERRIDING"))
 2032 tgl@sss.pgh.pa.us        4236                 :UBC           0 :         COMPLETE_WITH("SYSTEM VALUE", "USER VALUE");
                               4237                 :                : 
                               4238                 :                :     /* Complete after OVERRIDING clause */
 2032 tgl@sss.pgh.pa.us        4239         [ -  + ]:CBC          33 :     else if (TailMatches("OVERRIDING", MatchAny, "VALUE"))
 2032 tgl@sss.pgh.pa.us        4240                 :UBC           0 :         COMPLETE_WITH("SELECT", "TABLE", "VALUES");
                               4241                 :                : 
                               4242                 :                :     /* Insert an open parenthesis after "VALUES" */
 2032 tgl@sss.pgh.pa.us        4243   [ -  +  -  - ]:CBC          33 :     else if (TailMatches("VALUES") && !TailMatches("DEFAULT", "VALUES"))
 2032 tgl@sss.pgh.pa.us        4244                 :UBC           0 :         COMPLETE_WITH("(");
                               4245                 :                : 
                               4246                 :                : /* LOCK */
                               4247                 :                :     /* Complete LOCK [TABLE] [ONLY] with a list of tables */
 2032 tgl@sss.pgh.pa.us        4248         [ -  + ]:CBC          33 :     else if (Matches("LOCK"))
  805 tgl@sss.pgh.pa.us        4249                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_tables,
                               4250                 :                :                                         "TABLE", "ONLY");
 2032 tgl@sss.pgh.pa.us        4251         [ -  + ]:CBC          33 :     else if (Matches("LOCK", "TABLE"))
  805 tgl@sss.pgh.pa.us        4252                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_tables,
                               4253                 :                :                                         "ONLY");
  922 fujii@postgresql.org     4254   [ +  -  -  + ]:CBC          33 :     else if (Matches("LOCK", "TABLE", "ONLY") || Matches("LOCK", "ONLY"))
  805 tgl@sss.pgh.pa.us        4255                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
                               4256                 :                :     /* For the following, handle the case of a single table only for now */
                               4257                 :                : 
                               4258                 :                :     /* Complete LOCK [TABLE] [ONLY] <table> with IN or NOWAIT */
  922 fujii@postgresql.org     4259   [ +  -  +  - ]:CBC          66 :     else if (Matches("LOCK", MatchAnyExcept("TABLE|ONLY")) ||
                               4260         [ +  - ]:             66 :              Matches("LOCK", "TABLE", MatchAnyExcept("ONLY")) ||
                               4261         [ -  + ]:             66 :              Matches("LOCK", "ONLY", MatchAny) ||
                               4262                 :             33 :              Matches("LOCK", "TABLE", "ONLY", MatchAny))
  922 fujii@postgresql.org     4263                 :UBC           0 :         COMPLETE_WITH("IN", "NOWAIT");
                               4264                 :                : 
                               4265                 :                :     /* Complete LOCK [TABLE] [ONLY] <table> IN with a lock mode */
  922 fujii@postgresql.org     4266   [ -  +  -  - ]:CBC          33 :     else if (HeadMatches("LOCK") && TailMatches("IN"))
 2032 tgl@sss.pgh.pa.us        4267                 :UBC           0 :         COMPLETE_WITH("ACCESS SHARE MODE",
                               4268                 :                :                       "ROW SHARE MODE", "ROW EXCLUSIVE MODE",
                               4269                 :                :                       "SHARE UPDATE EXCLUSIVE MODE", "SHARE MODE",
                               4270                 :                :                       "SHARE ROW EXCLUSIVE MODE",
                               4271                 :                :                       "EXCLUSIVE MODE", "ACCESS EXCLUSIVE MODE");
                               4272                 :                : 
                               4273                 :                :     /*
                               4274                 :                :      * Complete LOCK [TABLE][ONLY] <table> IN ACCESS|ROW with rest of lock
                               4275                 :                :      * mode
                               4276                 :                :      */
  922 fujii@postgresql.org     4277   [ -  +  -  - ]:CBC          33 :     else if (HeadMatches("LOCK") && TailMatches("IN", "ACCESS|ROW"))
 2032 tgl@sss.pgh.pa.us        4278                 :UBC           0 :         COMPLETE_WITH("EXCLUSIVE MODE", "SHARE MODE");
                               4279                 :                : 
                               4280                 :                :     /* Complete LOCK [TABLE] [ONLY] <table> IN SHARE with rest of lock mode */
  922 fujii@postgresql.org     4281   [ -  +  -  - ]:CBC          33 :     else if (HeadMatches("LOCK") && TailMatches("IN", "SHARE"))
 2032 tgl@sss.pgh.pa.us        4282                 :UBC           0 :         COMPLETE_WITH("MODE", "ROW EXCLUSIVE MODE",
                               4283                 :                :                       "UPDATE EXCLUSIVE MODE");
                               4284                 :                : 
                               4285                 :                :     /* Complete LOCK [TABLE] [ONLY] <table> [IN lockmode MODE] with "NOWAIT" */
  570 fujii@postgresql.org     4286   [ -  +  -  - ]:CBC          33 :     else if (HeadMatches("LOCK") && TailMatches("MODE"))
  570 fujii@postgresql.org     4287                 :UBC           0 :         COMPLETE_WITH("NOWAIT");
                               4288                 :                : 
                               4289                 :                : /* MERGE --- can be inside EXPLAIN */
  748 alvherre@alvh.no-ip.     4290         [ -  + ]:CBC          33 :     else if (TailMatches("MERGE"))
  748 alvherre@alvh.no-ip.     4291                 :UBC           0 :         COMPLETE_WITH("INTO");
  748 alvherre@alvh.no-ip.     4292         [ -  + ]:CBC          33 :     else if (TailMatches("MERGE", "INTO"))
  748 alvherre@alvh.no-ip.     4293                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_mergetargets);
                               4294                 :                : 
                               4295                 :                :     /* Complete MERGE INTO <table> [[AS] <alias>] with USING */
  748 alvherre@alvh.no-ip.     4296         [ -  + ]:CBC          33 :     else if (TailMatches("MERGE", "INTO", MatchAny))
  748 alvherre@alvh.no-ip.     4297                 :UBC           0 :         COMPLETE_WITH("USING", "AS");
  570 fujii@postgresql.org     4298   [ +  -  -  + ]:CBC          66 :     else if (TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny) ||
                               4299                 :             33 :              TailMatches("MERGE", "INTO", MatchAny, MatchAnyExcept("USING|AS")))
  748 alvherre@alvh.no-ip.     4300                 :UBC           0 :         COMPLETE_WITH("USING");
                               4301                 :                : 
                               4302                 :                :     /*
                               4303                 :                :      * Complete MERGE INTO ... USING with a list of relations supporting
                               4304                 :                :      * SELECT
                               4305                 :                :      */
  570 fujii@postgresql.org     4306   [ +  -  +  - ]:CBC          66 :     else if (TailMatches("MERGE", "INTO", MatchAny, "USING") ||
                               4307         [ -  + ]:             66 :              TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny, "USING") ||
                               4308                 :             33 :              TailMatches("MERGE", "INTO", MatchAny, MatchAny, "USING"))
  570 fujii@postgresql.org     4309                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_selectables);
                               4310                 :                : 
                               4311                 :                :     /*
                               4312                 :                :      * Complete MERGE INTO <table> [[AS] <alias>] USING <relations> [[AS]
                               4313                 :                :      * alias] with ON
                               4314                 :                :      */
  570 fujii@postgresql.org     4315   [ +  -  +  - ]:CBC          66 :     else if (TailMatches("MERGE", "INTO", MatchAny, "USING", MatchAny) ||
                               4316         [ -  + ]:             66 :              TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny, "USING", MatchAny) ||
                               4317                 :             33 :              TailMatches("MERGE", "INTO", MatchAny, MatchAny, "USING", MatchAny))
  570 fujii@postgresql.org     4318                 :UBC           0 :         COMPLETE_WITH("AS", "ON");
  570 fujii@postgresql.org     4319   [ +  -  +  - ]:CBC          66 :     else if (TailMatches("MERGE", "INTO", MatchAny, "USING", MatchAny, "AS", MatchAny) ||
                               4320         [ +  - ]:             66 :              TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny, "USING", MatchAny, "AS", MatchAny) ||
                               4321         [ +  - ]:             66 :              TailMatches("MERGE", "INTO", MatchAny, MatchAny, "USING", MatchAny, "AS", MatchAny) ||
                               4322         [ +  - ]:             66 :              TailMatches("MERGE", "INTO", MatchAny, "USING", MatchAny, MatchAnyExcept("ON|AS")) ||
                               4323         [ -  + ]:             66 :              TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny, "USING", MatchAny, MatchAnyExcept("ON|AS")) ||
                               4324                 :             33 :              TailMatches("MERGE", "INTO", MatchAny, MatchAny, "USING", MatchAny, MatchAnyExcept("ON|AS")))
  748 alvherre@alvh.no-ip.     4325                 :UBC           0 :         COMPLETE_WITH("ON");
                               4326                 :                : 
                               4327                 :                :     /* Complete MERGE INTO ... ON with target table attributes */
  748 alvherre@alvh.no-ip.     4328         [ -  + ]:CBC          33 :     else if (TailMatches("INTO", MatchAny, "USING", MatchAny, "ON"))
  748 alvherre@alvh.no-ip.     4329                 :UBC           0 :         COMPLETE_WITH_ATTR(prev4_wd);
  748 alvherre@alvh.no-ip.     4330         [ -  + ]:CBC          33 :     else if (TailMatches("INTO", MatchAny, "AS", MatchAny, "USING", MatchAny, "AS", MatchAny, "ON"))
  748 alvherre@alvh.no-ip.     4331                 :UBC           0 :         COMPLETE_WITH_ATTR(prev8_wd);
  748 alvherre@alvh.no-ip.     4332         [ -  + ]:CBC          33 :     else if (TailMatches("INTO", MatchAny, MatchAny, "USING", MatchAny, MatchAny, "ON"))
  748 alvherre@alvh.no-ip.     4333                 :UBC           0 :         COMPLETE_WITH_ATTR(prev6_wd);
                               4334                 :                : 
                               4335                 :                :     /*
                               4336                 :                :      * Complete ... USING <relation> [[AS] alias] ON join condition
                               4337                 :                :      * (consisting of one or three words typically used) with WHEN [NOT]
                               4338                 :                :      * MATCHED
                               4339                 :                :      */
  570 fujii@postgresql.org     4340   [ +  -  +  - ]:CBC          66 :     else if (TailMatches("USING", MatchAny, "ON", MatchAny) ||
                               4341         [ +  - ]:             66 :              TailMatches("USING", MatchAny, "AS", MatchAny, "ON", MatchAny) ||
                               4342         [ +  - ]:             66 :              TailMatches("USING", MatchAny, MatchAny, "ON", MatchAny) ||
                               4343         [ +  - ]:             66 :              TailMatches("USING", MatchAny, "ON", MatchAny, MatchAnyExcept("WHEN"), MatchAnyExcept("WHEN")) ||
                               4344         [ -  + ]:             66 :              TailMatches("USING", MatchAny, "AS", MatchAny, "ON", MatchAny, MatchAnyExcept("WHEN"), MatchAnyExcept("WHEN")) ||
                               4345                 :             33 :              TailMatches("USING", MatchAny, MatchAny, "ON", MatchAny, MatchAnyExcept("WHEN"), MatchAnyExcept("WHEN")))
  748 alvherre@alvh.no-ip.     4346                 :UBC           0 :         COMPLETE_WITH("WHEN MATCHED", "WHEN NOT MATCHED");
  570 fujii@postgresql.org     4347   [ +  -  +  - ]:CBC          66 :     else if (TailMatches("USING", MatchAny, "ON", MatchAny, "WHEN") ||
                               4348         [ +  - ]:             66 :              TailMatches("USING", MatchAny, "AS", MatchAny, "ON", MatchAny, "WHEN") ||
                               4349         [ +  - ]:             66 :              TailMatches("USING", MatchAny, MatchAny, "ON", MatchAny, "WHEN") ||
                               4350         [ +  - ]:             66 :              TailMatches("USING", MatchAny, "ON", MatchAny, MatchAny, MatchAny, "WHEN") ||
                               4351         [ -  + ]:             66 :              TailMatches("USING", MatchAny, "AS", MatchAny, "ON", MatchAny, MatchAny, MatchAny, "WHEN") ||
                               4352                 :             33 :              TailMatches("USING", MatchAny, MatchAny, "ON", MatchAny, MatchAny, MatchAny, "WHEN"))
  570 fujii@postgresql.org     4353                 :UBC           0 :         COMPLETE_WITH("MATCHED", "NOT MATCHED");
                               4354                 :                : 
                               4355                 :                :     /*
                               4356                 :                :      * Complete ... WHEN MATCHED and WHEN NOT MATCHED BY SOURCE|TARGET with
                               4357                 :                :      * THEN/AND
                               4358                 :                :      */
  570 fujii@postgresql.org     4359   [ +  -  -  + ]:CBC          66 :     else if (TailMatches("WHEN", "MATCHED") ||
   15 dean.a.rasheed@gmail     4360                 :GNC          33 :              TailMatches("WHEN", "NOT", "MATCHED", "BY", "SOURCE|TARGET"))
  748 alvherre@alvh.no-ip.     4361                 :UBC           0 :         COMPLETE_WITH("THEN", "AND");
                               4362                 :                : 
                               4363                 :                :     /* Complete ... WHEN NOT MATCHED with BY/THEN/AND */
   15 dean.a.rasheed@gmail     4364         [ -  + ]:GNC          33 :     else if (TailMatches("WHEN", "NOT", "MATCHED"))
   15 dean.a.rasheed@gmail     4365                 :UNC           0 :         COMPLETE_WITH("BY", "THEN", "AND");
                               4366                 :                : 
                               4367                 :                :     /* Complete ... WHEN NOT MATCHED BY with SOURCE/TARGET */
   15 dean.a.rasheed@gmail     4368         [ -  + ]:GNC          33 :     else if (TailMatches("WHEN", "NOT", "MATCHED", "BY"))
   15 dean.a.rasheed@gmail     4369                 :UNC           0 :         COMPLETE_WITH("SOURCE", "TARGET");
                               4370                 :                : 
                               4371                 :                :     /*
                               4372                 :                :      * Complete ... WHEN MATCHED THEN and WHEN NOT MATCHED BY SOURCE THEN with
                               4373                 :                :      * UPDATE SET/DELETE/DO NOTHING
                               4374                 :                :      */
   15 dean.a.rasheed@gmail     4375   [ +  -  -  + ]:GNC          66 :     else if (TailMatches("WHEN", "MATCHED", "THEN") ||
                               4376                 :             33 :              TailMatches("WHEN", "NOT", "MATCHED", "BY", "SOURCE", "THEN"))
  570 fujii@postgresql.org     4377                 :UBC           0 :         COMPLETE_WITH("UPDATE SET", "DELETE", "DO NOTHING");
                               4378                 :                : 
                               4379                 :                :     /*
                               4380                 :                :      * Complete ... WHEN NOT MATCHED [BY TARGET] THEN with INSERT/DO NOTHING
                               4381                 :                :      */
   15 dean.a.rasheed@gmail     4382   [ +  -  -  + ]:GNC          66 :     else if (TailMatches("WHEN", "NOT", "MATCHED", "THEN") ||
                               4383                 :             33 :              TailMatches("WHEN", "NOT", "MATCHED", "BY", "TARGET", "THEN"))
  748 alvherre@alvh.no-ip.     4384                 :UBC           0 :         COMPLETE_WITH("INSERT", "DO NOTHING");
                               4385                 :                : 
                               4386                 :                : /* NOTIFY --- can be inside EXPLAIN, RULE, etc */
 2032 tgl@sss.pgh.pa.us        4387         [ -  + ]:CBC          33 :     else if (TailMatches("NOTIFY"))
  805 tgl@sss.pgh.pa.us        4388                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_channels);
                               4389                 :                : 
                               4390                 :                : /* OPTIONS */
 2032 tgl@sss.pgh.pa.us        4391         [ -  + ]:CBC          33 :     else if (TailMatches("OPTIONS"))
 2032 tgl@sss.pgh.pa.us        4392                 :UBC           0 :         COMPLETE_WITH("(");
                               4393                 :                : 
                               4394                 :                : /* OWNER TO  - complete with available roles */
 2032 tgl@sss.pgh.pa.us        4395         [ -  + ]:CBC          33 :     else if (TailMatches("OWNER", "TO"))
  557 michael@paquier.xyz      4396                 :UBC           0 :         COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
                               4397                 :                :                                  Keywords_for_list_of_owner_roles);
                               4398                 :                : 
                               4399                 :                : /* ORDER BY */
 2032 tgl@sss.pgh.pa.us        4400         [ -  + ]:CBC          33 :     else if (TailMatches("FROM", MatchAny, "ORDER"))
 2032 tgl@sss.pgh.pa.us        4401                 :UBC           0 :         COMPLETE_WITH("BY");
 2032 tgl@sss.pgh.pa.us        4402         [ -  + ]:CBC          33 :     else if (TailMatches("FROM", MatchAny, "ORDER", "BY"))
  805 tgl@sss.pgh.pa.us        4403                 :UBC           0 :         COMPLETE_WITH_ATTR(prev3_wd);
                               4404                 :                : 
                               4405                 :                : /* PREPARE xx AS */
 2032 tgl@sss.pgh.pa.us        4406         [ -  + ]:CBC          33 :     else if (Matches("PREPARE", MatchAny, "AS"))
 1067 michael@paquier.xyz      4407                 :UBC           0 :         COMPLETE_WITH("SELECT", "UPDATE", "INSERT INTO", "DELETE FROM");
                               4408                 :                : 
                               4409                 :                : /*
                               4410                 :                :  * PREPARE TRANSACTION is missing on purpose. It's intended for transaction
                               4411                 :                :  * managers, not for manual use in interactive sessions.
                               4412                 :                :  */
                               4413                 :                : 
                               4414                 :                : /* REASSIGN OWNED BY xxx TO yyy */
 2032 tgl@sss.pgh.pa.us        4415         [ -  + ]:CBC          33 :     else if (Matches("REASSIGN"))
 2032 tgl@sss.pgh.pa.us        4416                 :UBC           0 :         COMPLETE_WITH("OWNED BY");
 2032 tgl@sss.pgh.pa.us        4417         [ -  + ]:CBC          33 :     else if (Matches("REASSIGN", "OWNED"))
 2032 tgl@sss.pgh.pa.us        4418                 :UBC           0 :         COMPLETE_WITH("BY");
 2032 tgl@sss.pgh.pa.us        4419         [ -  + ]:CBC          33 :     else if (Matches("REASSIGN", "OWNED", "BY"))
 6587 alvherre@alvh.no-ip.     4420                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_roles);
 2032 tgl@sss.pgh.pa.us        4421         [ -  + ]:CBC          33 :     else if (Matches("REASSIGN", "OWNED", "BY", MatchAny))
 2032 tgl@sss.pgh.pa.us        4422                 :UBC           0 :         COMPLETE_WITH("TO");
 2032 tgl@sss.pgh.pa.us        4423         [ -  + ]:CBC          33 :     else if (Matches("REASSIGN", "OWNED", "BY", MatchAny, "TO"))
 6587 alvherre@alvh.no-ip.     4424                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_roles);
                               4425                 :                : 
                               4426                 :                : /* REFRESH MATERIALIZED VIEW */
 2032 tgl@sss.pgh.pa.us        4427         [ -  + ]:CBC          33 :     else if (Matches("REFRESH"))
 2032 tgl@sss.pgh.pa.us        4428                 :UBC           0 :         COMPLETE_WITH("MATERIALIZED VIEW");
 2032 tgl@sss.pgh.pa.us        4429         [ -  + ]:CBC          33 :     else if (Matches("REFRESH", "MATERIALIZED"))
 2032 tgl@sss.pgh.pa.us        4430                 :UBC           0 :         COMPLETE_WITH("VIEW");
 2032 tgl@sss.pgh.pa.us        4431         [ -  + ]:CBC          33 :     else if (Matches("REFRESH", "MATERIALIZED", "VIEW"))
  805 tgl@sss.pgh.pa.us        4432                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_matviews,
                               4433                 :                :                                         "CONCURRENTLY");
 2032 tgl@sss.pgh.pa.us        4434         [ -  + ]:CBC          33 :     else if (Matches("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY"))
  805 tgl@sss.pgh.pa.us        4435                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews);
 2032 tgl@sss.pgh.pa.us        4436         [ -  + ]:CBC          33 :     else if (Matches("REFRESH", "MATERIALIZED", "VIEW", MatchAny))
 2032 tgl@sss.pgh.pa.us        4437                 :UBC           0 :         COMPLETE_WITH("WITH");
 2032 tgl@sss.pgh.pa.us        4438         [ -  + ]:CBC          33 :     else if (Matches("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny))
 2032 tgl@sss.pgh.pa.us        4439                 :UBC           0 :         COMPLETE_WITH("WITH");
 2032 tgl@sss.pgh.pa.us        4440         [ -  + ]:CBC          33 :     else if (Matches("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH"))
 2032 tgl@sss.pgh.pa.us        4441                 :UBC           0 :         COMPLETE_WITH("NO DATA", "DATA");
 2032 tgl@sss.pgh.pa.us        4442         [ -  + ]:CBC          33 :     else if (Matches("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH"))
 2032 tgl@sss.pgh.pa.us        4443                 :UBC           0 :         COMPLETE_WITH("NO DATA", "DATA");
 2032 tgl@sss.pgh.pa.us        4444         [ -  + ]:CBC          33 :     else if (Matches("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH", "NO"))
 2032 tgl@sss.pgh.pa.us        4445                 :UBC           0 :         COMPLETE_WITH("DATA");
 2032 tgl@sss.pgh.pa.us        4446         [ -  + ]:CBC          33 :     else if (Matches("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH", "NO"))
 2032 tgl@sss.pgh.pa.us        4447                 :UBC           0 :         COMPLETE_WITH("DATA");
                               4448                 :                : 
                               4449                 :                : /* REINDEX */
 1342 michael@paquier.xyz      4450   [ +  -  -  + ]:CBC          66 :     else if (Matches("REINDEX") ||
                               4451                 :             33 :              Matches("REINDEX", "(*)"))
 2032 tgl@sss.pgh.pa.us        4452                 :UBC           0 :         COMPLETE_WITH("TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE");
 1342 michael@paquier.xyz      4453   [ +  -  -  + ]:CBC          66 :     else if (Matches("REINDEX", "TABLE") ||
                               4454                 :             33 :              Matches("REINDEX", "(*)", "TABLE"))
  805 tgl@sss.pgh.pa.us        4455                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_indexables,
                               4456                 :                :                                         "CONCURRENTLY");
 1342 michael@paquier.xyz      4457   [ +  -  -  + ]:CBC          66 :     else if (Matches("REINDEX", "INDEX") ||
                               4458                 :             33 :              Matches("REINDEX", "(*)", "INDEX"))
  805 tgl@sss.pgh.pa.us        4459                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_indexes,
                               4460                 :                :                                         "CONCURRENTLY");
 1342 michael@paquier.xyz      4461   [ +  -  -  + ]:CBC          66 :     else if (Matches("REINDEX", "SCHEMA") ||
                               4462                 :             33 :              Matches("REINDEX", "(*)", "SCHEMA"))
  805 tgl@sss.pgh.pa.us        4463                 :UBC           0 :         COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_schemas,
                               4464                 :                :                                  "CONCURRENTLY");
 1342 michael@paquier.xyz      4465   [ +  -  -  + ]:CBC          66 :     else if (Matches("REINDEX", "SYSTEM|DATABASE") ||
                               4466                 :             33 :              Matches("REINDEX", "(*)", "SYSTEM|DATABASE"))
  805 tgl@sss.pgh.pa.us        4467                 :UBC           0 :         COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_databases,
                               4468                 :                :                                  "CONCURRENTLY");
 1342 michael@paquier.xyz      4469   [ +  -  -  + ]:CBC          66 :     else if (Matches("REINDEX", "TABLE", "CONCURRENTLY") ||
                               4470                 :             33 :              Matches("REINDEX", "(*)", "TABLE", "CONCURRENTLY"))
  805 tgl@sss.pgh.pa.us        4471                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexables);
 1342 michael@paquier.xyz      4472   [ +  -  -  + ]:CBC          66 :     else if (Matches("REINDEX", "INDEX", "CONCURRENTLY") ||
                               4473                 :             33 :              Matches("REINDEX", "(*)", "INDEX", "CONCURRENTLY"))
  805 tgl@sss.pgh.pa.us        4474                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes);
 1342 michael@paquier.xyz      4475   [ +  -  -  + ]:CBC          66 :     else if (Matches("REINDEX", "SCHEMA", "CONCURRENTLY") ||
                               4476                 :             33 :              Matches("REINDEX", "(*)", "SCHEMA", "CONCURRENTLY"))
 1843 peter@eisentraut.org     4477                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
 1342 michael@paquier.xyz      4478   [ +  -  -  + ]:CBC          66 :     else if (Matches("REINDEX", "SYSTEM|DATABASE", "CONCURRENTLY") ||
                               4479                 :             33 :              Matches("REINDEX", "(*)", "SYSTEM|DATABASE", "CONCURRENTLY"))
 3023 tgl@sss.pgh.pa.us        4480                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_databases);
 1342 michael@paquier.xyz      4481         [ -  + ]:CBC          33 :     else if (HeadMatches("REINDEX", "(*") &&
 1342 michael@paquier.xyz      4482         [ #  # ]:UBC           0 :              !HeadMatches("REINDEX", "(*)"))
                               4483                 :                :     {
                               4484                 :                :         /*
                               4485                 :                :          * This fires if we're in an unfinished parenthesized option list.
                               4486                 :                :          * get_previous_words treats a completed parenthesized option list as
                               4487                 :                :          * one word, so the above test is correct.
                               4488                 :                :          */
                               4489   [ #  #  #  # ]:              0 :         if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
 1165                          4490                 :              0 :             COMPLETE_WITH("CONCURRENTLY", "TABLESPACE", "VERBOSE");
                               4491         [ #  # ]:              0 :         else if (TailMatches("TABLESPACE"))
                               4492                 :              0 :             COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
                               4493                 :                :     }
                               4494                 :                : 
                               4495                 :                : /* SECURITY LABEL */
 2032 tgl@sss.pgh.pa.us        4496         [ -  + ]:CBC          33 :     else if (Matches("SECURITY"))
 2032 tgl@sss.pgh.pa.us        4497                 :UBC           0 :         COMPLETE_WITH("LABEL");
 2032 tgl@sss.pgh.pa.us        4498         [ -  + ]:CBC          33 :     else if (Matches("SECURITY", "LABEL"))
 2032 tgl@sss.pgh.pa.us        4499                 :UBC           0 :         COMPLETE_WITH("ON", "FOR");
 2032 tgl@sss.pgh.pa.us        4500         [ -  + ]:CBC          33 :     else if (Matches("SECURITY", "LABEL", "FOR", MatchAny))
 2032 tgl@sss.pgh.pa.us        4501                 :UBC           0 :         COMPLETE_WITH("ON");
 2032 tgl@sss.pgh.pa.us        4502   [ +  -  -  + ]:CBC          66 :     else if (Matches("SECURITY", "LABEL", "ON") ||
                               4503                 :             33 :              Matches("SECURITY", "LABEL", "FOR", MatchAny, "ON"))
 2032 tgl@sss.pgh.pa.us        4504                 :UBC           0 :         COMPLETE_WITH("TABLE", "COLUMN", "AGGREGATE", "DATABASE", "DOMAIN",
                               4505                 :                :                       "EVENT TRIGGER", "FOREIGN TABLE", "FUNCTION",
                               4506                 :                :                       "LARGE OBJECT", "MATERIALIZED VIEW", "LANGUAGE",
                               4507                 :                :                       "PUBLICATION", "PROCEDURE", "ROLE", "ROUTINE", "SCHEMA",
                               4508                 :                :                       "SEQUENCE", "SUBSCRIPTION", "TABLESPACE", "TYPE", "VIEW");
 2032 tgl@sss.pgh.pa.us        4509         [ -  + ]:CBC          33 :     else if (Matches("SECURITY", "LABEL", "ON", MatchAny, MatchAny))
 2032 tgl@sss.pgh.pa.us        4510                 :UBC           0 :         COMPLETE_WITH("IS");
                               4511                 :                : 
                               4512                 :                : /* SELECT */
                               4513                 :                :     /* naah . . . */
                               4514                 :                : 
                               4515                 :                : /* SET, RESET, SHOW */
                               4516                 :                :     /* Complete with a variable name */
 2032 tgl@sss.pgh.pa.us        4517   [ +  +  +  - ]:CBC          33 :     else if (TailMatches("SET|RESET") && !TailMatches("UPDATE", MatchAny, "SET"))
  795                          4518                 :              3 :         COMPLETE_WITH_QUERY_VERBATIM_PLUS(Query_for_list_of_set_vars,
                               4519                 :                :                                           "CONSTRAINTS",
                               4520                 :                :                                           "TRANSACTION",
                               4521                 :                :                                           "SESSION",
                               4522                 :                :                                           "ROLE",
                               4523                 :                :                                           "TABLESPACE",
                               4524                 :                :                                           "ALL");
 2032                          4525         [ -  + ]:             30 :     else if (Matches("SHOW"))
  795 tgl@sss.pgh.pa.us        4526                 :UBC           0 :         COMPLETE_WITH_QUERY_VERBATIM_PLUS(Query_for_list_of_show_vars,
                               4527                 :                :                                           "SESSION AUTHORIZATION",
                               4528                 :                :                                           "ALL");
  803 tgl@sss.pgh.pa.us        4529         [ -  + ]:CBC          30 :     else if (Matches("SHOW", "SESSION"))
  803 tgl@sss.pgh.pa.us        4530                 :UBC           0 :         COMPLETE_WITH("AUTHORIZATION");
                               4531                 :                :     /* Complete "SET TRANSACTION" */
 2032 tgl@sss.pgh.pa.us        4532         [ -  + ]:CBC          30 :     else if (Matches("SET", "TRANSACTION"))
 2032 tgl@sss.pgh.pa.us        4533                 :UBC           0 :         COMPLETE_WITH("SNAPSHOT", "ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
 2032 tgl@sss.pgh.pa.us        4534   [ +  -  +  - ]:CBC          60 :     else if (Matches("BEGIN|START", "TRANSACTION") ||
                               4535         [ +  - ]:             60 :              Matches("BEGIN", "WORK") ||
                               4536         [ -  + ]:             60 :              Matches("BEGIN") ||
                               4537                 :             30 :              Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION"))
 2032 tgl@sss.pgh.pa.us        4538                 :UBC           0 :         COMPLETE_WITH("ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
 2032 tgl@sss.pgh.pa.us        4539   [ +  -  +  - ]:CBC          60 :     else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "NOT") ||
                               4540         [ -  + ]:             60 :              Matches("BEGIN", "NOT") ||
                               4541                 :             30 :              Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "NOT"))
 2032 tgl@sss.pgh.pa.us        4542                 :UBC           0 :         COMPLETE_WITH("DEFERRABLE");
 2032 tgl@sss.pgh.pa.us        4543   [ +  -  +  - ]:CBC          60 :     else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION") ||
                               4544         [ -  + ]:             60 :              Matches("BEGIN", "ISOLATION") ||
                               4545                 :             30 :              Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION"))
 2032 tgl@sss.pgh.pa.us        4546                 :UBC           0 :         COMPLETE_WITH("LEVEL");
 2032 tgl@sss.pgh.pa.us        4547   [ +  -  +  - ]:CBC          60 :     else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL") ||
                               4548         [ -  + ]:             60 :              Matches("BEGIN", "ISOLATION", "LEVEL") ||
                               4549                 :             30 :              Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL"))
 2032 tgl@sss.pgh.pa.us        4550                 :UBC           0 :         COMPLETE_WITH("READ", "REPEATABLE READ", "SERIALIZABLE");
 2032 tgl@sss.pgh.pa.us        4551   [ +  -  +  - ]:CBC          60 :     else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "READ") ||
                               4552         [ -  + ]:             60 :              Matches("BEGIN", "ISOLATION", "LEVEL", "READ") ||
                               4553                 :             30 :              Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "READ"))
 2032 tgl@sss.pgh.pa.us        4554                 :UBC           0 :         COMPLETE_WITH("UNCOMMITTED", "COMMITTED");
 2032 tgl@sss.pgh.pa.us        4555   [ +  -  +  - ]:CBC          60 :     else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "REPEATABLE") ||
                               4556         [ -  + ]:             60 :              Matches("BEGIN", "ISOLATION", "LEVEL", "REPEATABLE") ||
                               4557                 :             30 :              Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "REPEATABLE"))
 2032 tgl@sss.pgh.pa.us        4558                 :UBC           0 :         COMPLETE_WITH("READ");
 2032 tgl@sss.pgh.pa.us        4559   [ +  -  +  - ]:CBC          60 :     else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "READ") ||
                               4560         [ -  + ]:             60 :              Matches("BEGIN", "READ") ||
                               4561                 :             30 :              Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "READ"))
 2032 tgl@sss.pgh.pa.us        4562                 :UBC           0 :         COMPLETE_WITH("ONLY", "WRITE");
                               4563                 :                :     /* SET CONSTRAINTS */
 2032 tgl@sss.pgh.pa.us        4564         [ -  + ]:CBC          30 :     else if (Matches("SET", "CONSTRAINTS"))
  805 tgl@sss.pgh.pa.us        4565                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_constraints_with_schema,
                               4566                 :                :                                         "ALL");
                               4567                 :                :     /* Complete SET CONSTRAINTS <foo> with DEFERRED|IMMEDIATE */
 2032 tgl@sss.pgh.pa.us        4568         [ -  + ]:CBC          30 :     else if (Matches("SET", "CONSTRAINTS", MatchAny))
 2032 tgl@sss.pgh.pa.us        4569                 :UBC           0 :         COMPLETE_WITH("DEFERRED", "IMMEDIATE");
                               4570                 :                :     /* Complete SET ROLE */
 2032 tgl@sss.pgh.pa.us        4571         [ -  + ]:CBC          30 :     else if (Matches("SET", "ROLE"))
 6818 tgl@sss.pgh.pa.us        4572                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_roles);
                               4573                 :                :     /* Complete SET SESSION with AUTHORIZATION or CHARACTERISTICS... */
 2032 tgl@sss.pgh.pa.us        4574         [ -  + ]:CBC          30 :     else if (Matches("SET", "SESSION"))
 2032 tgl@sss.pgh.pa.us        4575                 :UBC           0 :         COMPLETE_WITH("AUTHORIZATION", "CHARACTERISTICS AS TRANSACTION");
                               4576                 :                :     /* Complete SET SESSION AUTHORIZATION with username */
 2032 tgl@sss.pgh.pa.us        4577         [ -  + ]:CBC          30 :     else if (Matches("SET", "SESSION", "AUTHORIZATION"))
  805 tgl@sss.pgh.pa.us        4578                 :UBC           0 :         COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
                               4579                 :                :                                  "DEFAULT");
                               4580                 :                :     /* Complete RESET SESSION with AUTHORIZATION */
 2032 tgl@sss.pgh.pa.us        4581         [ -  + ]:CBC          30 :     else if (Matches("RESET", "SESSION"))
 2032 tgl@sss.pgh.pa.us        4582                 :UBC           0 :         COMPLETE_WITH("AUTHORIZATION");
                               4583                 :                :     /* Complete SET <var> with "TO" */
 2032 tgl@sss.pgh.pa.us        4584         [ +  + ]:CBC          30 :     else if (Matches("SET", MatchAny))
                               4585                 :              2 :         COMPLETE_WITH("TO");
                               4586                 :                : 
                               4587                 :                :     /*
                               4588                 :                :      * Complete ALTER DATABASE|FUNCTION|PROCEDURE|ROLE|ROUTINE|USER ... SET
                               4589                 :                :      * <name>
                               4590                 :                :      */
                               4591   [ -  +  -  - ]:             28 :     else if (HeadMatches("ALTER", "DATABASE|FUNCTION|PROCEDURE|ROLE|ROUTINE|USER") &&
  464 dean.a.rasheed@gmail     4592                 :UBC           0 :              TailMatches("SET", MatchAny) &&
                               4593         [ #  # ]:              0 :              !TailMatches("SCHEMA"))
 2032 tgl@sss.pgh.pa.us        4594                 :              0 :         COMPLETE_WITH("FROM CURRENT", "TO");
                               4595                 :                : 
                               4596                 :                :     /*
                               4597                 :                :      * Suggest possible variable values in SET variable TO|=, along with the
                               4598                 :                :      * preceding ALTER syntaxes.
                               4599                 :                :      */
 1748 tgl@sss.pgh.pa.us        4600         [ +  + ]:CBC          28 :     else if (TailMatches("SET", MatchAny, "TO|=") &&
                               4601         [ +  - ]:              4 :              !TailMatches("UPDATE", MatchAny, "SET", MatchAny, "TO|="))
                               4602                 :                :     {
                               4603                 :                :         /* special cased code for individual GUCs */
 2032                          4604         [ -  + ]:              8 :         if (TailMatches("DateStyle", "TO|="))
 2032 tgl@sss.pgh.pa.us        4605                 :UBC           0 :             COMPLETE_WITH("ISO", "SQL", "Postgres", "German",
                               4606                 :                :                           "YMD", "DMY", "MDY",
                               4607                 :                :                           "US", "European", "NonEuropean",
                               4608                 :                :                           "DEFAULT");
 2032 tgl@sss.pgh.pa.us        4609         [ -  + ]:CBC           4 :         else if (TailMatches("search_path", "TO|="))
                               4610                 :                :         {
                               4611                 :                :             /* Here, we want to allow pg_catalog, so use narrower exclusion */
  805 tgl@sss.pgh.pa.us        4612                 :UBC           0 :             COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_schemas
                               4613                 :                :                                      " AND nspname NOT LIKE E'pg\\\\_toast%%'"
                               4614                 :                :                                      " AND nspname NOT LIKE E'pg\\\\_temp%%'",
                               4615                 :                :                                      "DEFAULT");
                               4616                 :                :         }
  756 tgl@sss.pgh.pa.us        4617         [ +  + ]:CBC           4 :         else if (TailMatches("TimeZone", "TO|="))
                               4618   [ -  +  +  -  :              2 :             COMPLETE_WITH_TIMEZONE_NAME();
                                              +  + ]
                               4619                 :                :         else
                               4620                 :                :         {
                               4621                 :                :             /* generic, type based, GUC support */
 3141 andres@anarazel.de       4622                 :              2 :             char       *guctype = get_guctype(prev2_wd);
                               4623                 :                : 
                               4624                 :                :             /*
                               4625                 :                :              * Note: if we don't recognize the GUC name, it's important to not
                               4626                 :                :              * offer any completions, as most likely we've misinterpreted the
                               4627                 :                :              * context and this isn't a GUC-setting command at all.
                               4628                 :                :              */
 1748 tgl@sss.pgh.pa.us        4629         [ +  - ]:              2 :             if (guctype)
                               4630                 :                :             {
                               4631         [ +  - ]:              2 :                 if (strcmp(guctype, "enum") == 0)
                               4632                 :                :                 {
  795                          4633                 :              2 :                     set_completion_reference_verbatim(prev2_wd);
  805                          4634                 :              2 :                     COMPLETE_WITH_QUERY_PLUS(Query_for_values_of_enum_GUC,
                               4635                 :                :                                              "DEFAULT");
                               4636                 :                :                 }
 1748 tgl@sss.pgh.pa.us        4637         [ #  # ]:UBC           0 :                 else if (strcmp(guctype, "bool") == 0)
                               4638                 :              0 :                     COMPLETE_WITH("on", "off", "true", "false", "yes", "no",
                               4639                 :                :                                   "1", "0", "DEFAULT");
                               4640                 :                :                 else
                               4641                 :              0 :                     COMPLETE_WITH("DEFAULT");
                               4642                 :                : 
 3141 andres@anarazel.de       4643                 :CBC           2 :                 free(guctype);
                               4644                 :                :             }
                               4645                 :                :         }
                               4646                 :                :     }
                               4647                 :                : 
                               4648                 :                : /* START TRANSACTION */
 2032 tgl@sss.pgh.pa.us        4649         [ -  + ]:             24 :     else if (Matches("START"))
 2032 tgl@sss.pgh.pa.us        4650                 :UBC           0 :         COMPLETE_WITH("TRANSACTION");
                               4651                 :                : 
                               4652                 :                : /* TABLE, but not TABLE embedded in other commands */
 2032 tgl@sss.pgh.pa.us        4653         [ -  + ]:CBC          24 :     else if (Matches("TABLE"))
  805 tgl@sss.pgh.pa.us        4654                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_selectables);
                               4655                 :                : 
                               4656                 :                : /* TABLESAMPLE */
 2032 tgl@sss.pgh.pa.us        4657         [ -  + ]:CBC          24 :     else if (TailMatches("TABLESAMPLE"))
 3219 rhaas@postgresql.org     4658                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_tablesample_methods);
 2032 tgl@sss.pgh.pa.us        4659         [ -  + ]:CBC          24 :     else if (TailMatches("TABLESAMPLE", MatchAny))
 2032 tgl@sss.pgh.pa.us        4660                 :UBC           0 :         COMPLETE_WITH("(");
                               4661                 :                : 
                               4662                 :                : /* TRUNCATE */
 2032 tgl@sss.pgh.pa.us        4663         [ -  + ]:CBC          24 :     else if (Matches("TRUNCATE"))
  805 tgl@sss.pgh.pa.us        4664                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_truncatables,
                               4665                 :                :                                         "TABLE", "ONLY");
 1144 fujii@postgresql.org     4666         [ -  + ]:CBC          24 :     else if (Matches("TRUNCATE", "TABLE"))
  805 tgl@sss.pgh.pa.us        4667                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_truncatables,
                               4668                 :                :                                         "ONLY");
 1144 fujii@postgresql.org     4669   [ -  +  -  - ]:CBC          24 :     else if (HeadMatches("TRUNCATE") && TailMatches("ONLY"))
  805 tgl@sss.pgh.pa.us        4670                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_truncatables);
 1144 fujii@postgresql.org     4671   [ +  -  +  - ]:CBC          48 :     else if (Matches("TRUNCATE", MatchAny) ||
                               4672         [ -  + ]:             48 :              Matches("TRUNCATE", "TABLE|ONLY", MatchAny) ||
                               4673                 :             24 :              Matches("TRUNCATE", "TABLE", "ONLY", MatchAny))
 1144 fujii@postgresql.org     4674                 :UBC           0 :         COMPLETE_WITH("RESTART IDENTITY", "CONTINUE IDENTITY", "CASCADE", "RESTRICT");
 1144 fujii@postgresql.org     4675   [ -  +  -  - ]:CBC          24 :     else if (HeadMatches("TRUNCATE") && TailMatches("IDENTITY"))
 1144 fujii@postgresql.org     4676                 :UBC           0 :         COMPLETE_WITH("CASCADE", "RESTRICT");
                               4677                 :                : 
                               4678                 :                : /* UNLISTEN */
 2032 tgl@sss.pgh.pa.us        4679         [ -  + ]:CBC          24 :     else if (Matches("UNLISTEN"))
  805 tgl@sss.pgh.pa.us        4680                 :UBC           0 :         COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_channels, "*");
                               4681                 :                : 
                               4682                 :                : /* UPDATE --- can be inside EXPLAIN, RULE, etc */
                               4683                 :                :     /* If prev. word is UPDATE suggest a list of tables */
 2032 tgl@sss.pgh.pa.us        4684         [ -  + ]:CBC          24 :     else if (TailMatches("UPDATE"))
  805 tgl@sss.pgh.pa.us        4685                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables);
                               4686                 :                :     /* Complete UPDATE <table> with "SET" */
 2032 tgl@sss.pgh.pa.us        4687         [ -  + ]:CBC          24 :     else if (TailMatches("UPDATE", MatchAny))
 2032 tgl@sss.pgh.pa.us        4688                 :UBC           0 :         COMPLETE_WITH("SET");
                               4689                 :                :     /* Complete UPDATE <table> SET with list of attributes */
 2032 tgl@sss.pgh.pa.us        4690         [ -  + ]:CBC          24 :     else if (TailMatches("UPDATE", MatchAny, "SET"))
  805 tgl@sss.pgh.pa.us        4691                 :UBC           0 :         COMPLETE_WITH_ATTR(prev2_wd);
                               4692                 :                :     /* UPDATE <table> SET <attr> = */
 1737 tmunro@postgresql.or     4693         [ -  + ]:CBC          24 :     else if (TailMatches("UPDATE", MatchAny, "SET", MatchAnyExcept("*=")))
 2032 tgl@sss.pgh.pa.us        4694                 :UBC           0 :         COMPLETE_WITH("=");
                               4695                 :                : 
                               4696                 :                : /* USER MAPPING */
 2032 tgl@sss.pgh.pa.us        4697         [ -  + ]:CBC          24 :     else if (Matches("ALTER|CREATE|DROP", "USER", "MAPPING"))
 2032 tgl@sss.pgh.pa.us        4698                 :UBC           0 :         COMPLETE_WITH("FOR");
 2032 tgl@sss.pgh.pa.us        4699         [ -  + ]:CBC          24 :     else if (Matches("CREATE", "USER", "MAPPING", "FOR"))
  805 tgl@sss.pgh.pa.us        4700                 :UBC           0 :         COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
                               4701                 :                :                                  "CURRENT_ROLE",
                               4702                 :                :                                  "CURRENT_USER",
                               4703                 :                :                                  "PUBLIC",
                               4704                 :                :                                  "USER");
 2032 tgl@sss.pgh.pa.us        4705         [ -  + ]:CBC          24 :     else if (Matches("ALTER|DROP", "USER", "MAPPING", "FOR"))
 5595 peter_e@gmx.net          4706                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
 2032 tgl@sss.pgh.pa.us        4707         [ -  + ]:CBC          24 :     else if (Matches("CREATE|ALTER|DROP", "USER", "MAPPING", "FOR", MatchAny))
 2032 tgl@sss.pgh.pa.us        4708                 :UBC           0 :         COMPLETE_WITH("SERVER");
 2032 tgl@sss.pgh.pa.us        4709         [ -  + ]:CBC          24 :     else if (Matches("CREATE|ALTER", "USER", "MAPPING", "FOR", MatchAny, "SERVER", MatchAny))
 2032 tgl@sss.pgh.pa.us        4710                 :UBC           0 :         COMPLETE_WITH("OPTIONS");
                               4711                 :                : 
                               4712                 :                : /*
                               4713                 :                :  * VACUUM [ ( option [, ...] ) ] [ table_and_columns [, ...] ]
                               4714                 :                :  * VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ ANALYZE ] [ table_and_columns [, ...] ]
                               4715                 :                :  */
 2032 tgl@sss.pgh.pa.us        4716         [ -  + ]:CBC          24 :     else if (Matches("VACUUM"))
  805 tgl@sss.pgh.pa.us        4717                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_vacuumables,
                               4718                 :                :                                         "FULL",
                               4719                 :                :                                         "FREEZE",
                               4720                 :                :                                         "ANALYZE",
                               4721                 :                :                                         "VERBOSE");
 2032 tgl@sss.pgh.pa.us        4722         [ -  + ]:CBC          24 :     else if (Matches("VACUUM", "FULL"))
  805 tgl@sss.pgh.pa.us        4723                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_vacuumables,
                               4724                 :                :                                         "FREEZE",
                               4725                 :                :                                         "ANALYZE",
                               4726                 :                :                                         "VERBOSE");
 2032 tgl@sss.pgh.pa.us        4727   [ +  -  -  + ]:CBC          48 :     else if (Matches("VACUUM", "FREEZE") ||
                               4728                 :             24 :              Matches("VACUUM", "FULL", "FREEZE"))
  805 tgl@sss.pgh.pa.us        4729                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_vacuumables,
                               4730                 :                :                                         "VERBOSE",
                               4731                 :                :                                         "ANALYZE");
 2032 tgl@sss.pgh.pa.us        4732   [ +  -  +  - ]:CBC          48 :     else if (Matches("VACUUM", "VERBOSE") ||
                               4733         [ -  + ]:             48 :              Matches("VACUUM", "FULL|FREEZE", "VERBOSE") ||
                               4734                 :             24 :              Matches("VACUUM", "FULL", "FREEZE", "VERBOSE"))
  805 tgl@sss.pgh.pa.us        4735                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_vacuumables,
                               4736                 :                :                                         "ANALYZE");
 2032 tgl@sss.pgh.pa.us        4737         [ -  + ]:CBC          24 :     else if (HeadMatches("VACUUM", "(*") &&
 2032 tgl@sss.pgh.pa.us        4738         [ #  # ]:UBC           0 :              !HeadMatches("VACUUM", "(*)"))
                               4739                 :                :     {
                               4740                 :                :         /*
                               4741                 :                :          * This fires if we're in an unfinished parenthesized option list.
                               4742                 :                :          * get_previous_words treats a completed parenthesized option list as
                               4743                 :                :          * one word, so the above test is correct.
                               4744                 :                :          */
                               4745   [ #  #  #  # ]:              0 :         if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
                               4746                 :              0 :             COMPLETE_WITH("FULL", "FREEZE", "ANALYZE", "VERBOSE",
                               4747                 :                :                           "DISABLE_PAGE_SKIPPING", "SKIP_LOCKED",
                               4748                 :                :                           "INDEX_CLEANUP", "PROCESS_MAIN", "PROCESS_TOAST",
                               4749                 :                :                           "TRUNCATE", "PARALLEL", "SKIP_DATABASE_STATS",
                               4750                 :                :                           "ONLY_DATABASE_STATS", "BUFFER_USAGE_LIMIT");
  405 michael@paquier.xyz      4751         [ #  # ]:              0 :         else if (TailMatches("FULL|FREEZE|ANALYZE|VERBOSE|DISABLE_PAGE_SKIPPING|SKIP_LOCKED|PROCESS_MAIN|PROCESS_TOAST|TRUNCATE|SKIP_DATABASE_STATS|ONLY_DATABASE_STATS"))
 1843 rhaas@postgresql.org     4752                 :              0 :             COMPLETE_WITH("ON", "OFF");
 1031 pg@bowt.ie               4753         [ #  # ]:              0 :         else if (TailMatches("INDEX_CLEANUP"))
                               4754                 :              0 :             COMPLETE_WITH("AUTO", "ON", "OFF");
                               4755                 :                :     }
 2032 tgl@sss.pgh.pa.us        4756   [ -  +  -  - ]:CBC          24 :     else if (HeadMatches("VACUUM") && TailMatches("("))
                               4757                 :                :         /* "VACUUM (" should be caught above, so assume we want columns */
  805 tgl@sss.pgh.pa.us        4758                 :UBC           0 :         COMPLETE_WITH_ATTR(prev2_wd);
 2032 tgl@sss.pgh.pa.us        4759         [ -  + ]:CBC          24 :     else if (HeadMatches("VACUUM"))
  805 tgl@sss.pgh.pa.us        4760                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_vacuumables);
                               4761                 :                : 
                               4762                 :                : /* WITH [RECURSIVE] */
                               4763                 :                : 
                               4764                 :                :     /*
                               4765                 :                :      * Only match when WITH is the first word, as WITH may appear in many
                               4766                 :                :      * other contexts.
                               4767                 :                :      */
 2032 tgl@sss.pgh.pa.us        4768         [ -  + ]:CBC          24 :     else if (Matches("WITH"))
 2032 tgl@sss.pgh.pa.us        4769                 :UBC           0 :         COMPLETE_WITH("RECURSIVE");
                               4770                 :                : 
                               4771                 :                : /* WHERE */
                               4772                 :                :     /* Simple case of the word before the where being the table name */
 2032 tgl@sss.pgh.pa.us        4773         [ -  + ]:CBC          24 :     else if (TailMatches(MatchAny, "WHERE"))
  805 tgl@sss.pgh.pa.us        4774                 :UBC           0 :         COMPLETE_WITH_ATTR(prev2_wd);
                               4775                 :                : 
                               4776                 :                : /* ... FROM ... */
                               4777                 :                : /* TODO: also include SRF ? */
 2032 tgl@sss.pgh.pa.us        4778   [ +  +  +  - ]:CBC          24 :     else if (TailMatches("FROM") && !Matches("COPY|\\copy", MatchAny, "FROM"))
  805                          4779                 :             14 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_selectables);
                               4780                 :                : 
                               4781                 :                : /* ... JOIN ... */
 2032                          4782         [ -  + ]:             10 :     else if (TailMatches("JOIN"))
  805 tgl@sss.pgh.pa.us        4783                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_selectables);
                               4784                 :                : 
                               4785                 :                : /* ... AT [ LOCAL | TIME ZONE ] ... */
  184 michael@paquier.xyz      4786         [ -  + ]:GNC          10 :     else if (TailMatches("AT"))
  184 michael@paquier.xyz      4787                 :UNC           0 :         COMPLETE_WITH("LOCAL", "TIME ZONE");
  184 michael@paquier.xyz      4788         [ -  + ]:GNC          10 :     else if (TailMatches("AT", "TIME", "ZONE"))
  184 michael@paquier.xyz      4789   [ #  #  #  #  :UNC           0 :         COMPLETE_WITH_TIMEZONE_NAME();
                                              #  # ]
                               4790                 :                : 
                               4791                 :                : /* Backslash commands */
                               4792                 :                : /* TODO:  \dc \dd \dl */
 2032 tgl@sss.pgh.pa.us        4793         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\?"))
 2032 tgl@sss.pgh.pa.us        4794                 :UBC           0 :         COMPLETE_WITH_CS("commands", "options", "variables");
 2032 tgl@sss.pgh.pa.us        4795         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\connect|\\c"))
                               4796                 :                :     {
 3300 alvherre@alvh.no-ip.     4797         [ #  # ]:UBC           0 :         if (!recognized_connection_string(text))
                               4798                 :              0 :             COMPLETE_WITH_QUERY(Query_for_list_of_databases);
                               4799                 :                :     }
 2032 tgl@sss.pgh.pa.us        4800         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\connect|\\c", MatchAny))
                               4801                 :                :     {
 3300 alvherre@alvh.no-ip.     4802         [ #  # ]:UBC           0 :         if (!recognized_connection_string(prev_wd))
                               4803                 :              0 :             COMPLETE_WITH_QUERY(Query_for_list_of_roles);
                               4804                 :                :     }
 2032 tgl@sss.pgh.pa.us        4805         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\da*"))
  805 tgl@sss.pgh.pa.us        4806                 :UBC           0 :         COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_aggregates);
 1498 akorotkov@postgresql     4807   [ +  -  -  + ]:CBC          20 :     else if (TailMatchesCS("\\dAc*", MatchAny) ||
                               4808                 :             10 :              TailMatchesCS("\\dAf*", MatchAny))
  805 tgl@sss.pgh.pa.us        4809                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
 1498 akorotkov@postgresql     4810   [ +  -  -  + ]:CBC          20 :     else if (TailMatchesCS("\\dAo*", MatchAny) ||
                               4811                 :             10 :              TailMatchesCS("\\dAp*", MatchAny))
  805 tgl@sss.pgh.pa.us        4812                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_operator_families);
 2032 tgl@sss.pgh.pa.us        4813         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\dA*"))
 2868 alvherre@alvh.no-ip.     4814                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
 2032 tgl@sss.pgh.pa.us        4815         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\db*"))
 7177 bruce@momjian.us         4816                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
  738 tgl@sss.pgh.pa.us        4817         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\dconfig*"))
  738 tgl@sss.pgh.pa.us        4818                 :UBC           0 :         COMPLETE_WITH_QUERY_VERBATIM(Query_for_list_of_show_vars);
 2032 tgl@sss.pgh.pa.us        4819         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\dD*"))
  805 tgl@sss.pgh.pa.us        4820                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains);
 2032 tgl@sss.pgh.pa.us        4821         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\des*"))
 5595 peter_e@gmx.net          4822                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_servers);
 2032 tgl@sss.pgh.pa.us        4823         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\deu*"))
 5595 peter_e@gmx.net          4824                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
 2032 tgl@sss.pgh.pa.us        4825         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\dew*"))
 5595 peter_e@gmx.net          4826                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
 2032 tgl@sss.pgh.pa.us        4827         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\df*"))
  805 tgl@sss.pgh.pa.us        4828                 :UBC           0 :         COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_functions);
 1102 tgl@sss.pgh.pa.us        4829         [ -  + ]:CBC          10 :     else if (HeadMatchesCS("\\df*"))
  805 tgl@sss.pgh.pa.us        4830                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
                               4831                 :                : 
 2032 tgl@sss.pgh.pa.us        4832         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\dFd*"))
  805 tgl@sss.pgh.pa.us        4833                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_ts_dictionaries);
 2032 tgl@sss.pgh.pa.us        4834         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\dFp*"))
  805 tgl@sss.pgh.pa.us        4835                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_ts_parsers);
 2032 tgl@sss.pgh.pa.us        4836         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\dFt*"))
  805 tgl@sss.pgh.pa.us        4837                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_ts_templates);
                               4838                 :                :     /* must be at end of \dF alternatives: */
 2032 tgl@sss.pgh.pa.us        4839         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\dF*"))
  805 tgl@sss.pgh.pa.us        4840                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_ts_configurations);
                               4841                 :                : 
 2032 tgl@sss.pgh.pa.us        4842         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\di*"))
  805 tgl@sss.pgh.pa.us        4843                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes);
 2032 tgl@sss.pgh.pa.us        4844         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\dL*"))
 4833 rhaas@postgresql.org     4845                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_languages);
 2032 tgl@sss.pgh.pa.us        4846         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\dn*"))
 7689 bruce@momjian.us         4847                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
                               4848                 :                :     /* no support for completing operators, but we can complete types: */
 1102 tgl@sss.pgh.pa.us        4849         [ -  + ]:CBC          10 :     else if (HeadMatchesCS("\\do*", MatchAny))
  805 tgl@sss.pgh.pa.us        4850                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
 2032 tgl@sss.pgh.pa.us        4851   [ +  -  -  + ]:CBC          10 :     else if (TailMatchesCS("\\dp") || TailMatchesCS("\\z"))
  805 tgl@sss.pgh.pa.us        4852                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_grantables);
 1834 alvherre@alvh.no-ip.     4853         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\dPi*"))
  805 tgl@sss.pgh.pa.us        4854                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_partitioned_indexes);
 1834 alvherre@alvh.no-ip.     4855         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\dPt*"))
  805 tgl@sss.pgh.pa.us        4856                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_partitioned_tables);
 1834 alvherre@alvh.no-ip.     4857         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\dP*"))
  805 tgl@sss.pgh.pa.us        4858                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_partitioned_relations);
  557 michael@paquier.xyz      4859         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\dRp*"))
  557 michael@paquier.xyz      4860                 :UBC           0 :         COMPLETE_WITH_VERSIONED_QUERY(Query_for_list_of_publications);
  557 michael@paquier.xyz      4861         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\dRs*"))
  557 michael@paquier.xyz      4862                 :UBC           0 :         COMPLETE_WITH_VERSIONED_QUERY(Query_for_list_of_subscriptions);
 2032 tgl@sss.pgh.pa.us        4863         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\ds*"))
  805 tgl@sss.pgh.pa.us        4864                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences);
 2032 tgl@sss.pgh.pa.us        4865         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\dt*"))
  805 tgl@sss.pgh.pa.us        4866                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
 2032 tgl@sss.pgh.pa.us        4867         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\dT*"))
  805 tgl@sss.pgh.pa.us        4868                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
  270 tgl@sss.pgh.pa.us        4869   [ +  -  +  - ]:CBC          20 :     else if (TailMatchesCS("\\du*") ||
                               4870         [ -  + ]:             20 :              TailMatchesCS("\\dg*") ||
                               4871                 :             10 :              TailMatchesCS("\\drg*"))
 6818 tgl@sss.pgh.pa.us        4872                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_roles);
 2032 tgl@sss.pgh.pa.us        4873         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\dv*"))
  805 tgl@sss.pgh.pa.us        4874                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views);
 2032 tgl@sss.pgh.pa.us        4875         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\dx*"))
 3895 magnus@hagander.net      4876                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_extensions);
 1180 tomas.vondra@postgre     4877         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\dX*"))
  805 tgl@sss.pgh.pa.us        4878                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_statistics);
 2032 tgl@sss.pgh.pa.us        4879         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\dm*"))
  805 tgl@sss.pgh.pa.us        4880                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews);
 2032 tgl@sss.pgh.pa.us        4881         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\dE*"))
  805 tgl@sss.pgh.pa.us        4882                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables);
 2032 tgl@sss.pgh.pa.us        4883         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\dy*"))
 3204 fujii@postgresql.org     4884                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
                               4885                 :                : 
                               4886                 :                :     /* must be at end of \d alternatives: */
 2032 tgl@sss.pgh.pa.us        4887         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\d*"))
  805 tgl@sss.pgh.pa.us        4888                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations);
                               4889                 :                : 
 2032 tgl@sss.pgh.pa.us        4890         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\ef"))
  805 tgl@sss.pgh.pa.us        4891                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_routines);
 2032 tgl@sss.pgh.pa.us        4892         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\ev"))
  805 tgl@sss.pgh.pa.us        4893                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views);
                               4894                 :                : 
 2032 tgl@sss.pgh.pa.us        4895         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\encoding"))
  805 tgl@sss.pgh.pa.us        4896                 :UBC           0 :         COMPLETE_WITH_QUERY_VERBATIM(Query_for_list_of_encodings);
 2032 tgl@sss.pgh.pa.us        4897         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\h|\\help"))
 8768 bruce@momjian.us         4898                 :UBC           0 :         COMPLETE_WITH_LIST(sql_commands);
 2032 tgl@sss.pgh.pa.us        4899         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\h|\\help", MatchAny))
                               4900                 :                :     {
 2032 tgl@sss.pgh.pa.us        4901         [ #  # ]:UBC           0 :         if (TailMatches("DROP"))
 1584                          4902                 :              0 :             matches = rl_completion_matches(text, drop_command_generator);
 2032                          4903         [ #  # ]:              0 :         else if (TailMatches("ALTER"))
 1584                          4904                 :              0 :             matches = rl_completion_matches(text, alter_command_generator);
                               4905                 :                : 
                               4906                 :                :         /*
                               4907                 :                :          * CREATE is recognized by tail match elsewhere, so doesn't need to be
                               4908                 :                :          * repeated here
                               4909                 :                :          */
                               4910                 :                :     }
 2032 tgl@sss.pgh.pa.us        4911         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\h|\\help", MatchAny, MatchAny))
                               4912                 :                :     {
 2032 tgl@sss.pgh.pa.us        4913         [ #  # ]:UBC           0 :         if (TailMatches("CREATE|DROP", "ACCESS"))
                               4914                 :              0 :             COMPLETE_WITH("METHOD");
                               4915         [ #  # ]:              0 :         else if (TailMatches("ALTER", "DEFAULT"))
                               4916                 :              0 :             COMPLETE_WITH("PRIVILEGES");
                               4917         [ #  # ]:              0 :         else if (TailMatches("CREATE|ALTER|DROP", "EVENT"))
                               4918                 :              0 :             COMPLETE_WITH("TRIGGER");
                               4919         [ #  # ]:              0 :         else if (TailMatches("CREATE|ALTER|DROP", "FOREIGN"))
                               4920                 :              0 :             COMPLETE_WITH("DATA WRAPPER", "TABLE");
                               4921         [ #  # ]:              0 :         else if (TailMatches("ALTER", "LARGE"))
                               4922                 :              0 :             COMPLETE_WITH("OBJECT");
                               4923         [ #  # ]:              0 :         else if (TailMatches("CREATE|ALTER|DROP", "MATERIALIZED"))
                               4924                 :              0 :             COMPLETE_WITH("VIEW");
                               4925         [ #  # ]:              0 :         else if (TailMatches("CREATE|ALTER|DROP", "TEXT"))
                               4926                 :              0 :             COMPLETE_WITH("SEARCH");
                               4927         [ #  # ]:              0 :         else if (TailMatches("CREATE|ALTER|DROP", "USER"))
                               4928                 :              0 :             COMPLETE_WITH("MAPPING FOR");
                               4929                 :                :     }
 2032 tgl@sss.pgh.pa.us        4930         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\h|\\help", MatchAny, MatchAny, MatchAny))
                               4931                 :                :     {
 2032 tgl@sss.pgh.pa.us        4932         [ #  # ]:UBC           0 :         if (TailMatches("CREATE|ALTER|DROP", "FOREIGN", "DATA"))
                               4933                 :              0 :             COMPLETE_WITH("WRAPPER");
                               4934         [ #  # ]:              0 :         else if (TailMatches("CREATE|ALTER|DROP", "TEXT", "SEARCH"))
                               4935                 :              0 :             COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
                               4936         [ #  # ]:              0 :         else if (TailMatches("CREATE|ALTER|DROP", "USER", "MAPPING"))
                               4937                 :              0 :             COMPLETE_WITH("FOR");
                               4938                 :                :     }
 2032 tgl@sss.pgh.pa.us        4939   [ +  +  -  + ]:CBC          10 :     else if (TailMatchesCS("\\l*") && !TailMatchesCS("\\lo*"))
 2796 tgl@sss.pgh.pa.us        4940                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_databases);
 2032 tgl@sss.pgh.pa.us        4941         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\password"))
 6692 peter_e@gmx.net          4942                 :UBC           0 :         COMPLETE_WITH_QUERY(Query_for_list_of_roles);
 2032 tgl@sss.pgh.pa.us        4943         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\pset"))
 1966 tgl@sss.pgh.pa.us        4944                 :UBC           0 :         COMPLETE_WITH_CS("border", "columns", "csv_fieldsep", "expanded",
                               4945                 :                :                          "fieldsep", "fieldsep_zero", "footer", "format",
                               4946                 :                :                          "linestyle", "null", "numericlocale",
                               4947                 :                :                          "pager", "pager_min_lines",
                               4948                 :                :                          "recordsep", "recordsep_zero",
                               4949                 :                :                          "tableattr", "title", "tuples_only",
                               4950                 :                :                          "unicode_border_linestyle",
                               4951                 :                :                          "unicode_column_linestyle",
                               4952                 :                :                          "unicode_header_linestyle",
                               4953                 :                :                          "xheader_width");
 2032 tgl@sss.pgh.pa.us        4954         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\pset", MatchAny))
                               4955                 :                :     {
 2032 tgl@sss.pgh.pa.us        4956         [ #  # ]:UBC           0 :         if (TailMatchesCS("format"))
 1966                          4957                 :              0 :             COMPLETE_WITH_CS("aligned", "asciidoc", "csv", "html", "latex",
                               4958                 :                :                              "latex-longtable", "troff-ms", "unaligned",
                               4959                 :                :                              "wrapped");
  629 andrew@dunslane.net      4960         [ #  # ]:              0 :         else if (TailMatchesCS("xheader_width"))
                               4961                 :              0 :             COMPLETE_WITH_CS("full", "column", "page");
 2032 tgl@sss.pgh.pa.us        4962         [ #  # ]:              0 :         else if (TailMatchesCS("linestyle"))
                               4963                 :              0 :             COMPLETE_WITH_CS("ascii", "old-ascii", "unicode");
                               4964         [ #  # ]:              0 :         else if (TailMatchesCS("pager"))
                               4965                 :              0 :             COMPLETE_WITH_CS("on", "off", "always");
                               4966         [ #  # ]:              0 :         else if (TailMatchesCS("unicode_border_linestyle|"
                               4967                 :                :                                "unicode_column_linestyle|"
                               4968                 :                :                                "unicode_header_linestyle"))
                               4969                 :              0 :             COMPLETE_WITH_CS("single", "double");
                               4970                 :                :     }
 2032 tgl@sss.pgh.pa.us        4971         [ -  + ]:CBC          10 :     else if (TailMatchesCS("\\unset"))
 3533 fujii@postgresql.org     4972                 :UBC           0 :         matches = complete_from_variables(text, "", "", true);
 2032 tgl@sss.pgh.pa.us        4973         [ +  + ]:CBC          10 :     else if (TailMatchesCS("\\set"))
 3533 fujii@postgresql.org     4974                 :              1 :         matches = complete_from_variables(text, "", "", false);
 2032 tgl@sss.pgh.pa.us        4975         [ +  + ]:              9 :     else if (TailMatchesCS("\\set", MatchAny))
                               4976                 :                :     {
  741 peter@eisentraut.org     4977         [ -  + ]:              1 :         if (TailMatchesCS("AUTOCOMMIT|ON_ERROR_STOP|QUIET|SHOW_ALL_RESULTS|"
                               4978                 :                :                           "SINGLELINE|SINGLESTEP"))
 2032 tgl@sss.pgh.pa.us        4979                 :UBC           0 :             COMPLETE_WITH_CS("on", "off");
 2032 tgl@sss.pgh.pa.us        4980         [ -  + ]:CBC           1 :         else if (TailMatchesCS("COMP_KEYWORD_CASE"))
 2032 tgl@sss.pgh.pa.us        4981                 :UBC           0 :             COMPLETE_WITH_CS("lower", "upper",
                               4982                 :                :                              "preserve-lower", "preserve-upper");
 2032 tgl@sss.pgh.pa.us        4983         [ -  + ]:CBC           1 :         else if (TailMatchesCS("ECHO"))
 2032 tgl@sss.pgh.pa.us        4984                 :UBC           0 :             COMPLETE_WITH_CS("errors", "queries", "all", "none");
 2032 tgl@sss.pgh.pa.us        4985         [ -  + ]:CBC           1 :         else if (TailMatchesCS("ECHO_HIDDEN"))
 2032 tgl@sss.pgh.pa.us        4986                 :UBC           0 :             COMPLETE_WITH_CS("noexec", "off", "on");
 2032 tgl@sss.pgh.pa.us        4987         [ -  + ]:CBC           1 :         else if (TailMatchesCS("HISTCONTROL"))
 2032 tgl@sss.pgh.pa.us        4988                 :UBC           0 :             COMPLETE_WITH_CS("ignorespace", "ignoredups",
                               4989                 :                :                              "ignoreboth", "none");
 2032 tgl@sss.pgh.pa.us        4990         [ -  + ]:CBC           1 :         else if (TailMatchesCS("ON_ERROR_ROLLBACK"))
 2032 tgl@sss.pgh.pa.us        4991                 :UBC           0 :             COMPLETE_WITH_CS("on", "off", "interactive");
 2032 tgl@sss.pgh.pa.us        4992         [ -  + ]:CBC           1 :         else if (TailMatchesCS("SHOW_CONTEXT"))
 2032 tgl@sss.pgh.pa.us        4993                 :UBC           0 :             COMPLETE_WITH_CS("never", "errors", "always");
 2032 tgl@sss.pgh.pa.us        4994         [ +  - ]:CBC           1 :         else if (TailMatchesCS("VERBOSITY"))
 1837                          4995                 :              1 :             COMPLETE_WITH_CS("default", "verbose", "terse", "sqlstate");
                               4996                 :                :     }
 2032                          4997         [ -  + ]:              8 :     else if (TailMatchesCS("\\sf*"))
  805 tgl@sss.pgh.pa.us        4998                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_routines);
 2032 tgl@sss.pgh.pa.us        4999         [ -  + ]:CBC           8 :     else if (TailMatchesCS("\\sv*"))
  805 tgl@sss.pgh.pa.us        5000                 :UBC           0 :         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views);
 1475 bruce@momjian.us         5001         [ +  + ]:CBC           8 :     else if (TailMatchesCS("\\cd|\\e|\\edit|\\g|\\gx|\\i|\\include|"
                               5002                 :                :                            "\\ir|\\include_relative|\\o|\\out|"
                               5003                 :                :                            "\\s|\\w|\\write|\\lo_import"))
                               5004                 :                :     {
 4429 alvherre@alvh.no-ip.     5005                 :              2 :         completion_charp = "\\";
 1543 tgl@sss.pgh.pa.us        5006                 :              2 :         completion_force_quote = false;
 1584                          5007                 :              2 :         matches = rl_completion_matches(text, complete_from_files);
                               5008                 :                :     }
                               5009                 :                : 
                               5010                 :                :     /*
                               5011                 :                :      * Finally, we look through the list of "things", such as TABLE, INDEX and
                               5012                 :                :      * check if that was the previous word. If so, execute the query to get a
                               5013                 :                :      * list of them.
                               5014                 :                :      */
                               5015                 :                :     else
                               5016                 :                :     {
                               5017                 :                :         const pgsql_thing_t *wac;
                               5018                 :                : 
  805                          5019         [ +  + ]:            248 :         for (wac = words_after_create; wac->name != NULL; wac++)
                               5020                 :                :         {
                               5021         [ +  + ]:            246 :             if (pg_strcasecmp(prev_wd, wac->name) == 0)
                               5022                 :                :             {
                               5023         [ -  + ]:              4 :                 if (wac->query)
  805 tgl@sss.pgh.pa.us        5024                 :UBC           0 :                     COMPLETE_WITH_QUERY_LIST(wac->query,
                               5025                 :                :                                              wac->keywords);
  805 tgl@sss.pgh.pa.us        5026         [ +  + ]:CBC           4 :                 else if (wac->vquery)
                               5027                 :              1 :                     COMPLETE_WITH_VERSIONED_QUERY_LIST(wac->vquery,
                               5028                 :                :                                                        wac->keywords);
                               5029         [ +  - ]:              3 :                 else if (wac->squery)
                               5030                 :              3 :                     COMPLETE_WITH_VERSIONED_SCHEMA_QUERY_LIST(wac->squery,
                               5031                 :                :                                                               wac->keywords);
 8768 bruce@momjian.us         5032                 :              4 :                 break;
                               5033                 :                :             }
                               5034                 :                :         }
                               5035                 :                :     }
                               5036                 :                : 
                               5037                 :                :     /*
                               5038                 :                :      * If we still don't have anything to match we have to fabricate some sort
                               5039                 :                :      * of default list. If we were to just return NULL, readline automatically
                               5040                 :                :      * attempts filename completion, and that's usually no good.
                               5041                 :                :      */
 6726                          5042         [ +  + ]:             67 :     if (matches == NULL)
                               5043                 :                :     {
 1748 tgl@sss.pgh.pa.us        5044                 :              2 :         COMPLETE_WITH_CONST(true, "");
                               5045                 :                :         /* Also, prevent Readline from appending stuff to the non-match */
 6726 bruce@momjian.us         5046                 :              2 :         rl_completion_append_character = '\0';
                               5047                 :                : #ifdef HAVE_RL_COMPLETION_SUPPRESS_QUOTE
  819 tgl@sss.pgh.pa.us        5048                 :              2 :         rl_completion_suppress_quote = 1;
                               5049                 :                : #endif
                               5050                 :                :     }
                               5051                 :                : 
                               5052                 :                :     /* free storage */
 3038                          5053                 :             67 :     free(previous_words);
                               5054                 :             67 :     free(words_buffer);
 1563                          5055                 :             67 :     free(text_copy);
  668 peter@eisentraut.org     5056                 :             67 :     free(completion_ref_object);
  805 tgl@sss.pgh.pa.us        5057                 :             67 :     completion_ref_object = NULL;
  668 peter@eisentraut.org     5058                 :             67 :     free(completion_ref_schema);
  805 tgl@sss.pgh.pa.us        5059                 :             67 :     completion_ref_schema = NULL;
                               5060                 :                : 
                               5061                 :                :     /* Return our Grand List O' Matches */
 6726 bruce@momjian.us         5062                 :             67 :     return matches;
                               5063                 :                : }
                               5064                 :                : 
                               5065                 :                : 
                               5066                 :                : /*
                               5067                 :                :  * GENERATOR FUNCTIONS
                               5068                 :                :  *
                               5069                 :                :  * These functions do all the actual work of completing the input. They get
                               5070                 :                :  * passed the text so far and the count how many times they have been called
                               5071                 :                :  * so far with the same text.
                               5072                 :                :  * If you read the above carefully, you'll see that these don't get called
                               5073                 :                :  * directly but through the readline interface.
                               5074                 :                :  * The return value is expected to be the full completion of the text, going
                               5075                 :                :  * through a list each time, or NULL if there are no more matches. The string
                               5076                 :                :  * will be free()'d by readline, so you must run it through strdup() or
                               5077                 :                :  * something of that sort.
                               5078                 :                :  */
                               5079                 :                : 
                               5080                 :                : /*
                               5081                 :                :  * Common routine for create_command_generator and drop_command_generator.
                               5082                 :                :  * Entries that have 'excluded' flags are not returned.
                               5083                 :                :  */
                               5084                 :                : static char *
 4798 itagaki.takahiro@gma     5085                 :              4 : create_or_drop_command_generator(const char *text, int state, bits32 excluded)
                               5086                 :                : {
                               5087                 :                :     static int  list_index,
                               5088                 :                :                 string_length;
                               5089                 :                :     const char *name;
                               5090                 :                : 
                               5091                 :                :     /* If this is the first time for this completion, init some values */
 6726 bruce@momjian.us         5092         [ +  + ]:              4 :     if (state == 0)
                               5093                 :                :     {
                               5094                 :              2 :         list_index = 0;
                               5095                 :              2 :         string_length = strlen(text);
                               5096                 :                :     }
                               5097                 :                : 
                               5098                 :                :     /* find something that matches */
                               5099         [ +  + ]:            102 :     while ((name = words_after_create[list_index++].name))
                               5100                 :                :     {
 4935 tgl@sss.pgh.pa.us        5101         [ +  + ]:            100 :         if ((pg_strncasecmp(name, text, string_length) == 0) &&
 4798 itagaki.takahiro@gma     5102         [ +  - ]:              2 :             !(words_after_create[list_index - 1].flags & excluded))
 4359 peter_e@gmx.net          5103                 :              2 :             return pg_strdup_keyword_case(name, text);
                               5104                 :                :     }
                               5105                 :                :     /* if nothing matches, return NULL */
 6726 bruce@momjian.us         5106                 :              2 :     return NULL;
                               5107                 :                : }
                               5108                 :                : 
                               5109                 :                : /*
                               5110                 :                :  * This one gives you one from a list of things you can put after CREATE
                               5111                 :                :  * as defined above.
                               5112                 :                :  */
                               5113                 :                : static char *
 4798 itagaki.takahiro@gma     5114                 :              2 : create_command_generator(const char *text, int state)
                               5115                 :                : {
                               5116                 :              2 :     return create_or_drop_command_generator(text, state, THING_NO_CREATE);
                               5117                 :                : }
                               5118                 :                : 
                               5119                 :                : /*
                               5120                 :                :  * This function gives you a list of things you can put after a DROP command.
                               5121                 :                :  */
                               5122                 :                : static char *
 6587 alvherre@alvh.no-ip.     5123                 :              2 : drop_command_generator(const char *text, int state)
                               5124                 :                : {
 4798 itagaki.takahiro@gma     5125                 :              2 :     return create_or_drop_command_generator(text, state, THING_NO_DROP);
                               5126                 :                : }
                               5127                 :                : 
                               5128                 :                : /*
                               5129                 :                :  * This function gives you a list of things you can put after an ALTER command.
                               5130                 :                :  */
                               5131                 :                : static char *
 2586 peter_e@gmx.net          5132                 :UBC           0 : alter_command_generator(const char *text, int state)
                               5133                 :                : {
                               5134                 :              0 :     return create_or_drop_command_generator(text, state, THING_NO_ALTER);
                               5135                 :                : }
                               5136                 :                : 
                               5137                 :                : /*
                               5138                 :                :  * These functions generate lists using server queries.
                               5139                 :                :  * They are all wrappers for _complete_from_query.
                               5140                 :                :  */
                               5141                 :                : 
                               5142                 :                : static char *
 6726 bruce@momjian.us         5143                 :CBC         185 : complete_from_query(const char *text, int state)
                               5144                 :                : {
                               5145                 :                :     /* query is assumed to work for any server version */
  805 tgl@sss.pgh.pa.us        5146                 :            185 :     return _complete_from_query(completion_charp, NULL, completion_charpp,
                               5147                 :                :                                 completion_verbatim, text, state);
                               5148                 :                : }
                               5149                 :                : 
                               5150                 :                : static char *
 2232                          5151                 :              2 : complete_from_versioned_query(const char *text, int state)
                               5152                 :                : {
                               5153                 :              2 :     const VersionedQuery *vquery = completion_vquery;
                               5154                 :                : 
                               5155                 :                :     /* Find appropriate array element */
                               5156         [ -  + ]:              2 :     while (pset.sversion < vquery->min_server_version)
 2232 tgl@sss.pgh.pa.us        5157                 :UBC           0 :         vquery++;
                               5158                 :                :     /* Fail completion if server is too old */
 2232 tgl@sss.pgh.pa.us        5159         [ -  + ]:CBC           2 :     if (vquery->query == NULL)
 2232 tgl@sss.pgh.pa.us        5160                 :UBC           0 :         return NULL;
                               5161                 :                : 
  805 tgl@sss.pgh.pa.us        5162                 :CBC           2 :     return _complete_from_query(vquery->query, NULL, completion_charpp,
                               5163                 :                :                                 completion_verbatim, text, state);
                               5164                 :                : }
                               5165                 :                : 
                               5166                 :                : static char *
 6726 bruce@momjian.us         5167                 :             86 : complete_from_schema_query(const char *text, int state)
                               5168                 :                : {
                               5169                 :                :     /* query is assumed to work for any server version */
  805 tgl@sss.pgh.pa.us        5170                 :             86 :     return _complete_from_query(NULL, completion_squery, completion_charpp,
                               5171                 :                :                                 completion_verbatim, text, state);
                               5172                 :                : }
                               5173                 :                : 
                               5174                 :                : static char *
 2232                          5175                 :              8 : complete_from_versioned_schema_query(const char *text, int state)
                               5176                 :                : {
                               5177                 :              8 :     const SchemaQuery *squery = completion_squery;
                               5178                 :                : 
                               5179                 :                :     /* Find appropriate array element */
                               5180         [ -  + ]:              8 :     while (pset.sversion < squery->min_server_version)
 2232 tgl@sss.pgh.pa.us        5181                 :UBC           0 :         squery++;
                               5182                 :                :     /* Fail completion if server is too old */
 2232 tgl@sss.pgh.pa.us        5183         [ -  + ]:CBC           8 :     if (squery->catname == NULL)
 2232 tgl@sss.pgh.pa.us        5184                 :UBC           0 :         return NULL;
                               5185                 :                : 
  805 tgl@sss.pgh.pa.us        5186                 :CBC           8 :     return _complete_from_query(NULL, squery, completion_charpp,
                               5187                 :                :                                 completion_verbatim, text, state);
                               5188                 :                : }
                               5189                 :                : 
                               5190                 :                : 
                               5191                 :                : /*
                               5192                 :                :  * This creates a list of matching things, according to a query described by
                               5193                 :                :  * the initial arguments.  The caller has already done any work needed to
                               5194                 :                :  * select the appropriate query for the server's version.
                               5195                 :                :  *
                               5196                 :                :  * The query can be one of two kinds:
                               5197                 :                :  *
                               5198                 :                :  * 1. A simple query, which must contain a restriction clause of the form
                               5199                 :                :  *      output LIKE '%s'
                               5200                 :                :  * where "output" is the same string that the query returns.  The %s
                               5201                 :                :  * will be replaced by a LIKE pattern to match the already-typed text.
                               5202                 :                :  * There can be a second '%s', which will be replaced by a suitably-escaped
                               5203                 :                :  * version of the string provided in completion_ref_object.  If there is a
                               5204                 :                :  * third '%s', it will be replaced by a suitably-escaped version of the string
                               5205                 :                :  * provided in completion_ref_schema.  Those strings should be set up
                               5206                 :                :  * by calling set_completion_reference or set_completion_reference_verbatim.
                               5207                 :                :  * Simple queries should return a single column of matches.  If "verbatim"
                               5208                 :                :  * is true, the matches are returned as-is; otherwise, they are taken to
                               5209                 :                :  * be SQL identifiers and quoted if necessary.
                               5210                 :                :  *
                               5211                 :                :  * 2. A schema query used for completion of both schema and relation names.
                               5212                 :                :  * This is represented by a SchemaQuery object; see that typedef for details.
                               5213                 :                :  *
                               5214                 :                :  * See top of file for examples of both kinds of query.
                               5215                 :                :  *
                               5216                 :                :  * In addition to the query itself, we accept a null-terminated array of
                               5217                 :                :  * literal keywords, which will be returned if they match the input-so-far
                               5218                 :                :  * (case insensitively).  (These are in addition to keywords specified
                               5219                 :                :  * within the schema_query, if any.)
                               5220                 :                :  *
                               5221                 :                :  * If "verbatim" is true, then we use the given text as-is to match the
                               5222                 :                :  * query results; otherwise we parse it as a possibly-qualified identifier,
                               5223                 :                :  * and reconstruct suitable quoting afterward.
                               5224                 :                :  *
                               5225                 :                :  * "text" and "state" are supplied by Readline.  "text" is the word we are
                               5226                 :                :  * trying to complete.  "state" is zero on first call, nonzero later.
                               5227                 :                :  *
                               5228                 :                :  * readline will call this repeatedly with the same text and varying
                               5229                 :                :  * state.  On each call, we are supposed to return a malloc'd string
                               5230                 :                :  * that is a candidate completion.  Return NULL when done.
                               5231                 :                :  */
                               5232                 :                : static char *
 2232                          5233                 :            281 : _complete_from_query(const char *simple_query,
                               5234                 :                :                      const SchemaQuery *schema_query,
                               5235                 :                :                      const char *const *keywords,
                               5236                 :                :                      bool verbatim,
                               5237                 :                :                      const char *text, int state)
                               5238                 :                : {
                               5239                 :                :     static int  list_index,
                               5240                 :                :                 num_schema_only,
                               5241                 :                :                 num_query_other,
                               5242                 :                :                 num_keywords;
                               5243                 :                :     static PGresult *result = NULL;
                               5244                 :                :     static bool non_empty_object;
                               5245                 :                :     static bool schemaquoted;
                               5246                 :                :     static bool objectquoted;
                               5247                 :                : 
                               5248                 :                :     /*
                               5249                 :                :      * If this is the first time for this completion, we fetch a list of our
                               5250                 :                :      * "things" from the backend.
                               5251                 :                :      */
 6726 bruce@momjian.us         5252         [ +  + ]:            281 :     if (state == 0)
                               5253                 :                :     {
                               5254                 :                :         PQExpBufferData query_buffer;
                               5255                 :                :         char       *schemaname;
                               5256                 :                :         char       *objectname;
                               5257                 :                :         char       *e_object_like;
                               5258                 :                :         char       *e_schemaname;
                               5259                 :                :         char       *e_ref_object;
                               5260                 :                :         char       *e_ref_schema;
                               5261                 :                : 
                               5262                 :                :         /* Reset static state, ensuring no memory leaks */
                               5263                 :             44 :         list_index = 0;
  805 tgl@sss.pgh.pa.us        5264                 :             44 :         num_schema_only = 0;
  803                          5265                 :             44 :         num_query_other = 0;
                               5266                 :             44 :         num_keywords = 0;
  805                          5267                 :             44 :         PQclear(result);
                               5268                 :             44 :         result = NULL;
                               5269                 :                : 
                               5270                 :                :         /* Parse text, splitting into schema and object name if needed */
                               5271         [ +  + ]:             44 :         if (verbatim)
                               5272                 :                :         {
                               5273                 :              8 :             objectname = pg_strdup(text);
                               5274                 :              8 :             schemaname = NULL;
                               5275                 :                :         }
                               5276                 :                :         else
                               5277                 :                :         {
                               5278                 :             36 :             parse_identifier(text,
                               5279                 :                :                              &schemaname, &objectname,
                               5280                 :                :                              &schemaquoted, &objectquoted);
                               5281                 :                :         }
                               5282                 :                : 
                               5283                 :                :         /* Remember whether the user has typed anything in the object part */
                               5284                 :             44 :         non_empty_object = (*objectname != '\0');
                               5285                 :                : 
                               5286                 :                :         /*
                               5287                 :                :          * Convert objectname to a LIKE prefix pattern (e.g. 'foo%'), and set
                               5288                 :                :          * up suitably-escaped copies of all the strings we need.
                               5289                 :                :          */
                               5290                 :             44 :         e_object_like = make_like_pattern(objectname);
                               5291                 :                : 
                               5292         [ +  + ]:             44 :         if (schemaname)
                               5293                 :              3 :             e_schemaname = escape_string(schemaname);
                               5294                 :                :         else
                               5295                 :             41 :             e_schemaname = NULL;
                               5296                 :                : 
                               5297         [ +  + ]:             44 :         if (completion_ref_object)
                               5298                 :             21 :             e_ref_object = escape_string(completion_ref_object);
                               5299                 :                :         else
                               5300                 :             23 :             e_ref_object = NULL;
                               5301                 :                : 
                               5302         [ +  + ]:             44 :         if (completion_ref_schema)
                               5303                 :              1 :             e_ref_schema = escape_string(completion_ref_schema);
                               5304                 :                :         else
                               5305                 :             43 :             e_ref_schema = NULL;
                               5306                 :                : 
 6726 bruce@momjian.us         5307                 :             44 :         initPQExpBuffer(&query_buffer);
                               5308                 :                : 
 2232 tgl@sss.pgh.pa.us        5309         [ +  + ]:             44 :         if (schema_query)
                               5310                 :                :         {
  805                          5311         [ -  + ]:             36 :             Assert(simple_query == NULL);
                               5312                 :                : 
                               5313                 :                :             /*
                               5314                 :                :              * We issue different queries depending on whether the input is
                               5315                 :                :              * already qualified or not.  schema_query gives us the pieces to
                               5316                 :                :              * assemble.
                               5317                 :                :              */
                               5318   [ +  +  -  + ]:             36 :             if (schemaname == NULL || schema_query->namespace == NULL)
                               5319                 :                :             {
                               5320                 :                :                 /* Get unqualified names matching the input-so-far */
                               5321                 :             33 :                 appendPQExpBufferStr(&query_buffer, "SELECT ");
                               5322         [ -  + ]:             33 :                 if (schema_query->use_distinct)
  805 tgl@sss.pgh.pa.us        5323                 :UBC           0 :                     appendPQExpBufferStr(&query_buffer, "DISTINCT ");
  805 tgl@sss.pgh.pa.us        5324                 :CBC          33 :                 appendPQExpBuffer(&query_buffer,
                               5325                 :                :                                   "%s, NULL::pg_catalog.text FROM %s",
                               5326                 :             33 :                                   schema_query->result,
                               5327                 :             33 :                                   schema_query->catname);
                               5328   [ +  +  +  + ]:             33 :                 if (schema_query->refnamespace && completion_ref_schema)
                               5329                 :              1 :                     appendPQExpBufferStr(&query_buffer,
                               5330                 :                :                                          ", pg_catalog.pg_namespace nr");
                               5331                 :             33 :                 appendPQExpBufferStr(&query_buffer, " WHERE ");
                               5332         [ +  - ]:             33 :                 if (schema_query->selcondition)
                               5333                 :             33 :                     appendPQExpBuffer(&query_buffer, "%s AND ",
                               5334                 :             33 :                                       schema_query->selcondition);
                               5335                 :             33 :                 appendPQExpBuffer(&query_buffer, "(%s) LIKE '%s'",
                               5336                 :             33 :                                   schema_query->result,
                               5337                 :                :                                   e_object_like);
                               5338         [ +  + ]:             33 :                 if (schema_query->viscondition)
                               5339                 :             15 :                     appendPQExpBuffer(&query_buffer, " AND %s",
                               5340                 :             15 :                                       schema_query->viscondition);
                               5341         [ +  + ]:             33 :                 if (schema_query->refname)
                               5342                 :                :                 {
                               5343         [ -  + ]:             18 :                     Assert(completion_ref_object);
                               5344                 :             18 :                     appendPQExpBuffer(&query_buffer, " AND %s = '%s'",
                               5345                 :             18 :                                       schema_query->refname, e_ref_object);
                               5346   [ +  -  +  + ]:             18 :                     if (schema_query->refnamespace && completion_ref_schema)
                               5347                 :              1 :                         appendPQExpBuffer(&query_buffer,
                               5348                 :                :                                           " AND %s = nr.oid AND nr.nspname = '%s'",
                               5349                 :              1 :                                           schema_query->refnamespace,
                               5350                 :                :                                           e_ref_schema);
                               5351         [ +  - ]:             17 :                     else if (schema_query->refviscondition)
                               5352                 :             17 :                         appendPQExpBuffer(&query_buffer,
                               5353                 :                :                                           " AND %s",
                               5354                 :             17 :                                           schema_query->refviscondition);
                               5355                 :                :                 }
                               5356                 :                : 
                               5357                 :                :                 /*
                               5358                 :                :                  * When fetching relation names, suppress system catalogs
                               5359                 :                :                  * unless the input-so-far begins with "pg_".  This is a
                               5360                 :                :                  * compromise between not offering system catalogs for
                               5361                 :                :                  * completion at all, and having them swamp the result when
                               5362                 :                :                  * the input is just "p".
                               5363                 :                :                  */
                               5364         [ +  + ]:             33 :                 if (strcmp(schema_query->catname,
                               5365                 :             14 :                            "pg_catalog.pg_class c") == 0 &&
                               5366         [ +  - ]:             14 :                     strncmp(objectname, "pg_", 3) != 0)
                               5367                 :                :                 {
                               5368                 :             14 :                     appendPQExpBufferStr(&query_buffer,
                               5369                 :                :                                          " AND c.relnamespace <> (SELECT oid FROM"
                               5370                 :                :                                          " pg_catalog.pg_namespace WHERE nspname = 'pg_catalog')");
                               5371                 :                :                 }
                               5372                 :                : 
                               5373                 :                :                 /*
                               5374                 :                :                  * If the target object type can be schema-qualified, add in
                               5375                 :                :                  * schema names matching the input-so-far.
                               5376                 :                :                  */
                               5377         [ +  + ]:             33 :                 if (schema_query->namespace)
                               5378                 :                :                 {
                               5379                 :             15 :                     appendPQExpBuffer(&query_buffer, "\nUNION ALL\n"
                               5380                 :                :                                       "SELECT NULL::pg_catalog.text, n.nspname "
                               5381                 :                :                                       "FROM pg_catalog.pg_namespace n "
                               5382                 :                :                                       "WHERE n.nspname LIKE '%s'",
                               5383                 :                :                                       e_object_like);
                               5384                 :                : 
                               5385                 :                :                     /*
                               5386                 :                :                      * Likewise, suppress system schemas unless the
                               5387                 :                :                      * input-so-far begins with "pg_".
                               5388                 :                :                      */
                               5389         [ +  - ]:             15 :                     if (strncmp(objectname, "pg_", 3) != 0)
                               5390                 :             15 :                         appendPQExpBufferStr(&query_buffer,
                               5391                 :                :                                              " AND n.nspname NOT LIKE E'pg\\\\_%'");
                               5392                 :                : 
                               5393                 :                :                     /*
                               5394                 :                :                      * Since we're matching these schema names to the object
                               5395                 :                :                      * name, handle their quoting using the object name's
                               5396                 :                :                      * quoting state.
                               5397                 :                :                      */
                               5398                 :             15 :                     schemaquoted = objectquoted;
                               5399                 :                :                 }
                               5400                 :                :             }
                               5401                 :                :             else
                               5402                 :                :             {
                               5403                 :                :                 /* Input is qualified, so produce only qualified names */
                               5404                 :              3 :                 appendPQExpBufferStr(&query_buffer, "SELECT ");
                               5405         [ +  + ]:              3 :                 if (schema_query->use_distinct)
                               5406                 :              1 :                     appendPQExpBufferStr(&query_buffer, "DISTINCT ");
                               5407                 :              3 :                 appendPQExpBuffer(&query_buffer, "%s, n.nspname "
                               5408                 :                :                                   "FROM %s, pg_catalog.pg_namespace n",
                               5409                 :              3 :                                   schema_query->result,
                               5410                 :              3 :                                   schema_query->catname);
                               5411   [ -  +  -  - ]:              3 :                 if (schema_query->refnamespace && completion_ref_schema)
  805 tgl@sss.pgh.pa.us        5412                 :UBC           0 :                     appendPQExpBufferStr(&query_buffer,
                               5413                 :                :                                          ", pg_catalog.pg_namespace nr");
  805 tgl@sss.pgh.pa.us        5414                 :CBC           3 :                 appendPQExpBuffer(&query_buffer, " WHERE %s = n.oid AND ",
                               5415                 :              3 :                                   schema_query->namespace);
                               5416         [ +  - ]:              3 :                 if (schema_query->selcondition)
                               5417                 :              3 :                     appendPQExpBuffer(&query_buffer, "%s AND ",
                               5418                 :              3 :                                       schema_query->selcondition);
                               5419                 :              3 :                 appendPQExpBuffer(&query_buffer, "(%s) LIKE '%s' AND ",
                               5420                 :              3 :                                   schema_query->result,
                               5421                 :                :                                   e_object_like);
                               5422                 :              3 :                 appendPQExpBuffer(&query_buffer, "n.nspname = '%s'",
                               5423                 :                :                                   e_schemaname);
                               5424         [ +  + ]:              3 :                 if (schema_query->refname)
                               5425                 :                :                 {
                               5426         [ -  + ]:              1 :                     Assert(completion_ref_object);
                               5427                 :              1 :                     appendPQExpBuffer(&query_buffer, " AND %s = '%s'",
                               5428                 :              1 :                                       schema_query->refname, e_ref_object);
                               5429   [ -  +  -  - ]:              1 :                     if (schema_query->refnamespace && completion_ref_schema)
  805 tgl@sss.pgh.pa.us        5430                 :UBC           0 :                         appendPQExpBuffer(&query_buffer,
                               5431                 :                :                                           " AND %s = nr.oid AND nr.nspname = '%s'",
                               5432                 :              0 :                                           schema_query->refnamespace,
                               5433                 :                :                                           e_ref_schema);
  805 tgl@sss.pgh.pa.us        5434         [ -  + ]:CBC           1 :                     else if (schema_query->refviscondition)
  805 tgl@sss.pgh.pa.us        5435                 :UBC           0 :                         appendPQExpBuffer(&query_buffer,
                               5436                 :                :                                           " AND %s",
                               5437                 :              0 :                                           schema_query->refviscondition);
                               5438                 :                :                 }
                               5439                 :                :             }
                               5440                 :                :         }
                               5441                 :                :         else
                               5442                 :                :         {
 2232 tgl@sss.pgh.pa.us        5443         [ -  + ]:CBC           8 :             Assert(simple_query);
                               5444                 :                :             /* simple_query is an sprintf-style format string */
                               5445                 :              8 :             appendPQExpBuffer(&query_buffer, simple_query,
                               5446                 :                :                               e_object_like,
                               5447                 :                :                               e_ref_object, e_ref_schema);
                               5448                 :                :         }
                               5449                 :                : 
                               5450                 :                :         /* Limit the number of records in the result */
 6726 bruce@momjian.us         5451                 :             44 :         appendPQExpBuffer(&query_buffer, "\nLIMIT %d",
                               5452                 :                :                           completion_max_records);
                               5453                 :                : 
                               5454                 :                :         /* Finally, we can issue the query */
                               5455                 :             44 :         result = exec_query(query_buffer.data);
                               5456                 :                : 
                               5457                 :                :         /* Clean up */
                               5458                 :             44 :         termPQExpBuffer(&query_buffer);
  632 tgl@sss.pgh.pa.us        5459                 :             44 :         free(schemaname);
                               5460                 :             44 :         free(objectname);
  805                          5461                 :             44 :         free(e_object_like);
  668 peter@eisentraut.org     5462                 :             44 :         free(e_schemaname);
                               5463                 :             44 :         free(e_ref_object);
                               5464                 :             44 :         free(e_ref_schema);
                               5465                 :                :     }
                               5466                 :                : 
                               5467                 :                :     /* Return the next result, if any, but not if the query failed */
 6726 bruce@momjian.us         5468   [ +  -  +  - ]:            281 :     if (result && PQresultStatus(result) == PGRES_TUPLES_OK)
                               5469                 :                :     {
                               5470                 :                :         int         nskip;
                               5471                 :                : 
  805 tgl@sss.pgh.pa.us        5472         [ +  + ]:            281 :         while (list_index < PQntuples(result))
                               5473                 :                :         {
                               5474                 :            212 :             const char *item = NULL;
                               5475                 :            212 :             const char *nsp = NULL;
                               5476                 :                : 
                               5477         [ +  + ]:            212 :             if (!PQgetisnull(result, list_index, 0))
                               5478                 :            211 :                 item = PQgetvalue(result, list_index, 0);
                               5479   [ +  +  +  + ]:            245 :             if (PQnfields(result) > 1 &&
                               5480                 :             33 :                 !PQgetisnull(result, list_index, 1))
                               5481                 :              4 :                 nsp = PQgetvalue(result, list_index, 1);
                               5482                 :            212 :             list_index++;
                               5483                 :                : 
                               5484                 :                :             /* In verbatim mode, we return all the items as-is */
                               5485         [ +  + ]:            212 :             if (verbatim)
                               5486                 :                :             {
  803                          5487                 :            181 :                 num_query_other++;
 6726 bruce@momjian.us         5488                 :            181 :                 return pg_strdup(item);
                               5489                 :                :             }
                               5490                 :                : 
                               5491                 :                :             /*
                               5492                 :                :              * In normal mode, a name requiring quoting will be returned only
                               5493                 :                :              * if the input was empty or quoted.  Otherwise the user might see
                               5494                 :                :              * completion inserting a quote she didn't type, which is
                               5495                 :                :              * surprising.  This restriction also dodges some odd behaviors of
                               5496                 :                :              * some versions of readline/libedit.
                               5497                 :                :              */
  805 tgl@sss.pgh.pa.us        5498         [ +  + ]:             31 :             if (non_empty_object)
                               5499                 :                :             {
                               5500   [ +  +  +  +  :             26 :                 if (item && !objectquoted && identifier_needs_quotes(item))
                                              -  + ]
  805 tgl@sss.pgh.pa.us        5501                 :UBC           0 :                     continue;
  805 tgl@sss.pgh.pa.us        5502   [ +  +  +  -  :CBC          26 :                 if (nsp && !schemaquoted && identifier_needs_quotes(nsp))
                                              -  + ]
  805 tgl@sss.pgh.pa.us        5503                 :UBC           0 :                     continue;
                               5504                 :                :             }
                               5505                 :                : 
                               5506                 :                :             /* Count schema-only results for hack below */
  805 tgl@sss.pgh.pa.us        5507   [ +  +  +  - ]:CBC          31 :             if (item == NULL && nsp != NULL)
                               5508                 :              1 :                 num_schema_only++;
                               5509                 :                :             else
  803                          5510                 :             30 :                 num_query_other++;
                               5511                 :                : 
  805                          5512                 :             31 :             return requote_identifier(nsp, item, schemaquoted, objectquoted);
                               5513                 :                :         }
                               5514                 :                : 
                               5515                 :                :         /*
                               5516                 :                :          * When the query result is exhausted, check for hard-wired keywords.
                               5517                 :                :          * These will only be returned if they match the input-so-far,
                               5518                 :                :          * ignoring case.
                               5519                 :                :          */
                               5520                 :             69 :         nskip = list_index - PQntuples(result);
                               5521   [ +  +  +  + ]:             69 :         if (schema_query && schema_query->keywords)
                               5522                 :                :         {
                               5523                 :              2 :             const char *const *itemp = schema_query->keywords;
                               5524                 :                : 
                               5525         [ +  + ]:              9 :             while (*itemp)
                               5526                 :                :             {
                               5527                 :              8 :                 const char *item = *itemp++;
                               5528                 :                : 
                               5529         [ +  + ]:              8 :                 if (nskip-- > 0)
                               5530                 :              1 :                     continue;
                               5531                 :              7 :                 list_index++;
                               5532         [ +  + ]:              7 :                 if (pg_strncasecmp(text, item, strlen(text)) == 0)
                               5533                 :                :                 {
  803                          5534                 :              1 :                     num_keywords++;
  795                          5535                 :              1 :                     return pg_strdup_keyword_case(item, text);
                               5536                 :                :                 }
                               5537                 :                :             }
                               5538                 :                :         }
  805                          5539         [ +  + ]:             68 :         if (keywords)
                               5540                 :                :         {
                               5541                 :             44 :             const char *const *itemp = keywords;
                               5542                 :                : 
                               5543         [ +  + ]:            115 :             while (*itemp)
                               5544                 :                :             {
                               5545                 :             95 :                 const char *item = *itemp++;
                               5546                 :                : 
                               5547         [ +  + ]:             95 :                 if (nskip-- > 0)
                               5548                 :             36 :                     continue;
                               5549                 :             59 :                 list_index++;
                               5550         [ +  + ]:             59 :                 if (pg_strncasecmp(text, item, strlen(text)) == 0)
                               5551                 :                :                 {
  803                          5552                 :             24 :                     num_keywords++;
  795                          5553                 :             24 :                     return pg_strdup_keyword_case(item, text);
                               5554                 :                :                 }
                               5555                 :                :             }
                               5556                 :                :         }
                               5557                 :                :     }
                               5558                 :                : 
                               5559                 :                :     /*
                               5560                 :                :      * Hack: if we returned only bare schema names, don't let Readline add a
                               5561                 :                :      * space afterwards.  Otherwise the schema will stop being part of the
                               5562                 :                :      * completion subject text, which is not what we want.
                               5563                 :                :      */
  803                          5564   [ +  +  +  -  :             44 :     if (num_schema_only > 0 && num_query_other == 0 && num_keywords == 0)
                                              +  - ]
  805                          5565                 :              1 :         rl_completion_append_character = '\0';
                               5566                 :                : 
                               5567                 :                :     /* No more matches, so free the result structure and return null */
 6726 bruce@momjian.us         5568                 :             44 :     PQclear(result);
                               5569                 :             44 :     result = NULL;
                               5570                 :             44 :     return NULL;
                               5571                 :                : }
                               5572                 :                : 
                               5573                 :                : 
                               5574                 :                : /*
                               5575                 :                :  * Set up completion_ref_object and completion_ref_schema
                               5576                 :                :  * by parsing the given word.  These variables can then be
                               5577                 :                :  * used in a query passed to _complete_from_query.
                               5578                 :                :  */
                               5579                 :                : static void
  805 tgl@sss.pgh.pa.us        5580                 :             19 : set_completion_reference(const char *word)
                               5581                 :                : {
                               5582                 :                :     bool        schemaquoted,
                               5583                 :                :                 objectquoted;
                               5584                 :                : 
                               5585                 :             19 :     parse_identifier(word,
                               5586                 :                :                      &completion_ref_schema, &completion_ref_object,
                               5587                 :                :                      &schemaquoted, &objectquoted);
                               5588                 :             19 : }
                               5589                 :                : 
                               5590                 :                : /*
                               5591                 :                :  * Set up completion_ref_object when it should just be
                               5592                 :                :  * the given word verbatim.
                               5593                 :                :  */
                               5594                 :                : static void
  795                          5595                 :              2 : set_completion_reference_verbatim(const char *word)
                               5596                 :                : {
                               5597                 :              2 :     completion_ref_schema = NULL;
                               5598                 :              2 :     completion_ref_object = pg_strdup(word);
                               5599                 :              2 : }
                               5600                 :                : 
                               5601                 :                : 
                               5602                 :                : /*
                               5603                 :                :  * This function returns in order one of a fixed, NULL pointer terminated list
                               5604                 :                :  * of strings (if matching). This can be used if there are only a fixed number
                               5605                 :                :  * SQL words that can appear at certain spot.
                               5606                 :                :  */
                               5607                 :                : static char *
 6726 bruce@momjian.us         5608                 :             32 : complete_from_list(const char *text, int state)
                               5609                 :                : {
                               5610                 :                :     static int  string_length,
                               5611                 :                :                 list_index,
                               5612                 :                :                 matches;
                               5613                 :                :     static bool casesensitive;
                               5614                 :                :     const char *item;
                               5615                 :                : 
                               5616                 :                :     /* need to have a list */
 4139 andrew@dunslane.net      5617         [ -  + ]:             32 :     Assert(completion_charpp != NULL);
                               5618                 :                : 
                               5619                 :                :     /* Initialization */
 6726 bruce@momjian.us         5620         [ +  + ]:             32 :     if (state == 0)
                               5621                 :                :     {
                               5622                 :             13 :         list_index = 0;
                               5623                 :             13 :         string_length = strlen(text);
 4456 peter_e@gmx.net          5624                 :             13 :         casesensitive = completion_case_sensitive;
 6726 bruce@momjian.us         5625                 :             13 :         matches = 0;
                               5626                 :                :     }
                               5627                 :                : 
                               5628         [ +  + ]:            506 :     while ((item = completion_charpp[list_index++]))
                               5629                 :                :     {
                               5630                 :                :         /* First pass is case sensitive */
                               5631   [ +  +  +  + ]:            460 :         if (casesensitive && strncmp(text, item, string_length) == 0)
                               5632                 :                :         {
                               5633                 :              4 :             matches++;
                               5634                 :              4 :             return pg_strdup(item);
                               5635                 :                :         }
                               5636                 :                : 
                               5637                 :                :         /* Second pass is case insensitive, don't bother counting matches */
                               5638   [ +  +  +  + ]:            456 :         if (!casesensitive && pg_strncasecmp(text, item, string_length) == 0)
                               5639                 :                :         {
 4456 peter_e@gmx.net          5640         [ +  + ]:             14 :             if (completion_case_sensitive)
                               5641                 :              1 :                 return pg_strdup(item);
                               5642                 :                :             else
                               5643                 :                : 
                               5644                 :                :                 /*
                               5645                 :                :                  * If case insensitive matching was requested initially,
                               5646                 :                :                  * adjust the case according to setting.
                               5647                 :                :                  */
 4359                          5648                 :             13 :                 return pg_strdup_keyword_case(item, text);
                               5649                 :                :         }
                               5650                 :                :     }
                               5651                 :                : 
                               5652                 :                :     /*
                               5653                 :                :      * No matches found. If we're not case insensitive already, lets switch to
                               5654                 :                :      * being case insensitive and try again
                               5655                 :                :      */
 6726 bruce@momjian.us         5656   [ +  +  +  + ]:             14 :     if (casesensitive && matches == 0)
                               5657                 :                :     {
                               5658                 :              1 :         casesensitive = false;
                               5659                 :              1 :         list_index = 0;
                               5660                 :              1 :         state++;
 6668 neilc@samurai.com        5661                 :              1 :         return complete_from_list(text, state);
                               5662                 :                :     }
                               5663                 :                : 
                               5664                 :                :     /* If no more matches, return null. */
 6726 bruce@momjian.us         5665                 :             13 :     return NULL;
                               5666                 :                : }
                               5667                 :                : 
                               5668                 :                : 
                               5669                 :                : /*
                               5670                 :                :  * This function returns one fixed string the first time even if it doesn't
                               5671                 :                :  * match what's there, and nothing the second time.  The string
                               5672                 :                :  * to be used must be in completion_charp.
                               5673                 :                :  *
                               5674                 :                :  * If the given string is "", this has the effect of preventing readline
                               5675                 :                :  * from doing any completion.  (Without this, readline tries to do filename
                               5676                 :                :  * completion which is seldom the right thing.)
                               5677                 :                :  *
                               5678                 :                :  * If the given string is not empty, readline will replace whatever the
                               5679                 :                :  * user typed with that string.  This behavior might be useful if it's
                               5680                 :                :  * completely certain that we know what must appear at a certain spot,
                               5681                 :                :  * so that it's okay to overwrite misspellings.  In practice, given the
                               5682                 :                :  * relatively lame parsing technology used in this file, the level of
                               5683                 :                :  * certainty is seldom that high, so that you probably don't want to
                               5684                 :                :  * use this.  Use complete_from_list with a one-element list instead;
                               5685                 :                :  * that won't try to auto-correct "misspellings".
                               5686                 :                :  */
                               5687                 :                : static char *
                               5688                 :              4 : complete_from_const(const char *text, int state)
                               5689                 :                : {
 4139 andrew@dunslane.net      5690         [ -  + ]:              4 :     Assert(completion_charp != NULL);
 6726 bruce@momjian.us         5691         [ +  + ]:              4 :     if (state == 0)
                               5692                 :                :     {
 4456 peter_e@gmx.net          5693         [ +  - ]:              2 :         if (completion_case_sensitive)
                               5694                 :              2 :             return pg_strdup(completion_charp);
                               5695                 :                :         else
                               5696                 :                : 
                               5697                 :                :             /*
                               5698                 :                :              * If case insensitive matching was requested initially, adjust
                               5699                 :                :              * the case according to setting.
                               5700                 :                :              */
 4359 peter_e@gmx.net          5701                 :UBC           0 :             return pg_strdup_keyword_case(completion_charp, text);
                               5702                 :                :     }
                               5703                 :                :     else
 6726 bruce@momjian.us         5704                 :CBC           2 :         return NULL;
                               5705                 :                : }
                               5706                 :                : 
                               5707                 :                : 
                               5708                 :                : /*
                               5709                 :                :  * This function appends the variable name with prefix and suffix to
                               5710                 :                :  * the variable names array.
                               5711                 :                :  */
                               5712                 :                : static void
 3533 fujii@postgresql.org     5713                 :            112 : append_variable_names(char ***varnames, int *nvars,
                               5714                 :                :                       int *maxvars, const char *varname,
                               5715                 :                :                       const char *prefix, const char *suffix)
                               5716                 :                : {
                               5717         [ -  + ]:            112 :     if (*nvars >= *maxvars)
                               5718                 :                :     {
 3533 fujii@postgresql.org     5719                 :UBC           0 :         *maxvars *= 2;
 3435 tgl@sss.pgh.pa.us        5720                 :              0 :         *varnames = (char **) pg_realloc(*varnames,
                               5721                 :              0 :                                          ((*maxvars) + 1) * sizeof(char *));
                               5722                 :                :     }
                               5723                 :                : 
 3533 fujii@postgresql.org     5724                 :CBC         112 :     (*varnames)[(*nvars)++] = psprintf("%s%s%s", prefix, varname, suffix);
                               5725                 :            112 : }
                               5726                 :                : 
                               5727                 :                : 
                               5728                 :                : /*
                               5729                 :                :  * This function supports completion with the name of a psql variable.
                               5730                 :                :  * The variable names can be prefixed and suffixed with additional text
                               5731                 :                :  * to support quoting usages. If need_value is true, only variables
                               5732                 :                :  * that are currently set are included; otherwise, special variables
                               5733                 :                :  * (those that have hooks) are included even if currently unset.
                               5734                 :                :  */
                               5735                 :                : static char **
                               5736                 :              3 : complete_from_variables(const char *text, const char *prefix, const char *suffix,
                               5737                 :                :                         bool need_value)
                               5738                 :                : {
                               5739                 :                :     char      **matches;
                               5740                 :                :     char      **varnames;
 4935 tgl@sss.pgh.pa.us        5741                 :              3 :     int         nvars = 0;
                               5742                 :              3 :     int         maxvars = 100;
                               5743                 :                :     int         i;
                               5744                 :                :     struct _variable *ptr;
                               5745                 :                : 
 4457 peter_e@gmx.net          5746                 :              3 :     varnames = (char **) pg_malloc((maxvars + 1) * sizeof(char *));
                               5747                 :                : 
 4935 tgl@sss.pgh.pa.us        5748         [ +  + ]:            117 :     for (ptr = pset.vars->next; ptr; ptr = ptr->next)
                               5749                 :                :     {
 3533 fujii@postgresql.org     5750   [ +  +  +  + ]:            114 :         if (need_value && !(ptr->value))
                               5751                 :              2 :             continue;
                               5752                 :            112 :         append_variable_names(&varnames, &nvars, &maxvars, ptr->name,
                               5753                 :                :                               prefix, suffix);
                               5754                 :                :     }
                               5755                 :                : 
 4935 tgl@sss.pgh.pa.us        5756                 :              3 :     varnames[nvars] = NULL;
 4326 bruce@momjian.us         5757                 :              3 :     COMPLETE_WITH_LIST_CS((const char *const *) varnames);
                               5758                 :                : 
 4935 tgl@sss.pgh.pa.us        5759         [ +  + ]:            115 :     for (i = 0; i < nvars; i++)
 4457 peter_e@gmx.net          5760                 :            112 :         free(varnames[i]);
 4935 tgl@sss.pgh.pa.us        5761                 :              3 :     free(varnames);
                               5762                 :                : 
                               5763                 :              3 :     return matches;
                               5764                 :                : }
                               5765                 :                : 
                               5766                 :                : 
                               5767                 :                : /*
                               5768                 :                :  * This function wraps rl_filename_completion_function() to strip quotes from
                               5769                 :                :  * the input before searching for matches and to quote any matches for which
                               5770                 :                :  * the consuming command will require it.
                               5771                 :                :  *
                               5772                 :                :  * Caller must set completion_charp to a zero- or one-character string
                               5773                 :                :  * containing the escape character.  This is necessary since \copy has no
                               5774                 :                :  * escape character, but every other backslash command recognizes "\" as an
                               5775                 :                :  * escape character.
                               5776                 :                :  *
                               5777                 :                :  * Caller must also set completion_force_quote to indicate whether to force
                               5778                 :                :  * quotes around the result.  (The SQL COPY command requires that.)
                               5779                 :                :  */
                               5780                 :                : static char *
 4429 alvherre@alvh.no-ip.     5781                 :             16 : complete_from_files(const char *text, int state)
                               5782                 :                : {
                               5783                 :                : #ifdef USE_FILENAME_QUOTING_FUNCTIONS
                               5784                 :                : 
                               5785                 :                :     /*
                               5786                 :                :      * If we're using a version of Readline that supports filename quoting
                               5787                 :                :      * hooks, rely on those, and invoke rl_filename_completion_function()
                               5788                 :                :      * without messing with its arguments.  Readline does stuff internally
                               5789                 :                :      * that does not work well at all if we try to handle dequoting here.
                               5790                 :                :      * Instead, Readline will call quote_file_name() and dequote_file_name()
                               5791                 :                :      * (see below) at appropriate times.
                               5792                 :                :      *
                               5793                 :                :      * ... or at least, mostly it will.  There are some paths involving
                               5794                 :                :      * unmatched file names in which Readline never calls quote_file_name(),
                               5795                 :                :      * and if left to its own devices it will incorrectly append a quote
                               5796                 :                :      * anyway.  Set rl_completion_suppress_quote to prevent that.  If we do
                               5797                 :                :      * get to quote_file_name(), we'll clear this again.  (Yes, this seems
                               5798                 :                :      * like it's working around Readline bugs.)
                               5799                 :                :      */
                               5800                 :                : #ifdef HAVE_RL_COMPLETION_SUPPRESS_QUOTE
 1543 tgl@sss.pgh.pa.us        5801                 :             16 :     rl_completion_suppress_quote = 1;
                               5802                 :                : #endif
                               5803                 :                : 
                               5804                 :                :     /* If user typed a quote, force quoting (never remove user's quote) */
                               5805         [ -  + ]:             16 :     if (*text == '\'')
 1543 tgl@sss.pgh.pa.us        5806                 :UBC           0 :         completion_force_quote = true;
                               5807                 :                : 
 1543 tgl@sss.pgh.pa.us        5808                 :CBC          16 :     return rl_filename_completion_function(text, state);
                               5809                 :                : #else
                               5810                 :                : 
                               5811                 :                :     /*
                               5812                 :                :      * Otherwise, we have to do the best we can.
                               5813                 :                :      */
                               5814                 :                :     static const char *unquoted_text;
                               5815                 :                :     char       *unquoted_match;
                               5816                 :                :     char       *ret = NULL;
                               5817                 :                : 
                               5818                 :                :     /* If user typed a quote, force quoting (never remove user's quote) */
                               5819                 :                :     if (*text == '\'')
                               5820                 :                :         completion_force_quote = true;
                               5821                 :                : 
                               5822                 :                :     if (state == 0)
                               5823                 :                :     {
                               5824                 :                :         /* Initialization: stash the unquoted input. */
                               5825                 :                :         unquoted_text = strtokx(text, "", NULL, "'", *completion_charp,
                               5826                 :                :                                 false, true, pset.encoding);
                               5827                 :                :         /* expect a NULL return for the empty string only */
                               5828                 :                :         if (!unquoted_text)
                               5829                 :                :         {
                               5830                 :                :             Assert(*text == '\0');
                               5831                 :                :             unquoted_text = text;
                               5832                 :                :         }
                               5833                 :                :     }
                               5834                 :                : 
                               5835                 :                :     unquoted_match = rl_filename_completion_function(unquoted_text, state);
                               5836                 :                :     if (unquoted_match)
                               5837                 :                :     {
                               5838                 :                :         struct stat statbuf;
                               5839                 :                :         bool        is_dir = (stat(unquoted_match, &statbuf) == 0 &&
                               5840                 :                :                               S_ISDIR(statbuf.st_mode) != 0);
                               5841                 :                : 
                               5842                 :                :         /* Re-quote the result, if needed. */
                               5843                 :                :         ret = quote_if_needed(unquoted_match, " \t\r\n\"`",
                               5844                 :                :                               '\'', *completion_charp,
                               5845                 :                :                               completion_force_quote,
                               5846                 :                :                               pset.encoding);
                               5847                 :                :         if (ret)
                               5848                 :                :             free(unquoted_match);
                               5849                 :                :         else
                               5850                 :                :             ret = unquoted_match;
                               5851                 :                : 
                               5852                 :                :         /*
                               5853                 :                :          * If it's a directory, replace trailing quote with a slash; this is
                               5854                 :                :          * usually more convenient.  (If we didn't quote, leave this to
                               5855                 :                :          * libedit.)
                               5856                 :                :          */
                               5857                 :                :         if (*ret == '\'' && is_dir)
                               5858                 :                :         {
                               5859                 :                :             char       *retend = ret + strlen(ret) - 1;
                               5860                 :                : 
                               5861                 :                :             Assert(*retend == '\'');
                               5862                 :                :             *retend = '/';
                               5863                 :                :             /* Prevent libedit from adding a space, too */
                               5864                 :                :             rl_completion_append_character = '\0';
                               5865                 :                :         }
                               5866                 :                :     }
                               5867                 :                : 
                               5868                 :                :     return ret;
                               5869                 :                : #endif                          /* USE_FILENAME_QUOTING_FUNCTIONS */
                               5870                 :                : }
                               5871                 :                : 
                               5872                 :                : 
                               5873                 :                : /* HELPER FUNCTIONS */
                               5874                 :                : 
                               5875                 :                : 
                               5876                 :                : /*
                               5877                 :                :  * Make a pg_strdup copy of s and convert the case according to
                               5878                 :                :  * COMP_KEYWORD_CASE setting, using ref as the text that was already entered.
                               5879                 :                :  */
                               5880                 :                : static char *
 4359 peter_e@gmx.net          5881                 :             40 : pg_strdup_keyword_case(const char *s, const char *ref)
                               5882                 :                : {
                               5883                 :                :     char       *ret,
                               5884                 :                :                *p;
 4456                          5885                 :             40 :     unsigned char first = ref[0];
                               5886                 :                : 
 4359                          5887                 :             40 :     ret = pg_strdup(s);
                               5888                 :                : 
 3392 tgl@sss.pgh.pa.us        5889         [ +  + ]:             40 :     if (pset.comp_case == PSQL_COMP_CASE_LOWER ||
                               5890         [ +  + ]:             34 :         ((pset.comp_case == PSQL_COMP_CASE_PRESERVE_LOWER ||
 2489                          5891   [ +  +  +  + ]:             34 :           pset.comp_case == PSQL_COMP_CASE_PRESERVE_UPPER) && islower(first)) ||
 3392                          5892   [ -  +  -  - ]:             26 :         (pset.comp_case == PSQL_COMP_CASE_PRESERVE_LOWER && !isalpha(first)))
                               5893                 :                :     {
 4359 peter_e@gmx.net          5894         [ +  + ]:            122 :         for (p = ret; *p; p++)
                               5895                 :            108 :             *p = pg_tolower((unsigned char) *p);
                               5896                 :                :     }
                               5897                 :                :     else
                               5898                 :                :     {
                               5899         [ +  + ]:            241 :         for (p = ret; *p; p++)
                               5900                 :            215 :             *p = pg_toupper((unsigned char) *p);
                               5901                 :                :     }
                               5902                 :                : 
                               5903                 :             40 :     return ret;
                               5904                 :                : }
                               5905                 :                : 
                               5906                 :                : 
                               5907                 :                : /*
                               5908                 :                :  * escape_string - Escape argument for use as string literal.
                               5909                 :                :  *
                               5910                 :                :  * The returned value has to be freed.
                               5911                 :                :  */
                               5912                 :                : static char *
 3141 andres@anarazel.de       5913                 :             71 : escape_string(const char *text)
                               5914                 :                : {
                               5915                 :                :     size_t      text_length;
                               5916                 :                :     char       *result;
                               5917                 :                : 
                               5918                 :             71 :     text_length = strlen(text);
                               5919                 :                : 
                               5920                 :             71 :     result = pg_malloc(text_length * 2 + 1);
                               5921                 :             71 :     PQescapeStringConn(pset.db, result, text, text_length, NULL);
                               5922                 :                : 
                               5923                 :             71 :     return result;
                               5924                 :                : }
                               5925                 :                : 
                               5926                 :                : 
                               5927                 :                : /*
                               5928                 :                :  * make_like_pattern - Convert argument to a LIKE prefix pattern.
                               5929                 :                :  *
                               5930                 :                :  * We escape _ and % in the given text by backslashing, append a % to
                               5931                 :                :  * represent "any subsequent characters", and then pass the string through
                               5932                 :                :  * escape_string() so it's ready to insert in a query.  The result needs
                               5933                 :                :  * to be freed.
                               5934                 :                :  */
                               5935                 :                : static char *
  805 tgl@sss.pgh.pa.us        5936                 :             44 : make_like_pattern(const char *word)
                               5937                 :                : {
                               5938                 :                :     char       *result;
                               5939                 :             44 :     char       *buffer = pg_malloc(strlen(word) * 2 + 2);
                               5940                 :             44 :     char       *bptr = buffer;
                               5941                 :                : 
                               5942         [ +  + ]:            180 :     while (*word)
                               5943                 :                :     {
                               5944   [ +  +  -  + ]:            136 :         if (*word == '_' || *word == '%')
                               5945                 :              2 :             *bptr++ = '\\';
                               5946         [ -  + ]:            136 :         if (IS_HIGHBIT_SET(*word))
                               5947                 :                :         {
                               5948                 :                :             /*
                               5949                 :                :              * Transfer multibyte characters without further processing, to
                               5950                 :                :              * avoid getting confused in unsafe client encodings.
                               5951                 :                :              */
  805 tgl@sss.pgh.pa.us        5952                 :UBC           0 :             int         chlen = PQmblenBounded(word, pset.encoding);
                               5953                 :                : 
                               5954         [ #  # ]:              0 :             while (chlen-- > 0)
                               5955                 :              0 :                 *bptr++ = *word++;
                               5956                 :                :         }
                               5957                 :                :         else
  805 tgl@sss.pgh.pa.us        5958                 :CBC         136 :             *bptr++ = *word++;
                               5959                 :                :     }
                               5960                 :             44 :     *bptr++ = '%';
                               5961                 :             44 :     *bptr = '\0';
                               5962                 :                : 
                               5963                 :             44 :     result = escape_string(buffer);
                               5964                 :             44 :     free(buffer);
                               5965                 :             44 :     return result;
                               5966                 :                : }
                               5967                 :                : 
                               5968                 :                : 
                               5969                 :                : /*
                               5970                 :                :  * parse_identifier - Parse a possibly-schema-qualified SQL identifier.
                               5971                 :                :  *
                               5972                 :                :  * This involves splitting off the schema name if present, de-quoting,
                               5973                 :                :  * and downcasing any unquoted text.  We are a bit laxer than the backend
                               5974                 :                :  * in that we allow just portions of a name to be quoted --- that's because
                               5975                 :                :  * psql metacommands have traditionally behaved that way.
                               5976                 :                :  *
                               5977                 :                :  * Outputs are a malloc'd schema name (NULL if none), malloc'd object name,
                               5978                 :                :  * and booleans telling whether any part of the schema and object name was
                               5979                 :                :  * double-quoted.
                               5980                 :                :  */
                               5981                 :                : static void
                               5982                 :             55 : parse_identifier(const char *ident,
                               5983                 :                :                  char **schemaname, char **objectname,
                               5984                 :                :                  bool *schemaquoted, bool *objectquoted)
                               5985                 :                : {
                               5986                 :             55 :     size_t      buflen = strlen(ident) + 1;
                               5987                 :             55 :     bool        enc_is_single_byte = (pg_encoding_max_length(pset.encoding) == 1);
                               5988                 :                :     char       *sname;
                               5989                 :                :     char       *oname;
                               5990                 :                :     char       *optr;
                               5991                 :                :     bool        inquotes;
                               5992                 :                : 
                               5993                 :                :     /* Initialize, making a certainly-large-enough output buffer */
                               5994                 :             55 :     sname = NULL;
                               5995                 :             55 :     oname = pg_malloc(buflen);
                               5996                 :             55 :     *schemaquoted = *objectquoted = false;
                               5997                 :                :     /* Scan */
                               5998                 :             55 :     optr = oname;
                               5999                 :             55 :     inquotes = false;
                               6000         [ +  + ]:            268 :     while (*ident)
                               6001                 :                :     {
                               6002                 :            213 :         unsigned char ch = (unsigned char) *ident++;
                               6003                 :                : 
                               6004         [ +  + ]:            213 :         if (ch == '"')
                               6005                 :                :         {
                               6006   [ +  +  -  + ]:              7 :             if (inquotes && *ident == '"')
                               6007                 :                :             {
                               6008                 :                :                 /* two quote marks within a quoted identifier = emit quote */
  805 tgl@sss.pgh.pa.us        6009                 :UBC           0 :                 *optr++ = '"';
                               6010                 :              0 :                 ident++;
                               6011                 :                :             }
                               6012                 :                :             else
                               6013                 :                :             {
  805 tgl@sss.pgh.pa.us        6014                 :CBC           7 :                 inquotes = !inquotes;
                               6015                 :              7 :                 *objectquoted = true;
                               6016                 :                :             }
                               6017                 :                :         }
                               6018   [ +  +  +  - ]:            206 :         else if (ch == '.' && !inquotes)
                               6019                 :                :         {
                               6020                 :                :             /* Found a schema name, transfer it to sname / *schemaquoted */
                               6021                 :              4 :             *optr = '\0';
                               6022                 :              4 :             free(sname);        /* drop any catalog name */
                               6023                 :              4 :             sname = oname;
                               6024                 :              4 :             oname = pg_malloc(buflen);
                               6025                 :              4 :             optr = oname;
                               6026                 :              4 :             *schemaquoted = *objectquoted;
                               6027                 :              4 :             *objectquoted = false;
                               6028                 :                :         }
                               6029   [ +  -  -  + ]:            202 :         else if (!enc_is_single_byte && IS_HIGHBIT_SET(ch))
  805 tgl@sss.pgh.pa.us        6030                 :UBC           0 :         {
                               6031                 :                :             /*
                               6032                 :                :              * Transfer multibyte characters without further processing.  They
                               6033                 :                :              * wouldn't be affected by our downcasing rule anyway, and this
                               6034                 :                :              * avoids possibly doing the wrong thing in unsafe client
                               6035                 :                :              * encodings.
                               6036                 :                :              */
                               6037                 :              0 :             int         chlen = PQmblenBounded(ident - 1, pset.encoding);
                               6038                 :                : 
                               6039                 :              0 :             *optr++ = (char) ch;
                               6040         [ #  # ]:              0 :             while (--chlen > 0)
                               6041                 :              0 :                 *optr++ = *ident++;
                               6042                 :                :         }
                               6043                 :                :         else
                               6044                 :                :         {
  805 tgl@sss.pgh.pa.us        6045         [ +  + ]:CBC         202 :             if (!inquotes)
                               6046                 :                :             {
                               6047                 :                :                 /*
                               6048                 :                :                  * This downcasing transformation should match the backend's
                               6049                 :                :                  * downcase_identifier() as best we can.  We do not know the
                               6050                 :                :                  * backend's locale, though, so it's necessarily approximate.
                               6051                 :                :                  * We assume that psql is operating in the same locale and
                               6052                 :                :                  * encoding as the backend.
                               6053                 :                :                  */
                               6054   [ +  +  +  + ]:            178 :                 if (ch >= 'A' && ch <= 'Z')
                               6055                 :             28 :                     ch += 'a' - 'A';
                               6056   [ -  +  -  -  :            150 :                 else if (enc_is_single_byte && IS_HIGHBIT_SET(ch) && isupper(ch))
                                              -  - ]
  805 tgl@sss.pgh.pa.us        6057                 :UBC           0 :                     ch = tolower(ch);
                               6058                 :                :             }
  805 tgl@sss.pgh.pa.us        6059                 :CBC         202 :             *optr++ = (char) ch;
                               6060                 :                :         }
                               6061                 :                :     }
                               6062                 :                : 
                               6063                 :             55 :     *optr = '\0';
                               6064                 :             55 :     *schemaname = sname;
                               6065                 :             55 :     *objectname = oname;
                               6066                 :             55 : }
                               6067                 :                : 
                               6068                 :                : 
                               6069                 :                : /*
                               6070                 :                :  * requote_identifier - Reconstruct a possibly-schema-qualified SQL identifier.
                               6071                 :                :  *
                               6072                 :                :  * Build a malloc'd string containing the identifier, with quoting applied
                               6073                 :                :  * as necessary.  This is more or less the inverse of parse_identifier;
                               6074                 :                :  * in particular, if an input component was quoted, we'll quote the output
                               6075                 :                :  * even when that isn't strictly required.
                               6076                 :                :  *
                               6077                 :                :  * Unlike parse_identifier, we handle the case where a schema and no
                               6078                 :                :  * object name is provided, producing just "schema.".
                               6079                 :                :  */
                               6080                 :                : static char *
                               6081                 :             31 : requote_identifier(const char *schemaname, const char *objectname,
                               6082                 :                :                    bool quote_schema, bool quote_object)
                               6083                 :                : {
                               6084                 :                :     char       *result;
                               6085                 :             31 :     size_t      buflen = 1;     /* count the trailing \0 */
                               6086                 :                :     char       *ptr;
                               6087                 :                : 
                               6088                 :                :     /*
                               6089                 :                :      * We could use PQescapeIdentifier for some of this, but not all, and it
                               6090                 :                :      * adds more notational cruft than it seems worth.
                               6091                 :                :      */
                               6092         [ +  + ]:             31 :     if (schemaname)
                               6093                 :                :     {
                               6094                 :              4 :         buflen += strlen(schemaname) + 1;   /* +1 for the dot */
                               6095         [ +  - ]:              4 :         if (!quote_schema)
                               6096                 :              4 :             quote_schema = identifier_needs_quotes(schemaname);
                               6097         [ -  + ]:              4 :         if (quote_schema)
                               6098                 :                :         {
  805 tgl@sss.pgh.pa.us        6099                 :UBC           0 :             buflen += 2;        /* account for quote marks */
                               6100         [ #  # ]:              0 :             for (const char *p = schemaname; *p; p++)
                               6101                 :                :             {
                               6102         [ #  # ]:              0 :                 if (*p == '"')
                               6103                 :              0 :                     buflen++;
                               6104                 :                :             }
                               6105                 :                :         }
                               6106                 :                :     }
  805 tgl@sss.pgh.pa.us        6107         [ +  + ]:CBC          31 :     if (objectname)
                               6108                 :                :     {
                               6109                 :             30 :         buflen += strlen(objectname);
                               6110         [ +  + ]:             30 :         if (!quote_object)
                               6111                 :             22 :             quote_object = identifier_needs_quotes(objectname);
                               6112         [ +  + ]:             30 :         if (quote_object)
                               6113                 :                :         {
                               6114                 :              8 :             buflen += 2;        /* account for quote marks */
                               6115         [ +  + ]:             73 :             for (const char *p = objectname; *p; p++)
                               6116                 :                :             {
                               6117         [ -  + ]:             65 :                 if (*p == '"')
  805 tgl@sss.pgh.pa.us        6118                 :UBC           0 :                     buflen++;
                               6119                 :                :             }
                               6120                 :                :         }
                               6121                 :                :     }
  805 tgl@sss.pgh.pa.us        6122                 :CBC          31 :     result = pg_malloc(buflen);
                               6123                 :             31 :     ptr = result;
                               6124         [ +  + ]:             31 :     if (schemaname)
                               6125                 :                :     {
                               6126         [ -  + ]:              4 :         if (quote_schema)
  805 tgl@sss.pgh.pa.us        6127                 :UBC           0 :             *ptr++ = '"';
  805 tgl@sss.pgh.pa.us        6128         [ +  + ]:CBC          28 :         for (const char *p = schemaname; *p; p++)
                               6129                 :                :         {
                               6130                 :             24 :             *ptr++ = *p;
                               6131         [ -  + ]:             24 :             if (*p == '"')
  805 tgl@sss.pgh.pa.us        6132                 :UBC           0 :                 *ptr++ = '"';
                               6133                 :                :         }
  805 tgl@sss.pgh.pa.us        6134         [ -  + ]:CBC           4 :         if (quote_schema)
  805 tgl@sss.pgh.pa.us        6135                 :UBC           0 :             *ptr++ = '"';
  805 tgl@sss.pgh.pa.us        6136                 :CBC           4 :         *ptr++ = '.';
                               6137                 :                :     }
                               6138         [ +  + ]:             31 :     if (objectname)
                               6139                 :                :     {
                               6140         [ +  + ]:             30 :         if (quote_object)
                               6141                 :              8 :             *ptr++ = '"';
                               6142         [ +  + ]:            264 :         for (const char *p = objectname; *p; p++)
                               6143                 :                :         {
                               6144                 :            234 :             *ptr++ = *p;
                               6145         [ -  + ]:            234 :             if (*p == '"')
  805 tgl@sss.pgh.pa.us        6146                 :UBC           0 :                 *ptr++ = '"';
                               6147                 :                :         }
  805 tgl@sss.pgh.pa.us        6148         [ +  + ]:CBC          30 :         if (quote_object)
                               6149                 :              8 :             *ptr++ = '"';
                               6150                 :                :     }
                               6151                 :             31 :     *ptr = '\0';
                               6152                 :             31 :     return result;
                               6153                 :                : }
                               6154                 :                : 
                               6155                 :                : 
                               6156                 :                : /*
                               6157                 :                :  * Detect whether an identifier must be double-quoted.
                               6158                 :                :  *
                               6159                 :                :  * Note we'll quote anything that's not ASCII; the backend's quote_ident()
                               6160                 :                :  * does the same.  Perhaps this could be relaxed in future.
                               6161                 :                :  */
                               6162                 :                : static bool
                               6163                 :             46 : identifier_needs_quotes(const char *ident)
                               6164                 :                : {
                               6165                 :                :     int         kwnum;
                               6166                 :                : 
                               6167                 :                :     /* Check syntax. */
                               6168   [ +  -  -  +  :             46 :     if (!((ident[0] >= 'a' && ident[0] <= 'z') || ident[0] == '_'))
                                              -  - ]
  805 tgl@sss.pgh.pa.us        6169                 :UBC           0 :         return true;
  208 heikki.linnakangas@i     6170         [ -  + ]:GNC          46 :     if (strspn(ident, "abcdefghijklmnopqrstuvwxyz0123456789_$") != strlen(ident))
  805 tgl@sss.pgh.pa.us        6171                 :UBC           0 :         return true;
                               6172                 :                : 
                               6173                 :                :     /*
                               6174                 :                :      * Check for keyword.  We quote keywords except for unreserved ones.
                               6175                 :                :      *
                               6176                 :                :      * It is possible that our keyword list doesn't quite agree with the
                               6177                 :                :      * server's, but this should be close enough for tab-completion purposes.
                               6178                 :                :      *
                               6179                 :                :      * Note: ScanKeywordLookup() does case-insensitive comparison, but that's
                               6180                 :                :      * fine, since we already know we have all-lower-case.
                               6181                 :                :      */
  805 tgl@sss.pgh.pa.us        6182                 :CBC          46 :     kwnum = ScanKeywordLookup(ident, &ScanKeywords);
                               6183                 :                : 
                               6184   [ -  +  -  - ]:             46 :     if (kwnum >= 0 && ScanKeywordCategories[kwnum] != UNRESERVED_KEYWORD)
  805 tgl@sss.pgh.pa.us        6185                 :UBC           0 :         return true;
                               6186                 :                : 
  805 tgl@sss.pgh.pa.us        6187                 :CBC          46 :     return false;
                               6188                 :                : }
                               6189                 :                : 
                               6190                 :                : 
                               6191                 :                : /*
                               6192                 :                :  * Execute a query, returning NULL if there was any error.
                               6193                 :                :  * This should be the preferred way of talking to the database in this file.
                               6194                 :                :  */
                               6195                 :                : static PGresult *
 6726 bruce@momjian.us         6196                 :             46 : exec_query(const char *query)
                               6197                 :                : {
                               6198                 :                :     PGresult   *result;
                               6199                 :                : 
                               6200   [ +  -  +  -  :             46 :     if (query == NULL || !pset.db || PQstatus(pset.db) != CONNECTION_OK)
                                              -  + ]
 6726 bruce@momjian.us         6201                 :UBC           0 :         return NULL;
                               6202                 :                : 
 6726 bruce@momjian.us         6203                 :CBC          46 :     result = PQexec(pset.db, query);
                               6204                 :                : 
 5720 tgl@sss.pgh.pa.us        6205         [ -  + ]:             46 :     if (PQresultStatus(result) != PGRES_TUPLES_OK)
                               6206                 :                :     {
                               6207                 :                :         /*
                               6208                 :                :          * Printing an error while the user is typing would be quite annoying,
                               6209                 :                :          * so we don't.  This does complicate debugging of this code; but you
                               6210                 :                :          * can look in the server log instead.
                               6211                 :                :          */
                               6212                 :                : #ifdef NOT_USED
                               6213                 :                :         pg_log_error("tab completion query failed: %s\nQuery was:\n%s",
                               6214                 :                :                      PQerrorMessage(pset.db), query);
                               6215                 :                : #endif
 6726 bruce@momjian.us         6216                 :UBC           0 :         PQclear(result);
                               6217                 :              0 :         result = NULL;
                               6218                 :                :     }
                               6219                 :                : 
 6726 bruce@momjian.us         6220                 :CBC          46 :     return result;
                               6221                 :                : }
                               6222                 :                : 
                               6223                 :                : 
                               6224                 :                : /*
                               6225                 :                :  * Parse all the word(s) before point.
                               6226                 :                :  *
                               6227                 :                :  * Returns a malloc'd array of character pointers that point into the malloc'd
                               6228                 :                :  * data array returned to *buffer; caller must free() both of these when done.
                               6229                 :                :  * *nwords receives the number of words found, ie, the valid length of the
                               6230                 :                :  * return array.
                               6231                 :                :  *
                               6232                 :                :  * Words are returned right to left, that is, previous_words[0] gets the last
                               6233                 :                :  * word before point, previous_words[1] the next-to-last, etc.
                               6234                 :                :  */
                               6235                 :                : static char **
 3038 tgl@sss.pgh.pa.us        6236                 :             67 : get_previous_words(int point, char **buffer, int *nwords)
                               6237                 :                : {
                               6238                 :                :     char      **previous_words;
                               6239                 :                :     char       *buf;
                               6240                 :                :     char       *outptr;
 3039                          6241                 :             67 :     int         words_found = 0;
                               6242                 :                :     int         i;
                               6243                 :                : 
                               6244                 :                :     /*
                               6245                 :                :      * If we have anything in tab_completion_query_buf, paste it together with
                               6246                 :                :      * rl_line_buffer to construct the full query.  Otherwise we can just use
                               6247                 :                :      * rl_line_buffer as the input string.
                               6248                 :                :      */
 3037                          6249   [ +  -  +  + ]:             67 :     if (tab_completion_query_buf && tab_completion_query_buf->len > 0)
                               6250                 :                :     {
                               6251                 :              3 :         i = tab_completion_query_buf->len;
                               6252                 :              3 :         buf = pg_malloc(point + i + 2);
                               6253                 :              3 :         memcpy(buf, tab_completion_query_buf->data, i);
 3038                          6254                 :              3 :         buf[i++] = '\n';
 3037                          6255                 :              3 :         memcpy(buf + i, rl_line_buffer, point);
                               6256                 :              3 :         i += point;
                               6257                 :              3 :         buf[i] = '\0';
                               6258                 :                :         /* Readjust point to reference appropriate offset in buf */
                               6259                 :              3 :         point = i;
                               6260                 :                :     }
                               6261                 :                :     else
                               6262                 :             64 :         buf = rl_line_buffer;
                               6263                 :                : 
                               6264                 :                :     /*
                               6265                 :                :      * Allocate an array of string pointers and a buffer to hold the strings
                               6266                 :                :      * themselves.  The worst case is that the line contains only
                               6267                 :                :      * non-whitespace WORD_BREAKS characters, making each one a separate word.
                               6268                 :                :      * This is usually much more space than we need, but it's cheaper than
                               6269                 :                :      * doing a separate malloc() for each word.
                               6270                 :                :      */
                               6271                 :             67 :     previous_words = (char **) pg_malloc(point * sizeof(char *));
                               6272                 :             67 :     *buffer = outptr = (char *) pg_malloc(point * 2);
                               6273                 :                : 
                               6274                 :                :     /*
                               6275                 :                :      * First we look for a non-word char before the current point.  (This is
                               6276                 :                :      * probably useless, if readline is on the same page as we are about what
                               6277                 :                :      * is a word, but if so it's cheap.)
                               6278                 :                :      */
 5170 itagaki.takahiro@gma     6279         [ +  + ]:             73 :     for (i = point - 1; i >= 0; i--)
                               6280                 :                :     {
                               6281         [ +  + ]:             70 :         if (strchr(WORD_BREAKS, buf[i]))
                               6282                 :             64 :             break;
                               6283                 :                :     }
                               6284                 :             67 :     point = i;
                               6285                 :                : 
                               6286                 :                :     /*
                               6287                 :                :      * Now parse words, working backwards, until we hit start of line.  The
                               6288                 :                :      * backwards scan has some interesting but intentional properties
                               6289                 :                :      * concerning parenthesis handling.
                               6290                 :                :      */
 3038 tgl@sss.pgh.pa.us        6291         [ +  + ]:            255 :     while (point >= 0)
                               6292                 :                :     {
                               6293                 :                :         int         start,
                               6294                 :                :                     end;
                               6295                 :            188 :         bool        inquotes = false;
                               6296                 :            188 :         int         parentheses = 0;
                               6297                 :                : 
                               6298                 :                :         /* now find the first non-space which then constitutes the end */
 4560                          6299                 :            188 :         end = -1;
 5170 itagaki.takahiro@gma     6300         [ +  - ]:            382 :         for (i = point; i >= 0; i--)
                               6301                 :                :         {
 4560 tgl@sss.pgh.pa.us        6302         [ +  + ]:            382 :             if (!isspace((unsigned char) buf[i]))
                               6303                 :                :             {
 6726 bruce@momjian.us         6304                 :            188 :                 end = i;
                               6305                 :            188 :                 break;
                               6306                 :                :             }
                               6307                 :                :         }
                               6308                 :                :         /* if no end found, we're done */
 3038 tgl@sss.pgh.pa.us        6309         [ -  + ]:            188 :         if (end < 0)
 3038 tgl@sss.pgh.pa.us        6310                 :UBC           0 :             break;
                               6311                 :                : 
                               6312                 :                :         /*
                               6313                 :                :          * Otherwise we now look for the start.  The start is either the last
                               6314                 :                :          * character before any word-break character going backwards from the
                               6315                 :                :          * end, or it's simply character 0.  We also handle open quotes and
                               6316                 :                :          * parentheses.
                               6317                 :                :          */
 3038 tgl@sss.pgh.pa.us        6318         [ +  + ]:CBC         943 :         for (start = end; start > 0; start--)
                               6319                 :                :         {
                               6320         [ +  + ]:            879 :             if (buf[start] == '"')
                               6321                 :              2 :                 inquotes = !inquotes;
                               6322         [ +  + ]:            879 :             if (!inquotes)
                               6323                 :                :             {
                               6324         [ -  + ]:            874 :                 if (buf[start] == ')')
 3038 tgl@sss.pgh.pa.us        6325                 :UBC           0 :                     parentheses++;
 3038 tgl@sss.pgh.pa.us        6326         [ +  + ]:CBC         874 :                 else if (buf[start] == '(')
                               6327                 :                :                 {
                               6328         [ +  - ]:              3 :                     if (--parentheses <= 0)
 5170 itagaki.takahiro@gma     6329                 :              3 :                         break;
                               6330                 :                :                 }
 3038 tgl@sss.pgh.pa.us        6331         [ +  - ]:            871 :                 else if (parentheses == 0 &&
                               6332         [ +  + ]:            871 :                          strchr(WORD_BREAKS, buf[start - 1]))
                               6333                 :            121 :                     break;
                               6334                 :                :             }
                               6335                 :                :         }
                               6336                 :                : 
                               6337                 :                :         /* Return the word located at start to end inclusive */
 3037                          6338                 :            188 :         previous_words[words_found++] = outptr;
                               6339                 :            188 :         i = end - start + 1;
                               6340                 :            188 :         memcpy(outptr, &buf[start], i);
                               6341                 :            188 :         outptr += i;
                               6342                 :            188 :         *outptr++ = '\0';
                               6343                 :                : 
                               6344                 :                :         /* Continue searching */
 3038                          6345                 :            188 :         point = start - 1;
                               6346                 :                :     }
                               6347                 :                : 
                               6348                 :                :     /* Release parsing input workspace, if we made one above */
 3037                          6349         [ +  + ]:             67 :     if (buf != rl_line_buffer)
                               6350                 :              3 :         free(buf);
                               6351                 :                : 
 3038                          6352                 :             67 :     *nwords = words_found;
                               6353                 :             67 :     return previous_words;
                               6354                 :                : }
                               6355                 :                : 
                               6356                 :                : /*
                               6357                 :                :  * Look up the type for the GUC variable with the passed name.
                               6358                 :                :  *
                               6359                 :                :  * Returns NULL if the variable is unknown. Otherwise the returned string,
                               6360                 :                :  * containing the type, has to be freed.
                               6361                 :                :  */
                               6362                 :                : static char *
 3141 andres@anarazel.de       6363                 :              2 : get_guctype(const char *varname)
                               6364                 :                : {
                               6365                 :                :     PQExpBufferData query_buffer;
                               6366                 :                :     char       *e_varname;
                               6367                 :                :     PGresult   *result;
                               6368                 :              2 :     char       *guctype = NULL;
                               6369                 :                : 
                               6370                 :              2 :     e_varname = escape_string(varname);
                               6371                 :                : 
                               6372                 :              2 :     initPQExpBuffer(&query_buffer);
                               6373                 :              2 :     appendPQExpBuffer(&query_buffer,
                               6374                 :                :                       "SELECT vartype FROM pg_catalog.pg_settings "
                               6375                 :                :                       "WHERE pg_catalog.lower(name) = pg_catalog.lower('%s')",
                               6376                 :                :                       e_varname);
                               6377                 :                : 
                               6378                 :              2 :     result = exec_query(query_buffer.data);
                               6379                 :              2 :     termPQExpBuffer(&query_buffer);
                               6380                 :              2 :     free(e_varname);
                               6381                 :                : 
                               6382   [ +  -  +  - ]:              2 :     if (PQresultStatus(result) == PGRES_TUPLES_OK && PQntuples(result) > 0)
                               6383                 :              2 :         guctype = pg_strdup(PQgetvalue(result, 0, 0));
                               6384                 :                : 
                               6385                 :              2 :     PQclear(result);
                               6386                 :                : 
                               6387                 :              2 :     return guctype;
                               6388                 :                : }
                               6389                 :                : 
                               6390                 :                : #ifdef USE_FILENAME_QUOTING_FUNCTIONS
                               6391                 :                : 
                               6392                 :                : /*
                               6393                 :                :  * Quote a filename according to SQL rules, returning a malloc'd string.
                               6394                 :                :  * completion_charp must point to escape character or '\0', and
                               6395                 :                :  * completion_force_quote must be set correctly, as per comments for
                               6396                 :                :  * complete_from_files().
                               6397                 :                :  */
                               6398                 :                : static char *
 1543 tgl@sss.pgh.pa.us        6399                 :              5 : quote_file_name(char *fname, int match_type, char *quote_pointer)
                               6400                 :                : {
                               6401                 :                :     char       *s;
                               6402                 :                :     struct stat statbuf;
                               6403                 :                : 
                               6404                 :                :     /* Quote if needed. */
                               6405                 :              5 :     s = quote_if_needed(fname, " \t\r\n\"`",
                               6406                 :              5 :                         '\'', *completion_charp,
                               6407                 :                :                         completion_force_quote,
                               6408                 :                :                         pset.encoding);
                               6409         [ +  + ]:              5 :     if (!s)
                               6410                 :              2 :         s = pg_strdup(fname);
                               6411                 :                : 
                               6412                 :                :     /*
                               6413                 :                :      * However, some of the time we have to strip the trailing quote from what
                               6414                 :                :      * we send back.  Never strip the trailing quote if the user already typed
                               6415                 :                :      * one; otherwise, suppress the trailing quote if we have multiple/no
                               6416                 :                :      * matches (because we don't want to add a quote if the input is seemingly
                               6417                 :                :      * unfinished), or if the input was already quoted (because Readline will
                               6418                 :                :      * do arguably-buggy things otherwise), or if the file does not exist, or
                               6419                 :                :      * if it's a directory.
                               6420                 :                :      */
                               6421         [ +  + ]:              5 :     if (*s == '\'' &&
                               6422   [ +  -  +  + ]:              3 :         completion_last_char != '\'' &&
                               6423         [ +  - ]:              1 :         (match_type != SINGLE_MATCH ||
                               6424   [ +  -  +  - ]:              2 :          (quote_pointer && *quote_pointer == '\'') ||
                               6425                 :              1 :          stat(fname, &statbuf) != 0 ||
                               6426         [ -  + ]:              1 :          S_ISDIR(statbuf.st_mode)))
                               6427                 :                :     {
                               6428                 :              2 :         char       *send = s + strlen(s) - 1;
                               6429                 :                : 
                               6430         [ -  + ]:              2 :         Assert(*send == '\'');
                               6431                 :              2 :         *send = '\0';
                               6432                 :                :     }
                               6433                 :                : 
                               6434                 :                :     /*
                               6435                 :                :      * And now we can let Readline do its thing with possibly adding a quote
                               6436                 :                :      * on its own accord.  (This covers some additional cases beyond those
                               6437                 :                :      * dealt with above.)
                               6438                 :                :      */
                               6439                 :                : #ifdef HAVE_RL_COMPLETION_SUPPRESS_QUOTE
                               6440                 :              5 :     rl_completion_suppress_quote = 0;
                               6441                 :                : #endif
                               6442                 :                : 
                               6443                 :                :     /*
                               6444                 :                :      * If user typed a leading quote character other than single quote (i.e.,
                               6445                 :                :      * double quote), zap it, so that we replace it with the correct single
                               6446                 :                :      * quote.
                               6447                 :                :      */
                               6448   [ +  -  +  + ]:              5 :     if (quote_pointer && *quote_pointer != '\'')
                               6449                 :              4 :         *quote_pointer = '\0';
                               6450                 :                : 
 6726 bruce@momjian.us         6451                 :              5 :     return s;
                               6452                 :                : }
                               6453                 :                : 
                               6454                 :                : /*
                               6455                 :                :  * Dequote a filename, if it's quoted.
                               6456                 :                :  * completion_charp must point to escape character or '\0', as per
                               6457                 :                :  * comments for complete_from_files().
                               6458                 :                :  */
                               6459                 :                : static char *
 1543 tgl@sss.pgh.pa.us        6460                 :             12 : dequote_file_name(char *fname, int quote_char)
                               6461                 :                : {
                               6462                 :                :     char       *unquoted_fname;
                               6463                 :                : 
                               6464                 :                :     /*
                               6465                 :                :      * If quote_char is set, it's not included in "fname".  We have to add it
                               6466                 :                :      * or strtokx will not interpret the string correctly (notably, it won't
                               6467                 :                :      * recognize escapes).
                               6468                 :                :      */
                               6469         [ +  + ]:             12 :     if (quote_char == '\'')
                               6470                 :                :     {
                               6471                 :              6 :         char       *workspace = (char *) pg_malloc(strlen(fname) + 2);
                               6472                 :                : 
                               6473                 :              6 :         workspace[0] = quote_char;
                               6474                 :              6 :         strcpy(workspace + 1, fname);
                               6475                 :              6 :         unquoted_fname = strtokx(workspace, "", NULL, "'", *completion_charp,
                               6476                 :                :                                  false, true, pset.encoding);
                               6477                 :              6 :         free(workspace);
                               6478                 :                :     }
                               6479                 :                :     else
                               6480                 :              6 :         unquoted_fname = strtokx(fname, "", NULL, "'", *completion_charp,
                               6481                 :                :                                  false, true, pset.encoding);
                               6482                 :                : 
                               6483                 :                :     /* expect a NULL return for the empty string only */
                               6484         [ -  + ]:             12 :     if (!unquoted_fname)
                               6485                 :                :     {
 1543 tgl@sss.pgh.pa.us        6486         [ #  # ]:UBC           0 :         Assert(*fname == '\0');
                               6487                 :              0 :         unquoted_fname = fname;
                               6488                 :                :     }
                               6489                 :                : 
                               6490                 :                :     /* readline expects a malloc'd result that it is to free */
 1543 tgl@sss.pgh.pa.us        6491                 :CBC          12 :     return pg_strdup(unquoted_fname);
                               6492                 :                : }
                               6493                 :                : 
                               6494                 :                : #endif                          /* USE_FILENAME_QUOTING_FUNCTIONS */
                               6495                 :                : 
                               6496                 :                : #endif                          /* USE_READLINE */
        

Generated by: LCOV version 2.1-beta2-3-g6141622