diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index a27ef69..5d042f0 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -132,6 +132,7 @@ static const char *const * completion_charpp;	/* to pass a list of strings */
 static const char *completion_info_charp;		/* to pass a second string */
 static const char *completion_info_charp2;		/* to pass a third string */
 static const SchemaQuery *completion_squery;	/* to pass a SchemaQuery */
+static bool completion_case_sensitive;			/* completion is case sensitive */
 
 /*
  * A few macros to ease typing. You can use these to complete the given
@@ -155,15 +156,24 @@ do { \
 	matches = completion_matches(text, complete_from_schema_query); \
 } while (0)
 
+#define COMPLETE_WITH_LIST_CS(list) \
+do { \
+	completion_charpp = list; \
+	completion_case_sensitive = true; \
+	matches = completion_matches(text, complete_from_list); \
+} while (0)
+
 #define COMPLETE_WITH_LIST(list) \
 do { \
 	completion_charpp = list; \
+	completion_case_sensitive = false; \
 	matches = completion_matches(text, complete_from_list); \
 } while (0)
 
 #define COMPLETE_WITH_CONST(string) \
 do { \
 	completion_charp = string; \
+	completion_case_sensitive = false; \
 	matches = completion_matches(text, complete_from_const); \
 } while (0)
 
@@ -771,7 +781,7 @@ psql_completion(char *text, int start, int end)
 
 	/* If a backslash command was started, continue */
 	if (text[0] == '\\')
-		COMPLETE_WITH_LIST(backslash_commands);
+		COMPLETE_WITH_LIST_CS(backslash_commands);
 
 	/* Variable interpolation */
 	else if (text[0] == ':' && text[1] != ':')
@@ -2864,7 +2874,7 @@ psql_completion(char *text, int start, int end)
 			"null", "fieldsep", "tuples_only", "title", "tableattr",
 		"linestyle", "pager", "recordsep", NULL};
 
-		COMPLETE_WITH_LIST(my_list);
+		COMPLETE_WITH_LIST_CS(my_list);
 	}
 	else if (strcmp(prev2_wd, "\\pset") == 0)
 	{
@@ -2874,14 +2884,14 @@ psql_completion(char *text, int start, int end)
 			{"unaligned", "aligned", "wrapped", "html", "latex",
 			"troff-ms", NULL};
 
-			COMPLETE_WITH_LIST(my_list);
+			COMPLETE_WITH_LIST_CS(my_list);
 		}
 		else if (strcmp(prev_wd, "linestyle") == 0)
 		{
 			static const char *const my_list[] =
 			{"ascii", "old-ascii", "unicode", NULL};
 
-			COMPLETE_WITH_LIST(my_list);
+			COMPLETE_WITH_LIST_CS(my_list);
 		}
 	}
 	else if (strcmp(prev_wd, "\\set") == 0)
@@ -3234,6 +3244,31 @@ _complete_from_query(int is_schema_query, const char *text, int state)
 
 
 /*
+ * Make a pg_strdup copy of s and convert it to the same case as ref.
+ */
+static char *
+pg_strdup_same_case(const char *s, const char *ref)
+{
+	char *ret, *p;
+	unsigned char first = ref[0];
+
+	if (isalpha(first))
+	{
+		ret = pg_strdup(s);
+		if (islower(first))
+			for (p = ret; *p; p++)
+				*p = pg_tolower((unsigned char) *p);
+		else
+			for (p = ret; *p; p++)
+				*p = pg_toupper((unsigned char) *p);
+		return ret;
+	}
+	else
+		return pg_strdup(s);
+}
+
+
+/*
  * This function returns in order one of a fixed, NULL pointer terminated list
  * of strings (if matching). This can be used if there are only a fixed number
  * SQL words that can appear at certain spot.
@@ -3255,7 +3290,7 @@ complete_from_list(const char *text, int state)
 	{
 		list_index = 0;
 		string_length = strlen(text);
-		casesensitive = true;
+		casesensitive = completion_case_sensitive;
 		matches = 0;
 	}
 
@@ -3270,7 +3305,14 @@ complete_from_list(const char *text, int state)
 
 		/* Second pass is case insensitive, don't bother counting matches */
 		if (!casesensitive && pg_strncasecmp(text, item, string_length) == 0)
-			return pg_strdup(item);
+		{
+			if (completion_case_sensitive)
+				return pg_strdup(item);
+			else
+				/* If case insensitive matching was requested initially, return
+				 * it in the case of what was already entered. */
+				return pg_strdup_same_case(item, text);
+		}
 	}
 
 	/*
@@ -3300,12 +3342,16 @@ complete_from_list(const char *text, int state)
 static char *
 complete_from_const(const char *text, int state)
 {
-	(void) text;				/* We don't care about what was entered
-								 * already. */
-
 	psql_assert(completion_charp);
 	if (state == 0)
-		return pg_strdup(completion_charp);
+	{
+		if (completion_case_sensitive)
+			return pg_strdup(completion_charp);
+		else
+			/* If case insensitive matching was requested initially, return it
+			 * in the case of what was already entered. */
+			return pg_strdup_same_case(completion_charp, text);
+	}
 	else
 		return NULL;
 }
@@ -3351,7 +3397,7 @@ complete_from_variables(char *text, const char *prefix, const char *suffix)
 	}
 
 	varnames[nvars] = NULL;
-	COMPLETE_WITH_LIST(varnames);
+	COMPLETE_WITH_LIST_CS(varnames);
 
 	for (i = 0; i < nvars; i++)
 		free((void *) varnames[i]);
