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

Commit092f3c6

Browse files
michaelpqRyo Kanbayashi
and
Ryo Kanbayashi
committed
libpq: Add "servicefile" connection option
This commit adds the possibility to specify a service file in aconnection string, using a new option called "servicefile". The parsingof the service file happens so as things are done in this order ofpriority:- The servicefile connection option.- Environment variable PGSERVICEFILE.- Default path, depending on the HOME environment.Note that in the last default case, we need to fill in "servicefile" forthe connection's PQconninfoOption to let clients know which service filehas been used for the connection. Some TAP tests are added, with a fewtweaks required for Windows when using URIs or connection option values,for the location paths.Author: Torsten Förtsch <tfoertsch123@gmail.com>Co-authored-by: Ryo Kanbayashi <kanbayashi.dev@gmail.com>Discussion:https://postgr.es/m/CAKkG4_nCjx3a_F3gyXHSPWxD8Sd8URaM89wey7fG_9g7KBkOCQ@mail.gmail.com
1 parent8893c3a commit092f3c6

File tree

4 files changed

+146
-13
lines changed

4 files changed

+146
-13
lines changed

‎doc/src/sgml/libpq.sgml

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2320,6 +2320,19 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
23202320
</listitem>
23212321
</varlistentry>
23222322

2323+
<varlistentry id="libpq-connect-servicefile" xreflabel="servicefile">
2324+
<term><literal>servicefile</literal></term>
2325+
<listitem>
2326+
<para>
2327+
This option specifies the name of the per-user connection service file
2328+
(see <xref linkend="libpq-pgservice"/>).
2329+
Defaults to <filename>~/.pg_service.conf</filename>, or
2330+
<filename>%APPDATA%\postgresql\.pg_service.conf</filename> on
2331+
Microsoft Windows.
2332+
</para>
2333+
</listitem>
2334+
</varlistentry>
2335+
23232336
<varlistentry id="libpq-connect-target-session-attrs" xreflabel="target_session_attrs">
23242337
<term><literal>target_session_attrs</literal></term>
23252338
<listitem>
@@ -9140,12 +9153,8 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
91409153
<indexterm>
91419154
<primary><envar>PGSERVICEFILE</envar></primary>
91429155
</indexterm>
9143-
<envar>PGSERVICEFILE</envar> specifies the name of the per-user
9144-
connection service file
9145-
(see <xref linkend="libpq-pgservice"/>).
9146-
Defaults to <filename>~/.pg_service.conf</filename>, or
9147-
<filename>%APPDATA%\postgresql\.pg_service.conf</filename> on
9148-
Microsoft Windows.
9156+
<envar>PGSERVICEFILE</envar> behaves the same as the
9157+
<xref linkend="libpq-connect-servicefile"/> connection parameter.
91499158
</para>
91509159
</listitem>
91519160

@@ -9576,7 +9585,8 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
95769585
On Microsoft Windows, it is named
95779586
<filename>%APPDATA%\postgresql\.pg_service.conf</filename> (where
95789587
<filename>%APPDATA%</filename> refers to the Application Data subdirectory
9579-
in the user's profile). A different file name can be specified by
9588+
in the user's profile). A different file name can be specified using the
9589+
<literal>servicefile</literal> key word in a libpq connection string or by
95809590
setting the environment variable <envar>PGSERVICEFILE</envar>.
95819591
The system-wide file is named <filename>pg_service.conf</filename>.
95829592
By default it is sought in the <filename>etc</filename> directory

‎src/interfaces/libpq/fe-connect.c

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,10 @@ static const internalPQconninfoOption PQconninfoOptions[] = {
201201
"Database-Service","",20,
202202
offsetof(structpg_conn,pgservice)},
203203

204+
{"servicefile","PGSERVICEFILE",NULL,NULL,
205+
"Database-Service-File","",64,
206+
offsetof(structpg_conn,pgservicefile)},
207+
204208
{"user","PGUSER",NULL,NULL,
205209
"Database-User","",20,
206210
offsetof(structpg_conn,pguser)},
@@ -5062,6 +5066,7 @@ freePGconn(PGconn *conn)
50625066
free(conn->dbName);
50635067
free(conn->replication);
50645068
free(conn->pgservice);
5069+
free(conn->pgservicefile);
50655070
free(conn->pguser);
50665071
if (conn->pgpass)
50675072
{
@@ -5914,6 +5919,7 @@ static int
59145919
parseServiceInfo(PQconninfoOption*options,PQExpBuffererrorMessage)
59155920
{
59165921
constchar*service=conninfo_getval(options,"service");
5922+
constchar*service_fname=conninfo_getval(options,"servicefile");
59175923
charserviceFile[MAXPGPATH];
59185924
char*env;
59195925
boolgroup_found= false;
@@ -5933,10 +5939,13 @@ parseServiceInfo(PQconninfoOption *options, PQExpBuffer errorMessage)
59335939
return0;
59345940

59355941
/*
5936-
* Try PGSERVICEFILE if specified, else try ~/.pg_service.conf (if that
5937-
* exists).
5942+
* First, try the "servicefile" option in connection string. Then, try
5943+
* the PGSERVICEFILE environment variable. Finally, check
5944+
* ~/.pg_service.conf (if that exists).
59385945
*/
5939-
if ((env=getenv("PGSERVICEFILE"))!=NULL)
5946+
if (service_fname!=NULL)
5947+
strlcpy(serviceFile,service_fname,sizeof(serviceFile));
5948+
elseif ((env=getenv("PGSERVICEFILE"))!=NULL)
59405949
strlcpy(serviceFile,env,sizeof(serviceFile));
59415950
else
59425951
{
@@ -6092,7 +6101,17 @@ parseServiceFile(const char *serviceFile,
60926101
if (strcmp(key,"service")==0)
60936102
{
60946103
libpq_append_error(errorMessage,
6095-
"nested service specifications not supported in service file \"%s\", line %d",
6104+
"nested \"service\" specifications not supported in service file \"%s\", line %d",
6105+
serviceFile,
6106+
linenr);
6107+
result=3;
6108+
gotoexit;
6109+
}
6110+
6111+
if (strcmp(key,"servicefile")==0)
6112+
{
6113+
libpq_append_error(errorMessage,
6114+
"nested \"servicefile\" specifications not supported in service file \"%s\", line %d",
60966115
serviceFile,
60976116
linenr);
60986117
result=3;
@@ -6135,6 +6154,33 @@ parseServiceFile(const char *serviceFile,
61356154
}
61366155

61376156
exit:
6157+
6158+
/*
6159+
* If a service has been successfully found, set the "servicefile" option
6160+
* if not already set. This matters when we use a default service file or
6161+
* PGSERVICEFILE, where we want to be able track the value.
6162+
*/
6163+
if (*group_found&&result==0)
6164+
{
6165+
for (i=0;options[i].keyword;i++)
6166+
{
6167+
if (strcmp(options[i].keyword,"servicefile")!=0)
6168+
continue;
6169+
6170+
/* If value is already set, nothing to do */
6171+
if (options[i].val!=NULL)
6172+
break;
6173+
6174+
options[i].val=strdup(serviceFile);
6175+
if (options[i].val==NULL)
6176+
{
6177+
libpq_append_error(errorMessage,"out of memory");
6178+
result=3;
6179+
}
6180+
break;
6181+
}
6182+
}
6183+
61386184
fclose(f);
61396185

61406186
returnresult;

‎src/interfaces/libpq/libpq-int.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,8 @@ struct pg_conn
389389
char*dbName;/* database name */
390390
char*replication;/* connect as the replication standby? */
391391
char*pgservice;/* Postgres service, if any */
392+
char*pgservicefile;/* path to a service file containing
393+
* service(s) */
392394
char*pguser;/* Postgres username and password, if any */
393395
char*pgpass;
394396
char*pgpassfile;/* path to a file containing password(s) */

‎src/interfaces/libpq/t/006_service.pl

Lines changed: 77 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@
5353
ordie"Could not copy$srvfile_valid to$srvfile_nested:$!";
5454
append_to_file($srvfile_nested,'service=invalid_srv' .$newline);
5555

56+
# Service file with nested "servicefile" defined.
57+
my$srvfile_nested_2 ="$td/pg_service_nested_2.conf";
58+
copy($srvfile_valid,$srvfile_nested_2)
59+
ordie"Could not copy$srvfile_valid to$srvfile_nested_2:$!";
60+
append_to_file($srvfile_nested_2,
61+
'servicefile=' .$srvfile_default .$newline);
62+
5663
# Set the fallback directory lookup of the service file to the temporary
5764
# directory of this test. PGSYSCONFDIR is used if the service file
5865
# defined in PGSERVICEFILE cannot be found, or when a service file is
@@ -158,9 +165,77 @@
158165

159166
$dummy_node->connect_fails(
160167
'service=my_srv',
161-
'connection with nested service file',
168+
'connection with "service" in nested service file',
169+
expected_stderr=>
170+
qr/nested "service" specifications not supported in service file/);
171+
172+
local$ENV{PGSERVICEFILE} =$srvfile_nested_2;
173+
174+
$dummy_node->connect_fails(
175+
'service=my_srv',
176+
'connection with "servicefile" in nested service file',
162177
expected_stderr=>
163-
qr/nested service specifications not supported in service file/);
178+
qr/nested "servicefile" specifications not supported in service file/
179+
);
180+
}
181+
182+
# Properly escape backslashes in the path, to ensure the generation of
183+
# correct connection strings.
184+
my$srvfile_win_cared =$srvfile_valid;
185+
$srvfile_win_cared =~s/\\/\\\\/g;
186+
187+
# Checks that the "servicefile" option works as expected
188+
{
189+
$dummy_node->connect_ok(
190+
q{service=my_srv servicefile='} .$srvfile_win_cared .q{'},
191+
'connection with valid servicefile in connection string',
192+
sql=>"SELECT 'connect3_1'",
193+
expected_stdout=>qr/connect3_1/);
194+
195+
# Encode slashes and backslash
196+
my$encoded_srvfile =$srvfile_valid =~s{([\\/])}{
197+
$1 eq '/' ? '%2F' : '%5C'
198+
}ger;
199+
200+
# Additionally encode a colon in servicefile path of Windows
201+
$encoded_srvfile =~s/:/%3A/g;
202+
203+
$dummy_node->connect_ok(
204+
'postgresql:///?service=my_srv&servicefile=' .$encoded_srvfile,
205+
'connection with valid servicefile in URI',
206+
sql=>"SELECT 'connect3_2'",
207+
expected_stdout=>qr/connect3_2/);
208+
209+
local$ENV{PGSERVICE} ='my_srv';
210+
$dummy_node->connect_ok(
211+
q{servicefile='} .$srvfile_win_cared .q{'},
212+
'connection with PGSERVICE and servicefile in connection string',
213+
sql=>"SELECT 'connect3_3'",
214+
expected_stdout=>qr/connect3_3/);
215+
216+
$dummy_node->connect_ok(
217+
'postgresql://?servicefile=' .$encoded_srvfile,
218+
'connection with PGSERVICE and servicefile in URI',
219+
sql=>"SELECT 'connect3_4'",
220+
expected_stdout=>qr/connect3_4/);
221+
}
222+
223+
# Check that the "servicefile" option takes priority over the PGSERVICEFILE
224+
# environment variable.
225+
{
226+
local$ENV{PGSERVICEFILE} ='non-existent-file.conf';
227+
228+
$dummy_node->connect_fails(
229+
'service=my_srv',
230+
'connection with invalid PGSERVICEFILE',
231+
expected_stderr=>
232+
qr/service file "non-existent-file\.conf" not found/);
233+
234+
$dummy_node->connect_ok(
235+
q{service=my_srv servicefile='} .$srvfile_win_cared .q{'},
236+
'connection with both servicefile and PGSERVICEFILE',
237+
sql=>"SELECT 'connect4_1'",
238+
expected_stdout=>qr/connect4_1/);
164239
}
165240

166241
$node->teardown_node;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp