DETAIL: FATAL: role "invalid" does not exist
ALTER USER MAPPING FOR PUBLIC SERVER loopback2 OPTIONS (DROP user);
-SELECT * FROM postgresql_fdw_connections ORDER BY conname;
- conname | srvname | usename
------------+-----------+---------
- loopback1 | loopback1 | public
-(1 row)
-
SELECT * FROM ft2 ORDER BY c1; -- ERROR
ERROR: could not execute foreign query
DETAIL: ERROR: relation "public.invalid" does not exist
^
HINT: SELECT c1, c2, c3 FROM public.invalid ft2
-SELECT * FROM postgresql_fdw_connections ORDER BY conname;
- conname | srvname | usename
------------+-----------+---------
- loopback1 | loopback1 | public
- loopback2 | loopback2 | public
-(2 rows)
-
ALTER FOREIGN TABLE ft2 OPTIONS (SET relname 't1');
SELECT * FROM ft2 ORDER BY c1;
c1 | c2 | c3
3 | buz | 01-03-1970
(3 rows)
-SELECT * FROM postgresql_fdw_connections ORDER BY conname;
- conname | srvname | usename
------------+-----------+---------
- loopback1 | loopback1 | public
- loopback2 | loopback2 | public
-(2 rows)
-
-- query using join
SELECT * FROM ft1 JOIN ft2 ON (ft1.c1 = ft2.c1) ORDER BY ft1.c1;
c1 | c2 | c3 | c1 | c2 | c3
#include "fsconnection.h"
-extern Datum postgresql_fdw_connections(PG_FUNCTION_ARGS);
-
-
/*
* Connection cache entry managed with hash table.
*/
FSConnectionHash = NULL;
}
-/*
- * Retrieve foreign server connections.
- */
-Datum
-postgresql_fdw_connections(PG_FUNCTION_ARGS)
-{
-#define PG_FOREIGN_SERVER_CONNECTIONS_COLS 3
- ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
- TupleDesc tupdesc;
- Tuplestorestate *tupstore;
- MemoryContext per_query_ctx;
- MemoryContext oldcontext;
-
- /* check to see if caller supports us returning a tuplestore */
- if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("set-valued function called in context that cannot accept a set")));
- if (!(rsinfo->allowedModes & SFRM_Materialize))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("materialize mode required, but it is not " \
- "allowed in this context")));
-
- /* Build a tuple descriptor for our result type */
- if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
- elog(ERROR, "return type must be a row type");
-
- per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
- oldcontext = MemoryContextSwitchTo(per_query_ctx);
-
- tupstore = tuplestore_begin_heap(true, false, work_mem);
- rsinfo->returnMode = SFRM_Materialize;
- rsinfo->setResult = tupstore;
- rsinfo->setDesc = tupdesc;
-
- if (FSConnectionHash)
- {
- HASH_SEQ_STATUS hash_seq;
- ConnCacheEntry *entry;
-
- MemoryContextSwitchTo(oldcontext);
-
- hash_seq_init(&hash_seq, FSConnectionHash);
- while ((entry = hash_seq_search(&hash_seq)) != NULL)
- {
- Datum values[PG_FOREIGN_SERVER_CONNECTIONS_COLS];
- bool nulls[PG_FOREIGN_SERVER_CONNECTIONS_COLS];
- int i = 0;
-
- memset(values, 0, sizeof(values));
- memset(nulls, 0, sizeof(nulls));
-
- values[i++] = CStringGetTextDatum(entry->name);
- values[i++] = ObjectIdGetDatum(entry->serverid);
- values[i++] = ObjectIdGetDatum(entry->userid);
-
- Assert(i == PG_FOREIGN_SERVER_CONNECTIONS_COLS);
-
- tuplestore_putvalues(tupstore, tupdesc, values, nulls);
- }
- }
-
- /* clean up and return the tuplestore */
- tuplestore_donestoring(tupstore);
-
- return (Datum) 0;
-}
-
/*
* Disconnect all connections on the exit of backend process.
*/
RETURNS fdw_handler
AS 'MODULE_PATHNAME','postgresql_fdw_handler'
LANGUAGE C STRICT;
-
-CREATE OR REPLACE FUNCTION postgresql_fdw_connections(conname OUT text, serverid OUT oid, userid OUT oid)
- RETURNS SETOF record
- AS 'MODULE_PATHNAME','postgresql_fdw_connections'
- LANGUAGE C STRICT;
-
-CREATE OR REPLACE VIEW postgresql_fdw_connections AS
- SELECT c.conname AS conname,
- s.srvname AS srvname,
- CASE WHEN c.userid = 0 THEN
- 'public'
- ELSE
- a.rolname
- END AS usename
- FROM postgresql_fdw_connections() c
- JOIN pg_foreign_server s ON (s.oid = c.serverid)
- LEFT JOIN pg_authid a ON (a.oid = c.userid);
-
-GRANT EXECUTE ON FUNCTION postgresql_fdw_connections(conname OUT text, serverid OUT oid, userid OUT oid) TO public;
-GRANT SELECT ON postgresql_fdw_connections TO public;
-
SELECT * FROM ft1 ORDER BY c1;
SELECT * FROM ft2 ORDER BY c1; -- ERROR
ALTER USER MAPPING FOR PUBLIC SERVER loopback2 OPTIONS (DROP user);
-SELECT * FROM postgresql_fdw_connections ORDER BY conname;
SELECT * FROM ft2 ORDER BY c1; -- ERROR
-SELECT * FROM postgresql_fdw_connections ORDER BY conname;
ALTER FOREIGN TABLE ft2 OPTIONS (SET relname 't1');
SELECT * FROM ft2 ORDER BY c1;
-SELECT * FROM postgresql_fdw_connections ORDER BY conname;
-- query using join
SELECT * FROM ft1 JOIN ft2 ON (ft1.c1 = ft2.c1) ORDER BY ft1.c1;
set search_path = public;
DROP FUNCTION postgresql_fdw_handler ();
-DROP VIEW postgresql_fdw_connections;
-DROP FUNCTION postgresql_fdw_connections(conname OUT text, serverid OUT oid, userid OUT oid);
-
</listitem>
</varlistentry>
- <varlistentry>
- <term>
- <function>postgresql_fdw_connections() returns record</function>
- </term>
-
- <listitem>
- <para>
- <function>postgresql_fdw_connections</function> is a function which
- returns list of active connections which are estabilshed via
- postgresql_fdw. This function was designed as a private function, used
- from postgresql_fdw_connections view.
- </para>
- </listitem>
- </varlistentry>
-
- </variablelist>
-
- </sect2>
-
- <sect2>
- <title>Views</title>
-
- <variablelist>
- <varlistentry>
- <term>
- <function>postgresql_fdw_connections</function>
- </term>
-
- <listitem>
- <para>
- <structname>postgresql_fdw_connections</structname> is a view which
- shows active connections which are estabilshed via postgresql_fdw.
- </para>
-
- <table>
- <title><structname>postgresql_fdw_connections</> Columns</title>
-
- <tgroup cols="4">
- <thead>
- <row>
- <entry>Name</entry>
- <entry>Type</entry>
- <entry>References</entry>
- <entry>Description</entry>
- </row>
- </thead>
-
- <tbody>
- <row>
- <entry><structfield>conname</structfield></entry>
- <entry><type>name</type></entry>
- <entry></entry>
- <entry>Name of the connection</entry>
- </row>
-
- <row>
- <entry><structfield>srvname</structfield></entry>
- <entry><type>name</type></entry>
- <entry>pg_foreign_server.srvname</entry>
- <entry>Name of the foreign server used by this connection</entry>
- </row>
-
- <row>
- <entry><structfield>usename</structfield></entry>
- <entry><type>name</type></entry>
- <entry>pg_authid.rolname</entry>
- <entry>Name of the user being mapped, or <literal>PUBLIC</literal> if
- the mapping is public</entry>
- </row>
-
- </tbody>
- </tgroup>
- </table>
-
- </listitem>
- </varlistentry>
</variablelist>
</sect2>