@@ -982,10 +982,11 @@ typedef struct
982982
983983#define THING_NO_CREATE (1 << 0) /* should not show up after CREATE */
984984#define THING_NO_DROP (1 << 1) /* should not show up after DROP */
985- #define THING_NO_SHOW (THING_NO_CREATE | THING_NO_DROP)
985+ #define THING_NO_ALTER (1 << 2) /* should not show up after ALTER */
986+ #define THING_NO_SHOW (THING_NO_CREATE | THING_NO_DROP | THING_NO_ALTER)
986987
987988static const pgsql_thing_t words_after_create [] = {
988- {"ACCESS METHOD" , NULL , NULL },
989+ {"ACCESS METHOD" , NULL , NULL , THING_NO_ALTER },
989990 {"AGGREGATE" , NULL , & Query_for_list_of_aggregates },
990991 {"CAST" , NULL , NULL }, /* Casts have complex structures for names, so
991992 * skip it */
@@ -999,19 +1000,21 @@ static const pgsql_thing_t words_after_create[] = {
9991000 {"CONVERSION" , "SELECT pg_catalog.quote_ident(conname) FROM pg_catalog.pg_conversion WHERE substring(pg_catalog.quote_ident(conname),1,%d)='%s'" },
10001001 {"DATABASE" , Query_for_list_of_databases },
10011002 {"DICTIONARY" , Query_for_list_of_ts_dictionaries , NULL , THING_NO_SHOW },
1003+ {"DEFAULT PRIVILEGES" , NULL , NULL , THING_NO_CREATE | THING_NO_DROP },
10021004 {"DOMAIN" , NULL , & Query_for_list_of_domains },
10031005 {"EVENT TRIGGER" , NULL , NULL },
10041006 {"EXTENSION" , Query_for_list_of_extensions },
10051007 {"FOREIGN DATA WRAPPER" , NULL , NULL },
10061008 {"FOREIGN TABLE" , NULL , NULL },
10071009 {"FUNCTION" , NULL , & Query_for_list_of_functions },
10081010 {"GROUP" , Query_for_list_of_roles },
1009- {"LANGUAGE" , Query_for_list_of_languages },
10101011 {"INDEX" , NULL , & Query_for_list_of_indexes },
1012+ {"LANGUAGE" , Query_for_list_of_languages },
1013+ {"LARGE OBJECT" , NULL , NULL , THING_NO_CREATE | THING_NO_DROP },
10111014 {"MATERIALIZED VIEW" , NULL , & Query_for_list_of_matviews },
10121015 {"OPERATOR" , NULL , NULL }, /* Querying for this is probably not such a
10131016 * good idea. */
1014- {"OWNED" , NULL , NULL , THING_NO_CREATE }, /* for DROP OWNED BY ... */
1017+ {"OWNED" , NULL , NULL , THING_NO_CREATE | THING_NO_ALTER }, /* for DROP OWNED BY ... */
10151018 {"PARSER" , Query_for_list_of_ts_parsers , NULL , THING_NO_SHOW },
10161019 {"POLICY" , NULL , NULL },
10171020 {"PUBLICATION" , Query_for_list_of_publications },
@@ -1021,15 +1024,18 @@ static const pgsql_thing_t words_after_create[] = {
10211024 {"SEQUENCE" , NULL , & Query_for_list_of_sequences },
10221025 {"SERVER" , Query_for_list_of_servers },
10231026 {"SUBSCRIPTION" , Query_for_list_of_subscriptions },
1027+ {"SYSTEM" , NULL , NULL , THING_NO_CREATE | THING_NO_DROP },
10241028 {"TABLE" , NULL , & Query_for_list_of_tables },
10251029 {"TABLESPACE" , Query_for_list_of_tablespaces },
1026- {"TEMP" , NULL , NULL , THING_NO_DROP }, /* for CREATE TEMP TABLE ... */
1030+ {"TEMP" , NULL , NULL , THING_NO_DROP | THING_NO_ALTER }, /* for CREATE TEMP TABLE ... */
10271031 {"TEMPLATE" , Query_for_list_of_ts_templates , NULL , THING_NO_SHOW },
1032+ {"TEMPORARY" , NULL , NULL , THING_NO_DROP | THING_NO_ALTER }, /* for CREATE TEMPORARY TABLE ... */
10281033 {"TEXT SEARCH" , NULL , NULL },
1034+ {"TRANSFORM" , NULL , NULL },
10291035 {"TRIGGER" , "SELECT pg_catalog.quote_ident(tgname) FROM pg_catalog.pg_trigger WHERE substring(pg_catalog.quote_ident(tgname),1,%d)='%s' AND NOT tgisinternal" },
10301036 {"TYPE" , NULL , & Query_for_list_of_datatypes },
1031- {"UNIQUE" , NULL , NULL , THING_NO_DROP }, /* for CREATE UNIQUE INDEX ... */
1032- {"UNLOGGED" , NULL , NULL , THING_NO_DROP }, /* for CREATE UNLOGGED TABLE
1037+ {"UNIQUE" , NULL , NULL , THING_NO_DROP | THING_NO_ALTER }, /* for CREATE UNIQUE INDEX ... */
1038+ {"UNLOGGED" , NULL , NULL , THING_NO_DROP | THING_NO_ALTER }, /* for CREATE UNLOGGED TABLE
10331039 * ... */
10341040 {"USER" , Query_for_list_of_roles },
10351041 {"USER MAPPING FOR" , NULL , NULL },
@@ -1042,6 +1048,7 @@ static const pgsql_thing_t words_after_create[] = {
10421048static char * * psql_completion (const char * text , int start , int end );
10431049static char * create_command_generator (const char * text , int state );
10441050static char * drop_command_generator (const char * text , int state );
1051+ static char * alter_command_generator (const char * text , int state );
10451052static char * complete_from_query (const char * text , int state );
10461053static char * complete_from_schema_query (const char * text , int state );
10471054static char * _complete_from_query (int is_schema_query ,
@@ -1316,6 +1323,17 @@ psql_completion(const char *text, int start, int end)
13161323 (previous_words_count >= 2 && \
13171324 word_matches_cs(p1, prev_wd) && \
13181325 word_matches_cs(p2, prev2_wd))
1326+ #define TailMatchesCS3 (p3 , p2 , p1 ) \
1327+ (previous_words_count >= 3 && \
1328+ word_matches_cs(p1, prev_wd) && \
1329+ word_matches_cs(p2, prev2_wd) && \
1330+ word_matches_cs(p3, prev3_wd))
1331+ #define TailMatchesCS4 (p4 , p3 , p2 , p1 ) \
1332+ (previous_words_count >= 4 && \
1333+ word_matches_cs(p1, prev_wd) && \
1334+ word_matches_cs(p2, prev2_wd) && \
1335+ word_matches_cs(p3, prev3_wd) && \
1336+ word_matches_cs(p4, prev4_wd))
13191337
13201338 /*
13211339 * Macros for matching N words beginning at the start of the line,
@@ -1459,17 +1477,7 @@ psql_completion(const char *text, int start, int end)
14591477
14601478 /* ALTER something */
14611479 else if (Matches1 ("ALTER" ))
1462- {
1463- static const char * const list_ALTER [] =
1464- {"AGGREGATE" , "COLLATION" , "CONVERSION" , "DATABASE" , "DEFAULT PRIVILEGES" , "DOMAIN" ,
1465- "EVENT TRIGGER" , "EXTENSION" , "FOREIGN DATA WRAPPER" , "FOREIGN TABLE" , "FUNCTION" ,
1466- "GROUP" , "INDEX" , "LANGUAGE" , "LARGE OBJECT" , "MATERIALIZED VIEW" , "OPERATOR" ,
1467- "POLICY" , "PUBLICATION" , "ROLE" , "RULE" , "SCHEMA" , "SERVER" , "SEQUENCE" ,
1468- "SUBSCRIPTION" , "SYSTEM" , "TABLE" , "TABLESPACE" , "TEXT SEARCH" , "TRIGGER" , "TYPE" ,
1469- "USER" , "USER MAPPING FOR" , "VIEW" , NULL };
1470-
1471- COMPLETE_WITH_LIST (list_ALTER );
1472- }
1480+ matches = completion_matches (text , alter_command_generator );
14731481 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx */
14741482 else if (TailMatches4 ("ALL" , "IN" , "TABLESPACE" , MatchAny ))
14751483 COMPLETE_WITH_LIST2 ("SET TABLESPACE" , "OWNED BY" );
@@ -2622,6 +2630,7 @@ psql_completion(const char *text, int start, int end)
26222630 else if (Matches3 ("DROP" , "OWNED" , "BY" ))
26232631 COMPLETE_WITH_QUERY (Query_for_list_of_roles );
26242632
2633+ /* DROP TEXT SEARCH */
26252634 else if (Matches3 ("DROP" , "TEXT" , "SEARCH" ))
26262635 COMPLETE_WITH_LIST4 ("CONFIGURATION" , "DICTIONARY" , "PARSER" , "TEMPLATE" );
26272636
@@ -3353,8 +3362,45 @@ psql_completion(const char *text, int start, int end)
33533362
33543363 else if (TailMatchesCS1 ("\\encoding" ))
33553364 COMPLETE_WITH_QUERY (Query_for_list_of_encodings );
3356- else if (TailMatchesCS1 ("\\h" ) || TailMatchesCS1 ( " \\help" ))
3365+ else if (TailMatchesCS1 ("\\h| \\help" ))
33573366 COMPLETE_WITH_LIST (sql_commands );
3367+ else if (TailMatchesCS2 ("\\h|\\help" , MatchAny ))
3368+ {
3369+ if (TailMatches1 ("DROP" ))
3370+ matches = completion_matches (text , drop_command_generator );
3371+ else if (TailMatches1 ("ALTER" ))
3372+ matches = completion_matches (text , alter_command_generator );
3373+ /* CREATE is recognized by tail match elsewhere, so doesn't need to be
3374+ * repeated here */
3375+ }
3376+ else if (TailMatchesCS3 ("\\h|\\help" , MatchAny , MatchAny ))
3377+ {
3378+ if (TailMatches2 ("CREATE|DROP" , "ACCESS" ))
3379+ COMPLETE_WITH_CONST ("METHOD" );
3380+ else if (TailMatches2 ("ALTER" , "DEFAULT" ))
3381+ COMPLETE_WITH_CONST ("PRIVILEGES" );
3382+ else if (TailMatches2 ("CREATE|ALTER|DROP" , "EVENT" ))
3383+ COMPLETE_WITH_CONST ("TRIGGER" );
3384+ else if (TailMatches2 ("CREATE|ALTER|DROP" , "FOREIGN" ))
3385+ COMPLETE_WITH_LIST2 ("DATA WRAPPER" , "TABLE" );
3386+ else if (TailMatches2 ("ALTER" , "LARGE" ))
3387+ COMPLETE_WITH_CONST ("OBJECT" );
3388+ else if (TailMatches2 ("CREATE|ALTER|DROP" , "MATERIALIZED" ))
3389+ COMPLETE_WITH_CONST ("VIEW" );
3390+ else if (TailMatches2 ("CREATE|ALTER|DROP" , "TEXT" ))
3391+ COMPLETE_WITH_CONST ("SEARCH" );
3392+ else if (TailMatches2 ("CREATE|ALTER|DROP" , "USER" ))
3393+ COMPLETE_WITH_CONST ("MAPPING FOR" );
3394+ }
3395+ else if (TailMatchesCS4 ("\\h|\\help" , MatchAny , MatchAny , MatchAny ))
3396+ {
3397+ if (TailMatches3 ("CREATE|ALTER|DROP" , "FOREIGN" , "DATA" ))
3398+ COMPLETE_WITH_CONST ("WRAPPER" );
3399+ else if (TailMatches3 ("CREATE|ALTER|DROP" , "TEXT" , "SEARCH" ))
3400+ COMPLETE_WITH_LIST4 ("CONFIGURATION" , "DICTIONARY" , "PARSER" , "TEMPLATE" );
3401+ else if (TailMatches3 ("CREATE|ALTER|DROP" , "USER" , "MAPPING" ))
3402+ COMPLETE_WITH_CONST ("FOR" );
3403+ }
33583404 else if (TailMatchesCS1 ("\\l*" ) && !TailMatchesCS1 ("\\lo*" ))
33593405 COMPLETE_WITH_QUERY (Query_for_list_of_databases );
33603406 else if (TailMatchesCS1 ("\\password" ))
@@ -3536,6 +3582,15 @@ drop_command_generator(const char *text, int state)
35363582 return create_or_drop_command_generator (text , state , THING_NO_DROP );
35373583}
35383584
3585+ /*
3586+ * This function gives you a list of things you can put after an ALTER command.
3587+ */
3588+ static char *
3589+ alter_command_generator (const char * text , int state )
3590+ {
3591+ return create_or_drop_command_generator (text , state , THING_NO_ALTER );
3592+ }
3593+
35393594/* The following two functions are wrappers for _complete_from_query */
35403595
35413596static char *
0 commit comments