diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2005-10-19 22:51:26 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2005-10-19 22:51:26 +0000 |
commit | fd5efffc150233c6849bc29005291deacd7ccfee (patch) | |
tree | 7585ddc2c0ee49ac17f2527d06d5688eed3a240d /src | |
parent | 98658dd40432c3c12ace9e0fd16315b32bb478f5 (diff) | |
download | postgresql-fd5efffc150233c6849bc29005291deacd7ccfee.tar.gz postgresql-fd5efffc150233c6849bc29005291deacd7ccfee.zip |
Back-patch fix for proper labeling of whole-row Datums generated from
subquery results.
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/access/common/heaptuple.c | 29 | ||||
-rw-r--r-- | src/backend/executor/execQual.c | 88 |
2 files changed, 85 insertions, 32 deletions
diff --git a/src/backend/access/common/heaptuple.c b/src/backend/access/common/heaptuple.c index d60cd2a214a..9a34077543c 100644 --- a/src/backend/access/common/heaptuple.c +++ b/src/backend/access/common/heaptuple.c @@ -9,7 +9,7 @@ * * * 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 * 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: result = ObjectIdGetDatum(tup->t_tableOid); 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: elog(ERROR, "invalid attnum: %d", attnum); result = 0; /* keep compiler quiet */ diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c index 0199df0f719..5ff95e10872 100644 --- a/src/backend/executor/execQual.c +++ b/src/backend/executor/execQual.c @@ -8,7 +8,7 @@ * * * 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); static Datum ExecEvalVar(ExprState *exprstate, ExprContext *econtext, bool *isNull, ExprDoneCond *isDone); +static Datum ExecEvalWholeRowVar(ExprState *exprstate, ExprContext *econtext, + bool *isNull, ExprDoneCond *isDone); static Datum ExecEvalConst(ExprState *exprstate, ExprContext *econtext, bool *isNull, ExprDoneCond *isDone); static Datum ExecEvalParam(ExprState *exprstate, ExprContext *econtext, @@ -528,6 +530,77 @@ ExecEvalVar(ExprState *exprstate, ExprContext *econtext, } /* ---------------------------------------------------------------- + * 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 * * Returns the value of a constant. @@ -2830,8 +2903,15 @@ ExecInitExpr(Expr *node, PlanState *parent) switch (nodeTag(node)) { case T_Var: - state = (ExprState *) makeNode(ExprState); - state->evalfunc = ExecEvalVar; + { + Var *var = (Var *) node; + + state = (ExprState *) makeNode(ExprState); + if (var->varattno != InvalidAttrNumber) + state->evalfunc = ExecEvalVar; + else + state->evalfunc = ExecEvalWholeRowVar; + } break; case T_Const: state = (ExprState *) makeNode(ExprState); @@ -3170,7 +3250,7 @@ ExecInitExpr(Expr *node, PlanState *parent) { /* generic record, use runtime type assignment */ rstate->tupdesc = ExecTypeFromExprList(rowexpr->args); - rstate->tupdesc = BlessTupleDesc(rstate->tupdesc); + BlessTupleDesc(rstate->tupdesc); } else { |