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

Commit 274bb2b

Browse files
committed
libpq: Allow connection strings and URIs to specify multiple hosts.
It's also possible to specify a separate port for each host. Previously, we'd loop over every address returned by looking up the host name; now, we'll try every address for every host name. Patch by me. Victor Wagner wrote an earlier patch for this feature, which I read, but I didn't use any of his code. Review by Mithun Cy.
1 parent 7706710 commit 274bb2b

File tree

4 files changed

+506
-208
lines changed

4 files changed

+506
-208
lines changed

doc/src/sgml/libpq.sgml

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -756,8 +756,10 @@ PGPing PQping(const char *conninfo);
756756
Several <application>libpq</> functions parse a user-specified string to obtain
757757
connection parameters. There are two accepted formats for these strings:
758758
plain <literal>keyword = value</literal> strings
759-
and <ulink url="http://www.ietf.org/rfc/rfc3986.txt">RFC
760-
3986</ulink> URIs.
759+
and URIs. URIs generally follow
760+
<ulink url="http://www.ietf.org/rfc/rfc3986.txt">RFC
761+
3986</ulink>, except that multi-host connection strings are allowed
762+
as further described below.
761763
</para>
762764

763765
<sect3>
@@ -792,7 +794,7 @@ host=localhost port=5432 dbname=mydb connect_timeout=10
792794
<para>
793795
The general form for a connection <acronym>URI</acronym> is:
794796
<synopsis>
795-
postgresql://[user[:password]@][netloc][:port][/dbname][?param1=value1&amp;...]
797+
postgresql://[user[:password]@][netloc][:port][,...][/dbname][?param1=value1&amp;...]
796798
</synopsis>
797799
</para>
798800

@@ -809,6 +811,7 @@ postgresql://localhost/mydb
809811
postgresql://user@localhost
810812
postgresql://user:secret@localhost
811813
postgresql://other@localhost/otherdb?connect_timeout=10&amp;application_name=myapp
814+
postgresql://host1:123,host2:456/somedb
812815
</programlisting>
813816
Components of the hierarchical part of the <acronym>URI</acronym> can also
814817
be given as parameters. For example:
@@ -856,6 +859,15 @@ postgresql:///dbname?host=/var/lib/postgresql
856859
postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
857860
</programlisting>
858861
</para>
862+
863+
<para>
864+
It is possible to specify multiple host components, each with an optional
865+
port component, in a single URI. A URI of the form
866+
<literal>postgresql://host1:port1,host2:port2,host3:port3/</literal>
867+
is equivalent to a connection string of the form
868+
<literal>host=host1,host2,host3 port=port1,port2,port3</literal>. Each
869+
host will be tried in turn until a connection is successfully established.
870+
</para>
859871
</sect3>
860872
</sect2>
861873

@@ -870,12 +882,13 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
870882
<term><literal>host</literal></term>
871883
<listitem>
872884
<para>
873-
Name of host to connect to.<indexterm><primary>host name</></>
874-
If this begins with a slash, it specifies Unix-domain
885+
Comma-separated list of host names.<indexterm><primary>host name</></>
886+
If a host name begins with a slash, it specifies Unix-domain
875887
communication rather than TCP/IP communication; the value is the
876-
name of the directory in which the socket file is stored. The
877-
default behavior when <literal>host</literal> is not specified
878-
is to connect to a Unix-domain
888+
name of the directory in which the socket file is stored. If
889+
multiple host names are specified, each will be tried in turn in
890+
the order given. The default behavior when <literal>host</literal> is
891+
not specified is to connect to a Unix-domain
879892
socket<indexterm><primary>Unix domain socket</></> in
880893
<filename>/tmp</filename> (or whatever socket directory was specified
881894
when <productname>PostgreSQL</> was built). On machines without
@@ -950,6 +963,9 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
950963
Port number to connect to at the server host, or socket file
951964
name extension for Unix-domain
952965
connections.<indexterm><primary>port</></>
966+
If the <literal>host</> parameter included multiple, comma-separated
967+
hosts, this parameter may specify a list of ports of equal length,
968+
or it may specify a single port number to be used for all hosts.
953969
</para>
954970
</listitem>
955971
</varlistentry>
@@ -1394,7 +1410,11 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
13941410

13951411
<para>
13961412
The following functions return parameter values established at connection.
1397-
These values are fixed for the life of the <structname>PGconn</> object.
1413+
These values are fixed for the life of the connection. If a multi-host
1414+
connection string is used, the values of <function>PQhost</>,
1415+
<function>PQport</>, and <function>PQpass</> can change if a new connection
1416+
is established using the same <structname>PGconn</> object. Other values
1417+
are fixed for the lifetime of the <structname>PGconn</> object.
13981418

13991419
<variablelist>
14001420
<varlistentry id="libpq-pqdb">

src/interfaces/libpq/fe-auth.c

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -683,20 +683,26 @@ pg_fe_sendauth(AuthRequest areq, PGconn *conn)
683683

684684
case AUTH_REQ_MD5:
685685
case AUTH_REQ_PASSWORD:
686-
conn->password_needed = true;
687-
if (conn->pgpass == NULL || conn->pgpass[0] == '\0')
688686
{
689-
printfPQExpBuffer(&conn->errorMessage,
690-
PQnoPasswordSupplied);
691-
return STATUS_ERROR;
692-
}
693-
if (pg_password_sendauth(conn, conn->pgpass, areq) != STATUS_OK)
694-
{
695-
printfPQExpBuffer(&conn->errorMessage,
687+
char *password = conn->connhost[conn->whichhost].password;
688+
689+
if (password == NULL)
690+
password = conn->pgpass;
691+
conn->password_needed = true;
692+
if (password == NULL || password[0] == '\0')
693+
{
694+
printfPQExpBuffer(&conn->errorMessage,
695+
PQnoPasswordSupplied);
696+
return STATUS_ERROR;
697+
}
698+
if (pg_password_sendauth(conn, password, areq) != STATUS_OK)
699+
{
700+
printfPQExpBuffer(&conn->errorMessage,
696701
"fe_sendauth: error sending password authentication\n");
697-
return STATUS_ERROR;
702+
return STATUS_ERROR;
703+
}
704+
break;
698705
}
699-
break;
700706

701707
case AUTH_REQ_SCM_CREDS:
702708
if (pg_local_sendauth(conn) != STATUS_OK)

0 commit comments

Comments
 (0)