fix-rw-objects-in-domains-and-CASE.patch
text/x-diff
Filename: fix-rw-objects-in-domains-and-CASE.patch
Type: text/x-diff
Part: 0
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/backend/executor/execQual.c | 0 | 0 |
| src/backend/utils/adt/domains.c | 0 | 0 |
| src/include/nodes/execnodes.h | 0 | 0 |
| src/include/utils/typcache.h | 0 | 0 |
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index 743e7d6..ab09691 100644
*** a/src/backend/executor/execQual.c
--- b/src/backend/executor/execQual.c
*************** ExecEvalCase(CaseExprState *caseExpr, Ex
*** 2992,3003 ****
if (caseExpr->arg)
{
bool arg_isNull;
! econtext->caseValue_datum = ExecEvalExpr(caseExpr->arg,
! econtext,
! &arg_isNull,
! NULL);
econtext->caseValue_isNull = arg_isNull;
}
--- 2992,3009 ----
if (caseExpr->arg)
{
+ Datum arg_value;
bool arg_isNull;
! 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;
}
*************** ExecEvalCoerceToDomain(CoerceToDomainSta
*** 4127,4137 ****
* 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.
*/
save_datum = econtext->domainValue_datum;
save_isNull = econtext->domainValue_isNull;
! econtext->domainValue_datum = result;
econtext->domainValue_isNull = *isNull;
conResult = ExecEvalExpr(con->check_expr,
--- 4133,4150 ----
* 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 =
! MakeExpandedObjectReadOnly(result, *isNull,
! cstate->constraint_ref->tcache->typlen);
econtext->domainValue_isNull = *isNull;
conResult = ExecEvalExpr(con->check_expr,
*************** ExecInitExpr(Expr *node, PlanState *pare
*** 4939,4944 ****
--- 4952,4959 ----
}
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 26bbbb5..1cd80ae 100644
*** a/src/backend/utils/adt/domains.c
--- b/src/backend/utils/adt/domains.c
***************
*** 35,40 ****
--- 35,41 ----
#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"
*************** domain_check_input(Datum value, bool isn
*** 166,174 ****
* 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.
*/
! econtext->domainValue_datum = value;
econtext->domainValue_isNull = isnull;
conResult = ExecEvalExprSwitchContext(con->check_expr,
--- 167,180 ----
* 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. 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 =
! MakeExpandedObjectReadOnly(value, isnull,
! my_extra->constraint_ref.tcache->typlen);
econtext->domainValue_isNull = isnull;
conResult = ExecEvalExprSwitchContext(con->check_expr,
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 5c3b868..cc0821b 100644
*** a/src/include/nodes/execnodes.h
--- b/src/include/nodes/execnodes.h
*************** typedef struct CaseExprState
*** 889,894 ****
--- 889,895 ----
ExprState *arg; /* implicit equality comparison argument */
List *args; /* the arguments (list of WHEN clauses) */
ExprState *defresult; /* the default result (ELSE clause) */
+ int16 argtyplen; /* if arg is provided, its typlen */
} CaseExprState;
/* ----------------
diff --git a/src/include/utils/typcache.h b/src/include/utils/typcache.h
index c72efcc..d187650 100644
*** a/src/include/utils/typcache.h
--- b/src/include/utils/typcache.h
*************** typedef struct DomainConstraintRef
*** 131,139 ****
{
List *constraints; /* list of DomainConstraintState nodes */
MemoryContext refctx; /* context holding DomainConstraintRef */
/* Management data --- treat these fields as private to typcache.c */
- TypeCacheEntry *tcache; /* owning typcache entry */
DomainConstraintCache *dcc; /* current constraints, or NULL if none */
MemoryContextCallback callback; /* used to release refcount when done */
} DomainConstraintRef;
--- 131,139 ----
{
List *constraints; /* list of DomainConstraintState nodes */
MemoryContext refctx; /* context holding DomainConstraintRef */
+ TypeCacheEntry *tcache; /* typcache entry for domain type */
/* Management data --- treat these fields as private to typcache.c */
DomainConstraintCache *dcc; /* current constraints, or NULL if none */
MemoryContextCallback callback; /* used to release refcount when done */
} DomainConstraintRef;