summaryrefslogtreecommitdiff
path: root/src/backend/commands
diff options
context:
space:
mode:
authorRobert Haas2015-09-16 19:38:47 +0000
committerRobert Haas2015-09-16 19:38:47 +0000
commit7aea8e4f2daa4b39ca9d1309a0c4aadb0f7ed81b (patch)
treef92032ada7ea070c55e6173bdb70550027a4dc46 /src/backend/commands
parentb44d92b67b65a76f92448b5a282aae72820ac676 (diff)
Determine whether it's safe to attempt a parallel plan for a query.
Commit 924bcf4f16d54c55310b28f77686608684734f42 introduced a framework for parallel computation in PostgreSQL that makes most but not all built-in functions safe to execute in parallel mode. In order to have parallel query, we'll need to be able to determine whether that query contains functions (either built-in or user-defined) that cannot be safely executed in parallel mode. This requires those functions to be labeled, so this patch introduces an infrastructure for that. Some functions currently labeled as safe may need to be revised depending on how pending issues related to heavyweight locking under paralllelism are resolved. Parallel plans can't be used except for the case where the query will run to completion. If portal execution were suspended, the parallel mode restrictions would need to remain in effect during that time, but that might make other queries fail. Therefore, this patch introduces a framework that enables consideration of parallel plans only when it is known that the plan will be run to completion. This probably needs some refinement; for example, at bind time, we do not know whether a query run via the extended protocol will be execution to completion or run with a limited fetch count. Having the client indicate its intentions at bind time would constitute a wire protocol break. Some contexts in which parallel mode would be safe are not adjusted by this patch; the default is not to try parallel plans except from call sites that have been updated to say that such plans are OK. This commit doesn't introduce any parallel paths or plans; it just provides a way to determine whether they could potentially be used. I'm committing it on the theory that the remaining parallel sequential scan patches will also get committed to this release, hopefully in the not-too-distant future. Robert Haas and Amit Kapila. Reviewed (in earlier versions) by Noah Misch.
Diffstat (limited to 'src/backend/commands')
-rw-r--r--src/backend/commands/explain.c2
-rw-r--r--src/backend/commands/extension.c2
-rw-r--r--src/backend/commands/functioncmds.c51
-rw-r--r--src/backend/commands/proclang.c3
-rw-r--r--src/backend/commands/typecmds.c1
5 files changed, 52 insertions, 7 deletions
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 5d06fa4ea65..4f32400011f 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -348,7 +348,7 @@ ExplainOneQuery(Query *query, IntoClause *into, ExplainState *es,
INSTR_TIME_SET_CURRENT(planstart);
/* plan the query */
- plan = pg_plan_query(query, 0, params);
+ plan = pg_plan_query(query, CURSOR_OPT_PARALLEL_OK, params);
INSTR_TIME_SET_CURRENT(planduration);
INSTR_TIME_SUBTRACT(planduration, planstart);
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index 2b1dcd0d19c..6b92bdc5e0e 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -707,7 +707,7 @@ execute_sql_string(const char *sql, const char *filename)
sql,
NULL,
0);
- stmt_list = pg_plan_queries(stmt_list, 0, NULL);
+ stmt_list = pg_plan_queries(stmt_list, CURSOR_OPT_PARALLEL_OK, NULL);
foreach(lc2, stmt_list)
{
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index dbbb2d3f88a..efc3aa4b9cc 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -465,7 +465,8 @@ compute_common_attribute(DefElem *defel,
DefElem **leakproof_item,
List **set_items,
DefElem **cost_item,
- DefElem **rows_item)
+ DefElem **rows_item,
+ DefElem **parallel_item)
{
if (strcmp(defel->defname, "volatility") == 0)
{
@@ -513,6 +514,13 @@ compute_common_attribute(DefElem *defel,
*rows_item = defel;
}
+ else if (strcmp(defel->defname, "parallel") == 0)
+ {
+ if (*parallel_item)
+ goto duplicate_error;
+
+ *parallel_item = defel;
+ }
else
return false;
@@ -544,6 +552,27 @@ interpret_func_volatility(DefElem *defel)
}
}
+static char
+interpret_func_parallel(DefElem *defel)
+{
+ char *str = strVal(defel->arg);
+
+ if (strcmp(str, "safe") == 0)
+ return PROPARALLEL_SAFE;
+ else if (strcmp(str, "unsafe") == 0)
+ return PROPARALLEL_UNSAFE;
+ else if (strcmp(str, "restricted") == 0)
+ return PROPARALLEL_RESTRICTED;
+ else
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("parallel option \"%s\" not recognized",
+ str)));
+ return PROPARALLEL_UNSAFE; /* keep compiler quiet */
+ }
+}
+
/*
* Update a proconfig value according to a list of VariableSetStmt items.
*
@@ -592,7 +621,8 @@ compute_attributes_sql_style(List *options,
bool *leakproof_p,
ArrayType **proconfig,
float4 *procost,
- float4 *prorows)
+ float4 *prorows,
+ char *parallel_p)
{
ListCell *option;
DefElem *as_item = NULL;
@@ -606,6 +636,7 @@ compute_attributes_sql_style(List *options,
List *set_items = NIL;
DefElem *cost_item = NULL;
DefElem *rows_item = NULL;
+ DefElem *parallel_item = NULL;
foreach(option, options)
{
@@ -650,7 +681,8 @@ compute_attributes_sql_style(List *options,
&leakproof_item,
&set_items,
&cost_item,
- &rows_item))
+ &rows_item,
+ &parallel_item))
{
/* recognized common option */
continue;
@@ -712,6 +744,8 @@ compute_attributes_sql_style(List *options,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("ROWS must be positive")));
}
+ if (parallel_item)
+ *parallel_p = interpret_func_parallel(parallel_item);
}
@@ -858,6 +892,7 @@ CreateFunction(CreateFunctionStmt *stmt, const char *queryString)
HeapTuple languageTuple;
Form_pg_language languageStruct;
List *as_clause;
+ char parallel;
/* Convert list of names to a name and namespace */
namespaceId = QualifiedNameGetCreationNamespace(stmt->funcname,
@@ -878,13 +913,14 @@ CreateFunction(CreateFunctionStmt *stmt, const char *queryString)
proconfig = NULL;
procost = -1; /* indicates not set */
prorows = -1; /* indicates not set */
+ parallel = PROPARALLEL_UNSAFE;
/* override attributes from explicit list */
compute_attributes_sql_style(stmt->options,
&as_clause, &language, &transformDefElem,
&isWindowFunc, &volatility,
&isStrict, &security, &isLeakProof,
- &proconfig, &procost, &prorows);
+ &proconfig, &procost, &prorows, &parallel);
/* Look up the language and validate permissions */
languageTuple = SearchSysCache1(LANGNAME, PointerGetDatum(language));
@@ -1061,6 +1097,7 @@ CreateFunction(CreateFunctionStmt *stmt, const char *queryString)
isLeakProof,
isStrict,
volatility,
+ parallel,
parameterTypes,
PointerGetDatum(allParameterTypes),
PointerGetDatum(parameterModes),
@@ -1141,6 +1178,7 @@ AlterFunction(AlterFunctionStmt *stmt)
List *set_items = NIL;
DefElem *cost_item = NULL;
DefElem *rows_item = NULL;
+ DefElem *parallel_item = NULL;
ObjectAddress address;
rel = heap_open(ProcedureRelationId, RowExclusiveLock);
@@ -1178,7 +1216,8 @@ AlterFunction(AlterFunctionStmt *stmt)
&leakproof_item,
&set_items,
&cost_item,
- &rows_item) == false)
+ &rows_item,
+ &parallel_item) == false)
elog(ERROR, "option \"%s\" not recognized", defel->defname);
}
@@ -1250,6 +1289,8 @@ AlterFunction(AlterFunctionStmt *stmt)
tup = heap_modify_tuple(tup, RelationGetDescr(rel),
repl_val, repl_null, repl_repl);
}
+ if (parallel_item)
+ procForm->proparallel = interpret_func_parallel(parallel_item);
/* Do the update */
simple_heap_update(rel, &tup->t_self, tup);
diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c
index 3995a575e4e..939b147c1d6 100644
--- a/src/backend/commands/proclang.c
+++ b/src/backend/commands/proclang.c
@@ -135,6 +135,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
false, /* isLeakProof */
false, /* isStrict */
PROVOLATILE_VOLATILE,
+ PROPARALLEL_UNSAFE,
buildoidvector(funcargtypes, 0),
PointerGetDatum(NULL),
PointerGetDatum(NULL),
@@ -174,6 +175,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
false, /* isLeakProof */
true, /* isStrict */
PROVOLATILE_VOLATILE,
+ PROPARALLEL_UNSAFE,
buildoidvector(funcargtypes, 1),
PointerGetDatum(NULL),
PointerGetDatum(NULL),
@@ -216,6 +218,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
false, /* isLeakProof */
true, /* isStrict */
PROVOLATILE_VOLATILE,
+ PROPARALLEL_UNSAFE,
buildoidvector(funcargtypes, 1),
PointerGetDatum(NULL),
PointerGetDatum(NULL),
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index de913538910..d2b3f2297b2 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -1611,6 +1611,7 @@ makeRangeConstructors(const char *name, Oid namespace,
false, /* leakproof */
false, /* isStrict */
PROVOLATILE_IMMUTABLE, /* volatility */
+ PROPARALLEL_SAFE, /* parallel safety */
constructorArgTypesVector, /* parameterTypes */
PointerGetDatum(NULL), /* allParameterTypes */
PointerGetDatum(NULL), /* parameterModes */