From: Tom Lane Date: Wed, 19 Oct 2005 22:30:30 +0000 (+0000) Subject: Better solution to the problem of labeling whole-row Datums that are X-Git-Tag: REL8_1_0BETA4~23 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d9cb48786ee84c27dc20e3aed92bb1f1cadf95c3;p=postgresql Better solution to the problem of labeling whole-row Datums that are generated from subquery outputs: use the type info stored in the Var itself. To avoid making ExecEvalVar and slot_getattr more complex and slower, I split out the whole-row case into a separate ExecEval routine. --- diff --git a/src/backend/access/common/heaptuple.c b/src/backend/access/common/heaptuple.c index fc0a85d2dd..5551f744bb 100644 --- a/src/backend/access/common/heaptuple.c +++ b/src/backend/access/common/heaptuple.c @@ -16,7 +16,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/common/heaptuple.c,v 1.101 2005/10/19 18:18:32 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/common/heaptuple.c,v 1.102 2005/10/19 22:30:30 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -27,7 +27,6 @@ #include "access/tuptoaster.h" #include "catalog/pg_type.h" #include "executor/tuptable.h" -#include "utils/typcache.h" /* ---------------------------------------------------------------- @@ -595,38 +594,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. - * - * It's possible that the passed tupleDesc is a record type that - * hasn't been "blessed" yet, so cover that case. - */ - case InvalidAttrNumber: - { - HeapTupleHeader dtup; - - if (tupleDesc->tdtypeid == RECORDOID && - tupleDesc->tdtypmod < 0) - assign_record_type_typmod(tupleDesc); - - 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 5a27046906..4ee9a4ca62 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.182 2005/10/19 18:18:33 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.183 2005/10/19 22:30:30 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -64,6 +64,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, @@ -448,9 +450,9 @@ ExecEvalVar(ExprState *exprstate, ExprContext *econtext, /* * Get the slot and attribute number we want * - * The asserts check that references to system attributes only appear at the - * level of a relation scan; at higher levels, system attributes must be - * treated as ordinary variables (since we no longer have access to the + * The asserts check that references to system attributes only appear at + * the level of a relation scan; at higher levels, system attributes must + * be treated as ordinary variables (since we no longer have access to the * original tuple). */ attnum = variable->varattno; @@ -505,6 +507,77 @@ ExecEvalVar(ExprState *exprstate, ExprContext *econtext, return slot_getattr(slot, attnum, isNull); } +/* ---------------------------------------------------------------- + * 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->tts_tuple; + tupleDesc = slot->tts_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 * @@ -2841,8 +2914,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);