Re: patch: reduce overhead of execution of CALL statement in no atomic mode from PL/pgSQL

2021-01-25 Thread Pavel Stehule
út 26. 1. 2021 v 4:33 odesílatel Tom Lane  napsal:

> Pavel Stehule  writes:
> > [ plpgsql-plan-cache-for-call-3.patch ]
>
> Pushed with some additional cleanup.
>

Thank you

Pavel


> It strikes me that we ought to get rid of SPI_execute_with_receiver
> (which has been added since v13) in favor of a "SPI_execute_extended"
> that shares the same options struct as SPI_execute_plan_extended.
> But I left that for tomorrow.
>
> regards, tom lane
>


Re: patch: reduce overhead of execution of CALL statement in no atomic mode from PL/pgSQL

2021-01-25 Thread Tom Lane
Pavel Stehule  writes:
> [ plpgsql-plan-cache-for-call-3.patch ]

Pushed with some additional cleanup.

It strikes me that we ought to get rid of SPI_execute_with_receiver
(which has been added since v13) in favor of a "SPI_execute_extended"
that shares the same options struct as SPI_execute_plan_extended.
But I left that for tomorrow.

regards, tom lane




Re: patch: reduce overhead of execution of CALL statement in no atomic mode from PL/pgSQL

2021-01-21 Thread Pavel Stehule
čt 21. 1. 2021 v 14:37 odesílatel Pavel Stehule 
napsal:

> Hi
>
> This is a little bit of an enhanced version of the previous patch. The
> worst case overhead is reduced almost to zero. The local resource owner is
> created only when routine is executed in non-atomic mode, and when routine
> contains a CALL statement.
>

Sorry. Last patch wasn't tested well.

Regards

Pavel




> Regards
>
> Pavel
>
>
diff --git a/doc/src/sgml/spi.sgml b/doc/src/sgml/spi.sgml
index f5e0a35da0..8cf66f8c7b 100644
--- a/doc/src/sgml/spi.sgml
+++ b/doc/src/sgml/spi.sgml
@@ -1722,6 +1722,138 @@ int SPI_execute_plan(SPIPlanPtr plan, Datum * 
 
 
 
+
+ SPI_execute_plan_extended
+
+ 
+  SPI_execute_plan_extended
+  3
+ 
+
+ 
+  SPI_execute_plan_extended
+  execute a statement prepared by SPI_prepare
+ 
+
+ 
+
+int SPI_execute_plan_extended(SPIPlanPtr plan,
+  ParamListInfo params,
+  bool read_only,
+  long count,
+  const SPIExecuteOptions * options)
+
+ 
+
+ 
+  Description
+
+  
+   SPI_execute_plan_extended executes a statement
+   prepared by SPI_prepare.
+   This function is equivalent to SPI_execute_plan_with_paramlist,
+   but allows to pass additional options.
+  
+ 
+
+ 
+  Arguments
+
+  
+   
+SPIPlanPtr plan
+
+ 
+  prepared statement (returned by SPI_prepare)
+ 
+
+   
+
+   
+ParamListInfo params
+
+ 
+  data structure containing parameter types and values; NULL if none
+ 
+
+   
+
+   
+bool read_only
+
+ true for read-only execution
+
+   
+
+   
+long count
+
+ 
+  maximum number of rows to return,
+  or 0 for no limit
+ 
+
+   
+
+   
+const SPIPExecuteOptions * options
+
+ 
+  struct containing optional arguments
+ 
+
+   
+  
+
+  
+   Callers should always zero out the entire options
+   struct, then fill whichever fields they want to set.  This ensures forward
+   compatibility of code, since any fields that are added to the struct in
+   future will be defined to behave backwards-compatibly if they are zero.
+   The currently available options fields are:
+  
+
+  
+   
+DestReceiver * dest
+
+ 
+  Query target
+ 
+
+   
+
+   
+ResourceOwner owner
+
+ 
+  The resource owner that will be used for plan execution. Now it is used
+  as cached query plan owner only. This resource owner should to have longer
+  life cycle than executed command. Current resource owner is used when
+  this option is NULL.
+ 
+
+   
+  
+ 
+
+ 
+  Return Value
+
+  
+   The return value is the same as for SPI_execute_plan.
+  
+
+  
+   SPI_processed and
+   SPI_tuptable are set as in
+   SPI_execute_plan if successful.
+  
+ 
+
+
+
+
 
  SPI_execute_plan_with_paramlist
 
diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c
index 653ef8e41a..3de2932a03 100644
--- a/src/backend/commands/prepare.c
+++ b/src/backend/commands/prepare.c
@@ -230,7 +230,7 @@ ExecuteQuery(ParseState *pstate,
 	   entry->plansource->query_string);
 
 	/* Replan if needed, and increment plan refcount for portal */
-	cplan = GetCachedPlan(entry->plansource, paramLI, false, NULL);
+	cplan = GetCachedPlan(entry->plansource, paramLI, NULL, NULL);
 	plan_list = cplan->stmt_list;
 
 	/*
@@ -651,7 +651,7 @@ ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, ExplainState *es,
 	}
 
 	/* Replan if needed, and acquire a transient refcount */
-	cplan = GetCachedPlan(entry->plansource, paramLI, true, queryEnv);
+	cplan = GetCachedPlan(entry->plansource, paramLI, CurrentResourceOwner, queryEnv);
 
 	INSTR_TIME_SET_CURRENT(planduration);
 	INSTR_TIME_SUBTRACT(planduration, planstart);
@@ -687,7 +687,7 @@ ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, ExplainState *es,
 	if (estate)
 		FreeExecutorState(estate);
 
-	ReleaseCachedPlan(cplan, true);
+	ReleaseCachedPlan(cplan, CurrentResourceOwner);
 }
 
 /*
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index e28d242922..17df852959 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -67,7 +67,7 @@ static void _SPI_prepare_oneshot_plan(const char *src, SPIPlanPtr plan);
 static int	_SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
 			  Snapshot snapshot, Snapshot crosscheck_snapshot,
 			  bool read_only, bool fire_triggers, uint64 tcount,
-			  DestReceiver *caller_dest);
+			  DestReceiver *caller_dest, ResourceOwner owner);
 
 static ParamListInfo _SPI_convert_params(int nargs, Oid *argtypes,
 		 Datum *Values, const char *Nulls);
@@ -521,7 +521,7 @@ SPI_execute(const char *src, bool read_only, long tcount)
 
 	res = _SPI_execute_plan(, NULL,
 			InvalidSnapshot, InvalidSnapshot,
-			read_only, true, tcount, NULL);
+			read_only, true, tcount, NULL, NULL);
 
 	_SPI_end_call(true);
 	return res;

Re: patch: reduce overhead of execution of CALL statement in no atomic mode from PL/pgSQL

2021-01-21 Thread Pavel Stehule
Hi

This is a little bit of an enhanced version of the previous patch. The
worst case overhead is reduced almost to zero. The local resource owner is
created only when routine is executed in non-atomic mode, and when routine
contains a CALL statement.

Regards

Pavel
diff --git a/doc/src/sgml/spi.sgml b/doc/src/sgml/spi.sgml
index f5e0a35da0..8cf66f8c7b 100644
--- a/doc/src/sgml/spi.sgml
+++ b/doc/src/sgml/spi.sgml
@@ -1722,6 +1722,138 @@ int SPI_execute_plan(SPIPlanPtr plan, Datum * 
 
 
 
+
+ SPI_execute_plan_extended
+
+ 
+  SPI_execute_plan_extended
+  3
+ 
+
+ 
+  SPI_execute_plan_extended
+  execute a statement prepared by SPI_prepare
+ 
+
+ 
+
+int SPI_execute_plan_extended(SPIPlanPtr plan,
+  ParamListInfo params,
+  bool read_only,
+  long count,
+  const SPIExecuteOptions * options)
+
+ 
+
+ 
+  Description
+
+  
+   SPI_execute_plan_extended executes a statement
+   prepared by SPI_prepare.
+   This function is equivalent to SPI_execute_plan_with_paramlist,
+   but allows to pass additional options.
+  
+ 
+
+ 
+  Arguments
+
+  
+   
+SPIPlanPtr plan
+
+ 
+  prepared statement (returned by SPI_prepare)
+ 
+
+   
+
+   
+ParamListInfo params
+
+ 
+  data structure containing parameter types and values; NULL if none
+ 
+
+   
+
+   
+bool read_only
+
+ true for read-only execution
+
+   
+
+   
+long count
+
+ 
+  maximum number of rows to return,
+  or 0 for no limit
+ 
+
+   
+
+   
+const SPIPExecuteOptions * options
+
+ 
+  struct containing optional arguments
+ 
+
+   
+  
+
+  
+   Callers should always zero out the entire options
+   struct, then fill whichever fields they want to set.  This ensures forward
+   compatibility of code, since any fields that are added to the struct in
+   future will be defined to behave backwards-compatibly if they are zero.
+   The currently available options fields are:
+  
+
+  
+   
+DestReceiver * dest
+
+ 
+  Query target
+ 
+
+   
+
+   
+ResourceOwner owner
+
+ 
+  The resource owner that will be used for plan execution. Now it is used
+  as cached query plan owner only. This resource owner should to have longer
+  life cycle than executed command. Current resource owner is used when
+  this option is NULL.
+ 
+
+   
+  
+ 
+
+ 
+  Return Value
+
+  
+   The return value is the same as for SPI_execute_plan.
+  
+
+  
+   SPI_processed and
+   SPI_tuptable are set as in
+   SPI_execute_plan if successful.
+  
+ 
+
+
+
+
 
  SPI_execute_plan_with_paramlist
 
diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c
index 653ef8e41a..3de2932a03 100644
--- a/src/backend/commands/prepare.c
+++ b/src/backend/commands/prepare.c
@@ -230,7 +230,7 @@ ExecuteQuery(ParseState *pstate,
 	   entry->plansource->query_string);
 
 	/* Replan if needed, and increment plan refcount for portal */
-	cplan = GetCachedPlan(entry->plansource, paramLI, false, NULL);
+	cplan = GetCachedPlan(entry->plansource, paramLI, NULL, NULL);
 	plan_list = cplan->stmt_list;
 
 	/*
@@ -651,7 +651,7 @@ ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, ExplainState *es,
 	}
 
 	/* Replan if needed, and acquire a transient refcount */
-	cplan = GetCachedPlan(entry->plansource, paramLI, true, queryEnv);
+	cplan = GetCachedPlan(entry->plansource, paramLI, CurrentResourceOwner, queryEnv);
 
 	INSTR_TIME_SET_CURRENT(planduration);
 	INSTR_TIME_SUBTRACT(planduration, planstart);
@@ -687,7 +687,7 @@ ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, ExplainState *es,
 	if (estate)
 		FreeExecutorState(estate);
 
-	ReleaseCachedPlan(cplan, true);
+	ReleaseCachedPlan(cplan, CurrentResourceOwner);
 }
 
 /*
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index e28d242922..17df852959 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -67,7 +67,7 @@ static void _SPI_prepare_oneshot_plan(const char *src, SPIPlanPtr plan);
 static int	_SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
 			  Snapshot snapshot, Snapshot crosscheck_snapshot,
 			  bool read_only, bool fire_triggers, uint64 tcount,
-			  DestReceiver *caller_dest);
+			  DestReceiver *caller_dest, ResourceOwner owner);
 
 static ParamListInfo _SPI_convert_params(int nargs, Oid *argtypes,
 		 Datum *Values, const char *Nulls);
@@ -521,7 +521,7 @@ SPI_execute(const char *src, bool read_only, long tcount)
 
 	res = _SPI_execute_plan(, NULL,
 			InvalidSnapshot, InvalidSnapshot,
-			read_only, true, tcount, NULL);
+			read_only, true, tcount, NULL, NULL);
 
 	_SPI_end_call(true);
 	return res;
@@ -555,7 +555,7 @@ SPI_execute_plan(SPIPlanPtr plan, Datum *Values, const char *Nulls,
 			_SPI_convert_params(plan->nargs, 

Re: patch: reduce overhead of execution of CALL statement in no atomic mode from PL/pgSQL

2021-01-21 Thread Pavel Stehule
Hi

pá 15. 1. 2021 v 22:46 odesílatel Tom Lane  napsal:

> Pavel Stehule  writes:
> > [ plpgsql-using-local-resowner-for-call-plans-20200108.patch ]
>
> I took a quick look through this patch, just reading it without
> any testing.  A few thoughts:
>
> * Instead of adding an argument to GetCachedPlan and ReleaseCachedPlan,
> I think it'd be better to *replace* the useResOwner bool with
> a ResourceOwner pointer, with the obvious semantics "do nothing if
> it's NULL".  Otherwise you have to explain what it means to pass NULL
> with useResOwner = true.  In any case, changing the APIs of these
> functions without updating their header comments is not okay.
>

done


> * I'm not really happy with adding yet another nonorthogonal variant
> of SPI_execute_plan.  Maybe better to do something like I did with
> SPI_prepare_extended() in commit 844fe9f15, and create a struct with
> all the inessential parameters so that we can make future API extensions
> without inventing whole new functions.  Remember also that new SPI
> functions have to be documented in spi.sgml.
>

done


> * Do we really need a PG_TRY in exec_toplevel_block?  Not to mention
> creating and destroying a ResOwner?  That seems pretty expensive, and it
> should be unnecessary for ordinary plpgsql functions.  (I'm also unhappy
> that you've utterly falsified that function's comment without doing
> anything to update it.)  This is really the part that needs more
> work.  I'm not sure that you can sell a speedup of CALL operations
> if the penalty is to slow down every other plpgsql function.
>

I rewrote this part - now there is no new PG_TRY. local_resowner is created
only when routine is executed in non atomic mode


> * The part of the patch around exec_stmt_call is just about unreadable,
> mainly because git diff seems to think that exec_stmt_call is being
> changed into make_callstmt_target.  Maybe it'd be less messy if you
> put make_callstmt_target after exec_stmt_call.
>

done


> * Looks like an extra exec_prepare_plan() call snuck into
> exec_assign_expr()?
>

fixed

I did performance tests and not the slowdown in the worst case is lower
(3-5%) only for execution in non-atomic mode. The performance of atomic
mode is the same.

Regards

Pavel




> regards, tom lane
>
diff --git a/doc/src/sgml/spi.sgml b/doc/src/sgml/spi.sgml
index f5e0a35da0..8cf66f8c7b 100644
--- a/doc/src/sgml/spi.sgml
+++ b/doc/src/sgml/spi.sgml
@@ -1722,6 +1722,138 @@ int SPI_execute_plan(SPIPlanPtr plan, Datum * 
 
 
 
+
+ SPI_execute_plan_extended
+
+ 
+  SPI_execute_plan_extended
+  3
+ 
+
+ 
+  SPI_execute_plan_extended
+  execute a statement prepared by SPI_prepare
+ 
+
+ 
+
+int SPI_execute_plan_extended(SPIPlanPtr plan,
+  ParamListInfo params,
+  bool read_only,
+  long count,
+  const SPIExecuteOptions * options)
+
+ 
+
+ 
+  Description
+
+  
+   SPI_execute_plan_extended executes a statement
+   prepared by SPI_prepare.
+   This function is equivalent to SPI_execute_plan_with_paramlist,
+   but allows to pass additional options.
+  
+ 
+
+ 
+  Arguments
+
+  
+   
+SPIPlanPtr plan
+
+ 
+  prepared statement (returned by SPI_prepare)
+ 
+
+   
+
+   
+ParamListInfo params
+
+ 
+  data structure containing parameter types and values; NULL if none
+ 
+
+   
+
+   
+bool read_only
+
+ true for read-only execution
+
+   
+
+   
+long count
+
+ 
+  maximum number of rows to return,
+  or 0 for no limit
+ 
+
+   
+
+   
+const SPIPExecuteOptions * options
+
+ 
+  struct containing optional arguments
+ 
+
+   
+  
+
+  
+   Callers should always zero out the entire options
+   struct, then fill whichever fields they want to set.  This ensures forward
+   compatibility of code, since any fields that are added to the struct in
+   future will be defined to behave backwards-compatibly if they are zero.
+   The currently available options fields are:
+  
+
+  
+   
+DestReceiver * dest
+
+ 
+  Query target
+ 
+
+   
+
+   
+ResourceOwner owner
+
+ 
+  The resource owner that will be used for plan execution. Now it is used
+  as cached query plan owner only. This resource owner should to have longer
+  life cycle than executed command. Current resource owner is used when
+  this option is NULL.
+ 
+
+   
+  
+ 
+
+ 
+  Return Value
+
+  
+   The return value is the same as for SPI_execute_plan.
+  
+
+  
+   SPI_processed and
+   SPI_tuptable are set as in
+   SPI_execute_plan if successful.
+  
+ 
+
+
+
+
 
  SPI_execute_plan_with_paramlist
 
diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c
index 653ef8e41a..3de2932a03 100644
--- a/src/backend/commands/prepare.c
+++ b/src/backend/commands/prepare.c
@@ -230,7 +230,7 @@ 

Re: patch: reduce overhead of execution of CALL statement in no atomic mode from PL/pgSQL

2021-01-15 Thread Tom Lane
Pavel Stehule  writes:
> [ plpgsql-using-local-resowner-for-call-plans-20200108.patch ]

I took a quick look through this patch, just reading it without
any testing.  A few thoughts:

* Instead of adding an argument to GetCachedPlan and ReleaseCachedPlan,
I think it'd be better to *replace* the useResOwner bool with
a ResourceOwner pointer, with the obvious semantics "do nothing if
it's NULL".  Otherwise you have to explain what it means to pass NULL
with useResOwner = true.  In any case, changing the APIs of these
functions without updating their header comments is not okay.

* I'm not really happy with adding yet another nonorthogonal variant
of SPI_execute_plan.  Maybe better to do something like I did with
SPI_prepare_extended() in commit 844fe9f15, and create a struct with
all the inessential parameters so that we can make future API extensions
without inventing whole new functions.  Remember also that new SPI
functions have to be documented in spi.sgml.

* Do we really need a PG_TRY in exec_toplevel_block?  Not to mention
creating and destroying a ResOwner?  That seems pretty expensive, and it
should be unnecessary for ordinary plpgsql functions.  (I'm also unhappy
that you've utterly falsified that function's comment without doing
anything to update it.)  This is really the part that needs more
work.  I'm not sure that you can sell a speedup of CALL operations
if the penalty is to slow down every other plpgsql function.

* The part of the patch around exec_stmt_call is just about unreadable,
mainly because git diff seems to think that exec_stmt_call is being
changed into make_callstmt_target.  Maybe it'd be less messy if you
put make_callstmt_target after exec_stmt_call.

* Looks like an extra exec_prepare_plan() call snuck into
exec_assign_expr()?

regards, tom lane




Re: patch: reduce overhead of execution of CALL statement in no atomic mode from PL/pgSQL

2021-01-07 Thread Pavel Stehule
pá 1. 1. 2021 v 9:15 odesílatel Pavel Stehule 
napsal:

> Hi
>
> only rebase
>

rebase

regards

Pavel


> Regards
>
> Pavel
>
diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c
index 653ef8e41a..6f8643cc4a 100644
--- a/src/backend/commands/prepare.c
+++ b/src/backend/commands/prepare.c
@@ -230,7 +230,7 @@ ExecuteQuery(ParseState *pstate,
 	   entry->plansource->query_string);
 
 	/* Replan if needed, and increment plan refcount for portal */
-	cplan = GetCachedPlan(entry->plansource, paramLI, false, NULL);
+	cplan = GetCachedPlan(entry->plansource, paramLI, false, NULL, NULL);
 	plan_list = cplan->stmt_list;
 
 	/*
@@ -651,7 +651,7 @@ ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, ExplainState *es,
 	}
 
 	/* Replan if needed, and acquire a transient refcount */
-	cplan = GetCachedPlan(entry->plansource, paramLI, true, queryEnv);
+	cplan = GetCachedPlan(entry->plansource, paramLI, true, CurrentResourceOwner, queryEnv);
 
 	INSTR_TIME_SET_CURRENT(planduration);
 	INSTR_TIME_SUBTRACT(planduration, planstart);
@@ -687,7 +687,7 @@ ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, ExplainState *es,
 	if (estate)
 		FreeExecutorState(estate);
 
-	ReleaseCachedPlan(cplan, true);
+	ReleaseCachedPlan(cplan, true, CurrentResourceOwner);
 }
 
 /*
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index e28d242922..a4fe7eb2c3 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -67,7 +67,7 @@ static void _SPI_prepare_oneshot_plan(const char *src, SPIPlanPtr plan);
 static int	_SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
 			  Snapshot snapshot, Snapshot crosscheck_snapshot,
 			  bool read_only, bool fire_triggers, uint64 tcount,
-			  DestReceiver *caller_dest);
+			  DestReceiver *caller_dest, ResourceOwner owner);
 
 static ParamListInfo _SPI_convert_params(int nargs, Oid *argtypes,
 		 Datum *Values, const char *Nulls);
@@ -521,7 +521,8 @@ SPI_execute(const char *src, bool read_only, long tcount)
 
 	res = _SPI_execute_plan(, NULL,
 			InvalidSnapshot, InvalidSnapshot,
-			read_only, true, tcount, NULL);
+			read_only, true, tcount, NULL,
+			CurrentResourceOwner);
 
 	_SPI_end_call(true);
 	return res;
@@ -555,7 +556,8 @@ SPI_execute_plan(SPIPlanPtr plan, Datum *Values, const char *Nulls,
 			_SPI_convert_params(plan->nargs, plan->argtypes,
 Values, Nulls),
 			InvalidSnapshot, InvalidSnapshot,
-			read_only, true, tcount, NULL);
+			read_only, true, tcount, NULL,
+			CurrentResourceOwner);
 
 	_SPI_end_call(true);
 	return res;
@@ -584,7 +586,8 @@ SPI_execute_plan_with_paramlist(SPIPlanPtr plan, ParamListInfo params,
 
 	res = _SPI_execute_plan(plan, params,
 			InvalidSnapshot, InvalidSnapshot,
-			read_only, true, tcount, NULL);
+			read_only, true, tcount, NULL,
+			CurrentResourceOwner);
 
 	_SPI_end_call(true);
 	return res;
@@ -613,7 +616,37 @@ SPI_execute_plan_with_receiver(SPIPlanPtr plan,
 
 	res = _SPI_execute_plan(plan, params,
 			InvalidSnapshot, InvalidSnapshot,
-			read_only, true, tcount, dest);
+			read_only, true, tcount, dest,
+			CurrentResourceOwner);
+
+	_SPI_end_call(true);
+	return res;
+}
+
+
+/*
+ * Execute a previously prepared plan with possibility to
+ * specify resource owner
+ */
+int
+SPI_execute_plan_with_resowner(SPIPlanPtr plan,
+ParamListInfo params,
+bool read_only, long tcount,
+ResourceOwner owner)
+{
+	int			res;
+
+	if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC || tcount < 0)
+		return SPI_ERROR_ARGUMENT;
+
+	res = _SPI_begin_call(true);
+	if (res < 0)
+		return res;
+
+	res = _SPI_execute_plan(plan, params,
+			InvalidSnapshot, InvalidSnapshot,
+			read_only, true, tcount, NULL,
+			owner);
 
 	_SPI_end_call(true);
 	return res;
@@ -654,7 +687,8 @@ SPI_execute_snapshot(SPIPlanPtr plan,
 			_SPI_convert_params(plan->nargs, plan->argtypes,
 Values, Nulls),
 			snapshot, crosscheck_snapshot,
-			read_only, fire_triggers, tcount, NULL);
+			read_only, fire_triggers, tcount, NULL,
+			CurrentResourceOwner);
 
 	_SPI_end_call(true);
 	return res;
@@ -702,7 +736,8 @@ SPI_execute_with_args(const char *src,
 
 	res = _SPI_execute_plan(, paramLI,
 			InvalidSnapshot, InvalidSnapshot,
-			read_only, true, tcount, NULL);
+			read_only, true, tcount, NULL,
+			CurrentResourceOwner);
 
 	_SPI_end_call(true);
 	return res;
@@ -746,7 +781,8 @@ SPI_execute_with_receiver(const char *src,
 
 	res = _SPI_execute_plan(, params,
 			InvalidSnapshot, InvalidSnapshot,
-			read_only, true, tcount, dest);
+			read_only, true, tcount, dest,
+			CurrentResourceOwner);
 
 	_SPI_end_call(true);
 	return res;
@@ -1554,7 +1590,7 @@ SPI_cursor_open_internal(const char *name, SPIPlanPtr plan,
 	 */
 
 	/* Replan if needed, and increment plan refcount for portal */
-	cplan = 

Re: patch: reduce overhead of execution of CALL statement in no atomic mode from PL/pgSQL

2021-01-01 Thread Pavel Stehule
Hi

only rebase

Regards

Pavel
diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c
index 89087a7be3..b1d2f1af37 100644
--- a/src/backend/commands/prepare.c
+++ b/src/backend/commands/prepare.c
@@ -230,7 +230,7 @@ ExecuteQuery(ParseState *pstate,
 	   entry->plansource->query_string);
 
 	/* Replan if needed, and increment plan refcount for portal */
-	cplan = GetCachedPlan(entry->plansource, paramLI, false, NULL);
+	cplan = GetCachedPlan(entry->plansource, paramLI, false, NULL, NULL);
 	plan_list = cplan->stmt_list;
 
 	/*
@@ -651,7 +651,7 @@ ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, ExplainState *es,
 	}
 
 	/* Replan if needed, and acquire a transient refcount */
-	cplan = GetCachedPlan(entry->plansource, paramLI, true, queryEnv);
+	cplan = GetCachedPlan(entry->plansource, paramLI, true, CurrentResourceOwner, queryEnv);
 
 	INSTR_TIME_SET_CURRENT(planduration);
 	INSTR_TIME_SUBTRACT(planduration, planstart);
@@ -687,7 +687,7 @@ ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, ExplainState *es,
 	if (estate)
 		FreeExecutorState(estate);
 
-	ReleaseCachedPlan(cplan, true);
+	ReleaseCachedPlan(cplan, true, CurrentResourceOwner);
 }
 
 /*
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index 055ebb77ae..39c19f3b40 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -61,7 +61,7 @@ static void _SPI_prepare_oneshot_plan(const char *src, SPIPlanPtr plan);
 static int	_SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
 			  Snapshot snapshot, Snapshot crosscheck_snapshot,
 			  bool read_only, bool fire_triggers, uint64 tcount,
-			  DestReceiver *caller_dest);
+			  DestReceiver *caller_dest, ResourceOwner owner);
 
 static ParamListInfo _SPI_convert_params(int nargs, Oid *argtypes,
 		 Datum *Values, const char *Nulls);
@@ -514,7 +514,8 @@ SPI_execute(const char *src, bool read_only, long tcount)
 
 	res = _SPI_execute_plan(, NULL,
 			InvalidSnapshot, InvalidSnapshot,
-			read_only, true, tcount, NULL);
+			read_only, true, tcount, NULL,
+			CurrentResourceOwner);
 
 	_SPI_end_call(true);
 	return res;
@@ -548,7 +549,8 @@ SPI_execute_plan(SPIPlanPtr plan, Datum *Values, const char *Nulls,
 			_SPI_convert_params(plan->nargs, plan->argtypes,
 Values, Nulls),
 			InvalidSnapshot, InvalidSnapshot,
-			read_only, true, tcount, NULL);
+			read_only, true, tcount, NULL,
+			CurrentResourceOwner);
 
 	_SPI_end_call(true);
 	return res;
@@ -577,7 +579,8 @@ SPI_execute_plan_with_paramlist(SPIPlanPtr plan, ParamListInfo params,
 
 	res = _SPI_execute_plan(plan, params,
 			InvalidSnapshot, InvalidSnapshot,
-			read_only, true, tcount, NULL);
+			read_only, true, tcount, NULL,
+			CurrentResourceOwner);
 
 	_SPI_end_call(true);
 	return res;
@@ -606,7 +609,37 @@ SPI_execute_plan_with_receiver(SPIPlanPtr plan,
 
 	res = _SPI_execute_plan(plan, params,
 			InvalidSnapshot, InvalidSnapshot,
-			read_only, true, tcount, dest);
+			read_only, true, tcount, dest,
+			CurrentResourceOwner);
+
+	_SPI_end_call(true);
+	return res;
+}
+
+
+/*
+ * Execute a previously prepared plan with possibility to
+ * specify resource owner
+ */
+int
+SPI_execute_plan_with_resowner(SPIPlanPtr plan,
+ParamListInfo params,
+bool read_only, long tcount,
+ResourceOwner owner)
+{
+	int			res;
+
+	if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC || tcount < 0)
+		return SPI_ERROR_ARGUMENT;
+
+	res = _SPI_begin_call(true);
+	if (res < 0)
+		return res;
+
+	res = _SPI_execute_plan(plan, params,
+			InvalidSnapshot, InvalidSnapshot,
+			read_only, true, tcount, NULL,
+			owner);
 
 	_SPI_end_call(true);
 	return res;
@@ -647,7 +680,8 @@ SPI_execute_snapshot(SPIPlanPtr plan,
 			_SPI_convert_params(plan->nargs, plan->argtypes,
 Values, Nulls),
 			snapshot, crosscheck_snapshot,
-			read_only, fire_triggers, tcount, NULL);
+			read_only, fire_triggers, tcount, NULL,
+			CurrentResourceOwner);
 
 	_SPI_end_call(true);
 	return res;
@@ -694,7 +728,8 @@ SPI_execute_with_args(const char *src,
 
 	res = _SPI_execute_plan(, paramLI,
 			InvalidSnapshot, InvalidSnapshot,
-			read_only, true, tcount, NULL);
+			read_only, true, tcount, NULL,
+			CurrentResourceOwner);
 
 	_SPI_end_call(true);
 	return res;
@@ -737,7 +772,8 @@ SPI_execute_with_receiver(const char *src,
 
 	res = _SPI_execute_plan(, params,
 			InvalidSnapshot, InvalidSnapshot,
-			read_only, true, tcount, dest);
+			read_only, true, tcount, dest,
+			CurrentResourceOwner);
 
 	_SPI_end_call(true);
 	return res;
@@ -1502,7 +1538,7 @@ SPI_cursor_open_internal(const char *name, SPIPlanPtr plan,
 	 */
 
 	/* Replan if needed, and increment plan refcount for portal */
-	cplan = GetCachedPlan(plansource, paramLI, false, _SPI_current->queryEnv);
+	cplan = GetCachedPlan(plansource, 

Re: patch: reduce overhead of execution of CALL statement in no atomic mode from PL/pgSQL

2020-11-03 Thread Pavel Stehule
Hi

I played with the profiler a little bit to get some data - see attached
file.  Almost all overhead is related to impossibility to use simple
expression evaluation (that has very good performance now).

Probably there is no simple way to reduce this overhead.

Regards

Pavel


call-graph-profile.gz
Description: application/gzip