Re: tab complete changes

Поиск
Список
Период
Сортировка
От Bruce Momjian
Тема Re: tab complete changes
Дата
Msg-id 200709140425.l8E4PZk02156@momjian.us
обсуждение исходный текст
Ответ на tab complete changes  (Stefan Kaltenbrunner <stefan@kaltenbrunner.cc>)
Список pgsql-patches
Patch applied.  Thanks.

---------------------------------------------------------------------------


Stefan Kaltenbrunner wrote:
> the attached patch makes teh following changes to the psql tab-complete
>  support
>
> * adds a few missing words to some commands (like adding GIN as a valid
> index type or OWNED BY for ALTER SEQUENCE,...)
>
> * support for ALTER TABLE foo ENABLE/DISABLE REPLICA TRIGGER/RULE
>
> * autocomplete CREATE DATABASE foo TEMPLATE (mostly done to prevent
> conflicts with the TEMPLATE keyword for text search)
>
> * support for ALTER/CREATE/DROP TEXT SEARCH as well as COMMENT ON TEXT
> SEARCH and the corresponding psql backslash commands.
> This proved a little more difficult than expected due to the fact that
> words_after_create[] is used for two purposes - one is to provide a list
> of words that follow immediatly after CREATE (or DROP) and the other
> purpose is to use it for autocompleting anywhere in the statement if the
> word in that struct is found with a query.
> Since TEXT SEARCH CONFIGURATION|DICTIONARY|TEMPLATE|PARSER results in 3
> words instead of one (as all the other words in that list are) I added a
> flag to the struct to tell create_command_generator() to skip that entry
>  for autocompleting immediatly after CREATE which feels like a dirty
> hack (but that holds true for a lot of code in tab-complete.c).
>
>
> Stefan

> Index: src/bin/psql/tab-complete.c
> ===================================================================
> RCS file: /projects/cvsroot/pgsql/src/bin/psql/tab-complete.c,v
> retrieving revision 1.166
> diff -c -r1.166 tab-complete.c
> *** src/bin/psql/tab-complete.c    3 Jul 2007 01:30:37 -0000    1.166
> --- src/bin/psql/tab-complete.c    25 Aug 2007 11:17:23 -0000
> ***************
> *** 328,333 ****
> --- 328,337 ----
>   "   AND pg_catalog.quote_ident(relname)='%s' "\
>   "   AND pg_catalog.pg_table_is_visible(c.oid)"
>
> + #define Query_for_list_of_template_databases \
> + "SELECT pg_catalog.quote_ident(datname) FROM pg_catalog.pg_database "\
> + " WHERE substring(pg_catalog.quote_ident(datname),1,%d)='%s' and datistemplate IS TRUE"
> +
>   #define Query_for_list_of_databases \
>   "SELECT pg_catalog.quote_ident(datname) FROM pg_catalog.pg_database "\
>   " WHERE substring(pg_catalog.quote_ident(datname),1,%d)='%s'"
> ***************
> *** 419,424 ****
> --- 423,444 ----
>   "       (SELECT tgrelid FROM pg_catalog.pg_trigger "\
>   "         WHERE pg_catalog.quote_ident(tgname)='%s')"
>
> + #define Query_for_list_of_ts_configurations \
> + "SELECT pg_catalog.quote_ident(cfgname) FROM pg_catalog.pg_ts_config "\
> + " WHERE substring(pg_catalog.quote_ident(cfgname),1,%d)='%s'"
> +
> + #define Query_for_list_of_ts_dictionaries \
> + "SELECT pg_catalog.quote_ident(dictname) FROM pg_catalog.pg_ts_dict "\
> + " WHERE substring(pg_catalog.quote_ident(dictname),1,%d)='%s'"
> +
> + #define Query_for_list_of_ts_parsers \
> + "SELECT pg_catalog.quote_ident(prsname) FROM pg_catalog.pg_ts_parser "\
> + " WHERE substring(pg_catalog.quote_ident(prsname),1,%d)='%s'"
> +
> + #define Query_for_list_of_ts_templates \
> + "SELECT pg_catalog.quote_ident(tmplname) FROM pg_catalog.pg_ts_template "\
> + " WHERE substring(pg_catalog.quote_ident(tmplname),1,%d)='%s'"
> +
>   /*
>    * This is a list of all "things" in Pgsql, which can show up after CREATE or
>    * DROP; and there is also a query to get a list of them.
> ***************
> *** 429,434 ****
> --- 449,455 ----
>       const char *name;
>       const char *query;            /* simple query, or NULL */
>       const SchemaQuery *squery;    /* schema query, or NULL */
> +     const bool noshow;    /* NULL or true if this word should not show up after CREATE or DROP */
>   } pgsql_thing_t;
>
>   static const pgsql_thing_t words_after_create[] = {
> ***************
> *** 440,447 ****
> --- 461,470 ----
>        * CREATE CONSTRAINT TRIGGER is not supported here because it is designed
>        * to be used only by pg_dump.
>        */
> +     {"CONFIGURATION", Query_for_list_of_ts_configurations, NULL, true},
>       {"CONVERSION", "SELECT pg_catalog.quote_ident(conname) FROM pg_catalog.pg_conversion WHERE
substring(pg_catalog.quote_ident(conname),1,%d)='%s'"},
>       {"DATABASE", Query_for_list_of_databases},
> +     {"DICTIONARY", Query_for_list_of_ts_dictionaries, NULL, true},
>       {"DOMAIN", NULL, &Query_for_list_of_domains},
>       {"FUNCTION", NULL, &Query_for_list_of_functions},
>       {"GROUP", Query_for_list_of_roles},
> ***************
> *** 449,454 ****
> --- 472,478 ----
>       {"INDEX", NULL, &Query_for_list_of_indexes},
>       {"OPERATOR", NULL, NULL},    /* Querying for this is probably not such a
>                                    * good idea. */
> +     {"PARSER", Query_for_list_of_ts_parsers, NULL, true},
>       {"ROLE", Query_for_list_of_roles},
>       {"RULE", "SELECT pg_catalog.quote_ident(rulename) FROM pg_catalog.pg_rules WHERE
substring(pg_catalog.quote_ident(rulename),1,%d)='%s'"},
>       {"SCHEMA", Query_for_list_of_schemas},
> ***************
> *** 456,467 ****
>       {"TABLE", NULL, &Query_for_list_of_tables},
>       {"TABLESPACE", Query_for_list_of_tablespaces},
>       {"TEMP", NULL, NULL},        /* for CREATE TEMP TABLE ... */
>       {"TRIGGER", "SELECT pg_catalog.quote_ident(tgname) FROM pg_catalog.pg_trigger WHERE
substring(pg_catalog.quote_ident(tgname),1,%d)='%s'"},
>       {"TYPE", NULL, &Query_for_list_of_datatypes},
>       {"UNIQUE", NULL, NULL},        /* for CREATE UNIQUE INDEX ... */
>       {"USER", Query_for_list_of_roles},
>       {"VIEW", NULL, &Query_for_list_of_views},
> !     {NULL, NULL, NULL}            /* end of list */
>   };
>
>
> --- 480,493 ----
>       {"TABLE", NULL, &Query_for_list_of_tables},
>       {"TABLESPACE", Query_for_list_of_tablespaces},
>       {"TEMP", NULL, NULL},        /* for CREATE TEMP TABLE ... */
> +     {"TEMPLATE", Query_for_list_of_ts_templates, NULL, true},
> +     {"TEXT SEARCH", NULL, NULL},
>       {"TRIGGER", "SELECT pg_catalog.quote_ident(tgname) FROM pg_catalog.pg_trigger WHERE
substring(pg_catalog.quote_ident(tgname),1,%d)='%s'"},
>       {"TYPE", NULL, &Query_for_list_of_datatypes},
>       {"UNIQUE", NULL, NULL},        /* for CREATE UNIQUE INDEX ... */
>       {"USER", Query_for_list_of_roles},
>       {"VIEW", NULL, &Query_for_list_of_views},
> !     {NULL, NULL, NULL, false}            /* end of list */
>   };
>
>
> ***************
> *** 531,544 ****
>           "GRANT", "INSERT", "LISTEN", "LOAD", "LOCK", "MOVE", "NOTIFY", "PREPARE",
>           "REASSIGN", "REINDEX", "RELEASE", "RESET", "REVOKE", "ROLLBACK",
>           "SAVEPOINT", "SELECT", "SET", "SHOW", "START", "TRUNCATE", "UNLISTEN",
> !         "UPDATE", "VACUUM", NULL
>       };
>
>       static const char *const backslash_commands[] = {
>           "\\a", "\\connect", "\\C", "\\cd", "\\copy", "\\copyright",
>           "\\d", "\\da", "\\db", "\\dc", "\\dC", "\\dd", "\\dD", "\\df",
> !         "\\dg", "\\di", "\\dl", "\\dn", "\\do", "\\dp", "\\ds", "\\dS",
> !         "\\dt", "\\dT", "\\dv", "\\du",
>           "\\e", "\\echo", "\\encoding",
>           "\\f", "\\g", "\\h", "\\help", "\\H", "\\i", "\\l",
>           "\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",
> --- 557,570 ----
>           "GRANT", "INSERT", "LISTEN", "LOAD", "LOCK", "MOVE", "NOTIFY", "PREPARE",
>           "REASSIGN", "REINDEX", "RELEASE", "RESET", "REVOKE", "ROLLBACK",
>           "SAVEPOINT", "SELECT", "SET", "SHOW", "START", "TRUNCATE", "UNLISTEN",
> !         "UPDATE", "VACUUM", "VALUES", NULL
>       };
>
>       static const char *const backslash_commands[] = {
>           "\\a", "\\connect", "\\C", "\\cd", "\\copy", "\\copyright",
>           "\\d", "\\da", "\\db", "\\dc", "\\dC", "\\dd", "\\dD", "\\df",
> !         "\\dF", "\\dFd", "\\dFp", "\\dFt", "\\dg", "\\di", "\\dl",
> !         "\\dn", "\\do", "\\dp", "\\ds", "\\dS", "\\dt", "\\dT", "\\dv", "\\du",
>           "\\e", "\\echo", "\\encoding",
>           "\\f", "\\g", "\\h", "\\help", "\\H", "\\i", "\\l",
>           "\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",
> ***************
> *** 602,608 ****
>           static const char *const list_ALTER[] =
>           {"AGGREGATE", "CONVERSION", "DATABASE", "DOMAIN", "FUNCTION",
>               "GROUP", "INDEX", "LANGUAGE", "OPERATOR", "ROLE", "SCHEMA", "SEQUENCE", "TABLE",
> !         "TABLESPACE", "TRIGGER", "TYPE", "USER", "VIEW", NULL};
>
>           COMPLETE_WITH_LIST(list_ALTER);
>       }
> --- 628,634 ----
>           static const char *const list_ALTER[] =
>           {"AGGREGATE", "CONVERSION", "DATABASE", "DOMAIN", "FUNCTION",
>               "GROUP", "INDEX", "LANGUAGE", "OPERATOR", "ROLE", "SCHEMA", "SEQUENCE", "TABLE",
> !         "TABLESPACE", "TEXT SEARCH", "TRIGGER", "TYPE", "USER", "VIEW", NULL};
>
>           COMPLETE_WITH_LIST(list_ALTER);
>       }
> ***************
> *** 643,649 ****
>                pg_strcasecmp(prev2_wd, "INDEX") == 0)
>       {
>           static const char *const list_ALTERINDEX[] =
> !         {"SET TABLESPACE", "OWNER TO", "RENAME TO", NULL};
>
>           COMPLETE_WITH_LIST(list_ALTERINDEX);
>       }
> --- 669,675 ----
>                pg_strcasecmp(prev2_wd, "INDEX") == 0)
>       {
>           static const char *const list_ALTERINDEX[] =
> !         {"SET TABLESPACE", "OWNER TO", "RENAME TO", "SET", "RESET", NULL};
>
>           COMPLETE_WITH_LIST(list_ALTERINDEX);
>       }
> ***************
> *** 714,720 ****
>       {
>           static const char *const list_ALTERSEQUENCE[] =
>           {"INCREMENT", "MINVALUE", "MAXVALUE", "RESTART", "NO", "CACHE", "CYCLE",
> !         "SET SCHEMA", "RENAME TO", NULL};
>
>           COMPLETE_WITH_LIST(list_ALTERSEQUENCE);
>       }
> --- 740,746 ----
>       {
>           static const char *const list_ALTERSEQUENCE[] =
>           {"INCREMENT", "MINVALUE", "MAXVALUE", "RESTART", "NO", "CACHE", "CYCLE",
> !         "SET SCHEMA", "OWNED BY", "RENAME TO", NULL};
>
>           COMPLETE_WITH_LIST(list_ALTERSEQUENCE);
>       }
> ***************
> *** 769,779 ****
>                pg_strcasecmp(prev2_wd, "TABLE") == 0)
>       {
>           static const char *const list_ALTER2[] =
> !         {"ADD", "ALTER", "CLUSTER ON", "DROP", "RENAME", "OWNER TO",
> !         "SET", NULL};
>
>           COMPLETE_WITH_LIST(list_ALTER2);
>       }
>       /* If we have TABLE <sth> ALTER|RENAME, provide list of columns */
>       else if (pg_strcasecmp(prev3_wd, "TABLE") == 0 &&
>                (pg_strcasecmp(prev_wd, "ALTER") == 0 ||
> --- 795,832 ----
>                pg_strcasecmp(prev2_wd, "TABLE") == 0)
>       {
>           static const char *const list_ALTER2[] =
> !         {"ADD", "ALTER", "CLUSTER ON", "DISABLE", "DROP", "ENABLE", "INHERIT",
> !         "NO INHERIT", "RENAME", "RESET", "OWNER TO", "SET", NULL};
>
>           COMPLETE_WITH_LIST(list_ALTER2);
>       }
> +     /* ALTER TABLE xxx ENABLE */
> +     else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 &&
> +              pg_strcasecmp(prev3_wd, "TABLE") == 0 &&
> +              pg_strcasecmp(prev_wd, "ENABLE") == 0)
> +     {
> +         static const char *const list_ALTERENABLE[] =
> +         {"ALWAYS","REPLICA","RULE", "TRIGGER", NULL};
> +         COMPLETE_WITH_LIST(list_ALTERENABLE);
> +     }
> +     else if (pg_strcasecmp(prev4_wd, "TABLE") == 0 &&
> +             pg_strcasecmp(prev2_wd, "ENABLE") == 0 &&
> +             (pg_strcasecmp(prev_wd, "REPLICA") == 0 ||
> +              pg_strcasecmp(prev_wd, "ALWAYS") == 0))
> +     {
> +         static const char *const list_ALTERENABLE2[] =
> +         {"RULE", "TRIGGER", NULL};
> +         COMPLETE_WITH_LIST(list_ALTERENABLE2);
> +     }
> +     else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 &&
> +              pg_strcasecmp(prev3_wd, "TABLE") == 0 &&
> +              pg_strcasecmp(prev_wd, "DISABLE") == 0)
> +     {
> +         static const char *const list_ALTERDISABLE[] =
> +         {"RULE", "TRIGGER", NULL};
> +         COMPLETE_WITH_LIST(list_ALTERDISABLE);
> +     }
> +
>       /* If we have TABLE <sth> ALTER|RENAME, provide list of columns */
>       else if (pg_strcasecmp(prev3_wd, "TABLE") == 0 &&
>                (pg_strcasecmp(prev_wd, "ALTER") == 0 ||
> ***************
> *** 871,876 ****
> --- 924,968 ----
>
>           COMPLETE_WITH_LIST(list_ALTERTSPC);
>       }
> +     /* ALTER TEXT SEARCH */
> +     else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
> +              pg_strcasecmp(prev2_wd, "TEXT") == 0 &&
> +              pg_strcasecmp(prev_wd, "SEARCH") == 0)
> +     {
> +         static const char *const list_ALTERTEXTSEARCH[] =
> +         {"CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE", NULL};
> +
> +         COMPLETE_WITH_LIST(list_ALTERTEXTSEARCH);
> +     }
> +     else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 &&
> +              pg_strcasecmp(prev4_wd, "TEXT") == 0 &&
> +              pg_strcasecmp(prev3_wd, "SEARCH") == 0 &&
> +              (pg_strcasecmp(prev2_wd, "TEMPLATE") == 0 ||
> +              pg_strcasecmp(prev2_wd, "PARSER") == 0))
> +         COMPLETE_WITH_CONST("RENAME TO");
> +
> +     else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 &&
> +              pg_strcasecmp(prev4_wd, "TEXT") == 0 &&
> +              pg_strcasecmp(prev3_wd, "SEARCH") == 0 &&
> +              pg_strcasecmp(prev2_wd, "DICTIONARY") == 0)
> +     {
> +         static const char *const list_ALTERTEXTSEARCH2[] =
> +         {"OWNER TO", "RENAME TO", NULL};
> +
> +         COMPLETE_WITH_LIST(list_ALTERTEXTSEARCH2);
> +     }
> +
> +     else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 &&
> +              pg_strcasecmp(prev4_wd, "TEXT") == 0 &&
> +              pg_strcasecmp(prev3_wd, "SEARCH") == 0 &&
> +              pg_strcasecmp(prev2_wd, "CONFIGURATION") == 0)
> +     {
> +         static const char *const list_ALTERTEXTSEARCH3[] =
> +         {"ADD MAPPING FOR", "ALTER MAPPING", "DROP MAPPING FOR", "OWNER TO", "RENAME TO", NULL};
> +
> +         COMPLETE_WITH_LIST(list_ALTERTEXTSEARCH3);
> +     }
> +
>       /* complete ALTER TYPE <foo> with OWNER TO, SET SCHEMA */
>       else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
>                pg_strcasecmp(prev2_wd, "TYPE") == 0)
> ***************
> *** 947,953 ****
>       }
>
>       /*
> !      * If we have CLUSTER <sth> ORDER BY, then add the index as well.
>        */
>       else if (pg_strcasecmp(prev3_wd, "CLUSTER") == 0 &&
>                pg_strcasecmp(prev_wd, "USING") == 0)
> --- 1039,1045 ----
>       }
>
>       /*
> !      * If we have CLUSTER <sth> USING, then add the index as well.
>        */
>       else if (pg_strcasecmp(prev3_wd, "CLUSTER") == 0 &&
>                pg_strcasecmp(prev_wd, "USING") == 0)
> ***************
> *** 966,977 ****
>           {"CAST", "CONVERSION", "DATABASE", "INDEX", "LANGUAGE", "RULE", "SCHEMA",
>               "SEQUENCE", "TABLE", "TYPE", "VIEW", "COLUMN", "AGGREGATE", "FUNCTION",
>               "OPERATOR", "TRIGGER", "CONSTRAINT", "DOMAIN", "LARGE OBJECT",
> !         "TABLESPACE", "ROLE", NULL};
>
>           COMPLETE_WITH_LIST(list_COMMENT);
>       }
>       else if (pg_strcasecmp(prev4_wd, "COMMENT") == 0 &&
> !              pg_strcasecmp(prev3_wd, "ON") == 0)
>           COMPLETE_WITH_CONST("IS");
>
>   /* COPY */
> --- 1058,1082 ----
>           {"CAST", "CONVERSION", "DATABASE", "INDEX", "LANGUAGE", "RULE", "SCHEMA",
>               "SEQUENCE", "TABLE", "TYPE", "VIEW", "COLUMN", "AGGREGATE", "FUNCTION",
>               "OPERATOR", "TRIGGER", "CONSTRAINT", "DOMAIN", "LARGE OBJECT",
> !         "TABLESPACE", "TEXT SEARCH", "ROLE", NULL};
>
>           COMPLETE_WITH_LIST(list_COMMENT);
>       }
>       else if (pg_strcasecmp(prev4_wd, "COMMENT") == 0 &&
> !              pg_strcasecmp(prev3_wd, "ON") == 0  &&
> !              pg_strcasecmp(prev2_wd, "TEXT") == 0  &&
> !              pg_strcasecmp(prev_wd, "SEARCH") == 0)
> !     {
> !         static const char *const list_TRANS2[] =
> !         {"CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE", NULL};
> !
> !         COMPLETE_WITH_LIST(list_TRANS2);
> !     }
> !     else if ((pg_strcasecmp(prev4_wd, "COMMENT") == 0 &&
> !              pg_strcasecmp(prev3_wd, "ON") == 0) ||
> !              (pg_strcasecmp(prev5_wd, "ON") == 0 &&
> !               pg_strcasecmp(prev4_wd, "TEXT") == 0 &&
> !               pg_strcasecmp(prev3_wd, "SEARCH") == 0))
>           COMPLETE_WITH_CONST("IS");
>
>   /* COPY */
> ***************
> *** 1038,1043 ****
> --- 1143,1153 ----
>           COMPLETE_WITH_LIST(list_DATABASE);
>       }
>
> +     else if (pg_strcasecmp(prev4_wd, "CREATE") == 0 &&
> +              pg_strcasecmp(prev3_wd, "DATABASE") == 0 &&
> +              pg_strcasecmp(prev_wd, "TEMPLATE") == 0)
> +         COMPLETE_WITH_QUERY(Query_for_list_of_template_databases);
> +
>       /* CREATE INDEX */
>       /* First off we complete CREATE UNIQUE with "INDEX" */
>       else if (pg_strcasecmp(prev2_wd, "CREATE") == 0 &&
> ***************
> *** 1077,1083 ****
>       else if (pg_strcasecmp(prev_wd, "USING") == 0)
>       {
>           static const char *const index_mth[] =
> !         {"BTREE", "HASH", "GIST", NULL};
>
>           COMPLETE_WITH_LIST(index_mth);
>       }
> --- 1187,1193 ----
>       else if (pg_strcasecmp(prev_wd, "USING") == 0)
>       {
>           static const char *const index_mth[] =
> !         {"BTREE", "HASH", "GIN", "GIST", NULL};
>
>           COMPLETE_WITH_LIST(index_mth);
>       }
> ***************
> *** 1143,1148 ****
> --- 1253,1273 ----
>           COMPLETE_WITH_CONST("LOCATION");
>       }
>
> + /* CREATE TEXT SEARCH */
> +     else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 &&
> +              pg_strcasecmp(prev2_wd, "TEXT") == 0 &&
> +              pg_strcasecmp(prev_wd, "SEARCH") == 0)
> +     {
> +         static const char *const list_CREATETEXTSEARCH[] =
> +         {"CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE", NULL};
> +
> +         COMPLETE_WITH_LIST(list_CREATETEXTSEARCH);
> +     }
> +     else if (pg_strcasecmp(prev4_wd, "TEXT") == 0 &&
> +             pg_strcasecmp(prev3_wd, "SEARCH") == 0 &&
> +             pg_strcasecmp(prev2_wd, "CONFIGURATION") == 0)
> +     COMPLETE_WITH_CONST("(");
> +
>   /* CREATE TRIGGER */
>       /* complete CREATE TRIGGER <name> with BEFORE,AFTER */
>       else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 &&
> ***************
> *** 1287,1293 ****
>                  pg_strcasecmp(prev2_wd, "VIEW") == 0)) ||
>                (pg_strcasecmp(prev4_wd, "DROP") == 0 &&
>                 pg_strcasecmp(prev3_wd, "AGGREGATE") == 0 &&
> !               prev_wd[strlen(prev_wd) - 1] == ')'))
>       {
>           if ((pg_strcasecmp(prev3_wd, "DROP") == 0) && (pg_strcasecmp(prev2_wd, "FUNCTION") == 0))
>           {
> --- 1412,1426 ----
>                  pg_strcasecmp(prev2_wd, "VIEW") == 0)) ||
>                (pg_strcasecmp(prev4_wd, "DROP") == 0 &&
>                 pg_strcasecmp(prev3_wd, "AGGREGATE") == 0 &&
> !               prev_wd[strlen(prev_wd) - 1] == ')') ||
> !              (pg_strcasecmp(prev5_wd, "DROP") == 0  &&
> !               pg_strcasecmp(prev4_wd, "TEXT") == 0 &&
> !               pg_strcasecmp(prev3_wd, "SEARCH") == 0 &&
> !              (pg_strcasecmp(prev2_wd, "CONFIGURATION") == 0 ||
> !               pg_strcasecmp(prev2_wd, "DICTIONARY") == 0 ||
> !               pg_strcasecmp(prev2_wd, "PARSER") == 0 ||
> !               pg_strcasecmp(prev2_wd, "TEMPLATE") == 0))
> !              )
>       {
>           if ((pg_strcasecmp(prev3_wd, "DROP") == 0) && (pg_strcasecmp(prev2_wd, "FUNCTION") == 0))
>           {
> ***************
> *** 1332,1340 ****
>                pg_strcasecmp(prev2_wd, "OWNED") == 0 &&
>                pg_strcasecmp(prev_wd, "BY") == 0)
>           COMPLETE_WITH_QUERY(Query_for_list_of_roles);
>
>
> !
>   /* EXPLAIN */
>
>       /*
> --- 1465,1481 ----
>                pg_strcasecmp(prev2_wd, "OWNED") == 0 &&
>                pg_strcasecmp(prev_wd, "BY") == 0)
>           COMPLETE_WITH_QUERY(Query_for_list_of_roles);
> +     else if (pg_strcasecmp(prev3_wd, "DROP") == 0 &&
> +              pg_strcasecmp(prev2_wd, "TEXT") == 0 &&
> +               pg_strcasecmp(prev_wd, "SEARCH") == 0)
> +     {
>
> +         static const char *const list_ALTERTEXTSEARCH[] =
> +         {"CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE", NULL};
>
> !         COMPLETE_WITH_LIST(list_ALTERTEXTSEARCH);
> !     }
> !
>   /* EXPLAIN */
>
>       /*
> ***************
> *** 1873,1878 ****
> --- 2014,2027 ----
>           COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL);
>       else if (strcmp(prev_wd, "\\df") == 0 || strcmp(prev_wd, "\\df+") == 0)
>           COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
> +     else if (strcmp(prev_wd, "\\dF") == 0 || strcmp(prev_wd, "\\dF+") == 0)
> +         COMPLETE_WITH_QUERY(Query_for_list_of_ts_configurations);
> +     else if (strcmp(prev_wd, "\\dFd") == 0 || strcmp(prev_wd, "\\dFd+") == 0)
> +         COMPLETE_WITH_QUERY(Query_for_list_of_ts_dictionaries);
> +     else if (strcmp(prev_wd, "\\dFp") == 0 || strcmp(prev_wd, "\\dFp+") == 0)
> +         COMPLETE_WITH_QUERY(Query_for_list_of_ts_parsers);
> +     else if (strcmp(prev_wd, "\\dFt") == 0 || strcmp(prev_wd, "\\dFt+") == 0)
> +         COMPLETE_WITH_QUERY(Query_for_list_of_ts_templates);
>       else if (strcmp(prev_wd, "\\di") == 0 || strcmp(prev_wd, "\\di+") == 0)
>           COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
>       else if (strcmp(prev_wd, "\\dn") == 0)
> ***************
> *** 1985,1992 ****
>   static char *
>   create_command_generator(const char *text, int state)
>   {
> !     static int    list_index,
> !                 string_length;
>       const char *name;
>
>       /* If this is the first time for this completion, init some values */
> --- 2134,2140 ----
>   static char *
>   create_command_generator(const char *text, int state)
>   {
> !     static int list_index, string_length;
>       const char *name;
>
>       /* If this is the first time for this completion, init some values */
> ***************
> *** 1998,2006 ****
>
>       /* find something that matches */
>       while ((name = words_after_create[list_index++].name))
> !         if (pg_strncasecmp(name, text, string_length) == 0)
> !             return pg_strdup(name);
> !
>       /* if nothing matches, return NULL */
>       return NULL;
>   }
> --- 2146,2155 ----
>
>       /* find something that matches */
>       while ((name = words_after_create[list_index++].name))
> !     {
> !              if ((pg_strncasecmp(name, text, string_length) == 0) && !words_after_create[list_index - 1].noshow)
> !                     return pg_strdup(name);
> !     }
>       /* if nothing matches, return NULL */
>       return NULL;
>   }
> ***************
> *** 2014,2021 ****
>   static char *
>   drop_command_generator(const char *text, int state)
>   {
> !     static int    list_index,
> !                 string_length;
>       const char *name;
>
>       if (state == 0)
> --- 2163,2169 ----
>   static char *
>   drop_command_generator(const char *text, int state)
>   {
> !     static int    list_index, string_length;
>       const char *name;
>
>       if (state == 0)
> ***************
> *** 2043,2049 ****
>        */
>       while ((name = words_after_create[list_index++ - 1].name))
>       {
> !         if (pg_strncasecmp(name, text, string_length) == 0)
>               return pg_strdup(name);
>       }
>
> --- 2191,2197 ----
>        */
>       while ((name = words_after_create[list_index++ - 1].name))
>       {
> !         if ((pg_strncasecmp(name, text, string_length) == 0) && (!words_after_create[list_index - 2].noshow))
>               return pg_strdup(name);
>       }
>

>
> ---------------------------(end of broadcast)---------------------------
> TIP 9: In versions below 8.0, the planner will ignore your desire to
>        choose an index scan if your joining column's datatypes do not
>        match

--
  Bruce Momjian  <bruce@momjian.us>          http://momjian.us
  EnterpriseDB                               http://www.enterprisedb.com

  + If your life is a hard drive, Christ can be your backup. +

В списке pgsql-patches по дате отправления:

Предыдущее
От: Bruce Momjian
Дата:
Сообщение: Re: [HACKERS] PGparam extension version 0.4
Следующее
От: Bruce Momjian
Дата:
Сообщение: Re: XLogCacheByte is unused