From 46e5e3b85a528009a7235f2bcec670cd4fbfc47c Mon Sep 17 00:00:00 2001 From: Shlok Kyal Date: Wed, 11 Dec 2024 08:48:55 +0530 Subject: [PATCH v15 2/2] Selective Invalidation of Cache When we alter a publication, add/drop namespace to/from publication all the cache for all the tables are invalidated. With this patch for the above operationns we will invalidate the cache of only the desired tables. --- src/backend/commands/alter.c | 4 +- src/backend/commands/publicationcmds.c | 107 ++++++++++++++++++++ src/backend/parser/gram.y | 2 +- src/backend/replication/logical/snapbuild.c | 9 +- src/backend/replication/pgoutput/pgoutput.c | 18 ---- src/include/commands/publicationcmds.h | 1 + 6 files changed, 118 insertions(+), 23 deletions(-) diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c index a45f3bb6b8..79bd6b7cef 100644 --- a/src/backend/commands/alter.c +++ b/src/backend/commands/alter.c @@ -399,6 +399,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: @@ -416,7 +419,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 5050057a7e..402cd44c5f 100644 --- a/src/backend/commands/publicationcmds.c +++ b/src/backend/commands/publicationcmds.c @@ -470,6 +470,87 @@ 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)); + + /* 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); + + /* Invalidate the relcache. */ + if (pubform->puballtables) + { + CacheInvalidateRelcacheAll(); + } + else + { + List *relids = NIL; + List *schemarelids = NIL; + + /* + * For partition table, when we insert data, get_rel_sync_entry is + * called and a hash entry is created for the corresponding leaf table. + * So invalidating the leaf nodes would be sufficient here. + */ + relids = GetPublicationRelations(pubform->oid, + PUBLICATION_PART_LEAF); + schemarelids = GetAllSchemaPublicationRelations(pubform->oid, + PUBLICATION_PART_LEAF); + + relids = list_concat_unique_oid(relids, schemarelids); + + InvalidatePublicationRels(relids); + } + + CatalogTupleUpdate(rel, &tup->t_self, tup); + + 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) @@ -1973,6 +2054,32 @@ AlterPublicationOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId) } form->pubowner = newOwnerId; + + /* Invalidate the relcache. */ + if (form->puballtables) + { + CacheInvalidateRelcacheAll(); + } + else + { + List *relids = NIL; + List *schemarelids = NIL; + + /* + * For partition table, when we insert data, get_rel_sync_entry is + * called and a hash entry is created for the corresponding leaf table. + * So invalidating the leaf nodes would be sufficient here. + */ + relids = GetPublicationRelations(form->oid, + PUBLICATION_PART_LEAF); + schemarelids = GetAllSchemaPublicationRelations(form->oid, + PUBLICATION_PART_LEAF); + + relids = list_concat_unique_oid(relids, schemarelids); + + InvalidatePublicationRels(relids); + } + CatalogTupleUpdate(rel, &tup->t_self, tup); /* Update owner dependency reference */ diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 67eb96396a..bc2da291ca 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -9475,7 +9475,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/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index 28a685dba0..f00465b737 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -728,13 +728,15 @@ SnapBuildProcessNewCid(SnapBuild *builder, TransactionId xid, * catalog contents). */ static void -SnapBuildDistributeSnapshotAndInval(SnapBuild *builder, XLogRecPtr lsn, TransactionId xid) +SnapBuildDistributeSnapshotAndInval(SnapBuild *builder, XLogRecPtr lsn, + TransactionId xid) { dlist_iter txn_i; ReorderBufferTXN *txn; ReorderBufferTXN *curr_txn; - curr_txn = ReorderBufferTXNByXid(builder->reorder, xid, false, NULL, InvalidXLogRecPtr, false); + curr_txn = ReorderBufferTXNByXid(builder->reorder, xid, false, NULL, + InvalidXLogRecPtr, false); /* * Iterate through all toplevel transactions. This can include @@ -784,7 +786,8 @@ SnapBuildDistributeSnapshotAndInval(SnapBuild *builder, XLogRecPtr lsn, Transact */ if (txn->xid != xid && curr_txn->ninvalidations > 0) ReorderBufferAddInvalidations(builder->reorder, txn->xid, lsn, - curr_txn->ninvalidations, curr_txn->invalidations); + curr_txn->ninvalidations, + curr_txn->invalidations); } } diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c index b50b3d62e3..c68955fa85 100644 --- a/src/backend/replication/pgoutput/pgoutput.c +++ b/src/backend/replication/pgoutput/pgoutput.c @@ -1781,12 +1781,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); } /* @@ -1962,18 +1956,6 @@ init_rel_sync_cache(MemoryContext cachectx) rel_sync_cache_publication_cb, (Datum) 0); - /* - * Flush all cache entries after any publication changes. (We need no - * callback entry for pg_publication, because publication_invalidation_cb - * will take care of it.) - */ - CacheRegisterSyscacheCallback(PUBLICATIONRELMAP, - rel_sync_cache_publication_cb, - (Datum) 0); - CacheRegisterSyscacheCallback(PUBLICATIONNAMESPACEMAP, - rel_sync_cache_publication_cb, - (Datum) 0); - relation_callbacks_registered = true; } diff --git a/src/include/commands/publicationcmds.h b/src/include/commands/publicationcmds.h index 19037518e8..b812d6d19f 100644 --- a/src/include/commands/publicationcmds.h +++ b/src/include/commands/publicationcmds.h @@ -38,5 +38,6 @@ extern bool pub_contains_invalid_column(Oid pubid, Relation relation, bool pubgencols, bool *invalid_column_list, bool *invalid_gen_col); +extern ObjectAddress RenamePublication(const char *oldname, const char *newname); #endif /* PUBLICATIONCMDS_H */ -- 2.34.1