public inbox for [email protected]  
help / color / mirror / Atom feed
[PATCH v5 2/2] Make resowners more easily extensible.
10+ messages / 4 participants
[nested] [flat]

* [PATCH v5 2/2] Make resowners more easily extensible.
@ 2020-12-16 15:26  Heikki Linnakangas <[email protected]>
  0 siblings, 0 replies; 10+ messages in thread

From: Heikki Linnakangas @ 2020-12-16 15:26 UTC (permalink / raw)

Use a single array and hash, instead of one for each object kind.
---
 src/backend/access/common/tupdesc.c   |   42 +-
 src/backend/jit/jit.c                 |    2 -
 src/backend/jit/llvm/llvmjit.c        |   40 +-
 src/backend/storage/buffer/bufmgr.c   |   45 +-
 src/backend/storage/buffer/localbuf.c |    4 +-
 src/backend/storage/file/fd.c         |   44 +-
 src/backend/storage/ipc/dsm.c         |   44 +-
 src/backend/storage/lmgr/lock.c       |    2 +-
 src/backend/utils/cache/catcache.c    |   74 +-
 src/backend/utils/cache/plancache.c   |   45 +-
 src/backend/utils/cache/relcache.c    |   39 +-
 src/backend/utils/resowner/README     |   19 +-
 src/backend/utils/resowner/resowner.c | 1221 +++++++------------------
 src/backend/utils/time/snapmgr.c      |   38 +-
 src/common/cryptohash_openssl.c       |   45 +-
 src/include/storage/buf_internals.h   |    9 +
 src/include/utils/catcache.h          |    3 -
 src/include/utils/plancache.h         |    2 +
 src/include/utils/resowner.h          |   45 +-
 src/include/utils/resowner_private.h  |  105 ---
 20 files changed, 811 insertions(+), 1057 deletions(-)
 delete mode 100644 src/include/utils/resowner_private.h

diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c
index 902f59440cd..7fa44d5f7ee 100644
--- a/src/backend/access/common/tupdesc.c
+++ b/src/backend/access/common/tupdesc.c
@@ -29,9 +29,21 @@
 #include "utils/acl.h"
 #include "utils/builtins.h"
 #include "utils/datum.h"
-#include "utils/resowner_private.h"
+#include "utils/resowner.h"
 #include "utils/syscache.h"
 
+/* ResourceOwner callbacks to hold tupledesc references  */
+static void ResOwnerReleaseTupleDesc(Datum res);
+static void ResOwnerPrintTupleDescLeakWarning(Datum res);
+
+static ResourceOwnerFuncs tupdesc_resowner_funcs =
+{
+	/* relcache references */
+	.name = "tupdesc reference",
+	.phase = RESOURCE_RELEASE_AFTER_LOCKS,
+	.ReleaseResource = ResOwnerReleaseTupleDesc,
+	.PrintLeakWarning = ResOwnerPrintTupleDescLeakWarning
+};
 
 /*
  * CreateTemplateTupleDesc
@@ -376,9 +388,10 @@ IncrTupleDescRefCount(TupleDesc tupdesc)
 {
 	Assert(tupdesc->tdrefcount >= 0);
 
-	ResourceOwnerEnlargeTupleDescs(CurrentResourceOwner);
+	ResourceOwnerEnlarge(CurrentResourceOwner);
 	tupdesc->tdrefcount++;
-	ResourceOwnerRememberTupleDesc(CurrentResourceOwner, tupdesc);
+	ResourceOwnerRemember(CurrentResourceOwner, PointerGetDatum(tupdesc),
+						  &tupdesc_resowner_funcs);
 }
 
 /*
@@ -394,7 +407,8 @@ DecrTupleDescRefCount(TupleDesc tupdesc)
 {
 	Assert(tupdesc->tdrefcount > 0);
 
-	ResourceOwnerForgetTupleDesc(CurrentResourceOwner, tupdesc);
+	ResourceOwnerForget(CurrentResourceOwner, PointerGetDatum(tupdesc),
+						&tupdesc_resowner_funcs);
 	if (--tupdesc->tdrefcount == 0)
 		FreeTupleDesc(tupdesc);
 }
@@ -925,3 +939,23 @@ BuildDescFromLists(List *names, List *types, List *typmods, List *collations)
 
 	return desc;
 }
+
+
+/*
+ * ResourceOwner callbacks
+ */
+static void
+ResOwnerReleaseTupleDesc(Datum res)
+{
+	DecrTupleDescRefCount((TupleDesc) DatumGetPointer(res));
+}
+
+static void
+ResOwnerPrintTupleDescLeakWarning(Datum res)
+{
+	TupleDesc tupdesc = (TupleDesc) DatumGetPointer(res);
+
+	elog(WARNING,
+		 "TupleDesc reference leak: TupleDesc %p (%u,%d) still referenced",
+		 tupdesc, tupdesc->tdtypeid, tupdesc->tdtypmod);
+}
diff --git a/src/backend/jit/jit.c b/src/backend/jit/jit.c
index 2da300e000d..1aa04d173b4 100644
--- a/src/backend/jit/jit.c
+++ b/src/backend/jit/jit.c
@@ -26,7 +26,6 @@
 #include "jit/jit.h"
 #include "miscadmin.h"
 #include "utils/fmgrprotos.h"
-#include "utils/resowner_private.h"
 
 /* GUCs */
 bool		jit_enabled = true;
@@ -140,7 +139,6 @@ jit_release_context(JitContext *context)
 	if (provider_successfully_loaded)
 		provider.release_context(context);
 
-	ResourceOwnerForgetJIT(context->resowner, PointerGetDatum(context));
 	pfree(context);
 }
 
diff --git a/src/backend/jit/llvm/llvmjit.c b/src/backend/jit/llvm/llvmjit.c
index b0789a5fb80..64c7fd92bc7 100644
--- a/src/backend/jit/llvm/llvmjit.c
+++ b/src/backend/jit/llvm/llvmjit.c
@@ -40,7 +40,7 @@
 #include "portability/instr_time.h"
 #include "storage/ipc.h"
 #include "utils/memutils.h"
-#include "utils/resowner_private.h"
+#include "utils/resowner.h"
 
 /* Handle of a module emitted via ORC JIT */
 typedef struct LLVMJitHandle
@@ -121,8 +121,20 @@ static LLVMOrcLLJITRef llvm_create_jit_instance(LLVMTargetMachineRef tm);
 static char *llvm_error_message(LLVMErrorRef error);
 #endif							/* LLVM_VERSION_MAJOR > 11 */
 
-PG_MODULE_MAGIC;
+/* ResourceOwner callbacks to hold JitContexts  */
+static void ResOwnerReleaseJitContext(Datum res);
+static void ResOwnerPrintJitContextLeakWarning(Datum res);
+
+static ResourceOwnerFuncs jit_funcs =
+{
+	/* relcache references */
+	.name = "LLVM JIT context",
+	.phase = RESOURCE_RELEASE_BEFORE_LOCKS,
+	.ReleaseResource = ResOwnerReleaseJitContext,
+	.PrintLeakWarning = ResOwnerPrintJitContextLeakWarning
+};
 
+PG_MODULE_MAGIC;
 
 /*
  * Initialize LLVM JIT provider.
@@ -151,7 +163,7 @@ llvm_create_context(int jitFlags)
 
 	llvm_session_initialize();
 
-	ResourceOwnerEnlargeJIT(CurrentResourceOwner);
+	ResourceOwnerEnlarge(CurrentResourceOwner);
 
 	context = MemoryContextAllocZero(TopMemoryContext,
 									 sizeof(LLVMJitContext));
@@ -159,7 +171,7 @@ llvm_create_context(int jitFlags)
 
 	/* ensure cleanup */
 	context->base.resowner = CurrentResourceOwner;
-	ResourceOwnerRememberJIT(CurrentResourceOwner, PointerGetDatum(context));
+	ResourceOwnerRemember(CurrentResourceOwner, PointerGetDatum(context), &jit_funcs);
 
 	return context;
 }
@@ -221,6 +233,8 @@ llvm_release_context(JitContext *context)
 
 		pfree(jit_handle);
 	}
+
+	ResourceOwnerForget(context->resowner, PointerGetDatum(context), &jit_funcs);
 }
 
 /*
@@ -1231,3 +1245,21 @@ llvm_error_message(LLVMErrorRef error)
 }
 
 #endif							/* LLVM_VERSION_MAJOR > 11 */
+
+/*
+ * ResourceOwner callbacks
+ */
+static void
+ResOwnerReleaseJitContext(Datum res)
+{
+	jit_release_context((JitContext *) PointerGetDatum(res));
+}
+
+static void
+ResOwnerPrintJitContextLeakWarning(Datum res)
+{
+	/* XXX: We used to not print these. Was that intentional? */
+	JitContext *context = (JitContext *) PointerGetDatum(res);
+
+	elog(WARNING, "JIT context leak: context %p still referenced", context);
+}
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index cde869e7d64..82e39de19f9 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -52,7 +52,7 @@
 #include "utils/memdebug.h"
 #include "utils/ps_status.h"
 #include "utils/rel.h"
-#include "utils/resowner_private.h"
+#include "utils/resowner.h"
 #include "utils/timestamp.h"
 
 
@@ -206,6 +206,18 @@ static PrivateRefCountEntry *GetPrivateRefCountEntry(Buffer buffer, bool do_move
 static inline int32 GetPrivateRefCount(Buffer buffer);
 static void ForgetPrivateRefCountEntry(PrivateRefCountEntry *ref);
 
+/* ResourceOwner callbacks to hold buffer pins */
+static void ResOwnerReleaseBuffer(Datum res);
+static void ResOwnerPrintBufferLeakWarning(Datum res);
+
+ResourceOwnerFuncs buffer_resowner_funcs =
+{
+	.name = "buffer",
+	.phase = RESOURCE_RELEASE_BEFORE_LOCKS,
+	.ReleaseResource = ResOwnerReleaseBuffer,
+	.PrintLeakWarning = ResOwnerPrintBufferLeakWarning
+};
+
 /*
  * Ensure that the PrivateRefCountArray has sufficient space to store one more
  * entry. This has to be called before using NewPrivateRefCountEntry() to fill
@@ -1094,7 +1106,7 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 		 * pin.
 		 */
 		ReservePrivateRefCountEntry();
-		ResourceOwnerEnlargeBuffers(CurrentResourceOwner);
+		ResourceOwnerEnlarge(CurrentResourceOwner);
 
 		/*
 		 * Select a victim buffer.  The buffer is returned with its header
@@ -1604,7 +1616,7 @@ PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy)
 	bool		result;
 	PrivateRefCountEntry *ref;
 
-	ResourceOwnerEnlargeBuffers(CurrentResourceOwner);
+	ResourceOwnerEnlarge(CurrentResourceOwner);
 
 	ref = GetPrivateRefCountEntry(b, true);
 
@@ -1687,7 +1699,7 @@ PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy)
  *
  * As this function is called with the spinlock held, the caller has to
  * previously call ReservePrivateRefCountEntry() and
- * ResourceOwnerEnlargeBuffers(CurrentResourceOwner);
+ * ResourceOwnerEnlarge(CurrentResourceOwner);
  *
  * Currently, no callers of this function want to modify the buffer's
  * usage_count at all, so there's no need for a strategy parameter.
@@ -2423,7 +2435,7 @@ SyncOneBuffer(int buf_id, bool skip_recently_used, WritebackContext *wb_context)
 
 	/* Make sure we can handle the pin */
 	ReservePrivateRefCountEntry();
-	ResourceOwnerEnlargeBuffers(CurrentResourceOwner);
+	ResourceOwnerEnlarge(CurrentResourceOwner);
 
 	/*
 	 * Check whether buffer needs writing.
@@ -3496,7 +3508,7 @@ FlushRelationBuffers(Relation rel)
 
 		/* Make sure we can handle the pin */
 		ReservePrivateRefCountEntry();
-		ResourceOwnerEnlargeBuffers(CurrentResourceOwner);
+		ResourceOwnerEnlarge(CurrentResourceOwner);
 
 		buf_state = LockBufHdr(bufHdr);
 		if (RelFileNodeEquals(bufHdr->tag.rnode, rel->rd_node) &&
@@ -3591,7 +3603,7 @@ FlushRelationsAllBuffers(SMgrRelation *smgrs, int nrels)
 
 		/* Make sure we can handle the pin */
 		ReservePrivateRefCountEntry();
-		ResourceOwnerEnlargeBuffers(CurrentResourceOwner);
+		ResourceOwnerEnlarge(CurrentResourceOwner);
 
 		buf_state = LockBufHdr(bufHdr);
 		if (RelFileNodeEquals(bufHdr->tag.rnode, srelent->rnode) &&
@@ -3646,7 +3658,7 @@ FlushDatabaseBuffers(Oid dbid)
 
 		/* Make sure we can handle the pin */
 		ReservePrivateRefCountEntry();
-		ResourceOwnerEnlargeBuffers(CurrentResourceOwner);
+		ResourceOwnerEnlarge(CurrentResourceOwner);
 
 		buf_state = LockBufHdr(bufHdr);
 		if (bufHdr->tag.rnode.dbNode == dbid &&
@@ -3729,7 +3741,7 @@ void
 IncrBufferRefCount(Buffer buffer)
 {
 	Assert(BufferIsPinned(buffer));
-	ResourceOwnerEnlargeBuffers(CurrentResourceOwner);
+	ResourceOwnerEnlarge(CurrentResourceOwner);
 	if (BufferIsLocal(buffer))
 		LocalRefCount[-buffer - 1]++;
 	else
@@ -4803,3 +4815,18 @@ TestForOldSnapshot_impl(Snapshot snapshot, Relation relation)
 				(errcode(ERRCODE_SNAPSHOT_TOO_OLD),
 				 errmsg("snapshot too old")));
 }
+
+/*
+ * ResourceOwner callbacks
+ */
+static void
+ResOwnerReleaseBuffer(Datum res)
+{
+	ReleaseBuffer(DatumGetInt32(res));
+}
+
+static void
+ResOwnerPrintBufferLeakWarning(Datum res)
+{
+	PrintBufferLeakWarning(DatumGetInt32(res));
+}
diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c
index f7c15ea8a44..3f22d7127b9 100644
--- a/src/backend/storage/buffer/localbuf.c
+++ b/src/backend/storage/buffer/localbuf.c
@@ -22,7 +22,7 @@
 #include "storage/bufmgr.h"
 #include "utils/guc.h"
 #include "utils/memutils.h"
-#include "utils/resowner_private.h"
+#include "utils/resowner.h"
 
 
 /*#define LBDEBUG*/
@@ -124,7 +124,7 @@ LocalBufferAlloc(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum,
 		InitLocalBuffers();
 
 	/* Make sure we will have room to remember the buffer pin */
-	ResourceOwnerEnlargeBuffers(CurrentResourceOwner);
+	ResourceOwnerEnlarge(CurrentResourceOwner);
 
 	/* See if the desired buffer already exists */
 	hresult = (LocalBufferLookupEnt *)
diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c
index b58502837aa..1172ea245e0 100644
--- a/src/backend/storage/file/fd.c
+++ b/src/backend/storage/file/fd.c
@@ -97,7 +97,7 @@
 #include "storage/fd.h"
 #include "storage/ipc.h"
 #include "utils/guc.h"
-#include "utils/resowner_private.h"
+#include "utils/resowner.h"
 
 /* Define PG_FLUSH_DATA_WORKS if we have an implementation for pg_flush_data */
 #if defined(HAVE_SYNC_FILE_RANGE)
@@ -340,6 +340,24 @@ static void unlink_if_exists_fname(const char *fname, bool isdir, int elevel);
 static int	fsync_parent_path(const char *fname, int elevel);
 
 
+/* ResourceOwner callbacks to hold virtual file descriptors */
+static void ResOwnerReleaseFile(Datum res);
+static void ResOwnerPrintFileLeakWarning(Datum res);
+
+static ResourceOwnerFuncs file_resowner_funcs =
+{
+	.name = "File",
+	.phase = RESOURCE_RELEASE_AFTER_LOCKS,
+	.ReleaseResource = ResOwnerReleaseFile,
+	.PrintLeakWarning = ResOwnerPrintFileLeakWarning
+};
+
+/* Convenience wrappers over ResourceOwnerRemember/Forget */
+#define ResourceOwnerRememberFile(owner, file) \
+	ResourceOwnerRemember(owner, Int32GetDatum(file), &file_resowner_funcs)
+#define ResourceOwnerForgetFile(owner, file) \
+	ResourceOwnerForget(owner, Int32GetDatum(file), &file_resowner_funcs)
+
 /*
  * pg_fsync --- do fsync with or without writethrough
  */
@@ -1430,7 +1448,7 @@ ReportTemporaryFileUsage(const char *path, off_t size)
 
 /*
  * Called to register a temporary file for automatic close.
- * ResourceOwnerEnlargeFiles(CurrentResourceOwner) must have been called
+ * ResourceOwnerEnlarge(CurrentResourceOwner) must have been called
  * before the file was opened.
  */
 static void
@@ -1612,7 +1630,7 @@ OpenTemporaryFile(bool interXact)
 	 * open it, if we'll be registering it below.
 	 */
 	if (!interXact)
-		ResourceOwnerEnlargeFiles(CurrentResourceOwner);
+		ResourceOwnerEnlarge(CurrentResourceOwner);
 
 	/*
 	 * If some temp tablespace(s) have been given to us, try to use the next
@@ -1742,7 +1760,7 @@ PathNameCreateTemporaryFile(const char *path, bool error_on_failure)
 {
 	File		file;
 
-	ResourceOwnerEnlargeFiles(CurrentResourceOwner);
+	ResourceOwnerEnlarge(CurrentResourceOwner);
 
 	/*
 	 * Open the file.  Note: we don't use O_EXCL, in case there is an orphaned
@@ -1780,7 +1798,7 @@ PathNameOpenTemporaryFile(const char *path, int mode)
 {
 	File		file;
 
-	ResourceOwnerEnlargeFiles(CurrentResourceOwner);
+	ResourceOwnerEnlarge(CurrentResourceOwner);
 
 	file = PathNameOpenFile(path, mode | PG_BINARY);
 
@@ -3700,3 +3718,19 @@ pg_pwritev_with_retry(int fd, const struct iovec *iov, int iovcnt, off_t offset)
 
 	return sum;
 }
+
+/*
+ * ResourceOwner callbacks
+ */
+static void
+ResOwnerReleaseFile(Datum res)
+{
+	FileClose((File) DatumGetInt32(res));
+}
+
+static void
+ResOwnerPrintFileLeakWarning(Datum res)
+{
+	elog(WARNING, "temporary file leak: File %d still referenced",
+		 DatumGetInt32(res));
+}
diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c
index ae82b4bdc0e..31e8860fb53 100644
--- a/src/backend/storage/ipc/dsm.c
+++ b/src/backend/storage/ipc/dsm.c
@@ -37,13 +37,15 @@
 #include "miscadmin.h"
 #include "port/pg_bitutils.h"
 #include "storage/dsm.h"
+#include "storage/fd.h"
 #include "storage/ipc.h"
 #include "storage/lwlock.h"
 #include "storage/pg_shmem.h"
+#include "storage/shmem.h"
 #include "utils/freepage.h"
 #include "utils/guc.h"
 #include "utils/memutils.h"
-#include "utils/resowner_private.h"
+#include "utils/resowner.h"
 
 #define PG_DYNSHMEM_CONTROL_MAGIC		0x9a503d32
 
@@ -139,6 +141,25 @@ static dsm_control_header *dsm_control;
 static Size dsm_control_mapped_size = 0;
 static void *dsm_control_impl_private = NULL;
 
+
+/* ResourceOwner callbacks to hold DSM segments */
+static void ResOwnerReleaseDSM(Datum res);
+static void ResOwnerPrintDSMLeakWarning(Datum res);
+
+static ResourceOwnerFuncs dsm_resowner_funcs =
+{
+	.name = "dynamic shared memory segment",
+	.phase = RESOURCE_RELEASE_BEFORE_LOCKS,
+	.ReleaseResource = ResOwnerReleaseDSM,
+	.PrintLeakWarning = ResOwnerPrintDSMLeakWarning
+};
+
+/* Convenience wrappers over ResourceOwnerRemember/Forget */
+#define ResourceOwnerRememberDSM(owner, seg) \
+	ResourceOwnerRemember(owner, PointerGetDatum(seg), &dsm_resowner_funcs)
+#define ResourceOwnerForgetDSM(owner, seg) \
+	ResourceOwnerForget(owner, PointerGetDatum(seg), &dsm_resowner_funcs)
+
 /*
  * Start up the dynamic shared memory system.
  *
@@ -895,7 +916,7 @@ void
 dsm_unpin_mapping(dsm_segment *seg)
 {
 	Assert(seg->resowner == NULL);
-	ResourceOwnerEnlargeDSMs(CurrentResourceOwner);
+	ResourceOwnerEnlarge(CurrentResourceOwner);
 	seg->resowner = CurrentResourceOwner;
 	ResourceOwnerRememberDSM(seg->resowner, seg);
 }
@@ -1162,7 +1183,7 @@ dsm_create_descriptor(void)
 	dsm_segment *seg;
 
 	if (CurrentResourceOwner)
-		ResourceOwnerEnlargeDSMs(CurrentResourceOwner);
+		ResourceOwnerEnlarge(CurrentResourceOwner);
 
 	seg = MemoryContextAlloc(TopMemoryContext, sizeof(dsm_segment));
 	dlist_push_head(&dsm_segment_list, &seg->node);
@@ -1241,3 +1262,20 @@ is_main_region_dsm_handle(dsm_handle handle)
 {
 	return handle & 1;
 }
+
+/*
+ * ResourceOwner callbacks
+ */
+static void
+ResOwnerReleaseDSM(Datum res)
+{
+	dsm_detach((dsm_segment *) DatumGetPointer(res));
+}
+static void
+ResOwnerPrintDSMLeakWarning(Datum res)
+{
+	dsm_segment *seg = (dsm_segment *) res;
+
+	elog(WARNING, "dynamic shared memory leak: segment %u still referenced",
+		 dsm_segment_handle(seg));
+}
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 20e50247ea4..de39c844d49 100644
--- a/src/backend/storage/lmgr/lock.c
+++ b/src/backend/storage/lmgr/lock.c
@@ -47,7 +47,7 @@
 #include "storage/standby.h"
 #include "utils/memutils.h"
 #include "utils/ps_status.h"
-#include "utils/resowner_private.h"
+#include "utils/resowner.h"
 
 
 /* This configuration variable is used to set the lock table size */
diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c
index 86fdfc454d2..185ff00ee76 100644
--- a/src/backend/utils/cache/catcache.c
+++ b/src/backend/utils/cache/catcache.c
@@ -31,12 +31,13 @@
 #endif
 #include "storage/lmgr.h"
 #include "utils/builtins.h"
+#include "utils/catcache.h"
 #include "utils/datum.h"
 #include "utils/fmgroids.h"
 #include "utils/inval.h"
 #include "utils/memutils.h"
 #include "utils/rel.h"
-#include "utils/resowner_private.h"
+#include "utils/resowner.h"
 #include "utils/syscache.h"
 
 
@@ -104,6 +105,42 @@ static void CatCacheCopyKeys(TupleDesc tupdesc, int nkeys, int *attnos,
  *					internal support functions
  */
 
+/* ResourceOwner callbacks to hold catcache references */
+
+static void ResOwnerReleaseCatCache(Datum res);
+static void ResOwnerPrintCatCacheLeakWarning(Datum res);
+static void ResOwnerReleaseCatCacheList(Datum res);
+static void ResOwnerPrintCatCacheListLeakWarning(Datum res);
+
+static ResourceOwnerFuncs catcache_funcs =
+{
+	/* catcache references */
+	.name = "catcache reference",
+	.phase = RESOURCE_RELEASE_AFTER_LOCKS,
+	.ReleaseResource = ResOwnerReleaseCatCache,
+	.PrintLeakWarning = ResOwnerPrintCatCacheLeakWarning
+};
+
+static ResourceOwnerFuncs catlistref_funcs =
+{
+	/* catcache-list pins */
+	.name = "catcache list reference",
+	.phase = RESOURCE_RELEASE_AFTER_LOCKS,
+	.ReleaseResource = ResOwnerReleaseCatCacheList,
+	.PrintLeakWarning = ResOwnerPrintCatCacheListLeakWarning
+};
+
+/* Convenience wrappers over ResourceOwnerRemember/Forget */
+#define ResourceOwnerRememberCatCacheRef(owner, tuple) \
+	ResourceOwnerRemember(owner, PointerGetDatum(tuple), &catcache_funcs)
+#define ResourceOwnerForgetCatCacheRef(owner, tuple) \
+	ResourceOwnerForget(owner, PointerGetDatum(tuple), &catcache_funcs)
+#define ResourceOwnerRememberCatCacheListRef(owner, list) \
+	ResourceOwnerRemember(owner, PointerGetDatum(list), &catlistref_funcs)
+#define ResourceOwnerForgetCatCacheListRef(owner, list) \
+	ResourceOwnerForget(owner, PointerGetDatum(list), &catlistref_funcs)
+
+
 /*
  * Hash and equality functions for system types that are used as cache key
  * fields.  In some cases, we just call the regular SQL-callable functions for
@@ -1270,7 +1307,7 @@ SearchCatCacheInternal(CatCache *cache,
 		 */
 		if (!ct->negative)
 		{
-			ResourceOwnerEnlargeCatCacheRefs(CurrentResourceOwner);
+			ResourceOwnerEnlarge(CurrentResourceOwner);
 			ct->refcount++;
 			ResourceOwnerRememberCatCacheRef(CurrentResourceOwner, &ct->tuple);
 
@@ -1371,7 +1408,7 @@ SearchCatCacheMiss(CatCache *cache,
 									 hashValue, hashIndex,
 									 false);
 		/* immediately set the refcount to 1 */
-		ResourceOwnerEnlargeCatCacheRefs(CurrentResourceOwner);
+		ResourceOwnerEnlarge(CurrentResourceOwner);
 		ct->refcount++;
 		ResourceOwnerRememberCatCacheRef(CurrentResourceOwner, &ct->tuple);
 		break;					/* assume only one match */
@@ -1583,7 +1620,7 @@ SearchCatCacheList(CatCache *cache,
 		dlist_move_head(&cache->cc_lists, &cl->cache_elem);
 
 		/* Bump the list's refcount and return it */
-		ResourceOwnerEnlargeCatCacheListRefs(CurrentResourceOwner);
+		ResourceOwnerEnlarge(CurrentResourceOwner);
 		cl->refcount++;
 		ResourceOwnerRememberCatCacheListRef(CurrentResourceOwner, cl);
 
@@ -1695,7 +1732,7 @@ SearchCatCacheList(CatCache *cache,
 		table_close(relation, AccessShareLock);
 
 		/* Make sure the resource owner has room to remember this entry. */
-		ResourceOwnerEnlargeCatCacheListRefs(CurrentResourceOwner);
+		ResourceOwnerEnlarge(CurrentResourceOwner);
 
 		/* Now we can build the CatCList entry. */
 		oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
@@ -2069,14 +2106,19 @@ PrepareToInvalidateCacheTuple(Relation relation,
 	}
 }
 
-
 /*
- * Subroutines for warning about reference leaks.  These are exported so
- * that resowner.c can call them.
+ * ResourceOwner callbacks
  */
-void
-PrintCatCacheLeakWarning(HeapTuple tuple)
+static void
+ResOwnerReleaseCatCache(Datum res)
+{
+	ReleaseCatCache((HeapTuple) DatumGetPointer(res));
+}
+
+static void
+ResOwnerPrintCatCacheLeakWarning(Datum res)
 {
+	HeapTuple tuple = (HeapTuple) DatumGetPointer(res);
 	CatCTup    *ct = (CatCTup *) (((char *) tuple) -
 								  offsetof(CatCTup, tuple));
 
@@ -2090,9 +2132,17 @@ PrintCatCacheLeakWarning(HeapTuple tuple)
 		 ct->refcount);
 }
 
-void
-PrintCatCacheListLeakWarning(CatCList *list)
+static void
+ResOwnerReleaseCatCacheList(Datum res)
 {
+	ReleaseCatCacheList((CatCList *) DatumGetPointer(res));
+}
+
+static void
+ResOwnerPrintCatCacheListLeakWarning(Datum res)
+{
+	CatCList *list = (CatCList *) DatumGetPointer(res);
+
 	elog(WARNING, "cache reference leak: cache %s (%d), list %p has count %d",
 		 list->my_cache->cc_relname, list->my_cache->id,
 		 list, list->refcount);
diff --git a/src/backend/utils/cache/plancache.c b/src/backend/utils/cache/plancache.c
index cc04b5b4bef..ecc9296d2d3 100644
--- a/src/backend/utils/cache/plancache.c
+++ b/src/backend/utils/cache/plancache.c
@@ -69,7 +69,7 @@
 #include "tcop/utility.h"
 #include "utils/inval.h"
 #include "utils/memutils.h"
-#include "utils/resowner_private.h"
+#include "utils/resowner.h"
 #include "utils/rls.h"
 #include "utils/snapmgr.h"
 #include "utils/syscache.h"
@@ -115,6 +115,26 @@ static void PlanCacheRelCallback(Datum arg, Oid relid);
 static void PlanCacheObjectCallback(Datum arg, int cacheid, uint32 hashvalue);
 static void PlanCacheSysCallback(Datum arg, int cacheid, uint32 hashvalue);
 
+/* ResourceOwner callbacks to track plancache references */
+static void ResOwnerReleaseCachedPlan(Datum res);
+static void ResOwnerPrintPlanCacheLeakWarning(Datum res);
+
+/* this is exported for ResourceOwnerReleaseAllPlanCacheRefs() */
+ResourceOwnerFuncs planref_resowner_funcs =
+{
+	.name = "plancache reference",
+	.phase = RESOURCE_RELEASE_AFTER_LOCKS,
+	.ReleaseResource = ResOwnerReleaseCachedPlan,
+	.PrintLeakWarning = ResOwnerPrintPlanCacheLeakWarning
+};
+
+/* Convenience wrappers over ResourceOwnerRemember/Forget */
+#define ResourceOwnerRememberPlanCacheRef(owner, plan) \
+	ResourceOwnerRemember(owner, PointerGetDatum(plan), &planref_resowner_funcs)
+#define ResourceOwnerForgetPlanCacheRef(owner, plan) \
+	ResourceOwnerForget(owner, PointerGetDatum(plan), &planref_resowner_funcs)
+
+
 /* GUC parameter */
 int			plan_cache_mode;
 
@@ -1229,7 +1249,7 @@ GetCachedPlan(CachedPlanSource *plansource, ParamListInfo boundParams,
 
 	/* Flag the plan as in use by caller */
 	if (useResOwner)
-		ResourceOwnerEnlargePlanCacheRefs(CurrentResourceOwner);
+		ResourceOwnerEnlarge(CurrentResourceOwner);
 	plan->refcount++;
 	if (useResOwner)
 		ResourceOwnerRememberPlanCacheRef(CurrentResourceOwner, plan);
@@ -1392,7 +1412,7 @@ CachedPlanAllowsSimpleValidityCheck(CachedPlanSource *plansource,
 	/* Bump refcount if requested. */
 	if (owner)
 	{
-		ResourceOwnerEnlargePlanCacheRefs(owner);
+		ResourceOwnerEnlarge(owner);
 		plan->refcount++;
 		ResourceOwnerRememberPlanCacheRef(owner, plan);
 	}
@@ -1451,7 +1471,7 @@ CachedPlanIsSimplyValid(CachedPlanSource *plansource, CachedPlan *plan,
 	/* It's still good.  Bump refcount if requested. */
 	if (owner)
 	{
-		ResourceOwnerEnlargePlanCacheRefs(owner);
+		ResourceOwnerEnlarge(owner);
 		plan->refcount++;
 		ResourceOwnerRememberPlanCacheRef(owner, plan);
 	}
@@ -2205,3 +2225,20 @@ ResetPlanCache(void)
 		cexpr->is_valid = false;
 	}
 }
+
+/*
+ * ResourceOwner callbacks
+ */
+
+static void
+ResOwnerReleaseCachedPlan(Datum res)
+{
+	ReleaseCachedPlan((CachedPlan *) DatumGetPointer(res), true);
+}
+
+static void
+ResOwnerPrintPlanCacheLeakWarning(Datum res)
+{
+	elog(WARNING, "plancache reference leak: plan %p not closed",
+		 DatumGetPointer(res));
+}
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 7ef510cd01b..255d19a88b9 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -78,13 +78,14 @@
 #include "storage/smgr.h"
 #include "utils/array.h"
 #include "utils/builtins.h"
+#include "utils/catcache.h"
 #include "utils/datum.h"
 #include "utils/fmgroids.h"
 #include "utils/inval.h"
 #include "utils/lsyscache.h"
 #include "utils/memutils.h"
 #include "utils/relmapper.h"
-#include "utils/resowner_private.h"
+#include "utils/resowner.h"
 #include "utils/snapmgr.h"
 #include "utils/syscache.h"
 
@@ -2078,6 +2079,18 @@ RelationIdGetRelation(Oid relationId)
  * ----------------------------------------------------------------
  */
 
+/* ResourceOwner callbacks to track relcache references */
+static void ResOwnerReleaseRelation(Datum res);
+static void ResOwnerPrintRelCacheLeakWarning(Datum res);
+
+static ResourceOwnerFuncs relref_resowner_funcs =
+{
+	.name = "relcache reference",
+	.phase = RESOURCE_RELEASE_BEFORE_LOCKS,
+	.ReleaseResource = ResOwnerReleaseRelation,
+	.PrintLeakWarning = ResOwnerPrintRelCacheLeakWarning
+};
+
 /*
  * RelationIncrementReferenceCount
  *		Increments relation reference count.
@@ -2089,10 +2102,10 @@ RelationIdGetRelation(Oid relationId)
 void
 RelationIncrementReferenceCount(Relation rel)
 {
-	ResourceOwnerEnlargeRelationRefs(CurrentResourceOwner);
+	ResourceOwnerEnlarge(CurrentResourceOwner);
 	rel->rd_refcnt += 1;
 	if (!IsBootstrapProcessingMode())
-		ResourceOwnerRememberRelationRef(CurrentResourceOwner, rel);
+		ResourceOwnerRemember(CurrentResourceOwner, PointerGetDatum(rel), &relref_resowner_funcs);
 }
 
 /*
@@ -2105,7 +2118,7 @@ RelationDecrementReferenceCount(Relation rel)
 	Assert(rel->rd_refcnt > 0);
 	rel->rd_refcnt -= 1;
 	if (!IsBootstrapProcessingMode())
-		ResourceOwnerForgetRelationRef(CurrentResourceOwner, rel);
+		ResourceOwnerForget(CurrentResourceOwner, PointerGetDatum(rel), &relref_resowner_funcs);
 }
 
 /*
@@ -6417,3 +6430,21 @@ unlink_initfile(const char *initfilename, int elevel)
 							initfilename)));
 	}
 }
+
+/*
+ * ResourceOwner callbacks
+ */
+static void
+ResOwnerPrintRelCacheLeakWarning(Datum res)
+{
+	Relation rel = (Relation) res;
+
+	elog(WARNING, "relcache reference leak: relation \"%s\" not closed",
+		 RelationGetRelationName(rel));
+}
+
+static void
+ResOwnerReleaseRelation(Datum res)
+{
+	RelationClose((Relation) res);
+}
diff --git a/src/backend/utils/resowner/README b/src/backend/utils/resowner/README
index 2998f6bb362..c67ca603526 100644
--- a/src/backend/utils/resowner/README
+++ b/src/backend/utils/resowner/README
@@ -60,13 +60,18 @@ subtransaction or portal.  Therefore, the "release" operation on a child
 ResourceOwner transfers lock ownership to the parent instead of actually
 releasing the lock, if isCommit is true.
 
-Currently, ResourceOwners contain direct support for recording ownership of
-buffer pins, lmgr locks, and catcache, relcache, plancache, tupdesc, and
-snapshot references.  Other objects can be associated with a ResourceOwner by
-recording the address of the owning ResourceOwner in such an object.  There is
-an API for other modules to get control during ResourceOwner release, so that
-they can scan their own data structures to find the objects that need to be
-deleted.
+ResourceOwner can record ownership of many different kinds of objects.
+As of this writing, it's used internally for buffer pins, lmgr locks, and
+catcache, relcache, plancache, tupdesc, snapshot, DSM and JIT context
+references. ResourceOwner treats all resource the same, and extensions
+can define a new kind of resource by defining a new ResourceOwnerFuncs
+instance with a few callback functions.
+
+There is also an API for other modules to get control during ResourceOwner
+release, so that they can scan their own data structures to find the objects
+that need to be deleted. This used to be the only way to register new kinds
+of objects with a resource owner; nowadays it easier to write custom
+ResourceOwnerFuncs callbacks.
 
 Whenever we are inside a transaction, the global variable
 CurrentResourceOwner shows which resource owner should be assigned
diff --git a/src/backend/utils/resowner/resowner.c b/src/backend/utils/resowner/resowner.c
index 10f15f6a357..75fda4fcc13 100644
--- a/src/backend/utils/resowner/resowner.c
+++ b/src/backend/utils/resowner/resowner.c
@@ -22,73 +22,44 @@
 
 #include "common/cryptohash.h"
 #include "common/hashfn.h"
-#include "jit/jit.h"
-#include "storage/bufmgr.h"
 #include "storage/ipc.h"
 #include "storage/predicate.h"
 #include "storage/proc.h"
 #include "utils/memutils.h"
-#include "utils/rel.h"
-#include "utils/resowner_private.h"
-#include "utils/snapmgr.h"
-
-
-/*
- * All resource IDs managed by this code are required to fit into a Datum,
- * which is fine since they are generally pointers or integers.
- *
- * Provide Datum conversion macros for a couple of things that are really
- * just "int".
- */
-#define FileGetDatum(file) Int32GetDatum(file)
-#define DatumGetFile(datum) ((File) DatumGetInt32(datum))
-#define BufferGetDatum(buffer) Int32GetDatum(buffer)
-#define DatumGetBuffer(datum) ((Buffer) DatumGetInt32(datum))
+#include "utils/plancache.h"
+#include "utils/resowner.h"
 
 /*
- * ResourceArray is a common structure for storing all types of resource IDs.
- *
- * We manage small sets of resource IDs by keeping them in a simple array:
- * itemsarr[k] holds an ID, for 0 <= k < nitems <= maxitems = capacity.
- *
- * If a set grows large, we switch over to using open-addressing hashing.
- * Then, itemsarr[] is a hash table of "capacity" slots, with each
- * slot holding either an ID or "invalidval".  nitems is the number of valid
- * items present; if it would exceed maxitems, we enlarge the array and
- * re-hash.  In this mode, maxitems should be rather less than capacity so
- * that we don't waste too much time searching for empty slots.
+ * ResourceElem represents a reference associated with a resource owner.
  *
- * In either mode, lastidx remembers the location of the last item inserted
- * or returned by GetAny; this speeds up searches in ResourceArrayRemove.
+ * All objects managed by this code are required to fit into a Datum,
+ * which is fine since they are generally pointers or integers.
  */
-typedef struct ResourceArray
+typedef struct ResourceElem
 {
-	Datum	   *itemsarr;		/* buffer for storing values */
-	Datum		invalidval;		/* value that is considered invalid */
-	uint32		capacity;		/* allocated length of itemsarr[] */
-	uint32		nitems;			/* how many items are stored in items array */
-	uint32		maxitems;		/* current limit on nitems before enlarging */
-	uint32		lastidx;		/* index of last item returned by GetAny */
-} ResourceArray;
+	Datum		item;
+	ResourceOwnerFuncs *kind;
+} ResourceElem;
 
 /*
- * Initially allocated size of a ResourceArray.  Must be power of two since
- * we'll use (arraysize - 1) as mask for hashing.
+ * Size of the small fixed-size array to hold most-recently remembered resources.
  */
-#define RESARRAY_INIT_SIZE 16
+#define RESOWNER_ARRAY_SIZE 8
 
 /*
- * When to switch to hashing vs. simple array logic in a ResourceArray.
+ * Initially allocated size of a ResourceOwner's hash.  Must be power of two since
+ * we'll use (capacity - 1) as mask for hashing.
  */
-#define RESARRAY_MAX_ARRAY 64
-#define RESARRAY_IS_ARRAY(resarr) ((resarr)->capacity <= RESARRAY_MAX_ARRAY)
+#define RESOWNER_HASH_INIT_SIZE 32
 
 /*
- * How many items may be stored in a resource array of given capacity.
+ * How many items may be stored in a hash of given capacity.
  * When this number is reached, we must resize.
  */
-#define RESARRAY_MAX_ITEMS(capacity) \
-	((capacity) <= RESARRAY_MAX_ARRAY ? (capacity) : (capacity)/4 * 3)
+#define RESOWNER_HASH_MAX_ITEMS(capacity) ((capacity)/4 * 3)
+
+StaticAssertDecl(RESOWNER_HASH_MAX_ITEMS(RESOWNER_HASH_INIT_SIZE) > RESOWNER_ARRAY_SIZE,
+				 "initial hash size too small compared to array size");
 
 /*
  * To speed up bulk releasing or reassigning locks from a resource owner to
@@ -118,23 +89,33 @@ typedef struct ResourceOwnerData
 	ResourceOwner nextchild;	/* next child of same parent */
 	const char *name;			/* name (just for debugging) */
 
-	/* We have built-in support for remembering: */
-	ResourceArray bufferarr;	/* owned buffers */
-	ResourceArray catrefarr;	/* catcache references */
-	ResourceArray catlistrefarr;	/* catcache-list pins */
-	ResourceArray relrefarr;	/* relcache references */
-	ResourceArray planrefarr;	/* plancache references */
-	ResourceArray tupdescarr;	/* tupdesc references */
-	ResourceArray snapshotarr;	/* snapshot references */
-	ResourceArray filearr;		/* open temporary files */
-	ResourceArray dsmarr;		/* dynamic shmem segments */
-	ResourceArray jitarr;		/* JIT contexts */
-	ResourceArray cryptohasharr;	/* cryptohash contexts */
+	/*
+	 * These structs keep track of the objects registered with this owner.
+	 *
+	 * We manage a small set of references by keeping them in a simple
+	 * array. When the array gets full, all the elements in the array are
+	 * moved to a hash table. This way, the array always contains a few
+	 * most recently remembered references. To find a particular reference,
+	 * you need to search both the array and the hash table.
+	 */
+	ResourceElem arr[RESOWNER_ARRAY_SIZE];
+	uint32		narr;			/* how many items are stored in the array */
+
+	/*
+	 * The hash table. Uses open-addressing. 'nhash' is the number of items
+	 * present; if it would exceed 'grow_at', we enlarge it and re-hash.
+	 * 'grow_at' should be rather less than 'capacity' so that we don't waste
+	 * too much time searching for empty slots.
+	 */
+	ResourceElem *hash;
+	uint32		nhash;			/* how many items are stored in the hash */
+	uint32		capacity;		/* allocated length of hash[] */
+	uint32		grow_at;		/* grow hash when reach this */
 
 	/* We can remember up to MAX_RESOWNER_LOCKS references to local locks. */
 	int			nlocks;			/* number of owned locks */
 	LOCALLOCK  *locks[MAX_RESOWNER_LOCKS];	/* list of owned locks */
-}			ResourceOwnerData;
+} ResourceOwnerData;
 
 
 /*****************************************************************************
@@ -146,6 +127,18 @@ ResourceOwner CurTransactionResourceOwner = NULL;
 ResourceOwner TopTransactionResourceOwner = NULL;
 ResourceOwner AuxProcessResourceOwner = NULL;
 
+/* #define RESOWNER_STATS */
+/* #define RESOWNER_TRACE */
+
+#ifdef RESOWNER_STATS
+static int narray_lookups = 0;
+static int nhash_lookups = 0;
+#endif
+
+#ifdef RESOWNER_TRACE
+static int resowner_trace_counter = 0;
+#endif
+
 /*
  * List of add-on callbacks for resource releasing
  */
@@ -160,296 +153,311 @@ static ResourceReleaseCallbackItem *ResourceRelease_callbacks = NULL;
 
 
 /* Internal routines */
-static void ResourceArrayInit(ResourceArray *resarr, Datum invalidval);
-static void ResourceArrayEnlarge(ResourceArray *resarr);
-static void ResourceArrayAdd(ResourceArray *resarr, Datum value);
-static bool ResourceArrayRemove(ResourceArray *resarr, Datum value);
-static bool ResourceArrayGetAny(ResourceArray *resarr, Datum *value);
-static void ResourceArrayFree(ResourceArray *resarr);
 static void ResourceOwnerReleaseInternal(ResourceOwner owner,
 										 ResourceReleasePhase phase,
 										 bool isCommit,
 										 bool isTopLevel);
 static void ReleaseAuxProcessResourcesCallback(int code, Datum arg);
-static void PrintRelCacheLeakWarning(Relation rel);
-static void PrintPlanCacheLeakWarning(CachedPlan *plan);
-static void PrintTupleDescLeakWarning(TupleDesc tupdesc);
-static void PrintSnapshotLeakWarning(Snapshot snapshot);
-static void PrintFileLeakWarning(File file);
-static void PrintDSMLeakWarning(dsm_segment *seg);
-static void PrintCryptoHashLeakWarning(Datum handle);
 
 
 /*****************************************************************************
  *	  INTERNAL ROUTINES														 *
  *****************************************************************************/
 
+static inline uint32
+hash_resource_elem(Datum value, ResourceOwnerFuncs *kind)
+{
+	Datum		data[2];
+
+	data[0] = value;
+	data[1] = PointerGetDatum(kind);
+
+	return hash_bytes((unsigned char *) &data, 2 * SIZEOF_DATUM);
+}
 
-/*
- * Initialize a ResourceArray
- */
 static void
-ResourceArrayInit(ResourceArray *resarr, Datum invalidval)
+ResourceArrayAddToHash(ResourceOwner owner, Datum value, ResourceOwnerFuncs *kind)
 {
-	/* Assert it's empty */
-	Assert(resarr->itemsarr == NULL);
-	Assert(resarr->capacity == 0);
-	Assert(resarr->nitems == 0);
-	Assert(resarr->maxitems == 0);
-	/* Remember the appropriate "invalid" value */
-	resarr->invalidval = invalidval;
-	/* We don't allocate any storage until needed */
+	/* Insert into first free slot at or after hash location. */
+	uint32		mask = owner->capacity - 1;
+	uint32		idx;
+
+	idx = hash_resource_elem(value, kind) & mask;
+	for (;;)
+	{
+		if (owner->hash[idx].kind == NULL)
+			break;
+		idx = (idx + 1) & mask;
+	}
+	owner->hash[idx].item = value;
+	owner->hash[idx].kind = kind;
+	owner->nhash++;
 }
 
 /*
- * Make sure there is room for at least one more resource in an array.
- *
- * This is separate from actually inserting a resource because if we run out
- * of memory, it's critical to do so *before* acquiring the resource.
+ * Call the ReleaseResource callback on entries with given 'phase'.
  */
 static void
-ResourceArrayEnlarge(ResourceArray *resarr)
+ResourceOwnerReleaseAll(ResourceOwner owner, ResourceReleasePhase phase,
+						bool printLeakWarnings)
 {
-	uint32		i,
-				oldcap,
-				newcap;
-	Datum	   *olditemsarr;
-	Datum	   *newitemsarr;
-
-	if (resarr->nitems < resarr->maxitems)
-		return;					/* no work needed */
+	bool		found;
+	int			capacity;
 
-	olditemsarr = resarr->itemsarr;
-	oldcap = resarr->capacity;
-
-	/* Double the capacity of the array (capacity must stay a power of 2!) */
-	newcap = (oldcap > 0) ? oldcap * 2 : RESARRAY_INIT_SIZE;
-	newitemsarr = (Datum *) MemoryContextAlloc(TopMemoryContext,
-											   newcap * sizeof(Datum));
-	for (i = 0; i < newcap; i++)
-		newitemsarr[i] = resarr->invalidval;
+	/* First handle all the entries in the array. */
+	do
+	{
+		found = false;
+		for (int i = 0; i < owner->narr; i++)
+		{
+			if (owner->arr[i].kind->phase == phase)
+			{
+				Datum		value = owner->arr[i].item;
+				ResourceOwnerFuncs *kind = owner->arr[i].kind;
 
-	/* We assume we can't fail below this point, so OK to scribble on resarr */
-	resarr->itemsarr = newitemsarr;
-	resarr->capacity = newcap;
-	resarr->maxitems = RESARRAY_MAX_ITEMS(newcap);
-	resarr->nitems = 0;
+				if (printLeakWarnings)
+					kind->PrintLeakWarning(value);
+				kind->ReleaseResource(value);
+				found = true;
+			}
+		}
 
-	if (olditemsarr != NULL)
-	{
 		/*
-		 * Transfer any pre-existing entries into the new array; they don't
-		 * necessarily go where they were before, so this simple logic is the
-		 * best way.  Note that if we were managing the set as a simple array,
-		 * the entries after nitems are garbage, but that shouldn't matter
-		 * because we won't get here unless nitems was equal to oldcap.
+		 * If any resources were released, check again because some of the
+		 * elements might have been moved by the callbacks. We don't want to
+		 * miss them.
 		 */
-		for (i = 0; i < oldcap; i++)
+	} while (found && owner->narr > 0);
+
+	/* Ok, the array has now been handled. Then the hash */
+	do
+	{
+		capacity = owner->capacity;
+		for (int idx = 0; idx < capacity; idx++)
 		{
-			if (olditemsarr[i] != resarr->invalidval)
-				ResourceArrayAdd(resarr, olditemsarr[i]);
+			while (owner->hash[idx].kind != NULL &&
+				   owner->hash[idx].kind->phase == phase)
+			{
+				Datum		value = owner->hash[idx].item;
+				ResourceOwnerFuncs *kind = owner->hash[idx].kind;
+
+				if (printLeakWarnings)
+					kind->PrintLeakWarning(value);
+				kind->ReleaseResource(value);
+
+				/*
+				 * If the resource is remembered more than once in this
+				 * resource owner, the ReleaseResource callback might've
+				 * released a different copy of it. Because of that, loop
+				 * to check the same index again.
+				 */
+			}
 		}
 
-		/* And release old array. */
-		pfree(olditemsarr);
-	}
-
-	Assert(resarr->nitems < resarr->maxitems);
+		/*
+		 * It's possible that the callbacks acquired more resources, causing
+		 * the hash table to grow and the existing entries to be moved
+		 * around. If that happened, scan the hash table again, so that we
+		 * don't miss entries that were moved. (XXX: I'm not sure if any of
+		 * the callbacks actually do that, but this is cheap to check, and
+		 * better safe than sorry.)
+		 */
+		Assert(owner->capacity >= capacity);
+	} while (capacity != owner->capacity);
 }
 
+
+/*****************************************************************************
+ *	  EXPORTED ROUTINES														 *
+ *****************************************************************************/
+
+
 /*
- * Add a resource to ResourceArray
+ * ResourceOwnerCreate
+ *		Create an empty ResourceOwner.
  *
- * Caller must have previously done ResourceArrayEnlarge()
+ * All ResourceOwner objects are kept in TopMemoryContext, since they should
+ * only be freed explicitly.
  */
-static void
-ResourceArrayAdd(ResourceArray *resarr, Datum value)
+ResourceOwner
+ResourceOwnerCreate(ResourceOwner parent, const char *name)
 {
-	uint32		idx;
+	ResourceOwner owner;
 
-	Assert(value != resarr->invalidval);
-	Assert(resarr->nitems < resarr->maxitems);
+	owner = (ResourceOwner) MemoryContextAllocZero(TopMemoryContext,
+												   sizeof(ResourceOwnerData));
+	owner->name = name;
 
-	if (RESARRAY_IS_ARRAY(resarr))
+	if (parent)
 	{
-		/* Append to linear array. */
-		idx = resarr->nitems;
+		owner->parent = parent;
+		owner->nextchild = parent->firstchild;
+		parent->firstchild = owner;
 	}
-	else
-	{
-		/* Insert into first free slot at or after hash location. */
-		uint32		mask = resarr->capacity - 1;
 
-		idx = DatumGetUInt32(hash_any((void *) &value, sizeof(value))) & mask;
-		for (;;)
-		{
-			if (resarr->itemsarr[idx] == resarr->invalidval)
-				break;
-			idx = (idx + 1) & mask;
-		}
-	}
-	resarr->lastidx = idx;
-	resarr->itemsarr[idx] = value;
-	resarr->nitems++;
+#ifdef RESOWNER_TRACE
+	elog(LOG, "CREATE %d: %p %s",
+		 resowner_trace_counter++, owner, name);
+#endif
+
+	return owner;
 }
 
 /*
- * Remove a resource from ResourceArray
- *
- * Returns true on success, false if resource was not found.
+ * Make sure there is room for at least one more resource in an array.
  *
- * Note: if same resource ID appears more than once, one instance is removed.
+ * This is separate from actually inserting a resource because if we run out
+ * of memory, it's critical to do so *before* acquiring the resource.
  */
-static bool
-ResourceArrayRemove(ResourceArray *resarr, Datum value)
+void
+ResourceOwnerEnlarge(ResourceOwner owner)
 {
-	uint32		i,
-				idx,
-				lastidx = resarr->lastidx;
-
-	Assert(value != resarr->invalidval);
+	if (owner->narr < RESOWNER_ARRAY_SIZE)
+		return;					/* no work needed */
 
-	/* Search through all items, but try lastidx first. */
-	if (RESARRAY_IS_ARRAY(resarr))
+	/* Is there space in the hash? If not, enlarge it. */
+	if (owner->narr + owner->nhash >= owner->grow_at)
 	{
-		if (lastidx < resarr->nitems &&
-			resarr->itemsarr[lastidx] == value)
-		{
-			resarr->itemsarr[lastidx] = resarr->itemsarr[resarr->nitems - 1];
-			resarr->nitems--;
-			/* Update lastidx to make reverse-order removals fast. */
-			resarr->lastidx = resarr->nitems - 1;
-			return true;
-		}
-		for (i = 0; i < resarr->nitems; i++)
+		uint32		i,
+					oldcap,
+					newcap;
+		ResourceElem *oldhash;
+		ResourceElem *newhash;
+
+		oldhash = owner->hash;
+		oldcap = owner->capacity;
+
+		/* Double the capacity (it must stay a power of 2!) */
+		newcap = (oldcap > 0) ? oldcap * 2 : RESOWNER_HASH_INIT_SIZE;
+		newhash = (ResourceElem *) MemoryContextAllocZero(TopMemoryContext,
+														  newcap * sizeof(ResourceElem));
+
+		/* We assume we can't fail below this point, so OK to scribble on FIXME */
+		owner->hash = newhash;
+		owner->capacity = newcap;
+		owner->grow_at = RESOWNER_HASH_MAX_ITEMS(newcap);
+		owner->nhash = 0;
+
+		if (oldhash != NULL)
 		{
-			if (resarr->itemsarr[i] == value)
+			/*
+			 * Transfer any pre-existing entries into the new hash table; they don't
+			 * necessarily go where they were before, so this simple logic is the
+			 * best way.
+			 */
+			for (i = 0; i < oldcap; i++)
 			{
-				resarr->itemsarr[i] = resarr->itemsarr[resarr->nitems - 1];
-				resarr->nitems--;
-				/* Update lastidx to make reverse-order removals fast. */
-				resarr->lastidx = resarr->nitems - 1;
-				return true;
+				if (oldhash[i].kind != NULL)
+					ResourceArrayAddToHash(owner, oldhash[i].item, oldhash[i].kind);
 			}
+
+			/* And release old hash table. */
+			pfree(oldhash);
 		}
 	}
-	else
-	{
-		uint32		mask = resarr->capacity - 1;
 
-		if (lastidx < resarr->capacity &&
-			resarr->itemsarr[lastidx] == value)
-		{
-			resarr->itemsarr[lastidx] = resarr->invalidval;
-			resarr->nitems--;
-			return true;
-		}
-		idx = DatumGetUInt32(hash_any((void *) &value, sizeof(value))) & mask;
-		for (i = 0; i < resarr->capacity; i++)
-		{
-			if (resarr->itemsarr[idx] == value)
-			{
-				resarr->itemsarr[idx] = resarr->invalidval;
-				resarr->nitems--;
-				return true;
-			}
-			idx = (idx + 1) & mask;
-		}
+	/* Move items from the array to the hash */
+	for (int i = 0; i < owner->narr; i++)
+	{
+		ResourceArrayAddToHash(owner, owner->arr[i].item, owner->arr[i].kind);
 	}
+	owner->narr = 0;
 
-	return false;
+	Assert(owner->nhash < owner->grow_at);
 }
 
 /*
- * Get any convenient entry in a ResourceArray.
- *
- * "Convenient" is defined as "easy for ResourceArrayRemove to remove";
- * we help that along by setting lastidx to match.  This avoids O(N^2) cost
- * when removing all ResourceArray items during ResourceOwner destruction.
+ * Remember that an object is owner by a ReourceOwner
  *
- * Returns true if we found an element, or false if the array is empty.
+ * Caller must have previously done ResourceOwnerEnlarge()
  */
-static bool
-ResourceArrayGetAny(ResourceArray *resarr, Datum *value)
+void
+ResourceOwnerRemember(ResourceOwner owner, Datum value, ResourceOwnerFuncs *kind)
 {
-	if (resarr->nitems == 0)
-		return false;
+	uint32		idx;
 
-	if (RESARRAY_IS_ARRAY(resarr))
-	{
-		/* Linear array: just return the first element. */
-		resarr->lastidx = 0;
-	}
-	else
-	{
-		/* Hash: search forward from wherever we were last. */
-		uint32		mask = resarr->capacity - 1;
+#ifdef RESOWNER_TRACE
+	elog(LOG, "REMEMBER %d: owner %p value " UINT64_FORMAT ", kind: %s",
+		 resowner_trace_counter++, owner, DatumGetUInt64(value), kind->name);
+#endif
 
-		for (;;)
-		{
-			resarr->lastidx &= mask;
-			if (resarr->itemsarr[resarr->lastidx] != resarr->invalidval)
-				break;
-			resarr->lastidx++;
-		}
-	}
+	Assert(owner->narr < RESOWNER_ARRAY_SIZE);
 
-	*value = resarr->itemsarr[resarr->lastidx];
-	return true;
+	/* Append to linear array. */
+	idx = owner->narr;
+	owner->arr[idx].item = value;
+	owner->arr[idx].kind = kind;
+	owner->narr++;
 }
 
 /*
- * Trash a ResourceArray (we don't care about its state after this)
+ * Forget that an object is owned by a ResourceOwner
+ *
+ * Returns true on success. If the resource was not found, returns false,
+ * and calls kind->ForgetError callback.
+ *
+ * Note: if same resource ID is associated with the ResourceOwner more than once,
+ * one instance is removed.
  */
-static void
-ResourceArrayFree(ResourceArray *resarr)
+void
+ResourceOwnerForget(ResourceOwner owner, Datum value, ResourceOwnerFuncs *kind)
 {
-	if (resarr->itemsarr)
-		pfree(resarr->itemsarr);
-}
+	uint32		i,
+				idx;
 
+#ifdef RESOWNER_TRACE
+	elog(LOG, "FORGET %d: owner %p value " UINT64_FORMAT ", kind: %s",
+		 resowner_trace_counter++, owner, DatumGetUInt64(value), kind->name);
+#endif
 
-/*****************************************************************************
- *	  EXPORTED ROUTINES														 *
- *****************************************************************************/
+	/* Search through all items, but check the array first. */
+	for (i = 0; i < owner->narr; i++)
+	{
+		if (owner->arr[i].item == value &&
+			owner->arr[i].kind == kind)
+		{
+			owner->arr[i] = owner->arr[owner->narr - 1];
+			owner->narr--;
 
+#ifdef RESOWNER_STATS
+			narray_lookups++;
+#endif
 
-/*
- * ResourceOwnerCreate
- *		Create an empty ResourceOwner.
- *
- * All ResourceOwner objects are kept in TopMemoryContext, since they should
- * only be freed explicitly.
- */
-ResourceOwner
-ResourceOwnerCreate(ResourceOwner parent, const char *name)
-{
-	ResourceOwner owner;
-
-	owner = (ResourceOwner) MemoryContextAllocZero(TopMemoryContext,
-												   sizeof(ResourceOwnerData));
-	owner->name = name;
+			return;
+		}
+	}
 
-	if (parent)
+	/* Search hash */
+	if (owner->nhash > 0)
 	{
-		owner->parent = parent;
-		owner->nextchild = parent->firstchild;
-		parent->firstchild = owner;
-	}
+		uint32		mask = owner->capacity - 1;
 
-	ResourceArrayInit(&(owner->bufferarr), BufferGetDatum(InvalidBuffer));
-	ResourceArrayInit(&(owner->catrefarr), PointerGetDatum(NULL));
-	ResourceArrayInit(&(owner->catlistrefarr), PointerGetDatum(NULL));
-	ResourceArrayInit(&(owner->relrefarr), PointerGetDatum(NULL));
-	ResourceArrayInit(&(owner->planrefarr), PointerGetDatum(NULL));
-	ResourceArrayInit(&(owner->tupdescarr), PointerGetDatum(NULL));
-	ResourceArrayInit(&(owner->snapshotarr), PointerGetDatum(NULL));
-	ResourceArrayInit(&(owner->filearr), FileGetDatum(-1));
-	ResourceArrayInit(&(owner->dsmarr), PointerGetDatum(NULL));
-	ResourceArrayInit(&(owner->jitarr), PointerGetDatum(NULL));
-	ResourceArrayInit(&(owner->cryptohasharr), PointerGetDatum(NULL));
+		idx = hash_resource_elem(value, kind) & mask;
+		for (i = 0; i < owner->capacity; i++)
+		{
+			if (owner->hash[idx].item == value &&
+				owner->hash[idx].kind == kind)
+			{
+				owner->hash[idx].item = (Datum) 0;
+				owner->hash[idx].kind = NULL;
+				owner->nhash--;
+
+#ifdef RESOWNER_STATS
+				nhash_lookups++;
+#endif
+				return;
+			}
+			idx = (idx + 1) & mask;
+		}
+	}
 
-	return owner;
+	/*
+	 * Use %p to print the reference, since most objects tracked by a resource owner
+	 * are pointers. It's a bit misleading if it's not a pointer, but this is a
+	 * programmer error, anyway.
+	 */
+	elog(ERROR, "%s %p is not owned by resource owner %s",
+		 kind->name, DatumGetPointer(value), owner->name);
 }
 
 /*
@@ -486,6 +494,15 @@ ResourceOwnerRelease(ResourceOwner owner,
 {
 	/* There's not currently any setup needed before recursing */
 	ResourceOwnerReleaseInternal(owner, phase, isCommit, isTopLevel);
+
+#ifdef RESOWNER_STATS
+	if (isTopLevel)
+	{
+		elog(LOG, "RESOWNER STATS: lookups: array %d, hash %d", narray_lookups, nhash_lookups);
+		narray_lookups = 0;
+		nhash_lookups = 0;
+	}
+#endif
 }
 
 static void
@@ -497,7 +514,6 @@ ResourceOwnerReleaseInternal(ResourceOwner owner,
 	ResourceOwner child;
 	ResourceOwner save;
 	ResourceReleaseCallbackItem *item;
-	Datum		foundres;
 
 	/* Recurse to handle descendants */
 	for (child = owner->firstchild; child != NULL; child = child->nextchild)
@@ -513,61 +529,13 @@ ResourceOwnerReleaseInternal(ResourceOwner owner,
 	if (phase == RESOURCE_RELEASE_BEFORE_LOCKS)
 	{
 		/*
-		 * Release buffer pins.  Note that ReleaseBuffer will remove the
-		 * buffer entry from our array, so we just have to iterate till there
-		 * are none.
+		 * Release all references that need to be released before the locks.
 		 *
-		 * During a commit, there shouldn't be any remaining pins --- that
+		 * During a commit, there shouldn't be any remaining references --- that
 		 * would indicate failure to clean up the executor correctly --- so
 		 * issue warnings.  In the abort case, just clean up quietly.
 		 */
-		while (ResourceArrayGetAny(&(owner->bufferarr), &foundres))
-		{
-			Buffer		res = DatumGetBuffer(foundres);
-
-			if (isCommit)
-				PrintBufferLeakWarning(res);
-			ReleaseBuffer(res);
-		}
-
-		/* Ditto for relcache references */
-		while (ResourceArrayGetAny(&(owner->relrefarr), &foundres))
-		{
-			Relation	res = (Relation) DatumGetPointer(foundres);
-
-			if (isCommit)
-				PrintRelCacheLeakWarning(res);
-			RelationClose(res);
-		}
-
-		/* Ditto for dynamic shared memory segments */
-		while (ResourceArrayGetAny(&(owner->dsmarr), &foundres))
-		{
-			dsm_segment *res = (dsm_segment *) DatumGetPointer(foundres);
-
-			if (isCommit)
-				PrintDSMLeakWarning(res);
-			dsm_detach(res);
-		}
-
-		/* Ditto for JIT contexts */
-		while (ResourceArrayGetAny(&(owner->jitarr), &foundres))
-		{
-			JitContext *context = (JitContext *) PointerGetDatum(foundres);
-
-			jit_release_context(context);
-		}
-
-		/* Ditto for cryptohash contexts */
-		while (ResourceArrayGetAny(&(owner->cryptohasharr), &foundres))
-		{
-			pg_cryptohash_ctx *context =
-			(pg_cryptohash_ctx *) PointerGetDatum(foundres);
-
-			if (isCommit)
-				PrintCryptoHashLeakWarning(foundres);
-			pg_cryptohash_free(context);
-		}
+		ResourceOwnerReleaseAll(owner, phase, isCommit);
 	}
 	else if (phase == RESOURCE_RELEASE_LOCKS)
 	{
@@ -576,7 +544,7 @@ ResourceOwnerReleaseInternal(ResourceOwner owner,
 			/*
 			 * For a top-level xact we are going to release all locks (or at
 			 * least all non-session locks), so just do a single lmgr call at
-			 * the top of the recursion.
+			 * the top of the recursion
 			 */
 			if (owner == TopTransactionResourceOwner)
 			{
@@ -620,70 +588,9 @@ ResourceOwnerReleaseInternal(ResourceOwner owner,
 	else if (phase == RESOURCE_RELEASE_AFTER_LOCKS)
 	{
 		/*
-		 * Release catcache references.  Note that ReleaseCatCache will remove
-		 * the catref entry from our array, so we just have to iterate till
-		 * there are none.
-		 *
-		 * As with buffer pins, warn if any are left at commit time.
+		 * Release all references that need to be released after the locks.
 		 */
-		while (ResourceArrayGetAny(&(owner->catrefarr), &foundres))
-		{
-			HeapTuple	res = (HeapTuple) DatumGetPointer(foundres);
-
-			if (isCommit)
-				PrintCatCacheLeakWarning(res);
-			ReleaseCatCache(res);
-		}
-
-		/* Ditto for catcache lists */
-		while (ResourceArrayGetAny(&(owner->catlistrefarr), &foundres))
-		{
-			CatCList   *res = (CatCList *) DatumGetPointer(foundres);
-
-			if (isCommit)
-				PrintCatCacheListLeakWarning(res);
-			ReleaseCatCacheList(res);
-		}
-
-		/* Ditto for plancache references */
-		while (ResourceArrayGetAny(&(owner->planrefarr), &foundres))
-		{
-			CachedPlan *res = (CachedPlan *) DatumGetPointer(foundres);
-
-			if (isCommit)
-				PrintPlanCacheLeakWarning(res);
-			ReleaseCachedPlan(res, true);
-		}
-
-		/* Ditto for tupdesc references */
-		while (ResourceArrayGetAny(&(owner->tupdescarr), &foundres))
-		{
-			TupleDesc	res = (TupleDesc) DatumGetPointer(foundres);
-
-			if (isCommit)
-				PrintTupleDescLeakWarning(res);
-			DecrTupleDescRefCount(res);
-		}
-
-		/* Ditto for snapshot references */
-		while (ResourceArrayGetAny(&(owner->snapshotarr), &foundres))
-		{
-			Snapshot	res = (Snapshot) DatumGetPointer(foundres);
-
-			if (isCommit)
-				PrintSnapshotLeakWarning(res);
-			UnregisterSnapshot(res);
-		}
-
-		/* Ditto for temporary files */
-		while (ResourceArrayGetAny(&(owner->filearr), &foundres))
-		{
-			File		res = DatumGetFile(foundres);
-
-			if (isCommit)
-				PrintFileLeakWarning(res);
-			FileClose(res);
-		}
+		ResourceOwnerReleaseAll(owner, phase, isCommit);
 	}
 
 	/* Let add-on modules get a chance too */
@@ -704,16 +611,42 @@ void
 ResourceOwnerReleaseAllPlanCacheRefs(ResourceOwner owner)
 {
 	ResourceOwner save;
-	Datum		foundres;
 
 	save = CurrentResourceOwner;
 	CurrentResourceOwner = owner;
-	while (ResourceArrayGetAny(&(owner->planrefarr), &foundres))
+
+	/* array first */
+	for (int i = 0; i < owner->narr; i++)
+	{
+		if (owner->arr[i].kind == &planref_resowner_funcs)
+		{
+			CachedPlan *planref = (CachedPlan *) DatumGetPointer(owner->arr[i].item);
+
+			owner->arr[i] = owner->arr[owner->narr - 1];
+			owner->narr--;
+			i--;
+
+			/* pass 'false' because we already removed the entry from the resowner */
+			ReleaseCachedPlan(planref, false);
+		}
+	}
+
+	/* Then hash */
+	for (int i = 0; i < owner->capacity; i++)
 	{
-		CachedPlan *res = (CachedPlan *) DatumGetPointer(foundres);
+		if (owner->hash[i].kind == &planref_resowner_funcs)
+		{
+			CachedPlan *planref = (CachedPlan *) DatumGetPointer(owner->hash[i].item);
 
-		ReleaseCachedPlan(res, true);
+			owner->hash[i].item = (Datum) 0;
+			owner->hash[i].kind = NULL;
+			owner->nhash--;
+
+			/* pass 'false' because we already removed the entry from the resowner */
+			ReleaseCachedPlan(planref, false);
+		}
 	}
+
 	CurrentResourceOwner = save;
 }
 
@@ -730,19 +663,15 @@ ResourceOwnerDelete(ResourceOwner owner)
 	Assert(owner != CurrentResourceOwner);
 
 	/* And it better not own any resources, either */
-	Assert(owner->bufferarr.nitems == 0);
-	Assert(owner->catrefarr.nitems == 0);
-	Assert(owner->catlistrefarr.nitems == 0);
-	Assert(owner->relrefarr.nitems == 0);
-	Assert(owner->planrefarr.nitems == 0);
-	Assert(owner->tupdescarr.nitems == 0);
-	Assert(owner->snapshotarr.nitems == 0);
-	Assert(owner->filearr.nitems == 0);
-	Assert(owner->dsmarr.nitems == 0);
-	Assert(owner->jitarr.nitems == 0);
-	Assert(owner->cryptohasharr.nitems == 0);
+	Assert(owner->narr == 0);
+	Assert(owner->nhash == 0);
 	Assert(owner->nlocks == 0 || owner->nlocks == MAX_RESOWNER_LOCKS + 1);
 
+#ifdef RESOWNER_TRACE
+	elog(LOG, "DELETE %d: %p %s",
+		 resowner_trace_counter++, owner, owner->name);
+#endif
+
 	/*
 	 * Delete children.  The recursive call will delink the child from me, so
 	 * just iterate as long as there is a child.
@@ -758,18 +687,8 @@ ResourceOwnerDelete(ResourceOwner owner)
 	ResourceOwnerNewParent(owner, NULL);
 
 	/* And free the object. */
-	ResourceArrayFree(&(owner->bufferarr));
-	ResourceArrayFree(&(owner->catrefarr));
-	ResourceArrayFree(&(owner->catlistrefarr));
-	ResourceArrayFree(&(owner->relrefarr));
-	ResourceArrayFree(&(owner->planrefarr));
-	ResourceArrayFree(&(owner->tupdescarr));
-	ResourceArrayFree(&(owner->snapshotarr));
-	ResourceArrayFree(&(owner->filearr));
-	ResourceArrayFree(&(owner->dsmarr));
-	ResourceArrayFree(&(owner->jitarr));
-	ResourceArrayFree(&(owner->cryptohasharr));
-
+	if (owner->hash)
+		pfree(owner->hash);
 	pfree(owner);
 }
 
@@ -827,11 +746,10 @@ ResourceOwnerNewParent(ResourceOwner owner,
 /*
  * Register or deregister callback functions for resource cleanup
  *
- * These functions are intended for use by dynamically loaded modules.
- * For built-in modules we generally just hardwire the appropriate calls.
- *
- * Note that the callback occurs post-commit or post-abort, so the callback
- * functions can only do noncritical cleanup.
+ * These functions can be used by dynamically loaded modules. These used
+ * to be the only way for an extension to register custom resource types
+ * with a resource owner, but nowadays it is easier to define a new
+ * ResourceOwnerFuncs instance with custom callbacks.
  */
 void
 RegisterResourceReleaseCallback(ResourceReleaseCallback callback, void *arg)
@@ -922,44 +840,6 @@ ReleaseAuxProcessResourcesCallback(int code, Datum arg)
 	ReleaseAuxProcessResources(isCommit);
 }
 
-
-/*
- * Make sure there is room for at least one more entry in a ResourceOwner's
- * buffer array.
- *
- * This is separate from actually inserting an entry because if we run out
- * of memory, it's critical to do so *before* acquiring the resource.
- */
-void
-ResourceOwnerEnlargeBuffers(ResourceOwner owner)
-{
-	/* We used to allow pinning buffers without a resowner, but no more */
-	Assert(owner != NULL);
-	ResourceArrayEnlarge(&(owner->bufferarr));
-}
-
-/*
- * Remember that a buffer pin is owned by a ResourceOwner
- *
- * Caller must have previously done ResourceOwnerEnlargeBuffers()
- */
-void
-ResourceOwnerRememberBuffer(ResourceOwner owner, Buffer buffer)
-{
-	ResourceArrayAdd(&(owner->bufferarr), BufferGetDatum(buffer));
-}
-
-/*
- * Forget that a buffer pin is owned by a ResourceOwner
- */
-void
-ResourceOwnerForgetBuffer(ResourceOwner owner, Buffer buffer)
-{
-	if (!ResourceArrayRemove(&(owner->bufferarr), BufferGetDatum(buffer)))
-		elog(ERROR, "buffer %d is not owned by resource owner %s",
-			 buffer, owner->name);
-}
-
 /*
  * Remember that a Local Lock is owned by a ResourceOwner
  *
@@ -1011,424 +891,3 @@ ResourceOwnerForgetLock(ResourceOwner owner, LOCALLOCK *locallock)
 	elog(ERROR, "lock reference %p is not owned by resource owner %s",
 		 locallock, owner->name);
 }
-
-/*
- * Make sure there is room for at least one more entry in a ResourceOwner's
- * catcache reference array.
- *
- * This is separate from actually inserting an entry because if we run out
- * of memory, it's critical to do so *before* acquiring the resource.
- */
-void
-ResourceOwnerEnlargeCatCacheRefs(ResourceOwner owner)
-{
-	ResourceArrayEnlarge(&(owner->catrefarr));
-}
-
-/*
- * Remember that a catcache reference is owned by a ResourceOwner
- *
- * Caller must have previously done ResourceOwnerEnlargeCatCacheRefs()
- */
-void
-ResourceOwnerRememberCatCacheRef(ResourceOwner owner, HeapTuple tuple)
-{
-	ResourceArrayAdd(&(owner->catrefarr), PointerGetDatum(tuple));
-}
-
-/*
- * Forget that a catcache reference is owned by a ResourceOwner
- */
-void
-ResourceOwnerForgetCatCacheRef(ResourceOwner owner, HeapTuple tuple)
-{
-	if (!ResourceArrayRemove(&(owner->catrefarr), PointerGetDatum(tuple)))
-		elog(ERROR, "catcache reference %p is not owned by resource owner %s",
-			 tuple, owner->name);
-}
-
-/*
- * Make sure there is room for at least one more entry in a ResourceOwner's
- * catcache-list reference array.
- *
- * This is separate from actually inserting an entry because if we run out
- * of memory, it's critical to do so *before* acquiring the resource.
- */
-void
-ResourceOwnerEnlargeCatCacheListRefs(ResourceOwner owner)
-{
-	ResourceArrayEnlarge(&(owner->catlistrefarr));
-}
-
-/*
- * Remember that a catcache-list reference is owned by a ResourceOwner
- *
- * Caller must have previously done ResourceOwnerEnlargeCatCacheListRefs()
- */
-void
-ResourceOwnerRememberCatCacheListRef(ResourceOwner owner, CatCList *list)
-{
-	ResourceArrayAdd(&(owner->catlistrefarr), PointerGetDatum(list));
-}
-
-/*
- * Forget that a catcache-list reference is owned by a ResourceOwner
- */
-void
-ResourceOwnerForgetCatCacheListRef(ResourceOwner owner, CatCList *list)
-{
-	if (!ResourceArrayRemove(&(owner->catlistrefarr), PointerGetDatum(list)))
-		elog(ERROR, "catcache list reference %p is not owned by resource owner %s",
-			 list, owner->name);
-}
-
-/*
- * Make sure there is room for at least one more entry in a ResourceOwner's
- * relcache reference array.
- *
- * This is separate from actually inserting an entry because if we run out
- * of memory, it's critical to do so *before* acquiring the resource.
- */
-void
-ResourceOwnerEnlargeRelationRefs(ResourceOwner owner)
-{
-	ResourceArrayEnlarge(&(owner->relrefarr));
-}
-
-/*
- * Remember that a relcache reference is owned by a ResourceOwner
- *
- * Caller must have previously done ResourceOwnerEnlargeRelationRefs()
- */
-void
-ResourceOwnerRememberRelationRef(ResourceOwner owner, Relation rel)
-{
-	ResourceArrayAdd(&(owner->relrefarr), PointerGetDatum(rel));
-}
-
-/*
- * Forget that a relcache reference is owned by a ResourceOwner
- */
-void
-ResourceOwnerForgetRelationRef(ResourceOwner owner, Relation rel)
-{
-	if (!ResourceArrayRemove(&(owner->relrefarr), PointerGetDatum(rel)))
-		elog(ERROR, "relcache reference %s is not owned by resource owner %s",
-			 RelationGetRelationName(rel), owner->name);
-}
-
-/*
- * Debugging subroutine
- */
-static void
-PrintRelCacheLeakWarning(Relation rel)
-{
-	elog(WARNING, "relcache reference leak: relation \"%s\" not closed",
-		 RelationGetRelationName(rel));
-}
-
-/*
- * Make sure there is room for at least one more entry in a ResourceOwner's
- * plancache reference array.
- *
- * This is separate from actually inserting an entry because if we run out
- * of memory, it's critical to do so *before* acquiring the resource.
- */
-void
-ResourceOwnerEnlargePlanCacheRefs(ResourceOwner owner)
-{
-	ResourceArrayEnlarge(&(owner->planrefarr));
-}
-
-/*
- * Remember that a plancache reference is owned by a ResourceOwner
- *
- * Caller must have previously done ResourceOwnerEnlargePlanCacheRefs()
- */
-void
-ResourceOwnerRememberPlanCacheRef(ResourceOwner owner, CachedPlan *plan)
-{
-	ResourceArrayAdd(&(owner->planrefarr), PointerGetDatum(plan));
-}
-
-/*
- * Forget that a plancache reference is owned by a ResourceOwner
- */
-void
-ResourceOwnerForgetPlanCacheRef(ResourceOwner owner, CachedPlan *plan)
-{
-	if (!ResourceArrayRemove(&(owner->planrefarr), PointerGetDatum(plan)))
-		elog(ERROR, "plancache reference %p is not owned by resource owner %s",
-			 plan, owner->name);
-}
-
-/*
- * Debugging subroutine
- */
-static void
-PrintPlanCacheLeakWarning(CachedPlan *plan)
-{
-	elog(WARNING, "plancache reference leak: plan %p not closed", plan);
-}
-
-/*
- * Make sure there is room for at least one more entry in a ResourceOwner's
- * tupdesc reference array.
- *
- * This is separate from actually inserting an entry because if we run out
- * of memory, it's critical to do so *before* acquiring the resource.
- */
-void
-ResourceOwnerEnlargeTupleDescs(ResourceOwner owner)
-{
-	ResourceArrayEnlarge(&(owner->tupdescarr));
-}
-
-/*
- * Remember that a tupdesc reference is owned by a ResourceOwner
- *
- * Caller must have previously done ResourceOwnerEnlargeTupleDescs()
- */
-void
-ResourceOwnerRememberTupleDesc(ResourceOwner owner, TupleDesc tupdesc)
-{
-	ResourceArrayAdd(&(owner->tupdescarr), PointerGetDatum(tupdesc));
-}
-
-/*
- * Forget that a tupdesc reference is owned by a ResourceOwner
- */
-void
-ResourceOwnerForgetTupleDesc(ResourceOwner owner, TupleDesc tupdesc)
-{
-	if (!ResourceArrayRemove(&(owner->tupdescarr), PointerGetDatum(tupdesc)))
-		elog(ERROR, "tupdesc reference %p is not owned by resource owner %s",
-			 tupdesc, owner->name);
-}
-
-/*
- * Debugging subroutine
- */
-static void
-PrintTupleDescLeakWarning(TupleDesc tupdesc)
-{
-	elog(WARNING,
-		 "TupleDesc reference leak: TupleDesc %p (%u,%d) still referenced",
-		 tupdesc, tupdesc->tdtypeid, tupdesc->tdtypmod);
-}
-
-/*
- * Make sure there is room for at least one more entry in a ResourceOwner's
- * snapshot reference array.
- *
- * This is separate from actually inserting an entry because if we run out
- * of memory, it's critical to do so *before* acquiring the resource.
- */
-void
-ResourceOwnerEnlargeSnapshots(ResourceOwner owner)
-{
-	ResourceArrayEnlarge(&(owner->snapshotarr));
-}
-
-/*
- * Remember that a snapshot reference is owned by a ResourceOwner
- *
- * Caller must have previously done ResourceOwnerEnlargeSnapshots()
- */
-void
-ResourceOwnerRememberSnapshot(ResourceOwner owner, Snapshot snapshot)
-{
-	ResourceArrayAdd(&(owner->snapshotarr), PointerGetDatum(snapshot));
-}
-
-/*
- * Forget that a snapshot reference is owned by a ResourceOwner
- */
-void
-ResourceOwnerForgetSnapshot(ResourceOwner owner, Snapshot snapshot)
-{
-	if (!ResourceArrayRemove(&(owner->snapshotarr), PointerGetDatum(snapshot)))
-		elog(ERROR, "snapshot reference %p is not owned by resource owner %s",
-			 snapshot, owner->name);
-}
-
-/*
- * Debugging subroutine
- */
-static void
-PrintSnapshotLeakWarning(Snapshot snapshot)
-{
-	elog(WARNING, "Snapshot reference leak: Snapshot %p still referenced",
-		 snapshot);
-}
-
-
-/*
- * Make sure there is room for at least one more entry in a ResourceOwner's
- * files reference array.
- *
- * This is separate from actually inserting an entry because if we run out
- * of memory, it's critical to do so *before* acquiring the resource.
- */
-void
-ResourceOwnerEnlargeFiles(ResourceOwner owner)
-{
-	ResourceArrayEnlarge(&(owner->filearr));
-}
-
-/*
- * Remember that a temporary file is owned by a ResourceOwner
- *
- * Caller must have previously done ResourceOwnerEnlargeFiles()
- */
-void
-ResourceOwnerRememberFile(ResourceOwner owner, File file)
-{
-	ResourceArrayAdd(&(owner->filearr), FileGetDatum(file));
-}
-
-/*
- * Forget that a temporary file is owned by a ResourceOwner
- */
-void
-ResourceOwnerForgetFile(ResourceOwner owner, File file)
-{
-	if (!ResourceArrayRemove(&(owner->filearr), FileGetDatum(file)))
-		elog(ERROR, "temporary file %d is not owned by resource owner %s",
-			 file, owner->name);
-}
-
-/*
- * Debugging subroutine
- */
-static void
-PrintFileLeakWarning(File file)
-{
-	elog(WARNING, "temporary file leak: File %d still referenced",
-		 file);
-}
-
-/*
- * Make sure there is room for at least one more entry in a ResourceOwner's
- * dynamic shmem segment reference array.
- *
- * This is separate from actually inserting an entry because if we run out
- * of memory, it's critical to do so *before* acquiring the resource.
- */
-void
-ResourceOwnerEnlargeDSMs(ResourceOwner owner)
-{
-	ResourceArrayEnlarge(&(owner->dsmarr));
-}
-
-/*
- * Remember that a dynamic shmem segment is owned by a ResourceOwner
- *
- * Caller must have previously done ResourceOwnerEnlargeDSMs()
- */
-void
-ResourceOwnerRememberDSM(ResourceOwner owner, dsm_segment *seg)
-{
-	ResourceArrayAdd(&(owner->dsmarr), PointerGetDatum(seg));
-}
-
-/*
- * Forget that a dynamic shmem segment is owned by a ResourceOwner
- */
-void
-ResourceOwnerForgetDSM(ResourceOwner owner, dsm_segment *seg)
-{
-	if (!ResourceArrayRemove(&(owner->dsmarr), PointerGetDatum(seg)))
-		elog(ERROR, "dynamic shared memory segment %u is not owned by resource owner %s",
-			 dsm_segment_handle(seg), owner->name);
-}
-
-/*
- * Debugging subroutine
- */
-static void
-PrintDSMLeakWarning(dsm_segment *seg)
-{
-	elog(WARNING, "dynamic shared memory leak: segment %u still referenced",
-		 dsm_segment_handle(seg));
-}
-
-/*
- * Make sure there is room for at least one more entry in a ResourceOwner's
- * JIT context reference array.
- *
- * This is separate from actually inserting an entry because if we run out of
- * memory, it's critical to do so *before* acquiring the resource.
- */
-void
-ResourceOwnerEnlargeJIT(ResourceOwner owner)
-{
-	ResourceArrayEnlarge(&(owner->jitarr));
-}
-
-/*
- * Remember that a JIT context is owned by a ResourceOwner
- *
- * Caller must have previously done ResourceOwnerEnlargeJIT()
- */
-void
-ResourceOwnerRememberJIT(ResourceOwner owner, Datum handle)
-{
-	ResourceArrayAdd(&(owner->jitarr), handle);
-}
-
-/*
- * Forget that a JIT context is owned by a ResourceOwner
- */
-void
-ResourceOwnerForgetJIT(ResourceOwner owner, Datum handle)
-{
-	if (!ResourceArrayRemove(&(owner->jitarr), handle))
-		elog(ERROR, "JIT context %p is not owned by resource owner %s",
-			 DatumGetPointer(handle), owner->name);
-}
-
-/*
- * Make sure there is room for at least one more entry in a ResourceOwner's
- * cryptohash context reference array.
- *
- * This is separate from actually inserting an entry because if we run out of
- * memory, it's critical to do so *before* acquiring the resource.
- */
-void
-ResourceOwnerEnlargeCryptoHash(ResourceOwner owner)
-{
-	ResourceArrayEnlarge(&(owner->cryptohasharr));
-}
-
-/*
- * Remember that a cryptohash context is owned by a ResourceOwner
- *
- * Caller must have previously done ResourceOwnerEnlargeCryptoHash()
- */
-void
-ResourceOwnerRememberCryptoHash(ResourceOwner owner, Datum handle)
-{
-	ResourceArrayAdd(&(owner->cryptohasharr), handle);
-}
-
-/*
- * Forget that a cryptohash context is owned by a ResourceOwner
- */
-void
-ResourceOwnerForgetCryptoHash(ResourceOwner owner, Datum handle)
-{
-	if (!ResourceArrayRemove(&(owner->cryptohasharr), handle))
-		elog(ERROR, "cryptohash context %p is not owned by resource owner %s",
-			 DatumGetPointer(handle), owner->name);
-}
-
-/*
- * Debugging subroutine
- */
-static void
-PrintCryptoHashLeakWarning(Datum handle)
-{
-	elog(WARNING, "cryptohash context reference leak: context %p still referenced",
-		 DatumGetPointer(handle));
-}
diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c
index ae16c3ed7d6..10cec8d39d0 100644
--- a/src/backend/utils/time/snapmgr.c
+++ b/src/backend/utils/time/snapmgr.c
@@ -66,7 +66,7 @@
 #include "utils/memutils.h"
 #include "utils/old_snapshot.h"
 #include "utils/rel.h"
-#include "utils/resowner_private.h"
+#include "utils/resowner.h"
 #include "utils/snapmgr.h"
 #include "utils/syscache.h"
 #include "utils/timestamp.h"
@@ -174,6 +174,18 @@ static Snapshot CopySnapshot(Snapshot snapshot);
 static void FreeSnapshot(Snapshot snapshot);
 static void SnapshotResetXmin(void);
 
+/* ResourceOwner callbacks to track snapshot references */
+static void ResOwnerReleaseSnapshot(Datum res);
+static void ResOwnerPrintSnapshotLeakWarning(Datum res);
+
+static ResourceOwnerFuncs snapshot_resowner_funcs =
+{
+	.name = "snapshot reference",
+	.phase = RESOURCE_RELEASE_AFTER_LOCKS,
+	.ReleaseResource = ResOwnerReleaseSnapshot,
+	.PrintLeakWarning = ResOwnerPrintSnapshotLeakWarning
+};
+
 /*
  * Snapshot fields to be serialized.
  *
@@ -831,9 +843,10 @@ RegisterSnapshotOnOwner(Snapshot snapshot, ResourceOwner owner)
 	snap = snapshot->copied ? snapshot : CopySnapshot(snapshot);
 
 	/* and tell resowner.c about it */
-	ResourceOwnerEnlargeSnapshots(owner);
+	ResourceOwnerEnlarge(owner);
 	snap->regd_count++;
-	ResourceOwnerRememberSnapshot(owner, snap);
+	ResourceOwnerRemember(owner, PointerGetDatum(snap),
+						  &snapshot_resowner_funcs);
 
 	if (snap->regd_count == 1)
 		pairingheap_add(&RegisteredSnapshots, &snap->ph_node);
@@ -870,7 +883,8 @@ UnregisterSnapshotFromOwner(Snapshot snapshot, ResourceOwner owner)
 	Assert(snapshot->regd_count > 0);
 	Assert(!pairingheap_is_empty(&RegisteredSnapshots));
 
-	ResourceOwnerForgetSnapshot(owner, snapshot);
+	ResourceOwnerForget(owner, PointerGetDatum(snapshot),
+						&snapshot_resowner_funcs);
 
 	snapshot->regd_count--;
 	if (snapshot->regd_count == 0)
@@ -2345,3 +2359,19 @@ XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot)
 
 	return false;
 }
+
+/*
+ * ResourceOwner callbacks
+ */
+static void
+ResOwnerReleaseSnapshot(Datum res)
+{
+	UnregisterSnapshot((Snapshot) DatumGetPointer(res));
+}
+
+static void
+ResOwnerPrintSnapshotLeakWarning(Datum res)
+{
+	elog(WARNING, "Snapshot reference leak: Snapshot %p still referenced",
+		 DatumGetPointer(res));
+}
diff --git a/src/common/cryptohash_openssl.c b/src/common/cryptohash_openssl.c
index 551ec392b60..642e72d8c0f 100644
--- a/src/common/cryptohash_openssl.c
+++ b/src/common/cryptohash_openssl.c
@@ -27,7 +27,6 @@
 #ifndef FRONTEND
 #include "utils/memutils.h"
 #include "utils/resowner.h"
-#include "utils/resowner_private.h"
 #endif
 
 /*
@@ -60,6 +59,21 @@ struct pg_cryptohash_ctx
 #endif
 };
 
+/* ResourceOwner callbacks to hold JitContexts  */
+#ifndef FRONTEND
+static void ResOwnerReleaseCryptoHash(Datum res);
+static void ResOwnerPrintCryptoHashLeakWarning(Datum res);
+
+static ResourceOwnerFuncs cryptohash_funcs =
+{
+	/* relcache references */
+	.name = "OpenSSL cryptohash context",
+	.phase = RESOURCE_RELEASE_BEFORE_LOCKS,
+	.ReleaseResource = ResOwnerReleaseCryptoHash,
+	.PrintLeakWarning = ResOwnerPrintCryptoHashLeakWarning,
+};
+#endif
+
 /*
  * pg_cryptohash_create
  *
@@ -77,7 +91,7 @@ pg_cryptohash_create(pg_cryptohash_type type)
 	 * allocation to avoid leaking.
 	 */
 #ifndef FRONTEND
-	ResourceOwnerEnlargeCryptoHash(CurrentResourceOwner);
+	ResourceOwnerEnlarge(CurrentResourceOwner);
 #endif
 
 	ctx = ALLOC(sizeof(pg_cryptohash_ctx));
@@ -106,8 +120,8 @@ pg_cryptohash_create(pg_cryptohash_type type)
 
 #ifndef FRONTEND
 	ctx->resowner = CurrentResourceOwner;
-	ResourceOwnerRememberCryptoHash(CurrentResourceOwner,
-									PointerGetDatum(ctx));
+	ResourceOwnerRemember(CurrentResourceOwner, PointerGetDatum(ctx),
+						  &cryptohash_funcs);
 #endif
 
 	return ctx;
@@ -207,10 +221,29 @@ pg_cryptohash_free(pg_cryptohash_ctx *ctx)
 	EVP_MD_CTX_destroy(ctx->evpctx);
 
 #ifndef FRONTEND
-	ResourceOwnerForgetCryptoHash(ctx->resowner,
-								  PointerGetDatum(ctx));
+	ResourceOwnerForget(ctx->resowner, PointerGetDatum(ctx),
+						&cryptohash_funcs);
 #endif
 
 	explicit_bzero(ctx, sizeof(pg_cryptohash_ctx));
 	FREE(ctx);
 }
+
+
+/*
+ * ResourceOwner callbacks
+ */
+#ifndef FRONTEND
+static void
+ResOwnerReleaseCryptoHash(Datum res)
+{
+	pg_cryptohash_free((pg_cryptohash_ctx *) DatumGetPointer(res));
+}
+
+static void
+ResOwnerPrintCryptoHashLeakWarning(Datum res)
+{
+	elog(WARNING, "cryptohash context reference leak: context %p still referenced",
+		 DatumGetPointer(res));
+}
+#endif
diff --git a/src/include/storage/buf_internals.h b/src/include/storage/buf_internals.h
index f6b57829653..6815dc38a16 100644
--- a/src/include/storage/buf_internals.h
+++ b/src/include/storage/buf_internals.h
@@ -296,6 +296,15 @@ typedef struct CkptSortItem
 
 extern CkptSortItem *CkptBufferIds;
 
+/* ResourceOwner callbacks to hold buffer pins */
+extern ResourceOwnerFuncs buffer_resowner_funcs;
+
+/* Convenience wrappers over ResourceOwnerRemember/Forget */
+#define ResourceOwnerRememberBuffer(owner, buffer) \
+	ResourceOwnerRemember(owner, Int32GetDatum(buffer), &buffer_resowner_funcs)
+#define ResourceOwnerForgetBuffer(owner, buffer) \
+	ResourceOwnerForget(owner, Int32GetDatum(buffer), &buffer_resowner_funcs)
+
 /*
  * Internal buffer management routines
  */
diff --git a/src/include/utils/catcache.h b/src/include/utils/catcache.h
index ddc2762eb3f..2bf95c22e84 100644
--- a/src/include/utils/catcache.h
+++ b/src/include/utils/catcache.h
@@ -225,7 +225,4 @@ extern void PrepareToInvalidateCacheTuple(Relation relation,
 										  HeapTuple newtuple,
 										  void (*function) (int, uint32, Oid));
 
-extern void PrintCatCacheLeakWarning(HeapTuple tuple);
-extern void PrintCatCacheListLeakWarning(CatCList *list);
-
 #endif							/* CATCACHE_H */
diff --git a/src/include/utils/plancache.h b/src/include/utils/plancache.h
index 79d96e5ed03..964af79b30d 100644
--- a/src/include/utils/plancache.h
+++ b/src/include/utils/plancache.h
@@ -233,4 +233,6 @@ extern bool CachedPlanIsSimplyValid(CachedPlanSource *plansource,
 extern CachedExpression *GetCachedExpression(Node *expr);
 extern void FreeCachedExpression(CachedExpression *cexpr);
 
+extern ResourceOwnerFuncs planref_resowner_funcs;
+
 #endif							/* PLANCACHE_H */
diff --git a/src/include/utils/resowner.h b/src/include/utils/resowner.h
index 109ac31b248..d59d14c0d01 100644
--- a/src/include/utils/resowner.h
+++ b/src/include/utils/resowner.h
@@ -50,6 +50,36 @@ typedef enum
 	RESOURCE_RELEASE_AFTER_LOCKS
 } ResourceReleasePhase;
 
+/*
+ * In order to track an object, resowner.c needs a few callbacks for it.
+ * The callbacks for an resource of a specific kind are encapsulated in
+ * ResourceOwnerFuncs.
+ *
+ * Note that the callback occurs post-commit or post-abort, so these callback
+ * functions can only do noncritical cleanup.
+ */
+typedef struct ResourceOwnerFuncs
+{
+	const char *name;		/* name for the object kind, for debugging */
+
+	ResourceReleasePhase phase; /* when are these objects released? */
+
+	/*
+	 * Release resource.
+	 *
+	 * NOTE: this must call ResourceOwnerForget to disassociate it with the
+	 * resource owner.
+	 */
+	void (*ReleaseResource)(Datum res);
+
+	/*
+	 * Print a warning, when a resource has not been properly released before
+	 * commit.
+	 */
+	void (*PrintLeakWarning)(Datum res);
+
+} ResourceOwnerFuncs;
+
 /*
  *	Dynamically loaded modules can get control during ResourceOwnerRelease
  *	by providing a callback of this form.
@@ -71,16 +101,29 @@ extern void ResourceOwnerRelease(ResourceOwner owner,
 								 ResourceReleasePhase phase,
 								 bool isCommit,
 								 bool isTopLevel);
-extern void ResourceOwnerReleaseAllPlanCacheRefs(ResourceOwner owner);
 extern void ResourceOwnerDelete(ResourceOwner owner);
 extern ResourceOwner ResourceOwnerGetParent(ResourceOwner owner);
 extern void ResourceOwnerNewParent(ResourceOwner owner,
 								   ResourceOwner newparent);
+
+extern void ResourceOwnerEnlarge(ResourceOwner owner);
+extern void ResourceOwnerRemember(ResourceOwner owner, Datum res, ResourceOwnerFuncs *kind);
+extern void ResourceOwnerForget(ResourceOwner owner, Datum res, ResourceOwnerFuncs *kind);
+
 extern void RegisterResourceReleaseCallback(ResourceReleaseCallback callback,
 											void *arg);
 extern void UnregisterResourceReleaseCallback(ResourceReleaseCallback callback,
 											  void *arg);
+
 extern void CreateAuxProcessResourceOwner(void);
 extern void ReleaseAuxProcessResources(bool isCommit);
 
+/* special support for local lock management */
+struct LOCALLOCK;
+extern void ResourceOwnerRememberLock(ResourceOwner owner, struct LOCALLOCK *locallock);
+extern void ResourceOwnerForgetLock(ResourceOwner owner, struct LOCALLOCK *locallock);
+
+/* special function to relase all plancache references */
+extern void ResourceOwnerReleaseAllPlanCacheRefs(ResourceOwner owner);
+
 #endif							/* RESOWNER_H */
diff --git a/src/include/utils/resowner_private.h b/src/include/utils/resowner_private.h
deleted file mode 100644
index c480a1a24be..00000000000
--- a/src/include/utils/resowner_private.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * resowner_private.h
- *	  POSTGRES resource owner private definitions.
- *
- * See utils/resowner/README for more info.
- *
- *
- * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * src/include/utils/resowner_private.h
- *
- *-------------------------------------------------------------------------
- */
-#ifndef RESOWNER_PRIVATE_H
-#define RESOWNER_PRIVATE_H
-
-#include "storage/dsm.h"
-#include "storage/fd.h"
-#include "storage/lock.h"
-#include "utils/catcache.h"
-#include "utils/plancache.h"
-#include "utils/resowner.h"
-#include "utils/snapshot.h"
-
-
-/* support for buffer refcount management */
-extern void ResourceOwnerEnlargeBuffers(ResourceOwner owner);
-extern void ResourceOwnerRememberBuffer(ResourceOwner owner, Buffer buffer);
-extern void ResourceOwnerForgetBuffer(ResourceOwner owner, Buffer buffer);
-
-/* support for local lock management */
-extern void ResourceOwnerRememberLock(ResourceOwner owner, LOCALLOCK *locallock);
-extern void ResourceOwnerForgetLock(ResourceOwner owner, LOCALLOCK *locallock);
-
-/* support for catcache refcount management */
-extern void ResourceOwnerEnlargeCatCacheRefs(ResourceOwner owner);
-extern void ResourceOwnerRememberCatCacheRef(ResourceOwner owner,
-											 HeapTuple tuple);
-extern void ResourceOwnerForgetCatCacheRef(ResourceOwner owner,
-										   HeapTuple tuple);
-extern void ResourceOwnerEnlargeCatCacheListRefs(ResourceOwner owner);
-extern void ResourceOwnerRememberCatCacheListRef(ResourceOwner owner,
-												 CatCList *list);
-extern void ResourceOwnerForgetCatCacheListRef(ResourceOwner owner,
-											   CatCList *list);
-
-/* support for relcache refcount management */
-extern void ResourceOwnerEnlargeRelationRefs(ResourceOwner owner);
-extern void ResourceOwnerRememberRelationRef(ResourceOwner owner,
-											 Relation rel);
-extern void ResourceOwnerForgetRelationRef(ResourceOwner owner,
-										   Relation rel);
-
-/* support for plancache refcount management */
-extern void ResourceOwnerEnlargePlanCacheRefs(ResourceOwner owner);
-extern void ResourceOwnerRememberPlanCacheRef(ResourceOwner owner,
-											  CachedPlan *plan);
-extern void ResourceOwnerForgetPlanCacheRef(ResourceOwner owner,
-											CachedPlan *plan);
-
-/* support for tupledesc refcount management */
-extern void ResourceOwnerEnlargeTupleDescs(ResourceOwner owner);
-extern void ResourceOwnerRememberTupleDesc(ResourceOwner owner,
-										   TupleDesc tupdesc);
-extern void ResourceOwnerForgetTupleDesc(ResourceOwner owner,
-										 TupleDesc tupdesc);
-
-/* support for snapshot refcount management */
-extern void ResourceOwnerEnlargeSnapshots(ResourceOwner owner);
-extern void ResourceOwnerRememberSnapshot(ResourceOwner owner,
-										  Snapshot snapshot);
-extern void ResourceOwnerForgetSnapshot(ResourceOwner owner,
-										Snapshot snapshot);
-
-/* support for temporary file management */
-extern void ResourceOwnerEnlargeFiles(ResourceOwner owner);
-extern void ResourceOwnerRememberFile(ResourceOwner owner,
-									  File file);
-extern void ResourceOwnerForgetFile(ResourceOwner owner,
-									File file);
-
-/* support for dynamic shared memory management */
-extern void ResourceOwnerEnlargeDSMs(ResourceOwner owner);
-extern void ResourceOwnerRememberDSM(ResourceOwner owner,
-									 dsm_segment *);
-extern void ResourceOwnerForgetDSM(ResourceOwner owner,
-								   dsm_segment *);
-
-/* support for JITContext management */
-extern void ResourceOwnerEnlargeJIT(ResourceOwner owner);
-extern void ResourceOwnerRememberJIT(ResourceOwner owner,
-									 Datum handle);
-extern void ResourceOwnerForgetJIT(ResourceOwner owner,
-								   Datum handle);
-
-/* support for cryptohash context management */
-extern void ResourceOwnerEnlargeCryptoHash(ResourceOwner owner);
-extern void ResourceOwnerRememberCryptoHash(ResourceOwner owner,
-											Datum handle);
-extern void ResourceOwnerForgetCryptoHash(ResourceOwner owner,
-										  Datum handle);
-
-#endif							/* RESOWNER_PRIVATE_H */
-- 
2.29.2


--------------1104342304EC6341F5D7C60C
Content-Type: text/x-patch; charset=UTF-8;
 name="0001-resownerbench.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename="0001-resownerbench.patch"



^ permalink  raw  reply  [nested|flat] 10+ messages in thread

* Re: PGDOCS - add more links in the pub/sub reference pages
@ 2023-10-09 06:45  Peter Smith <[email protected]>
  0 siblings, 2 replies; 10+ messages in thread

From: Peter Smith @ 2023-10-09 06:45 UTC (permalink / raw)
  To: Amit Kapila <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>

On Mon, Oct 9, 2023 at 3:32 PM Amit Kapila <[email protected]> wrote:
>
> On Fri, Oct 6, 2023 at 12:15 PM Peter Smith <[email protected]> wrote:
> >
> > Here is a patch to add the 2 missing references:
> >
> > ref/alter_subscription.sgml ==> added more ids
> > ref/alter_publication.sgml ==> added link to
> > "sql-altersubscription-refresh-publication"
> > ref/drop_subscription.sgml ==> added link to "sql-altersubscription"
> >
>
> -   <varlistentry>
> +   <varlistentry id="sql-altersubscription-new-owner">
>      <term><replaceable class="parameter">new_owner</replaceable></term>
>      <listitem>
>       <para>
> @@ -281,7 +281,7 @@ ALTER SUBSCRIPTION <replaceable
> class="parameter">name</replaceable> RENAME TO <
>      </listitem>
>     </varlistentry>
>
> -   <varlistentry>
> +   <varlistentry id="sql-altersubscription-new-name">
>      <term><replaceable class="parameter">new_name</replaceable></term>
>      <listitem>
>

Thanks for looking at this patch!

> Shall we append 'params' in the above and other id's in the patch. For
> example, sql-altersubscription-params-new-name. The other places like
> alter_role.sgml and alter_table.sgml uses similar id's. Is there a
> reason to be different here?

In v1, I used the same pattern as on the CREATE SUBSCRIPTION page,
which doesn't look like those...

~~~

The "Parameters" section describes some things that really are parameters:

e.g.
"sql-altersubscription-name"
"sql-altersubscription-new-owner"
"sql-altersubscription-new-name">

I agree, emphasising that those ones are parameters is better. Changed
like this in v2.

"sql-altersubscription-params-name"
"sql-altersubscription-params-new-owner"
"sql-altersubscription-params-new-name">

~

But, the "Parameters" section also describes other SQL syntax clauses
which are not really parameters at all.

e.g.
"sql-altersubscription-refresh-publication"
"sql-altersubscription-enable"
"sql-altersubscription-disable"

So I felt those ones are more intuitive left as they are  -- e.g.,
instead of having ids/linkends like:

"sql-altersubscription-params-refresh-publication"
"sql-altersubscription-params-enable"
"sql-altersubscription-params-disable"

~~

PSA v2.

======
Kind Regards,
Peter Smith.
Fujitsu Australia


Attachments:

  [application/octet-stream] v2-0001-Add-more-link.patch (5.7K, ../../CAHut+Puf6TTuZFSdMZpNLbup6fs7qF2e4dM0-4bYimxEkCZwig@mail.gmail.com/2-v2-0001-Add-more-link.patch)
  download | inline diff:
From 3722e96aee518bb12e3f3c68594b31cc4295070d Mon Sep 17 00:00:00 2001
From: Peter Smith <[email protected]>
Date: Mon, 9 Oct 2023 17:35:32 +1100
Subject: [PATCH v2] Add more link

---
 doc/src/sgml/ref/alter_publication.sgml  |  3 ++-
 doc/src/sgml/ref/alter_subscription.sgml | 20 ++++++++++----------
 doc/src/sgml/ref/drop_subscription.sgml  |  2 +-
 3 files changed, 13 insertions(+), 12 deletions(-)

diff --git a/doc/src/sgml/ref/alter_publication.sgml b/doc/src/sgml/ref/alter_publication.sgml
index c8424bc..51a67a7 100644
--- a/doc/src/sgml/ref/alter_publication.sgml
+++ b/doc/src/sgml/ref/alter_publication.sgml
@@ -51,7 +51,8 @@ ALTER PUBLICATION <replaceable class="parameter">name</replaceable> RENAME TO <r
    <literal>ADD</literal> and <literal>DROP</literal> clauses will add and
    remove one or more tables/schemas from the publication.  Note that adding
    tables/schemas to a publication that is already subscribed to will require an
-   <literal>ALTER SUBSCRIPTION ... REFRESH PUBLICATION</literal> action on the
+   <link linkend="sql-altersubscription-refresh-publication">
+   <literal>ALTER SUBSCRIPTION ... REFRESH PUBLICATION</literal></link> action on the
    subscribing side in order to become effective. Note also that
    <literal>DROP TABLES IN SCHEMA</literal> will not drop any schema tables
    that were specified using
diff --git a/doc/src/sgml/ref/alter_subscription.sgml b/doc/src/sgml/ref/alter_subscription.sgml
index a85e04e..baf062d 100644
--- a/doc/src/sgml/ref/alter_subscription.sgml
+++ b/doc/src/sgml/ref/alter_subscription.sgml
@@ -85,7 +85,7 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
   <title>Parameters</title>
 
   <variablelist>
-   <varlistentry>
+   <varlistentry id="sql-altersubscription-params-name">
     <term><replaceable class="parameter">name</replaceable></term>
     <listitem>
      <para>
@@ -94,7 +94,7 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
     </listitem>
    </varlistentry>
 
-   <varlistentry>
+   <varlistentry id="sql-altersubscription-connection">
     <term><literal>CONNECTION '<replaceable class="parameter">conninfo</replaceable>'</literal></term>
     <listitem>
      <para>
@@ -105,7 +105,7 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
     </listitem>
    </varlistentry>
 
-   <varlistentry>
+   <varlistentry id="sql-altersubscription-setadddrop-publication">
     <term><literal>SET PUBLICATION <replaceable class="parameter">publication_name</replaceable></literal></term>
     <term><literal>ADD PUBLICATION <replaceable class="parameter">publication_name</replaceable></literal></term>
     <term><literal>DROP PUBLICATION <replaceable class="parameter">publication_name</replaceable></literal></term>
@@ -147,7 +147,7 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
     </listitem>
    </varlistentry>
 
-   <varlistentry>
+   <varlistentry id="sql-altersubscription-refresh-publication">
     <term><literal>REFRESH PUBLICATION</literal></term>
     <listitem>
      <para>
@@ -192,7 +192,7 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
     </listitem>
    </varlistentry>
 
-   <varlistentry>
+   <varlistentry id="sql-altersubscription-enable">
     <term><literal>ENABLE</literal></term>
     <listitem>
      <para>
@@ -202,7 +202,7 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
     </listitem>
    </varlistentry>
 
-   <varlistentry>
+   <varlistentry id="sql-altersubscription-disable">
     <term><literal>DISABLE</literal></term>
     <listitem>
      <para>
@@ -212,7 +212,7 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
     </listitem>
    </varlistentry>
 
-   <varlistentry>
+   <varlistentry id="sql-altersubscription-set">
     <term><literal>SET ( <replaceable class="parameter">subscription_parameter</replaceable> [= <replaceable class="parameter">value</replaceable>] [, ... ] )</literal></term>
     <listitem>
      <para>
@@ -232,7 +232,7 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
     </listitem>
    </varlistentry>
 
-   <varlistentry>
+   <varlistentry id="sql-altersubscription-skip">
     <term><literal>SKIP ( <replaceable class="parameter">skip_option</replaceable> = <replaceable class="parameter">value</replaceable> )</literal></term>
     <listitem>
      <para>
@@ -272,7 +272,7 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
     </listitem>
    </varlistentry>
 
-   <varlistentry>
+   <varlistentry id="sql-altersubscription-params-new-owner">
     <term><replaceable class="parameter">new_owner</replaceable></term>
     <listitem>
      <para>
@@ -281,7 +281,7 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
     </listitem>
    </varlistentry>
 
-   <varlistentry>
+   <varlistentry id="sql-altersubscription-params-new-name">
     <term><replaceable class="parameter">new_name</replaceable></term>
     <listitem>
      <para>
diff --git a/doc/src/sgml/ref/drop_subscription.sgml b/doc/src/sgml/ref/drop_subscription.sgml
index 2a67bde..f48997b 100644
--- a/doc/src/sgml/ref/drop_subscription.sgml
+++ b/doc/src/sgml/ref/drop_subscription.sgml
@@ -40,7 +40,7 @@ DROP SUBSCRIPTION [ IF EXISTS ] <replaceable class="parameter">name</replaceable
   <para>
    <command>DROP SUBSCRIPTION</command> cannot be executed inside a
    transaction block if the subscription is associated with a replication
-   slot.  (You can use <command>ALTER SUBSCRIPTION</command> to unset the
+   slot.  (You can use <link linkend="sql-altersubscription"><command>ALTER SUBSCRIPTION</command></link> to unset the
    slot.)
   </para>
  </refsect1>
-- 
1.8.3.1



^ permalink  raw  reply  [nested|flat] 10+ messages in thread

* Re: PGDOCS - add more links in the pub/sub reference pages
@ 2023-10-10 00:46  vignesh C <[email protected]>
  parent: Peter Smith <[email protected]>
  1 sibling, 1 reply; 10+ messages in thread

From: vignesh C @ 2023-10-10 00:46 UTC (permalink / raw)
  To: Peter Smith <[email protected]>; +Cc: Amit Kapila <[email protected]>; PostgreSQL Hackers <[email protected]>

On Mon, 9 Oct 2023 at 12:18, Peter Smith <[email protected]> wrote:
>
> On Mon, Oct 9, 2023 at 3:32 PM Amit Kapila <[email protected]> wrote:
> >
> > On Fri, Oct 6, 2023 at 12:15 PM Peter Smith <[email protected]> wrote:
> > >
> > > Here is a patch to add the 2 missing references:
> > >
> > > ref/alter_subscription.sgml ==> added more ids
> > > ref/alter_publication.sgml ==> added link to
> > > "sql-altersubscription-refresh-publication"
> > > ref/drop_subscription.sgml ==> added link to "sql-altersubscription"
> > >
> >
> > -   <varlistentry>
> > +   <varlistentry id="sql-altersubscription-new-owner">
> >      <term><replaceable class="parameter">new_owner</replaceable></term>
> >      <listitem>
> >       <para>
> > @@ -281,7 +281,7 @@ ALTER SUBSCRIPTION <replaceable
> > class="parameter">name</replaceable> RENAME TO <
> >      </listitem>
> >     </varlistentry>
> >
> > -   <varlistentry>
> > +   <varlistentry id="sql-altersubscription-new-name">
> >      <term><replaceable class="parameter">new_name</replaceable></term>
> >      <listitem>
> >
>
> Thanks for looking at this patch!
>
> > Shall we append 'params' in the above and other id's in the patch. For
> > example, sql-altersubscription-params-new-name. The other places like
> > alter_role.sgml and alter_table.sgml uses similar id's. Is there a
> > reason to be different here?
>
> In v1, I used the same pattern as on the CREATE SUBSCRIPTION page,
> which doesn't look like those...
>
> ~~~
>
> The "Parameters" section describes some things that really are parameters:
>
> e.g.
> "sql-altersubscription-name"
> "sql-altersubscription-new-owner"
> "sql-altersubscription-new-name">
>
> I agree, emphasising that those ones are parameters is better. Changed
> like this in v2.
>
> "sql-altersubscription-params-name"
> "sql-altersubscription-params-new-owner"
> "sql-altersubscription-params-new-name">
>
> ~
>
> But, the "Parameters" section also describes other SQL syntax clauses
> which are not really parameters at all.
>
> e.g.
> "sql-altersubscription-refresh-publication"
> "sql-altersubscription-enable"
> "sql-altersubscription-disable"
>
> So I felt those ones are more intuitive left as they are  -- e.g.,
> instead of having ids/linkends like:
>
> "sql-altersubscription-params-refresh-publication"
> "sql-altersubscription-params-enable"
> "sql-altersubscription-params-disable"
>
> ~~
>
> PSA v2.

I noticed a couple of other places where a link to "ALTER SUBSCRIPTION
... DISABLE" and "ALTER SUBSCRIPTION ... SET" can be specified in
drop_subscription:
To proceed in this situation, first disable the subscription by
executing  <literal>ALTER SUBSCRIPTION ... DISABLE</literal>, and then
disassociate it from the replication slot by executing <literal>ALTER
SUBSCRIPTION ... SET (slot_name = NONE)</literal>.

Regards,
Vignesh






^ permalink  raw  reply  [nested|flat] 10+ messages in thread

* Re: PGDOCS - add more links in the pub/sub reference pages
@ 2023-10-10 03:17  Peter Smith <[email protected]>
  parent: vignesh C <[email protected]>
  0 siblings, 1 reply; 10+ messages in thread

From: Peter Smith @ 2023-10-10 03:17 UTC (permalink / raw)
  To: vignesh C <[email protected]>; +Cc: Amit Kapila <[email protected]>; PostgreSQL Hackers <[email protected]>

On Tue, Oct 10, 2023 at 11:46 AM vignesh C <[email protected]> wrote:
>
> I noticed a couple of other places where a link to "ALTER SUBSCRIPTION
> ... DISABLE" and "ALTER SUBSCRIPTION ... SET" can be specified in
> drop_subscription:
> To proceed in this situation, first disable the subscription by
> executing  <literal>ALTER SUBSCRIPTION ... DISABLE</literal>, and then
> disassociate it from the replication slot by executing <literal>ALTER
> SUBSCRIPTION ... SET (slot_name = NONE)</literal>.
>

Hi Vignesh. Thanks for the review comments.

Modified as suggested.

PSA v3.

======
Kind Regards,
Peter Smith.
Fujitsu Australia


Attachments:

  [application/octet-stream] v3-0001-Add-more-links.patch (6.7K, ../../CAHut+Ptk1-36GBtagggykbO1onaSpuAK1e_Eq_NHbAdTa-EQuw@mail.gmail.com/2-v3-0001-Add-more-links.patch)
  download | inline diff:
From c94e510a79bea48603a6825f71cb8d2cbf73692b Mon Sep 17 00:00:00 2001
From: Peter Smith <[email protected]>
Date: Tue, 10 Oct 2023 14:11:07 +1100
Subject: [PATCH v3] Add more links

---
 doc/src/sgml/ref/alter_publication.sgml  |  3 ++-
 doc/src/sgml/ref/alter_subscription.sgml | 20 ++++++++++----------
 doc/src/sgml/ref/drop_subscription.sgml  |  8 +++++---
 3 files changed, 17 insertions(+), 14 deletions(-)

diff --git a/doc/src/sgml/ref/alter_publication.sgml b/doc/src/sgml/ref/alter_publication.sgml
index c8424bc..51a67a7 100644
--- a/doc/src/sgml/ref/alter_publication.sgml
+++ b/doc/src/sgml/ref/alter_publication.sgml
@@ -51,7 +51,8 @@ ALTER PUBLICATION <replaceable class="parameter">name</replaceable> RENAME TO <r
    <literal>ADD</literal> and <literal>DROP</literal> clauses will add and
    remove one or more tables/schemas from the publication.  Note that adding
    tables/schemas to a publication that is already subscribed to will require an
-   <literal>ALTER SUBSCRIPTION ... REFRESH PUBLICATION</literal> action on the
+   <link linkend="sql-altersubscription-refresh-publication">
+   <literal>ALTER SUBSCRIPTION ... REFRESH PUBLICATION</literal></link> action on the
    subscribing side in order to become effective. Note also that
    <literal>DROP TABLES IN SCHEMA</literal> will not drop any schema tables
    that were specified using
diff --git a/doc/src/sgml/ref/alter_subscription.sgml b/doc/src/sgml/ref/alter_subscription.sgml
index a85e04e..baf062d 100644
--- a/doc/src/sgml/ref/alter_subscription.sgml
+++ b/doc/src/sgml/ref/alter_subscription.sgml
@@ -85,7 +85,7 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
   <title>Parameters</title>
 
   <variablelist>
-   <varlistentry>
+   <varlistentry id="sql-altersubscription-params-name">
     <term><replaceable class="parameter">name</replaceable></term>
     <listitem>
      <para>
@@ -94,7 +94,7 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
     </listitem>
    </varlistentry>
 
-   <varlistentry>
+   <varlistentry id="sql-altersubscription-connection">
     <term><literal>CONNECTION '<replaceable class="parameter">conninfo</replaceable>'</literal></term>
     <listitem>
      <para>
@@ -105,7 +105,7 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
     </listitem>
    </varlistentry>
 
-   <varlistentry>
+   <varlistentry id="sql-altersubscription-setadddrop-publication">
     <term><literal>SET PUBLICATION <replaceable class="parameter">publication_name</replaceable></literal></term>
     <term><literal>ADD PUBLICATION <replaceable class="parameter">publication_name</replaceable></literal></term>
     <term><literal>DROP PUBLICATION <replaceable class="parameter">publication_name</replaceable></literal></term>
@@ -147,7 +147,7 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
     </listitem>
    </varlistentry>
 
-   <varlistentry>
+   <varlistentry id="sql-altersubscription-refresh-publication">
     <term><literal>REFRESH PUBLICATION</literal></term>
     <listitem>
      <para>
@@ -192,7 +192,7 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
     </listitem>
    </varlistentry>
 
-   <varlistentry>
+   <varlistentry id="sql-altersubscription-enable">
     <term><literal>ENABLE</literal></term>
     <listitem>
      <para>
@@ -202,7 +202,7 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
     </listitem>
    </varlistentry>
 
-   <varlistentry>
+   <varlistentry id="sql-altersubscription-disable">
     <term><literal>DISABLE</literal></term>
     <listitem>
      <para>
@@ -212,7 +212,7 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
     </listitem>
    </varlistentry>
 
-   <varlistentry>
+   <varlistentry id="sql-altersubscription-set">
     <term><literal>SET ( <replaceable class="parameter">subscription_parameter</replaceable> [= <replaceable class="parameter">value</replaceable>] [, ... ] )</literal></term>
     <listitem>
      <para>
@@ -232,7 +232,7 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
     </listitem>
    </varlistentry>
 
-   <varlistentry>
+   <varlistentry id="sql-altersubscription-skip">
     <term><literal>SKIP ( <replaceable class="parameter">skip_option</replaceable> = <replaceable class="parameter">value</replaceable> )</literal></term>
     <listitem>
      <para>
@@ -272,7 +272,7 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
     </listitem>
    </varlistentry>
 
-   <varlistentry>
+   <varlistentry id="sql-altersubscription-params-new-owner">
     <term><replaceable class="parameter">new_owner</replaceable></term>
     <listitem>
      <para>
@@ -281,7 +281,7 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
     </listitem>
    </varlistentry>
 
-   <varlistentry>
+   <varlistentry id="sql-altersubscription-params-new-name">
     <term><replaceable class="parameter">new_name</replaceable></term>
     <listitem>
      <para>
diff --git a/doc/src/sgml/ref/drop_subscription.sgml b/doc/src/sgml/ref/drop_subscription.sgml
index 2a67bde..6212644 100644
--- a/doc/src/sgml/ref/drop_subscription.sgml
+++ b/doc/src/sgml/ref/drop_subscription.sgml
@@ -40,7 +40,7 @@ DROP SUBSCRIPTION [ IF EXISTS ] <replaceable class="parameter">name</replaceable
   <para>
    <command>DROP SUBSCRIPTION</command> cannot be executed inside a
    transaction block if the subscription is associated with a replication
-   slot.  (You can use <command>ALTER SUBSCRIPTION</command> to unset the
+   slot.  (You can use <link linkend="sql-altersubscription"><command>ALTER SUBSCRIPTION</command></link> to unset the
    slot.)
   </para>
  </refsect1>
@@ -87,9 +87,11 @@ DROP SUBSCRIPTION [ IF EXISTS ] <replaceable class="parameter">name</replaceable
    replication slot cannot be dropped or does not exist or never existed,
    the <command>DROP SUBSCRIPTION</command> command will fail.  To proceed
    in this situation, first disable the subscription by executing
-   <literal>ALTER SUBSCRIPTION ... DISABLE</literal>, and then disassociate
+   <link linkend="sql-altersubscription-disable">
+   <literal>ALTER SUBSCRIPTION ... DISABLE</literal></link>, and then disassociate
    it from the replication slot by executing
-   <literal>ALTER SUBSCRIPTION ... SET (slot_name = NONE)</literal>.
+   <link linkend="sql-altersubscription-set">
+   <literal>ALTER SUBSCRIPTION ... SET (slot_name = NONE)</literal></link>.
    After that, <command>DROP SUBSCRIPTION</command> will no longer attempt any
    actions on a remote host.  Note that if the remote replication slot still
    exists, it (and any related table synchronization slots) should then be
-- 
1.8.3.1



^ permalink  raw  reply  [nested|flat] 10+ messages in thread

* Re: PGDOCS - add more links in the pub/sub reference pages
@ 2023-10-10 06:10  vignesh C <[email protected]>
  parent: Peter Smith <[email protected]>
  0 siblings, 1 reply; 10+ messages in thread

From: vignesh C @ 2023-10-10 06:10 UTC (permalink / raw)
  To: Peter Smith <[email protected]>; +Cc: Amit Kapila <[email protected]>; PostgreSQL Hackers <[email protected]>

On Tue, 10 Oct 2023 at 08:47, Peter Smith <[email protected]> wrote:
>
> On Tue, Oct 10, 2023 at 11:46 AM vignesh C <[email protected]> wrote:
> >
> > I noticed a couple of other places where a link to "ALTER SUBSCRIPTION
> > ... DISABLE" and "ALTER SUBSCRIPTION ... SET" can be specified in
> > drop_subscription:
> > To proceed in this situation, first disable the subscription by
> > executing  <literal>ALTER SUBSCRIPTION ... DISABLE</literal>, and then
> > disassociate it from the replication slot by executing <literal>ALTER
> > SUBSCRIPTION ... SET (slot_name = NONE)</literal>.
> >
>
> Hi Vignesh. Thanks for the review comments.
>
> Modified as suggested.
>
> PSA v3.

Few more instances in other logical replication related pages:
1) Another instance was in alter_subscription.sgml:
      Fetch missing table information from publisher.  This will start
      replication of tables that were added to the subscribed-to publications
      since <command>CREATE SUBSCRIPTION</command> or
      the last invocation of <command>REFRESH PUBLICATION</command>.
2) Few more instances were in logical-replication-subscription.html
2.a)    Normally, the remote replication slot is created automatically when the
    subscription is created using <command>CREATE SUBSCRIPTION</command> and it
    is dropped automatically when the subscription is dropped using
    <command>DROP SUBSCRIPTION</command>.  In some situations, however, it can
    be useful or necessary to manipulate the subscription and the underlying
    replication slot separately.
2.b)  When dropping a subscription, the remote host is not reachable.  In
       that case, disassociate the slot from the subscription
       using <command>ALTER SUBSCRIPTION</command> before attempting to drop
       the subscription.
2.c)      If a subscription is affected by this problem, the only way to resume
     replication is to adjust one of the column lists on the publication
     side so that they all match; and then either recreate the subscription,
     or use <literal>ALTER SUBSCRIPTION ... DROP PUBLICATION</literal> to
     remove one of the offending publications and add it again.
2.d) The
   transaction that produced the conflict can be skipped by using
   <command>ALTER SUBSCRIPTION ... SKIP</command> with the finish LSN
   (i.e., LSN 0/14C0378).
2.e)    Before using this function, the subscription needs to be
disabled temporarily
   either by <command>ALTER SUBSCRIPTION ... DISABLE</command> or,

Regards,
Vignesh






^ permalink  raw  reply  [nested|flat] 10+ messages in thread

* Re: PGDOCS - add more links in the pub/sub reference pages
@ 2023-10-10 12:33  Amit Kapila <[email protected]>
  parent: vignesh C <[email protected]>
  0 siblings, 0 replies; 10+ messages in thread

From: Amit Kapila @ 2023-10-10 12:33 UTC (permalink / raw)
  To: vignesh C <[email protected]>; +Cc: Peter Smith <[email protected]>; PostgreSQL Hackers <[email protected]>

On Tue, Oct 10, 2023 at 11:40 AM vignesh C <[email protected]> wrote:
>
> On Tue, 10 Oct 2023 at 08:47, Peter Smith <[email protected]> wrote:
> > PSA v3.
>
> Few more instances in other logical replication related pages:
> 1) Another instance was in alter_subscription.sgml:
>       Fetch missing table information from publisher.  This will start
>       replication of tables that were added to the subscribed-to publications
>       since <command>CREATE SUBSCRIPTION</command> or
>       the last invocation of <command>REFRESH PUBLICATION</command>.
>

Do we want each and every occurrence of the commands to have
corresponding links? I am not against it if we think that is useful
for users but asking as I am not aware of the general practice we
follow in this regard. Does anyone else have any opinion on this
matter?

-- 
With Regards,
Amit Kapila.






^ permalink  raw  reply  [nested|flat] 10+ messages in thread

* Re: PGDOCS - add more links in the pub/sub reference pages
@ 2023-10-12 04:44  Amit Kapila <[email protected]>
  parent: Peter Smith <[email protected]>
  1 sibling, 1 reply; 10+ messages in thread

From: Amit Kapila @ 2023-10-12 04:44 UTC (permalink / raw)
  To: Peter Smith <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>

On Mon, Oct 9, 2023 at 12:15 PM Peter Smith <[email protected]> wrote:
>
> On Mon, Oct 9, 2023 at 3:32 PM Amit Kapila <[email protected]> wrote:
> >
>
> In v1, I used the same pattern as on the CREATE SUBSCRIPTION page,
> which doesn't look like those...
>

Yeah, I think it would have been better if we used params in the
CREATE SUBSCRIPTION page as well. I don't know if it is a good idea to
do now with this patch but it makes sense to be consistent. What do
you think?

> ~~~
>
> The "Parameters" section describes some things that really are parameters:
>
> e.g.
> "sql-altersubscription-name"
> "sql-altersubscription-new-owner"
> "sql-altersubscription-new-name">
>
> I agree, emphasising that those ones are parameters is better. Changed
> like this in v2.
>
> "sql-altersubscription-params-name"
> "sql-altersubscription-params-new-owner"
> "sql-altersubscription-params-new-name">
>
> ~
>
> But, the "Parameters" section also describes other SQL syntax clauses
> which are not really parameters at all.
>
> e.g.
> "sql-altersubscription-refresh-publication"
> "sql-altersubscription-enable"
> "sql-altersubscription-disable"
>
> So I felt those ones are more intuitive left as they are  -- e.g.,
> instead of having ids/linkends like:
>
> "sql-altersubscription-params-refresh-publication"
> "sql-altersubscription-params-enable"
> "sql-altersubscription-params-disable"
>

I checked alter_role.sgml which has similar mixed usage and it is
using 'params' consistently in all cases. So, I would suggest
following a similar style here.

-- 
With Regards,
Amit Kapila.






^ permalink  raw  reply  [nested|flat] 10+ messages in thread

* Re: PGDOCS - add more links in the pub/sub reference pages
@ 2023-10-13 03:32  Peter Smith <[email protected]>
  parent: Amit Kapila <[email protected]>
  0 siblings, 1 reply; 10+ messages in thread

From: Peter Smith @ 2023-10-13 03:32 UTC (permalink / raw)
  To: Amit Kapila <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>

On Thu, Oct 12, 2023 at 3:44 PM Amit Kapila <[email protected]> wrote:
>
> On Mon, Oct 9, 2023 at 12:15 PM Peter Smith <[email protected]> wrote:
> >
> > On Mon, Oct 9, 2023 at 3:32 PM Amit Kapila <[email protected]> wrote:
> > >
> >
> > In v1, I used the same pattern as on the CREATE SUBSCRIPTION page,
> > which doesn't look like those...
> >
>
> Yeah, I think it would have been better if we used params in the
> CREATE SUBSCRIPTION page as well. I don't know if it is a good idea to
> do now with this patch but it makes sense to be consistent. What do
> you think?
>

OK, I have given those changes as separate patches:
- 0002 (changes the CREATE PUBLICATION parameter ids)
- 0003 (changes CREATE SUBSCRIPTION parameter ids)

> > ~~~
> >
> > The "Parameters" section describes some things that really are parameters:
> >
> > e.g.
> > "sql-altersubscription-name"
> > "sql-altersubscription-new-owner"
> > "sql-altersubscription-new-name">
> >
> > I agree, emphasising that those ones are parameters is better. Changed
> > like this in v2.
> >
> > "sql-altersubscription-params-name"
> > "sql-altersubscription-params-new-owner"
> > "sql-altersubscription-params-new-name">
> >
> > ~
> >
> > But, the "Parameters" section also describes other SQL syntax clauses
> > which are not really parameters at all.
> >
> > e.g.
> > "sql-altersubscription-refresh-publication"
> > "sql-altersubscription-enable"
> > "sql-altersubscription-disable"
> >
> > So I felt those ones are more intuitive left as they are  -- e.g.,
> > instead of having ids/linkends like:
> >
> > "sql-altersubscription-params-refresh-publication"
> > "sql-altersubscription-params-enable"
> > "sql-altersubscription-params-disable"
> >
>
> I checked alter_role.sgml which has similar mixed usage and it is
> using 'params' consistently in all cases. So, I would suggest
> following a similar style here.
>

As you wish. Done that way in patch 0001.

~~

PSA the v5 patches.

======
Kind Regards,
Peter Smith.
Fujitsu Australia


Attachments:

  [application/octet-stream] v5-0001-Add-more-pub-sub-links.patch (11.2K, ../../CAHut+PsbcZ2=uTvHXEKxRR0xOKt1qs0ExqepCZPVhz6aVqMd1A@mail.gmail.com/2-v5-0001-Add-more-pub-sub-links.patch)
  download | inline diff:
From c872b4180991e238f239d95f73c2b1d95b82ffeb Mon Sep 17 00:00:00 2001
From: Peter Smith <[email protected]>
Date: Fri, 13 Oct 2023 13:46:46 +1100
Subject: [PATCH v5] Add more pub/sub links.

The pub/sub PG DOCS pages almost always have links to other pub/sub commands
whenever they are mentioned, but there were some omissions. This patch adds the
missing links.

In passing, add more pub/sub command links from other logical replication pages.

Author: Peter Smith
Reviewed-by: Vignesh C, Amit Kapila
Discussion: https://www.postgresql.org/message-id/flat/CAHut%2BPu2S4RdzYKR7H5_E7QYWyq5hB0hL4EFrYbP91Qso62jeg%40mail.gmail.com
---
---
 doc/src/sgml/logical-replication.sgml    | 20 +++++++++++++-------
 doc/src/sgml/ref/alter_publication.sgml  |  3 ++-
 doc/src/sgml/ref/alter_subscription.sgml | 23 ++++++++++++-----------
 doc/src/sgml/ref/drop_subscription.sgml  |  8 +++++---
 4 files changed, 32 insertions(+), 22 deletions(-)

diff --git a/doc/src/sgml/logical-replication.sgml b/doc/src/sgml/logical-replication.sgml
index 3b2fa11..8c3837e 100644
--- a/doc/src/sgml/logical-replication.sgml
+++ b/doc/src/sgml/logical-replication.sgml
@@ -274,9 +274,11 @@
    </para>
    <para>
     Normally, the remote replication slot is created automatically when the
-    subscription is created using <command>CREATE SUBSCRIPTION</command> and it
+    subscription is created using <link linkend="sql-createsubscription">
+    <command>CREATE SUBSCRIPTION</command></link> and it
     is dropped automatically when the subscription is dropped using
-    <command>DROP SUBSCRIPTION</command>.  In some situations, however, it can
+    <link linkend="sql-dropsubscription"><command>DROP SUBSCRIPTION</command></link>.
+    In some situations, however, it can
     be useful or necessary to manipulate the subscription and the underlying
     replication slot separately.  Here are some scenarios:
 
@@ -306,8 +308,9 @@
        When dropping a subscription, the replication slot should be kept.
        This could be useful when the subscriber database is being moved to a
        different host and will be activated from there.  In that case,
-       disassociate the slot from the subscription using <command>ALTER
-       SUBSCRIPTION</command> before attempting to drop the subscription.
+       disassociate the slot from the subscription using
+       <link linkend="sql-altersubscription"><command>ALTER SUBSCRIPTION</command></link>
+       before attempting to drop the subscription.
       </para>
      </listitem>
 
@@ -1349,7 +1352,8 @@ test_sub=# SELECT * FROM child ORDER BY a;
      If a subscription is affected by this problem, the only way to resume
      replication is to adjust one of the column lists on the publication
      side so that they all match; and then either recreate the subscription,
-     or use <literal>ALTER SUBSCRIPTION ... DROP PUBLICATION</literal> to
+     or use <link linkend="sql-altersubscription-params-setadddrop-publication">
+     <literal>ALTER SUBSCRIPTION ... DROP PUBLICATION</literal></link> to
      remove one of the offending publications and add it again.
     </para>
    </warning>
@@ -1504,13 +1508,15 @@ CONTEXT:  processing remote data for replication origin "pg_16395" during "INSER
    the replication origin name can be found from the server log (LSN 0/14C0378 and
    replication origin <literal>pg_16395</literal> in the above case).  The
    transaction that produced the conflict can be skipped by using
-   <command>ALTER SUBSCRIPTION ... SKIP</command> with the finish LSN
+   <link linkend="sql-altersubscription-params-skip"><command>ALTER SUBSCRIPTION ... SKIP</command></link>
+   with the finish LSN
    (i.e., LSN 0/14C0378).  The finish LSN could be an LSN at which the transaction
    is committed or prepared on the publisher.  Alternatively, the transaction can
    also be skipped by calling the <link linkend="pg-replication-origin-advance">
    <function>pg_replication_origin_advance()</function></link> function.
    Before using this function, the subscription needs to be disabled temporarily
-   either by <command>ALTER SUBSCRIPTION ... DISABLE</command> or, the
+   either by <link linkend="sql-altersubscription-params-disable">
+   <command>ALTER SUBSCRIPTION ... DISABLE</command></link> or, the
    subscription can be used with the
    <link linkend="sql-createsubscription-with-disable-on-error"><literal>disable_on_error</literal></link>
    option. Then, you can use <function>pg_replication_origin_advance()</function>
diff --git a/doc/src/sgml/ref/alter_publication.sgml b/doc/src/sgml/ref/alter_publication.sgml
index c8424bc..74fda82 100644
--- a/doc/src/sgml/ref/alter_publication.sgml
+++ b/doc/src/sgml/ref/alter_publication.sgml
@@ -51,7 +51,8 @@ ALTER PUBLICATION <replaceable class="parameter">name</replaceable> RENAME TO <r
    <literal>ADD</literal> and <literal>DROP</literal> clauses will add and
    remove one or more tables/schemas from the publication.  Note that adding
    tables/schemas to a publication that is already subscribed to will require an
-   <literal>ALTER SUBSCRIPTION ... REFRESH PUBLICATION</literal> action on the
+   <link linkend="sql-altersubscription-params-refresh-publication">
+   <literal>ALTER SUBSCRIPTION ... REFRESH PUBLICATION</literal></link> action on the
    subscribing side in order to become effective. Note also that
    <literal>DROP TABLES IN SCHEMA</literal> will not drop any schema tables
    that were specified using
diff --git a/doc/src/sgml/ref/alter_subscription.sgml b/doc/src/sgml/ref/alter_subscription.sgml
index a85e04e..ba70855 100644
--- a/doc/src/sgml/ref/alter_subscription.sgml
+++ b/doc/src/sgml/ref/alter_subscription.sgml
@@ -85,7 +85,7 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
   <title>Parameters</title>
 
   <variablelist>
-   <varlistentry>
+   <varlistentry id="sql-altersubscription-params-name">
     <term><replaceable class="parameter">name</replaceable></term>
     <listitem>
      <para>
@@ -94,7 +94,7 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
     </listitem>
    </varlistentry>
 
-   <varlistentry>
+   <varlistentry id="sql-altersubscription-params-connection">
     <term><literal>CONNECTION '<replaceable class="parameter">conninfo</replaceable>'</literal></term>
     <listitem>
      <para>
@@ -105,7 +105,7 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
     </listitem>
    </varlistentry>
 
-   <varlistentry>
+   <varlistentry id="sql-altersubscription-params-setadddrop-publication">
     <term><literal>SET PUBLICATION <replaceable class="parameter">publication_name</replaceable></literal></term>
     <term><literal>ADD PUBLICATION <replaceable class="parameter">publication_name</replaceable></literal></term>
     <term><literal>DROP PUBLICATION <replaceable class="parameter">publication_name</replaceable></literal></term>
@@ -147,13 +147,14 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
     </listitem>
    </varlistentry>
 
-   <varlistentry>
+   <varlistentry id="sql-altersubscription-params-refresh-publication">
     <term><literal>REFRESH PUBLICATION</literal></term>
     <listitem>
      <para>
       Fetch missing table information from publisher.  This will start
       replication of tables that were added to the subscribed-to publications
-      since <command>CREATE SUBSCRIPTION</command> or
+      since <link linkend="sql-createsubscription">
+      <command>CREATE SUBSCRIPTION</command></link> or
       the last invocation of <command>REFRESH PUBLICATION</command>.
      </para>
 
@@ -192,7 +193,7 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
     </listitem>
    </varlistentry>
 
-   <varlistentry>
+   <varlistentry id="sql-altersubscription-params-enable">
     <term><literal>ENABLE</literal></term>
     <listitem>
      <para>
@@ -202,7 +203,7 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
     </listitem>
    </varlistentry>
 
-   <varlistentry>
+   <varlistentry id="sql-altersubscription-params-disable">
     <term><literal>DISABLE</literal></term>
     <listitem>
      <para>
@@ -212,7 +213,7 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
     </listitem>
    </varlistentry>
 
-   <varlistentry>
+   <varlistentry id="sql-altersubscription-params-set">
     <term><literal>SET ( <replaceable class="parameter">subscription_parameter</replaceable> [= <replaceable class="parameter">value</replaceable>] [, ... ] )</literal></term>
     <listitem>
      <para>
@@ -232,7 +233,7 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
     </listitem>
    </varlistentry>
 
-   <varlistentry>
+   <varlistentry id="sql-altersubscription-params-skip">
     <term><literal>SKIP ( <replaceable class="parameter">skip_option</replaceable> = <replaceable class="parameter">value</replaceable> )</literal></term>
     <listitem>
      <para>
@@ -272,7 +273,7 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
     </listitem>
    </varlistentry>
 
-   <varlistentry>
+   <varlistentry id="sql-altersubscription-params-new-owner">
     <term><replaceable class="parameter">new_owner</replaceable></term>
     <listitem>
      <para>
@@ -281,7 +282,7 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
     </listitem>
    </varlistentry>
 
-   <varlistentry>
+   <varlistentry id="sql-altersubscription-params-new-name">
     <term><replaceable class="parameter">new_name</replaceable></term>
     <listitem>
      <para>
diff --git a/doc/src/sgml/ref/drop_subscription.sgml b/doc/src/sgml/ref/drop_subscription.sgml
index 2a67bde..d4f54c7 100644
--- a/doc/src/sgml/ref/drop_subscription.sgml
+++ b/doc/src/sgml/ref/drop_subscription.sgml
@@ -40,7 +40,7 @@ DROP SUBSCRIPTION [ IF EXISTS ] <replaceable class="parameter">name</replaceable
   <para>
    <command>DROP SUBSCRIPTION</command> cannot be executed inside a
    transaction block if the subscription is associated with a replication
-   slot.  (You can use <command>ALTER SUBSCRIPTION</command> to unset the
+   slot.  (You can use <link linkend="sql-altersubscription"><command>ALTER SUBSCRIPTION</command></link> to unset the
    slot.)
   </para>
  </refsect1>
@@ -87,9 +87,11 @@ DROP SUBSCRIPTION [ IF EXISTS ] <replaceable class="parameter">name</replaceable
    replication slot cannot be dropped or does not exist or never existed,
    the <command>DROP SUBSCRIPTION</command> command will fail.  To proceed
    in this situation, first disable the subscription by executing
-   <literal>ALTER SUBSCRIPTION ... DISABLE</literal>, and then disassociate
+   <link linkend="sql-altersubscription-params-disable">
+   <literal>ALTER SUBSCRIPTION ... DISABLE</literal></link>, and then disassociate
    it from the replication slot by executing
-   <literal>ALTER SUBSCRIPTION ... SET (slot_name = NONE)</literal>.
+   <link linkend="sql-altersubscription-params-set">
+   <literal>ALTER SUBSCRIPTION ... SET (slot_name = NONE)</literal></link>.
    After that, <command>DROP SUBSCRIPTION</command> will no longer attempt any
    actions on a remote host.  Note that if the remote replication slot still
    exists, it (and any related table synchronization slots) should then be
-- 
1.8.3.1



  [application/octet-stream] v5-0002-Change-ids-for-CREATE-PUBLICATION-parameters.patch (13.6K, ../../CAHut+PsbcZ2=uTvHXEKxRR0xOKt1qs0ExqepCZPVhz6aVqMd1A@mail.gmail.com/3-v5-0002-Change-ids-for-CREATE-PUBLICATION-parameters.patch)
  download | inline diff:
From bba5fca096d9e4a164311a4a7f731062c95a54b1 Mon Sep 17 00:00:00 2001
From: Peter Smith <[email protected]>
Date: Fri, 13 Oct 2023 14:06:10 +1100
Subject: [PATCH v5] Change ids for CREATE PUBLICATION parameters

---
 doc/src/sgml/logical-replication.sgml     | 22 +++++++++++-----------
 doc/src/sgml/ref/alter_publication.sgml   |  6 +++---
 doc/src/sgml/ref/create_publication.sgml  | 14 +++++++-------
 doc/src/sgml/ref/create_subscription.sgml |  6 +++---
 doc/src/sgml/system-views.sgml            |  4 ++--
 5 files changed, 26 insertions(+), 26 deletions(-)

diff --git a/doc/src/sgml/logical-replication.sgml b/doc/src/sgml/logical-replication.sgml
index 8c3837e..9f0f059 100644
--- a/doc/src/sgml/logical-replication.sgml
+++ b/doc/src/sgml/logical-replication.sgml
@@ -371,7 +371,7 @@ INSERT 0 3
     <para>
      Create publications for the tables. The publications <literal>pub2</literal>
      and <literal>pub3a</literal> disallow some
-     <link linkend="sql-createpublication-with-publish"><literal>publish</literal></link>
+     <link linkend="sql-createpublication-params-with-publish"><literal>publish</literal></link>
      operations. The publication <literal>pub3b</literal> has a row filter (see
      <xref linkend="logical-replication-row-filter"/>).
 <programlisting>
@@ -805,7 +805,7 @@ ALTER SUBSCRIPTION
 
    <para>
     If the publication contains a partitioned table, the publication parameter
-    <link linkend="sql-createpublication-with-publish-via-partition-root"><literal>publish_via_partition_root</literal></link>
+    <link linkend="sql-createpublication-params-with-publish-via-partition-root"><literal>publish_via_partition_root</literal></link>
     determines which row filter is used. If <literal>publish_via_partition_root</literal>
     is <literal>true</literal>, the <emphasis>root partitioned table's</emphasis>
     row filter is used. Otherwise, if <literal>publish_via_partition_root</literal>
@@ -834,7 +834,7 @@ ALTER SUBSCRIPTION
    <warning>
     <para>
      Because initial data synchronization does not take into account the
-     <link linkend="sql-createpublication-with-publish"><literal>publish</literal></link>
+     <link linkend="sql-createpublication-params-with-publish"><literal>publish</literal></link>
      parameter when copying existing table data, some rows may be copied that
      would not be replicated using DML. Refer to
      <xref linkend="logical-replication-snapshot"/>, and see
@@ -858,7 +858,7 @@ ALTER SUBSCRIPTION
    <para>
     If the subscription has several publications in which the same table has
     been published with different row filters (for the same
-    <link linkend="sql-createpublication-with-publish"><literal>publish</literal></link>
+    <link linkend="sql-createpublication-params-with-publish"><literal>publish</literal></link>
     operation), those expressions get ORed together, so that rows satisfying
     <emphasis>any</emphasis> of the expressions will be replicated. This means all
     the other row filters for the same table become redundant if:
@@ -871,14 +871,14 @@ ALTER SUBSCRIPTION
      <listitem>
       <para>
        One of the publications was created using
-       <link linkend="sql-createpublication-for-all-tables"><literal>FOR ALL TABLES</literal></link>.
+       <link linkend="sql-createpublication-params-for-all-tables"><literal>FOR ALL TABLES</literal></link>.
        This clause does not allow row filters.
       </para>
      </listitem>
      <listitem>
       <para>
        One of the publications was created using
-       <link linkend="sql-createpublication-for-tables-in-schema"><literal>FOR TABLES IN SCHEMA</literal></link>
+       <link linkend="sql-createpublication-params-for-tables-in-schema"><literal>FOR TABLES IN SCHEMA</literal></link>
        and the table belongs to the referred schema. This clause does not allow
        row filters.
       </para>
@@ -1145,7 +1145,7 @@ test_sub=# SELECT * FROM t1;
 
    <para>
     The following examples show how the publication parameter
-    <link linkend="sql-createpublication-with-publish-via-partition-root"><literal>publish_via_partition_root</literal></link>
+    <link linkend="sql-createpublication-params-with-publish-via-partition-root"><literal>publish_via_partition_root</literal></link>
     determines whether the row filter of the parent or child table will be used
     in the case of partitioned tables.
    </para>
@@ -1300,13 +1300,13 @@ test_sub=# SELECT * FROM child ORDER BY a;
 
   <para>
    Specifying a column list when the publication also publishes
-   <link linkend="sql-createpublication-for-tables-in-schema"><literal>FOR TABLES IN SCHEMA</literal></link>
+   <link linkend="sql-createpublication-params-for-tables-in-schema"><literal>FOR TABLES IN SCHEMA</literal></link>
    is not supported.
   </para>
 
   <para>
    For partitioned tables, the publication parameter
-   <link linkend="sql-createpublication-with-publish-via-partition-root"><literal>publish_via_partition_root</literal></link>
+   <link linkend="sql-createpublication-params-with-publish-via-partition-root"><literal>publish_via_partition_root</literal></link>
    determines which column list is used. If <literal>publish_via_partition_root</literal>
    is <literal>true</literal>, the root partitioned table's column list is
    used. Otherwise, if <literal>publish_via_partition_root</literal> is
@@ -1624,7 +1624,7 @@ CONTEXT:  processing remote data for replication origin "pg_16395" during "INSER
      using the identity and schema of the partitioned root table instead of
      that of the individual leaf partitions in which the changes actually
      originate (see
-     <link linkend="sql-createpublication-with-publish-via-partition-root"><literal>publish_via_partition_root</literal></link>
+     <link linkend="sql-createpublication-params-with-publish-via-partition-root"><literal>publish_via_partition_root</literal></link>
      parameter of <command>CREATE PUBLICATION</command>).
     </para>
    </listitem>
@@ -1709,7 +1709,7 @@ CONTEXT:  processing remote data for replication origin "pg_16395" during "INSER
     <note>
      <para>
       The publication
-      <link linkend="sql-createpublication-with-publish"><literal>publish</literal></link>
+      <link linkend="sql-createpublication-params-with-publish"><literal>publish</literal></link>
       parameter only affects what DML operations will be replicated. The
       initial data synchronization does not take this parameter into account
       when copying the existing table data.
diff --git a/doc/src/sgml/ref/alter_publication.sgml b/doc/src/sgml/ref/alter_publication.sgml
index 74fda82..44ae7e0 100644
--- a/doc/src/sgml/ref/alter_publication.sgml
+++ b/doc/src/sgml/ref/alter_publication.sgml
@@ -56,7 +56,7 @@ ALTER PUBLICATION <replaceable class="parameter">name</replaceable> RENAME TO <r
    subscribing side in order to become effective. Note also that
    <literal>DROP TABLES IN SCHEMA</literal> will not drop any schema tables
    that were specified using
-   <link linkend="sql-createpublication-for-table"><literal>FOR TABLE</literal></link>/
+   <link linkend="sql-createpublication-params-for-table"><literal>FOR TABLE</literal></link>/
    <literal>ADD TABLE</literal>, and the combination of <literal>DROP</literal>
    with a <literal>WHERE</literal> clause is not allowed.
   </para>
@@ -82,8 +82,8 @@ ALTER PUBLICATION <replaceable class="parameter">name</replaceable> RENAME TO <r
    new owning role, and that role must have <literal>CREATE</literal>
    privilege on the database.
    Also, the new owner of a
-   <link linkend="sql-createpublication-for-all-tables"><literal>FOR ALL TABLES</literal></link>
-   or <link linkend="sql-createpublication-for-tables-in-schema"><literal>FOR TABLES IN SCHEMA</literal></link>
+   <link linkend="sql-createpublication-params-for-all-tables"><literal>FOR ALL TABLES</literal></link>
+   or <link linkend="sql-createpublication-params-for-tables-in-schema"><literal>FOR TABLES IN SCHEMA</literal></link>
    publication must be a superuser. However, a superuser can
    change the ownership of a publication regardless of these restrictions.
   </para>
diff --git a/doc/src/sgml/ref/create_publication.sgml b/doc/src/sgml/ref/create_publication.sgml
index 606aa64..fd9c5de 100644
--- a/doc/src/sgml/ref/create_publication.sgml
+++ b/doc/src/sgml/ref/create_publication.sgml
@@ -54,7 +54,7 @@ CREATE PUBLICATION <replaceable class="parameter">name</replaceable>
   <title>Parameters</title>
 
   <variablelist>
-   <varlistentry id="sql-createpublication-name">
+   <varlistentry id="sql-createpublication-params-name">
     <term><replaceable class="parameter">name</replaceable></term>
     <listitem>
      <para>
@@ -63,7 +63,7 @@ CREATE PUBLICATION <replaceable class="parameter">name</replaceable>
     </listitem>
    </varlistentry>
 
-   <varlistentry id="sql-createpublication-for-table">
+   <varlistentry id="sql-createpublication-params-for-table">
     <term><literal>FOR TABLE</literal></term>
     <listitem>
      <para>
@@ -117,7 +117,7 @@ CREATE PUBLICATION <replaceable class="parameter">name</replaceable>
     </listitem>
    </varlistentry>
 
-   <varlistentry id="sql-createpublication-for-all-tables">
+   <varlistentry id="sql-createpublication-params-for-all-tables">
     <term><literal>FOR ALL TABLES</literal></term>
     <listitem>
      <para>
@@ -127,7 +127,7 @@ CREATE PUBLICATION <replaceable class="parameter">name</replaceable>
     </listitem>
    </varlistentry>
 
-   <varlistentry id="sql-createpublication-for-tables-in-schema">
+   <varlistentry id="sql-createpublication-params-for-tables-in-schema">
     <term><literal>FOR TABLES IN SCHEMA</literal></term>
     <listitem>
      <para>
@@ -158,7 +158,7 @@ CREATE PUBLICATION <replaceable class="parameter">name</replaceable>
     </listitem>
    </varlistentry>
 
-   <varlistentry id="sql-createpublication-with">
+   <varlistentry id="sql-createpublication-params-with">
     <term><literal>WITH ( <replaceable class="parameter">publication_parameter</replaceable> [= <replaceable class="parameter">value</replaceable>] [, ... ] )</literal></term>
     <listitem>
      <para>
@@ -166,7 +166,7 @@ CREATE PUBLICATION <replaceable class="parameter">name</replaceable>
       following parameters are supported:
 
       <variablelist>
-       <varlistentry id="sql-createpublication-with-publish">
+       <varlistentry id="sql-createpublication-params-with-publish">
         <term><literal>publish</literal> (<type>string</type>)</term>
         <listitem>
          <para>
@@ -188,7 +188,7 @@ CREATE PUBLICATION <replaceable class="parameter">name</replaceable>
         </listitem>
        </varlistentry>
 
-       <varlistentry id="sql-createpublication-with-publish-via-partition-root">
+       <varlistentry id="sql-createpublication-params-with-publish-via-partition-root">
         <term><literal>publish_via_partition_root</literal> (<type>boolean</type>)</term>
         <listitem>
          <para>
diff --git a/doc/src/sgml/ref/create_subscription.sgml b/doc/src/sgml/ref/create_subscription.sgml
index c1bafbf..db11ebc 100644
--- a/doc/src/sgml/ref/create_subscription.sgml
+++ b/doc/src/sgml/ref/create_subscription.sgml
@@ -452,8 +452,8 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
    the case of different <literal>WHERE</literal> clauses, if one of the
    publications has no <literal>WHERE</literal> clause (referring to that
    publish operation) or the publication is declared as
-   <link linkend="sql-createpublication-for-all-tables"><literal>FOR ALL TABLES</literal></link>
-   or <link linkend="sql-createpublication-for-tables-in-schema"><literal>FOR TABLES IN SCHEMA</literal></link>,
+   <link linkend="sql-createpublication-params-for-all-tables"><literal>FOR ALL TABLES</literal></link>
+   or <link linkend="sql-createpublication-params-for-tables-in-schema"><literal>FOR TABLES IN SCHEMA</literal></link>,
    rows are always published regardless of the definition of the other
    expressions. If the subscriber is a <productname>PostgreSQL</productname>
    version before 15, then any row filtering is ignored during the initial data
@@ -461,7 +461,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
    deleting any initially copied data that would be incompatible with
    subsequent filtering. Because initial data synchronization does not take
    into account the publication
-   <link linkend="sql-createpublication-with-publish"><literal>publish</literal></link>
+   <link linkend="sql-createpublication-params-with-publish"><literal>publish</literal></link>
    parameter when copying existing table data, some rows may be copied that
    would not be replicated using DML. See
    <xref linkend="logical-replication-subscription-examples"/> for examples.
diff --git a/doc/src/sgml/system-views.sgml b/doc/src/sgml/system-views.sgml
index 2b35c2f..fc7329e 100644
--- a/doc/src/sgml/system-views.sgml
+++ b/doc/src/sgml/system-views.sgml
@@ -2151,8 +2151,8 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx
    tables they contain.  Unlike the underlying catalog
    <link linkend="catalog-pg-publication-rel"><structname>pg_publication_rel</structname></link>,
    this view expands publications defined as
-   <link linkend="sql-createpublication-for-all-tables"><literal>FOR ALL TABLES</literal></link>
-   and <link linkend="sql-createpublication-for-tables-in-schema"><literal>FOR TABLES IN SCHEMA</literal></link>,
+   <link linkend="sql-createpublication-params-for-all-tables"><literal>FOR ALL TABLES</literal></link>
+   and <link linkend="sql-createpublication-params-for-tables-in-schema"><literal>FOR TABLES IN SCHEMA</literal></link>,
    so for such publications there will be a row for each eligible table.
   </para>
 
-- 
1.8.3.1



  [application/octet-stream] v5-0003-Change-ids-for-CREATE-SUBSCRIPTION-parameters.patch (17.2K, ../../CAHut+PsbcZ2=uTvHXEKxRR0xOKt1qs0ExqepCZPVhz6aVqMd1A@mail.gmail.com/4-v5-0003-Change-ids-for-CREATE-SUBSCRIPTION-parameters.patch)
  download | inline diff:
From bd05985c8fc35d33bb264c090ddece44f6928749 Mon Sep 17 00:00:00 2001
From: Peter Smith <[email protected]>
Date: Fri, 13 Oct 2023 14:23:19 +1100
Subject: [PATCH v5] Change ids for CREATE SUBSCRIPTION parameters

---
 doc/src/sgml/config.sgml                  |  2 +-
 doc/src/sgml/logical-replication.sgml     | 12 +++++------
 doc/src/sgml/ref/alter_subscription.sgml  | 26 +++++++++++------------
 doc/src/sgml/ref/create_subscription.sgml | 34 +++++++++++++++----------------
 doc/src/sgml/ref/pg_dump.sgml             |  2 +-
 5 files changed, 38 insertions(+), 38 deletions(-)

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 3839c72..d244390 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -11686,7 +11686,7 @@ LOG:  CleanUpLock: deleting: lock(0xb7acd844) id(24688,24696,0,0,0,1)
         On the publisher side, <varname>debug_logical_replication_streaming</varname>
         allows streaming or serializing changes immediately in logical decoding.
         When set to <literal>immediate</literal>, stream each change if the
-        <link linkend="sql-createsubscription-with-streaming"><literal>streaming</literal></link>
+        <link linkend="sql-createsubscription-params-with-streaming"><literal>streaming</literal></link>
         option of
         <link linkend="sql-createsubscription"><command>CREATE SUBSCRIPTION</command></link>
         is enabled, otherwise, serialize each change.  When set to
diff --git a/doc/src/sgml/logical-replication.sgml b/doc/src/sgml/logical-replication.sgml
index 9f0f059..1bb85e4 100644
--- a/doc/src/sgml/logical-replication.sgml
+++ b/doc/src/sgml/logical-replication.sgml
@@ -253,7 +253,7 @@
    will be filled with the default value as specified in the definition of the
    target table. However, logical replication in binary format is more
    restrictive. See the
-   <link linkend="sql-createsubscription-with-binary"><literal>binary</literal></link>
+   <link linkend="sql-createsubscription-params-with-binary"><literal>binary</literal></link>
    option of <command>CREATE SUBSCRIPTION</command> for details.
   </para>
 
@@ -593,7 +593,7 @@ ALTER SUBSCRIPTION
    <para>
     Example 2: Where the subscription says <literal>connect = false</literal>,
     but also specifies the
-    <link linkend="sql-createsubscription-with-slot-name"><literal>slot_name</literal></link>
+    <link linkend="sql-createsubscription-params-with-slot-name"><literal>slot_name</literal></link>
     option.
     <itemizedlist>
      <listitem>
@@ -712,7 +712,7 @@ ALTER SUBSCRIPTION
     then the row is not replicated. The <literal>WHERE</literal> clause expression
     is evaluated with the same role used for the replication connection (i.e.
     the role specified in the
-    <link linkend="sql-createsubscription-connection"><literal>CONNECTION</literal></link>
+    <link linkend="sql-createsubscription-params-connection"><literal>CONNECTION</literal></link>
     clause of the <xref linkend="sql-createsubscription"/>). Row filters have
     no effect for <command>TRUNCATE</command> command.
    </para>
@@ -1518,7 +1518,7 @@ CONTEXT:  processing remote data for replication origin "pg_16395" during "INSER
    either by <link linkend="sql-altersubscription-params-disable">
    <command>ALTER SUBSCRIPTION ... DISABLE</command></link> or, the
    subscription can be used with the
-   <link linkend="sql-createsubscription-with-disable-on-error"><literal>disable_on_error</literal></link>
+   <link linkend="sql-createsubscription-params-with-disable-on-error"><literal>disable_on_error</literal></link>
    option. Then, you can use <function>pg_replication_origin_advance()</function>
    function with the <parameter>node_name</parameter> (i.e., <literal>pg_16395</literal>)
    and the next LSN of the finish LSN (i.e., 0/14C0379).  The current position of
@@ -1531,7 +1531,7 @@ CONTEXT:  processing remote data for replication origin "pg_16395" during "INSER
 
   <para>
    When the
-   <link linkend="sql-createsubscription-with-streaming"><literal>streaming</literal></link>
+   <link linkend="sql-createsubscription-params-with-streaming"><literal>streaming</literal></link>
    mode is <literal>parallel</literal>, the finish LSN of failed transactions
    may not be logged. In that case, it may be necessary to change the streaming
    mode to <literal>on</literal> or <literal>off</literal> and cause the same
@@ -1743,7 +1743,7 @@ CONTEXT:  processing remote data for replication origin "pg_16395" during "INSER
    zero rows in this view.  If the initial data synchronization of any
    table is in progress, there will be additional workers for the tables
    being synchronized. Moreover, if the
-   <link linkend="sql-createsubscription-with-streaming"><literal>streaming</literal></link>
+   <link linkend="sql-createsubscription-params-with-streaming"><literal>streaming</literal></link>
    transaction is applied in parallel, there may be additional parallel apply
    workers.
   </para>
diff --git a/doc/src/sgml/ref/alter_subscription.sgml b/doc/src/sgml/ref/alter_subscription.sgml
index ba70855..6d36ff0 100644
--- a/doc/src/sgml/ref/alter_subscription.sgml
+++ b/doc/src/sgml/ref/alter_subscription.sgml
@@ -72,9 +72,9 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
    executed inside a transaction block.
 
    These commands also cannot be executed when the subscription has
-   <link linkend="sql-createsubscription-with-two-phase"><literal>two_phase</literal></link>
+   <link linkend="sql-createsubscription-params-with-two-phase"><literal>two_phase</literal></link>
    commit enabled, unless
-   <link linkend="sql-createsubscription-with-copy-data"><literal>copy_data</literal></link>
+   <link linkend="sql-createsubscription-params-with-copy-data"><literal>copy_data</literal></link>
    is <literal>false</literal>. See column <structfield>subtwophasestate</structfield>
    of <link linkend="catalog-pg-subscription"><structname>pg_subscription</structname></link>
    to know the actual two-phase state.
@@ -178,12 +178,12 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
          <para>
           See <xref linkend="sql-createsubscription-notes"/> for details of
           how <literal>copy_data = true</literal> can interact with the
-          <link linkend="sql-createsubscription-with-origin"><literal>origin</literal></link>
+          <link linkend="sql-createsubscription-params-with-origin"><literal>origin</literal></link>
           parameter.
          </para>
          <para>
           See the
-          <link linkend="sql-createsubscription-with-binary"><literal>binary</literal></link>
+          <link linkend="sql-createsubscription-params-with-binary"><literal>binary</literal></link>
           parameter of <command>CREATE SUBSCRIPTION</command> for details about
           copying pre-existing data in binary format.
          </para>
@@ -220,14 +220,14 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
       This clause alters parameters originally set by
       <xref linkend="sql-createsubscription"/>.  See there for more
       information.  The parameters that can be altered are
-      <link linkend="sql-createsubscription-with-slot-name"><literal>slot_name</literal></link>,
-      <link linkend="sql-createsubscription-with-synchronous-commit"><literal>synchronous_commit</literal></link>,
-      <link linkend="sql-createsubscription-with-binary"><literal>binary</literal></link>,
-      <link linkend="sql-createsubscription-with-streaming"><literal>streaming</literal></link>,
-      <link linkend="sql-createsubscription-with-disable-on-error"><literal>disable_on_error</literal></link>,
-      <link linkend="sql-createsubscription-with-password-required"><literal>password_required</literal></link>,
-      <link linkend="sql-createsubscription-with-run-as-owner"><literal>run_as_owner</literal></link>, and
-      <link linkend="sql-createsubscription-with-origin"><literal>origin</literal></link>.
+      <link linkend="sql-createsubscription-params-with-slot-name"><literal>slot_name</literal></link>,
+      <link linkend="sql-createsubscription-params-with-synchronous-commit"><literal>synchronous_commit</literal></link>,
+      <link linkend="sql-createsubscription-params-with-binary"><literal>binary</literal></link>,
+      <link linkend="sql-createsubscription-params-with-streaming"><literal>streaming</literal></link>,
+      <link linkend="sql-createsubscription-params-with-disable-on-error"><literal>disable_on_error</literal></link>,
+      <link linkend="sql-createsubscription-params-with-password-required"><literal>password_required</literal></link>,
+      <link linkend="sql-createsubscription-params-with-run-as-owner"><literal>run_as_owner</literal></link>, and
+      <link linkend="sql-createsubscription-params-with-origin"><literal>origin</literal></link>.
       Only a superuser can set <literal>password_required = false</literal>.
      </para>
     </listitem>
@@ -243,7 +243,7 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
       the logical replication worker skips all data modification changes within
       the transaction.  This option has no effect on the transactions that are
       already prepared by enabling
-      <link linkend="sql-createsubscription-with-two-phase"><literal>two_phase</literal></link>
+      <link linkend="sql-createsubscription-params-with-two-phase"><literal>two_phase</literal></link>
       on the subscriber.
       After the logical replication worker successfully skips the transaction or
       finishes a transaction, the LSN (stored in
diff --git a/doc/src/sgml/ref/create_subscription.sgml b/doc/src/sgml/ref/create_subscription.sgml
index db11ebc..f1c20b3 100644
--- a/doc/src/sgml/ref/create_subscription.sgml
+++ b/doc/src/sgml/ref/create_subscription.sgml
@@ -68,7 +68,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
   <title>Parameters</title>
 
   <variablelist>
-   <varlistentry id="sql-createsubscription-name">
+   <varlistentry id="sql-createsubscription-params-name">
     <term><replaceable class="parameter">subscription_name</replaceable></term>
     <listitem>
      <para>
@@ -77,7 +77,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
     </listitem>
    </varlistentry>
 
-   <varlistentry id="sql-createsubscription-connection">
+   <varlistentry id="sql-createsubscription-params-connection">
     <term><literal>CONNECTION '<replaceable class="parameter">conninfo</replaceable>'</literal></term>
     <listitem>
      <para>
@@ -88,7 +88,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
     </listitem>
    </varlistentry>
 
-   <varlistentry id="sql-createsubscription-publication">
+   <varlistentry id="sql-createsubscription-params-publication">
     <term><literal>PUBLICATION <replaceable class="parameter">publication_name</replaceable> [, ...]</literal></term>
     <listitem>
      <para>
@@ -97,7 +97,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
     </listitem>
    </varlistentry>
 
-   <varlistentry id="sql-createsubscription-with">
+   <varlistentry id="sql-createsubscription-params-with">
     <term><literal>WITH ( <replaceable class="parameter">subscription_parameter</replaceable> [= <replaceable class="parameter">value</replaceable>] [, ... ] )</literal></term>
     <listitem>
      <para>
@@ -109,7 +109,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
 
       <variablelist>
 
-       <varlistentry id="sql-createsubscription-with-connect">
+       <varlistentry id="sql-createsubscription-params-with-connect">
         <term><literal>connect</literal> (<type>boolean</type>)</term>
         <listitem>
          <para>
@@ -136,7 +136,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
         </listitem>
        </varlistentry>
 
-       <varlistentry id="sql-createsubscription-with-create-slot">
+       <varlistentry id="sql-createsubscription-params-with-create-slot">
         <term><literal>create_slot</literal> (<type>boolean</type>)</term>
         <listitem>
          <para>
@@ -152,7 +152,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
         </listitem>
        </varlistentry>
 
-       <varlistentry id="sql-createsubscription-with-enabled">
+       <varlistentry id="sql-createsubscription-params-with-enabled">
         <term><literal>enabled</literal> (<type>boolean</type>)</term>
         <listitem>
          <para>
@@ -163,7 +163,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
         </listitem>
        </varlistentry>
 
-       <varlistentry id="sql-createsubscription-with-slot-name">
+       <varlistentry id="sql-createsubscription-params-with-slot-name">
         <term><literal>slot_name</literal> (<type>string</type>)</term>
         <listitem>
          <para>
@@ -192,7 +192,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
 
       <variablelist>
 
-       <varlistentry id="sql-createsubscription-with-binary">
+       <varlistentry id="sql-createsubscription-params-with-binary">
         <term><literal>binary</literal> (<type>boolean</type>)</term>
         <listitem>
          <para>
@@ -229,7 +229,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
         </listitem>
        </varlistentry>
 
-       <varlistentry id="sql-createsubscription-with-copy-data">
+       <varlistentry id="sql-createsubscription-params-with-copy-data">
         <term><literal>copy_data</literal> (<type>boolean</type>)</term>
         <listitem>
          <para>
@@ -250,7 +250,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
         </listitem>
        </varlistentry>
 
-       <varlistentry id="sql-createsubscription-with-streaming">
+       <varlistentry id="sql-createsubscription-params-with-streaming">
         <term><literal>streaming</literal> (<type>enum</type>)</term>
         <listitem>
          <para>
@@ -278,7 +278,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
         </listitem>
        </varlistentry>
 
-       <varlistentry id="sql-createsubscription-with-synchronous-commit">
+       <varlistentry id="sql-createsubscription-params-with-synchronous-commit">
         <term><literal>synchronous_commit</literal> (<type>enum</type>)</term>
         <listitem>
          <para>
@@ -310,7 +310,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
         </listitem>
        </varlistentry>
 
-       <varlistentry id="sql-createsubscription-with-two-phase">
+       <varlistentry id="sql-createsubscription-params-with-two-phase">
         <term><literal>two_phase</literal> (<type>boolean</type>)</term>
         <listitem>
          <para>
@@ -341,7 +341,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
         </listitem>
        </varlistentry>
 
-       <varlistentry id="sql-createsubscription-with-disable-on-error">
+       <varlistentry id="sql-createsubscription-params-with-disable-on-error">
         <term><literal>disable_on_error</literal> (<type>boolean</type>)</term>
         <listitem>
          <para>
@@ -353,7 +353,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
         </listitem>
        </varlistentry>
 
-       <varlistentry id="sql-createsubscription-with-password-required">
+       <varlistentry id="sql-createsubscription-params-with-password-required">
         <term><literal>password_required</literal> (<type>boolean</type>)</term>
         <listitem>
          <para>
@@ -366,7 +366,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
         </listitem>
        </varlistentry>
 
-       <varlistentry id="sql-createsubscription-with-run-as-owner">
+       <varlistentry id="sql-createsubscription-params-with-run-as-owner">
         <term><literal>run_as_owner</literal> (<type>boolean</type>)</term>
         <listitem>
          <para>
@@ -380,7 +380,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
         </listitem>
        </varlistentry>
 
-       <varlistentry id="sql-createsubscription-with-origin">
+       <varlistentry id="sql-createsubscription-params-with-origin">
         <term><literal>origin</literal> (<type>string</type>)</term>
         <listitem>
          <para>
diff --git a/doc/src/sgml/ref/pg_dump.sgml b/doc/src/sgml/ref/pg_dump.sgml
index 1417d70..8695571 100644
--- a/doc/src/sgml/ref/pg_dump.sgml
+++ b/doc/src/sgml/ref/pg_dump.sgml
@@ -1488,7 +1488,7 @@ CREATE DATABASE foo WITH TEMPLATE template0;
    truncate the target tables before initiating a new full table copy.  If users
    intend to copy initial data during refresh they must create the slot with
    <literal>two_phase = false</literal>.  After the initial sync, the
-   <link linkend="sql-createsubscription-with-two-phase"><literal>two_phase</literal></link>
+   <link linkend="sql-createsubscription-params-with-two-phase"><literal>two_phase</literal></link>
    option will be automatically enabled by the subscriber if the subscription
    had been originally created with <literal>two_phase = true</literal> option.
   </para>
-- 
1.8.3.1



^ permalink  raw  reply  [nested|flat] 10+ messages in thread

* Re: PGDOCS - add more links in the pub/sub reference pages
@ 2023-10-16 00:45  Peter Smith <[email protected]>
  parent: Peter Smith <[email protected]>
  0 siblings, 1 reply; 10+ messages in thread

From: Peter Smith @ 2023-10-16 00:45 UTC (permalink / raw)
  To: Amit Kapila <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>

Thanks for pushing the 0001 patch! I am unsure what the decision was
for the remaining patches, but anyway, here they are again (rebased).

======
Kind Regards,
Peter Smith.
Fujitsu Australia


Attachments:

  [application/octet-stream] v6-0002-Change-ids-for-CREATE-SUBSCRIPTION-parameters.patch (17.2K, ../../CAHut+PvF8NTFfEnkX_MxWBrjYTa9mNNSm6Yg5CqXKgPSUqXVPA@mail.gmail.com/2-v6-0002-Change-ids-for-CREATE-SUBSCRIPTION-parameters.patch)
  download | inline diff:
From 6da9c88c971f9d37efeb569afbf83528baeaf398 Mon Sep 17 00:00:00 2001
From: Peter Smith <[email protected]>
Date: Fri, 13 Oct 2023 14:23:19 +1100
Subject: [PATCH v6] Change ids for CREATE SUBSCRIPTION parameters

---
 doc/src/sgml/config.sgml                  |  2 +-
 doc/src/sgml/logical-replication.sgml     | 12 +++++------
 doc/src/sgml/ref/alter_subscription.sgml  | 26 +++++++++++------------
 doc/src/sgml/ref/create_subscription.sgml | 34 +++++++++++++++----------------
 doc/src/sgml/ref/pg_dump.sgml             |  2 +-
 5 files changed, 38 insertions(+), 38 deletions(-)

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 3839c72..d244390 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -11686,7 +11686,7 @@ LOG:  CleanUpLock: deleting: lock(0xb7acd844) id(24688,24696,0,0,0,1)
         On the publisher side, <varname>debug_logical_replication_streaming</varname>
         allows streaming or serializing changes immediately in logical decoding.
         When set to <literal>immediate</literal>, stream each change if the
-        <link linkend="sql-createsubscription-with-streaming"><literal>streaming</literal></link>
+        <link linkend="sql-createsubscription-params-with-streaming"><literal>streaming</literal></link>
         option of
         <link linkend="sql-createsubscription"><command>CREATE SUBSCRIPTION</command></link>
         is enabled, otherwise, serialize each change.  When set to
diff --git a/doc/src/sgml/logical-replication.sgml b/doc/src/sgml/logical-replication.sgml
index 9f0f059..1bb85e4 100644
--- a/doc/src/sgml/logical-replication.sgml
+++ b/doc/src/sgml/logical-replication.sgml
@@ -253,7 +253,7 @@
    will be filled with the default value as specified in the definition of the
    target table. However, logical replication in binary format is more
    restrictive. See the
-   <link linkend="sql-createsubscription-with-binary"><literal>binary</literal></link>
+   <link linkend="sql-createsubscription-params-with-binary"><literal>binary</literal></link>
    option of <command>CREATE SUBSCRIPTION</command> for details.
   </para>
 
@@ -593,7 +593,7 @@ ALTER SUBSCRIPTION
    <para>
     Example 2: Where the subscription says <literal>connect = false</literal>,
     but also specifies the
-    <link linkend="sql-createsubscription-with-slot-name"><literal>slot_name</literal></link>
+    <link linkend="sql-createsubscription-params-with-slot-name"><literal>slot_name</literal></link>
     option.
     <itemizedlist>
      <listitem>
@@ -712,7 +712,7 @@ ALTER SUBSCRIPTION
     then the row is not replicated. The <literal>WHERE</literal> clause expression
     is evaluated with the same role used for the replication connection (i.e.
     the role specified in the
-    <link linkend="sql-createsubscription-connection"><literal>CONNECTION</literal></link>
+    <link linkend="sql-createsubscription-params-connection"><literal>CONNECTION</literal></link>
     clause of the <xref linkend="sql-createsubscription"/>). Row filters have
     no effect for <command>TRUNCATE</command> command.
    </para>
@@ -1518,7 +1518,7 @@ CONTEXT:  processing remote data for replication origin "pg_16395" during "INSER
    either by <link linkend="sql-altersubscription-params-disable">
    <command>ALTER SUBSCRIPTION ... DISABLE</command></link> or, the
    subscription can be used with the
-   <link linkend="sql-createsubscription-with-disable-on-error"><literal>disable_on_error</literal></link>
+   <link linkend="sql-createsubscription-params-with-disable-on-error"><literal>disable_on_error</literal></link>
    option. Then, you can use <function>pg_replication_origin_advance()</function>
    function with the <parameter>node_name</parameter> (i.e., <literal>pg_16395</literal>)
    and the next LSN of the finish LSN (i.e., 0/14C0379).  The current position of
@@ -1531,7 +1531,7 @@ CONTEXT:  processing remote data for replication origin "pg_16395" during "INSER
 
   <para>
    When the
-   <link linkend="sql-createsubscription-with-streaming"><literal>streaming</literal></link>
+   <link linkend="sql-createsubscription-params-with-streaming"><literal>streaming</literal></link>
    mode is <literal>parallel</literal>, the finish LSN of failed transactions
    may not be logged. In that case, it may be necessary to change the streaming
    mode to <literal>on</literal> or <literal>off</literal> and cause the same
@@ -1743,7 +1743,7 @@ CONTEXT:  processing remote data for replication origin "pg_16395" during "INSER
    zero rows in this view.  If the initial data synchronization of any
    table is in progress, there will be additional workers for the tables
    being synchronized. Moreover, if the
-   <link linkend="sql-createsubscription-with-streaming"><literal>streaming</literal></link>
+   <link linkend="sql-createsubscription-params-with-streaming"><literal>streaming</literal></link>
    transaction is applied in parallel, there may be additional parallel apply
    workers.
   </para>
diff --git a/doc/src/sgml/ref/alter_subscription.sgml b/doc/src/sgml/ref/alter_subscription.sgml
index ba70855..6d36ff0 100644
--- a/doc/src/sgml/ref/alter_subscription.sgml
+++ b/doc/src/sgml/ref/alter_subscription.sgml
@@ -72,9 +72,9 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
    executed inside a transaction block.
 
    These commands also cannot be executed when the subscription has
-   <link linkend="sql-createsubscription-with-two-phase"><literal>two_phase</literal></link>
+   <link linkend="sql-createsubscription-params-with-two-phase"><literal>two_phase</literal></link>
    commit enabled, unless
-   <link linkend="sql-createsubscription-with-copy-data"><literal>copy_data</literal></link>
+   <link linkend="sql-createsubscription-params-with-copy-data"><literal>copy_data</literal></link>
    is <literal>false</literal>. See column <structfield>subtwophasestate</structfield>
    of <link linkend="catalog-pg-subscription"><structname>pg_subscription</structname></link>
    to know the actual two-phase state.
@@ -178,12 +178,12 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
          <para>
           See <xref linkend="sql-createsubscription-notes"/> for details of
           how <literal>copy_data = true</literal> can interact with the
-          <link linkend="sql-createsubscription-with-origin"><literal>origin</literal></link>
+          <link linkend="sql-createsubscription-params-with-origin"><literal>origin</literal></link>
           parameter.
          </para>
          <para>
           See the
-          <link linkend="sql-createsubscription-with-binary"><literal>binary</literal></link>
+          <link linkend="sql-createsubscription-params-with-binary"><literal>binary</literal></link>
           parameter of <command>CREATE SUBSCRIPTION</command> for details about
           copying pre-existing data in binary format.
          </para>
@@ -220,14 +220,14 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
       This clause alters parameters originally set by
       <xref linkend="sql-createsubscription"/>.  See there for more
       information.  The parameters that can be altered are
-      <link linkend="sql-createsubscription-with-slot-name"><literal>slot_name</literal></link>,
-      <link linkend="sql-createsubscription-with-synchronous-commit"><literal>synchronous_commit</literal></link>,
-      <link linkend="sql-createsubscription-with-binary"><literal>binary</literal></link>,
-      <link linkend="sql-createsubscription-with-streaming"><literal>streaming</literal></link>,
-      <link linkend="sql-createsubscription-with-disable-on-error"><literal>disable_on_error</literal></link>,
-      <link linkend="sql-createsubscription-with-password-required"><literal>password_required</literal></link>,
-      <link linkend="sql-createsubscription-with-run-as-owner"><literal>run_as_owner</literal></link>, and
-      <link linkend="sql-createsubscription-with-origin"><literal>origin</literal></link>.
+      <link linkend="sql-createsubscription-params-with-slot-name"><literal>slot_name</literal></link>,
+      <link linkend="sql-createsubscription-params-with-synchronous-commit"><literal>synchronous_commit</literal></link>,
+      <link linkend="sql-createsubscription-params-with-binary"><literal>binary</literal></link>,
+      <link linkend="sql-createsubscription-params-with-streaming"><literal>streaming</literal></link>,
+      <link linkend="sql-createsubscription-params-with-disable-on-error"><literal>disable_on_error</literal></link>,
+      <link linkend="sql-createsubscription-params-with-password-required"><literal>password_required</literal></link>,
+      <link linkend="sql-createsubscription-params-with-run-as-owner"><literal>run_as_owner</literal></link>, and
+      <link linkend="sql-createsubscription-params-with-origin"><literal>origin</literal></link>.
       Only a superuser can set <literal>password_required = false</literal>.
      </para>
     </listitem>
@@ -243,7 +243,7 @@ ALTER SUBSCRIPTION <replaceable class="parameter">name</replaceable> RENAME TO <
       the logical replication worker skips all data modification changes within
       the transaction.  This option has no effect on the transactions that are
       already prepared by enabling
-      <link linkend="sql-createsubscription-with-two-phase"><literal>two_phase</literal></link>
+      <link linkend="sql-createsubscription-params-with-two-phase"><literal>two_phase</literal></link>
       on the subscriber.
       After the logical replication worker successfully skips the transaction or
       finishes a transaction, the LSN (stored in
diff --git a/doc/src/sgml/ref/create_subscription.sgml b/doc/src/sgml/ref/create_subscription.sgml
index db11ebc..f1c20b3 100644
--- a/doc/src/sgml/ref/create_subscription.sgml
+++ b/doc/src/sgml/ref/create_subscription.sgml
@@ -68,7 +68,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
   <title>Parameters</title>
 
   <variablelist>
-   <varlistentry id="sql-createsubscription-name">
+   <varlistentry id="sql-createsubscription-params-name">
     <term><replaceable class="parameter">subscription_name</replaceable></term>
     <listitem>
      <para>
@@ -77,7 +77,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
     </listitem>
    </varlistentry>
 
-   <varlistentry id="sql-createsubscription-connection">
+   <varlistentry id="sql-createsubscription-params-connection">
     <term><literal>CONNECTION '<replaceable class="parameter">conninfo</replaceable>'</literal></term>
     <listitem>
      <para>
@@ -88,7 +88,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
     </listitem>
    </varlistentry>
 
-   <varlistentry id="sql-createsubscription-publication">
+   <varlistentry id="sql-createsubscription-params-publication">
     <term><literal>PUBLICATION <replaceable class="parameter">publication_name</replaceable> [, ...]</literal></term>
     <listitem>
      <para>
@@ -97,7 +97,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
     </listitem>
    </varlistentry>
 
-   <varlistentry id="sql-createsubscription-with">
+   <varlistentry id="sql-createsubscription-params-with">
     <term><literal>WITH ( <replaceable class="parameter">subscription_parameter</replaceable> [= <replaceable class="parameter">value</replaceable>] [, ... ] )</literal></term>
     <listitem>
      <para>
@@ -109,7 +109,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
 
       <variablelist>
 
-       <varlistentry id="sql-createsubscription-with-connect">
+       <varlistentry id="sql-createsubscription-params-with-connect">
         <term><literal>connect</literal> (<type>boolean</type>)</term>
         <listitem>
          <para>
@@ -136,7 +136,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
         </listitem>
        </varlistentry>
 
-       <varlistentry id="sql-createsubscription-with-create-slot">
+       <varlistentry id="sql-createsubscription-params-with-create-slot">
         <term><literal>create_slot</literal> (<type>boolean</type>)</term>
         <listitem>
          <para>
@@ -152,7 +152,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
         </listitem>
        </varlistentry>
 
-       <varlistentry id="sql-createsubscription-with-enabled">
+       <varlistentry id="sql-createsubscription-params-with-enabled">
         <term><literal>enabled</literal> (<type>boolean</type>)</term>
         <listitem>
          <para>
@@ -163,7 +163,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
         </listitem>
        </varlistentry>
 
-       <varlistentry id="sql-createsubscription-with-slot-name">
+       <varlistentry id="sql-createsubscription-params-with-slot-name">
         <term><literal>slot_name</literal> (<type>string</type>)</term>
         <listitem>
          <para>
@@ -192,7 +192,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
 
       <variablelist>
 
-       <varlistentry id="sql-createsubscription-with-binary">
+       <varlistentry id="sql-createsubscription-params-with-binary">
         <term><literal>binary</literal> (<type>boolean</type>)</term>
         <listitem>
          <para>
@@ -229,7 +229,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
         </listitem>
        </varlistentry>
 
-       <varlistentry id="sql-createsubscription-with-copy-data">
+       <varlistentry id="sql-createsubscription-params-with-copy-data">
         <term><literal>copy_data</literal> (<type>boolean</type>)</term>
         <listitem>
          <para>
@@ -250,7 +250,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
         </listitem>
        </varlistentry>
 
-       <varlistentry id="sql-createsubscription-with-streaming">
+       <varlistentry id="sql-createsubscription-params-with-streaming">
         <term><literal>streaming</literal> (<type>enum</type>)</term>
         <listitem>
          <para>
@@ -278,7 +278,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
         </listitem>
        </varlistentry>
 
-       <varlistentry id="sql-createsubscription-with-synchronous-commit">
+       <varlistentry id="sql-createsubscription-params-with-synchronous-commit">
         <term><literal>synchronous_commit</literal> (<type>enum</type>)</term>
         <listitem>
          <para>
@@ -310,7 +310,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
         </listitem>
        </varlistentry>
 
-       <varlistentry id="sql-createsubscription-with-two-phase">
+       <varlistentry id="sql-createsubscription-params-with-two-phase">
         <term><literal>two_phase</literal> (<type>boolean</type>)</term>
         <listitem>
          <para>
@@ -341,7 +341,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
         </listitem>
        </varlistentry>
 
-       <varlistentry id="sql-createsubscription-with-disable-on-error">
+       <varlistentry id="sql-createsubscription-params-with-disable-on-error">
         <term><literal>disable_on_error</literal> (<type>boolean</type>)</term>
         <listitem>
          <para>
@@ -353,7 +353,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
         </listitem>
        </varlistentry>
 
-       <varlistentry id="sql-createsubscription-with-password-required">
+       <varlistentry id="sql-createsubscription-params-with-password-required">
         <term><literal>password_required</literal> (<type>boolean</type>)</term>
         <listitem>
          <para>
@@ -366,7 +366,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
         </listitem>
        </varlistentry>
 
-       <varlistentry id="sql-createsubscription-with-run-as-owner">
+       <varlistentry id="sql-createsubscription-params-with-run-as-owner">
         <term><literal>run_as_owner</literal> (<type>boolean</type>)</term>
         <listitem>
          <para>
@@ -380,7 +380,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
         </listitem>
        </varlistentry>
 
-       <varlistentry id="sql-createsubscription-with-origin">
+       <varlistentry id="sql-createsubscription-params-with-origin">
         <term><literal>origin</literal> (<type>string</type>)</term>
         <listitem>
          <para>
diff --git a/doc/src/sgml/ref/pg_dump.sgml b/doc/src/sgml/ref/pg_dump.sgml
index 1417d70..8695571 100644
--- a/doc/src/sgml/ref/pg_dump.sgml
+++ b/doc/src/sgml/ref/pg_dump.sgml
@@ -1488,7 +1488,7 @@ CREATE DATABASE foo WITH TEMPLATE template0;
    truncate the target tables before initiating a new full table copy.  If users
    intend to copy initial data during refresh they must create the slot with
    <literal>two_phase = false</literal>.  After the initial sync, the
-   <link linkend="sql-createsubscription-with-two-phase"><literal>two_phase</literal></link>
+   <link linkend="sql-createsubscription-params-with-two-phase"><literal>two_phase</literal></link>
    option will be automatically enabled by the subscriber if the subscription
    had been originally created with <literal>two_phase = true</literal> option.
   </para>
-- 
1.8.3.1



  [application/octet-stream] v6-0001-Change-ids-for-CREATE-PUBLICATION-parameters.patch (13.6K, ../../CAHut+PvF8NTFfEnkX_MxWBrjYTa9mNNSm6Yg5CqXKgPSUqXVPA@mail.gmail.com/3-v6-0001-Change-ids-for-CREATE-PUBLICATION-parameters.patch)
  download | inline diff:
From e45e080f91a83942781f520d5ea2f448b16380dc Mon Sep 17 00:00:00 2001
From: Peter Smith <[email protected]>
Date: Fri, 13 Oct 2023 14:06:10 +1100
Subject: [PATCH v6] Change ids for CREATE PUBLICATION parameters

---
 doc/src/sgml/logical-replication.sgml     | 22 +++++++++++-----------
 doc/src/sgml/ref/alter_publication.sgml   |  6 +++---
 doc/src/sgml/ref/create_publication.sgml  | 14 +++++++-------
 doc/src/sgml/ref/create_subscription.sgml |  6 +++---
 doc/src/sgml/system-views.sgml            |  4 ++--
 5 files changed, 26 insertions(+), 26 deletions(-)

diff --git a/doc/src/sgml/logical-replication.sgml b/doc/src/sgml/logical-replication.sgml
index 8c3837e..9f0f059 100644
--- a/doc/src/sgml/logical-replication.sgml
+++ b/doc/src/sgml/logical-replication.sgml
@@ -371,7 +371,7 @@ INSERT 0 3
     <para>
      Create publications for the tables. The publications <literal>pub2</literal>
      and <literal>pub3a</literal> disallow some
-     <link linkend="sql-createpublication-with-publish"><literal>publish</literal></link>
+     <link linkend="sql-createpublication-params-with-publish"><literal>publish</literal></link>
      operations. The publication <literal>pub3b</literal> has a row filter (see
      <xref linkend="logical-replication-row-filter"/>).
 <programlisting>
@@ -805,7 +805,7 @@ ALTER SUBSCRIPTION
 
    <para>
     If the publication contains a partitioned table, the publication parameter
-    <link linkend="sql-createpublication-with-publish-via-partition-root"><literal>publish_via_partition_root</literal></link>
+    <link linkend="sql-createpublication-params-with-publish-via-partition-root"><literal>publish_via_partition_root</literal></link>
     determines which row filter is used. If <literal>publish_via_partition_root</literal>
     is <literal>true</literal>, the <emphasis>root partitioned table's</emphasis>
     row filter is used. Otherwise, if <literal>publish_via_partition_root</literal>
@@ -834,7 +834,7 @@ ALTER SUBSCRIPTION
    <warning>
     <para>
      Because initial data synchronization does not take into account the
-     <link linkend="sql-createpublication-with-publish"><literal>publish</literal></link>
+     <link linkend="sql-createpublication-params-with-publish"><literal>publish</literal></link>
      parameter when copying existing table data, some rows may be copied that
      would not be replicated using DML. Refer to
      <xref linkend="logical-replication-snapshot"/>, and see
@@ -858,7 +858,7 @@ ALTER SUBSCRIPTION
    <para>
     If the subscription has several publications in which the same table has
     been published with different row filters (for the same
-    <link linkend="sql-createpublication-with-publish"><literal>publish</literal></link>
+    <link linkend="sql-createpublication-params-with-publish"><literal>publish</literal></link>
     operation), those expressions get ORed together, so that rows satisfying
     <emphasis>any</emphasis> of the expressions will be replicated. This means all
     the other row filters for the same table become redundant if:
@@ -871,14 +871,14 @@ ALTER SUBSCRIPTION
      <listitem>
       <para>
        One of the publications was created using
-       <link linkend="sql-createpublication-for-all-tables"><literal>FOR ALL TABLES</literal></link>.
+       <link linkend="sql-createpublication-params-for-all-tables"><literal>FOR ALL TABLES</literal></link>.
        This clause does not allow row filters.
       </para>
      </listitem>
      <listitem>
       <para>
        One of the publications was created using
-       <link linkend="sql-createpublication-for-tables-in-schema"><literal>FOR TABLES IN SCHEMA</literal></link>
+       <link linkend="sql-createpublication-params-for-tables-in-schema"><literal>FOR TABLES IN SCHEMA</literal></link>
        and the table belongs to the referred schema. This clause does not allow
        row filters.
       </para>
@@ -1145,7 +1145,7 @@ test_sub=# SELECT * FROM t1;
 
    <para>
     The following examples show how the publication parameter
-    <link linkend="sql-createpublication-with-publish-via-partition-root"><literal>publish_via_partition_root</literal></link>
+    <link linkend="sql-createpublication-params-with-publish-via-partition-root"><literal>publish_via_partition_root</literal></link>
     determines whether the row filter of the parent or child table will be used
     in the case of partitioned tables.
    </para>
@@ -1300,13 +1300,13 @@ test_sub=# SELECT * FROM child ORDER BY a;
 
   <para>
    Specifying a column list when the publication also publishes
-   <link linkend="sql-createpublication-for-tables-in-schema"><literal>FOR TABLES IN SCHEMA</literal></link>
+   <link linkend="sql-createpublication-params-for-tables-in-schema"><literal>FOR TABLES IN SCHEMA</literal></link>
    is not supported.
   </para>
 
   <para>
    For partitioned tables, the publication parameter
-   <link linkend="sql-createpublication-with-publish-via-partition-root"><literal>publish_via_partition_root</literal></link>
+   <link linkend="sql-createpublication-params-with-publish-via-partition-root"><literal>publish_via_partition_root</literal></link>
    determines which column list is used. If <literal>publish_via_partition_root</literal>
    is <literal>true</literal>, the root partitioned table's column list is
    used. Otherwise, if <literal>publish_via_partition_root</literal> is
@@ -1624,7 +1624,7 @@ CONTEXT:  processing remote data for replication origin "pg_16395" during "INSER
      using the identity and schema of the partitioned root table instead of
      that of the individual leaf partitions in which the changes actually
      originate (see
-     <link linkend="sql-createpublication-with-publish-via-partition-root"><literal>publish_via_partition_root</literal></link>
+     <link linkend="sql-createpublication-params-with-publish-via-partition-root"><literal>publish_via_partition_root</literal></link>
      parameter of <command>CREATE PUBLICATION</command>).
     </para>
    </listitem>
@@ -1709,7 +1709,7 @@ CONTEXT:  processing remote data for replication origin "pg_16395" during "INSER
     <note>
      <para>
       The publication
-      <link linkend="sql-createpublication-with-publish"><literal>publish</literal></link>
+      <link linkend="sql-createpublication-params-with-publish"><literal>publish</literal></link>
       parameter only affects what DML operations will be replicated. The
       initial data synchronization does not take this parameter into account
       when copying the existing table data.
diff --git a/doc/src/sgml/ref/alter_publication.sgml b/doc/src/sgml/ref/alter_publication.sgml
index 74fda82..44ae7e0 100644
--- a/doc/src/sgml/ref/alter_publication.sgml
+++ b/doc/src/sgml/ref/alter_publication.sgml
@@ -56,7 +56,7 @@ ALTER PUBLICATION <replaceable class="parameter">name</replaceable> RENAME TO <r
    subscribing side in order to become effective. Note also that
    <literal>DROP TABLES IN SCHEMA</literal> will not drop any schema tables
    that were specified using
-   <link linkend="sql-createpublication-for-table"><literal>FOR TABLE</literal></link>/
+   <link linkend="sql-createpublication-params-for-table"><literal>FOR TABLE</literal></link>/
    <literal>ADD TABLE</literal>, and the combination of <literal>DROP</literal>
    with a <literal>WHERE</literal> clause is not allowed.
   </para>
@@ -82,8 +82,8 @@ ALTER PUBLICATION <replaceable class="parameter">name</replaceable> RENAME TO <r
    new owning role, and that role must have <literal>CREATE</literal>
    privilege on the database.
    Also, the new owner of a
-   <link linkend="sql-createpublication-for-all-tables"><literal>FOR ALL TABLES</literal></link>
-   or <link linkend="sql-createpublication-for-tables-in-schema"><literal>FOR TABLES IN SCHEMA</literal></link>
+   <link linkend="sql-createpublication-params-for-all-tables"><literal>FOR ALL TABLES</literal></link>
+   or <link linkend="sql-createpublication-params-for-tables-in-schema"><literal>FOR TABLES IN SCHEMA</literal></link>
    publication must be a superuser. However, a superuser can
    change the ownership of a publication regardless of these restrictions.
   </para>
diff --git a/doc/src/sgml/ref/create_publication.sgml b/doc/src/sgml/ref/create_publication.sgml
index 606aa64..fd9c5de 100644
--- a/doc/src/sgml/ref/create_publication.sgml
+++ b/doc/src/sgml/ref/create_publication.sgml
@@ -54,7 +54,7 @@ CREATE PUBLICATION <replaceable class="parameter">name</replaceable>
   <title>Parameters</title>
 
   <variablelist>
-   <varlistentry id="sql-createpublication-name">
+   <varlistentry id="sql-createpublication-params-name">
     <term><replaceable class="parameter">name</replaceable></term>
     <listitem>
      <para>
@@ -63,7 +63,7 @@ CREATE PUBLICATION <replaceable class="parameter">name</replaceable>
     </listitem>
    </varlistentry>
 
-   <varlistentry id="sql-createpublication-for-table">
+   <varlistentry id="sql-createpublication-params-for-table">
     <term><literal>FOR TABLE</literal></term>
     <listitem>
      <para>
@@ -117,7 +117,7 @@ CREATE PUBLICATION <replaceable class="parameter">name</replaceable>
     </listitem>
    </varlistentry>
 
-   <varlistentry id="sql-createpublication-for-all-tables">
+   <varlistentry id="sql-createpublication-params-for-all-tables">
     <term><literal>FOR ALL TABLES</literal></term>
     <listitem>
      <para>
@@ -127,7 +127,7 @@ CREATE PUBLICATION <replaceable class="parameter">name</replaceable>
     </listitem>
    </varlistentry>
 
-   <varlistentry id="sql-createpublication-for-tables-in-schema">
+   <varlistentry id="sql-createpublication-params-for-tables-in-schema">
     <term><literal>FOR TABLES IN SCHEMA</literal></term>
     <listitem>
      <para>
@@ -158,7 +158,7 @@ CREATE PUBLICATION <replaceable class="parameter">name</replaceable>
     </listitem>
    </varlistentry>
 
-   <varlistentry id="sql-createpublication-with">
+   <varlistentry id="sql-createpublication-params-with">
     <term><literal>WITH ( <replaceable class="parameter">publication_parameter</replaceable> [= <replaceable class="parameter">value</replaceable>] [, ... ] )</literal></term>
     <listitem>
      <para>
@@ -166,7 +166,7 @@ CREATE PUBLICATION <replaceable class="parameter">name</replaceable>
       following parameters are supported:
 
       <variablelist>
-       <varlistentry id="sql-createpublication-with-publish">
+       <varlistentry id="sql-createpublication-params-with-publish">
         <term><literal>publish</literal> (<type>string</type>)</term>
         <listitem>
          <para>
@@ -188,7 +188,7 @@ CREATE PUBLICATION <replaceable class="parameter">name</replaceable>
         </listitem>
        </varlistentry>
 
-       <varlistentry id="sql-createpublication-with-publish-via-partition-root">
+       <varlistentry id="sql-createpublication-params-with-publish-via-partition-root">
         <term><literal>publish_via_partition_root</literal> (<type>boolean</type>)</term>
         <listitem>
          <para>
diff --git a/doc/src/sgml/ref/create_subscription.sgml b/doc/src/sgml/ref/create_subscription.sgml
index c1bafbf..db11ebc 100644
--- a/doc/src/sgml/ref/create_subscription.sgml
+++ b/doc/src/sgml/ref/create_subscription.sgml
@@ -452,8 +452,8 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
    the case of different <literal>WHERE</literal> clauses, if one of the
    publications has no <literal>WHERE</literal> clause (referring to that
    publish operation) or the publication is declared as
-   <link linkend="sql-createpublication-for-all-tables"><literal>FOR ALL TABLES</literal></link>
-   or <link linkend="sql-createpublication-for-tables-in-schema"><literal>FOR TABLES IN SCHEMA</literal></link>,
+   <link linkend="sql-createpublication-params-for-all-tables"><literal>FOR ALL TABLES</literal></link>
+   or <link linkend="sql-createpublication-params-for-tables-in-schema"><literal>FOR TABLES IN SCHEMA</literal></link>,
    rows are always published regardless of the definition of the other
    expressions. If the subscriber is a <productname>PostgreSQL</productname>
    version before 15, then any row filtering is ignored during the initial data
@@ -461,7 +461,7 @@ CREATE SUBSCRIPTION <replaceable class="parameter">subscription_name</replaceabl
    deleting any initially copied data that would be incompatible with
    subsequent filtering. Because initial data synchronization does not take
    into account the publication
-   <link linkend="sql-createpublication-with-publish"><literal>publish</literal></link>
+   <link linkend="sql-createpublication-params-with-publish"><literal>publish</literal></link>
    parameter when copying existing table data, some rows may be copied that
    would not be replicated using DML. See
    <xref linkend="logical-replication-subscription-examples"/> for examples.
diff --git a/doc/src/sgml/system-views.sgml b/doc/src/sgml/system-views.sgml
index 2b35c2f..fc7329e 100644
--- a/doc/src/sgml/system-views.sgml
+++ b/doc/src/sgml/system-views.sgml
@@ -2151,8 +2151,8 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx
    tables they contain.  Unlike the underlying catalog
    <link linkend="catalog-pg-publication-rel"><structname>pg_publication_rel</structname></link>,
    this view expands publications defined as
-   <link linkend="sql-createpublication-for-all-tables"><literal>FOR ALL TABLES</literal></link>
-   and <link linkend="sql-createpublication-for-tables-in-schema"><literal>FOR TABLES IN SCHEMA</literal></link>,
+   <link linkend="sql-createpublication-params-for-all-tables"><literal>FOR ALL TABLES</literal></link>
+   and <link linkend="sql-createpublication-params-for-tables-in-schema"><literal>FOR TABLES IN SCHEMA</literal></link>,
    so for such publications there will be a row for each eligible table.
   </para>
 
-- 
1.8.3.1



^ permalink  raw  reply  [nested|flat] 10+ messages in thread

* Re: PGDOCS - add more links in the pub/sub reference pages
@ 2023-10-30 09:15  Amit Kapila <[email protected]>
  parent: Peter Smith <[email protected]>
  0 siblings, 0 replies; 10+ messages in thread

From: Amit Kapila @ 2023-10-30 09:15 UTC (permalink / raw)
  To: Peter Smith <[email protected]>; +Cc: PostgreSQL Hackers <[email protected]>

On Mon, Oct 16, 2023 at 6:15 AM Peter Smith <[email protected]> wrote:
>
> Thanks for pushing the 0001 patch! I am unsure what the decision was
> for the remaining patches, but anyway, here they are again (rebased).
>

To keep the link names the same in logical replication-related
commands, I have pushed your patch.

-- 
With Regards,
Amit Kapila.






^ permalink  raw  reply  [nested|flat] 10+ messages in thread


end of thread, other threads:[~2023-10-30 09:15 UTC | newest]

Thread overview: 10+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2020-12-16 15:26 [PATCH v5 2/2] Make resowners more easily extensible. Heikki Linnakangas <[email protected]>
2023-10-09 06:45 Re: PGDOCS - add more links in the pub/sub reference pages Peter Smith <[email protected]>
2023-10-10 00:46 ` Re: PGDOCS - add more links in the pub/sub reference pages vignesh C <[email protected]>
2023-10-10 03:17   ` Re: PGDOCS - add more links in the pub/sub reference pages Peter Smith <[email protected]>
2023-10-10 06:10     ` Re: PGDOCS - add more links in the pub/sub reference pages vignesh C <[email protected]>
2023-10-10 12:33       ` Re: PGDOCS - add more links in the pub/sub reference pages Amit Kapila <[email protected]>
2023-10-12 04:44 ` Re: PGDOCS - add more links in the pub/sub reference pages Amit Kapila <[email protected]>
2023-10-13 03:32   ` Re: PGDOCS - add more links in the pub/sub reference pages Peter Smith <[email protected]>
2023-10-16 00:45     ` Re: PGDOCS - add more links in the pub/sub reference pages Peter Smith <[email protected]>
2023-10-30 09:15       ` Re: PGDOCS - add more links in the pub/sub reference pages Amit Kapila <[email protected]>

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox