public inbox for [email protected]
help / color / mirror / Atom feedFrom: Hayato Kuroda (Fujitsu) <[email protected]>
To: Zhijie Hou (Fujitsu) <[email protected]>
Cc: [email protected] <[email protected]>
Cc: 'Amit Kapila' <[email protected]>
Cc: Masahiko Sawada <[email protected]>
Cc: [email protected] <[email protected]>
Subject: RE: Selectively invalidate caches in pgoutput module
Date: Mon, 10 Mar 2025 13:12:00 +0000
Message-ID: <OSCPR01MB14966DBBE4666C701FB8943E0F5D62@OSCPR01MB14966.jpnprd01.prod.outlook.com> (raw)
In-Reply-To: <OS3PR01MB5718B8EFFBB856C8B5749E8B94D62@OS3PR01MB5718.jpnprd01.prod.outlook.com>
References: <OSCPR01MB14966C09AA201EFFA706576A7F5C92@OSCPR01MB14966.jpnprd01.prod.outlook.com>
<CAA4eK1LHoHjZ1mbuf1Kya5eHZXyeO7Xi+XEiRFVf=-YMdPAY+g@mail.gmail.com>
<OSCPR01MB14966206D8490B0EC5E7B6AAEF5C82@OSCPR01MB14966.jpnprd01.prod.outlook.com>
<OS0PR01MB5716BCFACE982F17D1F7554994CB2@OS0PR01MB5716.jpnprd01.prod.outlook.com>
<OSCPR01MB1496622457D213FA8681750BEF5CB2@OSCPR01MB14966.jpnprd01.prod.outlook.com>
<OSCPR01MB149666315C734F781ED70D0AAF5CB2@OSCPR01MB14966.jpnprd01.prod.outlook.com>
<CAA4eK1LdT80+ASA4c_pvqoxzK=ZOCn8DtMLK5t8++62aL5LeNw@mail.gmail.com>
<OSCPR01MB1496638A193D30795EC24386FF5CA2@OSCPR01MB14966.jpnprd01.prod.outlook.com>
<CAA4eK1LMR7anY0Rv7sUFYFcqxetzV-M9BVsQYAm=OAp=3nL4CQ@mail.gmail.com>
<OSCPR01MB149661B4D4A4E912E8D85CB43F5D52@OSCPR01MB14966.jpnprd01.prod.outlook.com>
<CAA4eK1Jw4uSFv2zu2tT6GN4DVoW54kV=sM2iHj+h+b6xyVF02w@mail.gmail.com>
<OSCPR01MB149669AF61681064D2A75FAE9F5D42@OSCPR01MB14966.jpnprd01.prod.outlook.com>
<OSCPR01MB1496609BD298A6660B1F8AF28F5D62@OSCPR01MB14966.jpnprd01.prod.outlook.com>
<OSCPR01MB14966B4602D103050DC91837DF5D62@OSCPR01MB14966.jpnprd01.prod.outlook.com>
<OS3PR01MB5718B8EFFBB856C8B5749E8B94D62@OS3PR01MB5718.jpnprd01.prod.outlook.com>
Dear Hou,
> Currently, only the leaf partition is invalidated when the published table is
> partitioned. However, I think pgoutput could cache both the partitioned table
> and the leaf partition table as relsync entries.
>
> For INSERT/UPDATE/DELETE on a partitioned table, only the leaf partition's
> relsync entry is used in pgoutput, but the TRUNCATE references the parent
> table's relsync entry.
I think your analysis is correct. PSA new version. Below part contains my analysis.
In ExecuteTruncate(), if the specified relation has children, all of them are
checked via find_all_inheritors() and listed as target. Also, ExecuteTruncateGuts()
serializes both a parent and children in XLOG_HEAP_TRUNCATE WAL record.
Decoding layer passes relations as-is. These facts mean that output plugins can
store caches on the memory.
Best regards,
Hayato Kuroda
FUJITSU LIMITED
Attachments:
[application/octet-stream] v9-0001-Introduce-a-new-invalidation-message-to-invalidat.patch (10.1K, ../OSCPR01MB14966DBBE4666C701FB8943E0F5D62@OSCPR01MB14966.jpnprd01.prod.outlook.com/2-v9-0001-Introduce-a-new-invalidation-message-to-invalidat.patch)
download | inline diff:
From 7bbf7bc3278b3ad9e6071dca9eb78c8c6b80f4b0 Mon Sep 17 00:00:00 2001
From: Hayato Kuroda <[email protected]>
Date: Tue, 4 Mar 2025 16:51:19 +0900
Subject: [PATCH v9 1/2] Introduce a new invalidation message to invalidate
caches in output plugins
A new invalidation message is generated when either ALTER PUBLICATION RENAME TO
or is executed. The primal use-case of the message is to invalidate caches on
the logical decoding output plugin. Plugins can register callback functions for
the message via CacheRegisterRelSyncCallback(), and the function can invalidate
the cache for the specified relation.
A new invalidation message is transactional, and decoder processes should
recognize the message and invalidate specified caches. Thus, the messages are
stored in InvalMessageArray and serialized at the end of the transaction.
---
src/backend/access/rmgrdesc/standbydesc.c | 2 +
src/backend/utils/cache/inval.c | 127 ++++++++++++++++++++++
src/include/pg_config_manual.h | 8 +-
src/include/storage/sinval.h | 11 ++
src/include/utils/inval.h | 10 ++
5 files changed, 154 insertions(+), 4 deletions(-)
diff --git a/src/backend/access/rmgrdesc/standbydesc.c b/src/backend/access/rmgrdesc/standbydesc.c
index d849f8e54b..81eff5f31c 100644
--- a/src/backend/access/rmgrdesc/standbydesc.c
+++ b/src/backend/access/rmgrdesc/standbydesc.c
@@ -132,6 +132,8 @@ standby_desc_invalidations(StringInfo buf,
appendStringInfo(buf, " relmap db %u", msg->rm.dbId);
else if (msg->id == SHAREDINVALSNAPSHOT_ID)
appendStringInfo(buf, " snapshot %u", msg->sn.relId);
+ else if (msg->id == SHAREDINVALRELSYNC_ID)
+ appendStringInfo(buf, " relsync %u", msg->rs.relid);
else
appendStringInfo(buf, " unrecognized id %d", msg->id);
}
diff --git a/src/backend/utils/cache/inval.c b/src/backend/utils/cache/inval.c
index 700ccb6df9..35df9be5e5 100644
--- a/src/backend/utils/cache/inval.c
+++ b/src/backend/utils/cache/inval.c
@@ -271,6 +271,7 @@ int debug_discard_caches = 0;
#define MAX_SYSCACHE_CALLBACKS 64
#define MAX_RELCACHE_CALLBACKS 10
+#define MAX_RELSYNC_CALLBACKS 10
static struct SYSCACHECALLBACK
{
@@ -292,6 +293,15 @@ static struct RELCACHECALLBACK
static int relcache_callback_count = 0;
+static struct RELSYNCCALLBACK
+{
+ RelSyncCallbackFunction function;
+ Datum arg;
+} relsync_callback_list[MAX_RELSYNC_CALLBACKS];
+
+static int relsync_callback_count = 0;
+
+
/* ----------------------------------------------------------------
* Invalidation subgroup support functions
* ----------------------------------------------------------------
@@ -484,6 +494,34 @@ AddRelcacheInvalidationMessage(InvalidationMsgsGroup *group,
AddInvalidationMessage(group, RelCacheMsgs, &msg);
}
+/*
+ * Add a relsync inval entry
+ *
+ * We put these into the relcache subgroup for simplicity.
+ */
+static void
+AddRelsyncInvalidationMessage(InvalidationMsgsGroup *group,
+ Oid dbId, Oid relId)
+{
+ SharedInvalidationMessage msg;
+
+ /* Don't add a duplicate item */
+ /* We assume dbId need not be checked because it will never change */
+ ProcessMessageSubGroup(group, RelCacheMsgs,
+ if (msg->rc.id == SHAREDINVALRELSYNC_ID &&
+ msg->rc.relId == relId)
+ return);
+
+ /* OK, add the item */
+ msg.rc.id = SHAREDINVALRELSYNC_ID;
+ msg.rc.dbId = dbId;
+ msg.rc.relId = relId;
+ /* check AddCatcacheInvalidationMessage() for an explanation */
+ VALGRIND_MAKE_MEM_DEFINED(&msg, sizeof(msg));
+
+ AddInvalidationMessage(group, RelCacheMsgs, &msg);
+}
+
/*
* Add a snapshot inval entry
*
@@ -611,6 +649,18 @@ RegisterRelcacheInvalidation(InvalidationInfo *info, Oid dbId, Oid relId)
info->RelcacheInitFileInval = true;
}
+/*
+ * RegisterRelcacheInvalidation
+ *
+ * As above, but register a relsync invalidation event.
+ */
+static void
+RegisterRelsyncInvalidation(InvalidationInfo *info, Oid dbId, Oid relId)
+{
+ AddRelsyncInvalidationMessage(&info->CurrentCmdInvalidMsgs, dbId, relId);
+}
+
+
/*
* RegisterSnapshotInvalidation
*
@@ -751,6 +801,13 @@ InvalidateSystemCachesExtended(bool debug_discard)
ccitem->function(ccitem->arg, InvalidOid);
}
+
+ for (i = 0; i < relsync_callback_count; i++)
+ {
+ struct RELSYNCCALLBACK *ccitem = relsync_callback_list + i;
+
+ ccitem->function(ccitem->arg, InvalidOid);
+ }
}
/*
@@ -832,6 +889,12 @@ LocalExecuteInvalidationMessage(SharedInvalidationMessage *msg)
else if (msg->sn.dbId == MyDatabaseId)
InvalidateCatalogSnapshot();
}
+ else if (msg->id == SHAREDINVALRELSYNC_ID)
+ {
+ /* We only care about our own database */
+ if (msg->rs.dbId == MyDatabaseId)
+ CallRelSyncCallbacks(msg->rs.relid);
+ }
else
elog(FATAL, "unrecognized SI message ID: %d", msg->id);
}
@@ -1622,6 +1685,35 @@ CacheInvalidateRelcacheByRelid(Oid relid)
}
+/*
+ * RelationCacheInvalidate
+ * Register invalidation of the cache in logical decoding output plugin
+ * for a database.
+ *
+ * This type of invalidation message is used for the specific purpose of output
+ * plugins. Processes which do not decode WALs would do nothing even when it
+ * receives the message.
+ */
+void
+CacheInvalidateRelSync(Oid relid)
+{
+ RegisterRelsyncInvalidation(PrepareInvalidationState(),
+ MyDatabaseId, relid);
+}
+
+
+/*
+ * CacheInvalidateRelSyncAll
+ * Register invalidation of the whole cache in logical decoding output
+ * plugin.
+ */
+void
+CacheInvalidateRelSyncAll(void)
+{
+ CacheInvalidateRelSync(InvalidOid);
+}
+
+
/*
* CacheInvalidateSmgr
* Register invalidation of smgr references to a physical relation.
@@ -1763,6 +1855,27 @@ CacheRegisterRelcacheCallback(RelcacheCallbackFunction func,
++relcache_callback_count;
}
+/*
+ * CacheRegisterRelSyncCallback
+ * Register the specified function to be called for all future
+ * decoding-cache invalidation events.
+ *
+ * This function is intended to be call from the logical decoding output
+ * plugins.
+ */
+void
+CacheRegisterRelSyncCallback(RelSyncCallbackFunction func,
+ Datum arg)
+{
+ if (relsync_callback_count >= MAX_RELSYNC_CALLBACKS)
+ elog(FATAL, "out of relsync_callback_list slots");
+
+ relsync_callback_list[relsync_callback_count].function = func;
+ relsync_callback_list[relsync_callback_count].arg = arg;
+
+ ++relsync_callback_count;
+}
+
/*
* CallSyscacheCallbacks
*
@@ -1788,6 +1901,20 @@ CallSyscacheCallbacks(int cacheid, uint32 hashvalue)
}
}
+/*
+ * CallSyscacheCallbacks
+ */
+void
+CallRelSyncCallbacks(Oid relid)
+{
+ for (int i = 0; i < relsync_callback_count; i++)
+ {
+ struct RELSYNCCALLBACK *ccitem = relsync_callback_list + i;
+
+ ccitem->function(ccitem->arg, relid);
+ }
+}
+
/*
* LogLogicalInvalidations
*
diff --git a/src/include/pg_config_manual.h b/src/include/pg_config_manual.h
index 449e50bd78..23308f1de1 100644
--- a/src/include/pg_config_manual.h
+++ b/src/include/pg_config_manual.h
@@ -282,10 +282,10 @@
/*
* For cache-invalidation debugging, define DISCARD_CACHES_ENABLED to enable
- * use of the debug_discard_caches GUC to aggressively flush syscache/relcache
- * entries whenever it's possible to deliver invalidations. See
- * AcceptInvalidationMessages() in src/backend/utils/cache/inval.c for
- * details.
+ * use of the debug_discard_caches GUC to aggressively flush
+ * syscache/relcache/relsync cache entries whenever it's possible to deliver
+ * invalidations. See AcceptInvalidationMessages() in
+ * src/backend/utils/cache/inval.c for details.
*
* USE_ASSERT_CHECKING builds default to enabling this. It's possible to use
* DISCARD_CACHES_ENABLED without a cassert build and the implied
diff --git a/src/include/storage/sinval.h b/src/include/storage/sinval.h
index 2463c0f9fa..90a5af4ed8 100644
--- a/src/include/storage/sinval.h
+++ b/src/include/storage/sinval.h
@@ -27,6 +27,7 @@
* * invalidate an smgr cache entry for a specific physical relation
* * invalidate the mapped-relation mapping for a given database
* * invalidate any saved snapshot that might be used to scan a given relation
+ * * invalidate a specific entry for specific output plugin
* More types could be added if needed. The message type is identified by
* the first "int8" field of the message struct. Zero or positive means a
* specific-catcache inval message (and also serves as the catcache ID field).
@@ -110,6 +111,15 @@ typedef struct
Oid relId; /* relation ID */
} SharedInvalSnapshotMsg;
+#define SHAREDINVALRELSYNC_ID (-6)
+
+typedef struct
+{
+ int8 id; /* type field --- must be first */
+ Oid dbId; /* database ID */
+ Oid relid; /* relation ID, or 0 if whole relcache */
+} SharedInvalRelSyncMsg;
+
typedef union
{
int8 id; /* type field --- must be first */
@@ -119,6 +129,7 @@ typedef union
SharedInvalSmgrMsg sm;
SharedInvalRelmapMsg rm;
SharedInvalSnapshotMsg sn;
+ SharedInvalRelSyncMsg rs;
} SharedInvalidationMessage;
diff --git a/src/include/utils/inval.h b/src/include/utils/inval.h
index 40658ba2ff..9b871caef6 100644
--- a/src/include/utils/inval.h
+++ b/src/include/utils/inval.h
@@ -22,6 +22,7 @@ extern PGDLLIMPORT int debug_discard_caches;
typedef void (*SyscacheCallbackFunction) (Datum arg, int cacheid, uint32 hashvalue);
typedef void (*RelcacheCallbackFunction) (Datum arg, Oid relid);
+typedef void (*RelSyncCallbackFunction) (Datum arg, Oid relid);
extern void AcceptInvalidationMessages(void);
@@ -55,6 +56,10 @@ extern void CacheInvalidateRelcacheByTuple(HeapTuple classTuple);
extern void CacheInvalidateRelcacheByRelid(Oid relid);
+extern void CacheInvalidateRelSync(Oid relid);
+
+extern void CacheInvalidateRelSyncAll(void);
+
extern void CacheInvalidateSmgr(RelFileLocatorBackend rlocator);
extern void CacheInvalidateRelmap(Oid databaseId);
@@ -66,8 +71,13 @@ extern void CacheRegisterSyscacheCallback(int cacheid,
extern void CacheRegisterRelcacheCallback(RelcacheCallbackFunction func,
Datum arg);
+extern void CacheRegisterRelSyncCallback(RelSyncCallbackFunction func,
+ Datum arg);
+
extern void CallSyscacheCallbacks(int cacheid, uint32 hashvalue);
+extern void CallRelSyncCallbacks(Oid relid);
+
extern void InvalidateSystemCaches(void);
extern void InvalidateSystemCachesExtended(bool debug_discard);
--
2.43.5
[application/octet-stream] v9-0002-Invalidate-Relcaches-while-ALTER-PUBLICATION-RENA.patch (6.9K, ../OSCPR01MB14966DBBE4666C701FB8943E0F5D62@OSCPR01MB14966.jpnprd01.prod.outlook.com/3-v9-0002-Invalidate-Relcaches-while-ALTER-PUBLICATION-RENA.patch)
download | inline diff:
From e9d6bd5b003b9b8b4a6dc9eacc4e2440d338b58d Mon Sep 17 00:00:00 2001
From: Hayato Kuroda <[email protected]>
Date: Mon, 3 Mar 2025 19:41:04 +0900
Subject: [PATCH v9 2/2] Invalidate Relcaches while ALTER PUBLICATION RENAME TO
---
src/backend/commands/alter.c | 4 +-
src/backend/commands/publicationcmds.c | 111 ++++++++++++++++++++
src/backend/parser/gram.y | 2 +-
src/backend/replication/pgoutput/pgoutput.c | 8 +-
src/include/commands/publicationcmds.h | 2 +
5 files changed, 119 insertions(+), 8 deletions(-)
diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c
index 78c1d4e1b8..a79329acc1 100644
--- a/src/backend/commands/alter.c
+++ b/src/backend/commands/alter.c
@@ -400,6 +400,9 @@ ExecRenameStmt(RenameStmt *stmt)
case OBJECT_TYPE:
return RenameType(stmt);
+ case OBJECT_PUBLICATION:
+ return RenamePublication(stmt->subname, stmt->newname);
+
case OBJECT_AGGREGATE:
case OBJECT_COLLATION:
case OBJECT_CONVERSION:
@@ -417,7 +420,6 @@ ExecRenameStmt(RenameStmt *stmt)
case OBJECT_TSDICTIONARY:
case OBJECT_TSPARSER:
case OBJECT_TSTEMPLATE:
- case OBJECT_PUBLICATION:
case OBJECT_SUBSCRIPTION:
{
ObjectAddress address;
diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c
index 150a768d16..b1e38ed782 100644
--- a/src/backend/commands/publicationcmds.c
+++ b/src/backend/commands/publicationcmds.c
@@ -491,6 +491,105 @@ pub_contains_invalid_column(Oid pubid, Relation relation, List *ancestors,
return *invalid_column_list || *invalid_gen_col;
}
+/*
+ * Execute ALTER PUBLICATION RENAME
+ */
+ObjectAddress
+RenamePublication(const char *oldname, const char *newname)
+{
+ Relation rel;
+ HeapTuple tup;
+ ObjectAddress address;
+ Form_pg_publication pubform;
+ bool replaces[Natts_pg_publication];
+ bool nulls[Natts_pg_publication];
+ Datum values[Natts_pg_publication];
+
+ rel = table_open(PublicationRelationId, RowExclusiveLock);
+
+ tup = SearchSysCacheCopy1(PUBLICATIONNAME,
+ CStringGetDatum(oldname));
+
+ if (!HeapTupleIsValid(tup))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("publication \"%s\" does not exist",
+ oldname)));
+
+ pubform = (Form_pg_publication) GETSTRUCT(tup);
+
+ /* must be owner */
+ if (!object_ownercheck(PublicationRelationId, pubform->oid, GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_PUBLICATION,
+ NameStr(pubform->pubname));
+
+ /* Check if name is used */
+ if (OidIsValid(GetSysCacheOid1(PUBLICATIONNAME, Anum_pg_publication_oid,
+ CStringGetDatum(newname))))
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("publication \"%s\" already exists",
+ newname)));
+
+ /* Everything ok, form a new tuple. */
+ memset(values, 0, sizeof(values));
+ memset(nulls, false, sizeof(nulls));
+ memset(replaces, false, sizeof(replaces));
+
+ /* Only update the pubname */
+ values[Anum_pg_publication_pubname - 1] =
+ DirectFunctionCall1(namein, CStringGetDatum(newname));
+ replaces[Anum_pg_publication_pubname - 1] = true;
+
+ tup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls,
+ replaces);
+
+ /* Update the catalog. */
+ CatalogTupleUpdate(rel, &tup->t_self, tup);
+
+ /*
+ * Invalidate caches on the logical decoding output plugin.
+ *
+ * Apart from the ALTER PUBLICATION ADD/SET/DROP commands, we do not have
+ * to invalidate relcaches. They are required to refresh the publication's
+ * descriptor. The publication's name is not recorded in the attribute, so
+ * the RENAME commands do not require a refresh. Instead, we only
+ * invalidate a cache on the output plugin to rebuild its cache.
+ */
+ if (pubform->puballtables)
+ {
+ CacheInvalidateRelSyncAll();
+ }
+ else
+ {
+ List *relids = NIL;
+ List *schemarelids = NIL;
+
+ /*
+ * For partitioned tables, we must invalidate all partitions and
+ * itself. WAL records for INSERT/UPDATE/DELETE specify leaf
+ * tables as a target. However, WAL records for TRUNCATE specify
+ * both a root and its leaves.
+ */
+ relids = GetPublicationRelations(pubform->oid,
+ PUBLICATION_PART_ALL);
+ schemarelids = GetAllSchemaPublicationRelations(pubform->oid,
+ PUBLICATION_PART_ALL);
+
+ relids = list_concat_unique_oid(relids, schemarelids);
+
+ InvalidateRelSyncCaches(relids);
+ }
+
+ ObjectAddressSet(address, PublicationRelationId, pubform->oid);
+
+ heap_freetuple(tup);
+
+ table_close(rel, RowExclusiveLock);
+
+ return address;
+}
+
/* check_functions_in_node callback */
static bool
contain_mutable_or_user_functions_checker(Oid func_id, void *context)
@@ -2096,3 +2195,15 @@ defGetGeneratedColsOption(DefElem *def)
return PUBLISH_GENCOLS_NONE; /* keep compiler quiet */
}
+
+/*
+ * Invalidate the caches on the logical decoding output plugin.
+ */
+void
+InvalidateRelSyncCaches(List *relids)
+{
+ ListCell *lc;
+
+ foreach(lc, relids)
+ CacheInvalidateRelSync(lfirst_oid(lc));
+}
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 271ae26cba..0fb4041f15 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -9541,7 +9541,7 @@ RenameStmt: ALTER AGGREGATE aggregate_with_argtypes RENAME TO name
RenameStmt *n = makeNode(RenameStmt);
n->renameType = OBJECT_PUBLICATION;
- n->object = (Node *) makeString($3);
+ n->subname = $3;
n->newname = $6;
n->missing_ok = false;
$$ = (Node *) n;
diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c
index 9063af6e1d..ed806c5430 100644
--- a/src/backend/replication/pgoutput/pgoutput.c
+++ b/src/backend/replication/pgoutput/pgoutput.c
@@ -531,6 +531,8 @@ pgoutput_startup(LogicalDecodingContext *ctx, OutputPluginOptions *opt,
CacheRegisterSyscacheCallback(PUBLICATIONOID,
publication_invalidation_cb,
(Datum) 0);
+ CacheRegisterRelSyncCallback(rel_sync_cache_relation_cb,
+ (Datum) 0);
publication_callback_registered = true;
}
@@ -1789,12 +1791,6 @@ static void
publication_invalidation_cb(Datum arg, int cacheid, uint32 hashvalue)
{
publications_valid = false;
-
- /*
- * Also invalidate per-relation cache so that next time the filtering info
- * is checked it will be updated with the new publication settings.
- */
- rel_sync_cache_publication_cb(arg, cacheid, hashvalue);
}
/*
diff --git a/src/include/commands/publicationcmds.h b/src/include/commands/publicationcmds.h
index e11a942ea0..f130ea3090 100644
--- a/src/include/commands/publicationcmds.h
+++ b/src/include/commands/publicationcmds.h
@@ -38,5 +38,7 @@ extern bool pub_contains_invalid_column(Oid pubid, Relation relation,
char pubgencols_type,
bool *invalid_column_list,
bool *invalid_gen_col);
+extern ObjectAddress RenamePublication(const char *oldname, const char *newname);
+extern void InvalidateRelSyncCaches(List *relids);
#endif /* PUBLICATIONCMDS_H */
--
2.43.5
view thread (23+ messages) latest in thread
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected], [email protected], [email protected], [email protected], [email protected], [email protected]
Subject: RE: Selectively invalidate caches in pgoutput module
In-Reply-To: <OSCPR01MB14966DBBE4666C701FB8943E0F5D62@OSCPR01MB14966.jpnprd01.prod.outlook.com>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox