@@ -813,8 +813,11 @@ static char *_complete_from_query(int is_schema_query,
813813 const char * text , int state );
814814static char * complete_from_list (const char * text , int state );
815815static char * complete_from_const (const char * text , int state );
816+ static void append_variable_names (char * * * varnames , int * nvars ,
817+ int * maxvars , const char * varname ,
818+ const char * prefix , const char * suffix );
816819static char * * complete_from_variables (const char * text ,
817- const char * prefix , const char * suffix );
820+ const char * prefix , const char * suffix , bool need_value );
818821static char * complete_from_files (const char * text , int state );
819822
820823static char * pg_strdup_keyword_case (const char * s , const char * ref );
@@ -925,11 +928,11 @@ psql_completion(const char *text, int start, int end)
925928 else if (text [0 ] == ':' && text [1 ] != ':' )
926929 {
927930 if (text [1 ] == '\'' )
928- matches = complete_from_variables (text , ":'" , "'" );
931+ matches = complete_from_variables (text , ":'" , "'" , true );
929932 else if (text [1 ] == '"' )
930- matches = complete_from_variables (text , ":\"" , "\"" );
933+ matches = complete_from_variables (text , ":\"" , "\"" , true );
931934 else
932- matches = complete_from_variables (text , ":" , "" );
935+ matches = complete_from_variables (text , ":" , "" , true );
933936 }
934937
935938 /* If no previous word, suggest one of the basic sql commands */
@@ -3604,9 +3607,71 @@ psql_completion(const char *text, int start, int end)
36043607 COMPLETE_WITH_LIST_CS (my_list );
36053608 }
36063609 }
3610+ else if (strcmp (prev_wd , "\\unset" ) == 0 )
3611+ {
3612+ matches = complete_from_variables (text , "" , "" , true);
3613+ }
36073614 else if (strcmp (prev_wd , "\\set" ) == 0 )
36083615 {
3609- matches = complete_from_variables (text , "" , "" );
3616+ matches = complete_from_variables (text , "" , "" , false);
3617+ }
3618+ else if (strcmp (prev2_wd , "\\set" ) == 0 )
3619+ {
3620+ static const char * const boolean_value_list [] =
3621+ {"on" , "off" , NULL };
3622+
3623+ if (strcmp (prev_wd , "AUTOCOMMIT" ) == 0 )
3624+ COMPLETE_WITH_LIST_CS (boolean_value_list );
3625+ else if (strcmp (prev_wd , "COMP_KEYWORD_CASE" ) == 0 )
3626+ {
3627+ static const char * const my_list [] =
3628+ {"lower" , "upper" , "preserve-lower" , "preserve-upper" , NULL };
3629+
3630+ COMPLETE_WITH_LIST_CS (my_list );
3631+ }
3632+ else if (strcmp (prev_wd , "ECHO" ) == 0 )
3633+ {
3634+ static const char * const my_list [] =
3635+ {"errors" , "queries" , "all" , "none" , NULL };
3636+
3637+ COMPLETE_WITH_LIST_CS (my_list );
3638+ }
3639+ else if (strcmp (prev_wd , "ECHO_HIDDEN" ) == 0 )
3640+ {
3641+ static const char * const my_list [] =
3642+ {"noexec" , "off" , "on" , NULL };
3643+
3644+ COMPLETE_WITH_LIST_CS (my_list );
3645+ }
3646+ else if (strcmp (prev_wd , "HISTCONTROL" ) == 0 )
3647+ {
3648+ static const char * const my_list [] =
3649+ {"ignorespace" , "ignoredups" , "ignoreboth" , "none" , NULL };
3650+
3651+ COMPLETE_WITH_LIST_CS (my_list );
3652+ }
3653+ else if (strcmp (prev_wd , "ON_ERROR_ROLLBACK" ) == 0 )
3654+ {
3655+ static const char * const my_list [] =
3656+ {"on" , "off" , "interactive" , NULL };
3657+
3658+ COMPLETE_WITH_LIST_CS (my_list );
3659+ }
3660+ else if (strcmp (prev_wd , "ON_ERROR_STOP" ) == 0 )
3661+ COMPLETE_WITH_LIST_CS (boolean_value_list );
3662+ else if (strcmp (prev_wd , "QUIET" ) == 0 )
3663+ COMPLETE_WITH_LIST_CS (boolean_value_list );
3664+ else if (strcmp (prev_wd , "SINGLELINE" ) == 0 )
3665+ COMPLETE_WITH_LIST_CS (boolean_value_list );
3666+ else if (strcmp (prev_wd , "SINGLESTEP" ) == 0 )
3667+ COMPLETE_WITH_LIST_CS (boolean_value_list );
3668+ else if (strcmp (prev_wd , "VERBOSITY" ) == 0 )
3669+ {
3670+ static const char * const my_list [] =
3671+ {"default" , "verbose" , "terse" , NULL };
3672+
3673+ COMPLETE_WITH_LIST_CS (my_list );
3674+ }
36103675 }
36113676 else if (strcmp (prev_wd , "\\sf" ) == 0 || strcmp (prev_wd , "\\sf+" ) == 0 )
36123677 COMPLETE_WITH_SCHEMA_QUERY (Query_for_list_of_functions , NULL );
@@ -4052,13 +4117,40 @@ complete_from_const(const char *text, int state)
40524117}
40534118
40544119
4120+ /*
4121+ * This function appends the variable name with prefix and suffix to
4122+ * the variable names array.
4123+ */
4124+ static void
4125+ append_variable_names (char * * * varnames , int * nvars ,
4126+ int * maxvars , const char * varname ,
4127+ const char * prefix , const char * suffix )
4128+ {
4129+ if (* nvars >= * maxvars )
4130+ {
4131+ * maxvars *= 2 ;
4132+ * varnames = (char * * ) realloc (* varnames ,
4133+ ((* maxvars ) + 1 ) * sizeof (char * ));
4134+ if (!(* varnames ))
4135+ {
4136+ psql_error ("out of memory\n" );
4137+ exit (EXIT_FAILURE );
4138+ }
4139+ }
4140+
4141+ (* varnames )[(* nvars )++ ] = psprintf ("%s%s%s" , prefix , varname , suffix );
4142+ }
4143+
4144+
40554145/*
40564146 * This function supports completion with the name of a psql variable.
40574147 * The variable names can be prefixed and suffixed with additional text
4058- * to support quoting usages.
4148+ * to support quoting usages. If need_value is true, only the variables
4149+ * that have the set values are picked up.
40594150 */
40604151static char * *
4061- complete_from_variables (const char * text , const char * prefix , const char * suffix )
4152+ complete_from_variables (const char * text , const char * prefix , const char * suffix ,
4153+ bool need_value )
40624154{
40634155 char * * matches ;
40644156 char * * varnames ;
@@ -4067,23 +4159,34 @@ complete_from_variables(const char *text, const char *prefix, const char *suffix
40674159 int i ;
40684160 struct _variable * ptr ;
40694161
4162+ static const char * const known_varnames [] = {
4163+ "AUTOCOMMIT" , "COMP_KEYWORD_CASE" , "DBNAME" , "ECHO" , "ECHO_HIDDEN" ,
4164+ "ENCODING" , "FETCH_COUNT" , "HISTCONTROL" , "HISTFILE" , "HISTSIZE" ,
4165+ "HOST" , "IGNOREEOF" , "LASTOID" , "ON_ERROR_ROLLBACK" , "ON_ERROR_STOP" ,
4166+ "PORT" , "PROMPT1" , "PROMPT2" , "PROMPT3" , "QUIET" , "SINGLELINE" ,
4167+ "SINGLESTEP" , "USER" , "VERBOSITY" , NULL
4168+ };
4169+
40704170 varnames = (char * * ) pg_malloc ((maxvars + 1 ) * sizeof (char * ));
40714171
4172+ if (!need_value )
4173+ {
4174+ for (i = 0 ; known_varnames [i ] && nvars < maxvars ; i ++ )
4175+ append_variable_names (& varnames , & nvars , & maxvars ,
4176+ known_varnames [i ], prefix , suffix );
4177+ }
4178+
40724179 for (ptr = pset .vars -> next ; ptr ; ptr = ptr -> next )
40734180 {
4074- if (nvars >= maxvars )
4181+ if (need_value && !(ptr -> value ))
4182+ continue ;
4183+ for (i = 0 ; known_varnames [i ]; i ++ ) /* remove duplicate entry */
40754184 {
4076- maxvars *= 2 ;
4077- varnames = (char * * ) realloc (varnames ,
4078- (maxvars + 1 ) * sizeof (char * ));
4079- if (!varnames )
4080- {
4081- psql_error ("out of memory\n" );
4082- exit (EXIT_FAILURE );
4083- }
4185+ if (strcmp (ptr -> name , known_varnames [i ]) == 0 )
4186+ continue ;
40844187 }
4085-
4086- varnames [ nvars ++ ] = psprintf ( "%s%s%s" , prefix , ptr -> name , suffix );
4188+ append_variable_names ( & varnames , & nvars , & maxvars , ptr -> name ,
4189+ prefix , suffix );
40874190 }
40884191
40894192 varnames [nvars ] = NULL ;
0 commit comments