From b3f9e4435125be9939b9b65f5b823b51edb3f18d Mon Sep 17 00:00:00 2001 From: Dilip Kumar Date: Fri, 26 Sep 2025 17:14:50 +0530 Subject: [PATCH v1] non publishable rel --- src/backend/access/common/reloptions.c | 13 ++++++++- src/backend/catalog/pg_publication.c | 38 ++++++++++++++++++++------ src/bin/psql/tab-complete.in.c | 1 + src/include/utils/rel.h | 11 ++++++++ 4 files changed, 54 insertions(+), 9 deletions(-) diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c index 35150bf237b..6aa8acd83ea 100644 --- a/src/backend/access/common/reloptions.c +++ b/src/backend/access/common/reloptions.c @@ -166,6 +166,15 @@ static relopt_bool boolRelOpts[] = }, true }, + { + { + "non_publishable_table", + "Mark table as non publishable so that this will can not be included in publication", + RELOPT_KIND_HEAP, + AccessExclusiveLock + }, + true + }, /* list terminator */ {{NULL}} }; @@ -1915,7 +1924,9 @@ default_reloptions(Datum reloptions, bool validate, relopt_kind kind) {"vacuum_truncate", RELOPT_TYPE_BOOL, offsetof(StdRdOptions, vacuum_truncate), offsetof(StdRdOptions, vacuum_truncate_set)}, {"vacuum_max_eager_freeze_failure_rate", RELOPT_TYPE_REAL, - offsetof(StdRdOptions, vacuum_max_eager_freeze_failure_rate)} + offsetof(StdRdOptions, vacuum_max_eager_freeze_failure_rate)}, + {"non_publishable_table", RELOPT_TYPE_BOOL, + offsetof(StdRdOptions, non_publishable_table)} }; return (bytea *) build_reloptions(reloptions, validate, kind, diff --git a/src/backend/catalog/pg_publication.c b/src/backend/catalog/pg_publication.c index b911efcf9cb..27f8b685817 100644 --- a/src/backend/catalog/pg_publication.c +++ b/src/backend/catalog/pg_publication.c @@ -146,7 +146,8 @@ is_publishable_class(Oid relid, Form_pg_class reltuple) bool is_publishable_relation(Relation rel) { - return is_publishable_class(RelationGetRelid(rel), rel->rd_rel); + return is_publishable_class(RelationGetRelid(rel), rel->rd_rel) && + !RelationIsNotPublishable(rel); } /* @@ -162,12 +163,16 @@ pg_relation_is_publishable(PG_FUNCTION_ARGS) Oid relid = PG_GETARG_OID(0); HeapTuple tuple; bool result; + Relation rel; - tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid)); - if (!HeapTupleIsValid(tuple)) + rel = try_table_open(relid, AccessShareLock); + if (rel == NULL) PG_RETURN_NULL(); - result = is_publishable_class(relid, (Form_pg_class) GETSTRUCT(tuple)); - ReleaseSysCache(tuple); + + result = is_publishable_relation(rel); + + table_close(rel, AccessShareLock); + PG_RETURN_BOOL(result); } @@ -882,10 +887,15 @@ GetAllTablesPublicationRelations(bool pubviaroot) { Form_pg_class relForm = (Form_pg_class) GETSTRUCT(tuple); Oid relid = relForm->oid; + Relation rel; + + rel = table_open(relid, AccessShareLock); - if (is_publishable_class(relid, relForm) && + if (is_publishable_relation(rel) && !(relForm->relispartition && pubviaroot)) result = lappend_oid(result, relid); + + table_close(rel, AccessShareLock); } table_endscan(scan); @@ -903,10 +913,15 @@ GetAllTablesPublicationRelations(bool pubviaroot) { Form_pg_class relForm = (Form_pg_class) GETSTRUCT(tuple); Oid relid = relForm->oid; + Relation rel; - if (is_publishable_class(relid, relForm) && + rel = table_open(relid, AccessShareLock); + + if (is_publishable_relation(rel) && !relForm->relispartition) result = lappend_oid(result, relid); + + table_close(rel, AccessShareLock); } table_endscan(scan); @@ -1010,9 +1025,16 @@ GetSchemaPublicationRelations(Oid schemaid, PublicationPartOpt pub_partopt) Form_pg_class relForm = (Form_pg_class) GETSTRUCT(tuple); Oid relid = relForm->oid; char relkind; + Relation rel; + + rel = table_open(relid, AccessShareLock); - if (!is_publishable_class(relid, relForm)) + if (!is_publishable_relation(rel)) + { + table_close(rel, AccessShareLock); continue; + } + table_close(rel, AccessShareLock); relkind = get_rel_relkind(relid); if (relkind == RELKIND_RELATION) diff --git a/src/bin/psql/tab-complete.in.c b/src/bin/psql/tab-complete.in.c index 6b20a4404b2..74d4c164f62 100644 --- a/src/bin/psql/tab-complete.in.c +++ b/src/bin/psql/tab-complete.in.c @@ -1411,6 +1411,7 @@ static const char *const table_storage_parameters[] = { "autovacuum_vacuum_threshold", "fillfactor", "log_autovacuum_min_duration", + "non_publishable_table", "parallel_workers", "toast.autovacuum_enabled", "toast.autovacuum_freeze_max_age", diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h index 21990436373..033c365f469 100644 --- a/src/include/utils/rel.h +++ b/src/include/utils/rel.h @@ -348,6 +348,7 @@ typedef struct StdRdOptions StdRdOptIndexCleanup vacuum_index_cleanup; /* controls index vacuuming */ bool vacuum_truncate; /* enables vacuum to truncate a relation */ bool vacuum_truncate_set; /* whether vacuum_truncate is set */ + bool non_publishable_table; /* table will not be published */ /* * Fraction of pages in a relation that vacuum can eagerly scan and fail @@ -400,6 +401,16 @@ typedef struct StdRdOptions (relation)->rd_rel->relkind == RELKIND_MATVIEW) ? \ ((StdRdOptions *) (relation)->rd_options)->user_catalog_table : false) +/* + * RelationIsNonPublishable + * Returns whether the relation can be added in publication or not. + */ +#define RelationIsNotPublishable(relation) \ + ((relation)->rd_options && \ + ((relation)->rd_rel->relkind == RELKIND_RELATION || \ + (relation)->rd_rel->relkind == RELKIND_MATVIEW) ? \ + ((StdRdOptions *) (relation)->rd_options)->non_publishable_table : false) + /* * RelationGetParallelWorkers * Returns the relation's parallel_workers reloption setting. -- 2.49.0