mirror of
https://github.com/postgres/postgres.git
synced 2025-04-24 10:47:04 +03:00
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.
This commit is contained in:
parent
07908c9c37
commit
d9cb48786e
@ -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 */
|
||||
|
@ -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:
|
||||
{
|
||||
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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user