Hi all!
I am working on a new type of pooling mechanism for Postgres
connection managers. In this mode, the client connection is
detached from server between transactions only if no temporary
objects were created in that session
(temporary tables, prepared statements, and advisory locks).
Currently, I am exploring ways to notify the connection manager
when any of these session-level objects are created or existing.
I got next ideas:
- send a status info byte in RFQ package, but that requires a
protocol changes, so this option should be discarded, I suppose
- create an extension, that executes elog(NOTIFY, "some message") or
sends dedicated package with smth like pq_putemptymessage('O') in new
hook, that is called before RFQ sending (see POC patch in attachments)
- create an extension, that executes the same things as in option above,
but uses more specialized hooks. For temporary tables I can use
ProcessUtility_hook that already exists. For prepared statements and
advisory locks I wasn't able to find a suitable hooks, so I add a hook
before sending ParseComplete message and in LockAcquire end
(see another POC patch in attachments)
I would appreciate any feedback on the general idea, advices on a clean way
to implement such notifications, and comments on the attached POC patches.
If you have ideas, experience with similar tasks, or suggestions for a
better (or more canonical) Postgres way to approach this, please let me know.
Thanks!
----
Best regards,
Roman Khapov.
From 9c1a6aa28306b07ec72ae770e3ed5fa980fb1b71 Mon Sep 17 00:00:00 2001 From: rkhapov <r.kha...@ya.ru> Date: Tue, 24 Jun 2025 08:56:35 +0000 Subject: [PATCH] dummy hooks for parse complete and lock acquired
Signed-off-by: rkhapov <r.kha...@ya.ru> --- src/backend/storage/lmgr/lock.c | 4 ++++ src/backend/tcop/postgres.c | 8 ++++++++ src/backend/utils/adt/lockfuncs.c | 2 ++ src/include/postgres.h | 4 ++++ src/include/storage/lock.h | 4 ++++ 5 files changed, 22 insertions(+) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 2776ceb295b..00178d98a07 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -1265,6 +1265,10 @@ LockAcquireExtended(const LOCKTAG *locktag, locktag->locktag_field2); } + if (LockAcquired_hook) { + LockAcquired_hook(); + } + return LOCKACQUIRE_OK; } diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index e76b625ec31..f9bf13bfa8c 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -104,6 +104,7 @@ int client_connection_check_interval = 0; /* flags for non-system relation kinds to restrict use */ int restrict_nonsystem_relation_kind; +ParseComplete_hook_type ParseComplete_hook = NULL; ReadyForQuery_hook_type ReadyForQuery_hook = NULL; /* ---------------- @@ -1585,6 +1586,13 @@ exec_parse_message(const char *query_string, /* string to execute */ */ CommandCounterIncrement(); + /* + * Notify extensions about parse complete + */ + if (ParseComplete_hook) { + ParseComplete_hook(); + } + /* * Send ParseComplete. */ diff --git a/src/backend/utils/adt/lockfuncs.c b/src/backend/utils/adt/lockfuncs.c index 00e67fb46d0..d2a2235a811 100644 --- a/src/backend/utils/adt/lockfuncs.c +++ b/src/backend/utils/adt/lockfuncs.c @@ -65,6 +65,8 @@ typedef struct /* Number of columns in pg_locks output */ #define NUM_LOCK_STATUS_COLUMNS 16 +LockAcquired_hook_type LockAcquired_hook = NULL; + /* * VXIDGetDatum - Construct a text representation of a VXID * diff --git a/src/include/postgres.h b/src/include/postgres.h index c844742d977..f62d8355a8a 100644 --- a/src/include/postgres.h +++ b/src/include/postgres.h @@ -581,6 +581,10 @@ extern Datum Float8GetDatum(float8 X); #define NON_EXEC_STATIC static #endif +/* Hook for plugins to handle prepared statements creation */ +typedef void (*ParseComplete_hook_type) (); +extern PGDLLIMPORT ParseComplete_hook_type ParseComplete_hook; + /* Hook for plugins to catch RFQ sending */ typedef void (*ReadyForQuery_hook_type) (); extern PGDLLIMPORT ReadyForQuery_hook_type ReadyForQuery_hook; diff --git a/src/include/storage/lock.h b/src/include/storage/lock.h index 4862b80eec3..a0cc3bcd698 100644 --- a/src/include/storage/lock.h +++ b/src/include/storage/lock.h @@ -627,4 +627,8 @@ extern void VirtualXactLockTableInsert(VirtualTransactionId vxid); extern void VirtualXactLockTableCleanup(void); extern bool VirtualXactLock(VirtualTransactionId vxid, bool wait); +/* Hook for plugins to handle lock acquire */ +typedef void (*LockAcquired_hook_type) (); +extern PGDLLIMPORT LockAcquired_hook_type LockAcquired_hook; + #endif /* LOCK_H_ */ -- 2.43.0
From bd4f35bfa4c5709808169b847d64d350eae38804 Mon Sep 17 00:00:00 2001 From: rkhapov <r.kha...@ya.ru> Date: Tue, 24 Jun 2025 06:17:29 +0000 Subject: [PATCH] dummy RFQ hook impl Signed-off-by: rkhapov <r.kha...@ya.ru> --- src/backend/tcop/postgres.c | 6 ++++++ src/include/postgres.h | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 2f8c3d5f918..e76b625ec31 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -104,6 +104,8 @@ int client_connection_check_interval = 0; /* flags for non-system relation kinds to restrict use */ int restrict_nonsystem_relation_kind; +ReadyForQuery_hook_type ReadyForQuery_hook = NULL; + /* ---------------- * private typedefs etc * ---------------- @@ -4680,6 +4682,10 @@ PostgresMain(const char *dbname, const char *username) (double) auth_duration / NS_PER_US)); } + if (ReadyForQuery_hook) { + ReadyForQuery_hook(/* some arguments to determine connection state here */); + } + ReadyForQuery(whereToSendOutput); send_ready_for_query = false; } diff --git a/src/include/postgres.h b/src/include/postgres.h index 8a41a668687..c844742d977 100644 --- a/src/include/postgres.h +++ b/src/include/postgres.h @@ -581,4 +581,8 @@ extern Datum Float8GetDatum(float8 X); #define NON_EXEC_STATIC static #endif +/* Hook for plugins to catch RFQ sending */ +typedef void (*ReadyForQuery_hook_type) (); +extern PGDLLIMPORT ReadyForQuery_hook_type ReadyForQuery_hook; + #endif /* POSTGRES_H */ -- 2.43.0