@@ -598,10 +598,13 @@ typedef struct
598
598
const char * name ;
599
599
const char * query ;/* simple query, or NULL */
600
600
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 */
603
602
}pgsql_thing_t ;
604
603
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
+
605
608
static const pgsql_thing_t words_after_create []= {
606
609
{"AGGREGATE" ,NULL ,& Query_for_list_of_aggregates },
607
610
{"CAST" ,NULL ,NULL },/* Casts have complex structures for names, so
@@ -612,10 +615,10 @@ static const pgsql_thing_t words_after_create[] = {
612
615
* CREATE CONSTRAINT TRIGGER is not supported here because it is designed
613
616
* to be used only by pg_dump.
614
617
*/
615
- {"CONFIGURATION" ,Query_for_list_of_ts_configurations ,NULL ,true },
618
+ {"CONFIGURATION" ,Query_for_list_of_ts_configurations ,NULL ,THING_NO_SHOW },
616
619
{"CONVERSION" ,"SELECT pg_catalog.quote_ident(conname) FROM pg_catalog.pg_conversion WHERE substring(pg_catalog.quote_ident(conname),1,%d)='%s'" },
617
620
{"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 },
619
622
{"DOMAIN" ,NULL ,& Query_for_list_of_domains },
620
623
{"EXTENSION" ,Query_for_list_of_extensions },
621
624
{"FOREIGN DATA WRAPPER" ,NULL ,NULL },
@@ -626,24 +629,26 @@ static const pgsql_thing_t words_after_create[] = {
626
629
{"INDEX" ,NULL ,& Query_for_list_of_indexes },
627
630
{"OPERATOR" ,NULL ,NULL },/* Querying for this is probably not such a
628
631
* 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 },
630
634
{"ROLE" ,Query_for_list_of_roles },
631
635
{"RULE" ,"SELECT pg_catalog.quote_ident(rulename) FROM pg_catalog.pg_rules WHERE substring(pg_catalog.quote_ident(rulename),1,%d)='%s'" },
632
636
{"SCHEMA" ,Query_for_list_of_schemas },
633
637
{"SEQUENCE" ,NULL ,& Query_for_list_of_sequences },
634
638
{"SERVER" ,Query_for_list_of_servers },
635
639
{"TABLE" ,NULL ,& Query_for_list_of_tables },
636
640
{"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 },
639
643
{"TEXT SEARCH" ,NULL ,NULL },
640
644
{"TRIGGER" ,"SELECT pg_catalog.quote_ident(tgname) FROM pg_catalog.pg_trigger WHERE substring(pg_catalog.quote_ident(tgname),1,%d)='%s'" },
641
645
{"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 ... */
643
648
{"USER" ,Query_for_list_of_roles },
644
649
{"USER MAPPING FOR" ,NULL ,NULL },
645
650
{"VIEW" ,NULL ,& Query_for_list_of_views },
646
- {NULL , NULL , NULL , false }/* end of list */
651
+ {NULL }/* end of list */
647
652
};
648
653
649
654
@@ -1771,6 +1776,12 @@ psql_completion(char *text, int start, int end)
1771
1776
1772
1777
COMPLETE_WITH_LIST (list_TEMP );
1773
1778
}
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
+ }
1774
1785
1775
1786
/* CREATE TABLESPACE */
1776
1787
else if (pg_strcasecmp (prev3_wd ,"CREATE" )== 0 &&
@@ -2858,11 +2869,11 @@ psql_completion(char *text, int start, int end)
2858
2869
*/
2859
2870
2860
2871
/*
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 .
2863
2874
*/
2864
2875
static char *
2865
- create_command_generator (const char * text ,int state )
2876
+ create_or_drop_command_generator (const char * text ,int state , bits32 excluded )
2866
2877
{
2867
2878
static int list_index ,
2868
2879
string_length ;
@@ -2879,57 +2890,30 @@ create_command_generator(const char *text, int state)
2879
2890
while ((name = words_after_create [list_index ++ ].name ))
2880
2891
{
2881
2892
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 ) )
2883
2894
return pg_strdup (name );
2884
2895
}
2885
2896
/* if nothing matches, return NULL */
2886
2897
return NULL ;
2887
2898
}
2888
2899
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
+
2889
2910
/*
2890
2911
* 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.)
2894
2912
*/
2895
2913
static char *
2896
2914
drop_command_generator (const char * text ,int state )
2897
2915
{
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 );
2933
2917
}
2934
2918
2935
2919
/* The following two functions are wrappers for _complete_from_query */