v15-0006-logical-replication-allow-combined-conflict_log_.patch
application/octet-stream
Filename: v15-0006-logical-replication-allow-combined-conflict_log_.patch
Type: application/octet-stream
Part: 5
From e6a1c0a6f88f421f66a93a2483ca585f2a298c46 Mon Sep 17 00:00:00 2001
From: Vignesh C <vignesh21@gmail.com>
Date: Wed, 24 Dec 2025 15:47:01 +0530
Subject: [PATCH v15 6/6] logical replication: allow combined
conflict_log_destination settings
Extend conflict_log_destination handling to support combined destination
specifications. Previously, only log, table, or all were accepted. This change
allows combinations of them like log, table and all, log, table etc
---
src/backend/catalog/pg_subscription.c | 2 +-
src/backend/commands/subscriptioncmds.c | 95 +++++++++++++++-------
src/backend/replication/logical/conflict.c | 9 +-
src/bin/pg_dump/pg_dump.c | 42 ++++++----
src/bin/pg_dump/t/002_pg_dump.pl | 4 +-
src/include/catalog/pg_subscription.h | 4 +-
src/include/commands/subscriptioncmds.h | 2 +-
src/include/replication/conflict.h | 23 +++---
src/test/regress/expected/subscription.out | 72 +++++++++-------
src/test/regress/sql/subscription.sql | 11 ++-
src/tools/pgindent/typedefs.list | 3 +-
11 files changed, 170 insertions(+), 97 deletions(-)
diff --git a/src/backend/catalog/pg_subscription.c b/src/backend/catalog/pg_subscription.c
index dae44c659f8..c1b8c2870c5 100644
--- a/src/backend/catalog/pg_subscription.c
+++ b/src/backend/catalog/pg_subscription.c
@@ -147,7 +147,7 @@ GetSubscription(Oid subid, bool missing_ok)
datum = SysCacheGetAttrNotNull(SUBSCRIPTIONOID,
tup,
Anum_pg_subscription_sublogdestination);
- sub->logdestination = TextDatumGetCString(datum);
+ sub->logdestination = textarray_to_stringlist(DatumGetArrayTypeP(datum));
/* Is the subscription owner a superuser? */
sub->ownersuperuser = superuser_arg(sub->owner);
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index 1fbe0d474cf..9809b8b56f4 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -59,6 +59,7 @@
#include "utils/pg_lsn.h"
#include "utils/regproc.h"
#include "utils/syscache.h"
+#include "utils/varlena.h"
/*
* Options that can be specified by the user in CREATE/ALTER SUBSCRIPTION
@@ -417,23 +418,22 @@ parse_subscription_options(ParseState *pstate, List *stmt_options,
else if (IsSet(supported_opts, SUBOPT_CONFLICT_LOG_DESTINATION) &&
strcmp(defel->defname, "conflict_log_destination") == 0)
{
- char *val;
- ConflictLogDest dest;
+ char *val;
+ List *dest;
if (IsSet(opts->specified_opts, SUBOPT_CONFLICT_LOG_DESTINATION))
errorConflictingDefElem(defel, pstate);
val = defGetString(defel);
- dest = GetLogDestination(val);
-
- if (dest == CONFLICT_LOG_DEST_INVALID)
+ if (!SplitIdentifierString(val, ',', &dest))
ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("unrecognized conflict_log_destination value: \"%s\"", val),
- errhint("Valid values are \"log\", \"table\", and \"all\".")));
+ errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("invalid list syntax in parameter \"%s\"",
+ "conflict_log_destination"));
+
+ opts->logdest = GetLogDestination(dest, false);
- opts->logdest = dest;
opts->specified_opts |= SUBOPT_CONFLICT_LOG_DESTINATION;
}
else
@@ -613,6 +613,30 @@ publicationListToArray(List *publist)
return PointerGetDatum(arr);
}
+/*
+ * Build a text[] array representing the conflict_log_destination flags.
+ */
+static Datum
+ConflictLogDestFlagsToArray(ConflictLogDest logdest)
+{
+ Datum datums[3];
+ int ndatums = 0;
+
+ if (CONFLICT_LOG_DEST_ALL_ENABLED(logdest))
+ datums[ndatums++] = CStringGetTextDatum("all");
+ else
+ {
+ if (CONFLICT_LOG_DEST_LOG_ENABLED(logdest))
+ datums[ndatums++] = CStringGetTextDatum("log");
+
+ if (CONFLICT_LOG_DEST_TABLE_ENABLED(logdest))
+ datums[ndatums++] = CStringGetTextDatum("table");
+ }
+
+ return PointerGetDatum(
+ construct_array_builtin(datums, ndatums, TEXTOID));
+}
+
/*
* Create new subscription.
*/
@@ -784,7 +808,7 @@ CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt,
/* Always set the destination, default will be log. */
values[Anum_pg_subscription_sublogdestination - 1] =
- CStringGetTextDatum(ConflictLogDestLabels[opts.logdest]);
+ ConflictLogDestFlagsToArray(opts.logdest);
/*
* If the conflict log destination includes 'table', generate an internal
@@ -793,8 +817,8 @@ CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt,
* format in the pg_subscription catalog tuple., then physically create
* the table.
*/
- if (opts.logdest == CONFLICT_LOG_DEST_TABLE ||
- opts.logdest == CONFLICT_LOG_DEST_ALL)
+ if (CONFLICT_LOG_DEST_TABLE_ENABLED(opts.logdest) ||
+ CONFLICT_LOG_DEST_ALL_ENABLED(opts.logdest))
{
char conflict_table_name[NAMEDATALEN];
Oid namespaceId, logrelid;
@@ -1424,16 +1448,16 @@ AlterSubscriptionConflictLogDestination(Subscription *sub,
ConflictLogDest logdest,
Oid *conflicttablerelid)
{
- ConflictLogDest old_dest = GetLogDestination(sub->logdestination);
+ ConflictLogDest old_dest = GetLogDestination(sub->logdestination, true);
bool want_table;
bool has_oldtable;
bool update_relid = false;
Oid relid = InvalidOid;
- want_table = (logdest == CONFLICT_LOG_DEST_TABLE ||
- logdest == CONFLICT_LOG_DEST_ALL);
- has_oldtable = (old_dest == CONFLICT_LOG_DEST_TABLE ||
- old_dest == CONFLICT_LOG_DEST_ALL);
+ want_table = (CONFLICT_LOG_DEST_TABLE_ENABLED(logdest) ||
+ CONFLICT_LOG_DEST_ALL_ENABLED(logdest));
+ has_oldtable = (CONFLICT_LOG_DEST_TABLE_ENABLED(old_dest) ||
+ CONFLICT_LOG_DEST_ALL_ENABLED(old_dest));
if (want_table && !has_oldtable)
{
@@ -1856,7 +1880,7 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt,
if (IsSet(opts.specified_opts, SUBOPT_CONFLICT_LOG_DESTINATION))
{
ConflictLogDest old_dest =
- GetLogDestination(sub->logdestination);
+ GetLogDestination(sub->logdestination, true);
if (opts.logdest != old_dest)
{
@@ -1864,7 +1888,7 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt,
Oid relid = InvalidOid;
values[Anum_pg_subscription_sublogdestination - 1] =
- CStringGetTextDatum(ConflictLogDestLabels[opts.logdest]);
+ ConflictLogDestFlagsToArray(opts.logdest);
replaces[Anum_pg_subscription_sublogdestination - 1] = true;
update_relid = AlterSubscriptionConflictLogDestination(sub, opts.logdest, &relid);
if (update_relid)
@@ -3544,23 +3568,38 @@ GetConflictLogTableName(char *dest, Oid subid)
/*
* GetLogDestination
*
- * Convert string to enum by comparing against standardized labels.
+ * Convert log destination List of strings to enums.
*/
ConflictLogDest
-GetLogDestination(const char *dest)
+GetLogDestination(List *destlist, bool strnodelist)
{
- /* Empty string or NULL defaults to LOG. */
- if (dest == NULL || dest[0] == '\0')
+ ConflictLogDest logdest = CONFLICT_LOG_DEST_INVALID;
+ ListCell *cell;
+
+ if (destlist == NIL)
return CONFLICT_LOG_DEST_LOG;
- for (int i = CONFLICT_LOG_DEST_LOG; i <= CONFLICT_LOG_DEST_ALL; i++)
+ foreach(cell, destlist)
{
- if (pg_strcasecmp(dest, ConflictLogDestLabels[i]) == 0)
- return (ConflictLogDest) i;
+ char *name;
+
+ name = (strnodelist) ? strVal(lfirst(cell)) : (char *) lfirst(cell);
+
+ if (pg_strcasecmp(name, "log") == 0)
+ logdest |= CONFLICT_LOG_DEST_LOG;
+ else if (pg_strcasecmp(name, "table") == 0)
+ logdest |= CONFLICT_LOG_DEST_TABLE;
+ else if (pg_strcasecmp(name, "all") == 0)
+ logdest |= CONFLICT_LOG_DEST_ALL;
+ else
+ ereport(ERROR,
+ errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("unrecognized value for subscription parameter \"%s\": \"%s\"",
+ "conflict_log_destination", name),
+ errhint("Valid values are \"log\", \"table\", and \"all\"."));
}
- /* Unrecognized string. */
- return CONFLICT_LOG_DEST_INVALID;
+ return logdest;
}
/*
diff --git a/src/backend/replication/logical/conflict.c b/src/backend/replication/logical/conflict.c
index 0b6e3f4a2c8..1c7ac2da6f5 100644
--- a/src/backend/replication/logical/conflict.c
+++ b/src/backend/replication/logical/conflict.c
@@ -159,8 +159,8 @@ ReportApplyConflict(EState *estate, ResultRelInfo *relinfo, int elevel,
/* Insert to table if destination is 'table' or 'all' */
if (conflictlogrel)
{
- Assert(dest == CONFLICT_LOG_DEST_TABLE ||
- dest == CONFLICT_LOG_DEST_ALL);
+ Assert(CONFLICT_LOG_DEST_TABLE_ENABLED(dest) ||
+ CONFLICT_LOG_DEST_ALL_ENABLED(dest));
if (ValidateConflictLogTable(conflictlogrel))
{
@@ -187,7 +187,8 @@ ReportApplyConflict(EState *estate, ResultRelInfo *relinfo, int elevel,
pgstat_report_subscription_conflict(MySubscription->oid, type);
/* Decide what detail to show in server logs. */
- if (dest == CONFLICT_LOG_DEST_LOG || dest == CONFLICT_LOG_DEST_ALL)
+ if (CONFLICT_LOG_DEST_LOG_ENABLED(dest) ||
+ CONFLICT_LOG_DEST_ALL_ENABLED(dest))
{
/* Standard reporting with full internal details. */
ereport(elevel,
@@ -263,7 +264,7 @@ GetConflictLogTableInfo(ConflictLogDest *log_dest)
* Convert the text log destination to the internal enum. MySubscription
* already contains the data from pg_subscription.
*/
- *log_dest = GetLogDestination(MySubscription->logdestination);
+ *log_dest = GetLogDestination(MySubscription->logdestination, true);
conflictlogrelid = MySubscription->conflictrelid;
/* If destination is 'log' only, no table to open. */
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index d2477cfb5a1..85b2f3a9a47 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -5522,10 +5522,10 @@ dumpSubscription(Archive *fout, const SubscriptionInfo *subinfo)
DumpOptions *dopt = fout->dopt;
PQExpBuffer delq;
PQExpBuffer query;
- PQExpBuffer publications;
+ PQExpBuffer namebuf;
char *qsubname;
- char **pubnames = NULL;
- int npubnames = 0;
+ char **names = NULL;
+ int nnames = 0;
int i;
/* Do nothing if not dumping schema */
@@ -5545,19 +5545,22 @@ dumpSubscription(Archive *fout, const SubscriptionInfo *subinfo)
appendStringLiteralAH(query, subinfo->subconninfo, fout);
/* Build list of quoted publications and append them to query. */
- if (!parsePGArray(subinfo->subpublications, &pubnames, &npubnames))
+ if (!parsePGArray(subinfo->subpublications, &names, &nnames))
pg_fatal("could not parse %s array", "subpublications");
- publications = createPQExpBuffer();
- for (i = 0; i < npubnames; i++)
+ namebuf = createPQExpBuffer();
+ for (i = 0; i < nnames; i++)
{
if (i > 0)
- appendPQExpBufferStr(publications, ", ");
+ appendPQExpBufferStr(namebuf, ", ");
- appendPQExpBufferStr(publications, fmtId(pubnames[i]));
+ appendPQExpBufferStr(namebuf, fmtId(names[i]));
}
- appendPQExpBuffer(query, " PUBLICATION %s WITH (connect = false, slot_name = ", publications->data);
+ appendPQExpBuffer(query, " PUBLICATION %s WITH (connect = false, slot_name = ", namebuf->data);
+ resetPQExpBuffer(namebuf);
+ free(names);
+
if (subinfo->subslotname)
appendStringLiteralAH(query, subinfo->subslotname, fout);
else
@@ -5610,11 +5613,22 @@ dumpSubscription(Archive *fout, const SubscriptionInfo *subinfo)
tableInfo->dobj.namespace->dobj.name);
}
+ /* Build list of quoted conflict log destinations and append them to query. */
+ if (!parsePGArray(subinfo->sublogdestination, &names, &nnames))
+ pg_fatal("could not parse %s array", "conflict_log_destination");
+
+ for (i = 0; i < nnames; i++)
+ {
+ if (i > 0)
+ appendPQExpBufferStr(namebuf, ", ");
+
+ appendPQExpBuffer(namebuf, "%s", names[i]);
+ }
+
appendPQExpBuffer(query,
- "\n\nALTER SUBSCRIPTION %s SET (conflict_log_destination = %s);\n",
+ "\n\nALTER SUBSCRIPTION %s SET (conflict_log_destination = '%s');\n",
qsubname,
- subinfo->sublogdestination);
-
+ namebuf->data);
if (subinfo->subconflictlogrelid)
appendPQExpBufferStr(query, "\n\nSELECT pg_catalog.set_config('search_path', '', false);\n");
@@ -5675,8 +5689,8 @@ dumpSubscription(Archive *fout, const SubscriptionInfo *subinfo)
NULL, subinfo->rolname,
subinfo->dobj.catId, 0, subinfo->dobj.dumpId);
- destroyPQExpBuffer(publications);
- free(pubnames);
+ destroyPQExpBuffer(namebuf);
+ free(names);
destroyPQExpBuffer(delq);
destroyPQExpBuffer(query);
diff --git a/src/bin/pg_dump/t/002_pg_dump.pl b/src/bin/pg_dump/t/002_pg_dump.pl
index 8ec7b0069dd..e0859dddf4f 100644
--- a/src/bin/pg_dump/t/002_pg_dump.pl
+++ b/src/bin/pg_dump/t/002_pg_dump.pl
@@ -3204,11 +3204,11 @@ my %tests = (
create_order => 50,
create_sql => 'CREATE SUBSCRIPTION sub3
CONNECTION \'dbname=doesnotexist\' PUBLICATION pub1
- WITH (connect = false, origin = any, streaming = on, conflict_log_destination= table);',
+ WITH (connect = false, origin = any, streaming = on, conflict_log_destination= \'log,table\');',
regexp => qr/^
\QCREATE SUBSCRIPTION sub3 CONNECTION 'dbname=doesnotexist' PUBLICATION pub1 WITH (connect = false, slot_name = 'sub3', streaming = on);\E\n\n\n
\QSELECT pg_catalog.set_config('search_path', 'public', false);\E\n\n\n
- \QALTER SUBSCRIPTION sub3 SET (conflict_log_destination = table);\E\n\n\n
+ \QALTER SUBSCRIPTION sub3 SET (conflict_log_destination = 'log, table');\E\n\n\n
\QSELECT pg_catalog.set_config('search_path', '', false);\E
/xm,
like => { %full_runs, section_post_data => 1, },
diff --git a/src/include/catalog/pg_subscription.h b/src/include/catalog/pg_subscription.h
index 46c446eaf8b..b3b2c29b96d 100644
--- a/src/include/catalog/pg_subscription.h
+++ b/src/include/catalog/pg_subscription.h
@@ -110,7 +110,7 @@ CATALOG(pg_subscription,6100,SubscriptionRelationId) BKI_SHARED_RELATION BKI_ROW
* table - internal table only,
* all - both log and table.
*/
- text sublogdestination;
+ text sublogdestination[1] BKI_FORCE_NULL;
/* Only publish data originating from the specified origin */
text suborigin BKI_DEFAULT(LOGICALREP_ORIGIN_ANY);
@@ -169,7 +169,7 @@ typedef struct Subscription
List *publications; /* List of publication names to subscribe to */
char *origin; /* Only publish data originating from the
* specified origin */
- char *logdestination; /* Conflict log destination */
+ List *logdestination; /* Conflict log destination */
} Subscription;
#ifdef EXPOSE_TO_CLIENT_CODE
diff --git a/src/include/commands/subscriptioncmds.h b/src/include/commands/subscriptioncmds.h
index 255e1e241b8..aa0bc503847 100644
--- a/src/include/commands/subscriptioncmds.h
+++ b/src/include/commands/subscriptioncmds.h
@@ -38,7 +38,7 @@ extern void CheckSubDeadTupleRetention(bool check_guc, bool sub_disabled,
bool max_retention_set);
extern void GetConflictLogTableName(char *dest, Oid subid);
-extern ConflictLogDest GetLogDestination(const char *dest);
+extern ConflictLogDest GetLogDestination(List *destlist, bool strnodelist);
extern bool IsConflictLogTable(Oid relid);
#endif /* SUBSCRIPTIONCMDS_H */
diff --git a/src/include/replication/conflict.h b/src/include/replication/conflict.h
index 5f313b7a976..92b7e619eb8 100644
--- a/src/include/replication/conflict.h
+++ b/src/include/replication/conflict.h
@@ -89,19 +89,20 @@ typedef struct ConflictTupleInfo
typedef enum ConflictLogDest
{
CONFLICT_LOG_DEST_INVALID = 0,
- CONFLICT_LOG_DEST_LOG, /* "log" (default) */
- CONFLICT_LOG_DEST_TABLE, /* "table" */
- CONFLICT_LOG_DEST_ALL /* "all" */
+ CONFLICT_LOG_DEST_LOG = 1 << 0, /* 0x00000001 */
+ CONFLICT_LOG_DEST_TABLE = 1 << 1, /* 0x00000002 */
+ CONFLICT_LOG_DEST_ALL = 1 << 2 /* 0x00000004 */
} ConflictLogDest;
-/*
- * Array mapping for converting internal enum to string.
- */
-static const char *const ConflictLogDestLabels[] = {
- [CONFLICT_LOG_DEST_LOG] = "log",
- [CONFLICT_LOG_DEST_TABLE] = "table",
- [CONFLICT_LOG_DEST_ALL] = "all"
-};
+/* Conflict log destination flags */
+#define CONFLICT_LOG_DEST_LOG_ENABLED(dest) \
+ ((dest) & CONFLICT_LOG_DEST_LOG)
+
+#define CONFLICT_LOG_DEST_TABLE_ENABLED(dest) \
+ ((dest) & CONFLICT_LOG_DEST_TABLE)
+
+#define CONFLICT_LOG_DEST_ALL_ENABLED(dest) \
+ ((dest) & CONFLICT_LOG_DEST_ALL)
/* Structure to hold metadata for one column of the conflict log table */
typedef struct ConflictLogColumnDef
diff --git a/src/test/regress/expected/subscription.out b/src/test/regress/expected/subscription.out
index 92423c83197..471821167a0 100644
--- a/src/test/regress/expected/subscription.out
+++ b/src/test/regress/expected/subscription.out
@@ -119,7 +119,7 @@ HINT: To initiate replication, you must manually create the replication slot, e
List of subscriptions
Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Retain dead tuples | Max retention duration | Retention active | Synchronous commit | Conninfo | Skip LSN | Conflict log destination
------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+------------------------+------------------+--------------------+-----------------------------+------------+--------------------------
- regress_testsub4 | regress_subscription_user | f | {testpub} | f | parallel | d | f | none | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist | 0/00000000 | log
+ regress_testsub4 | regress_subscription_user | f | {testpub} | f | parallel | d | f | none | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist | 0/00000000 | {log}
(1 row)
ALTER SUBSCRIPTION regress_testsub4 SET (origin = any);
@@ -127,7 +127,7 @@ ALTER SUBSCRIPTION regress_testsub4 SET (origin = any);
List of subscriptions
Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Retain dead tuples | Max retention duration | Retention active | Synchronous commit | Conninfo | Skip LSN | Conflict log destination
------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+------------------------+------------------+--------------------+-----------------------------+------------+--------------------------
- regress_testsub4 | regress_subscription_user | f | {testpub} | f | parallel | d | f | any | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist | 0/00000000 | log
+ regress_testsub4 | regress_subscription_user | f | {testpub} | f | parallel | d | f | any | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist | 0/00000000 | {log}
(1 row)
DROP SUBSCRIPTION regress_testsub3;
@@ -148,7 +148,7 @@ ERROR: invalid connection string syntax: missing "=" after "foobar" in connecti
List of subscriptions
Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Retain dead tuples | Max retention duration | Retention active | Synchronous commit | Conninfo | Skip LSN | Conflict log destination
-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+------------------------+------------------+--------------------+-----------------------------+------------+--------------------------
- regress_testsub | regress_subscription_user | f | {testpub} | f | parallel | d | f | any | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist | 0/00000000 | log
+ regress_testsub | regress_subscription_user | f | {testpub} | f | parallel | d | f | any | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist | 0/00000000 | {log}
(1 row)
ALTER SUBSCRIPTION regress_testsub SET PUBLICATION testpub2, testpub3 WITH (refresh = false);
@@ -160,7 +160,7 @@ ALTER SUBSCRIPTION regress_testsub SET (run_as_owner = true);
List of subscriptions
Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Retain dead tuples | Max retention duration | Retention active | Synchronous commit | Conninfo | Skip LSN | Conflict log destination
-----------------+---------------------------+---------+---------------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+------------------------+------------------+--------------------+------------------------------+------------+--------------------------
- regress_testsub | regress_subscription_user | f | {testpub2,testpub3} | f | parallel | d | f | any | f | t | f | f | 0 | f | off | dbname=regress_doesnotexist2 | 0/00000000 | log
+ regress_testsub | regress_subscription_user | f | {testpub2,testpub3} | f | parallel | d | f | any | f | t | f | f | 0 | f | off | dbname=regress_doesnotexist2 | 0/00000000 | {log}
(1 row)
ALTER SUBSCRIPTION regress_testsub SET (password_required = true);
@@ -179,7 +179,7 @@ ALTER SUBSCRIPTION regress_testsub SKIP (lsn = '0/12345');
List of subscriptions
Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Retain dead tuples | Max retention duration | Retention active | Synchronous commit | Conninfo | Skip LSN | Conflict log destination
-----------------+---------------------------+---------+---------------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+------------------------+------------------+--------------------+------------------------------+------------+--------------------------
- regress_testsub | regress_subscription_user | f | {testpub2,testpub3} | f | parallel | d | f | any | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist2 | 0/00012345 | log
+ regress_testsub | regress_subscription_user | f | {testpub2,testpub3} | f | parallel | d | f | any | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist2 | 0/00012345 | {log}
(1 row)
-- ok - with lsn = NONE
@@ -191,7 +191,7 @@ ERROR: invalid WAL location (LSN): 0/0
List of subscriptions
Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Retain dead tuples | Max retention duration | Retention active | Synchronous commit | Conninfo | Skip LSN | Conflict log destination
-----------------+---------------------------+---------+---------------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+------------------------+------------------+--------------------+------------------------------+------------+--------------------------
- regress_testsub | regress_subscription_user | f | {testpub2,testpub3} | f | parallel | d | f | any | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist2 | 0/00000000 | log
+ regress_testsub | regress_subscription_user | f | {testpub2,testpub3} | f | parallel | d | f | any | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist2 | 0/00000000 | {log}
(1 row)
BEGIN;
@@ -226,7 +226,7 @@ HINT: Available values: local, remote_write, remote_apply, on, off.
List of subscriptions
Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Retain dead tuples | Max retention duration | Retention active | Synchronous commit | Conninfo | Skip LSN | Conflict log destination
---------------------+---------------------------+---------+---------------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+------------------------+------------------+--------------------+------------------------------+------------+--------------------------
- regress_testsub_foo | regress_subscription_user | f | {testpub2,testpub3} | f | parallel | d | f | any | t | f | f | f | 0 | f | local | dbname=regress_doesnotexist2 | 0/00000000 | log
+ regress_testsub_foo | regress_subscription_user | f | {testpub2,testpub3} | f | parallel | d | f | any | t | f | f | f | 0 | f | local | dbname=regress_doesnotexist2 | 0/00000000 | {log}
(1 row)
-- rename back to keep the rest simple
@@ -258,7 +258,7 @@ HINT: To initiate replication, you must manually create the replication slot, e
List of subscriptions
Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Retain dead tuples | Max retention duration | Retention active | Synchronous commit | Conninfo | Skip LSN | Conflict log destination
-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+------------------------+------------------+--------------------+-----------------------------+------------+--------------------------
- regress_testsub | regress_subscription_user | f | {testpub} | t | parallel | d | f | any | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist | 0/00000000 | log
+ regress_testsub | regress_subscription_user | f | {testpub} | t | parallel | d | f | any | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist | 0/00000000 | {log}
(1 row)
ALTER SUBSCRIPTION regress_testsub SET (binary = false);
@@ -267,7 +267,7 @@ ALTER SUBSCRIPTION regress_testsub SET (slot_name = NONE);
List of subscriptions
Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Retain dead tuples | Max retention duration | Retention active | Synchronous commit | Conninfo | Skip LSN | Conflict log destination
-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+------------------------+------------------+--------------------+-----------------------------+------------+--------------------------
- regress_testsub | regress_subscription_user | f | {testpub} | f | parallel | d | f | any | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist | 0/00000000 | log
+ regress_testsub | regress_subscription_user | f | {testpub} | f | parallel | d | f | any | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist | 0/00000000 | {log}
(1 row)
DROP SUBSCRIPTION regress_testsub;
@@ -282,7 +282,7 @@ HINT: To initiate replication, you must manually create the replication slot, e
List of subscriptions
Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Retain dead tuples | Max retention duration | Retention active | Synchronous commit | Conninfo | Skip LSN | Conflict log destination
-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+------------------------+------------------+--------------------+-----------------------------+------------+--------------------------
- regress_testsub | regress_subscription_user | f | {testpub} | f | on | d | f | any | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist | 0/00000000 | log
+ regress_testsub | regress_subscription_user | f | {testpub} | f | on | d | f | any | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist | 0/00000000 | {log}
(1 row)
ALTER SUBSCRIPTION regress_testsub SET (streaming = parallel);
@@ -290,7 +290,7 @@ ALTER SUBSCRIPTION regress_testsub SET (streaming = parallel);
List of subscriptions
Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Retain dead tuples | Max retention duration | Retention active | Synchronous commit | Conninfo | Skip LSN | Conflict log destination
-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+------------------------+------------------+--------------------+-----------------------------+------------+--------------------------
- regress_testsub | regress_subscription_user | f | {testpub} | f | parallel | d | f | any | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist | 0/00000000 | log
+ regress_testsub | regress_subscription_user | f | {testpub} | f | parallel | d | f | any | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist | 0/00000000 | {log}
(1 row)
ALTER SUBSCRIPTION regress_testsub SET (streaming = false);
@@ -299,7 +299,7 @@ ALTER SUBSCRIPTION regress_testsub SET (slot_name = NONE);
List of subscriptions
Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Retain dead tuples | Max retention duration | Retention active | Synchronous commit | Conninfo | Skip LSN | Conflict log destination
-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+------------------------+------------------+--------------------+-----------------------------+------------+--------------------------
- regress_testsub | regress_subscription_user | f | {testpub} | f | off | d | f | any | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist | 0/00000000 | log
+ regress_testsub | regress_subscription_user | f | {testpub} | f | off | d | f | any | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist | 0/00000000 | {log}
(1 row)
-- fail - publication already exists
@@ -317,7 +317,7 @@ ERROR: publication "testpub1" is already in subscription "regress_testsub"
List of subscriptions
Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Retain dead tuples | Max retention duration | Retention active | Synchronous commit | Conninfo | Skip LSN | Conflict log destination
-----------------+---------------------------+---------+-----------------------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+------------------------+------------------+--------------------+-----------------------------+------------+--------------------------
- regress_testsub | regress_subscription_user | f | {testpub,testpub1,testpub2} | f | off | d | f | any | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist | 0/00000000 | log
+ regress_testsub | regress_subscription_user | f | {testpub,testpub1,testpub2} | f | off | d | f | any | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist | 0/00000000 | {log}
(1 row)
-- fail - publication used more than once
@@ -335,7 +335,7 @@ ALTER SUBSCRIPTION regress_testsub DROP PUBLICATION testpub1, testpub2 WITH (ref
List of subscriptions
Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Retain dead tuples | Max retention duration | Retention active | Synchronous commit | Conninfo | Skip LSN | Conflict log destination
-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+------------------------+------------------+--------------------+-----------------------------+------------+--------------------------
- regress_testsub | regress_subscription_user | f | {testpub} | f | off | d | f | any | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist | 0/00000000 | log
+ regress_testsub | regress_subscription_user | f | {testpub} | f | off | d | f | any | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist | 0/00000000 | {log}
(1 row)
DROP SUBSCRIPTION regress_testsub;
@@ -374,7 +374,7 @@ HINT: To initiate replication, you must manually create the replication slot, e
List of subscriptions
Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Retain dead tuples | Max retention duration | Retention active | Synchronous commit | Conninfo | Skip LSN | Conflict log destination
-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+------------------------+------------------+--------------------+-----------------------------+------------+--------------------------
- regress_testsub | regress_subscription_user | f | {testpub} | f | parallel | p | f | any | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist | 0/00000000 | log
+ regress_testsub | regress_subscription_user | f | {testpub} | f | parallel | p | f | any | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist | 0/00000000 | {log}
(1 row)
-- we can alter streaming when two_phase enabled
@@ -383,7 +383,7 @@ ALTER SUBSCRIPTION regress_testsub SET (streaming = true);
List of subscriptions
Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Retain dead tuples | Max retention duration | Retention active | Synchronous commit | Conninfo | Skip LSN | Conflict log destination
-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+------------------------+------------------+--------------------+-----------------------------+------------+--------------------------
- regress_testsub | regress_subscription_user | f | {testpub} | f | on | p | f | any | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist | 0/00000000 | log
+ regress_testsub | regress_subscription_user | f | {testpub} | f | on | p | f | any | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist | 0/00000000 | {log}
(1 row)
ALTER SUBSCRIPTION regress_testsub SET (slot_name = NONE);
@@ -396,7 +396,7 @@ HINT: To initiate replication, you must manually create the replication slot, e
List of subscriptions
Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Retain dead tuples | Max retention duration | Retention active | Synchronous commit | Conninfo | Skip LSN | Conflict log destination
-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+------------------------+------------------+--------------------+-----------------------------+------------+--------------------------
- regress_testsub | regress_subscription_user | f | {testpub} | f | on | p | f | any | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist | 0/00000000 | log
+ regress_testsub | regress_subscription_user | f | {testpub} | f | on | p | f | any | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist | 0/00000000 | {log}
(1 row)
ALTER SUBSCRIPTION regress_testsub SET (slot_name = NONE);
@@ -412,7 +412,7 @@ HINT: To initiate replication, you must manually create the replication slot, e
List of subscriptions
Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Retain dead tuples | Max retention duration | Retention active | Synchronous commit | Conninfo | Skip LSN | Conflict log destination
-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+------------------------+------------------+--------------------+-----------------------------+------------+--------------------------
- regress_testsub | regress_subscription_user | f | {testpub} | f | parallel | d | f | any | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist | 0/00000000 | log
+ regress_testsub | regress_subscription_user | f | {testpub} | f | parallel | d | f | any | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist | 0/00000000 | {log}
(1 row)
ALTER SUBSCRIPTION regress_testsub SET (disable_on_error = true);
@@ -420,7 +420,7 @@ ALTER SUBSCRIPTION regress_testsub SET (disable_on_error = true);
List of subscriptions
Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Retain dead tuples | Max retention duration | Retention active | Synchronous commit | Conninfo | Skip LSN | Conflict log destination
-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+------------------------+------------------+--------------------+-----------------------------+------------+--------------------------
- regress_testsub | regress_subscription_user | f | {testpub} | f | parallel | d | t | any | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist | 0/00000000 | log
+ regress_testsub | regress_subscription_user | f | {testpub} | f | parallel | d | t | any | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist | 0/00000000 | {log}
(1 row)
ALTER SUBSCRIPTION regress_testsub SET (slot_name = NONE);
@@ -436,7 +436,7 @@ HINT: To initiate replication, you must manually create the replication slot, e
List of subscriptions
Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Retain dead tuples | Max retention duration | Retention active | Synchronous commit | Conninfo | Skip LSN | Conflict log destination
-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+------------------------+------------------+--------------------+-----------------------------+------------+--------------------------
- regress_testsub | regress_subscription_user | f | {testpub} | f | parallel | d | f | any | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist | 0/00000000 | log
+ regress_testsub | regress_subscription_user | f | {testpub} | f | parallel | d | f | any | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist | 0/00000000 | {log}
(1 row)
ALTER SUBSCRIPTION regress_testsub SET (slot_name = NONE);
@@ -453,7 +453,7 @@ HINT: To initiate replication, you must manually create the replication slot, e
List of subscriptions
Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Retain dead tuples | Max retention duration | Retention active | Synchronous commit | Conninfo | Skip LSN | Conflict log destination
-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+------------------------+------------------+--------------------+-----------------------------+------------+--------------------------
- regress_testsub | regress_subscription_user | f | {testpub} | f | parallel | d | f | any | t | f | f | f | 1000 | f | off | dbname=regress_doesnotexist | 0/00000000 | log
+ regress_testsub | regress_subscription_user | f | {testpub} | f | parallel | d | f | any | t | f | f | f | 1000 | f | off | dbname=regress_doesnotexist | 0/00000000 | {log}
(1 row)
-- ok
@@ -462,7 +462,7 @@ ALTER SUBSCRIPTION regress_testsub SET (max_retention_duration = 0);
List of subscriptions
Name | Owner | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Retain dead tuples | Max retention duration | Retention active | Synchronous commit | Conninfo | Skip LSN | Conflict log destination
-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+------------------------+------------------+--------------------+-----------------------------+------------+--------------------------
- regress_testsub | regress_subscription_user | f | {testpub} | f | parallel | d | f | any | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist | 0/00000000 | log
+ regress_testsub | regress_subscription_user | f | {testpub} | f | parallel | d | f | any | t | f | f | f | 0 | f | off | dbname=regress_doesnotexist | 0/00000000 | {log}
(1 row)
ALTER SUBSCRIPTION regress_testsub SET (slot_name = NONE);
@@ -523,7 +523,7 @@ DROP SUBSCRIPTION regress_testsub;
SET SESSION AUTHORIZATION 'regress_subscription_user';
-- fail - unrecognized format value
CREATE SUBSCRIPTION regress_conflict_fail CONNECTION 'dbname=regress_doesnotexist' PUBLICATION testpub WITH (connect = false, conflict_log_destination = 'invalid');
-ERROR: unrecognized conflict_log_destination value: "invalid"
+ERROR: unrecognized value for subscription parameter "conflict_log_destination": "invalid"
HINT: Valid values are "log", "table", and "all".
-- verify sublogdestination is 'log' and relid is 0 (InvalidOid) for default case
CREATE SUBSCRIPTION regress_conflict_log_default CONNECTION 'dbname=regress_doesnotexist' PUBLICATION testpub WITH (connect = false);
@@ -533,7 +533,7 @@ SELECT subname, sublogdestination, subconflictlogrelid
FROM pg_subscription WHERE subname = 'regress_conflict_log_default';
subname | sublogdestination | subconflictlogrelid
------------------------------+-------------------+---------------------
- regress_conflict_log_default | log | 0
+ regress_conflict_log_default | {log} | 0
(1 row)
-- verify empty string defaults to 'log'
@@ -544,11 +544,11 @@ SELECT subname, sublogdestination, subconflictlogrelid
FROM pg_subscription WHERE subname = 'regress_conflict_empty_str';
subname | sublogdestination | subconflictlogrelid
----------------------------+-------------------+---------------------
- regress_conflict_empty_str | log | 0
+ regress_conflict_empty_str | {log} | 0
(1 row)
-- this should generate an internal table named conflict_log_table_$subid$
-CREATE SUBSCRIPTION regress_conflict_test1 CONNECTION 'dbname=regress_doesnotexist' PUBLICATION testpub WITH (connect = false, conflict_log_destination = 'table');
+CREATE SUBSCRIPTION regress_conflict_test1 CONNECTION 'dbname=regress_doesnotexist' PUBLICATION testpub WITH (connect = false, conflict_log_destination = 'log, table');
WARNING: subscription was created, but is not connected
HINT: To initiate replication, you must manually create the replication slot, enable the subscription, and alter the subscription to refresh publications.
-- check metadata in pg_subscription: destination should be 'table' and relid valid
@@ -556,7 +556,7 @@ SELECT subname, sublogdestination, subconflictlogrelid > 0 AS has_relid
FROM pg_subscription WHERE subname = 'regress_conflict_test1';
subname | sublogdestination | has_relid
------------------------+-------------------+-----------
- regress_conflict_test1 | table | t
+ regress_conflict_test1 | {log,table} | t
(1 row)
-- verify the physical table exists and its OID matches subconflictlogrelid
@@ -581,17 +581,27 @@ WHERE s.subname = 'regress_conflict_test1' AND a.attnum > 0;
(1 row)
-- ALTER: State transitions
--- transition from 'log' to 'all'
+-- transition from 'log' to 'log, table'
CREATE SUBSCRIPTION regress_conflict_test2 CONNECTION 'dbname=regress_doesnotexist' PUBLICATION testpub WITH (connect = false, conflict_log_destination = 'log');
WARNING: subscription was created, but is not connected
HINT: To initiate replication, you must manually create the replication slot, enable the subscription, and alter the subscription to refresh publications.
+ALTER SUBSCRIPTION regress_conflict_test2 SET (conflict_log_destination = 'log, table');
+-- verify metadata after ALTER (destination should be 'log, table')
+SELECT subname, sublogdestination, subconflictlogrelid > 0 AS has_relid
+FROM pg_subscription WHERE subname = 'regress_conflict_test2';
+ subname | sublogdestination | has_relid
+------------------------+-------------------+-----------
+ regress_conflict_test2 | {log,table} | t
+(1 row)
+
+-- transition from 'log, table' to 'all'
ALTER SUBSCRIPTION regress_conflict_test2 SET (conflict_log_destination = 'all');
-- verify metadata after ALTER (destination should be 'all')
SELECT subname, sublogdestination, subconflictlogrelid > 0 AS has_relid
FROM pg_subscription WHERE subname = 'regress_conflict_test2';
subname | sublogdestination | has_relid
------------------------+-------------------+-----------
- regress_conflict_test2 | all | t
+ regress_conflict_test2 | {all} | t
(1 row)
-- transition from 'all' to 'table' (should NOT drop the table, only change destination string)
@@ -601,7 +611,7 @@ SELECT sublogdestination, subconflictlogrelid = :old_relid AS relid_unchanged
FROM pg_subscription WHERE subname = 'regress_conflict_test2';
sublogdestination | relid_unchanged
-------------------+-----------------
- table | t
+ {table} | t
(1 row)
-- transition from 'table' to 'log' (should drop the table and clear relid)
@@ -610,7 +620,7 @@ SELECT sublogdestination, subconflictlogrelid
FROM pg_subscription WHERE subname = 'regress_conflict_test2';
sublogdestination | subconflictlogrelid
-------------------+---------------------
- log | 0
+ {log} | 0
(1 row)
-- verify the physical table is gone
diff --git a/src/test/regress/sql/subscription.sql b/src/test/regress/sql/subscription.sql
index b4b98c9a178..b437c383a4e 100644
--- a/src/test/regress/sql/subscription.sql
+++ b/src/test/regress/sql/subscription.sql
@@ -385,7 +385,7 @@ SELECT subname, sublogdestination, subconflictlogrelid
FROM pg_subscription WHERE subname = 'regress_conflict_empty_str';
-- this should generate an internal table named conflict_log_table_$subid$
-CREATE SUBSCRIPTION regress_conflict_test1 CONNECTION 'dbname=regress_doesnotexist' PUBLICATION testpub WITH (connect = false, conflict_log_destination = 'table');
+CREATE SUBSCRIPTION regress_conflict_test1 CONNECTION 'dbname=regress_doesnotexist' PUBLICATION testpub WITH (connect = false, conflict_log_destination = 'log, table');
-- check metadata in pg_subscription: destination should be 'table' and relid valid
SELECT subname, sublogdestination, subconflictlogrelid > 0 AS has_relid
@@ -405,8 +405,15 @@ JOIN pg_subscription s ON c.relname = 'conflict_log_table_' || s.oid
WHERE s.subname = 'regress_conflict_test1' AND a.attnum > 0;
-- ALTER: State transitions
--- transition from 'log' to 'all'
+-- transition from 'log' to 'log, table'
CREATE SUBSCRIPTION regress_conflict_test2 CONNECTION 'dbname=regress_doesnotexist' PUBLICATION testpub WITH (connect = false, conflict_log_destination = 'log');
+ALTER SUBSCRIPTION regress_conflict_test2 SET (conflict_log_destination = 'log, table');
+
+-- verify metadata after ALTER (destination should be 'log, table')
+SELECT subname, sublogdestination, subconflictlogrelid > 0 AS has_relid
+FROM pg_subscription WHERE subname = 'regress_conflict_test2';
+
+-- transition from 'log, table' to 'all'
ALTER SUBSCRIPTION regress_conflict_test2 SET (conflict_log_destination = 'all');
-- verify metadata after ALTER (destination should be 'all')
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 21826be5bd7..65ba5074331 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -501,8 +501,9 @@ ConditionalStack
ConfigData
ConfigVariable
ConflictLogColumnDef
+ConflictLogDest
ConflictTupleInfo
-ConflictType
+ConflictTyp
ConnCacheEntry
ConnCacheKey
ConnParams
--
2.43.0