@@ -598,10 +598,13 @@ typedef struct
598598 const char * name ;
599599 const char * query ; /* simple query, or NULL */
600600 const SchemaQuery * squery ; /* schema query, or NULL */
601- const bool noshow ; /* NULL or true if this word should not show
602- * up after CREATE or DROP */
601+ const bits32 flags ; /* visibility flags, see below */
603602} pgsql_thing_t ;
604603
604+ #define THING_NO_CREATE (1 << 0) /* should not show up after CREATE */
605+ #define THING_NO_DROP (1 << 1) /* should not show up after DROP */
606+ #define THING_NO_SHOW (THING_NO_CREATE | THING_NO_DROP)
607+
605608static const pgsql_thing_t words_after_create [] = {
606609 {"AGGREGATE" , NULL , & Query_for_list_of_aggregates },
607610 {"CAST" , NULL , NULL }, /* Casts have complex structures for names, so
@@ -612,10 +615,10 @@ static const pgsql_thing_t words_after_create[] = {
612615 * CREATE CONSTRAINT TRIGGER is not supported here because it is designed
613616 * to be used only by pg_dump.
614617 */
615- {"CONFIGURATION" , Query_for_list_of_ts_configurations , NULL , true },
618+ {"CONFIGURATION" , Query_for_list_of_ts_configurations , NULL , THING_NO_SHOW },
616619 {"CONVERSION" , "SELECT pg_catalog.quote_ident(conname) FROM pg_catalog.pg_conversion WHERE substring(pg_catalog.quote_ident(conname),1,%d)='%s'" },
617620 {"DATABASE" , Query_for_list_of_databases },
618- {"DICTIONARY" , Query_for_list_of_ts_dictionaries , NULL , true },
621+ {"DICTIONARY" , Query_for_list_of_ts_dictionaries , NULL , THING_NO_SHOW },
619622 {"DOMAIN" , NULL , & Query_for_list_of_domains },
620623 {"EXTENSION" , Query_for_list_of_extensions },
621624 {"FOREIGN DATA WRAPPER" , NULL , NULL },
@@ -626,24 +629,26 @@ static const pgsql_thing_t words_after_create[] = {
626629 {"INDEX" , NULL , & Query_for_list_of_indexes },
627630 {"OPERATOR" , NULL , NULL }, /* Querying for this is probably not such a
628631 * good idea. */
629- {"PARSER" , Query_for_list_of_ts_parsers , NULL , true},
632+ {"OWNED" , NULL , NULL , THING_NO_CREATE }, /* for DROP OWNED BY ... */
633+ {"PARSER" , Query_for_list_of_ts_parsers , NULL , THING_NO_SHOW },
630634 {"ROLE" , Query_for_list_of_roles },
631635 {"RULE" , "SELECT pg_catalog.quote_ident(rulename) FROM pg_catalog.pg_rules WHERE substring(pg_catalog.quote_ident(rulename),1,%d)='%s'" },
632636 {"SCHEMA" , Query_for_list_of_schemas },
633637 {"SEQUENCE" , NULL , & Query_for_list_of_sequences },
634638 {"SERVER" , Query_for_list_of_servers },
635639 {"TABLE" , NULL , & Query_for_list_of_tables },
636640 {"TABLESPACE" , Query_for_list_of_tablespaces },
637- {"TEMP" , NULL , NULL }, /* for CREATE TEMP TABLE ... */
638- {"TEMPLATE" , Query_for_list_of_ts_templates , NULL , true },
641+ {"TEMP" , NULL , NULL , THING_NO_DROP }, /* for CREATE TEMP TABLE ... */
642+ {"TEMPLATE" , Query_for_list_of_ts_templates , NULL , THING_NO_SHOW },
639643 {"TEXT SEARCH" , NULL , NULL },
640644 {"TRIGGER" , "SELECT pg_catalog.quote_ident(tgname) FROM pg_catalog.pg_trigger WHERE substring(pg_catalog.quote_ident(tgname),1,%d)='%s'" },
641645 {"TYPE" , NULL , & Query_for_list_of_datatypes },
642- {"UNIQUE" , NULL , NULL }, /* for CREATE UNIQUE INDEX ... */
646+ {"UNIQUE" , NULL , NULL , THING_NO_DROP }, /* for CREATE UNIQUE INDEX ... */
647+ {"UNLOGGED" , NULL , NULL , THING_NO_DROP },/* for CREATE UNLOGGED TABLE ... */
643648 {"USER" , Query_for_list_of_roles },
644649 {"USER MAPPING FOR" , NULL , NULL },
645650 {"VIEW" , NULL , & Query_for_list_of_views },
646- {NULL , NULL , NULL , false } /* end of list */
651+ {NULL } /* end of list */
647652};
648653
649654
@@ -1771,6 +1776,12 @@ psql_completion(char *text, int start, int end)
17711776
17721777 COMPLETE_WITH_LIST (list_TEMP );
17731778 }
1779+ /* Complete "CREATE UNLOGGED" with TABLE */
1780+ else if (pg_strcasecmp (prev2_wd , "CREATE" ) == 0 &&
1781+ pg_strcasecmp (prev_wd , "UNLOGGED" ) == 0 )
1782+ {
1783+ COMPLETE_WITH_CONST ("TABLE" );
1784+ }
17741785
17751786/* CREATE TABLESPACE */
17761787 else if (pg_strcasecmp (prev3_wd , "CREATE" ) == 0 &&
@@ -2858,11 +2869,11 @@ psql_completion(char *text, int start, int end)
28582869 */
28592870
28602871/*
2861- * This one gives you one from a list of things you can put after CREATE
2862- * as defined above .
2872+ * Common routine for create_command_generator and drop_command_generator.
2873+ * Entries that have 'excluded' flags are not returned .
28632874 */
28642875static char *
2865- create_command_generator (const char * text , int state )
2876+ create_or_drop_command_generator (const char * text , int state , bits32 excluded )
28662877{
28672878 static int list_index ,
28682879 string_length ;
@@ -2879,57 +2890,30 @@ create_command_generator(const char *text, int state)
28792890 while ((name = words_after_create [list_index ++ ].name ))
28802891 {
28812892 if ((pg_strncasecmp (name , text , string_length ) == 0 ) &&
2882- !words_after_create [list_index - 1 ].noshow )
2893+ !( words_after_create [list_index - 1 ].flags & excluded ) )
28832894 return pg_strdup (name );
28842895 }
28852896 /* if nothing matches, return NULL */
28862897 return NULL ;
28872898}
28882899
2900+ /*
2901+ * This one gives you one from a list of things you can put after CREATE
2902+ * as defined above.
2903+ */
2904+ static char *
2905+ create_command_generator (const char * text , int state )
2906+ {
2907+ return create_or_drop_command_generator (text , state , THING_NO_CREATE );
2908+ }
2909+
28892910/*
28902911 * This function gives you a list of things you can put after a DROP command.
2891- * Very similar to create_command_generator, but has an additional entry for
2892- * OWNED BY. (We do it this way in order not to duplicate the
2893- * words_after_create list.)
28942912 */
28952913static char *
28962914drop_command_generator (const char * text , int state )
28972915{
2898- static int list_index ,
2899- string_length ;
2900- const char * name ;
2901-
2902- if (state == 0 )
2903- {
2904- /* If this is the first time for this completion, init some values */
2905- list_index = 0 ;
2906- string_length = strlen (text );
2907-
2908- /*
2909- * DROP can be followed by "OWNED BY", which is not found in the list
2910- * for CREATE matches, so make it the first state. (We do not make it
2911- * the last state because it would be more difficult to detect when we
2912- * have to return NULL instead.)
2913- *
2914- * Make sure we advance to the next state.
2915- */
2916- list_index ++ ;
2917- if (pg_strncasecmp ("OWNED" , text , string_length ) == 0 )
2918- return pg_strdup ("OWNED" );
2919- }
2920-
2921- /*
2922- * In subsequent attempts, try to complete with the same items we use for
2923- * CREATE
2924- */
2925- while ((name = words_after_create [list_index ++ - 1 ].name ))
2926- {
2927- if ((pg_strncasecmp (name , text , string_length ) == 0 ) && (!words_after_create [list_index - 2 ].noshow ))
2928- return pg_strdup (name );
2929- }
2930-
2931- /* if nothing matches, return NULL */
2932- return NULL ;
2916+ return create_or_drop_command_generator (text , state , THING_NO_DROP );
29332917}
29342918
29352919/* The following two functions are wrappers for _complete_from_query */
0 commit comments