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

Commit68e4099

Browse files
committed
Extend whole-row Var evaluation to cope with the case that the sub-plan
generating the tuples has resjunk output columns. This is not possible forsimple table scans but can happen when evaluating a whole-row Var for a view.Per example from Patryk Kordylewski. The problem exists back to 8.0 butI'm not going to risk back-patching further than 8.2 because of the manychanges in this area.
1 parent42e9e26 commit68e4099

File tree

1 file changed

+76
-5
lines changed

1 file changed

+76
-5
lines changed

‎src/backend/executor/execQual.c

Lines changed: 76 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.220 2007/06/11 22:22:40 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.221 2007/08/31 18:33:40 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -68,6 +68,8 @@ static Datum ExecEvalScalarVar(ExprState *exprstate, ExprContext *econtext,
6868
bool*isNull,ExprDoneCond*isDone);
6969
staticDatumExecEvalWholeRowVar(ExprState*exprstate,ExprContext*econtext,
7070
bool*isNull,ExprDoneCond*isDone);
71+
staticDatumExecEvalWholeRowSlow(ExprState*exprstate,ExprContext*econtext,
72+
bool*isNull,ExprDoneCond*isDone);
7173
staticDatumExecEvalConst(ExprState*exprstate,ExprContext*econtext,
7274
bool*isNull,ExprDoneCond*isDone);
7375
staticDatumExecEvalParam(ExprState*exprstate,ExprContext*econtext,
@@ -438,7 +440,8 @@ ExecEvalAggref(AggrefExprState *aggref, ExprContext *econtext,
438440
*
439441
* Note: ExecEvalVar is executed only the first time through in a given plan;
440442
* it changes the ExprState's function pointer to pass control directly to
441-
* ExecEvalScalarVar or ExecEvalWholeRowVar after making one-time checks.
443+
* ExecEvalScalarVar, ExecEvalWholeRowVar, or ExecEvalWholeRowSlow after
444+
* making one-time checks.
442445
* ----------------------------------------------------------------
443446
*/
444447
staticDatum
@@ -544,6 +547,7 @@ ExecEvalVar(ExprState *exprstate, ExprContext *econtext,
544547
* the actual tuple type is compatible with it.
545548
*/
546549
TupleDescslot_tupdesc=slot->tts_tupleDescriptor;
550+
boolneedslow= false;
547551

548552
if (variable->vartype==RECORDOID)
549553
{
@@ -561,16 +565,26 @@ ExecEvalVar(ExprState *exprstate, ExprContext *econtext,
561565
* Also, we can ignore type mismatch on columns that are dropped
562566
* in the destination type, so long as the physical storage
563567
* matches. This is helpful in some cases involving out-of-date
564-
* cached plans.
568+
* cached plans. Also, we have to allow the case that the slot
569+
* has more columns than the Var's type, because we might be
570+
* looking at the output of a subplan that includes resjunk
571+
* columns. (XXX it would be nice to verify that the extra
572+
* columns are all marked resjunk, but we haven't got access to
573+
* the subplan targetlist here...) Resjunk columns should always
574+
* be at the end of a targetlist, so it's sufficient to ignore
575+
* them here; but we need to use ExecEvalWholeRowSlow to get
576+
* rid of them in the eventual output tuples.
565577
*/
566578
var_tupdesc=lookup_rowtype_tupdesc(variable->vartype,-1);
567579

568-
if (var_tupdesc->natts!=slot_tupdesc->natts)
580+
if (var_tupdesc->natts>slot_tupdesc->natts)
569581
ereport(ERROR,
570582
(errcode(ERRCODE_DATATYPE_MISMATCH),
571583
errmsg("table row type and query-specified row type do not match"),
572584
errdetail("Table row contains %d attributes, but query expects %d.",
573585
slot_tupdesc->natts,var_tupdesc->natts)));
586+
elseif (var_tupdesc->natts<slot_tupdesc->natts)
587+
needslow= true;
574588

575589
for (i=0;i<var_tupdesc->natts;i++)
576590
{
@@ -601,7 +615,10 @@ ExecEvalVar(ExprState *exprstate, ExprContext *econtext,
601615
}
602616

603617
/* Skip the checking on future executions of node */
604-
exprstate->evalfunc=ExecEvalWholeRowVar;
618+
if (needslow)
619+
exprstate->evalfunc=ExecEvalWholeRowSlow;
620+
else
621+
exprstate->evalfunc=ExecEvalWholeRowVar;
605622

606623
/* Fetch the value */
607624
returnExecEvalWholeRowVar(exprstate,econtext,isNull,isDone);
@@ -698,6 +715,60 @@ ExecEvalWholeRowVar(ExprState *exprstate, ExprContext *econtext,
698715
returnPointerGetDatum(dtuple);
699716
}
700717

718+
/* ----------------------------------------------------------------
719+
*ExecEvalWholeRowSlow
720+
*
721+
*Returns a Datum for a whole-row variable, in the "slow" case where
722+
*we can't just copy the subplan's output.
723+
* ----------------------------------------------------------------
724+
*/
725+
staticDatum
726+
ExecEvalWholeRowSlow(ExprState*exprstate,ExprContext*econtext,
727+
bool*isNull,ExprDoneCond*isDone)
728+
{
729+
Var*variable= (Var*)exprstate->expr;
730+
TupleTableSlot*slot=econtext->ecxt_scantuple;
731+
HeapTupletuple;
732+
TupleDescvar_tupdesc;
733+
HeapTupleHeaderdtuple;
734+
735+
if (isDone)
736+
*isDone=ExprSingleResult;
737+
*isNull= false;
738+
739+
/*
740+
* Currently, the only case handled here is stripping of trailing
741+
* resjunk fields, which we do in a slightly chintzy way by just
742+
* adjusting the tuple's natts header field. Possibly there will someday
743+
* be a need for more-extensive rearrangements, in which case it'd
744+
* be worth disassembling and reassembling the tuple (perhaps use a
745+
* JunkFilter for that?)
746+
*/
747+
Assert(variable->vartype!=RECORDOID);
748+
var_tupdesc=lookup_rowtype_tupdesc(variable->vartype,-1);
749+
750+
tuple=ExecFetchSlotTuple(slot);
751+
752+
/*
753+
* We have to make a copy of the tuple so we can safely insert the Datum
754+
* overhead fields, which are not set in on-disk tuples; not to mention
755+
* fooling with its natts field.
756+
*/
757+
dtuple= (HeapTupleHeader)palloc(tuple->t_len);
758+
memcpy((char*)dtuple, (char*)tuple->t_data,tuple->t_len);
759+
760+
HeapTupleHeaderSetDatumLength(dtuple,tuple->t_len);
761+
HeapTupleHeaderSetTypeId(dtuple,variable->vartype);
762+
HeapTupleHeaderSetTypMod(dtuple,variable->vartypmod);
763+
764+
Assert(HeapTupleHeaderGetNatts(dtuple) >=var_tupdesc->natts);
765+
HeapTupleHeaderSetNatts(dtuple,var_tupdesc->natts);
766+
767+
ReleaseTupleDesc(var_tupdesc);
768+
769+
returnPointerGetDatum(dtuple);
770+
}
771+
701772
/* ----------------------------------------------------------------
702773
*ExecEvalConst
703774
*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp