1
0
mirror of https://github.com/postgres/postgres.git synced 2025-08-11 04:22:52 +03:00

Back-patch fix for proper labeling of whole-row Datums generated from

subquery results.
This commit is contained in:
Tom Lane
2005-10-19 22:51:26 +00:00
parent 98658dd404
commit fd5efffc15
2 changed files with 85 additions and 32 deletions

View File

@@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/common/heaptuple.c,v 1.95 2004/12/31 21:59:07 pgsql Exp $ * $PostgreSQL: pgsql/src/backend/access/common/heaptuple.c,v 1.95.4.1 2005/10/19 22:51:26 tgl Exp $
* *
* NOTES * NOTES
* The old interface functions have been converted to macros * The old interface functions have been converted to macros
@@ -466,33 +466,6 @@ heap_getsysattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
case TableOidAttributeNumber: case TableOidAttributeNumber:
result = ObjectIdGetDatum(tup->t_tableOid); result = ObjectIdGetDatum(tup->t_tableOid);
break; break;
/*
* If the attribute number is 0, then we are supposed to
* return the entire tuple as a row-type Datum. (Using zero
* for this purpose is unclean since it risks confusion with
* "invalid attr" result codes, but it's not worth changing
* now.)
*
* We have to make a copy of the tuple so we can safely insert
* the Datum overhead fields, which are not set in on-disk
* tuples.
*/
case InvalidAttrNumber:
{
HeapTupleHeader dtup;
dtup = (HeapTupleHeader) palloc(tup->t_len);
memcpy((char *) dtup, (char *) tup->t_data, tup->t_len);
HeapTupleHeaderSetDatumLength(dtup, tup->t_len);
HeapTupleHeaderSetTypeId(dtup, tupleDesc->tdtypeid);
HeapTupleHeaderSetTypMod(dtup, tupleDesc->tdtypmod);
result = PointerGetDatum(dtup);
}
break;
default: default:
elog(ERROR, "invalid attnum: %d", attnum); elog(ERROR, "invalid attnum: %d", attnum);
result = 0; /* keep compiler quiet */ result = 0; /* keep compiler quiet */

View File

@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.171 2004/12/31 21:59:45 pgsql Exp $ * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.171.4.1 2005/10/19 22:51:26 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@@ -63,6 +63,8 @@ static Datum ExecEvalAggref(AggrefExprState *aggref,
bool *isNull, ExprDoneCond *isDone); bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalVar(ExprState *exprstate, ExprContext *econtext, static Datum ExecEvalVar(ExprState *exprstate, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone); bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalWholeRowVar(ExprState *exprstate, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalConst(ExprState *exprstate, ExprContext *econtext, static Datum ExecEvalConst(ExprState *exprstate, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone); bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalParam(ExprState *exprstate, ExprContext *econtext, static Datum ExecEvalParam(ExprState *exprstate, ExprContext *econtext,
@@ -527,6 +529,77 @@ ExecEvalVar(ExprState *exprstate, ExprContext *econtext,
return result; return result;
} }
/* ----------------------------------------------------------------
* ExecEvalWholeRowVar
*
* Returns a Datum for a whole-row variable.
*
* This could be folded into ExecEvalVar, but we make it a separate
* routine so as not to slow down ExecEvalVar with tests for this
* uncommon case.
* ----------------------------------------------------------------
*/
static Datum
ExecEvalWholeRowVar(ExprState *exprstate, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone)
{
Var *variable = (Var *) exprstate->expr;
TupleTableSlot *slot;
HeapTuple tuple;
TupleDesc tupleDesc;
HeapTupleHeader dtuple;
if (isDone)
*isDone = ExprSingleResult;
*isNull = false;
Assert(variable->varattno == InvalidAttrNumber);
/*
* Whole-row Vars can only appear at the level of a relation scan,
* never in a join.
*/
Assert(variable->varno != INNER);
Assert(variable->varno != OUTER);
slot = econtext->ecxt_scantuple;
tuple = slot->val;
tupleDesc = slot->ttc_tupleDescriptor;
/*
* We have to make a copy of the tuple so we can safely insert the
* Datum overhead fields, which are not set in on-disk tuples.
*/
dtuple = (HeapTupleHeader) palloc(tuple->t_len);
memcpy((char *) dtuple, (char *) tuple->t_data, tuple->t_len);
HeapTupleHeaderSetDatumLength(dtuple, tuple->t_len);
/*
* If the Var identifies a named composite type, label the tuple
* with that type; otherwise use what is in the tupleDesc.
*
* It's likely that the slot's tupleDesc is a record type; if so,
* make sure it's been "blessed", so that the Datum can be interpreted
* later.
*/
if (variable->vartype != RECORDOID)
{
HeapTupleHeaderSetTypeId(dtuple, variable->vartype);
HeapTupleHeaderSetTypMod(dtuple, variable->vartypmod);
}
else
{
if (tupleDesc->tdtypeid == RECORDOID &&
tupleDesc->tdtypmod < 0)
assign_record_type_typmod(tupleDesc);
HeapTupleHeaderSetTypeId(dtuple, tupleDesc->tdtypeid);
HeapTupleHeaderSetTypMod(dtuple, tupleDesc->tdtypmod);
}
return PointerGetDatum(dtuple);
}
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* ExecEvalConst * ExecEvalConst
* *
@@ -2830,8 +2903,15 @@ ExecInitExpr(Expr *node, PlanState *parent)
switch (nodeTag(node)) switch (nodeTag(node))
{ {
case T_Var: case T_Var:
{
Var *var = (Var *) node;
state = (ExprState *) makeNode(ExprState); state = (ExprState *) makeNode(ExprState);
if (var->varattno != InvalidAttrNumber)
state->evalfunc = ExecEvalVar; state->evalfunc = ExecEvalVar;
else
state->evalfunc = ExecEvalWholeRowVar;
}
break; break;
case T_Const: case T_Const:
state = (ExprState *) makeNode(ExprState); state = (ExprState *) makeNode(ExprState);
@@ -3170,7 +3250,7 @@ ExecInitExpr(Expr *node, PlanState *parent)
{ {
/* generic record, use runtime type assignment */ /* generic record, use runtime type assignment */
rstate->tupdesc = ExecTypeFromExprList(rowexpr->args); rstate->tupdesc = ExecTypeFromExprList(rowexpr->args);
rstate->tupdesc = BlessTupleDesc(rstate->tupdesc); BlessTupleDesc(rstate->tupdesc);
} }
else else
{ {