diff options
Diffstat (limited to 'src/backend/executor/execQual.c')
-rw-r--r-- | src/backend/executor/execQual.c | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c index c0ca58bbb4d..01e04d3b14e 100644 --- a/src/backend/executor/execQual.c +++ b/src/backend/executor/execQual.c @@ -5350,15 +5350,24 @@ ExecCleanTargetListLength(List *targetlist) * of *isDone = ExprMultipleResult signifies a set element, and a return * of *isDone = ExprEndResult signifies end of the set of tuple. * We assume that *isDone has been initialized to ExprSingleResult by caller. + * + * Since fields of the result tuple might be multiply referenced in higher + * plan nodes, we have to force any read/write expanded values to read-only + * status. It's a bit annoying to have to do that for every projected + * expression; in the future, consider teaching the planner to detect + * actually-multiply-referenced Vars and insert an expression node that + * would do that only where really required. */ static bool ExecTargetList(List *targetlist, + TupleDesc tupdesc, ExprContext *econtext, Datum *values, bool *isnull, ExprDoneCond *itemIsDone, ExprDoneCond *isDone) { + Form_pg_attribute *att = tupdesc->attrs; MemoryContext oldContext; ListCell *tl; bool haveDoneSets; @@ -5384,6 +5393,10 @@ ExecTargetList(List *targetlist, &isnull[resind], &itemIsDone[resind]); + values[resind] = MakeExpandedObjectReadOnly(values[resind], + isnull[resind], + att[resind]->attlen); + if (itemIsDone[resind] != ExprSingleResult) { /* We have a set-valued expression in the tlist */ @@ -5437,6 +5450,10 @@ ExecTargetList(List *targetlist, &isnull[resind], &itemIsDone[resind]); + values[resind] = MakeExpandedObjectReadOnly(values[resind], + isnull[resind], + att[resind]->attlen); + if (itemIsDone[resind] == ExprEndResult) { /* @@ -5470,6 +5487,7 @@ ExecTargetList(List *targetlist, econtext, &isnull[resind], &itemIsDone[resind]); + /* no need for MakeExpandedObjectReadOnly */ } } @@ -5595,6 +5613,7 @@ ExecProject(ProjectionInfo *projInfo, ExprDoneCond *isDone) if (projInfo->pi_targetlist) { if (!ExecTargetList(projInfo->pi_targetlist, + slot->tts_tupleDescriptor, econtext, slot->tts_values, slot->tts_isnull, |