Le 30/07/2021 à 23:49, Tom Lane a écrit :
Andres Freund <and...@anarazel.de> writes:
On 2021-07-30 13:58:51 -0400, Tom Lane wrote:
I've not read this version of the patch, but I see from the cfbot's
results that it's broken postgres_fdw.
I think this may partially be an issue with the way that postgres_fdw
uses the callback than with the patch. It disconnects from the server
*regardless* of the XactEvent passed to the callback. That makes it
really hard to extend the callback mechanism to further events...
Perhaps.  Nonetheless, I thought upthread that adding these events
as Xact/SubXactCallback events was the wrong design, and I still
think that.  A new hook would be a more sensible way.

I'm *very* unconvinced it makes sense to implement a feature like this
in an extension / that we should expose API for that purpose. To me the
top-level transaction state is way too tied to our internals for it to
be reasonably dealt with in an extension.
Yeah, that's the other major problem --- the use-case doesn't seem
very convincing.  I'm not even sold on the goal, let alone on trying
to implement it by hooking into these particular places.  I think
that'll end up being buggy and fragile as well as not very performant.


I've attached the new version v5 of the patch that use a hook instead of the use of a xact callback. Compared to the first implementation calls to the hook have been extracted from the start_xact_command() function. The test extension have also be updated.


If I understand well the last discussions there is no chance of having this hook included. If there is no contrary opinion I will withdraw the patch from the commitfest. However thank you so much to have taken time to review this proposal.


Best regards,

--
Gilles Darold

diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 530caa520b..bc62a2cb98 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -207,6 +207,8 @@ static void log_disconnections(int code, Datum arg);
 static void enable_statement_timeout(void);
 static void disable_statement_timeout(void);
 
+/* Hooks for plugins to get control at end of start_xact_command() */
+XactCommandStart_hook_type start_xact_command_hook = NULL;
 
 /* ----------------------------------------------------------------
  *		routines to obtain user input
@@ -989,6 +991,13 @@ exec_simple_query(const char *query_string)
 	 */
 	start_xact_command();
 
+	/*
+	 * Now give loadable modules a chance to execute code
+	 * before a transaction command is processed.
+	 */
+	if (start_xact_command_hook)
+		(*start_xact_command_hook) ();
+
 	/*
 	 * Zap any pre-existing unnamed statement.  (While not strictly necessary,
 	 * it seems best to define simple-Query mode as if it used the unnamed
@@ -1082,6 +1091,13 @@ exec_simple_query(const char *query_string)
 		/* Make sure we are in a transaction command */
 		start_xact_command();
 
+		/*
+		 * Now give loadable modules a chance to execute code
+		 * before a transaction command is processed.
+		 */
+		if (start_xact_command_hook)
+			(*start_xact_command_hook) ();
+
 		/*
 		 * If using an implicit transaction block, and we're not already in a
 		 * transaction block, start an implicit block to force this statement
@@ -1361,6 +1377,13 @@ exec_parse_message(const char *query_string,	/* string to execute */
 	 */
 	start_xact_command();
 
+	/*
+	 * Now give loadable modules a chance to execute code
+	 * before a transaction command is processed.
+	 */
+	if (start_xact_command_hook)
+		(*start_xact_command_hook) ();
+
 	/*
 	 * Switch to appropriate context for constructing parsetrees.
 	 *
@@ -1647,6 +1670,13 @@ exec_bind_message(StringInfo input_message)
 	 */
 	start_xact_command();
 
+	/*
+	 * Now give loadable modules a chance to execute code
+	 * before a transaction command is processed.
+	 */
+	if (start_xact_command_hook)
+		(*start_xact_command_hook) ();
+
 	/* Switch back to message context */
 	MemoryContextSwitchTo(MessageContext);
 
@@ -2140,6 +2170,13 @@ exec_execute_message(const char *portal_name, long max_rows)
 	 */
 	start_xact_command();
 
+	/*
+	 * Now give loadable modules a chance to execute code
+	 * before a transaction command is processed.
+	 */
+	if (start_xact_command_hook)
+		(*start_xact_command_hook) ();
+
 	/*
 	 * If we re-issue an Execute protocol request against an existing portal,
 	 * then we are only fetching more rows rather than completely re-executing
@@ -2546,6 +2583,13 @@ exec_describe_statement_message(const char *stmt_name)
 	 */
 	start_xact_command();
 
+	/*
+	 * Now give loadable modules a chance to execute code
+	 * before a transaction command is processed.
+	 */
+	if (start_xact_command_hook)
+		(*start_xact_command_hook) ();
+
 	/* Switch back to message context */
 	MemoryContextSwitchTo(MessageContext);
 
@@ -2641,6 +2685,13 @@ exec_describe_portal_message(const char *portal_name)
 	 */
 	start_xact_command();
 
+	/*
+	 * Now give loadable modules a chance to execute code
+	 * before a transaction command is processed.
+	 */
+	if (start_xact_command_hook)
+		(*start_xact_command_hook) ();
+
 	/* Switch back to message context */
 	MemoryContextSwitchTo(MessageContext);
 
@@ -4561,6 +4612,13 @@ PostgresMain(int argc, char *argv[],
 				/* start an xact for this function invocation */
 				start_xact_command();
 
+				/*
+				 * Now give loadable modules a chance to execute code
+				 * before a transaction command is processed.
+				 */
+				if (start_xact_command_hook)
+					(*start_xact_command_hook) ();
+
 				/*
 				 * Note: we may at this point be inside an aborted
 				 * transaction.  We can't throw error for that until we've
diff --git a/src/include/tcop/pquery.h b/src/include/tcop/pquery.h
index 2318f04ff0..540ede42fd 100644
--- a/src/include/tcop/pquery.h
+++ b/src/include/tcop/pquery.h
@@ -48,4 +48,8 @@ extern bool PlannedStmtRequiresSnapshot(struct PlannedStmt *pstmt);
 
 extern void EnsurePortalSnapshotExists(void);
 
+/* Hook for plugins to get control in start_xact_command() and finish_xact_command() */
+typedef void (*XactCommandStart_hook_type) (void);
+extern PGDLLIMPORT XactCommandStart_hook_type start_xact_command_hook;
+
 #endif							/* PQUERY_H */
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 37cf4b2f76..110541731c 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -2938,6 +2938,7 @@ XPVIV
 XPVMG
 XactCallback
 XactCallbackItem
+XactCommandStart_hook_type
 XactEvent
 XactLockTableWaitInfo
 XidBoundsViolation

Reply via email to