Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 9445db9

Browse files
committed
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.
1 parent 33b5eab commit 9445db9

File tree

1 file changed

+19
-11
lines changed

1 file changed

+19
-11
lines changed

src/bin/psql/tab-complete.c

+19-11
Original file line numberDiff line numberDiff line change
@@ -3198,9 +3198,8 @@ static char *
31983198
_complete_from_query(int is_schema_query, const char *text, int state)
31993199
{
32003200
static int list_index,
3201-
string_length;
3201+
byte_length;
32023202
static PGresult *result = NULL;
3203-
32043203
/*
32053204
* If this is the first time for this completion, we fetch a list of our
32063205
* "things" from the backend.
@@ -3211,9 +3210,18 @@ _complete_from_query(int is_schema_query, const char *text, int state)
32113210
char *e_text;
32123211
char *e_info_charp;
32133212
char *e_info_charp2;
3213+
const char *pstr = text;
3214+
int char_length = 0;
32143215

32153216
list_index = 0;
3216-
string_length = strlen(text);
3217+
byte_length = strlen(text);
3218+
3219+
/* Count length as number of characters (not bytes), for passing to substring */
3220+
while (*pstr)
3221+
{
3222+
char_length++;
3223+
pstr += PQmblen(pstr, pset.encoding);
3224+
}
32173225

32183226
/* Free any prior result */
32193227
PQclear(result);
@@ -3251,7 +3259,7 @@ _complete_from_query(int is_schema_query, const char *text, int state)
32513259
completion_squery->selcondition);
32523260
appendPQExpBuffer(&query_buffer, "substring(%s,1,%d)='%s'",
32533261
completion_squery->result,
3254-
string_length, e_text);
3262+
char_length, e_text);
32553263
appendPQExpBuffer(&query_buffer, " AND %s",
32563264
completion_squery->viscondition);
32573265

@@ -3278,13 +3286,13 @@ _complete_from_query(int is_schema_query, const char *text, int state)
32783286
"SELECT pg_catalog.quote_ident(n.nspname) || '.' "
32793287
"FROM pg_catalog.pg_namespace n "
32803288
"WHERE substring(pg_catalog.quote_ident(n.nspname) || '.',1,%d)='%s'",
3281-
string_length, e_text);
3289+
char_length, e_text);
32823290
appendPQExpBuffer(&query_buffer,
32833291
" AND (SELECT pg_catalog.count(*)"
32843292
" FROM pg_catalog.pg_namespace"
32853293
" WHERE substring(pg_catalog.quote_ident(nspname) || '.',1,%d) ="
32863294
" substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(nspname))+1)) > 1",
3287-
string_length, e_text);
3295+
char_length, e_text);
32883296

32893297
/*
32903298
* Add in matching qualified names, but only if there is exactly
@@ -3302,7 +3310,7 @@ _complete_from_query(int is_schema_query, const char *text, int state)
33023310
completion_squery->selcondition);
33033311
appendPQExpBuffer(&query_buffer, "substring(pg_catalog.quote_ident(n.nspname) || '.' || %s,1,%d)='%s'",
33043312
qualresult,
3305-
string_length, e_text);
3313+
char_length, e_text);
33063314

33073315
/*
33083316
* This condition exploits the single-matching-schema rule to
@@ -3311,13 +3319,13 @@ _complete_from_query(int is_schema_query, const char *text, int state)
33113319
appendPQExpBuffer(&query_buffer,
33123320
" AND substring(pg_catalog.quote_ident(n.nspname) || '.',1,%d) ="
33133321
" substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(n.nspname))+1)",
3314-
string_length, e_text);
3322+
char_length, e_text);
33153323
appendPQExpBuffer(&query_buffer,
33163324
" AND (SELECT pg_catalog.count(*)"
33173325
" FROM pg_catalog.pg_namespace"
33183326
" WHERE substring(pg_catalog.quote_ident(nspname) || '.',1,%d) ="
33193327
" substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(nspname))+1)) = 1",
3320-
string_length, e_text);
3328+
char_length, e_text);
33213329

33223330
/* If an addon query was provided, use it */
33233331
if (completion_charp)
@@ -3327,7 +3335,7 @@ _complete_from_query(int is_schema_query, const char *text, int state)
33273335
{
33283336
/* completion_charp is an sprintf-style format string */
33293337
appendPQExpBuffer(&query_buffer, completion_charp,
3330-
string_length, e_text,
3338+
char_length, e_text,
33313339
e_info_charp, e_info_charp,
33323340
e_info_charp2, e_info_charp2);
33333341
}
@@ -3353,7 +3361,7 @@ _complete_from_query(int is_schema_query, const char *text, int state)
33533361

33543362
while (list_index < PQntuples(result) &&
33553363
(item = PQgetvalue(result, list_index++, 0)))
3356-
if (pg_strncasecmp(text, item, string_length) == 0)
3364+
if (pg_strncasecmp(text, item, byte_length) == 0)
33573365
return pg_strdup(item);
33583366
}
33593367

0 commit comments

Comments
 (0)