diff options
-rw-r--r-- | src/backend/executor/execQual.c | 33 | ||||
-rw-r--r-- | src/test/regress/expected/subselect.out | 18 | ||||
-rw-r--r-- | src/test/regress/sql/subselect.sql | 10 |
3 files changed, 47 insertions, 14 deletions
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) @@ -926,6 +917,20 @@ ExecEvalWholeRowFast(WholeRowVarExprState *wrvstate, ExprContext *econtext, 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. */ dtuple = DatumGetHeapTupleHeader(ExecFetchSlotTupleDatum(slot)); 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 @@ -775,6 +775,24 @@ select * from int4_tbl o where (f1, f1) in (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 @@ -433,6 +433,16 @@ 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 -- |