From ca30f6e0ceebc319f6bf41d29aa6af0ac992881c Mon Sep 17 00:00:00 2001 From: Vignesh C Date: Tue, 3 Nov 2026 07:12:58 +0530 Subject: [PATCH v91 2/3] Preserve conflict log destination and subscription OID for subscriptions Support pg_dump to dump and restore the conflict_log_destination setting for subscriptions. During a normal CREATE SUBSCRIPTION, a conflict log table is created automatically when required. However, during binary upgrade, the conflict log table will already exist and must be reused rather than recreated, and the subscription must retain its original OID to correctly re-establish catalog relationships. To ensure correct behavior, pg_dump now emits an ALTER SUBSCRIPTION command after subscription creation to restore the conflict_log_destination setting. --- src/backend/commands/subscriptioncmds.c | 56 +++++++-- src/backend/replication/logical/conflict.c | 2 +- src/backend/utils/adt/pg_upgrade_support.c | 10 ++ src/bin/pg_dump/pg_dump.c | 107 +++++++++++++++++- src/bin/pg_dump/pg_dump.h | 2 + src/bin/pg_dump/pg_dump_sort.c | 40 +++++++ src/bin/pg_dump/t/002_pg_dump.pl | 46 +++++++- src/bin/pg_upgrade/pg_upgrade.c | 4 + src/bin/pg_upgrade/t/004_subscription.pl | 29 ++++- src/include/catalog/binary_upgrade.h | 1 + src/include/catalog/pg_proc.dat | 4 + src/include/catalog/pg_subscription.h | 3 + .../expected/spgist_name_ops.out | 6 +- 13 files changed, 293 insertions(+), 17 deletions(-) diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c index bed27e3b35e..ecc7fcf8a5f 100644 --- a/src/backend/commands/subscriptioncmds.c +++ b/src/backend/commands/subscriptioncmds.c @@ -19,6 +19,7 @@ #include "access/table.h" #include "access/twophase.h" #include "access/xact.h" +#include "catalog/binary_upgrade.h" #include "catalog/catalog.h" #include "catalog/dependency.h" #include "catalog/indexing.h" @@ -88,6 +89,12 @@ /* check if the 'val' has 'bits' set */ #define IsSet(val, bits) (((val) & (bits)) == (bits)) +/* + * This will be set by the pg_upgrade_support function -- + * binary_upgrade_set_next_pg_subscription_oid(). + */ +Oid binary_upgrade_next_pg_subscription_oid = InvalidOid; + /* * Structure to hold a bitmap representing the user-provided CREATE/ALTER * SUBSCRIPTION command options and the parsed/default values of each of them. @@ -846,8 +853,21 @@ CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt, memset(values, 0, sizeof(values)); memset(nulls, false, sizeof(nulls)); - subid = GetNewOidWithIndex(rel, SubscriptionObjectIndexId, - Anum_pg_subscription_oid); + /* Use binary-upgrade override for pg_subscription.oid? */ + if (IsBinaryUpgrade) + { + if (!OidIsValid(binary_upgrade_next_pg_subscription_oid)) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("pg_subscription OID value not set when in binary upgrade mode"))); + + subid = binary_upgrade_next_pg_subscription_oid; + binary_upgrade_next_pg_subscription_oid = InvalidOid; + } + else + subid = GetNewOidWithIndex(rel, SubscriptionObjectIndexId, + Anum_pg_subscription_oid); + values[Anum_pg_subscription_oid - 1] = ObjectIdGetDatum(subid); values[Anum_pg_subscription_subdbid - 1] = ObjectIdGetDatum(MyDatabaseId); values[Anum_pg_subscription_subskiplsn - 1] = LSNGetDatum(InvalidXLogRecPtr); @@ -1639,18 +1659,40 @@ alter_sub_conflict_log_dest(Subscription *sub, ConflictLogDest oldlogdest, { ObjectAddress cltaddr; ObjectAddress subobj; + char relname[NAMEDATALEN]; - relid = create_conflict_log_table(sub->oid, sub->name, sub->owner); - update_relid = true; + snprintf(relname, NAMEDATALEN, CONFLICT_LOG_RELATION_NAME_FMT, sub->oid); /* - * Establish an internal dependency between the conflict log table - * and the subscription. For details refer comments in - * CreateSubscription function. + * In upgrade scenarios, old_dest reflects the default behavior of + * a newly created subscription (i.e., no conflict logging to + * table). However, the conflict log table will already exist from + * the upgraded cluster. In such cases, we need to detect the + * pre-existing table and update the catalog state to associate it + * with the subscription instead of creating a new one. + */ + relid = get_relname_relid(relname, PG_CONFLICT_NAMESPACE); + if (OidIsValid(relid)) + { + /* Existing table from upgrade */ + Assert(IsBinaryUpgrade); + } + else + { + relid = create_conflict_log_table(sub->oid, sub->name, + sub->owner); + } + + /* + * Establish an internal dependency between the conflict log + * table and the subscription. Refer to comments in the + * CreateSubscription function for details. */ ObjectAddressSet(cltaddr, RelationRelationId, relid); ObjectAddressSet(subobj, SubscriptionRelationId, sub->oid); recordDependencyOn(&cltaddr, &subobj, DEPENDENCY_INTERNAL); + + update_relid = true; } } diff --git a/src/backend/replication/logical/conflict.c b/src/backend/replication/logical/conflict.c index 9ba885da4a0..00cd575b9f2 100644 --- a/src/backend/replication/logical/conflict.c +++ b/src/backend/replication/logical/conflict.c @@ -211,7 +211,7 @@ create_conflict_log_table(Oid subid, char *subname, Oid subowner) Oid relid; char relname[NAMEDATALEN]; - snprintf(relname, NAMEDATALEN, "pg_conflict_log_%u", subid); + snprintf(relname, NAMEDATALEN, CONFLICT_LOG_RELATION_NAME_FMT, subid); /* Build the tuple descriptor for the new table. */ tupdesc = create_conflict_log_table_tupdesc(); diff --git a/src/backend/utils/adt/pg_upgrade_support.c b/src/backend/utils/adt/pg_upgrade_support.c index f5017022d2e..9152f5cfd76 100644 --- a/src/backend/utils/adt/pg_upgrade_support.c +++ b/src/backend/utils/adt/pg_upgrade_support.c @@ -192,6 +192,16 @@ binary_upgrade_set_next_pg_authid_oid(PG_FUNCTION_ARGS) PG_RETURN_VOID(); } +Datum +binary_upgrade_set_next_pg_subscription_oid(PG_FUNCTION_ARGS) +{ + Oid subid = PG_GETARG_OID(0); + + CHECK_IS_BINARY_UPGRADE; + binary_upgrade_next_pg_subscription_oid = subid; + PG_RETURN_VOID(); +} + Datum binary_upgrade_create_empty_extension(PG_FUNCTION_ARGS) { diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 69171d6b859..4e06910dda7 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -2050,9 +2050,34 @@ selectDumpableNamespace(NamespaceInfo *nsinfo, Archive *fout) static void selectDumpableTable(TableInfo *tbinfo, Archive *fout) { + DumpOptions *dopt = fout->dopt; + if (checkExtensionMembership(&tbinfo->dobj, fout)) return; /* extension membership overrides all else */ + if (strcmp(tbinfo->dobj.namespace->dobj.name, "pg_conflict") == 0) + { + /* + * Conflict log tables are dumped only during binary upgrade, where the + * table must be restored with the same OIDs and filenode so that the + * ALTER SUBSCRIPTION emitted by dumpSubscription() can reuse it. + * Otherwise the table is created again when the subscription's + * conflict_log_destination is set. Also dump the privileges that were + * granted on the table, for example to let non-superusers delete + * conflicts. + * + * The pg_conflict schema itself is created by initdb and is not dumped, + * so the tables in it are selected here, regardless of the schema and + * table switches. + */ + if (dopt->binary_upgrade) + tbinfo->dobj.dump = DUMP_COMPONENT_DEFINITION | DUMP_COMPONENT_ACL; + else + tbinfo->dobj.dump = DUMP_COMPONENT_NONE; + + return; + } + /* * If specific tables are being dumped, dump just those tables; else, dump * according to the parent namespace's dump flag. @@ -5136,6 +5161,8 @@ getSubscriptions(Archive *fout) int i_subfailover; int i_subretaindeadtuples; int i_submaxretention; + int i_subconflictlogrelid; + int i_sublogdestination; int i, ntups; @@ -5234,9 +5261,16 @@ getSubscriptions(Archive *fout) " '-1' AS subwalrcvtimeout,\n"); if (fout->remoteVersion >= 190000) - appendPQExpBufferStr(query, " fs.srvname AS subservername\n"); + appendPQExpBufferStr(query, " fs.srvname AS subservername,\n"); + else + appendPQExpBufferStr(query, " NULL AS subservername,\n"); + + if (fout->remoteVersion >= 200000) + appendPQExpBufferStr(query, + " s.subconflictlogrelid, s.subconflictlogdest\n"); else - appendPQExpBufferStr(query, " NULL AS subservername\n"); + appendPQExpBufferStr(query, + " NULL AS subconflictlogrelid, NULL AS subconflictlogdest\n"); appendPQExpBufferStr(query, "FROM pg_subscription s\n"); @@ -5285,6 +5319,8 @@ getSubscriptions(Archive *fout) i_subpublications = PQfnumber(res, "subpublications"); i_suborigin = PQfnumber(res, "suborigin"); i_suboriginremotelsn = PQfnumber(res, "suboriginremotelsn"); + i_subconflictlogrelid = PQfnumber(res, "subconflictlogrelid"); + i_sublogdestination = PQfnumber(res, "subconflictlogdest"); subinfo = pg_malloc_array(SubscriptionInfo, ntups); @@ -5343,6 +5379,32 @@ getSubscriptions(Archive *fout) subinfo[i].suboriginremotelsn = pg_strdup(PQgetvalue(res, i, i_suboriginremotelsn)); + if (PQgetisnull(res, i, i_subconflictlogrelid)) + subinfo[i].subconflictlogrelid = InvalidOid; + else + { + subinfo[i].subconflictlogrelid = + atooid(PQgetvalue(res, i, i_subconflictlogrelid)); + + if (subinfo[i].subconflictlogrelid) + { + TableInfo *tableInfo; + + tableInfo = findTableByOid(subinfo[i].subconflictlogrelid); + if (!tableInfo) + pg_fatal("could not find conflict log table with OID %u", + subinfo[i].subconflictlogrelid); + + addObjectDependency(&subinfo[i].dobj, tableInfo->dobj.dumpId); + } + } + + if (PQgetisnull(res, i, i_sublogdestination)) + subinfo[i].subconflictlogdest = NULL; + else + subinfo[i].subconflictlogdest = + pg_strdup(PQgetvalue(res, i, i_sublogdestination)); + /* Decide whether we want to dump it */ selectDumpableObject(&(subinfo[i].dobj), fout); } @@ -5535,6 +5597,14 @@ dumpSubscription(Archive *fout, const SubscriptionInfo *subinfo) appendPQExpBuffer(delq, "DROP SUBSCRIPTION %s;\n", qsubname); + if (dopt->binary_upgrade) + { + appendPQExpBufferStr(query, "\n-- For binary upgrade, must preserve pg_subscription.oid\n"); + appendPQExpBuffer(query, + "SELECT pg_catalog.binary_upgrade_set_next_pg_subscription_oid('%u'::pg_catalog.oid);\n\n", + subinfo->dobj.catId.oid); + } + appendPQExpBuffer(query, "CREATE SUBSCRIPTION %s ", qsubname); if (subinfo->subservername) @@ -5608,6 +5678,28 @@ dumpSubscription(Archive *fout, const SubscriptionInfo *subinfo) appendPQExpBufferStr(query, ");\n"); + /* + * Restore the conflict log destination separately from CREATE SUBSCRIPTION. + * Setting conflict_log_destination to 'table' may create and associate + * a conflict log table whose name is derived from the subscription OID. + * Since the subscription must already exist before that OID is known, + * emit this as a separate ALTER SUBSCRIPTION so that any required conflict + * log table can be created and linked after the subscription itself has + * been restored. + * + * We skip the default value ('log') to match the handling of other + * subscription options. + */ + if (subinfo->subconflictlogdest && + (pg_strcasecmp(subinfo->subconflictlogdest, "log") != 0)) + { + appendPQExpBuffer(query, + "\nALTER SUBSCRIPTION %s SET (conflict_log_destination = ", + qsubname); + appendStringLiteralAH(query, subinfo->subconflictlogdest, fout); + appendPQExpBufferStr(query, ");\n"); + } + /* * In binary-upgrade mode, we allow the replication to continue after the * upgrade. @@ -17029,6 +17121,15 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo) int j, k; + /* + * Do not emit "ALTER TABLE ... OWNER TO ..." for a conflict log table: + * changing its owner is not allowed. Its owner follows the owner of the + * subscription, and is set when the ALTER SUBSCRIPTION ... OWNER TO of the + * dump is restored. + */ + bool conflict_log_table = + (strcmp(tbinfo->dobj.namespace->dobj.name, "pg_conflict") == 0); + /* We had better have loaded per-column details about this table */ Assert(tbinfo->interesting); @@ -17930,7 +18031,7 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo) .tablespace = tablespace, .tableam = tableam, .relkind = tbinfo->relkind, - .owner = tbinfo->rolname, + .owner = conflict_log_table ? NULL : tbinfo->rolname, .description = reltypename, .section = tbinfo->postponed_def ? SECTION_POST_DATA : SECTION_PRE_DATA, diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h index 4dcb6c854e8..7cf7520908a 100644 --- a/src/bin/pg_dump/pg_dump.h +++ b/src/bin/pg_dump/pg_dump.h @@ -720,6 +720,7 @@ typedef struct _SubscriptionInfo bool subfailover; bool subretaindeadtuples; int submaxretention; + Oid subconflictlogrelid; char *subservername; char *subconninfo; char *subslotname; @@ -728,6 +729,7 @@ typedef struct _SubscriptionInfo char *subpublications; char *suborigin; char *suboriginremotelsn; + char *subconflictlogdest; } SubscriptionInfo; /* diff --git a/src/bin/pg_dump/pg_dump_sort.c b/src/bin/pg_dump/pg_dump_sort.c index 4f3469d4396..c37bc145a95 100644 --- a/src/bin/pg_dump/pg_dump_sort.c +++ b/src/bin/pg_dump/pg_dump_sort.c @@ -1129,6 +1129,28 @@ repairTableAttrDefMultiLoop(DumpableObject *tableobj, addObjectDependency(attrdefobj, tableobj->dumpId); } +/* + * A subscription and its conflict log table depend on each other. + * + * pg_depend records an internal dependency of the table on the subscription + * (so that dropping the subscription drops the table), which makes pg_dump + * want the subscription first. In the other direction, getSubscriptions() + * makes the subscription depend on its table: the ALTER SUBSCRIPTION that + * restores conflict_log_destination looks up the table by name and, in + * binary-upgrade mode, reuses it, so the table must already exist. + * + * Break the loop by removing the table's dependency on the subscription. + * This dependency is not needed to establish the restore order. The + * ALTER SUBSCRIPTION that associates the table with the subscription + * records the internal dependency again. + */ +static void +repairSubscriptionTableLoop(DumpableObject *subobj, DumpableObject *tableobj) +{ + /* Remove table's dependency on subscription */ + removeObjectDependency(tableobj, subobj->dumpId); +} + /* * CHECK, NOT NULL constraints on domains work just like those on tables ... */ @@ -1359,6 +1381,24 @@ repairDependencyLoop(DumpableObject **loop, return; } + /* + * Subscription and its Conflict Log Table + */ + if (nLoop == 2 && + loop[0]->objType == DO_TABLE && + loop[1]->objType == DO_SUBSCRIPTION) + { + repairSubscriptionTableLoop(loop[1], loop[0]); + return; + } + if (nLoop == 2 && + loop[0]->objType == DO_SUBSCRIPTION && + loop[1]->objType == DO_TABLE) + { + repairSubscriptionTableLoop(loop[0], loop[1]); + return; + } + /* index on partitioned table and corresponding index on partition */ if (nLoop == 2 && loop[0]->objType == DO_INDEX && diff --git a/src/bin/pg_dump/t/002_pg_dump.pl b/src/bin/pg_dump/t/002_pg_dump.pl index c89d699e816..4535dfc2f57 100644 --- a/src/bin/pg_dump/t/002_pg_dump.pl +++ b/src/bin/pg_dump/t/002_pg_dump.pl @@ -3346,13 +3346,22 @@ my %tests = ( }, }, + # The default destination, "log", is not dumped. + 'ALTER SUBSCRIPTION sub2 SET (conflict_log_destination)' => { + regexp => qr/^ + \QALTER SUBSCRIPTION sub2 SET (conflict_log_destination\E + /xm, + like => {}, + }, + 'CREATE SUBSCRIPTION sub3' => { create_order => 50, create_sql => 'CREATE SUBSCRIPTION sub3 CONNECTION \'dbname=doesnotexist\' PUBLICATION pub1 - WITH (connect = false, origin = any, streaming = on);', + WITH (connect = false, origin = any, streaming = on, conflict_log_destination = table);', regexp => qr/^ - \QCREATE SUBSCRIPTION sub3 CONNECTION 'dbname=doesnotexist' PUBLICATION pub1 WITH (connect = false, slot_name = 'sub3', streaming = on);\E + \QCREATE SUBSCRIPTION sub3 CONNECTION 'dbname=doesnotexist' PUBLICATION pub1 WITH (connect = false, slot_name = 'sub3', streaming = on);\E\n+ + \QALTER SUBSCRIPTION sub3 SET (conflict_log_destination = 'table');\E /xm, like => { %full_runs, section_post_data => 1, }, unlike => { @@ -3361,6 +3370,39 @@ my %tests = ( }, }, + # In binary-upgrade mode, the subscription OID is preserved and the + # conflict log table is dumped, to be reused by the ALTER SUBSCRIPTION + # ßabove. + 'binary upgrade: pg_subscription OID of sub3' => { + regexp => qr/^ + \Q-- For binary upgrade, must preserve pg_subscription.oid\E\n + \QSELECT pg_catalog.binary_upgrade_set_next_pg_subscription_oid(\E'\d+'\Q::pg_catalog.oid);\E\n+ + \QCREATE SUBSCRIPTION sub3 \E + /xm, + like => { binary_upgrade => 1, }, + }, + + 'binary upgrade: conflict log table of sub3' => { + regexp => qr/^ + \QCREATE TABLE pg_conflict.pg_conflict_log_\E\d+\Q (\E + /xm, + like => { binary_upgrade => 1, }, + }, + + 'CREATE SUBSCRIPTION sub4' => { + create_order => 50, + create_sql => 'CREATE SUBSCRIPTION sub4 + CONNECTION \'dbname=doesnotexist\' PUBLICATION pub1 + WITH (connect = false, conflict_log_destination = all);', + regexp => qr/^ + \QALTER SUBSCRIPTION sub4 SET (conflict_log_destination = 'all');\E + /xm, + like => { %full_runs, section_post_data => 1, }, + unlike => { + no_subscriptions => 1, + no_subscriptions_restore => 1, + }, + }, # Regardless of whether the table or schema is excluded, publications must # still be dumped, as excluded objects do not apply to publications. We diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 6d01084e4b0..6a46ceca83c 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -35,6 +35,10 @@ * * We control all assignments of pg_database.oid because we want the directory * names to match between the old and new cluster. + * + * We control assignment of pg_subscription.oid because we want the oid to + * match between the old and new cluster to make use of subscription's + * conflict log table which is named using the subscription oid. */ diff --git a/src/bin/pg_upgrade/t/004_subscription.pl b/src/bin/pg_upgrade/t/004_subscription.pl index 36f059faa2e..534a69f6311 100644 --- a/src/bin/pg_upgrade/t/004_subscription.pl +++ b/src/bin/pg_upgrade/t/004_subscription.pl @@ -290,7 +290,7 @@ $publisher->safe_psql( $old_sub->safe_psql( 'postgres', qq[ CREATE TABLE tab_upgraded2(id int); - CREATE SUBSCRIPTION regress_sub5 CONNECTION '$connstr' PUBLICATION regress_pub5; + CREATE SUBSCRIPTION regress_sub5 CONNECTION '$connstr' PUBLICATION regress_pub5 with (conflict_log_destination = 'table'); ]); # The table tab_upgraded2 will be in the init state as the subscriber's @@ -312,7 +312,19 @@ my $tab_upgraded1_oid = $old_sub->safe_psql('postgres', "SELECT oid FROM pg_class WHERE relname = 'tab_upgraded1'"); my $tab_upgraded2_oid = $old_sub->safe_psql('postgres', "SELECT oid FROM pg_class WHERE relname = 'tab_upgraded2'"); - +my $sub5_oid = $old_sub->safe_psql('postgres', + "SELECT oid FROM pg_subscription where subname = 'regress_sub5'"); +my $sub_clt_relid = $old_sub->safe_psql('postgres', + "SELECT subconflictlogrelid FROM pg_subscription WHERE subname = 'regress_sub5'"); + +# A privilege granted on the conflict log table must survive the upgrade. +my $sub_clt_name = $old_sub->safe_psql('postgres', + "SELECT relname FROM pg_class WHERE oid = $sub_clt_relid"); +$old_sub->safe_psql( + 'postgres', qq[ + CREATE ROLE regress_clt_reader; + GRANT DELETE ON pg_conflict.$sub_clt_name TO regress_clt_reader; +]); $old_sub->stop; # Change configuration so that initial table sync does not get started @@ -394,6 +406,19 @@ $result = $new_sub->safe_psql('postgres', ); is($result, qq(t), "conflict detection slot exists"); +# The subscription oid and the subscription conflict log table relid should be preserved +$result = $new_sub->safe_psql('postgres', "SELECT oid FROM pg_subscription WHERE subname = 'regress_sub5'"); +is($result, qq($sub5_oid), "subscription oid should have been preserved"); + +$result = $new_sub->safe_psql('postgres', "SELECT subconflictlogrelid FROM pg_subscription WHERE subname = 'regress_sub5'"); +is($result, qq($sub_clt_relid), "subscription conflict log table relid should have been preserved"); + +$result = $new_sub->safe_psql('postgres', + "SELECT has_table_privilege('regress_clt_reader', $sub_clt_relid, 'DELETE'), has_table_privilege('regress_clt_reader', $sub_clt_relid, 'INSERT')" +); +is($result, qq(t|f), + "privileges granted on the subscription conflict log table should have been preserved"); + # Resume the initial sync and wait until all tables of subscription # 'regress_sub5' are synchronized $new_sub->append_conf('postgresql.conf', diff --git a/src/include/catalog/binary_upgrade.h b/src/include/catalog/binary_upgrade.h index 117f3e3f774..ba23b042a75 100644 --- a/src/include/catalog/binary_upgrade.h +++ b/src/include/catalog/binary_upgrade.h @@ -33,6 +33,7 @@ extern PGDLLIMPORT Oid binary_upgrade_next_toast_chunk_id_typoid; extern PGDLLIMPORT Oid binary_upgrade_next_pg_enum_oid; extern PGDLLIMPORT Oid binary_upgrade_next_pg_authid_oid; +extern PGDLLIMPORT Oid binary_upgrade_next_pg_subscription_oid; extern PGDLLIMPORT bool binary_upgrade_record_init_privs; diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 9b78fcad414..ed07d7aa88b 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -12059,6 +12059,10 @@ proisstrict => 'f', provolatile => 'v', proparallel => 'u', prorettype => 'void', proargtypes => '', prosrc => 'binary_upgrade_create_conflict_detection_slot' }, +{ oid => '8407', descr => 'for use by pg_upgrade', + proname => 'binary_upgrade_set_next_pg_subscription_oid', provolatile => 'v', + proparallel => 'r', prorettype => 'void', proargtypes => 'oid', + prosrc => 'binary_upgrade_set_next_pg_subscription_oid' }, # conversion functions { oid => '4310', descr => 'internal conversion function for KOI8R to WIN1251', diff --git a/src/include/catalog/pg_subscription.h b/src/include/catalog/pg_subscription.h index b860f02d166..2408288b202 100644 --- a/src/include/catalog/pg_subscription.h +++ b/src/include/catalog/pg_subscription.h @@ -219,6 +219,9 @@ typedef struct Subscription */ #define LOGICALREP_STREAM_PARALLEL 'p' +/* Conflict log table name format. %u is replaced with the subscription OID. */ +#define CONFLICT_LOG_RELATION_NAME_FMT "pg_conflict_log_%u" + #endif /* EXPOSE_TO_CLIENT_CODE */ extern Subscription *GetSubscription(Oid subid, bool missing_ok); diff --git a/src/test/modules/spgist_name_ops/expected/spgist_name_ops.out b/src/test/modules/spgist_name_ops/expected/spgist_name_ops.out index 35e59d0cd83..af8b929bb5b 100644 --- a/src/test/modules/spgist_name_ops/expected/spgist_name_ops.out +++ b/src/test/modules/spgist_name_ops/expected/spgist_name_ops.out @@ -59,12 +59,13 @@ select * from t binary_upgrade_set_next_multirange_pg_type_oid | 1 | binary_upgrade_set_next_multirange_pg_type_oid binary_upgrade_set_next_pg_authid_oid | | binary_upgrade_set_next_pg_authid_oid binary_upgrade_set_next_pg_enum_oid | | binary_upgrade_set_next_pg_enum_oid + binary_upgrade_set_next_pg_subscription_oid | | binary_upgrade_set_next_pg_subscription_oid binary_upgrade_set_next_pg_tablespace_oid | | binary_upgrade_set_next_pg_tablespace_oid binary_upgrade_set_next_pg_type_oid | | binary_upgrade_set_next_pg_type_oid binary_upgrade_set_next_toast_chunk_id_typoid | | binary_upgrade_set_next_toast_chunk_id_typoid binary_upgrade_set_next_toast_pg_class_oid | 1 | binary_upgrade_set_next_toast_pg_class_oid binary_upgrade_set_next_toast_relfilenode | | binary_upgrade_set_next_toast_relfilenode -(14 rows) +(15 rows) -- Verify clean failure when INCLUDE'd columns result in overlength tuple -- The error message details are platform-dependent, so show only SQLSTATE @@ -109,12 +110,13 @@ select * from t binary_upgrade_set_next_multirange_pg_type_oid | 1 | binary_upgrade_set_next_multirange_pg_type_oid binary_upgrade_set_next_pg_authid_oid | | binary_upgrade_set_next_pg_authid_oid binary_upgrade_set_next_pg_enum_oid | | binary_upgrade_set_next_pg_enum_oid + binary_upgrade_set_next_pg_subscription_oid | | binary_upgrade_set_next_pg_subscription_oid binary_upgrade_set_next_pg_tablespace_oid | | binary_upgrade_set_next_pg_tablespace_oid binary_upgrade_set_next_pg_type_oid | | binary_upgrade_set_next_pg_type_oid binary_upgrade_set_next_toast_chunk_id_typoid | | binary_upgrade_set_next_toast_chunk_id_typoid binary_upgrade_set_next_toast_pg_class_oid | 1 | binary_upgrade_set_next_toast_pg_class_oid binary_upgrade_set_next_toast_relfilenode | | binary_upgrade_set_next_toast_relfilenode -(14 rows) +(15 rows) \set VERBOSITY sqlstate insert into t values(repeat('xyzzy', 12), 42, repeat('xyzzy', 4000)); -- 2.54.0 (Apple Git-157)