aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bin/psql/tab-complete.c71
1 files changed, 59 insertions, 12 deletions
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index b0b318f426f..3854f7f421f 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)
@@ -671,6 +681,7 @@ static char *complete_from_const(const char *text, int state);
static char **complete_from_variables(char *text,
const char *prefix, const char *suffix);
+static char *pg_strdup_same_case(const char *s, const char *ref);
static PGresult *exec_query(const char *query);
static void get_previous_words(int point, char **previous_words, int nwords);
@@ -771,7 +782,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] != ':')
@@ -2907,7 +2918,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)
{
@@ -2917,14 +2928,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)
@@ -3030,7 +3041,7 @@ create_or_drop_command_generator(const char *text, int state, bits32 excluded)
{
if ((pg_strncasecmp(name, text, string_length) == 0) &&
!(words_after_create[list_index - 1].flags & excluded))
- return pg_strdup(name);
+ return pg_strdup_same_case(name, text);
}
/* if nothing matches, return NULL */
return NULL;
@@ -3298,7 +3309,7 @@ complete_from_list(const char *text, int state)
{
list_index = 0;
string_length = strlen(text);
- casesensitive = true;
+ casesensitive = completion_case_sensitive;
matches = 0;
}
@@ -3313,7 +3324,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);
+ }
}
/*
@@ -3343,12 +3361,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;
}
@@ -3394,7 +3416,7 @@ complete_from_variables(char *text, const char *prefix, const char *suffix)
}
varnames[nvars] = NULL;
- COMPLETE_WITH_LIST((const char * const *) varnames);
+ COMPLETE_WITH_LIST_CS((const char * const *) varnames);
for (i = 0; i < nvars; i++)
free(varnames[i]);
@@ -3408,6 +3430,31 @@ complete_from_variables(char *text, const char *prefix, const char *suffix)
/*
+ * 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);
+}
+
+
+/*
* Execute a query and report any errors. This should be the preferred way of
* talking to the database in this file.
*/