aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/executor/execQual.c25
-rw-r--r--src/backend/utils/adt/domains.c10
2 files changed, 28 insertions, 7 deletions
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index a6c9b6a66b4..169134d45c6 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -2960,12 +2960,18 @@ ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,
if (caseExpr->arg)
{
+ Datum arg_value;
bool arg_isNull;
- econtext->caseValue_datum = ExecEvalExpr(caseExpr->arg,
- econtext,
- &arg_isNull,
- NULL);
+ arg_value = ExecEvalExpr(caseExpr->arg,
+ econtext,
+ &arg_isNull,
+ NULL);
+ /* Since caseValue_datum may be read multiple times, force to R/O */
+ econtext->caseValue_datum =
+ MakeExpandedObjectReadOnly(arg_value,
+ arg_isNull,
+ caseExpr->argtyplen);
econtext->caseValue_isNull = arg_isNull;
}
@@ -4026,11 +4032,18 @@ ExecEvalCoerceToDomain(CoerceToDomainState *cstate, ExprContext *econtext,
* nodes. We must save and restore prior setting of
* econtext's domainValue fields, in case this node is
* itself within a check expression for another domain.
+ *
+ * Also, if we are working with a read-write expanded
+ * datum, be sure that what we pass to CHECK expressions
+ * is a read-only pointer; else called functions might
+ * modify or even delete the expanded object.
*/
save_datum = econtext->domainValue_datum;
save_isNull = econtext->domainValue_isNull;
- econtext->domainValue_datum = result;
+ econtext->domainValue_datum =
+ MakeExpandedObjectReadOnly(result, *isNull,
+ cstate->constraint_ref->tcache->typlen);
econtext->domainValue_isNull = *isNull;
conResult = ExecEvalExpr(con->check_expr,
@@ -4858,6 +4871,8 @@ ExecInitExpr(Expr *node, PlanState *parent)
}
cstate->args = outlist;
cstate->defresult = ExecInitExpr(caseexpr->defresult, parent);
+ if (caseexpr->arg)
+ cstate->argtyplen = get_typlen(exprType((Node *) caseexpr->arg));
state = (ExprState *) cstate;
}
break;
diff --git a/src/backend/utils/adt/domains.c b/src/backend/utils/adt/domains.c
index ac8c25266e0..9cf98a8f6b4 100644
--- a/src/backend/utils/adt/domains.c
+++ b/src/backend/utils/adt/domains.c
@@ -35,6 +35,7 @@
#include "executor/executor.h"
#include "lib/stringinfo.h"
#include "utils/builtins.h"
+#include "utils/expandeddatum.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
#include "utils/typcache.h"
@@ -157,9 +158,14 @@ domain_check_input(Datum value, bool isnull, DomainIOData *my_extra)
* Set up value to be returned by CoerceToDomainValue
* nodes. Unlike ExecEvalCoerceToDomain, this econtext
* couldn't be shared with anything else, so no need to
- * save and restore fields.
+ * save and restore fields. But we do need to protect the
+ * passed-in value against being changed by called
+ * functions. (It couldn't be a R/W expanded object for
+ * most uses, but that seems possible for domain_check().)
*/
- econtext->domainValue_datum = value;
+ econtext->domainValue_datum =
+ MakeExpandedObjectReadOnly(value, isnull,
+ my_extra->constraint_ref.tcache->typlen);
econtext->domainValue_isNull = isnull;
conResult = ExecEvalExprSwitchContext(con->check_expr,