
= PL/Proxy Cluster Configuration API =

PL/Proxy can be used in either CONNECT mode or CLUSTER mode.

In CONNECT mode PL/Proxy acts as a pass through proxy to another database.
Each PL/Proxy function contains a libpq connect string for the connection
to a database it will proxy the request to.

PL/Proxy can also be used in CLUSTER mode where it provides support for
partitioning data across multiple databases based on a clustering function.

When using PL/Proxy in CONNECT mode no configuration functions are required.
However, using PL/Proxy in CLUSTER mode requires the following configuration
functions to be defined.


== plproxy.get_cluster_version(cluster_name) ==

  plproxy.get_cluster_version(cluster_name text)
  returns integer

The get_cluster_version function is called on each request, it should return 
the version number of the current configuration for a particular cluster.  
If the version number returned by this function is higher than the one plproxy 
has cached, then the configuration and partition information will be reloaded
by calling the get_cluster_config() and get_cluster_paritions() functions.

This is an example function that does not lookup the version number for an 
external source such as a configuration table.

  CREATE OR REPLACE FUNCTION plproxy.get_cluster_version(cluster_name text)
  RETURNS int4 AS $$
  BEGIN
      IF cluster_name = 'a_cluster' THEN
          RETURN 1;
      END IF;
      RAISE EXCEPTION 'Unknown cluster';
  END;
  $$ LANGUAGE plpgsql;



== plproxy.get_cluster_partitions(cluster_name) ==

  plproxy.get_cluster_partitions(cluster_name text)
  returns setof text

This is called when a new partition configuration needs to be loaded. 
It should return connect strings to the partitions in the cluster.
The connstrings should be returned in the correct order.  The total
number of connstrings returned must be a power of 2.  If two or more
connstrings are equal then they will use the same connection.

If the string "user=" does not appear in a connect string then
user=CURRENT_USER will be appended to the connection string by PL/Proxy.  
This will cause PL/Proxy to connect to the partition database using
the same username as was used to connect to the proxy database.
This also avoids the accidental 'user=postgres' connections.

There are several appriaches how to handle passwords:

* Store passwords in .pgpass / pg_service.conf.  Secure (unless you have dblink
  installed on same Postgres instance.)  Only problem is that it's not
  administrable from inside the database.

* Load per-user password from table/file and append it to connect string.
  Slight problem - users can see the password.

* Use single user/password for all users and put it into connect string.
  Bigger problem - users can see the password.

* Use 'trust' authentication on a pooler listening on locahost/unix socket.
  This is good combination with PgBouncer as it can load
  passwords directly from Postgres own pg_auth file and
  use them for remote connections.

* Use 'trust' authentication on remote database.  Obviously bad idea.

An example function without the use of separate configuration tables:

  CREATE OR REPLACE FUNCTION plproxy.get_cluster_partitions(cluster_name text)
  RETURNS SETOF text AS $$
  BEGIN
      IF cluster_name = 'a_cluster' THEN
          RETURN NEXT 'dbname=part00 host=127.0.0.1';
          RETURN NEXT 'dbname=part01 host=127.0.0.1';
          RETURN NEXT 'dbname=part02 host=127.0.0.1';
          RETURN NEXT 'dbname=part03 host=127.0.0.1';
	  RETURN;
      END IF;
      RAISE EXCEPTION 'Unknown cluster';
  END;
  $$ LANGUAGE plpgsql;

== plproxy.get_cluster_config(cluster) ==

  plproxy.get_cluster_config(in cluster_name text,
			     out key text, out val text)
  returns setof record

The get_cluster_config function returns a set of key-value pairs that can 
consist of any of the following configuration parameters.  All of them are 
optional. Timeouts/lifetime values are given in seconds.  If the value is 0
or NULL then the parameter is disabled (a default value will be used)


  connection_lifetime::

  
	The maximum age a connection (in seconds) to a remote database will be kept
	open for. If this is disabled (0) then connections to remote databases will 
	be kept open as long as they are valid. Otherwise once a connection reaches 
	the age indicated it will be closed.

  query_timeout::

	If a query result does not appear in this time, the connection
	is closed.  If set then `statement_timeout` should also be set
	on remote server to a somewhat smaller value, so it takes effect earlier.
	It is meant for surviving network problems, not long queries.

  disable_binary::

	Do not use binary I/O for connections to this cluster.

  connect_timeout::

	Initial connect is canceled, if it takes more that this.
	+
	*Deprecated*: it duplicates libpq connect string parameter
	with same name.  Its better to just add the parameter to
	connect string.


Example function without the use of separate tables for storing parameters.

  CREATE OR REPLACE FUNCTION plproxy.get_cluster_config(
      in cluster_name text,
      out key text,
      out val text)
  RETURNS SETOF record AS $$
  BEGIN
      -- lets use same config for all clusters
      key := 'connection_lifetime';
      val := 30*60; -- 30m
      RETURN NEXT;
      RETURN;
  END;
  $$ LANGUAGE plpgsql;


