Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit41e3c94

Browse files
committed
psql: when tab-completing, use quotes on file names that need them
psql backslash commands that deal with file or directory names requirequotes around those that have spaces, single quotes, or backslashes.However, tab-completing such names does not provide said quotes, and isthus almost useless with them.This patch fixes the problem by having a wrapper function aroundrl_filename_completion_function that dequotes on input and quotes onoutput. This eases dealing with such names.Author: Noah Misch
1 parentcb3a7c2 commit41e3c94

File tree

3 files changed

+128
-2
lines changed

3 files changed

+128
-2
lines changed

‎src/bin/psql/stringutils.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,3 +272,72 @@ strip_quotes(char *source, char quote, char escape, int encoding)
272272

273273
*dst='\0';
274274
}
275+
276+
277+
/*
278+
* quote_if_needed
279+
*
280+
* Opposite of strip_quotes(). If "source" denotes itself literally without
281+
* quoting or escaping, returns NULL. Otherwise, returns a malloc'd copy with
282+
* quoting and escaping applied:
283+
*
284+
* source -string to parse
285+
* entails_quote -any of these present? need outer quotes
286+
* quote -doubled within string, affixed to both ends
287+
* escape -doubled within string
288+
* encoding -the active character-set encoding
289+
*
290+
* Do not use this as a substitute for PQescapeStringConn(). Use it for
291+
* strings to be parsed by strtokx() or psql_scan_slash_option().
292+
*/
293+
char*
294+
quote_if_needed(constchar*source,constchar*entails_quote,
295+
charquote,charescape,intencoding)
296+
{
297+
constchar*src;
298+
char*ret;
299+
char*dst;
300+
boolneed_quotes= false;
301+
302+
psql_assert(source);
303+
psql_assert(quote);
304+
305+
src=source;
306+
dst=ret=pg_malloc(2*strlen(src)+3);/* excess */
307+
308+
*dst++=quote;
309+
310+
while (*src)
311+
{
312+
charc=*src;
313+
inti;
314+
315+
if (c==quote)
316+
{
317+
need_quotes= true;
318+
*dst++=quote;
319+
}
320+
elseif (c==escape)
321+
{
322+
need_quotes= true;
323+
*dst++=escape;
324+
}
325+
elseif (strchr(entails_quote,c))
326+
need_quotes= true;
327+
328+
i=PQmblen(src,encoding);
329+
while (i--)
330+
*dst++=*src++;
331+
}
332+
333+
*dst++=quote;
334+
*dst='\0';
335+
336+
if (!need_quotes)
337+
{
338+
free(ret);
339+
ret=NULL;
340+
}
341+
342+
returnret;
343+
}

‎src/bin/psql/stringutils.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,7 @@ extern char *strtokx(const char *s,
1919
booldel_quotes,
2020
intencoding);
2121

22+
externchar*quote_if_needed(constchar*source,constchar*entails_quote,
23+
charquote,charescape,intencoding);
24+
2225
#endif/* STRINGUTILS_H */

‎src/bin/psql/tab-complete.c

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,7 @@ static char *complete_from_list(const char *text, int state);
680680
staticchar*complete_from_const(constchar*text,intstate);
681681
staticchar**complete_from_variables(char*text,
682682
constchar*prefix,constchar*suffix);
683+
staticchar*complete_from_files(constchar*text,intstate);
683684

684685
staticchar*pg_strdup_same_case(constchar*s,constchar*ref);
685686
staticPGresult*exec_query(constchar*query);
@@ -1630,7 +1631,10 @@ psql_completion(char *text, int start, int end)
16301631
pg_strcasecmp(prev3_wd,"BINARY")==0)&&
16311632
(pg_strcasecmp(prev_wd,"FROM")==0||
16321633
pg_strcasecmp(prev_wd,"TO")==0))
1633-
matches=completion_matches(text,filename_completion_function);
1634+
{
1635+
completion_charp="";
1636+
matches=completion_matches(text,complete_from_files);
1637+
}
16341638

16351639
/* Handle COPY|BINARY <sth> FROM|TO filename */
16361640
elseif ((pg_strcasecmp(prev4_wd,"COPY")==0||
@@ -2953,7 +2957,10 @@ psql_completion(char *text, int start, int end)
29532957
strcmp(prev_wd,"\\s")==0||
29542958
strcmp(prev_wd,"\\w")==0||strcmp(prev_wd,"\\write")==0
29552959
)
2956-
matches=completion_matches(text,filename_completion_function);
2960+
{
2961+
completion_charp="\\";
2962+
matches=completion_matches(text,complete_from_files);
2963+
}
29572964

29582965
/*
29592966
* Finally, we look through the list of "things", such as TABLE, INDEX and
@@ -3426,6 +3433,53 @@ complete_from_variables(char *text, const char *prefix, const char *suffix)
34263433
}
34273434

34283435

3436+
/*
3437+
* This function wraps rl_filename_completion_function() to strip quotes from
3438+
* the input before searching for matches and to quote any matches for which
3439+
* the consuming command will require it.
3440+
*/
3441+
staticchar*
3442+
complete_from_files(constchar*text,intstate)
3443+
{
3444+
staticconstchar*unquoted_text;
3445+
char*unquoted_match;
3446+
char*ret=NULL;
3447+
3448+
if (state==0)
3449+
{
3450+
/* Initialization: stash the unquoted input. */
3451+
unquoted_text=strtokx(text,"",NULL,"'",*completion_charp,
3452+
false, true,pset.encoding);
3453+
/* expect a NULL return for the empty string only */
3454+
if (!unquoted_text)
3455+
{
3456+
psql_assert(!*text);
3457+
unquoted_text=text;
3458+
}
3459+
}
3460+
3461+
unquoted_match=filename_completion_function(unquoted_text,state);
3462+
if (unquoted_match)
3463+
{
3464+
/*
3465+
* Caller sets completion_charp to a zero- or one-character string
3466+
* containing the escape character. This is necessary since \copy has
3467+
* no escape character, but every other backslash command recognizes
3468+
* "\" as an escape character. Since we have only two callers, don't
3469+
* bother providing a macro to simplify this.
3470+
*/
3471+
ret=quote_if_needed(unquoted_match," \t\r\n\"`",
3472+
'\'',*completion_charp,pset.encoding);
3473+
if (ret)
3474+
free(unquoted_match);
3475+
else
3476+
ret=unquoted_match;
3477+
}
3478+
3479+
returnret;
3480+
}
3481+
3482+
34293483
/* HELPER FUNCTIONS */
34303484

34313485

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp