public inbox for [email protected]
help / color / mirror / Atom feed[PATCH v4 2/2] Expose GUC flags in SQL function; retire ./check_guc
37+ messages / 7 participants
[nested] [flat]
* [PATCH v4 2/2] Expose GUC flags in SQL function; retire ./check_guc
@ 2021-12-08 18:06 Justin Pryzby <[email protected]>
0 siblings, 0 replies; 37+ messages in thread
From: Justin Pryzby @ 2021-12-08 18:06 UTC (permalink / raw)
---
src/backend/catalog/system_views.sql | 19 ++++-
src/backend/utils/misc/check_guc | 29 -------
src/backend/utils/misc/guc.c | 37 +++++++-
src/include/catalog/pg_proc.dat | 6 +-
src/test/regress/expected/guc.out | 122 +++++++++++++++++++++++++++
src/test/regress/expected/rules.out | 2 +-
src/test/regress/sql/guc.sql | 72 ++++++++++++++++
7 files changed, 252 insertions(+), 35 deletions(-)
delete mode 100755 src/backend/utils/misc/check_guc
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 61b515cdb85..e2c01443cb6 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -580,7 +580,24 @@ FROM
JOIN pg_authid rol ON l.classoid = rol.tableoid AND l.objoid = rol.oid;
CREATE VIEW pg_settings AS
- SELECT * FROM pg_show_all_settings() AS A;
+ SELECT a.name,
+ a.setting,
+ a.unit,
+ a.category,
+ a.short_desc,
+ a.extra_desc,
+ a.context,
+ a.vartype,
+ a.source,
+ a.min_val,
+ a.max_val,
+ a.enumvals,
+ a.boot_val,
+ a.reset_val,
+ a.sourcefile,
+ a.sourceline,
+ a.pending_restart
+ FROM pg_show_all_settings() AS A;
CREATE RULE pg_settings_u AS
ON UPDATE TO pg_settings
diff --git a/src/backend/utils/misc/check_guc b/src/backend/utils/misc/check_guc
deleted file mode 100755
index 323ca13191b..00000000000
--- a/src/backend/utils/misc/check_guc
+++ /dev/null
@@ -1,29 +0,0 @@
-#! /bin/sh
-set -e
-
-## this script makes some assumptions about the formatting of files it parses.
-## in postgresql.conf.sample:
-## 1) the valid config settings may be preceded by a '#', but NOT '# '
-## (we use this to skip comments)
-
-### What options are listed in postgresql.conf.sample, but don't appear
-### in guc.c?
-
-# grab everything that looks like a setting
-SETTINGS=`sed '/^#[[:alnum:]]/!d; s/^#//; s/ =.*//; /^include/d' postgresql.conf.sample`
-
-for i in $SETTINGS ; do
- ## it sure would be nice to replace this with an sql "not in" statement
- grep -i "\"$i\"" guc.c >/dev/null ||
- echo "$i seems to be missing from guc.c";
-done
-
-### What options are listed in guc.c, but don't appear
-### in postgresql.conf.sample?
-
-# grab everything that looks like a setting and convert it to lower case
-SETTINGS=`gawk -F '[",]' 'BEGIN{RS="\n\t\\\\{\n"} /",[[:space:]]*PGC_.*.*gettext_noop/ && !/NOT_IN_SAMPLE/{print tolower($2)}' guc.c`
-for i in $SETTINGS ; do
- grep "#$i " postgresql.conf.sample >/dev/null ||
- echo "$i seems to be missing from postgresql.conf.sample";
-done
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index f9504d3aec4..9b6ea9279bd 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -9622,6 +9622,36 @@ GetConfigOptionByName(const char *name, const char **varname, bool missing_ok)
return _ShowOption(record, true);
}
+/*
+ * Return an text[] array of the given flags (or a useful subset?) XXX
+ */
+static char *
+get_flags_array_text(int flags)
+{
+ StringInfoData ret;
+
+ initStringInfo(&ret);
+ appendStringInfoChar(&ret, '{');
+
+ if (flags & GUC_NO_SHOW_ALL)
+ appendStringInfo(&ret, "NO_SHOW_ALL,");
+ if (flags & GUC_NO_RESET_ALL)
+ appendStringInfo(&ret, "NO_RESET_ALL,");
+ if (flags & GUC_NOT_IN_SAMPLE)
+ appendStringInfo(&ret, "NOT_IN_SAMPLE,");
+ if (flags & GUC_EXPLAIN)
+ appendStringInfo(&ret, "EXPLAIN,");
+ if (flags & GUC_RUNTIME_COMPUTED)
+ appendStringInfo(&ret, "RUNTIME_COMPUTED,");
+
+ /* Remove trailing comma, if any */
+ if (ret.len > 1)
+ ret.data[--ret.len] = '\0';
+
+ appendStringInfoChar(&ret, '}');
+ return ret.data;
+}
+
/*
* Return GUC variable value by variable number; optionally return canonical
* form of name. Return value is palloc'd.
@@ -9849,6 +9879,9 @@ GetConfigOptionByNum(int varnum, const char **values, bool *noshow)
}
values[16] = (conf->status & GUC_PENDING_RESTART) ? "t" : "f";
+
+ /* flags */
+ values[17] = get_flags_array_text(conf->flags);
}
/*
@@ -9904,7 +9937,7 @@ show_config_by_name_missing_ok(PG_FUNCTION_ARGS)
* show_all_settings - equiv to SHOW ALL command but implemented as
* a Table Function.
*/
-#define NUM_PG_SETTINGS_ATTS 17
+#define NUM_PG_SETTINGS_ATTS 18
Datum
show_all_settings(PG_FUNCTION_ARGS)
@@ -9966,6 +9999,8 @@ show_all_settings(PG_FUNCTION_ARGS)
INT4OID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 17, "pending_restart",
BOOLOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 18, "flags",
+ TEXTARRAYOID, -1, 0);
/*
* Generate attribute metadata needed later to produce tuples from raw
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4d992dc2241..7e7e9a48fac 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -6092,9 +6092,9 @@
{ oid => '2084', descr => 'SHOW ALL as a function',
proname => 'pg_show_all_settings', prorows => '1000', proretset => 't',
provolatile => 's', prorettype => 'record', proargtypes => '',
- proallargtypes => '{text,text,text,text,text,text,text,text,text,text,text,_text,text,text,text,int4,bool}',
- proargmodes => '{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
- proargnames => '{name,setting,unit,category,short_desc,extra_desc,context,vartype,source,min_val,max_val,enumvals,boot_val,reset_val,sourcefile,sourceline,pending_restart}',
+ proallargtypes => '{text,text,text,text,text,text,text,text,text,text,text,_text,text,text,text,int4,bool,_text}',
+ proargmodes => '{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
+ proargnames => '{name,setting,unit,category,short_desc,extra_desc,context,vartype,source,min_val,max_val,enumvals,boot_val,reset_val,sourcefile,sourceline,pending_restart,flags}',
prosrc => 'show_all_settings' },
{ oid => '3329', descr => 'show config file settings',
proname => 'pg_show_all_file_settings', prorows => '1000', proretset => 't',
diff --git a/src/test/regress/expected/guc.out b/src/test/regress/expected/guc.out
index 59da91ff04d..d27b7c24747 100644
--- a/src/test/regress/expected/guc.out
+++ b/src/test/regress/expected/guc.out
@@ -813,3 +813,125 @@ set default_with_oids to f;
-- Should not allow to set it to true.
set default_with_oids to t;
ERROR: tables declared WITH OIDS are not supported
+--
+-- Test GUC categories and flags.
+--
+CREATE TABLE pg_settings_flags AS SELECT name, category,
+ 'NO_SHOW_ALL' =ANY(flags) AS no_show_all,
+ 'NO_RESET_ALL' =ANY(flags) AS no_reset_all,
+ 'NOT_IN_SAMPLE' =ANY(flags) AS not_in_sample,
+ 'EXPLAIN' =ANY(flags) AS guc_explain,
+ 'COMPUTED' =ANY(flags) AS guc_computed
+ FROM pg_show_all_settings();
+-- test that GUCS are in postgresql.conf
+SELECT lower(name) FROM pg_settings_flags WHERE NOT not_in_sample EXCEPT
+SELECT regexp_replace(ln, '^#?([_[:alpha:]]+) = .*', '\1') AS guc
+FROM (SELECT regexp_split_to_table(pg_read_file('postgresql.conf'), '\n') AS ln) conf
+WHERE ln ~ '^#?[[:alpha:]]'
+ORDER BY 1;
+ lower
+-----------------------------
+ config_file
+ plpgsql.check_asserts
+ plpgsql.extra_errors
+ plpgsql.extra_warnings
+ plpgsql.print_strict_params
+ plpgsql.variable_conflict
+(6 rows)
+
+-- test that lines in postgresql.conf that look like GUCs are GUCs
+SELECT regexp_replace(ln, '^#?([_[:alpha:]]+) = .*', '\1') AS guc
+FROM (SELECT regexp_split_to_table(pg_read_file('postgresql.conf'), '\n') AS ln) conf
+WHERE ln ~ '^#?[[:alpha:]]'
+EXCEPT SELECT lower(name) FROM pg_settings_flags WHERE NOT not_in_sample
+ORDER BY 1;
+ guc
+-------------------
+ include
+ include_dir
+ include_if_exists
+(3 rows)
+
+-- test that section:DEVELOPER GUCs are flagged GUC_NOT_IN_SAMPLE:
+SELECT * FROM pg_settings_flags
+WHERE category='Developer Options' AND NOT not_in_sample
+ORDER BY 1;
+ name | category | no_show_all | no_reset_all | not_in_sample | guc_explain | guc_computed
+------+----------+-------------+--------------+---------------+-------------+--------------
+(0 rows)
+
+-- Maybe the converse:
+SELECT * FROM pg_settings_flags
+WHERE category NOT IN ('Developer Options', 'Preset Options') AND not_in_sample
+ORDER BY 1;
+ name | category | no_show_all | no_reset_all | not_in_sample | guc_explain | guc_computed
+------------------------+-------------------------------------------------+-------------+--------------+---------------+-------------+--------------
+ application_name | Reporting and Logging / What to Log | f | f | t | f | f
+ transaction_deferrable | Client Connection Defaults / Statement Behavior | f | t | t | f | f
+ transaction_isolation | Client Connection Defaults / Statement Behavior | f | t | t | f | f
+ transaction_read_only | Client Connection Defaults / Statement Behavior | f | t | t | f | f
+(4 rows)
+
+-- Most Query Tuning GUCs are flagged as EXPLAIN:
+SELECT * FROM pg_settings_flags
+WHERE category ~ '^Query Tuning' AND NOT guc_explain
+ORDER BY 1;
+ name | category | no_show_all | no_reset_all | not_in_sample | guc_explain | guc_computed
+---------------------------+--------------------------------------+-------------+--------------+---------------+-------------+--------------
+ default_statistics_target | Query Tuning / Other Planner Options | f | f | f | f | f
+(1 row)
+
+-- Maybe the converse:
+SELECT * FROM pg_settings_flags
+WHERE guc_explain AND NOT category ~ '^Query Tuning|^Resource Usage'
+ORDER BY 1;
+ name | category | no_show_all | no_reset_all | not_in_sample | guc_explain | guc_computed
+---------------------+-------------------------------------------------+-------------+--------------+---------------+-------------+--------------
+ force_parallel_mode | Developer Options | f | f | t | t | f
+ search_path | Client Connection Defaults / Statement Behavior | f | f | f | t | f
+(2 rows)
+
+-- GUCs flagged RUNTIME are Preset
+SELECT * FROM pg_settings_flags
+WHERE guc_computed AND NOT category='Preset Options'
+ORDER BY 1;
+ name | category | no_show_all | no_reset_all | not_in_sample | guc_explain | guc_computed
+------+----------+-------------+--------------+---------------+-------------+--------------
+(0 rows)
+
+-- PRESET GUCs are flagged NOT_IN_SAMPLE
+SELECT * FROM pg_settings_flags
+WHERE category='Preset Options' AND NOT not_in_sample
+ORDER BY 1;
+ name | category | no_show_all | no_reset_all | not_in_sample | guc_explain | guc_computed
+------+----------+-------------+--------------+---------------+-------------+--------------
+(0 rows)
+
+-- NO_SHOW_ALL implies NO_RESET_ALL:
+SELECT * FROM pg_settings_flags
+WHERE no_show_all AND NOT no_reset_all
+ORDER BY 1;
+ name | category | no_show_all | no_reset_all | not_in_sample | guc_explain | guc_computed
+------+----------+-------------+--------------+---------------+-------------+--------------
+(0 rows)
+
+-- Usually the converse:
+SELECT * FROM pg_settings_flags
+WHERE NOT no_show_all AND no_reset_all
+ORDER BY 1;
+ name | category | no_show_all | no_reset_all | not_in_sample | guc_explain | guc_computed
+------------------------+-------------------------------------------------+-------------+--------------+---------------+-------------+--------------
+ transaction_deferrable | Client Connection Defaults / Statement Behavior | f | t | t | f | f
+ transaction_isolation | Client Connection Defaults / Statement Behavior | f | t | t | f | f
+ transaction_read_only | Client Connection Defaults / Statement Behavior | f | t | t | f | f
+(3 rows)
+
+-- NO_SHOW_ALL implies NOT_IN_SAMPLE:
+SELECT * FROM pg_settings_flags
+WHERE no_show_all AND NOT not_in_sample
+ORDER BY 1;
+ name | category | no_show_all | no_reset_all | not_in_sample | guc_explain | guc_computed
+------+----------+-------------+--------------+---------------+-------------+--------------
+(0 rows)
+
+DROP TABLE pg_settings_flags;
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index b58b062b10d..71cbdc37233 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1725,7 +1725,7 @@ pg_settings| SELECT a.name,
a.sourcefile,
a.sourceline,
a.pending_restart
- FROM pg_show_all_settings() a(name, setting, unit, category, short_desc, extra_desc, context, vartype, source, min_val, max_val, enumvals, boot_val, reset_val, sourcefile, sourceline, pending_restart);
+ FROM pg_show_all_settings() a(name, setting, unit, category, short_desc, extra_desc, context, vartype, source, min_val, max_val, enumvals, boot_val, reset_val, sourcefile, sourceline, pending_restart, flags);
pg_shadow| SELECT pg_authid.rolname AS usename,
pg_authid.oid AS usesysid,
pg_authid.rolcreatedb AS usecreatedb,
diff --git a/src/test/regress/sql/guc.sql b/src/test/regress/sql/guc.sql
index c39c11388d5..72b4c367941 100644
--- a/src/test/regress/sql/guc.sql
+++ b/src/test/regress/sql/guc.sql
@@ -311,3 +311,75 @@ reset check_function_bodies;
set default_with_oids to f;
-- Should not allow to set it to true.
set default_with_oids to t;
+
+--
+-- Test GUC categories and flags.
+--
+CREATE TABLE pg_settings_flags AS SELECT name, category,
+ 'NO_SHOW_ALL' =ANY(flags) AS no_show_all,
+ 'NO_RESET_ALL' =ANY(flags) AS no_reset_all,
+ 'NOT_IN_SAMPLE' =ANY(flags) AS not_in_sample,
+ 'EXPLAIN' =ANY(flags) AS guc_explain,
+ 'COMPUTED' =ANY(flags) AS guc_computed
+ FROM pg_show_all_settings();
+
+-- test that GUCS are in postgresql.conf
+SELECT lower(name) FROM pg_settings_flags WHERE NOT not_in_sample EXCEPT
+SELECT regexp_replace(ln, '^#?([_[:alpha:]]+) = .*', '\1') AS guc
+FROM (SELECT regexp_split_to_table(pg_read_file('postgresql.conf'), '\n') AS ln) conf
+WHERE ln ~ '^#?[[:alpha:]]'
+ORDER BY 1;
+
+-- test that lines in postgresql.conf that look like GUCs are GUCs
+SELECT regexp_replace(ln, '^#?([_[:alpha:]]+) = .*', '\1') AS guc
+FROM (SELECT regexp_split_to_table(pg_read_file('postgresql.conf'), '\n') AS ln) conf
+WHERE ln ~ '^#?[[:alpha:]]'
+EXCEPT SELECT lower(name) FROM pg_settings_flags WHERE NOT not_in_sample
+ORDER BY 1;
+
+-- test that section:DEVELOPER GUCs are flagged GUC_NOT_IN_SAMPLE:
+SELECT * FROM pg_settings_flags
+WHERE category='Developer Options' AND NOT not_in_sample
+ORDER BY 1;
+
+-- Maybe the converse:
+SELECT * FROM pg_settings_flags
+WHERE category NOT IN ('Developer Options', 'Preset Options') AND not_in_sample
+ORDER BY 1;
+
+-- Most Query Tuning GUCs are flagged as EXPLAIN:
+SELECT * FROM pg_settings_flags
+WHERE category ~ '^Query Tuning' AND NOT guc_explain
+ORDER BY 1;
+
+-- Maybe the converse:
+SELECT * FROM pg_settings_flags
+WHERE guc_explain AND NOT category ~ '^Query Tuning|^Resource Usage'
+ORDER BY 1;
+
+-- GUCs flagged RUNTIME are Preset
+SELECT * FROM pg_settings_flags
+WHERE guc_computed AND NOT category='Preset Options'
+ORDER BY 1;
+
+-- PRESET GUCs are flagged NOT_IN_SAMPLE
+SELECT * FROM pg_settings_flags
+WHERE category='Preset Options' AND NOT not_in_sample
+ORDER BY 1;
+
+-- NO_SHOW_ALL implies NO_RESET_ALL:
+SELECT * FROM pg_settings_flags
+WHERE no_show_all AND NOT no_reset_all
+ORDER BY 1;
+
+-- Usually the converse:
+SELECT * FROM pg_settings_flags
+WHERE NOT no_show_all AND no_reset_all
+ORDER BY 1;
+
+-- NO_SHOW_ALL implies NOT_IN_SAMPLE:
+SELECT * FROM pg_settings_flags
+WHERE no_show_all AND NOT not_in_sample
+ORDER BY 1;
+
+DROP TABLE pg_settings_flags;
--
2.17.1
--MW5yreqqjyrRcusr--
^ permalink raw reply [nested|flat] 37+ messages in thread
* [PATCH 2/2] Expose GUC flags in SQL function; retire ./check_guc
@ 2021-12-08 18:06 Justin Pryzby <[email protected]>
0 siblings, 0 replies; 37+ messages in thread
From: Justin Pryzby @ 2021-12-08 18:06 UTC (permalink / raw)
---
doc/src/sgml/func.sgml | 15 ++++
src/backend/utils/misc/check_guc | 29 -------
src/backend/utils/misc/guc.c | 37 +++++++++
src/include/catalog/pg_proc.dat | 6 ++
src/include/utils/guc.h | 3 +-
src/test/regress/expected/guc.out | 122 ++++++++++++++++++++++++++++++
src/test/regress/sql/guc.sql | 72 ++++++++++++++++++
7 files changed, 254 insertions(+), 30 deletions(-)
delete mode 100755 src/backend/utils/misc/check_guc
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 0ee6974f1c6..cbdbccb63d1 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -23596,6 +23596,21 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
</para></entry>
</row>
+ <row>
+ <entry role="func_table_entry"><para role="func_signature">
+ <indexterm>
+ <primary>pg_get_get_flags</primary>
+ </indexterm>
+ <function>pg_get_get_flags</function> ( <parameter>guc</parameter> <type>text</type> )
+ <returnvalue>text[]</returnvalue>
+ </para>
+ <para>
+ Return an array of flags associated with the given GUC, or NULL if the
+ GUC does not exist. Not all flags are exposed; the set of flags which
+ are exposed is subject to change.
+ </para></entry>
+ </row>
+
<row>
<entry role="func_table_entry"><para role="func_signature">
<indexterm>
diff --git a/src/backend/utils/misc/check_guc b/src/backend/utils/misc/check_guc
deleted file mode 100755
index 323ca13191b..00000000000
--- a/src/backend/utils/misc/check_guc
+++ /dev/null
@@ -1,29 +0,0 @@
-#! /bin/sh
-set -e
-
-## this script makes some assumptions about the formatting of files it parses.
-## in postgresql.conf.sample:
-## 1) the valid config settings may be preceded by a '#', but NOT '# '
-## (we use this to skip comments)
-
-### What options are listed in postgresql.conf.sample, but don't appear
-### in guc.c?
-
-# grab everything that looks like a setting
-SETTINGS=`sed '/^#[[:alnum:]]/!d; s/^#//; s/ =.*//; /^include/d' postgresql.conf.sample`
-
-for i in $SETTINGS ; do
- ## it sure would be nice to replace this with an sql "not in" statement
- grep -i "\"$i\"" guc.c >/dev/null ||
- echo "$i seems to be missing from guc.c";
-done
-
-### What options are listed in guc.c, but don't appear
-### in postgresql.conf.sample?
-
-# grab everything that looks like a setting and convert it to lower case
-SETTINGS=`gawk -F '[",]' 'BEGIN{RS="\n\t\\\\{\n"} /",[[:space:]]*PGC_.*.*gettext_noop/ && !/NOT_IN_SAMPLE/{print tolower($2)}' guc.c`
-for i in $SETTINGS ; do
- grep "#$i " postgresql.conf.sample >/dev/null ||
- echo "$i seems to be missing from postgresql.conf.sample";
-done
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 4c94f09c645..d3b56b2007c 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -9634,6 +9634,43 @@ GetConfigOptionByName(const char *name, const char **varname, bool missing_ok)
return _ShowOption(record, true);
}
+/*
+ * Return some flags for the specified GUC, or NULL if it doesn't exist.
+ */
+Datum
+pg_get_guc_flags(PG_FUNCTION_ARGS)
+{
+ char *varname = TextDatumGetCString(PG_GETARG_DATUM(0));
+ struct config_generic *record;
+ int cnt = 0;
+#define MAX_NUM_FLAGS 5
+ Datum flags[MAX_NUM_FLAGS];
+ ArrayType *a;
+
+ record = find_option(varname, false, true, ERROR);
+
+ /* return NULL if no such variable */
+ if (record == NULL)
+ PG_RETURN_NULL();
+
+ if (record->flags & GUC_NO_SHOW_ALL)
+ flags[cnt++] = CStringGetTextDatum("NO_SHOW_ALL");
+ if (record->flags & GUC_NO_RESET_ALL)
+ flags[cnt++] = CStringGetTextDatum("NO_RESET_ALL");
+ if (record->flags & GUC_NOT_IN_SAMPLE)
+ flags[cnt++] = CStringGetTextDatum("NOT_IN_SAMPLE");
+ if (record->flags & GUC_EXPLAIN)
+ flags[cnt++] = CStringGetTextDatum("EXPLAIN");
+ if (record->flags & GUC_RUNTIME_COMPUTED)
+ flags[cnt++] = CStringGetTextDatum("RUNTIME_COMPUTED");
+
+ Assert(cnt <= MAX_NUM_FLAGS);
+
+ /* Returns the record as Datum */
+ a = construct_array(flags, cnt, TEXTOID, -1, false, TYPALIGN_INT);
+ PG_RETURN_ARRAYTYPE_P(a);
+}
+
/*
* Return GUC variable value by variable number; optionally return canonical
* form of name. Return value is palloc'd.
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 0859dc81cac..562c1d779cb 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -6096,6 +6096,12 @@
proargmodes => '{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
proargnames => '{name,setting,unit,category,short_desc,extra_desc,context,vartype,source,min_val,max_val,enumvals,boot_val,reset_val,sourcefile,sourceline,pending_restart}',
prosrc => 'show_all_settings' },
+
+{ oid => '8921', descr => 'return flags for specified GUC',
+ proname => 'pg_get_guc_flags', provolatile => 's',
+ prorettype => '_text', proargtypes => 'text',
+ prosrc => 'pg_get_guc_flags' },
+
{ oid => '3329', descr => 'show config file settings',
proname => 'pg_show_all_file_settings', prorows => '1000', proretset => 't',
provolatile => 'v', prorettype => 'record', proargtypes => '',
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 6bb81707b09..1ac20f85ab3 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -198,8 +198,9 @@ typedef enum
#define GUC_QUALIFIER_SEPARATOR '.'
-/*
+/* --
* bit values in "flags" of a GUC variable
+ * Consider if any new flags should be exposed in pg_get_guc_flags().
*/
#define GUC_LIST_INPUT 0x0001 /* input can be list format */
#define GUC_LIST_QUOTE 0x0002 /* double-quote list elements */
diff --git a/src/test/regress/expected/guc.out b/src/test/regress/expected/guc.out
index 59da91ff04d..29173f3ce8e 100644
--- a/src/test/regress/expected/guc.out
+++ b/src/test/regress/expected/guc.out
@@ -813,3 +813,125 @@ set default_with_oids to f;
-- Should not allow to set it to true.
set default_with_oids to t;
ERROR: tables declared WITH OIDS are not supported
+--
+-- Test GUC categories and flags.
+--
+CREATE TABLE pg_settings_flags AS SELECT name, category,
+ 'NO_SHOW_ALL' =ANY(flags) AS no_show_all,
+ 'NO_RESET_ALL' =ANY(flags) AS no_reset_all,
+ 'NOT_IN_SAMPLE' =ANY(flags) AS not_in_sample,
+ 'EXPLAIN' =ANY(flags) AS guc_explain,
+ 'COMPUTED' =ANY(flags) AS guc_computed
+ FROM pg_show_all_settings() AS psas, pg_get_guc_flags(psas.name) AS flags;
+-- test that GUCS are in postgresql.conf
+SELECT lower(name) FROM pg_settings_flags WHERE NOT not_in_sample EXCEPT
+SELECT regexp_replace(ln, '^#?([_[:alpha:]]+) (= .*|[^ ]*$)', '\1') AS guc
+FROM (SELECT regexp_split_to_table(pg_read_file('postgresql.conf'), '\n') AS ln) conf
+WHERE ln ~ '^#?[[:alpha:]]'
+ORDER BY 1;
+ lower
+-----------------------------
+ config_file
+ plpgsql.check_asserts
+ plpgsql.extra_errors
+ plpgsql.extra_warnings
+ plpgsql.print_strict_params
+ plpgsql.variable_conflict
+(6 rows)
+
+-- test that lines in postgresql.conf that look like GUCs are GUCs
+SELECT regexp_replace(ln, '^#?([_[:alpha:]]+) (= .*|[^ ]*$)', '\1') AS guc
+FROM (SELECT regexp_split_to_table(pg_read_file('postgresql.conf'), '\n') AS ln) conf
+WHERE ln ~ '^#?[[:alpha:]]'
+EXCEPT SELECT lower(name) FROM pg_settings_flags WHERE NOT not_in_sample
+ORDER BY 1;
+ guc
+-------------------
+ include
+ include_dir
+ include_if_exists
+(3 rows)
+
+-- test that section:DEVELOPER GUCs are flagged GUC_NOT_IN_SAMPLE:
+SELECT * FROM pg_settings_flags
+WHERE category='Developer Options' AND NOT not_in_sample
+ORDER BY 1;
+ name | category | no_show_all | no_reset_all | not_in_sample | guc_explain | guc_computed
+------+----------+-------------+--------------+---------------+-------------+--------------
+(0 rows)
+
+-- Maybe the converse:
+SELECT * FROM pg_settings_flags
+WHERE category NOT IN ('Developer Options', 'Preset Options') AND not_in_sample
+ORDER BY 1;
+ name | category | no_show_all | no_reset_all | not_in_sample | guc_explain | guc_computed
+------------------------+-------------------------------------------------+-------------+--------------+---------------+-------------+--------------
+ application_name | Reporting and Logging / What to Log | f | f | t | f | f
+ transaction_deferrable | Client Connection Defaults / Statement Behavior | f | t | t | f | f
+ transaction_isolation | Client Connection Defaults / Statement Behavior | f | t | t | f | f
+ transaction_read_only | Client Connection Defaults / Statement Behavior | f | t | t | f | f
+(4 rows)
+
+-- Most Query Tuning GUCs are flagged as EXPLAIN:
+SELECT * FROM pg_settings_flags
+WHERE category ~ '^Query Tuning' AND NOT guc_explain
+ORDER BY 1;
+ name | category | no_show_all | no_reset_all | not_in_sample | guc_explain | guc_computed
+---------------------------+--------------------------------------+-------------+--------------+---------------+-------------+--------------
+ default_statistics_target | Query Tuning / Other Planner Options | f | f | f | f | f
+(1 row)
+
+-- Maybe the converse:
+SELECT * FROM pg_settings_flags
+WHERE guc_explain AND NOT category ~ '^Query Tuning|^Resource Usage'
+ORDER BY 1;
+ name | category | no_show_all | no_reset_all | not_in_sample | guc_explain | guc_computed
+---------------------+-------------------------------------------------+-------------+--------------+---------------+-------------+--------------
+ force_parallel_mode | Developer Options | f | f | t | t | f
+ search_path | Client Connection Defaults / Statement Behavior | f | f | f | t | f
+(2 rows)
+
+-- GUCs flagged RUNTIME are Preset
+SELECT * FROM pg_settings_flags
+WHERE guc_computed AND NOT category='Preset Options'
+ORDER BY 1;
+ name | category | no_show_all | no_reset_all | not_in_sample | guc_explain | guc_computed
+------+----------+-------------+--------------+---------------+-------------+--------------
+(0 rows)
+
+-- PRESET GUCs are flagged NOT_IN_SAMPLE
+SELECT * FROM pg_settings_flags
+WHERE category='Preset Options' AND NOT not_in_sample
+ORDER BY 1;
+ name | category | no_show_all | no_reset_all | not_in_sample | guc_explain | guc_computed
+------+----------+-------------+--------------+---------------+-------------+--------------
+(0 rows)
+
+-- NO_SHOW_ALL implies NO_RESET_ALL:
+SELECT * FROM pg_settings_flags
+WHERE no_show_all AND NOT no_reset_all
+ORDER BY 1;
+ name | category | no_show_all | no_reset_all | not_in_sample | guc_explain | guc_computed
+------+----------+-------------+--------------+---------------+-------------+--------------
+(0 rows)
+
+-- Usually the converse:
+SELECT * FROM pg_settings_flags
+WHERE NOT no_show_all AND no_reset_all
+ORDER BY 1;
+ name | category | no_show_all | no_reset_all | not_in_sample | guc_explain | guc_computed
+------------------------+-------------------------------------------------+-------------+--------------+---------------+-------------+--------------
+ transaction_deferrable | Client Connection Defaults / Statement Behavior | f | t | t | f | f
+ transaction_isolation | Client Connection Defaults / Statement Behavior | f | t | t | f | f
+ transaction_read_only | Client Connection Defaults / Statement Behavior | f | t | t | f | f
+(3 rows)
+
+-- NO_SHOW_ALL implies NOT_IN_SAMPLE:
+SELECT * FROM pg_settings_flags
+WHERE no_show_all AND NOT not_in_sample
+ORDER BY 1;
+ name | category | no_show_all | no_reset_all | not_in_sample | guc_explain | guc_computed
+------+----------+-------------+--------------+---------------+-------------+--------------
+(0 rows)
+
+DROP TABLE pg_settings_flags;
diff --git a/src/test/regress/sql/guc.sql b/src/test/regress/sql/guc.sql
index c39c11388d5..47b6a233d5c 100644
--- a/src/test/regress/sql/guc.sql
+++ b/src/test/regress/sql/guc.sql
@@ -311,3 +311,75 @@ reset check_function_bodies;
set default_with_oids to f;
-- Should not allow to set it to true.
set default_with_oids to t;
+
+--
+-- Test GUC categories and flags.
+--
+CREATE TABLE pg_settings_flags AS SELECT name, category,
+ 'NO_SHOW_ALL' =ANY(flags) AS no_show_all,
+ 'NO_RESET_ALL' =ANY(flags) AS no_reset_all,
+ 'NOT_IN_SAMPLE' =ANY(flags) AS not_in_sample,
+ 'EXPLAIN' =ANY(flags) AS guc_explain,
+ 'COMPUTED' =ANY(flags) AS guc_computed
+ FROM pg_show_all_settings() AS psas, pg_get_guc_flags(psas.name) AS flags;
+
+-- test that GUCS are in postgresql.conf
+SELECT lower(name) FROM pg_settings_flags WHERE NOT not_in_sample EXCEPT
+SELECT regexp_replace(ln, '^#?([_[:alpha:]]+) (= .*|[^ ]*$)', '\1') AS guc
+FROM (SELECT regexp_split_to_table(pg_read_file('postgresql.conf'), '\n') AS ln) conf
+WHERE ln ~ '^#?[[:alpha:]]'
+ORDER BY 1;
+
+-- test that lines in postgresql.conf that look like GUCs are GUCs
+SELECT regexp_replace(ln, '^#?([_[:alpha:]]+) (= .*|[^ ]*$)', '\1') AS guc
+FROM (SELECT regexp_split_to_table(pg_read_file('postgresql.conf'), '\n') AS ln) conf
+WHERE ln ~ '^#?[[:alpha:]]'
+EXCEPT SELECT lower(name) FROM pg_settings_flags WHERE NOT not_in_sample
+ORDER BY 1;
+
+-- test that section:DEVELOPER GUCs are flagged GUC_NOT_IN_SAMPLE:
+SELECT * FROM pg_settings_flags
+WHERE category='Developer Options' AND NOT not_in_sample
+ORDER BY 1;
+
+-- Maybe the converse:
+SELECT * FROM pg_settings_flags
+WHERE category NOT IN ('Developer Options', 'Preset Options') AND not_in_sample
+ORDER BY 1;
+
+-- Most Query Tuning GUCs are flagged as EXPLAIN:
+SELECT * FROM pg_settings_flags
+WHERE category ~ '^Query Tuning' AND NOT guc_explain
+ORDER BY 1;
+
+-- Maybe the converse:
+SELECT * FROM pg_settings_flags
+WHERE guc_explain AND NOT category ~ '^Query Tuning|^Resource Usage'
+ORDER BY 1;
+
+-- GUCs flagged RUNTIME are Preset
+SELECT * FROM pg_settings_flags
+WHERE guc_computed AND NOT category='Preset Options'
+ORDER BY 1;
+
+-- PRESET GUCs are flagged NOT_IN_SAMPLE
+SELECT * FROM pg_settings_flags
+WHERE category='Preset Options' AND NOT not_in_sample
+ORDER BY 1;
+
+-- NO_SHOW_ALL implies NO_RESET_ALL:
+SELECT * FROM pg_settings_flags
+WHERE no_show_all AND NOT no_reset_all
+ORDER BY 1;
+
+-- Usually the converse:
+SELECT * FROM pg_settings_flags
+WHERE NOT no_show_all AND no_reset_all
+ORDER BY 1;
+
+-- NO_SHOW_ALL implies NOT_IN_SAMPLE:
+SELECT * FROM pg_settings_flags
+WHERE no_show_all AND NOT not_in_sample
+ORDER BY 1;
+
+DROP TABLE pg_settings_flags;
--
2.17.1
--i3WE5m5QLioBhvvb--
^ permalink raw reply [nested|flat] 37+ messages in thread
* [PATCH 2/2] Expose GUC flags in SQL function; retire ./check_guc
@ 2021-12-08 18:06 Justin Pryzby <[email protected]>
0 siblings, 0 replies; 37+ messages in thread
From: Justin Pryzby @ 2021-12-08 18:06 UTC (permalink / raw)
---
src/backend/catalog/system_views.sql | 19 ++++-
src/backend/utils/misc/check_guc | 29 -------
src/backend/utils/misc/guc.c | 37 +++++++-
src/include/catalog/pg_proc.dat | 6 +-
src/test/regress/expected/guc.out | 122 +++++++++++++++++++++++++++
src/test/regress/expected/rules.out | 2 +-
src/test/regress/sql/guc.sql | 72 ++++++++++++++++
7 files changed, 252 insertions(+), 35 deletions(-)
delete mode 100755 src/backend/utils/misc/check_guc
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 3cb69b1f87b..cdae0616bdd 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -582,7 +582,24 @@ FROM
JOIN pg_authid rol ON l.classoid = rol.tableoid AND l.objoid = rol.oid;
CREATE VIEW pg_settings AS
- SELECT * FROM pg_show_all_settings() AS A;
+ SELECT a.name,
+ a.setting,
+ a.unit,
+ a.category,
+ a.short_desc,
+ a.extra_desc,
+ a.context,
+ a.vartype,
+ a.source,
+ a.min_val,
+ a.max_val,
+ a.enumvals,
+ a.boot_val,
+ a.reset_val,
+ a.sourcefile,
+ a.sourceline,
+ a.pending_restart
+ FROM pg_show_all_settings() AS A;
CREATE RULE pg_settings_u AS
ON UPDATE TO pg_settings
diff --git a/src/backend/utils/misc/check_guc b/src/backend/utils/misc/check_guc
deleted file mode 100755
index 323ca13191b..00000000000
--- a/src/backend/utils/misc/check_guc
+++ /dev/null
@@ -1,29 +0,0 @@
-#! /bin/sh
-set -e
-
-## this script makes some assumptions about the formatting of files it parses.
-## in postgresql.conf.sample:
-## 1) the valid config settings may be preceded by a '#', but NOT '# '
-## (we use this to skip comments)
-
-### What options are listed in postgresql.conf.sample, but don't appear
-### in guc.c?
-
-# grab everything that looks like a setting
-SETTINGS=`sed '/^#[[:alnum:]]/!d; s/^#//; s/ =.*//; /^include/d' postgresql.conf.sample`
-
-for i in $SETTINGS ; do
- ## it sure would be nice to replace this with an sql "not in" statement
- grep -i "\"$i\"" guc.c >/dev/null ||
- echo "$i seems to be missing from guc.c";
-done
-
-### What options are listed in guc.c, but don't appear
-### in postgresql.conf.sample?
-
-# grab everything that looks like a setting and convert it to lower case
-SETTINGS=`gawk -F '[",]' 'BEGIN{RS="\n\t\\\\{\n"} /",[[:space:]]*PGC_.*.*gettext_noop/ && !/NOT_IN_SAMPLE/{print tolower($2)}' guc.c`
-for i in $SETTINGS ; do
- grep "#$i " postgresql.conf.sample >/dev/null ||
- echo "$i seems to be missing from postgresql.conf.sample";
-done
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 4c94f09c645..2cb84d68610 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -9634,6 +9634,36 @@ GetConfigOptionByName(const char *name, const char **varname, bool missing_ok)
return _ShowOption(record, true);
}
+/*
+ * Return an text[] array of the given flags (or a useful subset?) XXX
+ */
+static char *
+get_flags_array_text(int flags)
+{
+ StringInfoData ret;
+
+ initStringInfo(&ret);
+ appendStringInfoChar(&ret, '{');
+
+ if (flags & GUC_NO_SHOW_ALL)
+ appendStringInfo(&ret, "NO_SHOW_ALL,");
+ if (flags & GUC_NO_RESET_ALL)
+ appendStringInfo(&ret, "NO_RESET_ALL,");
+ if (flags & GUC_NOT_IN_SAMPLE)
+ appendStringInfo(&ret, "NOT_IN_SAMPLE,");
+ if (flags & GUC_EXPLAIN)
+ appendStringInfo(&ret, "EXPLAIN,");
+ if (flags & GUC_RUNTIME_COMPUTED)
+ appendStringInfo(&ret, "RUNTIME_COMPUTED,");
+
+ /* Remove trailing comma, if any */
+ if (ret.len > 1)
+ ret.data[--ret.len] = '\0';
+
+ appendStringInfoChar(&ret, '}');
+ return ret.data;
+}
+
/*
* Return GUC variable value by variable number; optionally return canonical
* form of name. Return value is palloc'd.
@@ -9861,6 +9891,9 @@ GetConfigOptionByNum(int varnum, const char **values, bool *noshow)
}
values[16] = (conf->status & GUC_PENDING_RESTART) ? "t" : "f";
+
+ /* flags */
+ values[17] = get_flags_array_text(conf->flags);
}
/*
@@ -9916,7 +9949,7 @@ show_config_by_name_missing_ok(PG_FUNCTION_ARGS)
* show_all_settings - equiv to SHOW ALL command but implemented as
* a Table Function.
*/
-#define NUM_PG_SETTINGS_ATTS 17
+#define NUM_PG_SETTINGS_ATTS 18
Datum
show_all_settings(PG_FUNCTION_ARGS)
@@ -9978,6 +10011,8 @@ show_all_settings(PG_FUNCTION_ARGS)
INT4OID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 17, "pending_restart",
BOOLOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 18, "flags",
+ TEXTARRAYOID, -1, 0);
/*
* Generate attribute metadata needed later to produce tuples from raw
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 0859dc81cac..1d7f6b4d376 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -6092,9 +6092,9 @@
{ oid => '2084', descr => 'SHOW ALL as a function',
proname => 'pg_show_all_settings', prorows => '1000', proretset => 't',
provolatile => 's', prorettype => 'record', proargtypes => '',
- proallargtypes => '{text,text,text,text,text,text,text,text,text,text,text,_text,text,text,text,int4,bool}',
- proargmodes => '{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
- proargnames => '{name,setting,unit,category,short_desc,extra_desc,context,vartype,source,min_val,max_val,enumvals,boot_val,reset_val,sourcefile,sourceline,pending_restart}',
+ proallargtypes => '{text,text,text,text,text,text,text,text,text,text,text,_text,text,text,text,int4,bool,_text}',
+ proargmodes => '{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
+ proargnames => '{name,setting,unit,category,short_desc,extra_desc,context,vartype,source,min_val,max_val,enumvals,boot_val,reset_val,sourcefile,sourceline,pending_restart,flags}',
prosrc => 'show_all_settings' },
{ oid => '3329', descr => 'show config file settings',
proname => 'pg_show_all_file_settings', prorows => '1000', proretset => 't',
diff --git a/src/test/regress/expected/guc.out b/src/test/regress/expected/guc.out
index 59da91ff04d..5f15b5680be 100644
--- a/src/test/regress/expected/guc.out
+++ b/src/test/regress/expected/guc.out
@@ -813,3 +813,125 @@ set default_with_oids to f;
-- Should not allow to set it to true.
set default_with_oids to t;
ERROR: tables declared WITH OIDS are not supported
+--
+-- Test GUC categories and flags.
+--
+CREATE TABLE pg_settings_flags AS SELECT name, category,
+ 'NO_SHOW_ALL' =ANY(flags) AS no_show_all,
+ 'NO_RESET_ALL' =ANY(flags) AS no_reset_all,
+ 'NOT_IN_SAMPLE' =ANY(flags) AS not_in_sample,
+ 'EXPLAIN' =ANY(flags) AS guc_explain,
+ 'COMPUTED' =ANY(flags) AS guc_computed
+ FROM pg_show_all_settings();
+-- test that GUCS are in postgresql.conf
+SELECT lower(name) FROM pg_settings_flags WHERE NOT not_in_sample EXCEPT
+SELECT regexp_replace(ln, '^#?([_[:alpha:]]+) (= .*|[^ ]*$)', '\1') AS guc
+FROM (SELECT regexp_split_to_table(pg_read_file('postgresql.conf'), '\n') AS ln) conf
+WHERE ln ~ '^#?[[:alpha:]]'
+ORDER BY 1;
+ lower
+-----------------------------
+ config_file
+ plpgsql.check_asserts
+ plpgsql.extra_errors
+ plpgsql.extra_warnings
+ plpgsql.print_strict_params
+ plpgsql.variable_conflict
+(6 rows)
+
+-- test that lines in postgresql.conf that look like GUCs are GUCs
+SELECT regexp_replace(ln, '^#?([_[:alpha:]]+) (= .*|[^ ]*$)', '\1') AS guc
+FROM (SELECT regexp_split_to_table(pg_read_file('postgresql.conf'), '\n') AS ln) conf
+WHERE ln ~ '^#?[[:alpha:]]'
+EXCEPT SELECT lower(name) FROM pg_settings_flags WHERE NOT not_in_sample
+ORDER BY 1;
+ guc
+-------------------
+ include
+ include_dir
+ include_if_exists
+(3 rows)
+
+-- test that section:DEVELOPER GUCs are flagged GUC_NOT_IN_SAMPLE:
+SELECT * FROM pg_settings_flags
+WHERE category='Developer Options' AND NOT not_in_sample
+ORDER BY 1;
+ name | category | no_show_all | no_reset_all | not_in_sample | guc_explain | guc_computed
+------+----------+-------------+--------------+---------------+-------------+--------------
+(0 rows)
+
+-- Maybe the converse:
+SELECT * FROM pg_settings_flags
+WHERE category NOT IN ('Developer Options', 'Preset Options') AND not_in_sample
+ORDER BY 1;
+ name | category | no_show_all | no_reset_all | not_in_sample | guc_explain | guc_computed
+------------------------+-------------------------------------------------+-------------+--------------+---------------+-------------+--------------
+ application_name | Reporting and Logging / What to Log | f | f | t | f | f
+ transaction_deferrable | Client Connection Defaults / Statement Behavior | f | t | t | f | f
+ transaction_isolation | Client Connection Defaults / Statement Behavior | f | t | t | f | f
+ transaction_read_only | Client Connection Defaults / Statement Behavior | f | t | t | f | f
+(4 rows)
+
+-- Most Query Tuning GUCs are flagged as EXPLAIN:
+SELECT * FROM pg_settings_flags
+WHERE category ~ '^Query Tuning' AND NOT guc_explain
+ORDER BY 1;
+ name | category | no_show_all | no_reset_all | not_in_sample | guc_explain | guc_computed
+---------------------------+--------------------------------------+-------------+--------------+---------------+-------------+--------------
+ default_statistics_target | Query Tuning / Other Planner Options | f | f | f | f | f
+(1 row)
+
+-- Maybe the converse:
+SELECT * FROM pg_settings_flags
+WHERE guc_explain AND NOT category ~ '^Query Tuning|^Resource Usage'
+ORDER BY 1;
+ name | category | no_show_all | no_reset_all | not_in_sample | guc_explain | guc_computed
+---------------------+-------------------------------------------------+-------------+--------------+---------------+-------------+--------------
+ force_parallel_mode | Developer Options | f | f | t | t | f
+ search_path | Client Connection Defaults / Statement Behavior | f | f | f | t | f
+(2 rows)
+
+-- GUCs flagged RUNTIME are Preset
+SELECT * FROM pg_settings_flags
+WHERE guc_computed AND NOT category='Preset Options'
+ORDER BY 1;
+ name | category | no_show_all | no_reset_all | not_in_sample | guc_explain | guc_computed
+------+----------+-------------+--------------+---------------+-------------+--------------
+(0 rows)
+
+-- PRESET GUCs are flagged NOT_IN_SAMPLE
+SELECT * FROM pg_settings_flags
+WHERE category='Preset Options' AND NOT not_in_sample
+ORDER BY 1;
+ name | category | no_show_all | no_reset_all | not_in_sample | guc_explain | guc_computed
+------+----------+-------------+--------------+---------------+-------------+--------------
+(0 rows)
+
+-- NO_SHOW_ALL implies NO_RESET_ALL:
+SELECT * FROM pg_settings_flags
+WHERE no_show_all AND NOT no_reset_all
+ORDER BY 1;
+ name | category | no_show_all | no_reset_all | not_in_sample | guc_explain | guc_computed
+------+----------+-------------+--------------+---------------+-------------+--------------
+(0 rows)
+
+-- Usually the converse:
+SELECT * FROM pg_settings_flags
+WHERE NOT no_show_all AND no_reset_all
+ORDER BY 1;
+ name | category | no_show_all | no_reset_all | not_in_sample | guc_explain | guc_computed
+------------------------+-------------------------------------------------+-------------+--------------+---------------+-------------+--------------
+ transaction_deferrable | Client Connection Defaults / Statement Behavior | f | t | t | f | f
+ transaction_isolation | Client Connection Defaults / Statement Behavior | f | t | t | f | f
+ transaction_read_only | Client Connection Defaults / Statement Behavior | f | t | t | f | f
+(3 rows)
+
+-- NO_SHOW_ALL implies NOT_IN_SAMPLE:
+SELECT * FROM pg_settings_flags
+WHERE no_show_all AND NOT not_in_sample
+ORDER BY 1;
+ name | category | no_show_all | no_reset_all | not_in_sample | guc_explain | guc_computed
+------+----------+-------------+--------------+---------------+-------------+--------------
+(0 rows)
+
+DROP TABLE pg_settings_flags;
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index d652f7b5fb4..833c1fab6c7 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1725,7 +1725,7 @@ pg_settings| SELECT a.name,
a.sourcefile,
a.sourceline,
a.pending_restart
- FROM pg_show_all_settings() a(name, setting, unit, category, short_desc, extra_desc, context, vartype, source, min_val, max_val, enumvals, boot_val, reset_val, sourcefile, sourceline, pending_restart);
+ FROM pg_show_all_settings() a(name, setting, unit, category, short_desc, extra_desc, context, vartype, source, min_val, max_val, enumvals, boot_val, reset_val, sourcefile, sourceline, pending_restart, flags);
pg_shadow| SELECT pg_authid.rolname AS usename,
pg_authid.oid AS usesysid,
pg_authid.rolcreatedb AS usecreatedb,
diff --git a/src/test/regress/sql/guc.sql b/src/test/regress/sql/guc.sql
index c39c11388d5..c3898ae690f 100644
--- a/src/test/regress/sql/guc.sql
+++ b/src/test/regress/sql/guc.sql
@@ -311,3 +311,75 @@ reset check_function_bodies;
set default_with_oids to f;
-- Should not allow to set it to true.
set default_with_oids to t;
+
+--
+-- Test GUC categories and flags.
+--
+CREATE TABLE pg_settings_flags AS SELECT name, category,
+ 'NO_SHOW_ALL' =ANY(flags) AS no_show_all,
+ 'NO_RESET_ALL' =ANY(flags) AS no_reset_all,
+ 'NOT_IN_SAMPLE' =ANY(flags) AS not_in_sample,
+ 'EXPLAIN' =ANY(flags) AS guc_explain,
+ 'COMPUTED' =ANY(flags) AS guc_computed
+ FROM pg_show_all_settings();
+
+-- test that GUCS are in postgresql.conf
+SELECT lower(name) FROM pg_settings_flags WHERE NOT not_in_sample EXCEPT
+SELECT regexp_replace(ln, '^#?([_[:alpha:]]+) (= .*|[^ ]*$)', '\1') AS guc
+FROM (SELECT regexp_split_to_table(pg_read_file('postgresql.conf'), '\n') AS ln) conf
+WHERE ln ~ '^#?[[:alpha:]]'
+ORDER BY 1;
+
+-- test that lines in postgresql.conf that look like GUCs are GUCs
+SELECT regexp_replace(ln, '^#?([_[:alpha:]]+) (= .*|[^ ]*$)', '\1') AS guc
+FROM (SELECT regexp_split_to_table(pg_read_file('postgresql.conf'), '\n') AS ln) conf
+WHERE ln ~ '^#?[[:alpha:]]'
+EXCEPT SELECT lower(name) FROM pg_settings_flags WHERE NOT not_in_sample
+ORDER BY 1;
+
+-- test that section:DEVELOPER GUCs are flagged GUC_NOT_IN_SAMPLE:
+SELECT * FROM pg_settings_flags
+WHERE category='Developer Options' AND NOT not_in_sample
+ORDER BY 1;
+
+-- Maybe the converse:
+SELECT * FROM pg_settings_flags
+WHERE category NOT IN ('Developer Options', 'Preset Options') AND not_in_sample
+ORDER BY 1;
+
+-- Most Query Tuning GUCs are flagged as EXPLAIN:
+SELECT * FROM pg_settings_flags
+WHERE category ~ '^Query Tuning' AND NOT guc_explain
+ORDER BY 1;
+
+-- Maybe the converse:
+SELECT * FROM pg_settings_flags
+WHERE guc_explain AND NOT category ~ '^Query Tuning|^Resource Usage'
+ORDER BY 1;
+
+-- GUCs flagged RUNTIME are Preset
+SELECT * FROM pg_settings_flags
+WHERE guc_computed AND NOT category='Preset Options'
+ORDER BY 1;
+
+-- PRESET GUCs are flagged NOT_IN_SAMPLE
+SELECT * FROM pg_settings_flags
+WHERE category='Preset Options' AND NOT not_in_sample
+ORDER BY 1;
+
+-- NO_SHOW_ALL implies NO_RESET_ALL:
+SELECT * FROM pg_settings_flags
+WHERE no_show_all AND NOT no_reset_all
+ORDER BY 1;
+
+-- Usually the converse:
+SELECT * FROM pg_settings_flags
+WHERE NOT no_show_all AND no_reset_all
+ORDER BY 1;
+
+-- NO_SHOW_ALL implies NOT_IN_SAMPLE:
+SELECT * FROM pg_settings_flags
+WHERE no_show_all AND NOT not_in_sample
+ORDER BY 1;
+
+DROP TABLE pg_settings_flags;
--
2.17.1
--EsfvRFssnM00t552--
^ permalink raw reply [nested|flat] 37+ messages in thread
* Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect
@ 2025-11-18 15:59 Fujii Masao <[email protected]>
0 siblings, 3 replies; 37+ messages in thread
From: Fujii Masao @ 2025-11-18 15:59 UTC (permalink / raw)
To: PostgreSQL Hackers <[email protected]>
Hi,
In logical replication, any GUC settings specified in the CONNECTION clause of
CREATE SUBSCRIPTION are currently ignored. For example:
CREATE SUBSCRIPTION mysub
CONNECTION 'options=''-c wal_sender_timeout=1000'''
PUBLICATION ...
The wal_sender_timeout value here has no effect.
This is inconvenient when different logical replication walsenders need
different settings - e.g., a small wal_sender_timeout for walsender
connecting to a nearby subscriber and a larger one for walsender
connecting to a distant subscriber. Right now, it's not easy for users
to control such per-connection behavior.
The reason of thid limitation is that libpqrcv_connect() always overwrites
the options connection parameter as follows:
keys[++i] = "options";
vals[i] = "-c datestyle=ISO -c intervalstyle=postgres -c
extra_float_digits=3";
This wipes out any user-specified GUCs in the CONNECTION string.
Physical replication does not have this problem because it does not overwrite
options, so GUCs in primary_conninfo are honored.
To remove this restriction, how about switching to issuing SET commands for
datestyle, intervalstyle, and extra_float_digits after the connection
is established,
similar to what postgres_fdw does, instead of forcing them into options?
That would allow user-specified GUC settings in CREATE SUBSCRIPTION to
take effect.
This overwrite behavior was introduced in commit f3d4019da5d and chosen mainly
to avoid extra network round trips according to the discussion [1].
While SET commands would add a round trip, it only happens at
connection startup,
which is infrequent - so the overhead seems negligible.
Thoughts?
Regards,
[1] https://postgr.es/m/CAFF0-CF=D7pc6st-3A9f1JnOt0qmc+BcBPVzD6fLYisKyAjkGA@mail.gmail.com
--
Fujii Masao
^ permalink raw reply [nested|flat] 37+ messages in thread
* Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect
@ 2025-11-19 06:22 Fujii Masao <[email protected]>
parent: Fujii Masao <[email protected]>
2 siblings, 1 reply; 37+ messages in thread
From: Fujii Masao @ 2025-11-19 06:22 UTC (permalink / raw)
To: PostgreSQL Hackers <[email protected]>
On Wed, Nov 19, 2025 at 12:59 AM Fujii Masao <[email protected]> wrote:
>
> Hi,
>
> In logical replication, any GUC settings specified in the CONNECTION clause of
> CREATE SUBSCRIPTION are currently ignored. For example:
>
> CREATE SUBSCRIPTION mysub
> CONNECTION 'options=''-c wal_sender_timeout=1000'''
> PUBLICATION ...
>
> The wal_sender_timeout value here has no effect.
>
> This is inconvenient when different logical replication walsenders need
> different settings - e.g., a small wal_sender_timeout for walsender
> connecting to a nearby subscriber and a larger one for walsender
> connecting to a distant subscriber. Right now, it's not easy for users
> to control such per-connection behavior.
>
> The reason of thid limitation is that libpqrcv_connect() always overwrites
> the options connection parameter as follows:
>
> keys[++i] = "options";
> vals[i] = "-c datestyle=ISO -c intervalstyle=postgres -c
> extra_float_digits=3";
>
> This wipes out any user-specified GUCs in the CONNECTION string.
> Physical replication does not have this problem because it does not overwrite
> options, so GUCs in primary_conninfo are honored.
>
> To remove this restriction, how about switching to issuing SET commands for
> datestyle, intervalstyle, and extra_float_digits after the connection
> is established,
> similar to what postgres_fdw does, instead of forcing them into options?
> That would allow user-specified GUC settings in CREATE SUBSCRIPTION to
> take effect.
>
> This overwrite behavior was introduced in commit f3d4019da5d and chosen mainly
> to avoid extra network round trips according to the discussion [1].
> While SET commands would add a round trip, it only happens at
> connection startup,
> which is infrequent - so the overhead seems negligible.
>
> Thoughts?
Attached is a patch implementing this idea.
I've also added it to the next CommitFest.
Regards,
--
Fujii Masao
Attachments:
[application/octet-stream] v1-0001-Honor-GUC-settings-specified-in-CREATE-SUBSCRIPTI.patch (3.5K, ../../CAHGQGwEUp-OVRTMXG-oViKPhQdSXa8WaUgXVo89=H3wdJ8pWRA@mail.gmail.com/2-v1-0001-Honor-GUC-settings-specified-in-CREATE-SUBSCRIPTI.patch)
download | inline diff:
From 7d458371f8d737357d4d1e6899dd81f916c2d70b Mon Sep 17 00:00:00 2001
From: Fujii Masao <[email protected]>
Date: Wed, 19 Nov 2025 08:49:46 +0900
Subject: [PATCH v1] Honor GUC settings specified in CREATE SUBSCRIPTION
CONNECTION.
Previously, GUC settings supplied in the CONNECTION clause of
CREATE SUBSCRIPTION were not used by the publisher's walsender.
For example, in:
CREATE SUBSCRIPTION mysub
CONNECTION 'options=''-c wal_sender_timeout=1000'''
PUBLICATION ...
the wal_sender_timeout setting had no effect.
This contrasted with physical replication, where GUCs in primary_conninfo
are applied to the walsender.
This limitation made it difficult to tune logical replication connections
individually, for example, using a shorter timeout for walsender connecting
to a nearby subscriber and a longer one for walsender connecting
to a remote subscriber.
This commit removes the restriction by changing how logical replication
connections are established so that GUC settings in the CONNECTION string
are properly passed through to and uesd by the walsender. This enables
per-connection configuration for logical replication.
---
.../libpqwalreceiver/libpqwalreceiver.c | 43 ++++++++++++++-----
1 file changed, 32 insertions(+), 11 deletions(-)
diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
index 239641bfbb6..d880309e2da 100644
--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
+++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
@@ -180,17 +180,6 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
/* Tell the publisher to translate to our encoding */
keys[++i] = "client_encoding";
vals[i] = GetDatabaseEncodingName();
-
- /*
- * Force assorted GUC parameters to settings that ensure that the
- * publisher will output data values in a form that is unambiguous
- * to the subscriber. (We don't want to modify the subscriber's
- * GUC settings, since that might surprise user-defined code
- * running in the subscriber, such as triggers.) This should
- * match what pg_dump does.
- */
- keys[++i] = "options";
- vals[i] = "-c datestyle=ISO -c intervalstyle=postgres -c extra_float_digits=3";
}
else
{
@@ -256,6 +245,38 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
PQclear(res);
}
+ /*
+ * Force assorted GUC parameters to settings that ensure that the
+ * publisher will output data values in a form that is unambiguous to the
+ * subscriber. (We don't want to modify the subscriber's GUC settings,
+ * since that might surprise user-defined code running in the subscriber,
+ * such as triggers.) This should match what pg_dump does.
+ */
+ if (replication && logical)
+ {
+ const char *params[] =
+ {"datestyle", "intervalstyle", "extra_float_digits", NULL};
+ const char *values[] = {"ISO", "postgres", "3", NULL};
+
+ for (int i = 0; params[i] != NULL; i++)
+ {
+ char sql[100];
+ PGresult *res;
+
+ sprintf(sql, "SET %s = %s", params[i], values[i]);
+ res = libpqsrv_exec(conn->streamConn, sql,
+ WAIT_EVENT_LIBPQWALRECEIVER_RECEIVE);
+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
+ {
+ PQclear(res);
+ *err = psprintf(_("could not set %s: %s"),
+ params[i], pchomp(PQerrorMessage(conn->streamConn)));
+ goto bad_connection;
+ }
+ PQclear(res);
+ }
+ }
+
conn->logical = logical;
return conn;
--
2.51.2
^ permalink raw reply [nested|flat] 37+ messages in thread
* Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect
@ 2025-11-19 10:38 Fujii Masao <[email protected]>
parent: Fujii Masao <[email protected]>
0 siblings, 0 replies; 37+ messages in thread
From: Fujii Masao @ 2025-11-19 10:38 UTC (permalink / raw)
To: PostgreSQL Hackers <[email protected]>
On Wed, Nov 19, 2025 at 3:22 PM Fujii Masao <[email protected]> wrote:
> Attached is a patch implementing this idea.
> I've also added it to the next CommitFest.
I've fixed the compiler warning issue.
Attached is an updated version of the patch.
Regards,
--
Fujii Masao
Attachments:
[application/octet-stream] v2-0001-Honor-GUC-settings-specified-in-CREATE-SUBSCRIPTI.patch (3.5K, ../../CAHGQGwHtE2cjQrjjzs9mJ966uvXWiT4K4O2hC9scr7AdGw=4dg@mail.gmail.com/2-v2-0001-Honor-GUC-settings-specified-in-CREATE-SUBSCRIPTI.patch)
download | inline diff:
From 5fc2ab0592d5516b40266df2c786780d49d20b80 Mon Sep 17 00:00:00 2001
From: Fujii Masao <[email protected]>
Date: Wed, 19 Nov 2025 08:49:46 +0900
Subject: [PATCH v2] Honor GUC settings specified in CREATE SUBSCRIPTION
CONNECTION.
Previously, GUC settings supplied in the CONNECTION clause of
CREATE SUBSCRIPTION were not used by the publisher's walsender.
For example, in:
CREATE SUBSCRIPTION mysub
CONNECTION 'options=''-c wal_sender_timeout=1000'''
PUBLICATION ...
the wal_sender_timeout setting had no effect.
This contrasted with physical replication, where GUCs in primary_conninfo
are applied to the walsender.
This limitation made it difficult to tune logical replication connections
individually, for example, using a shorter timeout for walsender connecting
to a nearby subscriber and a longer one for walsender connecting
to a remote subscriber.
This commit removes the restriction by changing how logical replication
connections are established so that GUC settings in the CONNECTION string
are properly passed through to and uesd by the walsender. This enables
per-connection configuration for logical replication.
---
.../libpqwalreceiver/libpqwalreceiver.c | 43 ++++++++++++++-----
1 file changed, 32 insertions(+), 11 deletions(-)
diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
index 239641bfbb6..abc74a9230d 100644
--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
+++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
@@ -180,17 +180,6 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
/* Tell the publisher to translate to our encoding */
keys[++i] = "client_encoding";
vals[i] = GetDatabaseEncodingName();
-
- /*
- * Force assorted GUC parameters to settings that ensure that the
- * publisher will output data values in a form that is unambiguous
- * to the subscriber. (We don't want to modify the subscriber's
- * GUC settings, since that might surprise user-defined code
- * running in the subscriber, such as triggers.) This should
- * match what pg_dump does.
- */
- keys[++i] = "options";
- vals[i] = "-c datestyle=ISO -c intervalstyle=postgres -c extra_float_digits=3";
}
else
{
@@ -256,6 +245,38 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
PQclear(res);
}
+ /*
+ * Force assorted GUC parameters to settings that ensure that the
+ * publisher will output data values in a form that is unambiguous to the
+ * subscriber. (We don't want to modify the subscriber's GUC settings,
+ * since that might surprise user-defined code running in the subscriber,
+ * such as triggers.) This should match what pg_dump does.
+ */
+ if (replication && logical)
+ {
+ const char *params[] =
+ {"datestyle", "intervalstyle", "extra_float_digits", NULL};
+ const char *values[] = {"ISO", "postgres", "3", NULL};
+
+ for (int j = 0; params[j] != NULL; j++)
+ {
+ char sql[100];
+ PGresult *res;
+
+ sprintf(sql, "SET %s = %s", params[j], values[j]);
+ res = libpqsrv_exec(conn->streamConn, sql,
+ WAIT_EVENT_LIBPQWALRECEIVER_RECEIVE);
+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
+ {
+ PQclear(res);
+ *err = psprintf(_("could not set %s: %s"),
+ params[j], pchomp(PQerrorMessage(conn->streamConn)));
+ goto bad_connection;
+ }
+ PQclear(res);
+ }
+ }
+
conn->logical = logical;
return conn;
--
2.51.2
^ permalink raw reply [nested|flat] 37+ messages in thread
* Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect
@ 2025-11-20 06:53 Chao Li <[email protected]>
parent: Fujii Masao <[email protected]>
2 siblings, 1 reply; 37+ messages in thread
From: Chao Li @ 2025-11-20 06:53 UTC (permalink / raw)
To: Fujii Masao <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>
> On Nov 18, 2025, at 23:59, Fujii Masao <[email protected]> wrote:
>
> Hi,
>
> In logical replication, any GUC settings specified in the CONNECTION clause of
> CREATE SUBSCRIPTION are currently ignored. For example:
>
> CREATE SUBSCRIPTION mysub
> CONNECTION 'options=''-c wal_sender_timeout=1000'''
> PUBLICATION ...
>
> The wal_sender_timeout value here has no effect.
>
> This is inconvenient when different logical replication walsenders need
> different settings - e.g., a small wal_sender_timeout for walsender
> connecting to a nearby subscriber and a larger one for walsender
> connecting to a distant subscriber. Right now, it's not easy for users
> to control such per-connection behavior.
>
> The reason of thid limitation is that libpqrcv_connect() always overwrites
> the options connection parameter as follows:
>
> keys[++i] = "options";
> vals[i] = "-c datestyle=ISO -c intervalstyle=postgres -c
> extra_float_digits=3";
>
> This wipes out any user-specified GUCs in the CONNECTION string.
> Physical replication does not have this problem because it does not overwrite
> options, so GUCs in primary_conninfo are honored.
>
> To remove this restriction, how about switching to issuing SET commands for
> datestyle, intervalstyle, and extra_float_digits after the connection
> is established,
> similar to what postgres_fdw does, instead of forcing them into options?
> That would allow user-specified GUC settings in CREATE SUBSCRIPTION to
> take effect.
>
> This overwrite behavior was introduced in commit f3d4019da5d and chosen mainly
> to avoid extra network round trips according to the discussion [1].
> While SET commands would add a round trip, it only happens at
> connection startup,
> which is infrequent - so the overhead seems negligible.
>
> Thoughts?
Before this patch, all user specified options are silently discarded, now all user specified options expect the 3 will be kept, will that expose a hold where user badly specifies some option that may break logical replication? If that’s true, then we need to parse user specified options and do some verifications.
I just reviewed v2, and got some comments:
1.
```
+ char sql[100];
```
Hardcode 100 here doesn’t look good. If you decide to keep, I won’t have a strong objection.
2
```
+ const char *params[] =
+ {"datestyle", "intervalstyle", "extra_float_digits", NULL};
+ const char *values[] = {"ISO", "postgres", "3", NULL};
```
Nit: we don’t need to have a NULL terminator element. We can use lengthof() macro to get array length. lengthof() is defined in c.h.
3. To minimize the network round-trip, maybe we can combine the 3 set into a single statement?
4. The commit message:
```
This commit removes the restriction by changing how logical replication
connections are established so that GUC settings in the CONNECTION string
are properly passed through to and uesd by the walsender. This enables
```
This is a little bit inaccurate, all user specified settings expected the 3 ones being overwritten will be honored.
Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/
^ permalink raw reply [nested|flat] 37+ messages in thread
* Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect
@ 2025-11-21 07:47 Fujii Masao <[email protected]>
parent: Chao Li <[email protected]>
0 siblings, 2 replies; 37+ messages in thread
From: Fujii Masao @ 2025-11-21 07:47 UTC (permalink / raw)
To: Chao Li <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>
On Thu, Nov 20, 2025 at 3:54 PM Chao Li <[email protected]> wrote:
> Before this patch, all user specified options are silently discarded,
The GUC settings in CREATE SUBSCRIPTION were honored up through v14;
the behavior changed in commit f3d4019da5d, so some might view this
as a regression.
> now all user specified options expect the 3 will be kept, will that expose a hold where user badly specifies some option that may break logical replication? If that’s true, then we need to parse user specified options and do some verifications.
>
Yeah, I agree that if certain GUCs can break logical replication,
we should enforce "safe" values, just as we currently do for datestyle.
And if any other GUCs can cause the issue, they could affect
postgres_fdw etc, so the fix would need to be broader.
> I just reviewed v2, and got some comments:
Thanks for the review!
>
> 1.
> ```
> + char sql[100];
> ```
>
> Hardcode 100 here doesn’t look good. If you decide to keep, I won’t have a strong objection.
I think hardcoding 100 here is sufficient, since the queries built on
that buffer are fixed and clearly fit within that limit.
>
> 2
> ```
> + const char *params[] =
> + {"datestyle", "intervalstyle", "extra_float_digits", NULL};
> + const char *values[] = {"ISO", "postgres", "3", NULL};
> ```
>
> Nit: we don’t need to have a NULL terminator element. We can use lengthof() macro to get array length. lengthof() is defined in c.h.
Okay, I'll adjust the patch accordingly.
>
> 3. To minimize the network round-trip, maybe we can combine the 3 set into a single statement?
As for the extra network round trip, I still doubt it will matter
in practice given that it happens only at replication connection startup.
>
> 4. The commit message:
> ```
> This commit removes the restriction by changing how logical replication
> connections are established so that GUC settings in the CONNECTION string
> are properly passed through to and uesd by the walsender. This enables
> ```
>
> This is a little bit inaccurate, all user specified settings expected the 3 ones being overwritten will be honored.
Are you suggesting that, because datestyle and the other two parameters
specified in CONNECTION aren(t actually applied by the walsender,
the commit message should explicitly mention that not all parameters
from CONNECTION are used?
Regards,
--
Fujii Masao
^ permalink raw reply [nested|flat] 37+ messages in thread
* Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect
@ 2025-11-21 09:23 Chao Li <[email protected]>
parent: Fujii Masao <[email protected]>
1 sibling, 1 reply; 37+ messages in thread
From: Chao Li @ 2025-11-21 09:23 UTC (permalink / raw)
To: Fujii Masao <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>
> On Nov 21, 2025, at 15:47, Fujii Masao <[email protected]> wrote:
>
>>
>> 4. The commit message:
>> ```
>> This commit removes the restriction by changing how logical replication
>> connections are established so that GUC settings in the CONNECTION string
>> are properly passed through to and uesd by the walsender. This enables
>> ```
>>
>> This is a little bit inaccurate, all user specified settings expected the 3 ones being overwritten will be honored.
>
> Are you suggesting that, because datestyle and the other two parameters
> specified in CONNECTION aren(t actually applied by the walsender,
> the commit message should explicitly mention that not all parameters
> from CONNECTION are used?
No, what I was thinking is that, we could combine the three set statement into one, like:
```
Set a = 1; set b = 2; set c = 3;
```
So that sends a single statement to publisher server, that reduces round-trip from 3 times to one time.
Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/
^ permalink raw reply [nested|flat] 37+ messages in thread
* Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect
@ 2025-11-21 16:14 Fujii Masao <[email protected]>
parent: Chao Li <[email protected]>
0 siblings, 1 reply; 37+ messages in thread
From: Fujii Masao @ 2025-11-21 16:14 UTC (permalink / raw)
To: Chao Li <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>
On Fri, Nov 21, 2025 at 6:24 PM Chao Li <[email protected]> wrote:
> No, what I was thinking is that, we could combine the three set statement into one, like:
>
> ```
> Set a = 1; set b = 2; set c = 3;
> ```
> So that sends a single statement to publisher server, that reduces round-trip from 3 times to one time.
I see the point about combining the three SET commands to reduce round trips,
but I think the current approach in the patch (i.e., issuing a separate
SET command for each parameter) is sufficient. I still don't think
the additional round trip during replication connection startup is
a real concern. This approach is also consistent with what postgres_fdw
and pg_dump already do.
Regards,
--
Fujii Masao
^ permalink raw reply [nested|flat] 37+ messages in thread
* Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect
@ 2025-11-22 01:31 Chao Li <[email protected]>
parent: Fujii Masao <[email protected]>
0 siblings, 1 reply; 37+ messages in thread
From: Chao Li @ 2025-11-22 01:31 UTC (permalink / raw)
To: Fujii Masao <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>
> On Nov 22, 2025, at 00:14, Fujii Masao <[email protected]> wrote:
>
> On Fri, Nov 21, 2025 at 6:24 PM Chao Li <[email protected]> wrote:
>> No, what I was thinking is that, we could combine the three set statement into one, like:
>>
>> ```
>> Set a = 1; set b = 2; set c = 3;
>> ```
>> So that sends a single statement to publisher server, that reduces round-trip from 3 times to one time.
>
> I see the point about combining the three SET commands to reduce round trips,
> but I think the current approach in the patch (i.e., issuing a separate
> SET command for each parameter) is sufficient. I still don't think
> the additional round trip during replication connection startup is
> a real concern. This approach is also consistent with what postgres_fdw
> and pg_dump already do.
>
No problem. I don’t have a strong option here. I just saw you mentioned overhead of round trip and thought to improve. But I agree that overhead is tiny, not a real concern.
Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/
^ permalink raw reply [nested|flat] 37+ messages in thread
* Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect
@ 2025-11-22 14:14 Fujii Masao <[email protected]>
parent: Chao Li <[email protected]>
0 siblings, 2 replies; 37+ messages in thread
From: Fujii Masao @ 2025-11-22 14:14 UTC (permalink / raw)
To: Chao Li <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>
On Sat, Nov 22, 2025 at 10:31 AM Chao Li <[email protected]> wrote:
>
>
>
> > On Nov 22, 2025, at 00:14, Fujii Masao <[email protected]> wrote:
> >
> > On Fri, Nov 21, 2025 at 6:24 PM Chao Li <[email protected]> wrote:
> >> No, what I was thinking is that, we could combine the three set statement into one, like:
> >>
> >> ```
> >> Set a = 1; set b = 2; set c = 3;
> >> ```
> >> So that sends a single statement to publisher server, that reduces round-trip from 3 times to one time.
> >
> > I see the point about combining the three SET commands to reduce round trips,
> > but I think the current approach in the patch (i.e., issuing a separate
> > SET command for each parameter) is sufficient. I still don't think
> > the additional round trip during replication connection startup is
> > a real concern. This approach is also consistent with what postgres_fdw
> > and pg_dump already do.
> >
>
> No problem. I don’t have a strong option here. I just saw you mentioned overhead of round trip and thought to improve. But I agree that overhead is tiny, not a real concern.
Okay, thanks!
I've updated the patch to use lengthof() as you suggested.
The revised version is attached.
Regards,
--
Fujii Masao
Attachments:
[application/octet-stream] v3-0001-Honor-GUC-settings-specified-in-CREATE-SUBSCRIPTI.patch (3.6K, ../../CAHGQGwEeJ6ijS=d5byU0Pq1J9YYGw+X=fyomd_d71sx5NOHdsA@mail.gmail.com/2-v3-0001-Honor-GUC-settings-specified-in-CREATE-SUBSCRIPTI.patch)
download | inline diff:
From 4c5407fd093f1cf77234f4af604f2355d907a61e Mon Sep 17 00:00:00 2001
From: Fujii Masao <[email protected]>
Date: Sat, 22 Nov 2025 22:35:22 +0900
Subject: [PATCH v3] Honor GUC settings specified in CREATE SUBSCRIPTION
CONNECTION.
Previously, GUC settings supplied in the CONNECTION clause of
CREATE SUBSCRIPTION were not used by the publisher's walsender.
For example, in:
CREATE SUBSCRIPTION mysub
CONNECTION 'options=''-c wal_sender_timeout=1000'''
PUBLICATION ...
the wal_sender_timeout setting had no effect.
This contrasted with physical replication, where GUCs in primary_conninfo
are applied to the walsender.
This limitation made it difficult to tune logical replication connections
individually, for example, using a shorter timeout for walsender connecting
to a nearby subscriber and a longer one for walsender connecting
to a remote subscriber.
This commit removes the restriction by changing how logical replication
connections are established so that GUC settings in the CONNECTION string
are properly passed through to and uesd by the walsender. This enables
per-connection configuration for logical replication.
Author: Fujii Masao <[email protected]>
Reviewed-by: Chao Li <[email protected]>
Discussion: https://postgr.es/m/CAHGQGwGYV+-abbKwdrM2UHUe-JYOFWmsrs6=QicyJO-j+-Widw@mail.gmail.com
---
.../libpqwalreceiver/libpqwalreceiver.c | 43 ++++++++++++++-----
1 file changed, 32 insertions(+), 11 deletions(-)
diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
index 239641bfbb6..500632b462f 100644
--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
+++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
@@ -180,17 +180,6 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
/* Tell the publisher to translate to our encoding */
keys[++i] = "client_encoding";
vals[i] = GetDatabaseEncodingName();
-
- /*
- * Force assorted GUC parameters to settings that ensure that the
- * publisher will output data values in a form that is unambiguous
- * to the subscriber. (We don't want to modify the subscriber's
- * GUC settings, since that might surprise user-defined code
- * running in the subscriber, such as triggers.) This should
- * match what pg_dump does.
- */
- keys[++i] = "options";
- vals[i] = "-c datestyle=ISO -c intervalstyle=postgres -c extra_float_digits=3";
}
else
{
@@ -256,6 +245,38 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
PQclear(res);
}
+ /*
+ * Force assorted GUC parameters to settings that ensure that the
+ * publisher will output data values in a form that is unambiguous to the
+ * subscriber. (We don't want to modify the subscriber's GUC settings,
+ * since that might surprise user-defined code running in the subscriber,
+ * such as triggers.) This should match what pg_dump does.
+ */
+ if (replication && logical)
+ {
+ const char *params[] =
+ {"datestyle", "intervalstyle", "extra_float_digits"};
+ const char *values[] = {"ISO", "postgres", "3"};
+
+ for (int j = 0; j < lengthof(params); j++)
+ {
+ char sql[100];
+ PGresult *res;
+
+ sprintf(sql, "SET %s = %s", params[j], values[j]);
+ res = libpqsrv_exec(conn->streamConn, sql,
+ WAIT_EVENT_LIBPQWALRECEIVER_RECEIVE);
+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
+ {
+ PQclear(res);
+ *err = psprintf(_("could not set %s: %s"),
+ params[j], pchomp(PQerrorMessage(conn->streamConn)));
+ goto bad_connection;
+ }
+ PQclear(res);
+ }
+ }
+
conn->logical = logical;
return conn;
--
2.51.2
^ permalink raw reply [nested|flat] 37+ messages in thread
* Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect
@ 2025-11-24 03:51 Chao Li <[email protected]>
parent: Fujii Masao <[email protected]>
1 sibling, 1 reply; 37+ messages in thread
From: Chao Li @ 2025-11-24 03:51 UTC (permalink / raw)
To: Fujii Masao <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>
> On Nov 22, 2025, at 22:14, Fujii Masao <[email protected]> wrote:
>
> On Sat, Nov 22, 2025 at 10:31 AM Chao Li <[email protected]> wrote:
>>
>>
>>
>>> On Nov 22, 2025, at 00:14, Fujii Masao <[email protected]> wrote:
>>>
>>> On Fri, Nov 21, 2025 at 6:24 PM Chao Li <[email protected]> wrote:
>>>> No, what I was thinking is that, we could combine the three set statement into one, like:
>>>>
>>>> ```
>>>> Set a = 1; set b = 2; set c = 3;
>>>> ```
>>>> So that sends a single statement to publisher server, that reduces round-trip from 3 times to one time.
>>>
>>> I see the point about combining the three SET commands to reduce round trips,
>>> but I think the current approach in the patch (i.e., issuing a separate
>>> SET command for each parameter) is sufficient. I still don't think
>>> the additional round trip during replication connection startup is
>>> a real concern. This approach is also consistent with what postgres_fdw
>>> and pg_dump already do.
>>>
>>
>> No problem. I don’t have a strong option here. I just saw you mentioned overhead of round trip and thought to improve. But I agree that overhead is tiny, not a real concern.
>
> Okay, thanks!
>
> I've updated the patch to use lengthof() as you suggested.
> The revised version is attached.
>
> Regards,
>
> --
> Fujii Masao
> <v3-0001-Honor-GUC-settings-specified-in-CREATE-SUBSCRIPTI.patch>
V3 looks good to me.
>> now all user specified options expect the 3 will be kept, will that expose a hold where user badly specifies some option that may break logical replication? If that’s true, then we need to parse user specified options and do some verifications.
>>
>
> Yeah, I agree that if certain GUCs can break logical replication,
> we should enforce "safe" values, just as we currently do for datestyle.
> And if any other GUCs can cause the issue, they could affect
> postgres_fdw etc, so the fix would need to be broader.
Just want to clarify if you mean you will handle this in a future patch?
Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/
^ permalink raw reply [nested|flat] 37+ messages in thread
* Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect
@ 2025-11-24 05:54 Jelte Fennema-Nio <[email protected]>
parent: Fujii Masao <[email protected]>
1 sibling, 1 reply; 37+ messages in thread
From: Jelte Fennema-Nio @ 2025-11-24 05:54 UTC (permalink / raw)
To: Fujii Masao <[email protected]>; +Cc: Chao Li <[email protected]>; PostgreSQL Hackers <[email protected]>
On Fri, Nov 21, 2025, 00:47 Fujii Masao <[email protected]> wrote:
> On Thu, Nov 20, 2025 at 3:54 PM Chao Li <[email protected]> wrote:
> > Before this patch, all user specified options are silently discarded,
>
> The GUC settings in CREATE SUBSCRIPTION were honored up through v14;
> the behavior changed in commit f3d4019da5d, so some might view this
> as a regression.
>
FWIW, I definitely view it as a regression. I used this in citus to make
the logical replication sender of the shard rebalancer use a higher CPU
priority[1]. I had no clue, until now, that that logic got completely
broken in PG15 (which we coincidentally added support for in the same
release).
I'm not entirely sure if it's worth a backpatch. This citus feature
probably isn't the most critical. So if that's the only usecase in the wild
that got broken, then that might be fine. But I at least wanted to share
that others (i.e. me) have used this feature.
[1]:
https://github.com/citusdata/citus/blame/662b7248db2146d33a1a21227271b839355a970a/src/backend/distri...
>
^ permalink raw reply [nested|flat] 37+ messages in thread
* Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect
@ 2025-11-25 11:30 Fujii Masao <[email protected]>
parent: Chao Li <[email protected]>
0 siblings, 0 replies; 37+ messages in thread
From: Fujii Masao @ 2025-11-25 11:30 UTC (permalink / raw)
To: Chao Li <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>
On Mon, Nov 24, 2025 at 12:52 PM Chao Li <[email protected]> wrote:
> V3 looks good to me.
Thanks for reviewing the patch!
> > Yeah, I agree that if certain GUCs can break logical replication,
> > we should enforce "safe" values, just as we currently do for datestyle.
> > And if any other GUCs can cause the issue, they could affect
> > postgres_fdw etc, so the fix would need to be broader.
>
> Just want to clarify if you mean you will handle this in a future patch?
I don't currently know of any other parameters that must be forced for
logical replication or postgres_fdw. But if we identify any, I'm happy to
review a patch that adds the necessary handling.
Regards,
--
Fujii Masao
^ permalink raw reply [nested|flat] 37+ messages in thread
* Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect
@ 2025-11-25 11:32 Fujii Masao <[email protected]>
parent: Jelte Fennema-Nio <[email protected]>
0 siblings, 1 reply; 37+ messages in thread
From: Fujii Masao @ 2025-11-25 11:32 UTC (permalink / raw)
To: Jelte Fennema-Nio <[email protected]>; +Cc: Chao Li <[email protected]>; PostgreSQL Hackers <[email protected]>
On Mon, Nov 24, 2025 at 2:55 PM Jelte Fennema-Nio <[email protected]> wrote:
>
> On Fri, Nov 21, 2025, 00:47 Fujii Masao <[email protected]> wrote:
>>
>> On Thu, Nov 20, 2025 at 3:54 PM Chao Li <[email protected]> wrote:
>> > Before this patch, all user specified options are silently discarded,
>>
>> The GUC settings in CREATE SUBSCRIPTION were honored up through v14;
>> the behavior changed in commit f3d4019da5d, so some might view this
>> as a regression.
>
>
> FWIW, I definitely view it as a regression. I used this in citus to make the logical replication sender of the shard rebalancer use a higher CPU priority[1]. I had no clue, until now, that that logic got completely broken in PG15 (which we coincidentally added support for in the same release).
Thanks for sharing this!
> I'm not entirely sure if it's worth a backpatch. This citus feature probably isn't the most critical. So if that's the only usecase in the wild that got broken, then that might be fine. But I at least wanted to share that others (i.e. me) have used this feature.
I found the following description in logical replication docs, which makes me
start thinking that the patch would need to be backpatched.
-----------------
If the role does not trust all table owners, include options=-crow_security=off
in the connection string
https://www.postgresql.org/docs/devel/logical-replication-security.html
-----------------
Regards,
--
Fujii Masao
^ permalink raw reply [nested|flat] 37+ messages in thread
* Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect
@ 2025-11-26 16:33 Fujii Masao <[email protected]>
parent: Fujii Masao <[email protected]>
0 siblings, 0 replies; 37+ messages in thread
From: Fujii Masao @ 2025-11-26 16:33 UTC (permalink / raw)
To: Jelte Fennema-Nio <[email protected]>; +Cc: Chao Li <[email protected]>; PostgreSQL Hackers <[email protected]>
On Tue, Nov 25, 2025 at 8:32 PM Fujii Masao <[email protected]> wrote:
> I found the following description in logical replication docs, which makes me
> start thinking that the patch would need to be backpatched.
I've prepared patches for the older branches as well and attached them.
Regards,
--
Fujii Masao
From 159e0c886546f3b12ebd48b57d12c68493d5309e Mon Sep 17 00:00:00 2001
From: Fujii Masao <[email protected]>
Date: Wed, 26 Nov 2025 23:35:44 +0900
Subject: [PATCH v4] Honor GUC settings specified in CREATE SUBSCRIPTION
CONNECTION.
Prior to v15, GUC settings supplied in the CONNECTION clause of
CREATE SUBSCRIPTION were correctly passed through to
the publisher's walsender. For example:
CREATE SUBSCRIPTION mysub
CONNECTION 'options=''-c wal_sender_timeout=1000'''
PUBLICATION ...
would cause wal_sender_timeout to take effect on the publisher's walsender.
However, commit f3d4019da5d changed the way logical replication
connections are established, forcing the publisher's relevant
GUC settings (datestyle, intervalstyle, extra_float_digits) to
override those provided in the CONNECTION string. As a result,
from v15 through v18, GUC settings in the CONNECTION string were
always ignored.
This regression prevented per-connection tuning of logical replication.
For example, using a shorter timeout for walsender connecting
to a nearby subscriber and a longer one for walsender connecting
to a remote subscriber.
This commit restores the intended behavior by ensuring that
GUC settings in the CONNECTION string are again passed through
and applied by the walsender, allowing per-connection configuration.
Backpatch to v15, where the regression was introduced.
Author: Fujii Masao <[email protected]>
Reviewed-by: Chao Li <[email protected]>
Discussion: https://postgr.es/m/CAHGQGwGYV+-abbKwdrM2UHUe-JYOFWmsrs6=QicyJO-j+-Widw@mail.gmail.com
Backpatch-through: 15
---
.../libpqwalreceiver/libpqwalreceiver.c | 43 ++++++++++++++-----
1 file changed, 32 insertions(+), 11 deletions(-)
diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
index 568024ec974..1270d162c88 100644
--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
+++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
@@ -170,17 +170,6 @@ libpqrcv_connect(const char *conninfo, bool logical, bool must_use_password,
/* Tell the publisher to translate to our encoding */
keys[++i] = "client_encoding";
vals[i] = GetDatabaseEncodingName();
-
- /*
- * Force assorted GUC parameters to settings that ensure that the
- * publisher will output data values in a form that is unambiguous to
- * the subscriber. (We don't want to modify the subscriber's GUC
- * settings, since that might surprise user-defined code running in
- * the subscriber, such as triggers.) This should match what pg_dump
- * does.
- */
- keys[++i] = "options";
- vals[i] = "-c datestyle=ISO -c intervalstyle=postgres -c extra_float_digits=3";
}
keys[++i] = NULL;
vals[i] = NULL;
@@ -263,6 +252,37 @@ libpqrcv_connect(const char *conninfo, bool logical, bool must_use_password,
PQclear(res);
}
+ /*
+ * Force assorted GUC parameters to settings that ensure that the
+ * publisher will output data values in a form that is unambiguous to the
+ * subscriber. (We don't want to modify the subscriber's GUC settings,
+ * since that might surprise user-defined code running in the subscriber,
+ * such as triggers.) This should match what pg_dump does.
+ */
+ if (logical)
+ {
+ const char *params[] =
+ {"datestyle", "intervalstyle", "extra_float_digits"};
+ const char *values[] = {"ISO", "postgres", "3"};
+
+ for (int j = 0; j < lengthof(params); j++)
+ {
+ char sql[100];
+ PGresult *res;
+
+ sprintf(sql, "SET %s = %s", params[j], values[j]);
+ res = libpqrcv_PQexec(conn->streamConn, sql);
+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
+ {
+ PQclear(res);
+ *err = psprintf(_("could not set %s: %s"),
+ params[j], pchomp(PQerrorMessage(conn->streamConn)));
+ goto bad_connection;
+ }
+ PQclear(res);
+ }
+ }
+
conn->logical = logical;
return conn;
@@ -434,6 +454,7 @@ libpqrcv_identify_system(WalReceiverConn *conn, TimeLineID *primary_tli)
"the primary server: %s",
pchomp(PQerrorMessage(conn->streamConn)))));
}
+
/*
* IDENTIFY_SYSTEM returns 3 columns in 9.3 and earlier, and 4 columns in
* 9.4 and onwards.
--
2.51.2
From 1a1c412e2d320d82d7a6927e5e6550c554a77b23 Mon Sep 17 00:00:00 2001
From: Fujii Masao <[email protected]>
Date: Wed, 26 Nov 2025 23:35:44 +0900
Subject: [PATCH v4] Honor GUC settings specified in CREATE SUBSCRIPTION
CONNECTION.
Prior to v15, GUC settings supplied in the CONNECTION clause of
CREATE SUBSCRIPTION were correctly passed through to
the publisher's walsender. For example:
CREATE SUBSCRIPTION mysub
CONNECTION 'options=''-c wal_sender_timeout=1000'''
PUBLICATION ...
would cause wal_sender_timeout to take effect on the publisher's walsender.
However, commit f3d4019da5d changed the way logical replication
connections are established, forcing the publisher's relevant
GUC settings (datestyle, intervalstyle, extra_float_digits) to
override those provided in the CONNECTION string. As a result,
from v15 through v18, GUC settings in the CONNECTION string were
always ignored.
This regression prevented per-connection tuning of logical replication.
For example, using a shorter timeout for walsender connecting
to a nearby subscriber and a longer one for walsender connecting
to a remote subscriber.
This commit restores the intended behavior by ensuring that
GUC settings in the CONNECTION string are again passed through
and applied by the walsender, allowing per-connection configuration.
Backpatch to v15, where the regression was introduced.
Author: Fujii Masao <[email protected]>
Reviewed-by: Chao Li <[email protected]>
Discussion: https://postgr.es/m/CAHGQGwGYV+-abbKwdrM2UHUe-JYOFWmsrs6=QicyJO-j+-Widw@mail.gmail.com
Backpatch-through: 15
---
.../libpqwalreceiver/libpqwalreceiver.c | 42 ++++++++++++++-----
1 file changed, 31 insertions(+), 11 deletions(-)
diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
index 02f12f29219..02f3ee15c87 100644
--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
+++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
@@ -178,17 +178,6 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
/* Tell the publisher to translate to our encoding */
keys[++i] = "client_encoding";
vals[i] = GetDatabaseEncodingName();
-
- /*
- * Force assorted GUC parameters to settings that ensure that the
- * publisher will output data values in a form that is unambiguous
- * to the subscriber. (We don't want to modify the subscriber's
- * GUC settings, since that might surprise user-defined code
- * running in the subscriber, such as triggers.) This should
- * match what pg_dump does.
- */
- keys[++i] = "options";
- vals[i] = "-c datestyle=ISO -c intervalstyle=postgres -c extra_float_digits=3";
}
else
{
@@ -289,6 +278,37 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
PQclear(res);
}
+ /*
+ * Force assorted GUC parameters to settings that ensure that the
+ * publisher will output data values in a form that is unambiguous to the
+ * subscriber. (We don't want to modify the subscriber's GUC settings,
+ * since that might surprise user-defined code running in the subscriber,
+ * such as triggers.) This should match what pg_dump does.
+ */
+ if (replication && logical)
+ {
+ const char *params[] =
+ {"datestyle", "intervalstyle", "extra_float_digits"};
+ const char *values[] = {"ISO", "postgres", "3"};
+
+ for (int j = 0; j < lengthof(params); j++)
+ {
+ char sql[100];
+ PGresult *res;
+
+ sprintf(sql, "SET %s = %s", params[j], values[j]);
+ res = libpqrcv_PQexec(conn->streamConn, sql);
+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
+ {
+ PQclear(res);
+ *err = psprintf(_("could not set %s: %s"),
+ params[j], pchomp(PQerrorMessage(conn->streamConn)));
+ goto bad_connection;
+ }
+ PQclear(res);
+ }
+ }
+
conn->logical = logical;
return conn;
--
2.51.2
Attachments:
[text/plain] v4-0001-PG15-PG16-Honor-GUC-settings-specified-in-CREATE-SUBSCRIPTI.txt (4.1K, ../../CAHGQGwEOhhT0y1-sbtPMutRsxNHUSX7muB76VcrW04JcKCyOdg@mail.gmail.com/2-v4-0001-PG15-PG16-Honor-GUC-settings-specified-in-CREATE-SUBSCRIPTI.txt)
download | inline diff:
From 159e0c886546f3b12ebd48b57d12c68493d5309e Mon Sep 17 00:00:00 2001
From: Fujii Masao <[email protected]>
Date: Wed, 26 Nov 2025 23:35:44 +0900
Subject: [PATCH v4] Honor GUC settings specified in CREATE SUBSCRIPTION
CONNECTION.
Prior to v15, GUC settings supplied in the CONNECTION clause of
CREATE SUBSCRIPTION were correctly passed through to
the publisher's walsender. For example:
CREATE SUBSCRIPTION mysub
CONNECTION 'options=''-c wal_sender_timeout=1000'''
PUBLICATION ...
would cause wal_sender_timeout to take effect on the publisher's walsender.
However, commit f3d4019da5d changed the way logical replication
connections are established, forcing the publisher's relevant
GUC settings (datestyle, intervalstyle, extra_float_digits) to
override those provided in the CONNECTION string. As a result,
from v15 through v18, GUC settings in the CONNECTION string were
always ignored.
This regression prevented per-connection tuning of logical replication.
For example, using a shorter timeout for walsender connecting
to a nearby subscriber and a longer one for walsender connecting
to a remote subscriber.
This commit restores the intended behavior by ensuring that
GUC settings in the CONNECTION string are again passed through
and applied by the walsender, allowing per-connection configuration.
Backpatch to v15, where the regression was introduced.
Author: Fujii Masao <[email protected]>
Reviewed-by: Chao Li <[email protected]>
Discussion: https://postgr.es/m/CAHGQGwGYV+-abbKwdrM2UHUe-JYOFWmsrs6=QicyJO-j+-Widw@mail.gmail.com
Backpatch-through: 15
---
.../libpqwalreceiver/libpqwalreceiver.c | 43 ++++++++++++++-----
1 file changed, 32 insertions(+), 11 deletions(-)
diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
index 568024ec974..1270d162c88 100644
--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
+++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
@@ -170,17 +170,6 @@ libpqrcv_connect(const char *conninfo, bool logical, bool must_use_password,
/* Tell the publisher to translate to our encoding */
keys[++i] = "client_encoding";
vals[i] = GetDatabaseEncodingName();
-
- /*
- * Force assorted GUC parameters to settings that ensure that the
- * publisher will output data values in a form that is unambiguous to
- * the subscriber. (We don't want to modify the subscriber's GUC
- * settings, since that might surprise user-defined code running in
- * the subscriber, such as triggers.) This should match what pg_dump
- * does.
- */
- keys[++i] = "options";
- vals[i] = "-c datestyle=ISO -c intervalstyle=postgres -c extra_float_digits=3";
}
keys[++i] = NULL;
vals[i] = NULL;
@@ -263,6 +252,37 @@ libpqrcv_connect(const char *conninfo, bool logical, bool must_use_password,
PQclear(res);
}
+ /*
+ * Force assorted GUC parameters to settings that ensure that the
+ * publisher will output data values in a form that is unambiguous to the
+ * subscriber. (We don't want to modify the subscriber's GUC settings,
+ * since that might surprise user-defined code running in the subscriber,
+ * such as triggers.) This should match what pg_dump does.
+ */
+ if (logical)
+ {
+ const char *params[] =
+ {"datestyle", "intervalstyle", "extra_float_digits"};
+ const char *values[] = {"ISO", "postgres", "3"};
+
+ for (int j = 0; j < lengthof(params); j++)
+ {
+ char sql[100];
+ PGresult *res;
+
+ sprintf(sql, "SET %s = %s", params[j], values[j]);
+ res = libpqrcv_PQexec(conn->streamConn, sql);
+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
+ {
+ PQclear(res);
+ *err = psprintf(_("could not set %s: %s"),
+ params[j], pchomp(PQerrorMessage(conn->streamConn)));
+ goto bad_connection;
+ }
+ PQclear(res);
+ }
+ }
+
conn->logical = logical;
return conn;
@@ -434,6 +454,7 @@ libpqrcv_identify_system(WalReceiverConn *conn, TimeLineID *primary_tli)
"the primary server: %s",
pchomp(PQerrorMessage(conn->streamConn)))));
}
+
/*
* IDENTIFY_SYSTEM returns 3 columns in 9.3 and earlier, and 4 columns in
* 9.4 and onwards.
--
2.51.2
[application/octet-stream] v4-0001-Honor-GUC-settings-specified-in-CREATE-SUBSCRIPTI.patch (3.9K, ../../CAHGQGwEOhhT0y1-sbtPMutRsxNHUSX7muB76VcrW04JcKCyOdg@mail.gmail.com/3-v4-0001-Honor-GUC-settings-specified-in-CREATE-SUBSCRIPTI.patch)
download | inline diff:
From 947cf9d587333219791a257389b95eae01d76237 Mon Sep 17 00:00:00 2001
From: Fujii Masao <[email protected]>
Date: Wed, 26 Nov 2025 23:35:44 +0900
Subject: [PATCH v4] Honor GUC settings specified in CREATE SUBSCRIPTION
CONNECTION.
Prior to v15, GUC settings supplied in the CONNECTION clause of
CREATE SUBSCRIPTION were correctly passed through to
the publisher's walsender. For example:
CREATE SUBSCRIPTION mysub
CONNECTION 'options=''-c wal_sender_timeout=1000'''
PUBLICATION ...
would cause wal_sender_timeout to take effect on the publisher's walsender.
However, commit f3d4019da5d changed the way logical replication
connections are established, forcing the publisher's relevant
GUC settings (datestyle, intervalstyle, extra_float_digits) to
override those provided in the CONNECTION string. As a result,
from v15 through v18, GUC settings in the CONNECTION string were
always ignored.
This regression prevented per-connection tuning of logical replication.
For example, using a shorter timeout for walsender connecting
to a nearby subscriber and a longer one for walsender connecting
to a remote subscriber.
This commit restores the intended behavior by ensuring that
GUC settings in the CONNECTION string are again passed through
and applied by the walsender, allowing per-connection configuration.
Backpatch to v15, where the regression was introduced.
Author: Fujii Masao <[email protected]>
Reviewed-by: Chao Li <[email protected]>
Discussion: https://postgr.es/m/CAHGQGwGYV+-abbKwdrM2UHUe-JYOFWmsrs6=QicyJO-j+-Widw@mail.gmail.com
Backpatch-through: 15
---
.../libpqwalreceiver/libpqwalreceiver.c | 43 ++++++++++++++-----
1 file changed, 32 insertions(+), 11 deletions(-)
diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
index 239641bfbb6..500632b462f 100644
--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
+++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
@@ -180,17 +180,6 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
/* Tell the publisher to translate to our encoding */
keys[++i] = "client_encoding";
vals[i] = GetDatabaseEncodingName();
-
- /*
- * Force assorted GUC parameters to settings that ensure that the
- * publisher will output data values in a form that is unambiguous
- * to the subscriber. (We don't want to modify the subscriber's
- * GUC settings, since that might surprise user-defined code
- * running in the subscriber, such as triggers.) This should
- * match what pg_dump does.
- */
- keys[++i] = "options";
- vals[i] = "-c datestyle=ISO -c intervalstyle=postgres -c extra_float_digits=3";
}
else
{
@@ -256,6 +245,38 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
PQclear(res);
}
+ /*
+ * Force assorted GUC parameters to settings that ensure that the
+ * publisher will output data values in a form that is unambiguous to the
+ * subscriber. (We don't want to modify the subscriber's GUC settings,
+ * since that might surprise user-defined code running in the subscriber,
+ * such as triggers.) This should match what pg_dump does.
+ */
+ if (replication && logical)
+ {
+ const char *params[] =
+ {"datestyle", "intervalstyle", "extra_float_digits"};
+ const char *values[] = {"ISO", "postgres", "3"};
+
+ for (int j = 0; j < lengthof(params); j++)
+ {
+ char sql[100];
+ PGresult *res;
+
+ sprintf(sql, "SET %s = %s", params[j], values[j]);
+ res = libpqsrv_exec(conn->streamConn, sql,
+ WAIT_EVENT_LIBPQWALRECEIVER_RECEIVE);
+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
+ {
+ PQclear(res);
+ *err = psprintf(_("could not set %s: %s"),
+ params[j], pchomp(PQerrorMessage(conn->streamConn)));
+ goto bad_connection;
+ }
+ PQclear(res);
+ }
+ }
+
conn->logical = logical;
return conn;
--
2.51.2
[text/plain] v4-0001-PG17-Honor-GUC-settings-specified-in-CREATE-SUBSCRIPTI.txt (3.8K, ../../CAHGQGwEOhhT0y1-sbtPMutRsxNHUSX7muB76VcrW04JcKCyOdg@mail.gmail.com/4-v4-0001-PG17-Honor-GUC-settings-specified-in-CREATE-SUBSCRIPTI.txt)
download | inline diff:
From 1a1c412e2d320d82d7a6927e5e6550c554a77b23 Mon Sep 17 00:00:00 2001
From: Fujii Masao <[email protected]>
Date: Wed, 26 Nov 2025 23:35:44 +0900
Subject: [PATCH v4] Honor GUC settings specified in CREATE SUBSCRIPTION
CONNECTION.
Prior to v15, GUC settings supplied in the CONNECTION clause of
CREATE SUBSCRIPTION were correctly passed through to
the publisher's walsender. For example:
CREATE SUBSCRIPTION mysub
CONNECTION 'options=''-c wal_sender_timeout=1000'''
PUBLICATION ...
would cause wal_sender_timeout to take effect on the publisher's walsender.
However, commit f3d4019da5d changed the way logical replication
connections are established, forcing the publisher's relevant
GUC settings (datestyle, intervalstyle, extra_float_digits) to
override those provided in the CONNECTION string. As a result,
from v15 through v18, GUC settings in the CONNECTION string were
always ignored.
This regression prevented per-connection tuning of logical replication.
For example, using a shorter timeout for walsender connecting
to a nearby subscriber and a longer one for walsender connecting
to a remote subscriber.
This commit restores the intended behavior by ensuring that
GUC settings in the CONNECTION string are again passed through
and applied by the walsender, allowing per-connection configuration.
Backpatch to v15, where the regression was introduced.
Author: Fujii Masao <[email protected]>
Reviewed-by: Chao Li <[email protected]>
Discussion: https://postgr.es/m/CAHGQGwGYV+-abbKwdrM2UHUe-JYOFWmsrs6=QicyJO-j+-Widw@mail.gmail.com
Backpatch-through: 15
---
.../libpqwalreceiver/libpqwalreceiver.c | 42 ++++++++++++++-----
1 file changed, 31 insertions(+), 11 deletions(-)
diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
index 02f12f29219..02f3ee15c87 100644
--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
+++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
@@ -178,17 +178,6 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
/* Tell the publisher to translate to our encoding */
keys[++i] = "client_encoding";
vals[i] = GetDatabaseEncodingName();
-
- /*
- * Force assorted GUC parameters to settings that ensure that the
- * publisher will output data values in a form that is unambiguous
- * to the subscriber. (We don't want to modify the subscriber's
- * GUC settings, since that might surprise user-defined code
- * running in the subscriber, such as triggers.) This should
- * match what pg_dump does.
- */
- keys[++i] = "options";
- vals[i] = "-c datestyle=ISO -c intervalstyle=postgres -c extra_float_digits=3";
}
else
{
@@ -289,6 +278,37 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
PQclear(res);
}
+ /*
+ * Force assorted GUC parameters to settings that ensure that the
+ * publisher will output data values in a form that is unambiguous to the
+ * subscriber. (We don't want to modify the subscriber's GUC settings,
+ * since that might surprise user-defined code running in the subscriber,
+ * such as triggers.) This should match what pg_dump does.
+ */
+ if (replication && logical)
+ {
+ const char *params[] =
+ {"datestyle", "intervalstyle", "extra_float_digits"};
+ const char *values[] = {"ISO", "postgres", "3"};
+
+ for (int j = 0; j < lengthof(params); j++)
+ {
+ char sql[100];
+ PGresult *res;
+
+ sprintf(sql, "SET %s = %s", params[j], values[j]);
+ res = libpqrcv_PQexec(conn->streamConn, sql);
+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
+ {
+ PQclear(res);
+ *err = psprintf(_("could not set %s: %s"),
+ params[j], pchomp(PQerrorMessage(conn->streamConn)));
+ goto bad_connection;
+ }
+ PQclear(res);
+ }
+ }
+
conn->logical = logical;
return conn;
--
2.51.2
^ permalink raw reply [nested|flat] 37+ messages in thread
* Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect
@ 2025-11-26 17:37 Kirill Reshke <[email protected]>
parent: Fujii Masao <[email protected]>
1 sibling, 1 reply; 37+ messages in thread
From: Kirill Reshke @ 2025-11-26 17:37 UTC (permalink / raw)
To: Fujii Masao <[email protected]>; +Cc: Chao Li <[email protected]>; PostgreSQL Hackers <[email protected]>
On Sat, 22 Nov 2025 at 17:14, Fujii Masao <[email protected]> wrote:
>
>
> Okay, thanks!
>
> I've updated the patch to use lengthof() as you suggested.
> The revised version is attached.
>
> Regards,
>
> --
> Fujii Masao
Looking at v3 raises two questions for me.
First is if we should have a doc notion of which variables ought to be
set to what.
Second, how do we actually test that subscription connection options
are applied on the subscriber side? Can we have TAP for this (is is
worth the troubles)?
--
Best regards,
Kirill Reshke
^ permalink raw reply [nested|flat] 37+ messages in thread
* Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect
@ 2025-11-27 02:46 Fujii Masao <[email protected]>
parent: Kirill Reshke <[email protected]>
0 siblings, 1 reply; 37+ messages in thread
From: Fujii Masao @ 2025-11-27 02:46 UTC (permalink / raw)
To: Kirill Reshke <[email protected]>; +Cc: Chao Li <[email protected]>; PostgreSQL Hackers <[email protected]>
On Thu, Nov 27, 2025 at 2:37 AM Kirill Reshke <[email protected]> wrote:
> Looking at v3 raises two questions for me.
>
> First is if we should have a doc notion of which variables ought to be
> set to what.
Are you suggesting that we document which GUC parameters should be set,
and to what values, for logical replication? We already have a section on this
in logical-replication.sgml. Is that sufficient?
> Second, how do we actually test that subscription connection options
> are applied on the subscriber side? Can we have TAP for this (is is
> worth the troubles)?
+1 on adding a test. One idea is to enable log_replication_commands via
the CONNECTION option and then check that the publisher’s log contains
the message "received replication command: IDENTIFY_SYSTEM".
There may be a cleaner way to test this, though.
Regards,
--
Fujii Masao
^ permalink raw reply [nested|flat] 37+ messages in thread
* Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect
@ 2025-11-27 05:17 Fujii Masao <[email protected]>
parent: Fujii Masao <[email protected]>
0 siblings, 1 reply; 37+ messages in thread
From: Fujii Masao @ 2025-11-27 05:17 UTC (permalink / raw)
To: Kirill Reshke <[email protected]>; +Cc: Chao Li <[email protected]>; PostgreSQL Hackers <[email protected]>
On Thu, Nov 27, 2025 at 11:46 AM Fujii Masao <[email protected]> wrote:
>
> On Thu, Nov 27, 2025 at 2:37 AM Kirill Reshke <[email protected]> wrote:
> > Looking at v3 raises two questions for me.
> >
> > First is if we should have a doc notion of which variables ought to be
> > set to what.
>
> Are you suggesting that we document which GUC parameters should be set,
> and to what values, for logical replication? We already have a section on this
> in logical-replication.sgml. Is that sufficient?
>
>
> > Second, how do we actually test that subscription connection options
> > are applied on the subscriber side? Can we have TAP for this (is is
> > worth the troubles)?
>
> +1 on adding a test. One idea is to enable log_replication_commands via
> the CONNECTION option and then check that the publisher’s log contains
> the message "received replication command: IDENTIFY_SYSTEM".
> There may be a cleaner way to test this, though.
I've added the test and attached it as patch v4-0002.
The test enables log_disconnections via the CONNECTION string and then checks
that the publisher's log contains the expected disconnection message after
the logical replication connection is reestablished.
Regards,
--
Fujii Masao
From 159e0c886546f3b12ebd48b57d12c68493d5309e Mon Sep 17 00:00:00 2001
From: Fujii Masao <[email protected]>
Date: Wed, 26 Nov 2025 23:35:44 +0900
Subject: [PATCH v4] Honor GUC settings specified in CREATE SUBSCRIPTION
CONNECTION.
Prior to v15, GUC settings supplied in the CONNECTION clause of
CREATE SUBSCRIPTION were correctly passed through to
the publisher's walsender. For example:
CREATE SUBSCRIPTION mysub
CONNECTION 'options=''-c wal_sender_timeout=1000'''
PUBLICATION ...
would cause wal_sender_timeout to take effect on the publisher's walsender.
However, commit f3d4019da5d changed the way logical replication
connections are established, forcing the publisher's relevant
GUC settings (datestyle, intervalstyle, extra_float_digits) to
override those provided in the CONNECTION string. As a result,
from v15 through v18, GUC settings in the CONNECTION string were
always ignored.
This regression prevented per-connection tuning of logical replication.
For example, using a shorter timeout for walsender connecting
to a nearby subscriber and a longer one for walsender connecting
to a remote subscriber.
This commit restores the intended behavior by ensuring that
GUC settings in the CONNECTION string are again passed through
and applied by the walsender, allowing per-connection configuration.
Backpatch to v15, where the regression was introduced.
Author: Fujii Masao <[email protected]>
Reviewed-by: Chao Li <[email protected]>
Discussion: https://postgr.es/m/CAHGQGwGYV+-abbKwdrM2UHUe-JYOFWmsrs6=QicyJO-j+-Widw@mail.gmail.com
Backpatch-through: 15
---
.../libpqwalreceiver/libpqwalreceiver.c | 43 ++++++++++++++-----
1 file changed, 32 insertions(+), 11 deletions(-)
diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
index 568024ec974..1270d162c88 100644
--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
+++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
@@ -170,17 +170,6 @@ libpqrcv_connect(const char *conninfo, bool logical, bool must_use_password,
/* Tell the publisher to translate to our encoding */
keys[++i] = "client_encoding";
vals[i] = GetDatabaseEncodingName();
-
- /*
- * Force assorted GUC parameters to settings that ensure that the
- * publisher will output data values in a form that is unambiguous to
- * the subscriber. (We don't want to modify the subscriber's GUC
- * settings, since that might surprise user-defined code running in
- * the subscriber, such as triggers.) This should match what pg_dump
- * does.
- */
- keys[++i] = "options";
- vals[i] = "-c datestyle=ISO -c intervalstyle=postgres -c extra_float_digits=3";
}
keys[++i] = NULL;
vals[i] = NULL;
@@ -263,6 +252,37 @@ libpqrcv_connect(const char *conninfo, bool logical, bool must_use_password,
PQclear(res);
}
+ /*
+ * Force assorted GUC parameters to settings that ensure that the
+ * publisher will output data values in a form that is unambiguous to the
+ * subscriber. (We don't want to modify the subscriber's GUC settings,
+ * since that might surprise user-defined code running in the subscriber,
+ * such as triggers.) This should match what pg_dump does.
+ */
+ if (logical)
+ {
+ const char *params[] =
+ {"datestyle", "intervalstyle", "extra_float_digits"};
+ const char *values[] = {"ISO", "postgres", "3"};
+
+ for (int j = 0; j < lengthof(params); j++)
+ {
+ char sql[100];
+ PGresult *res;
+
+ sprintf(sql, "SET %s = %s", params[j], values[j]);
+ res = libpqrcv_PQexec(conn->streamConn, sql);
+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
+ {
+ PQclear(res);
+ *err = psprintf(_("could not set %s: %s"),
+ params[j], pchomp(PQerrorMessage(conn->streamConn)));
+ goto bad_connection;
+ }
+ PQclear(res);
+ }
+ }
+
conn->logical = logical;
return conn;
@@ -434,6 +454,7 @@ libpqrcv_identify_system(WalReceiverConn *conn, TimeLineID *primary_tli)
"the primary server: %s",
pchomp(PQerrorMessage(conn->streamConn)))));
}
+
/*
* IDENTIFY_SYSTEM returns 3 columns in 9.3 and earlier, and 4 columns in
* 9.4 and onwards.
--
2.51.2
From 1a1c412e2d320d82d7a6927e5e6550c554a77b23 Mon Sep 17 00:00:00 2001
From: Fujii Masao <[email protected]>
Date: Wed, 26 Nov 2025 23:35:44 +0900
Subject: [PATCH v4] Honor GUC settings specified in CREATE SUBSCRIPTION
CONNECTION.
Prior to v15, GUC settings supplied in the CONNECTION clause of
CREATE SUBSCRIPTION were correctly passed through to
the publisher's walsender. For example:
CREATE SUBSCRIPTION mysub
CONNECTION 'options=''-c wal_sender_timeout=1000'''
PUBLICATION ...
would cause wal_sender_timeout to take effect on the publisher's walsender.
However, commit f3d4019da5d changed the way logical replication
connections are established, forcing the publisher's relevant
GUC settings (datestyle, intervalstyle, extra_float_digits) to
override those provided in the CONNECTION string. As a result,
from v15 through v18, GUC settings in the CONNECTION string were
always ignored.
This regression prevented per-connection tuning of logical replication.
For example, using a shorter timeout for walsender connecting
to a nearby subscriber and a longer one for walsender connecting
to a remote subscriber.
This commit restores the intended behavior by ensuring that
GUC settings in the CONNECTION string are again passed through
and applied by the walsender, allowing per-connection configuration.
Backpatch to v15, where the regression was introduced.
Author: Fujii Masao <[email protected]>
Reviewed-by: Chao Li <[email protected]>
Discussion: https://postgr.es/m/CAHGQGwGYV+-abbKwdrM2UHUe-JYOFWmsrs6=QicyJO-j+-Widw@mail.gmail.com
Backpatch-through: 15
---
.../libpqwalreceiver/libpqwalreceiver.c | 42 ++++++++++++++-----
1 file changed, 31 insertions(+), 11 deletions(-)
diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
index 02f12f29219..02f3ee15c87 100644
--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
+++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
@@ -178,17 +178,6 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
/* Tell the publisher to translate to our encoding */
keys[++i] = "client_encoding";
vals[i] = GetDatabaseEncodingName();
-
- /*
- * Force assorted GUC parameters to settings that ensure that the
- * publisher will output data values in a form that is unambiguous
- * to the subscriber. (We don't want to modify the subscriber's
- * GUC settings, since that might surprise user-defined code
- * running in the subscriber, such as triggers.) This should
- * match what pg_dump does.
- */
- keys[++i] = "options";
- vals[i] = "-c datestyle=ISO -c intervalstyle=postgres -c extra_float_digits=3";
}
else
{
@@ -289,6 +278,37 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
PQclear(res);
}
+ /*
+ * Force assorted GUC parameters to settings that ensure that the
+ * publisher will output data values in a form that is unambiguous to the
+ * subscriber. (We don't want to modify the subscriber's GUC settings,
+ * since that might surprise user-defined code running in the subscriber,
+ * such as triggers.) This should match what pg_dump does.
+ */
+ if (replication && logical)
+ {
+ const char *params[] =
+ {"datestyle", "intervalstyle", "extra_float_digits"};
+ const char *values[] = {"ISO", "postgres", "3"};
+
+ for (int j = 0; j < lengthof(params); j++)
+ {
+ char sql[100];
+ PGresult *res;
+
+ sprintf(sql, "SET %s = %s", params[j], values[j]);
+ res = libpqrcv_PQexec(conn->streamConn, sql);
+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
+ {
+ PQclear(res);
+ *err = psprintf(_("could not set %s: %s"),
+ params[j], pchomp(PQerrorMessage(conn->streamConn)));
+ goto bad_connection;
+ }
+ PQclear(res);
+ }
+ }
+
conn->logical = logical;
return conn;
--
2.51.2
Attachments:
[text/plain] v4-0001-PG15-PG16-Honor-GUC-settings-specified-in-CREATE-SUBSCRIPTI.txt (4.1K, ../../CAHGQGwGxSVPia+ZtJxyqWTdP_-YG_YPb=CMrZpC7fTjknARX=A@mail.gmail.com/2-v4-0001-PG15-PG16-Honor-GUC-settings-specified-in-CREATE-SUBSCRIPTI.txt)
download | inline diff:
From 159e0c886546f3b12ebd48b57d12c68493d5309e Mon Sep 17 00:00:00 2001
From: Fujii Masao <[email protected]>
Date: Wed, 26 Nov 2025 23:35:44 +0900
Subject: [PATCH v4] Honor GUC settings specified in CREATE SUBSCRIPTION
CONNECTION.
Prior to v15, GUC settings supplied in the CONNECTION clause of
CREATE SUBSCRIPTION were correctly passed through to
the publisher's walsender. For example:
CREATE SUBSCRIPTION mysub
CONNECTION 'options=''-c wal_sender_timeout=1000'''
PUBLICATION ...
would cause wal_sender_timeout to take effect on the publisher's walsender.
However, commit f3d4019da5d changed the way logical replication
connections are established, forcing the publisher's relevant
GUC settings (datestyle, intervalstyle, extra_float_digits) to
override those provided in the CONNECTION string. As a result,
from v15 through v18, GUC settings in the CONNECTION string were
always ignored.
This regression prevented per-connection tuning of logical replication.
For example, using a shorter timeout for walsender connecting
to a nearby subscriber and a longer one for walsender connecting
to a remote subscriber.
This commit restores the intended behavior by ensuring that
GUC settings in the CONNECTION string are again passed through
and applied by the walsender, allowing per-connection configuration.
Backpatch to v15, where the regression was introduced.
Author: Fujii Masao <[email protected]>
Reviewed-by: Chao Li <[email protected]>
Discussion: https://postgr.es/m/CAHGQGwGYV+-abbKwdrM2UHUe-JYOFWmsrs6=QicyJO-j+-Widw@mail.gmail.com
Backpatch-through: 15
---
.../libpqwalreceiver/libpqwalreceiver.c | 43 ++++++++++++++-----
1 file changed, 32 insertions(+), 11 deletions(-)
diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
index 568024ec974..1270d162c88 100644
--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
+++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
@@ -170,17 +170,6 @@ libpqrcv_connect(const char *conninfo, bool logical, bool must_use_password,
/* Tell the publisher to translate to our encoding */
keys[++i] = "client_encoding";
vals[i] = GetDatabaseEncodingName();
-
- /*
- * Force assorted GUC parameters to settings that ensure that the
- * publisher will output data values in a form that is unambiguous to
- * the subscriber. (We don't want to modify the subscriber's GUC
- * settings, since that might surprise user-defined code running in
- * the subscriber, such as triggers.) This should match what pg_dump
- * does.
- */
- keys[++i] = "options";
- vals[i] = "-c datestyle=ISO -c intervalstyle=postgres -c extra_float_digits=3";
}
keys[++i] = NULL;
vals[i] = NULL;
@@ -263,6 +252,37 @@ libpqrcv_connect(const char *conninfo, bool logical, bool must_use_password,
PQclear(res);
}
+ /*
+ * Force assorted GUC parameters to settings that ensure that the
+ * publisher will output data values in a form that is unambiguous to the
+ * subscriber. (We don't want to modify the subscriber's GUC settings,
+ * since that might surprise user-defined code running in the subscriber,
+ * such as triggers.) This should match what pg_dump does.
+ */
+ if (logical)
+ {
+ const char *params[] =
+ {"datestyle", "intervalstyle", "extra_float_digits"};
+ const char *values[] = {"ISO", "postgres", "3"};
+
+ for (int j = 0; j < lengthof(params); j++)
+ {
+ char sql[100];
+ PGresult *res;
+
+ sprintf(sql, "SET %s = %s", params[j], values[j]);
+ res = libpqrcv_PQexec(conn->streamConn, sql);
+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
+ {
+ PQclear(res);
+ *err = psprintf(_("could not set %s: %s"),
+ params[j], pchomp(PQerrorMessage(conn->streamConn)));
+ goto bad_connection;
+ }
+ PQclear(res);
+ }
+ }
+
conn->logical = logical;
return conn;
@@ -434,6 +454,7 @@ libpqrcv_identify_system(WalReceiverConn *conn, TimeLineID *primary_tli)
"the primary server: %s",
pchomp(PQerrorMessage(conn->streamConn)))));
}
+
/*
* IDENTIFY_SYSTEM returns 3 columns in 9.3 and earlier, and 4 columns in
* 9.4 and onwards.
--
2.51.2
[application/octet-stream] v4-0001-Honor-GUC-settings-specified-in-CREATE-SUBSCRIPTI.patch (3.9K, ../../CAHGQGwGxSVPia+ZtJxyqWTdP_-YG_YPb=CMrZpC7fTjknARX=A@mail.gmail.com/3-v4-0001-Honor-GUC-settings-specified-in-CREATE-SUBSCRIPTI.patch)
download | inline diff:
From 947cf9d587333219791a257389b95eae01d76237 Mon Sep 17 00:00:00 2001
From: Fujii Masao <[email protected]>
Date: Wed, 26 Nov 2025 23:35:44 +0900
Subject: [PATCH v4] Honor GUC settings specified in CREATE SUBSCRIPTION
CONNECTION.
Prior to v15, GUC settings supplied in the CONNECTION clause of
CREATE SUBSCRIPTION were correctly passed through to
the publisher's walsender. For example:
CREATE SUBSCRIPTION mysub
CONNECTION 'options=''-c wal_sender_timeout=1000'''
PUBLICATION ...
would cause wal_sender_timeout to take effect on the publisher's walsender.
However, commit f3d4019da5d changed the way logical replication
connections are established, forcing the publisher's relevant
GUC settings (datestyle, intervalstyle, extra_float_digits) to
override those provided in the CONNECTION string. As a result,
from v15 through v18, GUC settings in the CONNECTION string were
always ignored.
This regression prevented per-connection tuning of logical replication.
For example, using a shorter timeout for walsender connecting
to a nearby subscriber and a longer one for walsender connecting
to a remote subscriber.
This commit restores the intended behavior by ensuring that
GUC settings in the CONNECTION string are again passed through
and applied by the walsender, allowing per-connection configuration.
Backpatch to v15, where the regression was introduced.
Author: Fujii Masao <[email protected]>
Reviewed-by: Chao Li <[email protected]>
Discussion: https://postgr.es/m/CAHGQGwGYV+-abbKwdrM2UHUe-JYOFWmsrs6=QicyJO-j+-Widw@mail.gmail.com
Backpatch-through: 15
---
.../libpqwalreceiver/libpqwalreceiver.c | 43 ++++++++++++++-----
1 file changed, 32 insertions(+), 11 deletions(-)
diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
index 239641bfbb6..500632b462f 100644
--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
+++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
@@ -180,17 +180,6 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
/* Tell the publisher to translate to our encoding */
keys[++i] = "client_encoding";
vals[i] = GetDatabaseEncodingName();
-
- /*
- * Force assorted GUC parameters to settings that ensure that the
- * publisher will output data values in a form that is unambiguous
- * to the subscriber. (We don't want to modify the subscriber's
- * GUC settings, since that might surprise user-defined code
- * running in the subscriber, such as triggers.) This should
- * match what pg_dump does.
- */
- keys[++i] = "options";
- vals[i] = "-c datestyle=ISO -c intervalstyle=postgres -c extra_float_digits=3";
}
else
{
@@ -256,6 +245,38 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
PQclear(res);
}
+ /*
+ * Force assorted GUC parameters to settings that ensure that the
+ * publisher will output data values in a form that is unambiguous to the
+ * subscriber. (We don't want to modify the subscriber's GUC settings,
+ * since that might surprise user-defined code running in the subscriber,
+ * such as triggers.) This should match what pg_dump does.
+ */
+ if (replication && logical)
+ {
+ const char *params[] =
+ {"datestyle", "intervalstyle", "extra_float_digits"};
+ const char *values[] = {"ISO", "postgres", "3"};
+
+ for (int j = 0; j < lengthof(params); j++)
+ {
+ char sql[100];
+ PGresult *res;
+
+ sprintf(sql, "SET %s = %s", params[j], values[j]);
+ res = libpqsrv_exec(conn->streamConn, sql,
+ WAIT_EVENT_LIBPQWALRECEIVER_RECEIVE);
+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
+ {
+ PQclear(res);
+ *err = psprintf(_("could not set %s: %s"),
+ params[j], pchomp(PQerrorMessage(conn->streamConn)));
+ goto bad_connection;
+ }
+ PQclear(res);
+ }
+ }
+
conn->logical = logical;
return conn;
--
2.51.2
[application/octet-stream] v4-0002-Add-TAP-test-for-GUC-settings-passed-via-CONNECTI.patch (3.1K, ../../CAHGQGwGxSVPia+ZtJxyqWTdP_-YG_YPb=CMrZpC7fTjknARX=A@mail.gmail.com/4-v4-0002-Add-TAP-test-for-GUC-settings-passed-via-CONNECTI.patch)
download | inline diff:
From b8ca4b8637140da82b13f40ae509787bb643fea7 Mon Sep 17 00:00:00 2001
From: Fujii Masao <[email protected]>
Date: Thu, 27 Nov 2025 12:36:59 +0900
Subject: [PATCH v4 2/2] Add TAP test for GUC settings passed via CONNECTION in
logical replication.
This commit adds a TAP test to verify that GUC settings provided in
the CONNECTION string of CREATE/ALTER SUBSCRIPTION are correctly
passed through to and applied by the publisher's walsender.
---
src/test/subscription/t/001_rep_changes.pl | 28 +++++++++++++++++++++-
1 file changed, 27 insertions(+), 1 deletion(-)
diff --git a/src/test/subscription/t/001_rep_changes.pl b/src/test/subscription/t/001_rep_changes.pl
index 430c1246d14..9d08ae8b641 100644
--- a/src/test/subscription/t/001_rep_changes.pl
+++ b/src/test/subscription/t/001_rep_changes.pl
@@ -438,17 +438,34 @@ is( $result, qq(11.11|baz|1
22.22|bar|2),
'update works with dropped subscriber column');
+# Verify that GUC settings supplied in the CONNECTION string take effect on
+# the publisher's walsender. We do this by enabling log_disconnections in
+# the CONNECTION string later and checking that the publisher's log contains a
+# disconnection message.
+#
+# First, confirm that no such disconnection message appears before enabling
+# log_disconnections.
+$logfile = slurp_file($node_publisher->logfile, $log_location);
+unlike(
+ $logfile,
+ qr/disconnection: session time:/,
+ 'log_disconnections has not been enabled yet');
+
# check that change of connection string and/or publication list causes
# restart of subscription workers. We check the state along with
# application_name to ensure that the walsender is (re)started.
#
# Not all of these are registered as tests as we need to poll for a change
# but the test suite will fail nonetheless when something goes wrong.
+#
+# Enable log_disconnections as the change of connection string,
+# which is also for the above mentioned test of GUC settings passed through
+# CONNECTION.
my $oldpid = $node_publisher->safe_psql('postgres',
"SELECT pid FROM pg_stat_replication WHERE application_name = 'tap_sub' AND state = 'streaming';"
);
$node_subscriber->safe_psql('postgres',
- "ALTER SUBSCRIPTION tap_sub CONNECTION '$publisher_connstr sslmode=disable'"
+ "ALTER SUBSCRIPTION tap_sub CONNECTION '$publisher_connstr options=''-c log_disconnections=on'''"
);
$node_publisher->poll_query_until('postgres',
"SELECT pid != $oldpid FROM pg_stat_replication WHERE application_name = 'tap_sub' AND state = 'streaming';"
@@ -552,6 +569,15 @@ $node_publisher->poll_query_until('postgres',
or die
"Timed out while waiting for apply to restart after renaming SUBSCRIPTION";
+# Check that the expected disconnection message appears,
+# which shows that log_disconnections=on from the CONNECTION string
+# was correctly passed through to and honored by the walsender.
+$logfile = slurp_file($node_publisher->logfile, $log_location);
+like(
+ $logfile,
+ qr/disconnection: session time:/,
+ 'log_disconnections in CONNECTION string had effect on publisher\'s walsender');
+
# check all the cleanup
$node_subscriber->safe_psql('postgres', "DROP SUBSCRIPTION tap_sub_renamed");
--
2.51.2
[text/plain] v4-0001-PG17-Honor-GUC-settings-specified-in-CREATE-SUBSCRIPTI.txt (3.8K, ../../CAHGQGwGxSVPia+ZtJxyqWTdP_-YG_YPb=CMrZpC7fTjknARX=A@mail.gmail.com/5-v4-0001-PG17-Honor-GUC-settings-specified-in-CREATE-SUBSCRIPTI.txt)
download | inline diff:
From 1a1c412e2d320d82d7a6927e5e6550c554a77b23 Mon Sep 17 00:00:00 2001
From: Fujii Masao <[email protected]>
Date: Wed, 26 Nov 2025 23:35:44 +0900
Subject: [PATCH v4] Honor GUC settings specified in CREATE SUBSCRIPTION
CONNECTION.
Prior to v15, GUC settings supplied in the CONNECTION clause of
CREATE SUBSCRIPTION were correctly passed through to
the publisher's walsender. For example:
CREATE SUBSCRIPTION mysub
CONNECTION 'options=''-c wal_sender_timeout=1000'''
PUBLICATION ...
would cause wal_sender_timeout to take effect on the publisher's walsender.
However, commit f3d4019da5d changed the way logical replication
connections are established, forcing the publisher's relevant
GUC settings (datestyle, intervalstyle, extra_float_digits) to
override those provided in the CONNECTION string. As a result,
from v15 through v18, GUC settings in the CONNECTION string were
always ignored.
This regression prevented per-connection tuning of logical replication.
For example, using a shorter timeout for walsender connecting
to a nearby subscriber and a longer one for walsender connecting
to a remote subscriber.
This commit restores the intended behavior by ensuring that
GUC settings in the CONNECTION string are again passed through
and applied by the walsender, allowing per-connection configuration.
Backpatch to v15, where the regression was introduced.
Author: Fujii Masao <[email protected]>
Reviewed-by: Chao Li <[email protected]>
Discussion: https://postgr.es/m/CAHGQGwGYV+-abbKwdrM2UHUe-JYOFWmsrs6=QicyJO-j+-Widw@mail.gmail.com
Backpatch-through: 15
---
.../libpqwalreceiver/libpqwalreceiver.c | 42 ++++++++++++++-----
1 file changed, 31 insertions(+), 11 deletions(-)
diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
index 02f12f29219..02f3ee15c87 100644
--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
+++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
@@ -178,17 +178,6 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
/* Tell the publisher to translate to our encoding */
keys[++i] = "client_encoding";
vals[i] = GetDatabaseEncodingName();
-
- /*
- * Force assorted GUC parameters to settings that ensure that the
- * publisher will output data values in a form that is unambiguous
- * to the subscriber. (We don't want to modify the subscriber's
- * GUC settings, since that might surprise user-defined code
- * running in the subscriber, such as triggers.) This should
- * match what pg_dump does.
- */
- keys[++i] = "options";
- vals[i] = "-c datestyle=ISO -c intervalstyle=postgres -c extra_float_digits=3";
}
else
{
@@ -289,6 +278,37 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
PQclear(res);
}
+ /*
+ * Force assorted GUC parameters to settings that ensure that the
+ * publisher will output data values in a form that is unambiguous to the
+ * subscriber. (We don't want to modify the subscriber's GUC settings,
+ * since that might surprise user-defined code running in the subscriber,
+ * such as triggers.) This should match what pg_dump does.
+ */
+ if (replication && logical)
+ {
+ const char *params[] =
+ {"datestyle", "intervalstyle", "extra_float_digits"};
+ const char *values[] = {"ISO", "postgres", "3"};
+
+ for (int j = 0; j < lengthof(params); j++)
+ {
+ char sql[100];
+ PGresult *res;
+
+ sprintf(sql, "SET %s = %s", params[j], values[j]);
+ res = libpqrcv_PQexec(conn->streamConn, sql);
+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
+ {
+ PQclear(res);
+ *err = psprintf(_("could not set %s: %s"),
+ params[j], pchomp(PQerrorMessage(conn->streamConn)));
+ goto bad_connection;
+ }
+ PQclear(res);
+ }
+ }
+
conn->logical = logical;
return conn;
--
2.51.2
^ permalink raw reply [nested|flat] 37+ messages in thread
* Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect
@ 2025-12-02 06:02 Fujii Masao <[email protected]>
parent: Fujii Masao <[email protected]>
0 siblings, 1 reply; 37+ messages in thread
From: Fujii Masao @ 2025-12-02 06:02 UTC (permalink / raw)
To: Kirill Reshke <[email protected]>; +Cc: Chao Li <[email protected]>; PostgreSQL Hackers <[email protected]>
On Thu, Nov 27, 2025 at 2:17 PM Fujii Masao <[email protected]> wrote:
> I've added the test and attached it as patch v4-0002.
>
> The test enables log_disconnections via the CONNECTION string and then checks
> that the publisher's log contains the expected disconnection message after
> the logical replication connection is reestablished.
Barring any objections, I will commit the v4-001 patch and backpatch it to v15.
Regards,
--
Fujii Masao
^ permalink raw reply [nested|flat] 37+ messages in thread
* Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect
@ 2025-12-02 06:37 Kirill Reshke <[email protected]>
parent: Fujii Masao <[email protected]>
0 siblings, 0 replies; 37+ messages in thread
From: Kirill Reshke @ 2025-12-02 06:37 UTC (permalink / raw)
To: Fujii Masao <[email protected]>; +Cc: Chao Li <[email protected]>; PostgreSQL Hackers <[email protected]>
On Tue, 2 Dec 2025 at 11:02, Fujii Masao <[email protected]> wrote:
>
> On Thu, Nov 27, 2025 at 2:17 PM Fujii Masao <[email protected]> wrote:
> > I've added the test and attached it as patch v4-0002.
> >
> > The test enables log_disconnections via the CONNECTION string and then checks
> > that the publisher's log contains the expected disconnection message after
> > the logical replication connection is reestablished.
>
> Barring any objections, I will commit the v4-001 patch and backpatch it to v15.
>
> Regards,
>
> --
> Fujii Masao
Sure lgtm. I actually checked v4-0001, but did not got any objections
--
Best regards,
Kirill Reshke
^ permalink raw reply [nested|flat] 37+ messages in thread
* Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect
@ 2025-12-02 12:08 Amit Kapila <[email protected]>
parent: Fujii Masao <[email protected]>
2 siblings, 1 reply; 37+ messages in thread
From: Amit Kapila @ 2025-12-02 12:08 UTC (permalink / raw)
To: Fujii Masao <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>
On Tue, Nov 18, 2025 at 9:29 PM Fujii Masao <[email protected]> wrote:
>
> In logical replication, any GUC settings specified in the CONNECTION clause of
> CREATE SUBSCRIPTION are currently ignored. For example:
>
> CREATE SUBSCRIPTION mysub
> CONNECTION 'options=''-c wal_sender_timeout=1000'''
> PUBLICATION ...
>
> The wal_sender_timeout value here has no effect.
>
> This is inconvenient when different logical replication walsenders need
> different settings - e.g., a small wal_sender_timeout for walsender
> connecting to a nearby subscriber and a larger one for walsender
> connecting to a distant subscriber. Right now, it's not easy for users
> to control such per-connection behavior.
>
> The reason of thid limitation is that libpqrcv_connect() always overwrites
> the options connection parameter as follows:
>
> keys[++i] = "options";
> vals[i] = "-c datestyle=ISO -c intervalstyle=postgres -c
> extra_float_digits=3";
>
> This wipes out any user-specified GUCs in the CONNECTION string.
> Physical replication does not have this problem because it does not overwrite
> options, so GUCs in primary_conninfo are honored.
>
> To remove this restriction, how about switching to issuing SET commands for
> datestyle, intervalstyle, and extra_float_digits after the connection
> is established,
> similar to what postgres_fdw does, instead of forcing them into options?
> That would allow user-specified GUC settings in CREATE SUBSCRIPTION to
> take effect.
>
Is it possible that we append the predefined options to the options
given by the user to avoid extra round-trip?
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 37+ messages in thread
* Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect
@ 2025-12-02 14:59 Fujii Masao <[email protected]>
parent: Amit Kapila <[email protected]>
0 siblings, 1 reply; 37+ messages in thread
From: Fujii Masao @ 2025-12-02 14:59 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>
On Tue, Dec 2, 2025 at 9:08 PM Amit Kapila <[email protected]> wrote:
> Is it possible that we append the predefined options to the options
> given by the user to avoid extra round-trip?
One idea is to add a function, similar to libpqrcv_get_dbname_from_conninfo()
in libpqwalreceiver.c, that extracts the options string from the conninfo,
to append the required fixed settings, and then to use the combined string as
the value of the options parameter. Do you think implementing this is worthwhile
to avoid the extra round trip?
Regards,
--
Fujii Masao
^ permalink raw reply [nested|flat] 37+ messages in thread
* Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect
@ 2025-12-03 05:45 Amit Kapila <[email protected]>
parent: Fujii Masao <[email protected]>
0 siblings, 1 reply; 37+ messages in thread
From: Amit Kapila @ 2025-12-03 05:45 UTC (permalink / raw)
To: Fujii Masao <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>
On Tue, Dec 2, 2025 at 8:30 PM Fujii Masao <[email protected]> wrote:
>
> On Tue, Dec 2, 2025 at 9:08 PM Amit Kapila <[email protected]> wrote:
> > Is it possible that we append the predefined options to the options
> > given by the user to avoid extra round-trip?
>
> One idea is to add a function, similar to libpqrcv_get_dbname_from_conninfo()
> in libpqwalreceiver.c, that extracts the options string from the conninfo,
> to append the required fixed settings, and then to use the combined string as
> the value of the options parameter.
>
Yes, but libpqrcv_get_dbname_from_conninfo() is an exposed function,
we can implement something internal for libpqwalreceiver.c like
conninfo_add_defaults() present in fe-connect.c.
> Do you think implementing this is worthwhile
> to avoid the extra round trip?
>
I think so. Today, we have three variables, tomorrow there could be
more such variables as well and apart from avoiding extra round trips,
the idea to append options to provided options (if any) sounds more
logical to me.
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 37+ messages in thread
* Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect
@ 2025-12-19 07:55 Fujii Masao <[email protected]>
parent: Amit Kapila <[email protected]>
0 siblings, 2 replies; 37+ messages in thread
From: Fujii Masao @ 2025-12-19 07:55 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>
On Wed, Dec 3, 2025 at 2:45 PM Amit Kapila <[email protected]> wrote:
>
> On Tue, Dec 2, 2025 at 8:30 PM Fujii Masao <[email protected]> wrote:
> >
> > On Tue, Dec 2, 2025 at 9:08 PM Amit Kapila <[email protected]> wrote:
> > > Is it possible that we append the predefined options to the options
> > > given by the user to avoid extra round-trip?
> >
> > One idea is to add a function, similar to libpqrcv_get_dbname_from_conninfo()
> > in libpqwalreceiver.c, that extracts the options string from the conninfo,
> > to append the required fixed settings, and then to use the combined string as
> > the value of the options parameter.
> >
>
> Yes, but libpqrcv_get_dbname_from_conninfo() is an exposed function,
> we can implement something internal for libpqwalreceiver.c like
> conninfo_add_defaults() present in fe-connect.c.
>
> > Do you think implementing this is worthwhile
> > to avoid the extra round trip?
> >
>
> I think so. Today, we have three variables, tomorrow there could be
> more such variables as well and apart from avoiding extra round trips,
> the idea to append options to provided options (if any) sounds more
> logical to me.
OK, I've implemented the idea discussed upthread. The patch updates
libpqrcv_connect() so that, for logical replication, it extracts the options
string from the conninfo, appends the required fixed settings, and passes
the combined string as the options parameter to libpq.
For example, if the conninfo specifies -c wal_sender_timeout=10s,
the resulting options value becomes:
-c wal_sender_timeout=10s -c datestyle=ISO -c
intervalstyle=postgres -c extra_float_digits=3.
Patch attached.
Regards,
--
Fujii Masao
From f8e0dcdea82d08d65e30224da2339f58de8c5fc3 Mon Sep 17 00:00:00 2001
From: Fujii Masao <[email protected]>
Date: Wed, 3 Dec 2025 00:59:09 +0900
Subject: [PATCH v5] Honor GUC settings specified in CREATE SUBSCRIPTION
CONNECTION.
Prior to v15, GUC settings supplied in the CONNECTION clause of
CREATE SUBSCRIPTION were correctly passed through to
the publisher's walsender. For example:
CREATE SUBSCRIPTION mysub
CONNECTION 'options=''-c wal_sender_timeout=1000'''
PUBLICATION ...
would cause wal_sender_timeout to take effect on the publisher's walsender.
However, commit f3d4019da5d changed the way logical replication
connections are established, forcing the publisher's relevant
GUC settings (datestyle, intervalstyle, extra_float_digits) to
override those provided in the CONNECTION string. As a result,
from v15 through v18, GUC settings in the CONNECTION string were
always ignored.
This regression prevented per-connection tuning of logical replication.
For example, using a shorter timeout for walsender connecting
to a nearby subscriber and a longer one for walsender connecting
to a remote subscriber.
This commit restores the intended behavior by ensuring that
GUC settings in the CONNECTION string are again passed through
and applied by the walsender, allowing per-connection configuration.
Backpatch to v15, where the regression was introduced.
Author: Fujii Masao <[email protected]>
Reviewed-by: Chao Li <[email protected]>
Reviewed-by: Kirill Reshke <[email protected]>
Reviewed-by: Amit Kapila <[email protected]>
Discussion: https://postgr.es/m/CAHGQGwGYV+-abbKwdrM2UHUe-JYOFWmsrs6=QicyJO-j+-Widw@mail.gmail.com
Backpatch-through: 15
---
.../libpqwalreceiver/libpqwalreceiver.c | 61 ++++++++++++++++++-
1 file changed, 60 insertions(+), 1 deletion(-)
diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
index 568024ec974..743f951f330 100644
--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
+++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
@@ -57,6 +57,8 @@ static void libpqrcv_get_senderinfo(WalReceiverConn *conn,
char **sender_host, int *sender_port);
static char *libpqrcv_identify_system(WalReceiverConn *conn,
TimeLineID *primary_tli);
+static char *libpqrcv_get_option_from_conninfo(const char *connInfo,
+ const char *keyword);
static int libpqrcv_server_version(WalReceiverConn *conn);
static void libpqrcv_readtimelinehistoryfile(WalReceiverConn *conn,
TimeLineID tli, char **filename,
@@ -136,6 +138,7 @@ libpqrcv_connect(const char *conninfo, bool logical, bool must_use_password,
const char *keys[6];
const char *vals[6];
int i = 0;
+ char *options_val = NULL;
/*
* Re-validate connection string. The validation already happened at DDL
@@ -167,6 +170,8 @@ libpqrcv_connect(const char *conninfo, bool logical, bool must_use_password,
vals[i] = appname;
if (logical)
{
+ char *opt = NULL;
+
/* Tell the publisher to translate to our encoding */
keys[++i] = "client_encoding";
vals[i] = GetDatabaseEncodingName();
@@ -179,8 +184,13 @@ libpqrcv_connect(const char *conninfo, bool logical, bool must_use_password,
* the subscriber, such as triggers.) This should match what pg_dump
* does.
*/
+ opt = libpqrcv_get_option_from_conninfo(conninfo, "options");
+ options_val = psprintf("%s -c datestyle=ISO -c intervalstyle=postgres -c extra_float_digits=3",
+ (opt == NULL) ? "" : opt);
keys[++i] = "options";
- vals[i] = "-c datestyle=ISO -c intervalstyle=postgres -c extra_float_digits=3";
+ vals[i] = options_val;
+ if (opt != NULL)
+ pfree(opt);
}
keys[++i] = NULL;
vals[i] = NULL;
@@ -232,6 +242,9 @@ libpqrcv_connect(const char *conninfo, bool logical, bool must_use_password,
status = PQconnectPoll(conn->streamConn);
} while (status != PGRES_POLLING_OK && status != PGRES_POLLING_FAILED);
+ if (options_val != NULL)
+ pfree(options_val);
+
if (PQstatus(conn->streamConn) != CONNECTION_OK)
goto bad_connection_errmsg;
@@ -434,6 +447,7 @@ libpqrcv_identify_system(WalReceiverConn *conn, TimeLineID *primary_tli)
"the primary server: %s",
pchomp(PQerrorMessage(conn->streamConn)))));
}
+
/*
* IDENTIFY_SYSTEM returns 3 columns in 9.3 and earlier, and 4 columns in
* 9.4 and onwards.
@@ -466,6 +480,51 @@ libpqrcv_server_version(WalReceiverConn *conn)
return PQserverVersion(conn->streamConn);
}
+/*
+ * Get the value of the option with the given keyword from the primary
+ * server's conninfo.
+ *
+ * If the option is not found in connInfo, return NULL value.
+ */
+static char *
+libpqrcv_get_option_from_conninfo(const char *connInfo, const char *keyword)
+{
+ PQconninfoOption *opts;
+ char *option = NULL;
+ char *err = NULL;
+
+ opts = PQconninfoParse(connInfo, &err);
+ if (opts == NULL)
+ {
+ /* The error string is malloc'd, so we must free it explicitly */
+ char *errcopy = err ? pstrdup(err) : "out of memory";
+
+ PQfreemem(err);
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("invalid connection string syntax: %s", errcopy)));
+ }
+
+ for (PQconninfoOption *opt = opts; opt->keyword != NULL; ++opt)
+ {
+ /*
+ * If the same option appears multiple times, then the last one will
+ * be returned
+ */
+ if (strcmp(opt->keyword, keyword) == 0 && opt->val &&
+ *opt->val)
+ {
+ if (option)
+ pfree(option);
+
+ option = pstrdup(opt->val);
+ }
+ }
+
+ PQconninfoFree(opts);
+ return option;
+}
+
/*
* Start streaming WAL data from given streaming options.
*
--
2.51.2
Attachments:
[text/plain] v5-0001-PG15-PG16-Honor-GUC-settings-specified-in-CREATE-SUBSCRIPTI.txt (5.6K, ../../CAHGQGwEs08VO8SFFbp+4d=ktqh0K66rXWmqL4ea59iSn24ykLg@mail.gmail.com/2-v5-0001-PG15-PG16-Honor-GUC-settings-specified-in-CREATE-SUBSCRIPTI.txt)
download | inline diff:
From f8e0dcdea82d08d65e30224da2339f58de8c5fc3 Mon Sep 17 00:00:00 2001
From: Fujii Masao <[email protected]>
Date: Wed, 3 Dec 2025 00:59:09 +0900
Subject: [PATCH v5] Honor GUC settings specified in CREATE SUBSCRIPTION
CONNECTION.
Prior to v15, GUC settings supplied in the CONNECTION clause of
CREATE SUBSCRIPTION were correctly passed through to
the publisher's walsender. For example:
CREATE SUBSCRIPTION mysub
CONNECTION 'options=''-c wal_sender_timeout=1000'''
PUBLICATION ...
would cause wal_sender_timeout to take effect on the publisher's walsender.
However, commit f3d4019da5d changed the way logical replication
connections are established, forcing the publisher's relevant
GUC settings (datestyle, intervalstyle, extra_float_digits) to
override those provided in the CONNECTION string. As a result,
from v15 through v18, GUC settings in the CONNECTION string were
always ignored.
This regression prevented per-connection tuning of logical replication.
For example, using a shorter timeout for walsender connecting
to a nearby subscriber and a longer one for walsender connecting
to a remote subscriber.
This commit restores the intended behavior by ensuring that
GUC settings in the CONNECTION string are again passed through
and applied by the walsender, allowing per-connection configuration.
Backpatch to v15, where the regression was introduced.
Author: Fujii Masao <[email protected]>
Reviewed-by: Chao Li <[email protected]>
Reviewed-by: Kirill Reshke <[email protected]>
Reviewed-by: Amit Kapila <[email protected]>
Discussion: https://postgr.es/m/CAHGQGwGYV+-abbKwdrM2UHUe-JYOFWmsrs6=QicyJO-j+-Widw@mail.gmail.com
Backpatch-through: 15
---
.../libpqwalreceiver/libpqwalreceiver.c | 61 ++++++++++++++++++-
1 file changed, 60 insertions(+), 1 deletion(-)
diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
index 568024ec974..743f951f330 100644
--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
+++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
@@ -57,6 +57,8 @@ static void libpqrcv_get_senderinfo(WalReceiverConn *conn,
char **sender_host, int *sender_port);
static char *libpqrcv_identify_system(WalReceiverConn *conn,
TimeLineID *primary_tli);
+static char *libpqrcv_get_option_from_conninfo(const char *connInfo,
+ const char *keyword);
static int libpqrcv_server_version(WalReceiverConn *conn);
static void libpqrcv_readtimelinehistoryfile(WalReceiverConn *conn,
TimeLineID tli, char **filename,
@@ -136,6 +138,7 @@ libpqrcv_connect(const char *conninfo, bool logical, bool must_use_password,
const char *keys[6];
const char *vals[6];
int i = 0;
+ char *options_val = NULL;
/*
* Re-validate connection string. The validation already happened at DDL
@@ -167,6 +170,8 @@ libpqrcv_connect(const char *conninfo, bool logical, bool must_use_password,
vals[i] = appname;
if (logical)
{
+ char *opt = NULL;
+
/* Tell the publisher to translate to our encoding */
keys[++i] = "client_encoding";
vals[i] = GetDatabaseEncodingName();
@@ -179,8 +184,13 @@ libpqrcv_connect(const char *conninfo, bool logical, bool must_use_password,
* the subscriber, such as triggers.) This should match what pg_dump
* does.
*/
+ opt = libpqrcv_get_option_from_conninfo(conninfo, "options");
+ options_val = psprintf("%s -c datestyle=ISO -c intervalstyle=postgres -c extra_float_digits=3",
+ (opt == NULL) ? "" : opt);
keys[++i] = "options";
- vals[i] = "-c datestyle=ISO -c intervalstyle=postgres -c extra_float_digits=3";
+ vals[i] = options_val;
+ if (opt != NULL)
+ pfree(opt);
}
keys[++i] = NULL;
vals[i] = NULL;
@@ -232,6 +242,9 @@ libpqrcv_connect(const char *conninfo, bool logical, bool must_use_password,
status = PQconnectPoll(conn->streamConn);
} while (status != PGRES_POLLING_OK && status != PGRES_POLLING_FAILED);
+ if (options_val != NULL)
+ pfree(options_val);
+
if (PQstatus(conn->streamConn) != CONNECTION_OK)
goto bad_connection_errmsg;
@@ -434,6 +447,7 @@ libpqrcv_identify_system(WalReceiverConn *conn, TimeLineID *primary_tli)
"the primary server: %s",
pchomp(PQerrorMessage(conn->streamConn)))));
}
+
/*
* IDENTIFY_SYSTEM returns 3 columns in 9.3 and earlier, and 4 columns in
* 9.4 and onwards.
@@ -466,6 +480,51 @@ libpqrcv_server_version(WalReceiverConn *conn)
return PQserverVersion(conn->streamConn);
}
+/*
+ * Get the value of the option with the given keyword from the primary
+ * server's conninfo.
+ *
+ * If the option is not found in connInfo, return NULL value.
+ */
+static char *
+libpqrcv_get_option_from_conninfo(const char *connInfo, const char *keyword)
+{
+ PQconninfoOption *opts;
+ char *option = NULL;
+ char *err = NULL;
+
+ opts = PQconninfoParse(connInfo, &err);
+ if (opts == NULL)
+ {
+ /* The error string is malloc'd, so we must free it explicitly */
+ char *errcopy = err ? pstrdup(err) : "out of memory";
+
+ PQfreemem(err);
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("invalid connection string syntax: %s", errcopy)));
+ }
+
+ for (PQconninfoOption *opt = opts; opt->keyword != NULL; ++opt)
+ {
+ /*
+ * If the same option appears multiple times, then the last one will
+ * be returned
+ */
+ if (strcmp(opt->keyword, keyword) == 0 && opt->val &&
+ *opt->val)
+ {
+ if (option)
+ pfree(option);
+
+ option = pstrdup(opt->val);
+ }
+ }
+
+ PQconninfoFree(opts);
+ return option;
+}
+
/*
* Start streaming WAL data from given streaming options.
*
--
2.51.2
[application/octet-stream] v5-0002-Add-TAP-test-for-GUC-settings-passed-via-CONNECTI.patch (3.1K, ../../CAHGQGwEs08VO8SFFbp+4d=ktqh0K66rXWmqL4ea59iSn24ykLg@mail.gmail.com/3-v5-0002-Add-TAP-test-for-GUC-settings-passed-via-CONNECTI.patch)
download | inline diff:
From ad7ac7f3d88b6178cb50e2b64982bf89589c3655 Mon Sep 17 00:00:00 2001
From: Fujii Masao <[email protected]>
Date: Thu, 27 Nov 2025 12:36:59 +0900
Subject: [PATCH v5 2/2] Add TAP test for GUC settings passed via CONNECTION in
logical replication.
This commit adds a TAP test to verify that GUC settings provided in
the CONNECTION string of CREATE/ALTER SUBSCRIPTION are correctly
passed through to and applied by the publisher's walsender.
---
src/test/subscription/t/001_rep_changes.pl | 29 +++++++++++++++++++++-
1 file changed, 28 insertions(+), 1 deletion(-)
diff --git a/src/test/subscription/t/001_rep_changes.pl b/src/test/subscription/t/001_rep_changes.pl
index 430c1246d14..c044a1e63e1 100644
--- a/src/test/subscription/t/001_rep_changes.pl
+++ b/src/test/subscription/t/001_rep_changes.pl
@@ -438,17 +438,34 @@ is( $result, qq(11.11|baz|1
22.22|bar|2),
'update works with dropped subscriber column');
+# Verify that GUC settings supplied in the CONNECTION string take effect on
+# the publisher's walsender. We do this by enabling log_disconnections in
+# the CONNECTION string later and checking that the publisher's log contains a
+# disconnection message.
+#
+# First, confirm that no such disconnection message appears before enabling
+# log_disconnections.
+$logfile = slurp_file($node_publisher->logfile, $log_location);
+unlike(
+ $logfile,
+ qr/disconnection: session time:/,
+ 'log_disconnections has not been enabled yet');
+
# check that change of connection string and/or publication list causes
# restart of subscription workers. We check the state along with
# application_name to ensure that the walsender is (re)started.
#
# Not all of these are registered as tests as we need to poll for a change
# but the test suite will fail nonetheless when something goes wrong.
+#
+# Enable log_disconnections as the change of connection string,
+# which is also for the above mentioned test of GUC settings passed through
+# CONNECTION.
my $oldpid = $node_publisher->safe_psql('postgres',
"SELECT pid FROM pg_stat_replication WHERE application_name = 'tap_sub' AND state = 'streaming';"
);
$node_subscriber->safe_psql('postgres',
- "ALTER SUBSCRIPTION tap_sub CONNECTION '$publisher_connstr sslmode=disable'"
+ "ALTER SUBSCRIPTION tap_sub CONNECTION '$publisher_connstr options=''-c log_disconnections=on'''"
);
$node_publisher->poll_query_until('postgres',
"SELECT pid != $oldpid FROM pg_stat_replication WHERE application_name = 'tap_sub' AND state = 'streaming';"
@@ -552,6 +569,16 @@ $node_publisher->poll_query_until('postgres',
or die
"Timed out while waiting for apply to restart after renaming SUBSCRIPTION";
+# Check that the expected disconnection message appears,
+# which shows that log_disconnections=on from the CONNECTION string
+# was correctly passed through to and honored by the walsender.
+$logfile = slurp_file($node_publisher->logfile, $log_location);
+like(
+ $logfile,
+ qr/disconnection: session time:/,
+ 'log_disconnections in CONNECTION string had effect on publisher\'s walsender'
+);
+
# check all the cleanup
$node_subscriber->safe_psql('postgres', "DROP SUBSCRIPTION tap_sub_renamed");
--
2.51.2
[application/octet-stream] v5-0001-Honor-GUC-settings-specified-in-CREATE-SUBSCRIPTI.patch (5.3K, ../../CAHGQGwEs08VO8SFFbp+4d=ktqh0K66rXWmqL4ea59iSn24ykLg@mail.gmail.com/4-v5-0001-Honor-GUC-settings-specified-in-CREATE-SUBSCRIPTI.patch)
download | inline diff:
From c3e510636e8b7a1cce0657d86d6a29097544ee99 Mon Sep 17 00:00:00 2001
From: Fujii Masao <[email protected]>
Date: Wed, 3 Dec 2025 00:59:09 +0900
Subject: [PATCH v5 1/2] Honor GUC settings specified in CREATE SUBSCRIPTION
CONNECTION.
Prior to v15, GUC settings supplied in the CONNECTION clause of
CREATE SUBSCRIPTION were correctly passed through to
the publisher's walsender. For example:
CREATE SUBSCRIPTION mysub
CONNECTION 'options=''-c wal_sender_timeout=1000'''
PUBLICATION ...
would cause wal_sender_timeout to take effect on the publisher's walsender.
However, commit f3d4019da5d changed the way logical replication
connections are established, forcing the publisher's relevant
GUC settings (datestyle, intervalstyle, extra_float_digits) to
override those provided in the CONNECTION string. As a result,
from v15 through v18, GUC settings in the CONNECTION string were
always ignored.
This regression prevented per-connection tuning of logical replication.
For example, using a shorter timeout for walsender connecting
to a nearby subscriber and a longer one for walsender connecting
to a remote subscriber.
This commit restores the intended behavior by ensuring that
GUC settings in the CONNECTION string are again passed through
and applied by the walsender, allowing per-connection configuration.
Backpatch to v15, where the regression was introduced.
Author: Fujii Masao <[email protected]>
Reviewed-by: Chao Li <[email protected]>
Reviewed-by: Kirill Reshke <[email protected]>
Reviewed-by: Amit Kapila <[email protected]>
Discussion: https://postgr.es/m/CAHGQGwGYV+-abbKwdrM2UHUe-JYOFWmsrs6=QicyJO-j+-Widw@mail.gmail.com
Backpatch-through: 15
---
.../libpqwalreceiver/libpqwalreceiver.c | 43 +++++++++++++++----
1 file changed, 34 insertions(+), 9 deletions(-)
diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
index 5ddc9e812e7..c067908da35 100644
--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
+++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
@@ -65,6 +65,8 @@ static void libpqrcv_get_senderinfo(WalReceiverConn *conn,
static char *libpqrcv_identify_system(WalReceiverConn *conn,
TimeLineID *primary_tli);
static char *libpqrcv_get_dbname_from_conninfo(const char *connInfo);
+static char *libpqrcv_get_option_from_conninfo(const char *connInfo,
+ const char *keyword);
static int libpqrcv_server_version(WalReceiverConn *conn);
static void libpqrcv_readtimelinehistoryfile(WalReceiverConn *conn,
TimeLineID tli, char **filename,
@@ -150,6 +152,7 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
const char *keys[6];
const char *vals[6];
int i = 0;
+ char *options_val = NULL;
/*
* Re-validate connection string. The validation already happened at DDL
@@ -177,6 +180,8 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
if (logical)
{
+ char *opt = NULL;
+
/* Tell the publisher to translate to our encoding */
keys[++i] = "client_encoding";
vals[i] = GetDatabaseEncodingName();
@@ -189,8 +194,13 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
* running in the subscriber, such as triggers.) This should
* match what pg_dump does.
*/
+ opt = libpqrcv_get_option_from_conninfo(conninfo, "options");
+ options_val = psprintf("%s -c datestyle=ISO -c intervalstyle=postgres -c extra_float_digits=3",
+ (opt == NULL) ? "" : opt);
keys[++i] = "options";
- vals[i] = "-c datestyle=ISO -c intervalstyle=postgres -c extra_float_digits=3";
+ vals[i] = options_val;
+ if (opt != NULL)
+ pfree(opt);
}
else
{
@@ -217,6 +227,9 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
/* expand_dbname = */ true,
WAIT_EVENT_LIBPQWALRECEIVER_CONNECT);
+ if (options_val != NULL)
+ pfree(options_val);
+
if (PQstatus(conn->streamConn) != CONNECTION_OK)
goto bad_connection_errmsg;
@@ -460,9 +473,21 @@ libpqrcv_server_version(WalReceiverConn *conn)
*/
static char *
libpqrcv_get_dbname_from_conninfo(const char *connInfo)
+{
+ return libpqrcv_get_option_from_conninfo(connInfo, "dbname");
+}
+
+/*
+ * Get the value of the option with the given keyword from the primary
+ * server's conninfo.
+ *
+ * If the option is not found in connInfo, return NULL value.
+ */
+static char *
+libpqrcv_get_option_from_conninfo(const char *connInfo, const char *keyword)
{
PQconninfoOption *opts;
- char *dbname = NULL;
+ char *option = NULL;
char *err = NULL;
opts = PQconninfoParse(connInfo, &err);
@@ -480,21 +505,21 @@ libpqrcv_get_dbname_from_conninfo(const char *connInfo)
for (PQconninfoOption *opt = opts; opt->keyword != NULL; ++opt)
{
/*
- * If multiple dbnames are specified, then the last one will be
- * returned
+ * If the same option appears multiple times, then the last one will
+ * be returned
*/
- if (strcmp(opt->keyword, "dbname") == 0 && opt->val &&
+ if (strcmp(opt->keyword, keyword) == 0 && opt->val &&
*opt->val)
{
- if (dbname)
- pfree(dbname);
+ if (option)
+ pfree(option);
- dbname = pstrdup(opt->val);
+ option = pstrdup(opt->val);
}
}
PQconninfoFree(opts);
- return dbname;
+ return option;
}
/*
--
2.51.2
^ permalink raw reply [nested|flat] 37+ messages in thread
* Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect
@ 2025-12-19 10:07 Japin Li <[email protected]>
parent: Fujii Masao <[email protected]>
1 sibling, 1 reply; 37+ messages in thread
From: Japin Li @ 2025-12-19 10:07 UTC (permalink / raw)
To: Fujii Masao <[email protected]>; +Cc: Amit Kapila <[email protected]>; PostgreSQL Hackers <[email protected]>
On Fri, 19 Dec 2025 at 16:55, Fujii Masao <[email protected]> wrote:
> On Wed, Dec 3, 2025 at 2:45 PM Amit Kapila <[email protected]> wrote:
>>
>> On Tue, Dec 2, 2025 at 8:30 PM Fujii Masao <[email protected]> wrote:
>> >
>> > On Tue, Dec 2, 2025 at 9:08 PM Amit Kapila <[email protected]> wrote:
>> > > Is it possible that we append the predefined options to the options
>> > > given by the user to avoid extra round-trip?
>> >
>> > One idea is to add a function, similar to libpqrcv_get_dbname_from_conninfo()
>> > in libpqwalreceiver.c, that extracts the options string from the conninfo,
>> > to append the required fixed settings, and then to use the combined string as
>> > the value of the options parameter.
>> >
>>
>> Yes, but libpqrcv_get_dbname_from_conninfo() is an exposed function,
>> we can implement something internal for libpqwalreceiver.c like
>> conninfo_add_defaults() present in fe-connect.c.
>>
>> > Do you think implementing this is worthwhile
>> > to avoid the extra round trip?
>> >
>>
>> I think so. Today, we have three variables, tomorrow there could be
>> more such variables as well and apart from avoiding extra round trips,
>> the idea to append options to provided options (if any) sounds more
>> logical to me.
>
> OK, I've implemented the idea discussed upthread. The patch updates
> libpqrcv_connect() so that, for logical replication, it extracts the options
> string from the conninfo, appends the required fixed settings, and passes
> the combined string as the options parameter to libpq.
>
> For example, if the conninfo specifies -c wal_sender_timeout=10s,
> the resulting options value becomes:
>
> -c wal_sender_timeout=10s -c datestyle=ISO -c
> intervalstyle=postgres -c extra_float_digits=3.
>
> Patch attached.
Thanks for the patch — that was my oversight.
LGTM with one small suggestion:
The comment says: "If the option is not found in connInfo, return NULL value."
Since the parameter is named `keyword`, I'd suggest: "If the keyword is not found in connInfo, return NULL."
This keeps terminology consistent with the function signature.
--
Regards,
Japin Li
ChengDu WenWu Information Technology Co., Ltd.
^ permalink raw reply [nested|flat] 37+ messages in thread
* Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect
@ 2025-12-19 11:05 Fujii Masao <[email protected]>
parent: Japin Li <[email protected]>
0 siblings, 2 replies; 37+ messages in thread
From: Fujii Masao @ 2025-12-19 11:05 UTC (permalink / raw)
To: Japin Li <[email protected]>; +Cc: Amit Kapila <[email protected]>; PostgreSQL Hackers <[email protected]>
On Fri, Dec 19, 2025 at 7:07 PM Japin Li <[email protected]> wrote:
> Thanks for the patch — that was my oversight.
>
> LGTM with one small suggestion:
Thanks for the review!
> The comment says: "If the option is not found in connInfo, return NULL value."
>
> Since the parameter is named `keyword`, I'd suggest: "If the keyword is not found in connInfo, return NULL."
>
> This keeps terminology consistent with the function signature.
I think "the option with the given keyword" is more precise than just
"the keyword".
That said, simply using "the option" also seems sufficient in this context...
Regarding 0002 patch, I found that it caused a CI failure, so I’ve updated
the patch to fix that. The revised patch is attached.
Regards,
--
Fujii Masao
From a29e80e158b043a76f00383705ee9c27f3f864a5 Mon Sep 17 00:00:00 2001
From: Fujii Masao <[email protected]>
Date: Wed, 3 Dec 2025 00:59:09 +0900
Subject: [PATCH v6 1/2] Honor GUC settings specified in CREATE SUBSCRIPTION
CONNECTION.
Prior to v15, GUC settings supplied in the CONNECTION clause of
CREATE SUBSCRIPTION were correctly passed through to
the publisher's walsender. For example:
CREATE SUBSCRIPTION mysub
CONNECTION 'options=''-c wal_sender_timeout=1000'''
PUBLICATION ...
would cause wal_sender_timeout to take effect on the publisher's walsender.
However, commit f3d4019da5d changed the way logical replication
connections are established, forcing the publisher's relevant
GUC settings (datestyle, intervalstyle, extra_float_digits) to
override those provided in the CONNECTION string. As a result,
from v15 through v18, GUC settings in the CONNECTION string were
always ignored.
This regression prevented per-connection tuning of logical replication.
For example, using a shorter timeout for walsender connecting
to a nearby subscriber and a longer one for walsender connecting
to a remote subscriber.
This commit restores the intended behavior by ensuring that
GUC settings in the CONNECTION string are again passed through
and applied by the walsender, allowing per-connection configuration.
Backpatch to v15, where the regression was introduced.
Author: Fujii Masao <[email protected]>
Reviewed-by: Chao Li <[email protected]>
Reviewed-by: Kirill Reshke <[email protected]>
Reviewed-by: Amit Kapila <[email protected]>
Reviewed-by: Japin Li <[email protected]>
Discussion: https://postgr.es/m/CAHGQGwGYV+-abbKwdrM2UHUe-JYOFWmsrs6=QicyJO-j+-Widw@mail.gmail.com
Backpatch-through: 15
---
.../libpqwalreceiver/libpqwalreceiver.c | 61 ++++++++++++++++++-
1 file changed, 60 insertions(+), 1 deletion(-)
diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
index 568024ec974..743f951f330 100644
--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
+++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
@@ -57,6 +57,8 @@ static void libpqrcv_get_senderinfo(WalReceiverConn *conn,
char **sender_host, int *sender_port);
static char *libpqrcv_identify_system(WalReceiverConn *conn,
TimeLineID *primary_tli);
+static char *libpqrcv_get_option_from_conninfo(const char *connInfo,
+ const char *keyword);
static int libpqrcv_server_version(WalReceiverConn *conn);
static void libpqrcv_readtimelinehistoryfile(WalReceiverConn *conn,
TimeLineID tli, char **filename,
@@ -136,6 +138,7 @@ libpqrcv_connect(const char *conninfo, bool logical, bool must_use_password,
const char *keys[6];
const char *vals[6];
int i = 0;
+ char *options_val = NULL;
/*
* Re-validate connection string. The validation already happened at DDL
@@ -167,6 +170,8 @@ libpqrcv_connect(const char *conninfo, bool logical, bool must_use_password,
vals[i] = appname;
if (logical)
{
+ char *opt = NULL;
+
/* Tell the publisher to translate to our encoding */
keys[++i] = "client_encoding";
vals[i] = GetDatabaseEncodingName();
@@ -179,8 +184,13 @@ libpqrcv_connect(const char *conninfo, bool logical, bool must_use_password,
* the subscriber, such as triggers.) This should match what pg_dump
* does.
*/
+ opt = libpqrcv_get_option_from_conninfo(conninfo, "options");
+ options_val = psprintf("%s -c datestyle=ISO -c intervalstyle=postgres -c extra_float_digits=3",
+ (opt == NULL) ? "" : opt);
keys[++i] = "options";
- vals[i] = "-c datestyle=ISO -c intervalstyle=postgres -c extra_float_digits=3";
+ vals[i] = options_val;
+ if (opt != NULL)
+ pfree(opt);
}
keys[++i] = NULL;
vals[i] = NULL;
@@ -232,6 +242,9 @@ libpqrcv_connect(const char *conninfo, bool logical, bool must_use_password,
status = PQconnectPoll(conn->streamConn);
} while (status != PGRES_POLLING_OK && status != PGRES_POLLING_FAILED);
+ if (options_val != NULL)
+ pfree(options_val);
+
if (PQstatus(conn->streamConn) != CONNECTION_OK)
goto bad_connection_errmsg;
@@ -434,6 +447,7 @@ libpqrcv_identify_system(WalReceiverConn *conn, TimeLineID *primary_tli)
"the primary server: %s",
pchomp(PQerrorMessage(conn->streamConn)))));
}
+
/*
* IDENTIFY_SYSTEM returns 3 columns in 9.3 and earlier, and 4 columns in
* 9.4 and onwards.
@@ -466,6 +480,51 @@ libpqrcv_server_version(WalReceiverConn *conn)
return PQserverVersion(conn->streamConn);
}
+/*
+ * Get the value of the option with the given keyword from the primary
+ * server's conninfo.
+ *
+ * If the option is not found in connInfo, return NULL value.
+ */
+static char *
+libpqrcv_get_option_from_conninfo(const char *connInfo, const char *keyword)
+{
+ PQconninfoOption *opts;
+ char *option = NULL;
+ char *err = NULL;
+
+ opts = PQconninfoParse(connInfo, &err);
+ if (opts == NULL)
+ {
+ /* The error string is malloc'd, so we must free it explicitly */
+ char *errcopy = err ? pstrdup(err) : "out of memory";
+
+ PQfreemem(err);
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("invalid connection string syntax: %s", errcopy)));
+ }
+
+ for (PQconninfoOption *opt = opts; opt->keyword != NULL; ++opt)
+ {
+ /*
+ * If the same option appears multiple times, then the last one will
+ * be returned
+ */
+ if (strcmp(opt->keyword, keyword) == 0 && opt->val &&
+ *opt->val)
+ {
+ if (option)
+ pfree(option);
+
+ option = pstrdup(opt->val);
+ }
+ }
+
+ PQconninfoFree(opts);
+ return option;
+}
+
/*
* Start streaming WAL data from given streaming options.
*
--
2.51.2
Attachments:
[text/plain] v6-0001-PG15-PG16-Honor-GUC-settings-specified-in-CREATE-SUBSCRIPTI.txt (5.6K, ../../CAHGQGwFQZoKd-d3WjODmEgemPqPmehGdRiTQx7pez2R9_UKCQg@mail.gmail.com/2-v6-0001-PG15-PG16-Honor-GUC-settings-specified-in-CREATE-SUBSCRIPTI.txt)
download | inline diff:
From a29e80e158b043a76f00383705ee9c27f3f864a5 Mon Sep 17 00:00:00 2001
From: Fujii Masao <[email protected]>
Date: Wed, 3 Dec 2025 00:59:09 +0900
Subject: [PATCH v6 1/2] Honor GUC settings specified in CREATE SUBSCRIPTION
CONNECTION.
Prior to v15, GUC settings supplied in the CONNECTION clause of
CREATE SUBSCRIPTION were correctly passed through to
the publisher's walsender. For example:
CREATE SUBSCRIPTION mysub
CONNECTION 'options=''-c wal_sender_timeout=1000'''
PUBLICATION ...
would cause wal_sender_timeout to take effect on the publisher's walsender.
However, commit f3d4019da5d changed the way logical replication
connections are established, forcing the publisher's relevant
GUC settings (datestyle, intervalstyle, extra_float_digits) to
override those provided in the CONNECTION string. As a result,
from v15 through v18, GUC settings in the CONNECTION string were
always ignored.
This regression prevented per-connection tuning of logical replication.
For example, using a shorter timeout for walsender connecting
to a nearby subscriber and a longer one for walsender connecting
to a remote subscriber.
This commit restores the intended behavior by ensuring that
GUC settings in the CONNECTION string are again passed through
and applied by the walsender, allowing per-connection configuration.
Backpatch to v15, where the regression was introduced.
Author: Fujii Masao <[email protected]>
Reviewed-by: Chao Li <[email protected]>
Reviewed-by: Kirill Reshke <[email protected]>
Reviewed-by: Amit Kapila <[email protected]>
Reviewed-by: Japin Li <[email protected]>
Discussion: https://postgr.es/m/CAHGQGwGYV+-abbKwdrM2UHUe-JYOFWmsrs6=QicyJO-j+-Widw@mail.gmail.com
Backpatch-through: 15
---
.../libpqwalreceiver/libpqwalreceiver.c | 61 ++++++++++++++++++-
1 file changed, 60 insertions(+), 1 deletion(-)
diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
index 568024ec974..743f951f330 100644
--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
+++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
@@ -57,6 +57,8 @@ static void libpqrcv_get_senderinfo(WalReceiverConn *conn,
char **sender_host, int *sender_port);
static char *libpqrcv_identify_system(WalReceiverConn *conn,
TimeLineID *primary_tli);
+static char *libpqrcv_get_option_from_conninfo(const char *connInfo,
+ const char *keyword);
static int libpqrcv_server_version(WalReceiverConn *conn);
static void libpqrcv_readtimelinehistoryfile(WalReceiverConn *conn,
TimeLineID tli, char **filename,
@@ -136,6 +138,7 @@ libpqrcv_connect(const char *conninfo, bool logical, bool must_use_password,
const char *keys[6];
const char *vals[6];
int i = 0;
+ char *options_val = NULL;
/*
* Re-validate connection string. The validation already happened at DDL
@@ -167,6 +170,8 @@ libpqrcv_connect(const char *conninfo, bool logical, bool must_use_password,
vals[i] = appname;
if (logical)
{
+ char *opt = NULL;
+
/* Tell the publisher to translate to our encoding */
keys[++i] = "client_encoding";
vals[i] = GetDatabaseEncodingName();
@@ -179,8 +184,13 @@ libpqrcv_connect(const char *conninfo, bool logical, bool must_use_password,
* the subscriber, such as triggers.) This should match what pg_dump
* does.
*/
+ opt = libpqrcv_get_option_from_conninfo(conninfo, "options");
+ options_val = psprintf("%s -c datestyle=ISO -c intervalstyle=postgres -c extra_float_digits=3",
+ (opt == NULL) ? "" : opt);
keys[++i] = "options";
- vals[i] = "-c datestyle=ISO -c intervalstyle=postgres -c extra_float_digits=3";
+ vals[i] = options_val;
+ if (opt != NULL)
+ pfree(opt);
}
keys[++i] = NULL;
vals[i] = NULL;
@@ -232,6 +242,9 @@ libpqrcv_connect(const char *conninfo, bool logical, bool must_use_password,
status = PQconnectPoll(conn->streamConn);
} while (status != PGRES_POLLING_OK && status != PGRES_POLLING_FAILED);
+ if (options_val != NULL)
+ pfree(options_val);
+
if (PQstatus(conn->streamConn) != CONNECTION_OK)
goto bad_connection_errmsg;
@@ -434,6 +447,7 @@ libpqrcv_identify_system(WalReceiverConn *conn, TimeLineID *primary_tli)
"the primary server: %s",
pchomp(PQerrorMessage(conn->streamConn)))));
}
+
/*
* IDENTIFY_SYSTEM returns 3 columns in 9.3 and earlier, and 4 columns in
* 9.4 and onwards.
@@ -466,6 +480,51 @@ libpqrcv_server_version(WalReceiverConn *conn)
return PQserverVersion(conn->streamConn);
}
+/*
+ * Get the value of the option with the given keyword from the primary
+ * server's conninfo.
+ *
+ * If the option is not found in connInfo, return NULL value.
+ */
+static char *
+libpqrcv_get_option_from_conninfo(const char *connInfo, const char *keyword)
+{
+ PQconninfoOption *opts;
+ char *option = NULL;
+ char *err = NULL;
+
+ opts = PQconninfoParse(connInfo, &err);
+ if (opts == NULL)
+ {
+ /* The error string is malloc'd, so we must free it explicitly */
+ char *errcopy = err ? pstrdup(err) : "out of memory";
+
+ PQfreemem(err);
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("invalid connection string syntax: %s", errcopy)));
+ }
+
+ for (PQconninfoOption *opt = opts; opt->keyword != NULL; ++opt)
+ {
+ /*
+ * If the same option appears multiple times, then the last one will
+ * be returned
+ */
+ if (strcmp(opt->keyword, keyword) == 0 && opt->val &&
+ *opt->val)
+ {
+ if (option)
+ pfree(option);
+
+ option = pstrdup(opt->val);
+ }
+ }
+
+ PQconninfoFree(opts);
+ return option;
+}
+
/*
* Start streaming WAL data from given streaming options.
*
--
2.51.2
[application/octet-stream] v6-0002-Add-TAP-test-for-GUC-settings-passed-via-CONNECTI.patch (3.1K, ../../CAHGQGwFQZoKd-d3WjODmEgemPqPmehGdRiTQx7pez2R9_UKCQg@mail.gmail.com/3-v6-0002-Add-TAP-test-for-GUC-settings-passed-via-CONNECTI.patch)
download | inline diff:
From 0e49936016a81eccf095cf710aa6c5ea1ca761cf Mon Sep 17 00:00:00 2001
From: Fujii Masao <[email protected]>
Date: Thu, 27 Nov 2025 12:36:59 +0900
Subject: [PATCH v6 2/2] Add TAP test for GUC settings passed via CONNECTION in
logical replication.
This commit adds a TAP test to verify that GUC settings provided in
the CONNECTION string of CREATE/ALTER SUBSCRIPTION are correctly
passed through to and applied by the publisher's walsender.
---
src/test/subscription/t/001_rep_changes.pl | 29 +++++++++++++++++++++-
1 file changed, 28 insertions(+), 1 deletion(-)
diff --git a/src/test/subscription/t/001_rep_changes.pl b/src/test/subscription/t/001_rep_changes.pl
index 430c1246d14..9db7e8219de 100644
--- a/src/test/subscription/t/001_rep_changes.pl
+++ b/src/test/subscription/t/001_rep_changes.pl
@@ -438,17 +438,34 @@ is( $result, qq(11.11|baz|1
22.22|bar|2),
'update works with dropped subscriber column');
+# Verify that GUC settings supplied in the CONNECTION string take effect on
+# the publisher's walsender. We do this by enabling log_statement_stats in
+# the CONNECTION string later and checking that the publisher's log contains a
+# QUERY STATISTICS message.
+#
+# First, confirm that no such QUERY STATISTICS message appears before enabling
+# log_statement_stats.
+$logfile = slurp_file($node_publisher->logfile, $log_location);
+unlike(
+ $logfile,
+ qr/QUERY STATISTICS/,
+ 'log_statement_stats has not been enabled yet');
+
# check that change of connection string and/or publication list causes
# restart of subscription workers. We check the state along with
# application_name to ensure that the walsender is (re)started.
#
# Not all of these are registered as tests as we need to poll for a change
# but the test suite will fail nonetheless when something goes wrong.
+#
+# Enable log_statement_stats as the change of connection string,
+# which is also for the above mentioned test of GUC settings passed through
+# CONNECTION.
my $oldpid = $node_publisher->safe_psql('postgres',
"SELECT pid FROM pg_stat_replication WHERE application_name = 'tap_sub' AND state = 'streaming';"
);
$node_subscriber->safe_psql('postgres',
- "ALTER SUBSCRIPTION tap_sub CONNECTION '$publisher_connstr sslmode=disable'"
+ "ALTER SUBSCRIPTION tap_sub CONNECTION '$publisher_connstr options=''-c log_statement_stats=on'''"
);
$node_publisher->poll_query_until('postgres',
"SELECT pid != $oldpid FROM pg_stat_replication WHERE application_name = 'tap_sub' AND state = 'streaming';"
@@ -552,6 +569,16 @@ $node_publisher->poll_query_until('postgres',
or die
"Timed out while waiting for apply to restart after renaming SUBSCRIPTION";
+# Check that the expected QUERY STATISTICS message appears,
+# which shows that log_statement_stats=on from the CONNECTION string
+# was correctly passed through to and honored by the walsender.
+$logfile = slurp_file($node_publisher->logfile, $log_location);
+like(
+ $logfile,
+ qr/QUERY STATISTICS/,
+ 'log_statement_stats in CONNECTION string had effect on publisher\'s walsender'
+);
+
# check all the cleanup
$node_subscriber->safe_psql('postgres', "DROP SUBSCRIPTION tap_sub_renamed");
--
2.51.2
[application/octet-stream] v6-0001-Honor-GUC-settings-specified-in-CREATE-SUBSCRIPTI.patch (5.4K, ../../CAHGQGwFQZoKd-d3WjODmEgemPqPmehGdRiTQx7pez2R9_UKCQg@mail.gmail.com/4-v6-0001-Honor-GUC-settings-specified-in-CREATE-SUBSCRIPTI.patch)
download | inline diff:
From ca378d99f617b4418261fce74e4f5ff84570a7e7 Mon Sep 17 00:00:00 2001
From: Fujii Masao <[email protected]>
Date: Wed, 3 Dec 2025 00:59:09 +0900
Subject: [PATCH v6 1/2] Honor GUC settings specified in CREATE SUBSCRIPTION
CONNECTION.
Prior to v15, GUC settings supplied in the CONNECTION clause of
CREATE SUBSCRIPTION were correctly passed through to
the publisher's walsender. For example:
CREATE SUBSCRIPTION mysub
CONNECTION 'options=''-c wal_sender_timeout=1000'''
PUBLICATION ...
would cause wal_sender_timeout to take effect on the publisher's walsender.
However, commit f3d4019da5d changed the way logical replication
connections are established, forcing the publisher's relevant
GUC settings (datestyle, intervalstyle, extra_float_digits) to
override those provided in the CONNECTION string. As a result,
from v15 through v18, GUC settings in the CONNECTION string were
always ignored.
This regression prevented per-connection tuning of logical replication.
For example, using a shorter timeout for walsender connecting
to a nearby subscriber and a longer one for walsender connecting
to a remote subscriber.
This commit restores the intended behavior by ensuring that
GUC settings in the CONNECTION string are again passed through
and applied by the walsender, allowing per-connection configuration.
Backpatch to v15, where the regression was introduced.
Author: Fujii Masao <[email protected]>
Reviewed-by: Chao Li <[email protected]>
Reviewed-by: Kirill Reshke <[email protected]>
Reviewed-by: Amit Kapila <[email protected]>
Reviewed-by: Japin Li <[email protected]>
Discussion: https://postgr.es/m/CAHGQGwGYV+-abbKwdrM2UHUe-JYOFWmsrs6=QicyJO-j+-Widw@mail.gmail.com
Backpatch-through: 15
---
.../libpqwalreceiver/libpqwalreceiver.c | 43 +++++++++++++++----
1 file changed, 34 insertions(+), 9 deletions(-)
diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
index 5ddc9e812e7..c067908da35 100644
--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
+++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
@@ -65,6 +65,8 @@ static void libpqrcv_get_senderinfo(WalReceiverConn *conn,
static char *libpqrcv_identify_system(WalReceiverConn *conn,
TimeLineID *primary_tli);
static char *libpqrcv_get_dbname_from_conninfo(const char *connInfo);
+static char *libpqrcv_get_option_from_conninfo(const char *connInfo,
+ const char *keyword);
static int libpqrcv_server_version(WalReceiverConn *conn);
static void libpqrcv_readtimelinehistoryfile(WalReceiverConn *conn,
TimeLineID tli, char **filename,
@@ -150,6 +152,7 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
const char *keys[6];
const char *vals[6];
int i = 0;
+ char *options_val = NULL;
/*
* Re-validate connection string. The validation already happened at DDL
@@ -177,6 +180,8 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
if (logical)
{
+ char *opt = NULL;
+
/* Tell the publisher to translate to our encoding */
keys[++i] = "client_encoding";
vals[i] = GetDatabaseEncodingName();
@@ -189,8 +194,13 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
* running in the subscriber, such as triggers.) This should
* match what pg_dump does.
*/
+ opt = libpqrcv_get_option_from_conninfo(conninfo, "options");
+ options_val = psprintf("%s -c datestyle=ISO -c intervalstyle=postgres -c extra_float_digits=3",
+ (opt == NULL) ? "" : opt);
keys[++i] = "options";
- vals[i] = "-c datestyle=ISO -c intervalstyle=postgres -c extra_float_digits=3";
+ vals[i] = options_val;
+ if (opt != NULL)
+ pfree(opt);
}
else
{
@@ -217,6 +227,9 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
/* expand_dbname = */ true,
WAIT_EVENT_LIBPQWALRECEIVER_CONNECT);
+ if (options_val != NULL)
+ pfree(options_val);
+
if (PQstatus(conn->streamConn) != CONNECTION_OK)
goto bad_connection_errmsg;
@@ -460,9 +473,21 @@ libpqrcv_server_version(WalReceiverConn *conn)
*/
static char *
libpqrcv_get_dbname_from_conninfo(const char *connInfo)
+{
+ return libpqrcv_get_option_from_conninfo(connInfo, "dbname");
+}
+
+/*
+ * Get the value of the option with the given keyword from the primary
+ * server's conninfo.
+ *
+ * If the option is not found in connInfo, return NULL value.
+ */
+static char *
+libpqrcv_get_option_from_conninfo(const char *connInfo, const char *keyword)
{
PQconninfoOption *opts;
- char *dbname = NULL;
+ char *option = NULL;
char *err = NULL;
opts = PQconninfoParse(connInfo, &err);
@@ -480,21 +505,21 @@ libpqrcv_get_dbname_from_conninfo(const char *connInfo)
for (PQconninfoOption *opt = opts; opt->keyword != NULL; ++opt)
{
/*
- * If multiple dbnames are specified, then the last one will be
- * returned
+ * If the same option appears multiple times, then the last one will
+ * be returned
*/
- if (strcmp(opt->keyword, "dbname") == 0 && opt->val &&
+ if (strcmp(opt->keyword, keyword) == 0 && opt->val &&
*opt->val)
{
- if (dbname)
- pfree(dbname);
+ if (option)
+ pfree(option);
- dbname = pstrdup(opt->val);
+ option = pstrdup(opt->val);
}
}
PQconninfoFree(opts);
- return dbname;
+ return option;
}
/*
--
2.51.2
^ permalink raw reply [nested|flat] 37+ messages in thread
* Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect
@ 2025-12-19 12:30 Kirill Reshke <[email protected]>
parent: Fujii Masao <[email protected]>
1 sibling, 1 reply; 37+ messages in thread
From: Kirill Reshke @ 2025-12-19 12:30 UTC (permalink / raw)
To: Fujii Masao <[email protected]>; +Cc: Japin Li <[email protected]>; Amit Kapila <[email protected]>; PostgreSQL Hackers <[email protected]>
On Fri, 19 Dec 2025 at 16:05, Fujii Masao <[email protected]> wrote:
>
> On Fri, Dec 19, 2025 at 7:07 PM Japin Li <[email protected]> wrote:
> > Thanks for the patch — that was my oversight.
> >
> > LGTM with one small suggestion:
>
> Thanks for the review!
>
> > The comment says: "If the option is not found in connInfo, return NULL value."
> >
> > Since the parameter is named `keyword`, I'd suggest: "If the keyword is not found in connInfo, return NULL."
> >
> > This keeps terminology consistent with the function signature.
>
> I think "the option with the given keyword" is more precise than just
> "the keyword".
> That said, simply using "the option" also seems sufficient in this context...
>
>
> Regarding 0002 patch, I found that it caused a CI failure, so I’ve updated
> the patch to fix that. The revised patch is attached.
>
> Regards,
>
> --
> Fujii Masao
Hi!
I checked the new TAP test 0002 changes. I am wondering, why are
connection options validated so late in this test? I mean, we do
ALTER PUBLICATION, then we restart publisher, wait for catchup, check
alter publication, and etc, and only then we look if connection
options are indeed applied?
--
Best regards,
Kirill Reshke
^ permalink raw reply [nested|flat] 37+ messages in thread
* Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect
@ 2025-12-19 14:42 Fujii Masao <[email protected]>
parent: Kirill Reshke <[email protected]>
0 siblings, 1 reply; 37+ messages in thread
From: Fujii Masao @ 2025-12-19 14:42 UTC (permalink / raw)
To: Kirill Reshke <[email protected]>; +Cc: Japin Li <[email protected]>; Amit Kapila <[email protected]>; PostgreSQL Hackers <[email protected]>
On Fri, Dec 19, 2025 at 9:30 PM Kirill Reshke <[email protected]> wrote:
> I checked the new TAP test 0002 changes. I am wondering, why are
> connection options validated so late in this test? I mean, we do
> ALTER PUBLICATION, then we restart publisher, wait for catchup, check
> alter publication, and etc, and only then we look if connection
> options are indeed applied?
Are you suggesting testing whether the conninfo setting is applied earlier,
for example, right after both running ALTER SUBSCRIPTION CONNECTION and
confirming that the logical replication connection is re-established?
Yeah, that might be better and would also make the test easier to read.
Regards,
--
Fujii Masao
^ permalink raw reply [nested|flat] 37+ messages in thread
* Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect
@ 2025-12-19 15:48 Kirill Reshke <[email protected]>
parent: Fujii Masao <[email protected]>
0 siblings, 1 reply; 37+ messages in thread
From: Kirill Reshke @ 2025-12-19 15:48 UTC (permalink / raw)
To: Fujii Masao <[email protected]>; +Cc: Japin Li <[email protected]>; Amit Kapila <[email protected]>; PostgreSQL Hackers <[email protected]>
On Fri, 19 Dec 2025 at 19:42, Fujii Masao <[email protected]> wrote:
>
> On Fri, Dec 19, 2025 at 9:30 PM Kirill Reshke <[email protected]> wrote:
> > I checked the new TAP test 0002 changes. I am wondering, why are
> > connection options validated so late in this test? I mean, we do
> > ALTER PUBLICATION, then we restart publisher, wait for catchup, check
> > alter publication, and etc, and only then we look if connection
> > options are indeed applied?
>
> Are you suggesting testing whether the conninfo setting is applied earlier,
> for example, right after both running ALTER SUBSCRIPTION CONNECTION and
> confirming that the logical replication connection is re-established?
> Yeah, that might be better and would also make the test easier to read.
>
> Regards,
>
> --
> Fujii Masao
Yes, exactly
--
Best regards,
Kirill Reshke
^ permalink raw reply [nested|flat] 37+ messages in thread
* Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect
@ 2025-12-23 05:05 Amit Kapila <[email protected]>
parent: Fujii Masao <[email protected]>
1 sibling, 1 reply; 37+ messages in thread
From: Amit Kapila @ 2025-12-23 05:05 UTC (permalink / raw)
To: Fujii Masao <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>
On Fri, Dec 19, 2025 at 1:25 PM Fujii Masao <[email protected]> wrote:
>
> On Wed, Dec 3, 2025 at 2:45 PM Amit Kapila <[email protected]> wrote:
> >
> > On Tue, Dec 2, 2025 at 8:30 PM Fujii Masao <[email protected]> wrote:
> > >
> > > On Tue, Dec 2, 2025 at 9:08 PM Amit Kapila <[email protected]> wrote:
> > > > Is it possible that we append the predefined options to the options
> > > > given by the user to avoid extra round-trip?
> > >
> > > One idea is to add a function, similar to libpqrcv_get_dbname_from_conninfo()
> > > in libpqwalreceiver.c, that extracts the options string from the conninfo,
> > > to append the required fixed settings, and then to use the combined string as
> > > the value of the options parameter.
> > >
> >
> > Yes, but libpqrcv_get_dbname_from_conninfo() is an exposed function,
> > we can implement something internal for libpqwalreceiver.c like
> > conninfo_add_defaults() present in fe-connect.c.
> >
> > > Do you think implementing this is worthwhile
> > > to avoid the extra round trip?
> > >
> >
> > I think so. Today, we have three variables, tomorrow there could be
> > more such variables as well and apart from avoiding extra round trips,
> > the idea to append options to provided options (if any) sounds more
> > logical to me.
>
> OK, I've implemented the idea discussed upthread. The patch updates
> libpqrcv_connect() so that, for logical replication, it extracts the options
> string from the conninfo, appends the required fixed settings, and passes
> the combined string as the options parameter to libpq.
>
> For example, if the conninfo specifies -c wal_sender_timeout=10s,
> the resulting options value becomes:
>
> -c wal_sender_timeout=10s -c datestyle=ISO -c
> intervalstyle=postgres -c extra_float_digits=3.
>
> Patch attached.
>
Thanks, the idea looks good now. One minor comment:
}
+
/*
This appears to be an unnecessary addition in the patch.
--
With Regards,
Amit Kapila.
^ permalink raw reply [nested|flat] 37+ messages in thread
* Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect
@ 2025-12-23 06:17 Chao Li <[email protected]>
parent: Fujii Masao <[email protected]>
1 sibling, 1 reply; 37+ messages in thread
From: Chao Li @ 2025-12-23 06:17 UTC (permalink / raw)
To: Fujii Masao <[email protected]>; +Cc: Japin Li <[email protected]>; Amit Kapila <[email protected]>; PostgreSQL Hackers <[email protected]>
> On Dec 19, 2025, at 19:05, Fujii Masao <[email protected]> wrote:
>
> On Fri, Dec 19, 2025 at 7:07 PM Japin Li <[email protected]> wrote:
>> Thanks for the patch — that was my oversight.
>>
>> LGTM with one small suggestion:
>
> Thanks for the review!
>
>> The comment says: "If the option is not found in connInfo, return NULL value."
>>
>> Since the parameter is named `keyword`, I'd suggest: "If the keyword is not found in connInfo, return NULL."
>>
>> This keeps terminology consistent with the function signature.
>
> I think "the option with the given keyword" is more precise than just
> "the keyword".
> That said, simply using "the option" also seems sufficient in this context...
>
>
> Regarding 0002 patch, I found that it caused a CI failure, so I’ve updated
> the patch to fix that. The revised patch is attached.
>
> Regards,
>
> --
> Fujii Masao
> <v6-0001-PG15-PG16-Honor-GUC-settings-specified-in-CREATE-SUBSCRIPTI.txt><v6-0002-Add-TAP-test-for-GUC-settings-passed-via-CONNECTI.patch><v6-0001-Honor-GUC-settings-specified-in-CREATE-SUBSCRIPTI.patch>
A few more comments on v6:
1 - 0001
```
+ if (opt != NULL)
+ pfree(opt);
```
From what I learned from previous reviews, pfree() is safe to handle NULL, we can omit the NULL check, which makes the code simpler. This comment applies to multiple places.
2. I still think we should verify options extracted from conninfo. In the 0002’s tap script, if I make the following change:
```
$node_subscriber->safe_psql('postgres',
- "ALTER SUBSCRIPTION tap_sub CONNECTION '$publisher_connstr options=''-c log_statement_stats=on'''"
+ "ALTER SUBSCRIPTION tap_sub CONNECTION '$publisher_connstr options=''-c log_statement_stats=on-c wal_sender_timeout=1000'’'"
```
Notice, there is no space between the second “-c” and “on”, meaning that a user passes an invalid options. Then the test will get stuck forever, which would never happen before this patch.
Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/
^ permalink raw reply [nested|flat] 37+ messages in thread
* Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect
@ 2025-12-23 08:13 Japin Li <[email protected]>
parent: Chao Li <[email protected]>
0 siblings, 1 reply; 37+ messages in thread
From: Japin Li @ 2025-12-23 08:13 UTC (permalink / raw)
To: Chao Li <[email protected]>; +Cc: Fujii Masao <[email protected]>; Amit Kapila <[email protected]>; PostgreSQL Hackers <[email protected]>
On Tue, 23 Dec 2025 at 14:17, Chao Li <[email protected]> wrote:
>> On Dec 19, 2025, at 19:05, Fujii Masao <[email protected]> wrote:
>>
>> On Fri, Dec 19, 2025 at 7:07 PM Japin Li <[email protected]> wrote:
>>> Thanks for the patch — that was my oversight.
>>>
>>> LGTM with one small suggestion:
>>
>> Thanks for the review!
>>
>>> The comment says: "If the option is not found in connInfo, return NULL value."
>>>
>>> Since the parameter is named `keyword`, I'd suggest: "If the keyword is not found in connInfo, return NULL."
>>>
>>> This keeps terminology consistent with the function signature.
>>
>> I think "the option with the given keyword" is more precise than just
>> "the keyword".
>> That said, simply using "the option" also seems sufficient in this context...
>>
>>
>> Regarding 0002 patch, I found that it caused a CI failure, so I’ve updated
>> the patch to fix that. The revised patch is attached.
>>
>> Regards,
>>
>> --
>> Fujii Masao
>> <v6-0001-PG15-PG16-Honor-GUC-settings-specified-in-CREATE-SUBSCRIPTI.txt><v6-0002-Add-TAP-test-for-GUC-settings-passed-via-CONNECTI.patch><v6-0001-Honor-GUC-settings-specified-in-CREATE-SUBSCRIPTI.patch>
>
> A few more comments on v6:
>
> 1 - 0001
> ```
> + if (opt != NULL)
> + pfree(opt);
> ```
>
> From what I learned from previous reviews, pfree() is safe to handle NULL, we can omit the NULL check, which makes the code simpler. This comment applies to multiple places.
>
I think we cannot omit it here. We have two pfree()s, one for frontend and
one for backend. IIUC, the frontend pfree() is safe to handle NULL, but the
backend pfree() is not.
> 2. I still think we should verify options extracted from conninfo. In the 0002’s tap script, if I make the following change:
> ```
> $node_subscriber->safe_psql('postgres',
> - "ALTER SUBSCRIPTION tap_sub CONNECTION '$publisher_connstr options=''-c log_statement_stats=on'''"
> + "ALTER SUBSCRIPTION tap_sub CONNECTION '$publisher_connstr options=''-c log_statement_stats=on-c wal_sender_timeout=1000'’'"
> ```
>
> Notice, there is no space between the second “-c” and “on”, meaning that a user passes an invalid options. Then the test will get stuck forever, which would never happen before this patch.
>
How to verify the options? Checking for -c isn't enough because valid flags
can still carry invalid values. For example, -c log_statement_stats=aa is
syntactically correct but will fail at runtime.
--
Regards,
Japin Li
ChengDu WenWu Information Technology Co., Ltd.
^ permalink raw reply [nested|flat] 37+ messages in thread
* Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect
@ 2025-12-23 08:45 Chao Li <[email protected]>
parent: Japin Li <[email protected]>
0 siblings, 0 replies; 37+ messages in thread
From: Chao Li @ 2025-12-23 08:45 UTC (permalink / raw)
To: Japin Li <[email protected]>; +Cc: Fujii Masao <[email protected]>; Amit Kapila <[email protected]>; PostgreSQL Hackers <[email protected]>
> On Dec 23, 2025, at 16:13, Japin Li <[email protected]> wrote:
>
> On Tue, 23 Dec 2025 at 14:17, Chao Li <[email protected]> wrote:
>>> On Dec 19, 2025, at 19:05, Fujii Masao <[email protected]> wrote:
>>>
>>> On Fri, Dec 19, 2025 at 7:07 PM Japin Li <[email protected]> wrote:
>>>> Thanks for the patch — that was my oversight.
>>>>
>>>> LGTM with one small suggestion:
>>>
>>> Thanks for the review!
>>>
>>>> The comment says: "If the option is not found in connInfo, return NULL value."
>>>>
>>>> Since the parameter is named `keyword`, I'd suggest: "If the keyword is not found in connInfo, return NULL."
>>>>
>>>> This keeps terminology consistent with the function signature.
>>>
>>> I think "the option with the given keyword" is more precise than just
>>> "the keyword".
>>> That said, simply using "the option" also seems sufficient in this context...
>>>
>>>
>>> Regarding 0002 patch, I found that it caused a CI failure, so I’ve updated
>>> the patch to fix that. The revised patch is attached.
>>>
>>> Regards,
>>>
>>> --
>>> Fujii Masao
>>> <v6-0001-PG15-PG16-Honor-GUC-settings-specified-in-CREATE-SUBSCRIPTI.txt><v6-0002-Add-TAP-test-for-GUC-settings-passed-via-CONNECTI.patch><v6-0001-Honor-GUC-settings-specified-in-CREATE-SUBSCRIPTI.patch>
>>
>> A few more comments on v6:
>>
>> 1 - 0001
>> ```
>> + if (opt != NULL)
>> + pfree(opt);
>> ```
>>
>> From what I learned from previous reviews, pfree() is safe to handle NULL, we can omit the NULL check, which makes the code simpler. This comment applies to multiple places.
>>
>
> I think we cannot omit it here. We have two pfree()s, one for frontend and
> one for backend. IIUC, the frontend pfree() is safe to handle NULL, but the
> backend pfree() is not.
>
Ahh… You are right. I just traced a backend pfree(), and it ends up calling GetMemoryChunkMethodID(const void *point), and the function doesn’t handle NULL pointer.
Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/
^ permalink raw reply [nested|flat] 37+ messages in thread
* Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect
@ 2025-12-25 07:00 Fujii Masao <[email protected]>
parent: Kirill Reshke <[email protected]>
0 siblings, 0 replies; 37+ messages in thread
From: Fujii Masao @ 2025-12-25 07:00 UTC (permalink / raw)
To: Kirill Reshke <[email protected]>; +Cc: Japin Li <[email protected]>; Amit Kapila <[email protected]>; PostgreSQL Hackers <[email protected]>
On Sat, Dec 20, 2025 at 12:48 AM Kirill Reshke <[email protected]> wrote:
>
> On Fri, 19 Dec 2025 at 19:42, Fujii Masao <[email protected]> wrote:
> >
> > On Fri, Dec 19, 2025 at 9:30 PM Kirill Reshke <[email protected]> wrote:
> > > I checked the new TAP test 0002 changes. I am wondering, why are
> > > connection options validated so late in this test? I mean, we do
> > > ALTER PUBLICATION, then we restart publisher, wait for catchup, check
> > > alter publication, and etc, and only then we look if connection
> > > options are indeed applied?
> >
> > Are you suggesting testing whether the conninfo setting is applied earlier,
> > for example, right after both running ALTER SUBSCRIPTION CONNECTION and
> > confirming that the logical replication connection is re-established?
> > Yeah, that might be better and would also make the test easier to read.
> >
> > Regards,
> >
> > --
> > Fujii Masao
>
> Yes, exactly
OK, I've updated the 0002 patch accordingly.
Regards,
--
Fujii Masao
From 38798c9bc99f0499bea754f3d6a51d5244163360 Mon Sep 17 00:00:00 2001
From: Fujii Masao <[email protected]>
Date: Wed, 3 Dec 2025 00:59:09 +0900
Subject: [PATCH v7 1/2] Honor GUC settings specified in CREATE SUBSCRIPTION
CONNECTION.
Prior to v15, GUC settings supplied in the CONNECTION clause of
CREATE SUBSCRIPTION were correctly passed through to
the publisher's walsender. For example:
CREATE SUBSCRIPTION mysub
CONNECTION 'options=''-c wal_sender_timeout=1000'''
PUBLICATION ...
would cause wal_sender_timeout to take effect on the publisher's walsender.
However, commit f3d4019da5d changed the way logical replication
connections are established, forcing the publisher's relevant
GUC settings (datestyle, intervalstyle, extra_float_digits) to
override those provided in the CONNECTION string. As a result,
from v15 through v18, GUC settings in the CONNECTION string were
always ignored.
This regression prevented per-connection tuning of logical replication.
For example, using a shorter timeout for walsender connecting
to a nearby subscriber and a longer one for walsender connecting
to a remote subscriber.
This commit restores the intended behavior by ensuring that
GUC settings in the CONNECTION string are again passed through
and applied by the walsender, allowing per-connection configuration.
Backpatch to v15, where the regression was introduced.
Author: Fujii Masao <[email protected]>
Reviewed-by: Chao Li <[email protected]>
Reviewed-by: Kirill Reshke <[email protected]>
Reviewed-by: Amit Kapila <[email protected]>
Reviewed-by: Japin Li <[email protected]>
Discussion: https://postgr.es/m/CAHGQGwGYV+-abbKwdrM2UHUe-JYOFWmsrs6=QicyJO-j+-Widw@mail.gmail.com
Backpatch-through: 15
---
.../libpqwalreceiver/libpqwalreceiver.c | 61 ++++++++++++++++++-
1 file changed, 60 insertions(+), 1 deletion(-)
diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
index 568024ec974..743f951f330 100644
--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
+++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
@@ -57,6 +57,8 @@ static void libpqrcv_get_senderinfo(WalReceiverConn *conn,
char **sender_host, int *sender_port);
static char *libpqrcv_identify_system(WalReceiverConn *conn,
TimeLineID *primary_tli);
+static char *libpqrcv_get_option_from_conninfo(const char *connInfo,
+ const char *keyword);
static int libpqrcv_server_version(WalReceiverConn *conn);
static void libpqrcv_readtimelinehistoryfile(WalReceiverConn *conn,
TimeLineID tli, char **filename,
@@ -136,6 +138,7 @@ libpqrcv_connect(const char *conninfo, bool logical, bool must_use_password,
const char *keys[6];
const char *vals[6];
int i = 0;
+ char *options_val = NULL;
/*
* Re-validate connection string. The validation already happened at DDL
@@ -167,6 +170,8 @@ libpqrcv_connect(const char *conninfo, bool logical, bool must_use_password,
vals[i] = appname;
if (logical)
{
+ char *opt = NULL;
+
/* Tell the publisher to translate to our encoding */
keys[++i] = "client_encoding";
vals[i] = GetDatabaseEncodingName();
@@ -179,8 +184,13 @@ libpqrcv_connect(const char *conninfo, bool logical, bool must_use_password,
* the subscriber, such as triggers.) This should match what pg_dump
* does.
*/
+ opt = libpqrcv_get_option_from_conninfo(conninfo, "options");
+ options_val = psprintf("%s -c datestyle=ISO -c intervalstyle=postgres -c extra_float_digits=3",
+ (opt == NULL) ? "" : opt);
keys[++i] = "options";
- vals[i] = "-c datestyle=ISO -c intervalstyle=postgres -c extra_float_digits=3";
+ vals[i] = options_val;
+ if (opt != NULL)
+ pfree(opt);
}
keys[++i] = NULL;
vals[i] = NULL;
@@ -232,6 +242,9 @@ libpqrcv_connect(const char *conninfo, bool logical, bool must_use_password,
status = PQconnectPoll(conn->streamConn);
} while (status != PGRES_POLLING_OK && status != PGRES_POLLING_FAILED);
+ if (options_val != NULL)
+ pfree(options_val);
+
if (PQstatus(conn->streamConn) != CONNECTION_OK)
goto bad_connection_errmsg;
@@ -434,6 +447,7 @@ libpqrcv_identify_system(WalReceiverConn *conn, TimeLineID *primary_tli)
"the primary server: %s",
pchomp(PQerrorMessage(conn->streamConn)))));
}
+
/*
* IDENTIFY_SYSTEM returns 3 columns in 9.3 and earlier, and 4 columns in
* 9.4 and onwards.
@@ -466,6 +480,51 @@ libpqrcv_server_version(WalReceiverConn *conn)
return PQserverVersion(conn->streamConn);
}
+/*
+ * Get the value of the option with the given keyword from the primary
+ * server's conninfo.
+ *
+ * If the option is not found in connInfo, return NULL value.
+ */
+static char *
+libpqrcv_get_option_from_conninfo(const char *connInfo, const char *keyword)
+{
+ PQconninfoOption *opts;
+ char *option = NULL;
+ char *err = NULL;
+
+ opts = PQconninfoParse(connInfo, &err);
+ if (opts == NULL)
+ {
+ /* The error string is malloc'd, so we must free it explicitly */
+ char *errcopy = err ? pstrdup(err) : "out of memory";
+
+ PQfreemem(err);
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("invalid connection string syntax: %s", errcopy)));
+ }
+
+ for (PQconninfoOption *opt = opts; opt->keyword != NULL; ++opt)
+ {
+ /*
+ * If the same option appears multiple times, then the last one will
+ * be returned
+ */
+ if (strcmp(opt->keyword, keyword) == 0 && opt->val &&
+ *opt->val)
+ {
+ if (option)
+ pfree(option);
+
+ option = pstrdup(opt->val);
+ }
+ }
+
+ PQconninfoFree(opts);
+ return option;
+}
+
/*
* Start streaming WAL data from given streaming options.
*
--
2.51.2
Attachments:
[text/plain] v7-0001-PG15-PG16-Honor-GUC-settings-specified-in-CREATE-SUBSCRIPTI.txt (5.6K, ../../CAHGQGwHp28BJiCR59DCzPzUpetDtusNigta7aAC+yiL1dBFb-w@mail.gmail.com/2-v7-0001-PG15-PG16-Honor-GUC-settings-specified-in-CREATE-SUBSCRIPTI.txt)
download | inline diff:
From 38798c9bc99f0499bea754f3d6a51d5244163360 Mon Sep 17 00:00:00 2001
From: Fujii Masao <[email protected]>
Date: Wed, 3 Dec 2025 00:59:09 +0900
Subject: [PATCH v7 1/2] Honor GUC settings specified in CREATE SUBSCRIPTION
CONNECTION.
Prior to v15, GUC settings supplied in the CONNECTION clause of
CREATE SUBSCRIPTION were correctly passed through to
the publisher's walsender. For example:
CREATE SUBSCRIPTION mysub
CONNECTION 'options=''-c wal_sender_timeout=1000'''
PUBLICATION ...
would cause wal_sender_timeout to take effect on the publisher's walsender.
However, commit f3d4019da5d changed the way logical replication
connections are established, forcing the publisher's relevant
GUC settings (datestyle, intervalstyle, extra_float_digits) to
override those provided in the CONNECTION string. As a result,
from v15 through v18, GUC settings in the CONNECTION string were
always ignored.
This regression prevented per-connection tuning of logical replication.
For example, using a shorter timeout for walsender connecting
to a nearby subscriber and a longer one for walsender connecting
to a remote subscriber.
This commit restores the intended behavior by ensuring that
GUC settings in the CONNECTION string are again passed through
and applied by the walsender, allowing per-connection configuration.
Backpatch to v15, where the regression was introduced.
Author: Fujii Masao <[email protected]>
Reviewed-by: Chao Li <[email protected]>
Reviewed-by: Kirill Reshke <[email protected]>
Reviewed-by: Amit Kapila <[email protected]>
Reviewed-by: Japin Li <[email protected]>
Discussion: https://postgr.es/m/CAHGQGwGYV+-abbKwdrM2UHUe-JYOFWmsrs6=QicyJO-j+-Widw@mail.gmail.com
Backpatch-through: 15
---
.../libpqwalreceiver/libpqwalreceiver.c | 61 ++++++++++++++++++-
1 file changed, 60 insertions(+), 1 deletion(-)
diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
index 568024ec974..743f951f330 100644
--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
+++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
@@ -57,6 +57,8 @@ static void libpqrcv_get_senderinfo(WalReceiverConn *conn,
char **sender_host, int *sender_port);
static char *libpqrcv_identify_system(WalReceiverConn *conn,
TimeLineID *primary_tli);
+static char *libpqrcv_get_option_from_conninfo(const char *connInfo,
+ const char *keyword);
static int libpqrcv_server_version(WalReceiverConn *conn);
static void libpqrcv_readtimelinehistoryfile(WalReceiverConn *conn,
TimeLineID tli, char **filename,
@@ -136,6 +138,7 @@ libpqrcv_connect(const char *conninfo, bool logical, bool must_use_password,
const char *keys[6];
const char *vals[6];
int i = 0;
+ char *options_val = NULL;
/*
* Re-validate connection string. The validation already happened at DDL
@@ -167,6 +170,8 @@ libpqrcv_connect(const char *conninfo, bool logical, bool must_use_password,
vals[i] = appname;
if (logical)
{
+ char *opt = NULL;
+
/* Tell the publisher to translate to our encoding */
keys[++i] = "client_encoding";
vals[i] = GetDatabaseEncodingName();
@@ -179,8 +184,13 @@ libpqrcv_connect(const char *conninfo, bool logical, bool must_use_password,
* the subscriber, such as triggers.) This should match what pg_dump
* does.
*/
+ opt = libpqrcv_get_option_from_conninfo(conninfo, "options");
+ options_val = psprintf("%s -c datestyle=ISO -c intervalstyle=postgres -c extra_float_digits=3",
+ (opt == NULL) ? "" : opt);
keys[++i] = "options";
- vals[i] = "-c datestyle=ISO -c intervalstyle=postgres -c extra_float_digits=3";
+ vals[i] = options_val;
+ if (opt != NULL)
+ pfree(opt);
}
keys[++i] = NULL;
vals[i] = NULL;
@@ -232,6 +242,9 @@ libpqrcv_connect(const char *conninfo, bool logical, bool must_use_password,
status = PQconnectPoll(conn->streamConn);
} while (status != PGRES_POLLING_OK && status != PGRES_POLLING_FAILED);
+ if (options_val != NULL)
+ pfree(options_val);
+
if (PQstatus(conn->streamConn) != CONNECTION_OK)
goto bad_connection_errmsg;
@@ -434,6 +447,7 @@ libpqrcv_identify_system(WalReceiverConn *conn, TimeLineID *primary_tli)
"the primary server: %s",
pchomp(PQerrorMessage(conn->streamConn)))));
}
+
/*
* IDENTIFY_SYSTEM returns 3 columns in 9.3 and earlier, and 4 columns in
* 9.4 and onwards.
@@ -466,6 +480,51 @@ libpqrcv_server_version(WalReceiverConn *conn)
return PQserverVersion(conn->streamConn);
}
+/*
+ * Get the value of the option with the given keyword from the primary
+ * server's conninfo.
+ *
+ * If the option is not found in connInfo, return NULL value.
+ */
+static char *
+libpqrcv_get_option_from_conninfo(const char *connInfo, const char *keyword)
+{
+ PQconninfoOption *opts;
+ char *option = NULL;
+ char *err = NULL;
+
+ opts = PQconninfoParse(connInfo, &err);
+ if (opts == NULL)
+ {
+ /* The error string is malloc'd, so we must free it explicitly */
+ char *errcopy = err ? pstrdup(err) : "out of memory";
+
+ PQfreemem(err);
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("invalid connection string syntax: %s", errcopy)));
+ }
+
+ for (PQconninfoOption *opt = opts; opt->keyword != NULL; ++opt)
+ {
+ /*
+ * If the same option appears multiple times, then the last one will
+ * be returned
+ */
+ if (strcmp(opt->keyword, keyword) == 0 && opt->val &&
+ *opt->val)
+ {
+ if (option)
+ pfree(option);
+
+ option = pstrdup(opt->val);
+ }
+ }
+
+ PQconninfoFree(opts);
+ return option;
+}
+
/*
* Start streaming WAL data from given streaming options.
*
--
2.51.2
[application/octet-stream] v7-0002-Add-TAP-test-for-GUC-settings-passed-via-CONNECTI.patch (3.2K, ../../CAHGQGwHp28BJiCR59DCzPzUpetDtusNigta7aAC+yiL1dBFb-w@mail.gmail.com/3-v7-0002-Add-TAP-test-for-GUC-settings-passed-via-CONNECTI.patch)
download | inline diff:
From 32f36d5bf49c5ec8b60aa05cc0e070b686b459ed Mon Sep 17 00:00:00 2001
From: Fujii Masao <[email protected]>
Date: Thu, 27 Nov 2025 12:36:59 +0900
Subject: [PATCH v7 2/2] Add TAP test for GUC settings passed via CONNECTION in
logical replication.
This commit adds a TAP test to verify that GUC settings provided in
the CONNECTION string of CREATE/ALTER SUBSCRIPTION are correctly
passed through to and applied by the publisher's walsender.
---
src/test/subscription/t/001_rep_changes.pl | 29 +++++++++++++++++++++-
1 file changed, 28 insertions(+), 1 deletion(-)
diff --git a/src/test/subscription/t/001_rep_changes.pl b/src/test/subscription/t/001_rep_changes.pl
index ecb79e79474..4eab249d62e 100644
--- a/src/test/subscription/t/001_rep_changes.pl
+++ b/src/test/subscription/t/001_rep_changes.pl
@@ -438,17 +438,34 @@ is( $result, qq(11.11|baz|1
22.22|bar|2),
'update works with dropped subscriber column');
+# Verify that GUC settings supplied in the CONNECTION string take effect on
+# the publisher's walsender. We do this by enabling log_statement_stats in
+# the CONNECTION string later and checking that the publisher's log contains a
+# QUERY STATISTICS message.
+#
+# First, confirm that no such QUERY STATISTICS message appears before enabling
+# log_statement_stats.
+$logfile = slurp_file($node_publisher->logfile, $log_location);
+unlike(
+ $logfile,
+ qr/QUERY STATISTICS/,
+ 'log_statement_stats has not been enabled yet');
+
# check that change of connection string and/or publication list causes
# restart of subscription workers. We check the state along with
# application_name to ensure that the walsender is (re)started.
#
# Not all of these are registered as tests as we need to poll for a change
# but the test suite will fail nonetheless when something goes wrong.
+#
+# Enable log_statement_stats as the change of connection string,
+# which is also for the above mentioned test of GUC settings passed through
+# CONNECTION.
my $oldpid = $node_publisher->safe_psql('postgres',
"SELECT pid FROM pg_stat_replication WHERE application_name = 'tap_sub' AND state = 'streaming';"
);
$node_subscriber->safe_psql('postgres',
- "ALTER SUBSCRIPTION tap_sub CONNECTION '$publisher_connstr sslmode=disable'"
+ "ALTER SUBSCRIPTION tap_sub CONNECTION '$publisher_connstr options=''-c log_statement_stats=on'''"
);
$node_publisher->poll_query_until('postgres',
"SELECT pid != $oldpid FROM pg_stat_replication WHERE application_name = 'tap_sub' AND state = 'streaming';"
@@ -456,6 +473,16 @@ $node_publisher->poll_query_until('postgres',
or die
"Timed out while waiting for apply to restart after changing CONNECTION";
+# Check that the expected QUERY STATISTICS message appears,
+# which shows that log_statement_stats=on from the CONNECTION string
+# was correctly passed through to and honored by the walsender.
+$logfile = slurp_file($node_publisher->logfile, $log_location);
+like(
+ $logfile,
+ qr/QUERY STATISTICS/,
+ 'log_statement_stats in CONNECTION string had effect on publisher\'s walsender'
+);
+
$oldpid = $node_publisher->safe_psql('postgres',
"SELECT pid FROM pg_stat_replication WHERE application_name = 'tap_sub' AND state = 'streaming';"
);
--
2.51.2
[application/octet-stream] v7-0001-Honor-GUC-settings-specified-in-CREATE-SUBSCRIPTI.patch (5.4K, ../../CAHGQGwHp28BJiCR59DCzPzUpetDtusNigta7aAC+yiL1dBFb-w@mail.gmail.com/4-v7-0001-Honor-GUC-settings-specified-in-CREATE-SUBSCRIPTI.patch)
download | inline diff:
From 84d9dfd3e7d49c318dfad78c31cd5ca620b31877 Mon Sep 17 00:00:00 2001
From: Fujii Masao <[email protected]>
Date: Wed, 3 Dec 2025 00:59:09 +0900
Subject: [PATCH v7 1/2] Honor GUC settings specified in CREATE SUBSCRIPTION
CONNECTION.
Prior to v15, GUC settings supplied in the CONNECTION clause of
CREATE SUBSCRIPTION were correctly passed through to
the publisher's walsender. For example:
CREATE SUBSCRIPTION mysub
CONNECTION 'options=''-c wal_sender_timeout=1000'''
PUBLICATION ...
would cause wal_sender_timeout to take effect on the publisher's walsender.
However, commit f3d4019da5d changed the way logical replication
connections are established, forcing the publisher's relevant
GUC settings (datestyle, intervalstyle, extra_float_digits) to
override those provided in the CONNECTION string. As a result,
from v15 through v18, GUC settings in the CONNECTION string were
always ignored.
This regression prevented per-connection tuning of logical replication.
For example, using a shorter timeout for walsender connecting
to a nearby subscriber and a longer one for walsender connecting
to a remote subscriber.
This commit restores the intended behavior by ensuring that
GUC settings in the CONNECTION string are again passed through
and applied by the walsender, allowing per-connection configuration.
Backpatch to v15, where the regression was introduced.
Author: Fujii Masao <[email protected]>
Reviewed-by: Chao Li <[email protected]>
Reviewed-by: Kirill Reshke <[email protected]>
Reviewed-by: Amit Kapila <[email protected]>
Reviewed-by: Japin Li <[email protected]>
Discussion: https://postgr.es/m/CAHGQGwGYV+-abbKwdrM2UHUe-JYOFWmsrs6=QicyJO-j+-Widw@mail.gmail.com
Backpatch-through: 15
---
.../libpqwalreceiver/libpqwalreceiver.c | 43 +++++++++++++++----
1 file changed, 34 insertions(+), 9 deletions(-)
diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
index 5ddc9e812e7..c067908da35 100644
--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
+++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
@@ -65,6 +65,8 @@ static void libpqrcv_get_senderinfo(WalReceiverConn *conn,
static char *libpqrcv_identify_system(WalReceiverConn *conn,
TimeLineID *primary_tli);
static char *libpqrcv_get_dbname_from_conninfo(const char *connInfo);
+static char *libpqrcv_get_option_from_conninfo(const char *connInfo,
+ const char *keyword);
static int libpqrcv_server_version(WalReceiverConn *conn);
static void libpqrcv_readtimelinehistoryfile(WalReceiverConn *conn,
TimeLineID tli, char **filename,
@@ -150,6 +152,7 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
const char *keys[6];
const char *vals[6];
int i = 0;
+ char *options_val = NULL;
/*
* Re-validate connection string. The validation already happened at DDL
@@ -177,6 +180,8 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
if (logical)
{
+ char *opt = NULL;
+
/* Tell the publisher to translate to our encoding */
keys[++i] = "client_encoding";
vals[i] = GetDatabaseEncodingName();
@@ -189,8 +194,13 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
* running in the subscriber, such as triggers.) This should
* match what pg_dump does.
*/
+ opt = libpqrcv_get_option_from_conninfo(conninfo, "options");
+ options_val = psprintf("%s -c datestyle=ISO -c intervalstyle=postgres -c extra_float_digits=3",
+ (opt == NULL) ? "" : opt);
keys[++i] = "options";
- vals[i] = "-c datestyle=ISO -c intervalstyle=postgres -c extra_float_digits=3";
+ vals[i] = options_val;
+ if (opt != NULL)
+ pfree(opt);
}
else
{
@@ -217,6 +227,9 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
/* expand_dbname = */ true,
WAIT_EVENT_LIBPQWALRECEIVER_CONNECT);
+ if (options_val != NULL)
+ pfree(options_val);
+
if (PQstatus(conn->streamConn) != CONNECTION_OK)
goto bad_connection_errmsg;
@@ -460,9 +473,21 @@ libpqrcv_server_version(WalReceiverConn *conn)
*/
static char *
libpqrcv_get_dbname_from_conninfo(const char *connInfo)
+{
+ return libpqrcv_get_option_from_conninfo(connInfo, "dbname");
+}
+
+/*
+ * Get the value of the option with the given keyword from the primary
+ * server's conninfo.
+ *
+ * If the option is not found in connInfo, return NULL value.
+ */
+static char *
+libpqrcv_get_option_from_conninfo(const char *connInfo, const char *keyword)
{
PQconninfoOption *opts;
- char *dbname = NULL;
+ char *option = NULL;
char *err = NULL;
opts = PQconninfoParse(connInfo, &err);
@@ -480,21 +505,21 @@ libpqrcv_get_dbname_from_conninfo(const char *connInfo)
for (PQconninfoOption *opt = opts; opt->keyword != NULL; ++opt)
{
/*
- * If multiple dbnames are specified, then the last one will be
- * returned
+ * If the same option appears multiple times, then the last one will
+ * be returned
*/
- if (strcmp(opt->keyword, "dbname") == 0 && opt->val &&
+ if (strcmp(opt->keyword, keyword) == 0 && opt->val &&
*opt->val)
{
- if (dbname)
- pfree(dbname);
+ if (option)
+ pfree(option);
- dbname = pstrdup(opt->val);
+ option = pstrdup(opt->val);
}
}
PQconninfoFree(opts);
- return dbname;
+ return option;
}
/*
--
2.51.2
^ permalink raw reply [nested|flat] 37+ messages in thread
* Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect
@ 2025-12-25 07:01 Fujii Masao <[email protected]>
parent: Amit Kapila <[email protected]>
0 siblings, 0 replies; 37+ messages in thread
From: Fujii Masao @ 2025-12-25 07:01 UTC (permalink / raw)
To: Amit Kapila <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>
On Tue, Dec 23, 2025 at 2:05 PM Amit Kapila <[email protected]> wrote:
> Thanks, the idea looks good now. One minor comment:
Thanks for the review!
> }
> +
> /*
>
> This appears to be an unnecessary addition in the patch.
The added blank line is due to pgindent, so I didn't exclude it from the patch.
I'm not sure what the preferred practice is for handling pgindent changes
in older branches, but in general it seems better to keep the code clean
and pgindent-compliant even there. Thoughts?
Regards,
--
Fujii Masao
^ permalink raw reply [nested|flat] 37+ messages in thread
end of thread, other threads:[~2025-12-25 07:01 UTC | newest]
Thread overview: 37+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2021-12-08 18:06 [PATCH v4 2/2] Expose GUC flags in SQL function; retire ./check_guc Justin Pryzby <[email protected]>
2021-12-08 18:06 [PATCH 2/2] Expose GUC flags in SQL function; retire ./check_guc Justin Pryzby <[email protected]>
2021-12-08 18:06 [PATCH 2/2] Expose GUC flags in SQL function; retire ./check_guc Justin Pryzby <[email protected]>
2025-11-18 15:59 Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect Fujii Masao <[email protected]>
2025-11-19 06:22 ` Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect Fujii Masao <[email protected]>
2025-11-19 10:38 ` Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect Fujii Masao <[email protected]>
2025-11-20 06:53 ` Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect Chao Li <[email protected]>
2025-11-21 07:47 ` Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect Fujii Masao <[email protected]>
2025-11-21 09:23 ` Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect Chao Li <[email protected]>
2025-11-21 16:14 ` Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect Fujii Masao <[email protected]>
2025-11-22 01:31 ` Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect Chao Li <[email protected]>
2025-11-22 14:14 ` Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect Fujii Masao <[email protected]>
2025-11-24 03:51 ` Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect Chao Li <[email protected]>
2025-11-25 11:30 ` Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect Fujii Masao <[email protected]>
2025-11-26 17:37 ` Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect Kirill Reshke <[email protected]>
2025-11-27 02:46 ` Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect Fujii Masao <[email protected]>
2025-11-27 05:17 ` Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect Fujii Masao <[email protected]>
2025-12-02 06:02 ` Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect Fujii Masao <[email protected]>
2025-12-02 06:37 ` Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect Kirill Reshke <[email protected]>
2025-11-24 05:54 ` Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect Jelte Fennema-Nio <[email protected]>
2025-11-25 11:32 ` Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect Fujii Masao <[email protected]>
2025-11-26 16:33 ` Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect Fujii Masao <[email protected]>
2025-12-02 12:08 ` Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect Amit Kapila <[email protected]>
2025-12-02 14:59 ` Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect Fujii Masao <[email protected]>
2025-12-03 05:45 ` Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect Amit Kapila <[email protected]>
2025-12-19 07:55 ` Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect Fujii Masao <[email protected]>
2025-12-19 10:07 ` Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect Japin Li <[email protected]>
2025-12-19 11:05 ` Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect Fujii Masao <[email protected]>
2025-12-19 12:30 ` Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect Kirill Reshke <[email protected]>
2025-12-19 14:42 ` Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect Fujii Masao <[email protected]>
2025-12-19 15:48 ` Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect Kirill Reshke <[email protected]>
2025-12-25 07:00 ` Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect Fujii Masao <[email protected]>
2025-12-23 06:17 ` Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect Chao Li <[email protected]>
2025-12-23 08:13 ` Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect Japin Li <[email protected]>
2025-12-23 08:45 ` Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect Chao Li <[email protected]>
2025-12-23 05:05 ` Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect Amit Kapila <[email protected]>
2025-12-25 07:01 ` Re: Allow GUC settings in CREATE SUBSCRIPTION CONNECTION to take effect Fujii Masao <[email protected]>
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox