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;
