/*
* Construct connection params from generic options of ForeignServer
* and UserMapping. (Some of them might not be libpq options, in
- * which case we'll just waste a few array slots.) Add 3 extra slots
- * for fallback_application_name, client_encoding, end marker.
+ * which case we'll just waste a few array slots.) Add 4 extra slots
+ * for application_name, fallback_application_name, client_encoding,
+ * end marker.
*/
- n = list_length(server->options) + list_length(user->options) + 3;
+ n = list_length(server->options) + list_length(user->options) + 4;
keywords = (const char **) palloc(n * sizeof(char *));
values = (const char **) palloc(n * sizeof(char *));
n += ExtractConnectionOptions(user->options,
keywords + n, values + n);
- /* Use "postgres_fdw" as fallback_application_name. */
+ /*
+ * Use pgfdw_application_name as application_name if set.
+ *
+ * PQconnectdbParams() processes the parameter arrays from start to
+ * end. If any key word is repeated, the last value is used. Therefore
+ * note that pgfdw_application_name must be added to the arrays after
+ * options of ForeignServer are, so that it can override
+ * application_name set in ForeignServer.
+ */
+ if (pgfdw_application_name && *pgfdw_application_name != '\0')
+ {
+ keywords[n] = "application_name";
+ values[n] = pgfdw_application_name;
+ n++;
+ }
+
+ /* Use "postgres_fdw" as fallback_application_name */
keywords[n] = "fallback_application_name";
values[n] = "postgres_fdw";
n++;
CREATE FOREIGN TABLE inv_bsz (c1 int )
SERVER loopback OPTIONS (batch_size '100$%$#$#');
ERROR: invalid value for integer option "batch_size": 100$%$#$#
+-- ===================================================================
+-- test postgres_fdw.application_name GUC
+-- ===================================================================
+-- Turn debug_discard_caches off for this test to make that
+-- the remote connection is alive when checking its application_name.
+-- For each test, close all the existing cached connections manually and
+-- establish connection with new setting of application_name.
+SET debug_discard_caches = 0;
+-- If appname is set as GUC but not as options of server object,
+-- the GUC setting is used as application_name of remote connection.
+SET postgres_fdw.application_name TO 'fdw_guc_appname';
+SELECT 1 FROM postgres_fdw_disconnect_all();
+ ?column?
+----------
+ 1
+(1 row)
+
+SELECT 1 FROM ft6 LIMIT 1;
+ ?column?
+----------
+ 1
+(1 row)
+
+SELECT application_name FROM pg_stat_activity
+ WHERE application_name IN ('loopback2', 'fdw_guc_appname');
+ application_name
+------------------
+ fdw_guc_appname
+(1 row)
+
+-- If appname is set as options of server object but not as GUC,
+-- appname of server object is used.
+RESET postgres_fdw.application_name;
+ALTER SERVER loopback2 OPTIONS (ADD application_name 'loopback2');
+SELECT 1 FROM postgres_fdw_disconnect_all();
+ ?column?
+----------
+ 1
+(1 row)
+
+SELECT 1 FROM ft6 LIMIT 1;
+ ?column?
+----------
+ 1
+(1 row)
+
+SELECT application_name FROM pg_stat_activity
+ WHERE application_name IN ('loopback2', 'fdw_guc_appname');
+ application_name
+------------------
+ loopback2
+(1 row)
+
+-- If appname is set both as GUC and as options of server object,
+-- the GUC setting overrides appname of server object and is used.
+SET postgres_fdw.application_name TO 'fdw_guc_appname';
+SELECT 1 FROM postgres_fdw_disconnect_all();
+ ?column?
+----------
+ 1
+(1 row)
+
+SELECT 1 FROM ft6 LIMIT 1;
+ ?column?
+----------
+ 1
+(1 row)
+
+SELECT application_name FROM pg_stat_activity
+ WHERE application_name IN ('loopback2', 'fdw_guc_appname');
+ application_name
+------------------
+ fdw_guc_appname
+(1 row)
+
+--Clean up
+ALTER SERVER loopback2 OPTIONS (DROP application_name);
+RESET postgres_fdw.application_name;
+RESET debug_discard_caches;
/*-------------------------------------------------------------------------
*
* option.c
- * FDW option handling for postgres_fdw
+ * FDW and GUC option handling for postgres_fdw
*
* Portions Copyright (c) 2012-2021, PostgreSQL Global Development Group
*
*/
static PQconninfoOption *libpq_options;
+/*
+ * GUC parameters
+ */
+char *pgfdw_application_name = NULL;
+
+void _PG_init(void);
+
/*
* Helper functions
*/
list_free(extlist);
return extensionOids;
}
+
+/*
+ * Module load callback
+ */
+void
+_PG_init(void)
+{
+ /*
+ * Unlike application_name GUC, don't set GUC_IS_NAME flag nor check_hook
+ * to allow postgres_fdw.application_name to be any string more than
+ * NAMEDATALEN characters and to include non-ASCII characters. Instead,
+ * remote server truncates application_name of remote connection to less
+ * than NAMEDATALEN and replaces any non-ASCII characters in it with a '?'
+ * character.
+ */
+ DefineCustomStringVariable("postgres_fdw.application_name",
+ "Sets the application name to be used on the remote server.",
+ NULL,
+ &pgfdw_application_name,
+ NULL,
+ PGC_USERSET,
+ 0,
+ NULL,
+ NULL,
+ NULL);
+}
const char **values);
extern List *ExtractExtensionList(const char *extensionsString,
bool warnOnMissing);
+extern char *pgfdw_application_name;
/* in deparse.c */
extern void classifyConditions(PlannerInfo *root,
-- Invalid batch_size option
CREATE FOREIGN TABLE inv_bsz (c1 int )
SERVER loopback OPTIONS (batch_size '100$%$#$#');
+
+-- ===================================================================
+-- test postgres_fdw.application_name GUC
+-- ===================================================================
+-- Turn debug_discard_caches off for this test to make that
+-- the remote connection is alive when checking its application_name.
+-- For each test, close all the existing cached connections manually and
+-- establish connection with new setting of application_name.
+SET debug_discard_caches = 0;
+
+-- If appname is set as GUC but not as options of server object,
+-- the GUC setting is used as application_name of remote connection.
+SET postgres_fdw.application_name TO 'fdw_guc_appname';
+SELECT 1 FROM postgres_fdw_disconnect_all();
+SELECT 1 FROM ft6 LIMIT 1;
+SELECT application_name FROM pg_stat_activity
+ WHERE application_name IN ('loopback2', 'fdw_guc_appname');
+
+-- If appname is set as options of server object but not as GUC,
+-- appname of server object is used.
+RESET postgres_fdw.application_name;
+ALTER SERVER loopback2 OPTIONS (ADD application_name 'loopback2');
+SELECT 1 FROM postgres_fdw_disconnect_all();
+SELECT 1 FROM ft6 LIMIT 1;
+SELECT application_name FROM pg_stat_activity
+ WHERE application_name IN ('loopback2', 'fdw_guc_appname');
+
+-- If appname is set both as GUC and as options of server object,
+-- the GUC setting overrides appname of server object and is used.
+SET postgres_fdw.application_name TO 'fdw_guc_appname';
+SELECT 1 FROM postgres_fdw_disconnect_all();
+SELECT 1 FROM ft6 LIMIT 1;
+SELECT application_name FROM pg_stat_activity
+ WHERE application_name IN ('loopback2', 'fdw_guc_appname');
+
+--Clean up
+ALTER SERVER loopback2 OPTIONS (DROP application_name);
+RESET postgres_fdw.application_name;
+RESET debug_discard_caches;
</para>
</sect2>
+ <sect2>
+ <title>Configuration Parameters</title>
+
+ <variablelist>
+ <varlistentry>
+ <term>
+ <varname>postgres_fdw.application_name</varname> (<type>string</type>)
+ <indexterm>
+ <primary><varname>postgres_fdw.application_name</varname> configuration parameter</primary>
+ </indexterm>
+ </term>
+ <listitem>
+ <para>
+ Specifies a value for <xref linkend="guc-application-name"/>
+ configuration parameter used when <filename>postgres_fdw</filename>
+ establishes a connection to a foreign server. This overrides
+ <varname>application_name</varname> option of the server object.
+ Note that change of this parameter doesn't affect any existing
+ connections until they are re-established.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </sect2>
+
<sect2>
<title>Examples</title>