mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-30 19:00:29 +08:00
Fix query-based tab completion for multibyte characters.
The existing code confuses the byte length of the string (which is relevant when passing it to pg_strncasecmp) with the character length of the string (which is relevant when it is used with the SQL substring function). Separate those two concepts. Report and patch by Kyotaro Horiguchi, reviewed by Thomas Munro and reviewed and further revised by me.
This commit is contained in:
parent
ff4527408c
commit
54139ac22f
@ -3522,9 +3522,8 @@ static char *
|
||||
_complete_from_query(int is_schema_query, const char *text, int state)
|
||||
{
|
||||
static int list_index,
|
||||
string_length;
|
||||
byte_length;
|
||||
static PGresult *result = NULL;
|
||||
|
||||
/*
|
||||
* If this is the first time for this completion, we fetch a list of our
|
||||
* "things" from the backend.
|
||||
@ -3535,9 +3534,18 @@ _complete_from_query(int is_schema_query, const char *text, int state)
|
||||
char *e_text;
|
||||
char *e_info_charp;
|
||||
char *e_info_charp2;
|
||||
const char *pstr = text;
|
||||
int char_length = 0;
|
||||
|
||||
list_index = 0;
|
||||
string_length = strlen(text);
|
||||
byte_length = strlen(text);
|
||||
|
||||
/* Count length as number of characters (not bytes), for passing to substring */
|
||||
while (*pstr)
|
||||
{
|
||||
char_length++;
|
||||
pstr += PQmblen(pstr, pset.encoding);
|
||||
}
|
||||
|
||||
/* Free any prior result */
|
||||
PQclear(result);
|
||||
@ -3590,7 +3598,7 @@ _complete_from_query(int is_schema_query, const char *text, int state)
|
||||
completion_squery->selcondition);
|
||||
appendPQExpBuffer(&query_buffer, "substring(%s,1,%d)='%s'",
|
||||
completion_squery->result,
|
||||
string_length, e_text);
|
||||
char_length, e_text);
|
||||
appendPQExpBuffer(&query_buffer, " AND %s",
|
||||
completion_squery->viscondition);
|
||||
|
||||
@ -3617,13 +3625,13 @@ _complete_from_query(int is_schema_query, const char *text, int state)
|
||||
"SELECT pg_catalog.quote_ident(n.nspname) || '.' "
|
||||
"FROM pg_catalog.pg_namespace n "
|
||||
"WHERE substring(pg_catalog.quote_ident(n.nspname) || '.',1,%d)='%s'",
|
||||
string_length, e_text);
|
||||
char_length, e_text);
|
||||
appendPQExpBuffer(&query_buffer,
|
||||
" AND (SELECT pg_catalog.count(*)"
|
||||
" FROM pg_catalog.pg_namespace"
|
||||
" WHERE substring(pg_catalog.quote_ident(nspname) || '.',1,%d) ="
|
||||
" substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(nspname))+1)) > 1",
|
||||
string_length, e_text);
|
||||
char_length, e_text);
|
||||
|
||||
/*
|
||||
* Add in matching qualified names, but only if there is exactly
|
||||
@ -3641,7 +3649,7 @@ _complete_from_query(int is_schema_query, const char *text, int state)
|
||||
completion_squery->selcondition);
|
||||
appendPQExpBuffer(&query_buffer, "substring(pg_catalog.quote_ident(n.nspname) || '.' || %s,1,%d)='%s'",
|
||||
qualresult,
|
||||
string_length, e_text);
|
||||
char_length, e_text);
|
||||
|
||||
/*
|
||||
* This condition exploits the single-matching-schema rule to
|
||||
@ -3650,13 +3658,13 @@ _complete_from_query(int is_schema_query, const char *text, int state)
|
||||
appendPQExpBuffer(&query_buffer,
|
||||
" AND substring(pg_catalog.quote_ident(n.nspname) || '.',1,%d) ="
|
||||
" substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(n.nspname))+1)",
|
||||
string_length, e_text);
|
||||
char_length, e_text);
|
||||
appendPQExpBuffer(&query_buffer,
|
||||
" AND (SELECT pg_catalog.count(*)"
|
||||
" FROM pg_catalog.pg_namespace"
|
||||
" WHERE substring(pg_catalog.quote_ident(nspname) || '.',1,%d) ="
|
||||
" substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(nspname))+1)) = 1",
|
||||
string_length, e_text);
|
||||
char_length, e_text);
|
||||
|
||||
/* If an addon query was provided, use it */
|
||||
if (completion_charp)
|
||||
@ -3666,7 +3674,7 @@ _complete_from_query(int is_schema_query, const char *text, int state)
|
||||
{
|
||||
/* completion_charp is an sprintf-style format string */
|
||||
appendPQExpBuffer(&query_buffer, completion_charp,
|
||||
string_length, e_text,
|
||||
char_length, e_text,
|
||||
e_info_charp, e_info_charp,
|
||||
e_info_charp2, e_info_charp2);
|
||||
}
|
||||
@ -3692,7 +3700,7 @@ _complete_from_query(int is_schema_query, const char *text, int state)
|
||||
|
||||
while (list_index < PQntuples(result) &&
|
||||
(item = PQgetvalue(result, list_index++, 0)))
|
||||
if (pg_strncasecmp(text, item, string_length) == 0)
|
||||
if (pg_strncasecmp(text, item, byte_length) == 0)
|
||||
return pg_strdup(item);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user