Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitc45841f

Browse files
committed
Fix bug with whole-row references to append subplans.
ExecEvalWholeRowVar incorrectly supposed that it could "bless" the sourceTupleTableSlot just once per query. But if the input is coming from anAppend (or, perhaps, other cases?) more than one slot might be returnedover the query run. This led to "record type has not been registered"errors when a composite datum was extracted from a non-blessed slot.This bug has been there a long time; I guess it escaped notice because whendealing with subqueries the planner tends to expand whole-row Vars intoRowExprs, which don't have the same problem. It is possible to triggerthe problem in all active branches, though, as illustrated by the addedregression test.
1 parentfa21a76 commitc45841f

File tree

3 files changed

+47
-14
lines changed

3 files changed

+47
-14
lines changed

‎src/backend/executor/execQual.c

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -706,7 +706,6 @@ ExecEvalWholeRowVar(WholeRowVarExprState *wrvstate, ExprContext *econtext,
706706
{
707707
Var*variable= (Var*)wrvstate->xprstate.expr;
708708
TupleTableSlot*slot;
709-
TupleDescslot_tupdesc;
710709
boolneedslow= false;
711710

712711
if (isDone)
@@ -796,25 +795,14 @@ ExecEvalWholeRowVar(WholeRowVarExprState *wrvstate, ExprContext *econtext,
796795
if (wrvstate->wrv_junkFilter!=NULL)
797796
slot=ExecFilterJunk(wrvstate->wrv_junkFilter,slot);
798797

799-
slot_tupdesc=slot->tts_tupleDescriptor;
800-
801798
/*
802-
* If it's a RECORD Var, we'll use the slot's type ID info. It's likely
803-
* that the slot's type is also RECORD; if so, make sure it's been
804-
* "blessed", so that the Datum can be interpreted later.
805-
*
806799
* If the Var identifies a named composite type, we must check that the
807800
* actual tuple type is compatible with it.
808801
*/
809-
if (variable->vartype==RECORDOID)
810-
{
811-
if (slot_tupdesc->tdtypeid==RECORDOID&&
812-
slot_tupdesc->tdtypmod<0)
813-
assign_record_type_typmod(slot_tupdesc);
814-
}
815-
else
802+
if (variable->vartype!=RECORDOID)
816803
{
817804
TupleDescvar_tupdesc;
805+
TupleDescslot_tupdesc;
818806
inti;
819807

820808
/*
@@ -831,6 +819,8 @@ ExecEvalWholeRowVar(WholeRowVarExprState *wrvstate, ExprContext *econtext,
831819
*/
832820
var_tupdesc=lookup_rowtype_tupdesc(variable->vartype,-1);
833821

822+
slot_tupdesc=slot->tts_tupleDescriptor;
823+
834824
if (var_tupdesc->natts!=slot_tupdesc->natts)
835825
ereport(ERROR,
836826
(errcode(ERRCODE_DATATYPE_MISMATCH),
@@ -888,6 +878,7 @@ ExecEvalWholeRowFast(WholeRowVarExprState *wrvstate, ExprContext *econtext,
888878
{
889879
Var*variable= (Var*)wrvstate->xprstate.expr;
890880
TupleTableSlot*slot;
881+
TupleDescslot_tupdesc;
891882
HeapTupleHeaderdtuple;
892883

893884
if (isDone)
@@ -915,6 +906,20 @@ ExecEvalWholeRowFast(WholeRowVarExprState *wrvstate, ExprContext *econtext,
915906
if (wrvstate->wrv_junkFilter!=NULL)
916907
slot=ExecFilterJunk(wrvstate->wrv_junkFilter,slot);
917908

909+
/*
910+
* If it's a RECORD Var, we'll use the slot's type ID info. It's likely
911+
* that the slot's type is also RECORD; if so, make sure it's been
912+
* "blessed", so that the Datum can be interpreted later. (Note: we must
913+
* do this here, not in ExecEvalWholeRowVar, because some plan trees may
914+
* return different slots at different times. We have to be ready to
915+
* bless additional slots during the run.)
916+
*/
917+
slot_tupdesc=slot->tts_tupleDescriptor;
918+
if (variable->vartype==RECORDOID&&
919+
slot_tupdesc->tdtypeid==RECORDOID&&
920+
slot_tupdesc->tdtypmod<0)
921+
assign_record_type_typmod(slot_tupdesc);
922+
918923
/*
919924
* Copy the slot tuple and make sure any toasted fields get detoasted.
920925
*/

‎src/test/regress/expected/subselect.out

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -775,3 +775,21 @@ select * from int4_tbl o where (f1, f1) in
775775
(1 row)
776776

777777
reset enable_hashjoin;
778+
--
779+
-- check for over-optimization of whole-row Var referencing an Append plan
780+
--
781+
select (select q from
782+
(select 1,2,3 where f1 > 0
783+
union all
784+
select 4,5,6.0 where f1 <= 0
785+
) q )
786+
from int4_tbl;
787+
?column?
788+
-----------
789+
(4,5,6.0)
790+
(1,2,3)
791+
(4,5,6.0)
792+
(1,2,3)
793+
(4,5,6.0)
794+
(5 rows)
795+

‎src/test/regress/sql/subselect.sql

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,3 +433,13 @@ select * from int4_tbl o where (f1, f1) in
433433
select*from int4_tbl owhere (f1, f1)in
434434
(select f1, generate_series(1,2)/10 gfrom int4_tbl igroup by f1);
435435
reset enable_hashjoin;
436+
437+
--
438+
-- check for over-optimization of whole-row Var referencing an Append plan
439+
--
440+
select (select qfrom
441+
(select1,2,3where f1>0
442+
union all
443+
select4,5,6.0where f1<=0
444+
) q )
445+
from int4_tbl;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp