@@ -132,6 +132,7 @@ static const char *const * completion_charpp;/* to pass a list of strings */
132132static const char * completion_info_charp ;/* to pass a second string */
133133static const char * completion_info_charp2 ;/* to pass a third string */
134134static const SchemaQuery * completion_squery ;/* to pass a SchemaQuery */
135+ static bool completion_case_sensitive ;/* completion is case sensitive */
135136
136137/*
137138 * A few macros to ease typing. You can use these to complete the given
@@ -155,15 +156,24 @@ do { \
155156matches = completion_matches(text, complete_from_schema_query); \
156157} while (0)
157158
159+ #define COMPLETE_WITH_LIST_CS (list ) \
160+ do { \
161+ completion_charpp = list; \
162+ completion_case_sensitive = true; \
163+ matches = completion_matches(text, complete_from_list); \
164+ } while (0)
165+
158166#define COMPLETE_WITH_LIST (list ) \
159167do { \
160168completion_charpp = list; \
169+ completion_case_sensitive = false; \
161170matches = completion_matches(text, complete_from_list); \
162171} while (0)
163172
164173#define COMPLETE_WITH_CONST (string ) \
165174do { \
166175completion_charp = string; \
176+ completion_case_sensitive = false; \
167177matches = completion_matches(text, complete_from_const); \
168178} while (0)
169179
@@ -671,6 +681,7 @@ static char *complete_from_const(const char *text, int state);
671681static char * * complete_from_variables (char * text ,
672682const char * prefix ,const char * suffix );
673683
684+ static char * pg_strdup_same_case (const char * s ,const char * ref );
674685static PGresult * exec_query (const char * query );
675686
676687static void get_previous_words (int point ,char * * previous_words ,int nwords );
@@ -771,7 +782,7 @@ psql_completion(char *text, int start, int end)
771782
772783/* If a backslash command was started, continue */
773784if (text [0 ]== '\\' )
774- COMPLETE_WITH_LIST (backslash_commands );
785+ COMPLETE_WITH_LIST_CS (backslash_commands );
775786
776787/* Variable interpolation */
777788else if (text [0 ]== ':' && text [1 ]!= ':' )
@@ -2907,7 +2918,7 @@ psql_completion(char *text, int start, int end)
29072918"null" ,"fieldsep" ,"tuples_only" ,"title" ,"tableattr" ,
29082919"linestyle" ,"pager" ,"recordsep" ,NULL };
29092920
2910- COMPLETE_WITH_LIST (my_list );
2921+ COMPLETE_WITH_LIST_CS (my_list );
29112922}
29122923else if (strcmp (prev2_wd ,"\\pset" )== 0 )
29132924{
@@ -2917,14 +2928,14 @@ psql_completion(char *text, int start, int end)
29172928{"unaligned" ,"aligned" ,"wrapped" ,"html" ,"latex" ,
29182929"troff-ms" ,NULL };
29192930
2920- COMPLETE_WITH_LIST (my_list );
2931+ COMPLETE_WITH_LIST_CS (my_list );
29212932}
29222933else if (strcmp (prev_wd ,"linestyle" )== 0 )
29232934{
29242935static const char * const my_list []=
29252936{"ascii" ,"old-ascii" ,"unicode" ,NULL };
29262937
2927- COMPLETE_WITH_LIST (my_list );
2938+ COMPLETE_WITH_LIST_CS (my_list );
29282939}
29292940}
29302941else if (strcmp (prev_wd ,"\\set" )== 0 )
@@ -3030,7 +3041,7 @@ create_or_drop_command_generator(const char *text, int state, bits32 excluded)
30303041{
30313042if ((pg_strncasecmp (name ,text ,string_length )== 0 )&&
30323043!(words_after_create [list_index - 1 ].flags & excluded ))
3033- return pg_strdup (name );
3044+ return pg_strdup_same_case (name , text );
30343045}
30353046/* if nothing matches, return NULL */
30363047return NULL ;
@@ -3298,7 +3309,7 @@ complete_from_list(const char *text, int state)
32983309{
32993310list_index = 0 ;
33003311string_length = strlen (text );
3301- casesensitive = true ;
3312+ casesensitive = completion_case_sensitive ;
33023313matches = 0 ;
33033314}
33043315
@@ -3313,7 +3324,14 @@ complete_from_list(const char *text, int state)
33133324
33143325/* Second pass is case insensitive, don't bother counting matches */
33153326if (!casesensitive && pg_strncasecmp (text ,item ,string_length )== 0 )
3316- return pg_strdup (item );
3327+ {
3328+ if (completion_case_sensitive )
3329+ return pg_strdup (item );
3330+ else
3331+ /* If case insensitive matching was requested initially, return
3332+ * it in the case of what was already entered. */
3333+ return pg_strdup_same_case (item ,text );
3334+ }
33173335}
33183336
33193337/*
@@ -3343,12 +3361,16 @@ complete_from_list(const char *text, int state)
33433361static char *
33443362complete_from_const (const char * text ,int state )
33453363{
3346- (void )text ;/* We don't care about what was entered
3347- * already. */
3348-
33493364psql_assert (completion_charp );
33503365if (state == 0 )
3351- return pg_strdup (completion_charp );
3366+ {
3367+ if (completion_case_sensitive )
3368+ return pg_strdup (completion_charp );
3369+ else
3370+ /* If case insensitive matching was requested initially, return it
3371+ * in the case of what was already entered. */
3372+ return pg_strdup_same_case (completion_charp ,text );
3373+ }
33523374else
33533375return NULL ;
33543376}
@@ -3394,7 +3416,7 @@ complete_from_variables(char *text, const char *prefix, const char *suffix)
33943416}
33953417
33963418varnames [nvars ]= NULL ;
3397- COMPLETE_WITH_LIST ((const char * const * )varnames );
3419+ COMPLETE_WITH_LIST_CS ((const char * const * )varnames );
33983420
33993421for (i = 0 ;i < nvars ;i ++ )
34003422free (varnames [i ]);
@@ -3407,6 +3429,31 @@ complete_from_variables(char *text, const char *prefix, const char *suffix)
34073429/* HELPER FUNCTIONS */
34083430
34093431
3432+ /*
3433+ * Make a pg_strdup copy of s and convert it to the same case as ref.
3434+ */
3435+ static char *
3436+ pg_strdup_same_case (const char * s ,const char * ref )
3437+ {
3438+ char * ret ,* p ;
3439+ unsignedchar first = ref [0 ];
3440+
3441+ if (isalpha (first ))
3442+ {
3443+ ret = pg_strdup (s );
3444+ if (islower (first ))
3445+ for (p = ret ;* p ;p ++ )
3446+ * p = pg_tolower ((unsignedchar )* p );
3447+ else
3448+ for (p = ret ;* p ;p ++ )
3449+ * p = pg_toupper ((unsignedchar )* p );
3450+ return ret ;
3451+ }
3452+ else
3453+ return pg_strdup (s );
3454+ }
3455+
3456+
34103457/*
34113458 * Execute a query and report any errors. This should be the preferred way of
34123459 * talking to the database in this file.