pl_parallel_exec_support_v1.patch
application/octet-stream
Filename: pl_parallel_exec_support_v1.patch
Type: application/octet-stream
Part: 0
Patch
Format: unified
Series: patch v1
| File | + | − |
|---|---|---|
| src/backend/executor/execMain.c | 25 | 6 |
| src/backend/tcop/pquery.c | 1 | 0 |
| src/include/executor/execdesc.h | 1 | 0 |
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 3f76a407d7..098b14d227 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -84,7 +84,7 @@ static void ExecutePlan(EState *estate, PlanState *planstate,
bool sendTuples,
uint64 numberTuples,
ScanDirection direction,
- DestReceiver *dest);
+ DestReceiver *dest, bool execute_once);
static bool ExecCheckRTEPerms(RangeTblEntry *rte);
static bool ExecCheckRTEPermsModified(Oid relOid, Oid userid,
Bitmapset *modifiedCols,
@@ -97,7 +97,6 @@ static char *ExecBuildSlotValueDescription(Oid reloid,
int maxfieldlen);
static void EvalPlanQualStart(EPQState *epqstate, EState *parentestate,
Plan *planTree);
-
/*
* Note that GetUpdatedColumns() also exists in commands/trigger.c. There does
* not appear to be any good header to put it into, given the structures that
@@ -340,6 +339,12 @@ standard_ExecutorRun(QueryDesc *queryDesc,
* run plan
*/
if (!ScanDirectionIsNoMovement(direction))
+ {
+ if (queryDesc->execute_once)
+ elog(ERROR, "query is called more than once for the same query-descriptor %s", queryDesc->sourceText);
+ if (dest->mydest == DestSPI || dest->mydest == DestSQLFunction || count == 0)
+ queryDesc->execute_once = true;
+
ExecutePlan(estate,
queryDesc->planstate,
queryDesc->plannedstmt->parallelModeNeeded,
@@ -347,7 +352,9 @@ standard_ExecutorRun(QueryDesc *queryDesc,
sendTuples,
count,
direction,
- dest);
+ dest,
+ queryDesc->execute_once);
+ }
/*
* shutdown tuple receiver, if we started it
@@ -1570,7 +1577,8 @@ ExecutePlan(EState *estate,
bool sendTuples,
uint64 numberTuples,
ScanDirection direction,
- DestReceiver *dest)
+ DestReceiver *dest,
+ bool execute_once)
{
TupleTableSlot *slot;
uint64 current_tuple_count;
@@ -1589,9 +1597,11 @@ ExecutePlan(EState *estate,
* If a tuple count was supplied, we must force the plan to run without
* parallelism, because we might exit early. Also disable parallelism
* when writing into a relation, because no database changes are allowed
- * in parallel mode.
+ * in parallel mode. To enable parallelism for queries coming from SQL
+ * or other PL functions, allow parallelism if the planner considers
+ * it safe and those are coming from queryDesc which will execute only once.
*/
- if (numberTuples || dest->mydest == DestIntoRel)
+ if (!execute_once || dest->mydest == DestIntoRel)
use_parallel_mode = false;
if (use_parallel_mode)
@@ -1662,7 +1672,16 @@ ExecutePlan(EState *estate,
*/
current_tuple_count++;
if (numberTuples && numberTuples == current_tuple_count)
+ {
+ /*
+ * For the queries coming from SQL or PL functions, this condition
+ * will be satisfied for the first tuple and since we enabled
+ * parallel workers for it, a proper shutdown of the workers would
+ * be required.
+ */
+ (void) ExecShutdownNode(planstate);
break;
+ }
}
if (use_parallel_mode)
diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c
index e64ea2ed76..7737bf5041 100644
--- a/src/backend/tcop/pquery.c
+++ b/src/backend/tcop/pquery.c
@@ -87,6 +87,7 @@ CreateQueryDesc(PlannedStmt *plannedstmt,
qd->estate = NULL;
qd->planstate = NULL;
qd->totaltime = NULL;
+ qd->execute_once = false;
return qd;
}
diff --git a/src/include/executor/execdesc.h b/src/include/executor/execdesc.h
index c99ea81815..062f47fb76 100644
--- a/src/include/executor/execdesc.h
+++ b/src/include/executor/execdesc.h
@@ -49,6 +49,7 @@ typedef struct QueryDesc
/* This is always set NULL by the core system, but plugins can change it */
struct Instrumentation *totaltime; /* total time spent in ExecutorRun */
+ bool execute_once;
} QueryDesc;
/* in pquery.c */