aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/util/clauses.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/util/clauses.c')
-rw-r--r--src/backend/optimizer/util/clauses.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index e1147c431e6..e381ae512a2 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -28,6 +28,7 @@
#include "catalog/pg_type.h"
#include "executor/executor.h"
#include "executor/functions.h"
+#include "executor/execExpr.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
@@ -52,6 +53,7 @@
#include "utils/fmgroids.h"
#include "utils/json.h"
#include "utils/jsonb.h"
+#include "utils/jsonpath.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/syscache.h"
@@ -405,6 +407,24 @@ contain_mutable_functions_walker(Node *node, void *context)
/* Check all subnodes */
}
+ if (IsA(node, JsonExpr))
+ {
+ JsonExpr *jexpr = castNode(JsonExpr, node);
+ Const *cnst;
+
+ if (!IsA(jexpr->path_spec, Const))
+ return true;
+
+ cnst = castNode(Const, jexpr->path_spec);
+
+ Assert(cnst->consttype == JSONPATHOID);
+ if (cnst->constisnull)
+ return false;
+
+ return jspIsMutable(DatumGetJsonPathP(cnst->constvalue),
+ jexpr->passing_names, jexpr->passing_values);
+ }
+
if (IsA(node, SQLValueFunction))
{
/* all variants of SQLValueFunction are stable */
@@ -876,6 +896,18 @@ max_parallel_hazard_walker(Node *node, max_parallel_hazard_context *context)
context, 0);
}
+ /* JsonExpr is parallel-unsafe if subtransactions can be used. */
+ else if (IsA(node, JsonExpr))
+ {
+ JsonExpr *jsexpr = (JsonExpr *) node;
+
+ if (ExecEvalJsonNeedsSubTransaction(jsexpr, NULL))
+ {
+ context->max_hazard = PROPARALLEL_UNSAFE;
+ return true;
+ }
+ }
+
/* Recurse to check arguments */
return expression_tree_walker(node,
max_parallel_hazard_walker,