From 0961f835e70d1ee4fa784927e9d9c91f213e5a99 Mon Sep 17 00:00:00 2001 From: Ajin Cherian Date: Wed, 22 Apr 2026 18:27:45 +1000 Subject: [PATCH v2] Preserve replication origin OIDs in pg_upgrade Migrate all replication origins during pg_upgrade with special handling of replication origins of subscribers. When pg_upgrade migrates a subscriber, the replication origin OIDs (roident) assigned to subscriptions can change across the upgrade. This is a problem because commit-timestamp records embed roident and are copied directly from the old cluster's pg_commit_ts directory, causing spurious "update_origin_differs" conflicts after the upgrade. Fix this by skipping replorigin_create() in CreateSubscription() during binary-upgrade mode, and instead adding a new helper function binary_upgrade_set_next_replorigin_oid(oid, subname) that creates the replication origin with the preserved roident from the old cluster. pg_dump is extended to emit this call before the existing binary_upgrade_replorigin_advance() in the binary-upgrade script. --- src/backend/commands/subscriptioncmds.c | 10 ++- src/backend/replication/logical/origin.c | 72 ++++++++++++++++++++ src/backend/utils/adt/pg_upgrade_support.c | 76 ++++++++++++++++++++++ src/bin/pg_dump/pg_dump.c | 35 ++++++++++ src/bin/pg_dump/pg_dump.h | 1 + src/bin/pg_dump/pg_dumpall.c | 66 +++++++++++++++++++ src/bin/pg_upgrade/check.c | 11 ++-- src/bin/pg_upgrade/info.c | 11 +++- src/bin/pg_upgrade/pg_upgrade.h | 1 + src/bin/pg_upgrade/t/004_subscription.pl | 32 +++++++++ src/include/catalog/binary_upgrade.h | 2 + src/include/catalog/pg_proc.dat | 11 ++++ src/include/replication/origin.h | 1 + 13 files changed, 320 insertions(+), 9 deletions(-) diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c index d512e87cfe3..3788671506c 100644 --- a/src/backend/commands/subscriptioncmds.c +++ b/src/backend/commands/subscriptioncmds.c @@ -846,9 +846,15 @@ CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt, * apply workers initialization, and to handle origin creation dynamically * when tables are added to the subscription. It is not clear whether * preventing creation of origins is worth additional complexity. + * + * In binary-upgrade mode, skip origin creation here. This is required to + * preserve the roident from the old cluster for this subscription. */ - ReplicationOriginNameForLogicalRep(subid, InvalidOid, originname, sizeof(originname)); - replorigin_create(originname); + if (!IsBinaryUpgrade) + { + ReplicationOriginNameForLogicalRep(subid, InvalidOid, originname, sizeof(originname)); + replorigin_create(originname); + } /* * Connect to remote side to execute requested commands and fetch table diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c index c9dfb094c2b..3c5c2246df3 100644 --- a/src/backend/replication/logical/origin.c +++ b/src/backend/replication/logical/origin.c @@ -379,6 +379,78 @@ replorigin_create(const char *roname) return roident; } +/* + * TODO: unify with replorigin_create(). + * + * XXX: Should we put this function in pg_upgrade_support.c, because it's + * usable only while upgrading? + */ +ReplOriginId +replorigin_create_with_reploriginid(ReplOriginId node, const char *roname) +{ + HeapTuple tuple = NULL; + Relation rel; + Datum roname_d; + SysScanDesc scan; + ScanKeyData key; + bool nulls[Natts_pg_replication_origin]; + Datum values[Natts_pg_replication_origin]; + bool collides; + + Assert(node != InvalidReplOriginId); + + /* + * To avoid needing a TOAST table for pg_replication_origin, we limit + * replication origin names to 512 bytes. This should be more than enough + * for all practical use. + */ + if (strlen(roname) > MAX_RONAME_LEN) + ereport(ERROR, + (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), + errmsg("replication origin name is too long"), + errdetail("Replication origin names must be no longer than %d bytes.", + MAX_RONAME_LEN))); + + roname_d = CStringGetTextDatum(roname); + + Assert(IsTransactionState()); + + rel = table_open(ReplicationOriginRelationId, ExclusiveLock); + + Assert(!OidIsValid(rel->rd_rel->reltoastrelid)); + + ScanKeyInit(&key, + Anum_pg_replication_origin_roident, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(node)); + scan = systable_beginscan(rel, ReplicationOriginIdentIndex, + true /* indexOK */ , + SnapshotSelf, + 1, &key); + collides = HeapTupleIsValid(systable_getnext(scan)); + + if (collides) + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("replication origin ID %d already exists", node))); + + systable_endscan(scan); + + memset(&nulls, 0, sizeof(nulls)); + + values[Anum_pg_replication_origin_roident - 1] = ObjectIdGetDatum(node); + values[Anum_pg_replication_origin_roname - 1] = roname_d; + + tuple = heap_form_tuple(RelationGetDescr(rel), values, nulls); + CatalogTupleInsert(rel, tuple); + CommandCounterIncrement(); + + table_close(rel, ExclusiveLock); + + heap_freetuple(tuple); + return node; +} + /* * Helper function to drop a replication origin. */ diff --git a/src/backend/utils/adt/pg_upgrade_support.c b/src/backend/utils/adt/pg_upgrade_support.c index b505a6b4fee..06cb1465b20 100644 --- a/src/backend/utils/adt/pg_upgrade_support.c +++ b/src/backend/utils/adt/pg_upgrade_support.c @@ -28,6 +28,7 @@ #include "utils/array.h" #include "utils/builtins.h" #include "utils/lsyscache.h" +#include "utils/syscache.h" #include "utils/pg_lsn.h" @@ -181,6 +182,48 @@ binary_upgrade_set_next_pg_authid_oid(PG_FUNCTION_ARGS) PG_RETURN_VOID(); } +/* + * binary_upgrade_set_next_replorigin_oid + * + * Create the replication origin with the oid specified, preserving the + * origin id of the subscription from the old cluster. + * This must be called before binary_upgrade_replorigin_advance() for the + * same subscription. CreateSubscription() skips replorigin_create() in + * binary upgrade mode specifically to allow this function to control the + * roident. + */ +Datum +binary_upgrade_set_next_replorigin_oid(PG_FUNCTION_ARGS) +{ + ReplOriginId next_oid; + char *subname; + Oid subid; + char originname[NAMEDATALEN]; + + CHECK_IS_BINARY_UPGRADE; + + if (PG_ARGISNULL(0) || PG_ARGISNULL(1)) + elog(ERROR, + "null argument to binary_upgrade_set_next_replorigin_oid is not allowed"); + + next_oid = (ReplOriginId) PG_GETARG_OID(0); + subname = text_to_cstring(PG_GETARG_TEXT_PP(1)); + + if (next_oid == InvalidReplOriginId) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("replication origin OID must be valid"))); + + subid = get_subscription_oid(subname, false); + ReplicationOriginNameForLogicalRep(subid, InvalidOid, originname, + sizeof(originname)); + + /* Create the origin with the preserved OID from the old cluster */ + replorigin_create_with_reploriginid(next_oid, originname); + + PG_RETURN_VOID(); +} + Datum binary_upgrade_create_empty_extension(PG_FUNCTION_ARGS) { @@ -435,3 +478,36 @@ binary_upgrade_create_conflict_detection_slot(PG_FUNCTION_ARGS) PG_RETURN_VOID(); } + +Datum +binary_upgrade_create_replication_origin(PG_FUNCTION_ARGS) +{ + ReplOriginId node; + Name originname; + + CHECK_IS_BINARY_UPGRADE; + + /* NULL node id and origin name are not allowed */ + if (PG_ARGISNULL(0) || + PG_ARGISNULL(1)) + elog(ERROR, "null argument to binary_upgrade_create_replication_origin is not allowed"); + + node = PG_GETARG_OID(0); + originname = PG_GETARG_NAME(1); + + replorigin_create_with_reploriginid(node, NameStr(*originname)); + + if (!PG_ARGISNULL(2)) + { + XLogRecPtr remote_commit = PG_GETARG_LSN(2); + + /* Lock to prevent the replication origin from vanishing */ + LockRelationOid(ReplicationOriginRelationId, RowExclusiveLock); + replorigin_advance(node, remote_commit, InvalidXLogRecPtr, + false /* backward */ , + false /* WAL log */ ); + UnlockRelationOid(ReplicationOriginRelationId, RowExclusiveLock); + } + + PG_RETURN_VOID(); +} diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index d56dcc701ce..94699b60677 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -5180,6 +5180,7 @@ getSubscriptions(Archive *fout) int i_subpublications; int i_suborigin; int i_suboriginremotelsn; + int i_suboriginoid; int i_subenabled; int i_subfailover; int i_subretaindeadtuples; @@ -5254,6 +5255,11 @@ getSubscriptions(Archive *fout) appendPQExpBufferStr(query, " NULL AS suboriginremotelsn,\n" " false AS subenabled,\n"); + if (dopt->binary_upgrade && fout->remoteVersion >= 190000) + appendPQExpBufferStr(query, " ro.roident AS suboriginoid,\n"); + else + appendPQExpBufferStr(query, " NULL AS suboriginoid,\n"); + if (fout->remoteVersion >= 170000) appendPQExpBufferStr(query, " s.subfailover,\n"); @@ -5299,6 +5305,11 @@ getSubscriptions(Archive *fout) "LEFT JOIN pg_catalog.pg_replication_origin_status o \n" " ON o.external_id = 'pg_' || s.oid::text \n"); + if (dopt->binary_upgrade && fout->remoteVersion >= 190000) + appendPQExpBufferStr(query, + "LEFT JOIN pg_catalog.pg_replication_origin ro \n" + " ON ro.roname = 'pg_' || s.oid::text \n"); + appendPQExpBufferStr(query, "WHERE s.subdbid = (SELECT oid FROM pg_database\n" " WHERE datname = current_database())"); @@ -5333,6 +5344,7 @@ getSubscriptions(Archive *fout) i_subpublications = PQfnumber(res, "subpublications"); i_suborigin = PQfnumber(res, "suborigin"); i_suboriginremotelsn = PQfnumber(res, "suboriginremotelsn"); + i_suboriginoid = PQfnumber(res, "suboriginoid"); subinfo = pg_malloc_array(SubscriptionInfo, ntups); @@ -5390,6 +5402,11 @@ getSubscriptions(Archive *fout) else subinfo[i].suboriginremotelsn = pg_strdup(PQgetvalue(res, i, i_suboriginremotelsn)); + if (PQgetisnull(res, i, i_suboriginoid)) + subinfo[i].suboriginoid = NULL; + else + subinfo[i].suboriginoid = + pg_strdup(PQgetvalue(res, i, i_suboriginoid)); /* Decide whether we want to dump it */ selectDumpableObject(&(subinfo[i].dobj), fout); @@ -5662,6 +5679,23 @@ dumpSubscription(Archive *fout, const SubscriptionInfo *subinfo) */ if (dopt->binary_upgrade && fout->remoteVersion >= 170000) { + /* + * Pin the replication origin OID and create the origin. + * CreateSubscription() skips replorigin_create() in binary upgrade + * mode to allow us to control the roident and is preserved after + * upgrade. + */ + if (subinfo->suboriginoid) + { + appendPQExpBufferStr(query, + "\n-- For binary upgrade, must preserve the replication origin OID.\n"); + appendPQExpBufferStr(query, + "SELECT pg_catalog.binary_upgrade_set_next_replorigin_oid("); + appendPQExpBuffer(query, "%s::pg_catalog.oid, ", subinfo->suboriginoid); + appendStringLiteralAH(query, subinfo->dobj.name, fout); + appendPQExpBufferStr(query, ");\n"); + } + if (subinfo->suboriginremotelsn) { /* @@ -5675,6 +5709,7 @@ dumpSubscription(Archive *fout, const SubscriptionInfo *subinfo) */ appendPQExpBufferStr(query, "\n-- For binary upgrade, must preserve the remote_lsn for the subscriber's replication origin.\n"); + appendPQExpBufferStr(query, "SELECT pg_catalog.binary_upgrade_replorigin_advance("); appendStringLiteralAH(query, subinfo->dobj.name, fout); diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h index 5a6726d8b12..71cc66d75bc 100644 --- a/src/bin/pg_dump/pg_dump.h +++ b/src/bin/pg_dump/pg_dump.h @@ -730,6 +730,7 @@ typedef struct _SubscriptionInfo char *subpublications; char *suborigin; char *suboriginremotelsn; + char *suboriginoid; } SubscriptionInfo; /* diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c index 9e904f76baa..9f6498948f8 100644 --- a/src/bin/pg_dump/pg_dumpall.c +++ b/src/bin/pg_dump/pg_dumpall.c @@ -25,6 +25,7 @@ #include #include +#include "access/xlogdefs.h" #include "catalog/pg_authid_d.h" #include "common/connect.h" #include "common/file_perm.h" @@ -76,6 +77,7 @@ static void dropDBs(PGconn *conn); static void dumpUserConfig(PGconn *conn, const char *username); static void dumpDatabases(PGconn *conn); static void dumpTimestamp(const char *msg); +static void dumpReplicationOrigins(PGconn *conn); static int runPgDump(const char *dbname, const char *create_opts, char *dbfile); static void buildShSecLabels(PGconn *conn, const char *catalog_name, Oid objectId, @@ -813,6 +815,10 @@ main(int argc, char *argv[]) /* Dump role GUC privileges */ if (server_version >= 150000 && !skip_acls) dumpRoleGUCPrivs(conn); + + /* Dump replication origins */ + if (server_version >= 190000 && binary_upgrade && archDumpFormat == archNull) + dumpReplicationOrigins(conn); } /* Dump tablespaces */ @@ -2339,6 +2345,66 @@ dumpTimestamp(const char *msg) fprintf(OPF, "-- %s %s\n\n", msg, buf); } +static void +dumpReplicationOrigins(PGconn *conn) +{ + PQExpBuffer buf = createPQExpBuffer(); + PGresult *res; + int i_roident; + int i_roname; + int i_remotelsn; + + /* Get replication origins in current database. */ + appendPQExpBufferStr(buf, + "SELECT o.*, os.remote_lsn " + "FROM pg_catalog.pg_replication_origin o " + "LEFT OUTER JOIN pg_catalog.pg_replication_origin_status os ON o.roident = os.local_id " + "WHERE NOT EXISTS (" + " SELECT 1 FROM pg_catalog.pg_subscription s" + " WHERE o.roname = 'pg_' || s.oid::text);"); + + res = executeQuery(conn, buf->data); + + i_roident = PQfnumber(res, "roident"); + i_roname = PQfnumber(res, "roname"); + i_remotelsn = PQfnumber(res, "remote_lsn"); + + if (PQntuples(res) > 0 && archDumpFormat == archNull) + fprintf(OPF, "--\n-- Replication Origins \n--\n\n"); + + for (int i = 0; i < PQntuples(res); i++) + { + ReplOriginId roident; + const char *roname; + + roident = atooid(PQgetvalue(res, i, i_roident)); + roname = PQgetvalue(res, i, i_roname); + + resetPQExpBuffer(buf); + + appendPQExpBufferStr(buf, "\n-- For binary upgrade, must preserve replication origin roident and remote_lsn\n"); + appendPQExpBuffer(buf, + "SELECT pg_catalog.binary_upgrade_create_replication_origin('%u'::pg_catalog.oid, '%s'::pg_catalog.text", + roident, roname); + + if (!PQgetisnull(res, i, i_remotelsn)) + { + appendPQExpBuffer(buf, ", '%s'::pg_catalog.pg_lsn", + PQgetvalue(res, i, i_remotelsn)); + } + else + appendPQExpBufferStr(buf, ", NULL"); + + appendPQExpBuffer(buf, ");\n"); + + fprintf(OPF, "%s", buf->data); + } + + PQclear(res); + destroyPQExpBuffer(buf); +} + + /* * read_dumpall_filters - retrieve database identifier patterns from file * diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index 5a7afe62eab..5180c281dcc 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -2306,8 +2306,7 @@ check_new_cluster_replication_slots(void) * check_new_cluster_subscription_configuration() * * Verify that the max_active_replication_origins configuration specified is - * enough for creating the subscriptions. This is required to create the - * replication origin for each subscription. + * enough for creating all the replication origins. */ static void check_new_cluster_subscription_configuration(void) @@ -2320,8 +2319,8 @@ check_new_cluster_subscription_configuration(void) if (GET_MAJOR_VERSION(old_cluster.major_version) < 1700) return; - /* Quick return if there are no subscriptions to be migrated. */ - if (old_cluster.nsubs == 0) + /* Quick return if there are no origins to be migrated. */ + if (old_cluster.nrepl_origins == 0) return; prep_status("Checking for new cluster configuration for subscriptions"); @@ -2335,10 +2334,10 @@ check_new_cluster_subscription_configuration(void) pg_fatal("could not determine parameter settings on new cluster"); max_active_replication_origins = atoi(PQgetvalue(res, 0, 0)); - if (old_cluster.nsubs > max_active_replication_origins) + if (old_cluster.nrepl_origins > max_active_replication_origins) pg_fatal("\"max_active_replication_origins\" (%d) must be greater than or equal to the number of " "subscriptions (%d) on the old cluster", - max_active_replication_origins, old_cluster.nsubs); + max_active_replication_origins, old_cluster.nrepl_origins); PQclear(res); PQfinish(conn); diff --git a/src/bin/pg_upgrade/info.c b/src/bin/pg_upgrade/info.c index 8c5679b8097..f9359bd214b 100644 --- a/src/bin/pg_upgrade/info.c +++ b/src/bin/pg_upgrade/info.c @@ -834,7 +834,7 @@ count_old_cluster_logical_slots(void) /* * get_subscription_info() * - * Gets the information of subscriptions in the cluster. + * Gets the information of subscriptions and replication origins in the cluster. */ void get_subscription_info(ClusterInfo *cluster) @@ -842,6 +842,7 @@ get_subscription_info(ClusterInfo *cluster) PGconn *conn; PGresult *res; int i_nsub; + int i_nrepl_origins; int i_retain_dead_tuples; conn = connectToServer(cluster, "template1"); @@ -861,6 +862,14 @@ get_subscription_info(ClusterInfo *cluster) cluster->sub_retain_dead_tuples = (strcmp(PQgetvalue(res, 0, i_retain_dead_tuples), "t") == 0); PQclear(res); + + res = executeQueryOrDie(conn, + "SELECT count(*) AS nrepl_origins " + "FROM pg_catalog.pg_replication_origin"); + i_nrepl_origins = PQfnumber(res, "nrepl_origins"); + cluster->nrepl_origins = atoi(PQgetvalue(res, 0, i_nrepl_origins)); + PQclear(res); + PQfinish(conn); } diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index 1d767bbda2d..1d15700a886 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -311,6 +311,7 @@ typedef struct int num_tablespaces; const char *tablespace_suffix; /* directory specification */ int nsubs; /* number of subscriptions */ + int nrepl_origins; /* number of replication origins */ bool sub_retain_dead_tuples; /* whether a subscription enables * retain_dead_tuples. */ } ClusterInfo; diff --git a/src/bin/pg_upgrade/t/004_subscription.pl b/src/bin/pg_upgrade/t/004_subscription.pl index f68821df2a3..43322fb0596 100644 --- a/src/bin/pg_upgrade/t/004_subscription.pl +++ b/src/bin/pg_upgrade/t/004_subscription.pl @@ -303,6 +303,24 @@ is($result, qq(t), "Check that the table is in init state"); my $remote_lsn = $old_sub->safe_psql('postgres', "SELECT remote_lsn FROM pg_replication_origin_status os, pg_subscription s WHERE os.external_id = 'pg_' || s.oid AND s.subname = 'regress_sub4'" ); + +# Get the replication origin OIDs (roident) for all subscriptions, keyed by +# subscription name (which is stable across upgrade, unlike suboid). These +# must be preserved after upgrade. A mismatch would cause spurious +# update_origin_differs conflicts. +my %pre_upgrade_roident; +my $roident_rows = $old_sub->safe_psql('postgres', + "SELECT s.subname, o.roident + FROM pg_subscription s + JOIN pg_replication_origin o ON o.roname = 'pg_' || s.oid::text + ORDER BY s.subname" +); +for my $row (split /\n/, $roident_rows) +{ + my ($subname, $roident) = split /\|/, $row; + $pre_upgrade_roident{$subname} = $roident; +} + # Have the subscription in disabled state before upgrade $old_sub->safe_psql('postgres', "ALTER SUBSCRIPTION regress_sub5 DISABLE"); @@ -371,6 +389,20 @@ regress_sub5|f|f|f), "check that the subscription's running status, failover, and retain_dead_tuples are preserved" ); +# Verify that replication origin OIDs are preserved after upgrade. +my $post_roident_rows = $new_sub->safe_psql('postgres', + "SELECT s.subname, o.roident + FROM pg_subscription s + JOIN pg_replication_origin o ON o.roname = 'pg_' || s.oid::text + ORDER BY s.subname" +); +for my $row (split /\n/, $post_roident_rows) +{ + my ($subname, $roident) = split /\|/, $row; + is($roident, $pre_upgrade_roident{$subname}, + "roident preserved for subscription '$subname' after upgrade"); +} + # Subscription relations should be preserved $result = $new_sub->safe_psql('postgres', "SELECT srrelid, srsubstate FROM pg_subscription_rel ORDER BY srrelid"); diff --git a/src/include/catalog/binary_upgrade.h b/src/include/catalog/binary_upgrade.h index 7bf7ae44385..27f6f0befff 100644 --- a/src/include/catalog/binary_upgrade.h +++ b/src/include/catalog/binary_upgrade.h @@ -14,8 +14,10 @@ #ifndef BINARY_UPGRADE_H #define BINARY_UPGRADE_H +#include "access/xlogdefs.h" #include "common/relpath.h" + extern PGDLLIMPORT Oid binary_upgrade_next_pg_tablespace_oid; extern PGDLLIMPORT Oid binary_upgrade_next_pg_type_oid; diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index fa9ae79082b..392ca481f46 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -12024,6 +12024,17 @@ proname => 'binary_upgrade_create_conflict_detection_slot', proisstrict => 'f', provolatile => 'v', proparallel => 'u', prorettype => 'void', proargtypes => '', prosrc => 'binary_upgrade_create_conflict_detection_slot' }, +{ oid => '9160', descr => 'for use by pg_upgrade (replication origin)', + proname => 'binary_upgrade_create_replication_origin', proisstrict => 'f', + provolatile => 'v', proparallel => 'u', prorettype => 'void', + proargtypes => 'oid name pg_lsn', prosrc => 'binary_upgrade_create_replication_origin' }, +{ oid => '9161', + descr => 'for use by pg_upgrade only: set next replication origin OID and create origin', + proname => 'binary_upgrade_set_next_replorigin_oid', + provolatile => 'v', proretset => 'f', prosecdef => 'f', + proisstrict => 'f', prorettype => 'void', + proargtypes => 'oid text', + prosrc => 'binary_upgrade_set_next_replorigin_oid' }, # conversion functions { oid => '4310', descr => 'internal conversion function for KOI8R to WIN1251', diff --git a/src/include/replication/origin.h b/src/include/replication/origin.h index a69faf6eaaf..8f6b0d0635b 100644 --- a/src/include/replication/origin.h +++ b/src/include/replication/origin.h @@ -55,6 +55,7 @@ extern PGDLLIMPORT int max_active_replication_origins; /* API for querying & manipulating replication origins */ extern ReplOriginId replorigin_by_name(const char *roname, bool missing_ok); extern ReplOriginId replorigin_create(const char *roname); +extern ReplOriginId replorigin_create_with_reploriginid(ReplOriginId node, const char *roname); extern void replorigin_drop_by_name(const char *name, bool missing_ok, bool nowait); extern bool replorigin_by_oid(ReplOriginId roident, bool missing_ok, char **roname); -- 2.47.3