pl_parallel_v1.patch
application/octet-stream
Filename: pl_parallel_v1.patch
Type: application/octet-stream
Part: 0
Patch
Format: unified
Series: patch v1
| File | + | − |
|---|---|---|
| src/backend/executor/execMain.c | 25 | 0 |
| src/backend/executor/spi.c | 6 | 1 |
| src/pl/plpgsql/src/pl_exec.c | 27 | 7 |
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index a666391..fc5c82f 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -1596,6 +1596,22 @@ ExecutePlan(EState *estate,
EnterParallelMode();
/*
+ * For SQL or other PL functions, the supplied numberTuples is always
+ * one, thus, upper condition restricts parallelism for the queries
+ * coming from these functions. To enable such parallelism, we ignore the
+ * numberTuples check and identify if the planner considers it safe to use
+ * parallelism for this query and it is coming only from PL or SQL
+ * functions.
+ */
+
+ else if (estate->es_plannedstmt->parallelModeNeeded &&
+ (dest->mydest == DestSPI || dest->mydest == DestSQLFunction))
+ {
+ use_parallel_mode = true;
+ EnterParallelMode();
+ }
+
+ /*
* Loop until we've processed the proper number of tuples from the plan.
*/
for (;;)
@@ -1660,7 +1676,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/executor/spi.c b/src/backend/executor/spi.c
index 55f97b1..45114d2 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -314,7 +314,12 @@ SPI_execute(const char *src, bool read_only, long tcount)
memset(&plan, 0, sizeof(_SPI_plan));
plan.magic = _SPI_PLAN_MAGIC;
- plan.cursor_options = 0;
+
+ /* Allow parallelism if the query is read-only */
+ if(read_only)
+ plan.cursor_options = CURSOR_OPT_PARALLEL_OK;
+ else
+ plan.cursor_options = 0;
_SPI_prepare_oneshot_plan(src, &plan);
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index 6fc3db0..27c9e47 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -3625,7 +3625,12 @@ exec_stmt_execsql(PLpgSQL_execstate *estate,
{
ListCell *l;
- exec_prepare_plan(estate, expr, 0);
+ /* Allow parallelism if the function is not trigger type. */
+ if (estate->func->fn_is_trigger == PLPGSQL_NOT_TRIGGER)
+ exec_prepare_plan(estate, expr, CURSOR_OPT_PARALLEL_OK);
+ else
+ exec_prepare_plan(estate, expr, 0);
+
stmt->mod_stmt = false;
foreach(l, SPI_plan_get_plan_sources(expr->plan))
{
@@ -3869,8 +3874,13 @@ exec_stmt_dynexecute(PLpgSQL_execstate *estate,
estate->readonly_func, 0);
}
else
- exec_res = SPI_execute(querystr, estate->readonly_func, 0);
-
+ {
+ /* Allow parallelism if the function is not trigger type. */
+ if (estate->func->fn_is_trigger == PLPGSQL_NOT_TRIGGER)
+ exec_res = SPI_execute(querystr, estate->readonly_func, CURSOR_OPT_PARALLEL_OK);
+ else
+ exec_res = SPI_execute(querystr, estate->readonly_func, 0);
+ }
switch (exec_res)
{
case SPI_OK_SELECT:
@@ -5172,8 +5182,13 @@ exec_eval_expr(PLpgSQL_execstate *estate,
* If first time through, create a plan for this expression.
*/
if (expr->plan == NULL)
- exec_prepare_plan(estate, expr, 0);
-
+ {
+ /* Allow parallelism is the function is not trigger type. */
+ if (estate->func->fn_is_trigger == PLPGSQL_NOT_TRIGGER)
+ exec_prepare_plan(estate, expr, CURSOR_OPT_PARALLEL_OK);
+ else
+ exec_prepare_plan(estate, expr, 0);
+ }
/*
* If this is a simple expression, bypass SPI and use the executor
* directly
@@ -5183,9 +5198,14 @@ exec_eval_expr(PLpgSQL_execstate *estate,
return result;
/*
- * Else do it the hard way via exec_run_select
+ * Else do it the hard way via exec_run_select. Enable parallelism
+ * if function is not trigger type.
*/
- rc = exec_run_select(estate, expr, 2, NULL, false);
+ if (estate->func->fn_is_trigger == PLPGSQL_NOT_TRIGGER)
+ rc = exec_run_select(estate, expr, 2, NULL, true);
+ else
+ rc = exec_run_select(estate, expr, 2, NULL, false);
+
if (rc != SPI_OK_SELECT)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),