diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c index bc79e3aa00c..7cfa63f37dc 100644 --- a/src/backend/executor/execQual.c +++ b/src/backend/executor/execQual.c @@ -712,7 +712,6 @@ ExecEvalWholeRowVar(WholeRowVarExprState *wrvstate, ExprContext *econtext, { Var *variable = (Var *) wrvstate->xprstate.expr; TupleTableSlot *slot; - TupleDesc slot_tupdesc; bool needslow = false; if (isDone) @@ -804,25 +803,14 @@ ExecEvalWholeRowVar(WholeRowVarExprState *wrvstate, ExprContext *econtext, if (wrvstate->wrv_junkFilter != NULL) slot = ExecFilterJunk(wrvstate->wrv_junkFilter, slot); - slot_tupdesc = slot->tts_tupleDescriptor; - /* - * If it's a RECORD Var, we'll use the slot's type ID info. It's likely - * that the slot's type is also RECORD; if so, make sure it's been - * "blessed", so that the Datum can be interpreted later. - * * If the Var identifies a named composite type, we must check that the * actual tuple type is compatible with it. */ - if (variable->vartype == RECORDOID) - { - if (slot_tupdesc->tdtypeid == RECORDOID && - slot_tupdesc->tdtypmod < 0) - assign_record_type_typmod(slot_tupdesc); - } - else + if (variable->vartype != RECORDOID) { TupleDesc var_tupdesc; + TupleDesc slot_tupdesc; int i; /* @@ -839,6 +827,8 @@ ExecEvalWholeRowVar(WholeRowVarExprState *wrvstate, ExprContext *econtext, */ var_tupdesc = lookup_rowtype_tupdesc(variable->vartype, -1); + slot_tupdesc = slot->tts_tupleDescriptor; + if (var_tupdesc->natts != slot_tupdesc->natts) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), @@ -896,6 +886,7 @@ ExecEvalWholeRowFast(WholeRowVarExprState *wrvstate, ExprContext *econtext, { Var *variable = (Var *) wrvstate->xprstate.expr; TupleTableSlot *slot; + TupleDesc slot_tupdesc; HeapTupleHeader dtuple; if (isDone) @@ -925,6 +916,20 @@ ExecEvalWholeRowFast(WholeRowVarExprState *wrvstate, ExprContext *econtext, if (wrvstate->wrv_junkFilter != NULL) slot = ExecFilterJunk(wrvstate->wrv_junkFilter, slot); + /* + * If it's a RECORD Var, we'll use the slot's type ID info. It's likely + * that the slot's type is also RECORD; if so, make sure it's been + * "blessed", so that the Datum can be interpreted later. (Note: we must + * do this here, not in ExecEvalWholeRowVar, because some plan trees may + * return different slots at different times. We have to be ready to + * bless additional slots during the run.) + */ + slot_tupdesc = slot->tts_tupleDescriptor; + if (variable->vartype == RECORDOID && + slot_tupdesc->tdtypeid == RECORDOID && + slot_tupdesc->tdtypmod < 0) + assign_record_type_typmod(slot_tupdesc); + /* * Copy the slot tuple and make sure any toasted fields get detoasted. */ diff --git a/src/test/regress/expected/subselect.out b/src/test/regress/expected/subselect.out index d85a7170f30..01c91308f33 100644 --- a/src/test/regress/expected/subselect.out +++ b/src/test/regress/expected/subselect.out @@ -774,6 +774,24 @@ select * from int4_tbl o where (f1, f1) in 0 (1 row) +-- +-- check for over-optimization of whole-row Var referencing an Append plan +-- +select (select q from + (select 1,2,3 where f1 > 0 + union all + select 4,5,6.0 where f1 <= 0 + ) q ) +from int4_tbl; + q +----------- + (4,5,6.0) + (1,2,3) + (4,5,6.0) + (1,2,3) + (4,5,6.0) +(5 rows) + -- -- Check that volatile quals aren't pushed down past a DISTINCT: -- nextval() should not be called more than the nominal number of times diff --git a/src/test/regress/sql/subselect.sql b/src/test/regress/sql/subselect.sql index c3b47734887..56707e26bbf 100644 --- a/src/test/regress/sql/subselect.sql +++ b/src/test/regress/sql/subselect.sql @@ -432,6 +432,16 @@ select * from int4_tbl o where (f1, f1) in select * from int4_tbl o where (f1, f1) in (select f1, generate_series(1,2) / 10 g from int4_tbl i group by f1); +-- +-- check for over-optimization of whole-row Var referencing an Append plan +-- +select (select q from + (select 1,2,3 where f1 > 0 + union all + select 4,5,6.0 where f1 <= 0 + ) q ) +from int4_tbl; + -- -- Check that volatile quals aren't pushed down past a DISTINCT: -- nextval() should not be called more than the nominal number of times