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

Commite86fdb0

Browse files
committed
Support non-ASCII letters in psql variable names.
As in the backend, the implementation actually accepts any non-ASCIIcharacter, but we only document that you can use letters.
1 parent910725b commite86fdb0

File tree

5 files changed

+119
-37
lines changed

5 files changed

+119
-37
lines changed

‎doc/src/sgml/ref/psql-ref.sgml

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2206,7 +2206,7 @@ lo_import 152801
22062206
</para>
22072207

22082208
<para>
2209-
Valid variable names can containcharacters, digits, and
2209+
Valid variable names can containletters, digits, and
22102210
underscores. See the section <xref
22112211
linkend="APP-PSQL-variables"
22122212
endterm="APP-PSQL-variables-title"> below for details.
@@ -2461,8 +2461,12 @@ lo_import 152801
24612461
<application>psql</application> provides variable substitution
24622462
features similar to common Unix command shells.
24632463
Variables are simply name/value pairs, where the value
2464-
can be any string of any length. To set variables, use the
2465-
<application>psql</application> meta-command
2464+
can be any string of any length. The name must consist of letters
2465+
(including non-Latin letters), digits, and underscores.
2466+
</para>
2467+
2468+
<para>
2469+
To set a variable, use the <application>psql</application> meta-command
24662470
<command>\set</command>:
24672471
<programlisting>
24682472
testdb=&gt; <userinput>\set foo bar</userinput>
@@ -2498,16 +2502,15 @@ bar
24982502
</para>
24992503

25002504
<para>
2501-
<application>psql</application>'s internal variable names can
2502-
consist of letters, numbers, and underscores in any order and any
2503-
number of them. A number of these variables are treated specially
2504-
by <application>psql</application>. They indicate certain option
2505+
A number of these variables are treated specially
2506+
by <application>psql</application>. They represent certain option
25052507
settings that can be changed at run time by altering the value of
2506-
the variable or that represent some state of the application. Although
2507-
you can use these variables for any other purpose, this is not
2508+
the variable, or in some cases represent changeable state of
2509+
<application>psql</application>. Although
2510+
you can use these variables for other purposes, this is not
25082511
recommended, as the program behavior might grow really strange
2509-
really quickly. By convention, all specially treated variables
2510-
consist of all upper-case letters (and possiblynumbers and
2512+
really quickly. By convention, all specially treated variables' names
2513+
consist of all upper-caseASCIIletters (and possiblydigits and
25112514
underscores). To ensure maximum compatibility in the future, avoid
25122515
using such variable names for your own purposes. A list of all specially
25132516
treated variables follows.

‎src/bin/psql/command.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -995,7 +995,7 @@ exec_command(const char *cmd,
995995

996996
if (!SetVariable(pset.vars,opt,result))
997997
{
998-
psql_error("\\%s: error\n",cmd);
998+
psql_error("\\%s: error while setting variable\n",cmd);
999999
success= false;
10001000
}
10011001

@@ -1096,7 +1096,7 @@ exec_command(const char *cmd,
10961096

10971097
if (!SetVariable(pset.vars,opt0,newval))
10981098
{
1099-
psql_error("\\%s: error\n",cmd);
1099+
psql_error("\\%s: error while setting variable\n",cmd);
11001100
success= false;
11011101
}
11021102
free(newval);
@@ -1272,7 +1272,7 @@ exec_command(const char *cmd,
12721272
}
12731273
elseif (!SetVariable(pset.vars,opt,NULL))
12741274
{
1275-
psql_error("\\%s: error\n",cmd);
1275+
psql_error("\\%s: error while setting variable\n",cmd);
12761276
success= false;
12771277
}
12781278
free(opt);

‎src/bin/psql/psqlscan.l

Lines changed: 70 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ static bool var_is_current_source(PsqlScanState state, const char *varname);
120120
static YY_BUFFER_STATEprepare_buffer(constchar *txt,int len,
121121
char **txtcopy);
122122
staticvoidemit(constchar *txt,int len);
123+
staticchar *extract_substring(constchar *txt,int len);
123124
staticvoidescape_variable(bool as_ident);
124125

125126
#defineECHOemit(yytext, yyleng)
@@ -384,6 +385,9 @@ realfail2({integer}|{decimal})[Ee][-+]
384385

385386
param\${integer}
386387

388+
/* psql-specific: characters allowed in variable names*/
389+
variable_char[A-Za-z\200-\377_0-9]
390+
387391
other.
388392

389393
/*
@@ -680,11 +684,12 @@ other.
680684
return LEXRES_BACKSLASH;
681685
}
682686

683-
:[A-Za-z0-9_]+{
687+
:{variable_char}+{
684688
/* Possible psql variable substitution */
685-
constchar*varname = yytext +1;
689+
char *varname;
686690
constchar *value;
687691

692+
varname =extract_substring(yytext +1, yyleng -1);
688693
value =GetVariable(pset.vars, varname);
689694

690695
if (value)
@@ -713,13 +718,15 @@ other.
713718
*/
714719
ECHO;
715720
}
721+
722+
free(varname);
716723
}
717724

718-
:'[A-Za-z0-9_]+'{
725+
:'{variable_char}+'{
719726
escape_variable(false);
720727
}
721728

722-
:\"[A-Za-z0-9_]+\"{
729+
:\"{variable_char}+\"{
723730
escape_variable(true);
724731
}
725732
@@ -728,13 +735,13 @@ other.
728735
* two rules above fails to match completely.
729736
*/
730737
731-
:'[A-Za-z0-9_]*{
738+
:'{variable_char}*{
732739
/* Throw back everything but the colon */
733740
yyless(1);
734741
ECHO;
735742
}
736743
737-
:\"[A-Za-z0-9_]*{
744+
:\"{variable_char}*{
738745
/* Throw back everything but the colon */
739746
yyless(1);
740747
ECHO;
@@ -930,15 +937,18 @@ other.
930937
}
931938
}
932939

933-
:[A-Za-z0-9_]+{
940+
:{variable_char}+{
934941
/* Possible psql variable substitution */
935942
if (option_type == OT_VERBATIM)
936943
ECHO;
937944
else
938945
{
946+
char *varname;
939947
constchar *value;
940948

941-
value =GetVariable(pset.vars, yytext +1);
949+
varname =extract_substring(yytext +1, yyleng -1);
950+
value =GetVariable(pset.vars, varname);
951+
free(varname);
942952

943953
/*
944954
* The variable value is just emitted without any
@@ -956,7 +966,7 @@ other.
956966
return LEXRES_OK;
957967
}
958968

959-
:'[A-Za-z0-9_]+'{
969+
:'{variable_char}+'{
960970
if (option_type == OT_VERBATIM)
961971
ECHO;
962972
else
@@ -967,7 +977,7 @@ other.
967977
}
968978

969979

970-
:\"[A-Za-z0-9_]+\"{
980+
:\"{variable_char}+\"{
971981
if (option_type == OT_VERBATIM)
972982
ECHO;
973983
else
@@ -977,14 +987,14 @@ other.
977987
}
978988
}
979989
980-
:'[A-Za-z0-9_]*{
990+
:'{variable_char}*{
981991
/* Throw back everything but the colon */
982992
yyless(1);
983993
ECHO;
984994
BEGIN(xslashdefaultarg);
985995
}
986996
987-
:\"[A-Za-z0-9_]*{
997+
:\"{variable_char}*{
988998
/* Throw back everything but the colon */
989999
yyless(1);
9901000
ECHO;
@@ -1844,16 +1854,58 @@ emit(const char *txt, int len)
18441854
}
18451855
}
18461856

1857+
/*
1858+
* extract_substring --- fetch the true value of (part of) the current token
1859+
*
1860+
* This is like emit(), except that the data is returned as a malloc'd string
1861+
* rather than being pushed directly to output_buf.
1862+
*/
1863+
staticchar *
1864+
extract_substring(constchar *txt,int len)
1865+
{
1866+
char *result = (char *)pg_malloc(len +1);
1867+
1868+
if (cur_state->safe_encoding)
1869+
memcpy(result, txt, len);
1870+
else
1871+
{
1872+
/* Gotta do it the hard way */
1873+
constchar *reference = cur_state->refline;
1874+
inti;
1875+
1876+
reference += (txt - cur_state->curline);
1877+
1878+
for (i =0; i < len; i++)
1879+
{
1880+
charch = txt[i];
1881+
1882+
if (ch == (char)0xFF)
1883+
ch = reference[i];
1884+
result[i] = ch;
1885+
}
1886+
}
1887+
result[len] ='\0';
1888+
return result;
1889+
}
1890+
1891+
/*
1892+
* escape_variable --- process :'VARIABLE' or :"VARIABLE"
1893+
*
1894+
* If the variable name is found, escape its value using the appropriate
1895+
* quoting method and emit the value to output_buf. (Since the result is
1896+
* surely quoted, there is never any reason to rescan it.) If we don't
1897+
* find the variable or the escaping function fails, emit the token as-is.
1898+
*/
18471899
staticvoid
18481900
escape_variable(bool as_ident)
18491901
{
1850-
charsaved_char;
1902+
char *varname;
18511903
constchar *value;
18521904

18531905
/* Variable lookup. */
1854-
saved_char = yytext[yyleng -1];
1855-
yytext[yyleng -1] ='\0';
1856-
value =GetVariable(pset.vars, yytext +2);
1906+
varname =extract_substring(yytext +2,yyleng -3);
1907+
value =GetVariable(pset.vars, varname);
1908+
free(varname);
18571909

18581910
/* Escaping. */
18591911
if (value)
@@ -1870,9 +1922,11 @@ escape_variable(bool as_ident)
18701922
else
18711923
escaped_value =
18721924
PQescapeLiteral(pset.db, value,strlen(value));
1925+
18731926
if (escaped_value ==NULL)
18741927
{
18751928
constchar *error =PQerrorMessage(pset.db);
1929+
18761930
psql_error("%s", error);
18771931
}
18781932
else
@@ -1888,6 +1942,5 @@ escape_variable(bool as_ident)
18881942
* If we reach this point, some kind of error has occurred. Emit the
18891943
* original text into the output buffer.
18901944
*/
1891-
yytext[yyleng -1] = saved_char;
18921945
emit(yytext, yyleng);
18931946
}

‎src/bin/psql/variables.c

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,40 @@
66
* src/bin/psql/variables.c
77
*/
88
#include"postgres_fe.h"
9+
910
#include"common.h"
1011
#include"variables.h"
1112

1213

14+
/*
15+
* Check whether a variable's name is allowed.
16+
*
17+
* We allow any non-ASCII character, as well as ASCII letters, digits, and
18+
* underscore. Keep this in sync with the definition of variable_char in
19+
* psqlscan.l.
20+
*/
21+
staticbool
22+
valid_variable_name(constchar*name)
23+
{
24+
constunsignedchar*ptr= (constunsignedchar*)name;
25+
26+
/* Mustn't be zero-length */
27+
if (*ptr=='\0')
28+
return false;
29+
30+
while (*ptr)
31+
{
32+
if (IS_HIGHBIT_SET(*ptr)||
33+
strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ""abcdefghijklmnopqrstuvwxyz"
34+
"_0123456789",*ptr)!=NULL)
35+
ptr++;
36+
else
37+
return false;
38+
}
39+
40+
return true;
41+
}
42+
1343
/*
1444
* A "variable space" is represented by an otherwise-unused struct _variable
1545
* that serves as list header.
@@ -158,7 +188,7 @@ SetVariable(VariableSpace space, const char *name, const char *value)
158188
if (!space)
159189
return false;
160190

161-
if (strspn(name,VALID_VARIABLE_CHARS)!=strlen(name))
191+
if (!valid_variable_name(name))
162192
return false;
163193

164194
if (!value)
@@ -202,7 +232,7 @@ SetVariableAssignHook(VariableSpace space, const char *name, VariableAssignHook
202232
if (!space)
203233
return false;
204234

205-
if (strspn(name,VALID_VARIABLE_CHARS)!=strlen(name))
235+
if (!valid_variable_name(name))
206236
return false;
207237

208238
for (previous=space,current=space->next;

‎src/bin/psql/variables.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,6 @@ struct _variable
3232

3333
typedefstruct_variable*VariableSpace;
3434

35-
/* Allowed chars in a variable's name */
36-
#defineVALID_VARIABLE_CHARS "abcdefghijklmnopqrstuvwxyz"\
37-
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789_"
38-
3935
VariableSpaceCreateVariableSpace(void);
4036
constchar*GetVariable(VariableSpacespace,constchar*name);
4137

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp