aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/execUtils.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/execUtils.c')
-rw-r--r--src/backend/executor/execUtils.c110
1 files changed, 93 insertions, 17 deletions
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index 1718739fd6c..74567b04417 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.117 2004/12/31 21:59:45 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.118 2005/03/16 21:38:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -485,7 +485,7 @@ ExecGetResultType(PlanState *planstate)
{
TupleTableSlot *slot = planstate->ps_ResultTupleSlot;
- return slot->ttc_tupleDescriptor;
+ return slot->tts_tupleDescriptor;
}
/* ----------------
@@ -504,17 +504,99 @@ ExecBuildProjectionInfo(List *targetList,
{
ProjectionInfo *projInfo = makeNode(ProjectionInfo);
int len;
+ bool isVarList;
+ ListCell *tl;
len = ExecTargetListLength(targetList);
projInfo->pi_targetlist = targetList;
projInfo->pi_exprContext = econtext;
projInfo->pi_slot = slot;
- if (len > 0)
+
+ /*
+ * Determine whether the target list consists entirely of simple Var
+ * references (ie, references to non-system attributes). If so,
+ * we can use the simpler ExecVariableList instead of ExecTargetList.
+ */
+ isVarList = true;
+ foreach(tl, targetList)
+ {
+ GenericExprState *gstate = (GenericExprState *) lfirst(tl);
+ Var *variable = (Var *) gstate->arg->expr;
+
+ if (variable == NULL ||
+ !IsA(variable, Var) ||
+ variable->varattno <= 0)
+ {
+ isVarList = false;
+ break;
+ }
+ }
+ projInfo->pi_isVarList = isVarList;
+
+ if (isVarList)
+ {
+ int *varSlotOffsets;
+ int *varNumbers;
+ AttrNumber lastInnerVar = 0;
+ AttrNumber lastOuterVar = 0;
+ AttrNumber lastScanVar = 0;
+
+ projInfo->pi_itemIsDone = NULL; /* not needed */
+ projInfo->pi_varSlotOffsets = varSlotOffsets = (int *)
+ palloc0(len * sizeof(int));
+ projInfo->pi_varNumbers = varNumbers = (int *)
+ palloc0(len * sizeof(int));
+
+ /*
+ * Set up the data needed by ExecVariableList. The slots in which
+ * the variables can be found at runtime are denoted by the offsets
+ * of their slot pointers within the econtext. This rather grotty
+ * representation is needed because the caller may not have given
+ * us the real econtext yet (see hacks in nodeSubplan.c).
+ */
+ foreach(tl, targetList)
+ {
+ GenericExprState *gstate = (GenericExprState *) lfirst(tl);
+ Var *variable = (Var *) gstate->arg->expr;
+ AttrNumber attnum = variable->varattno;
+ TargetEntry *tle = (TargetEntry *) gstate->xprstate.expr;
+ AttrNumber resind = tle->resdom->resno - 1;
+
+ Assert(resind >= 0 && resind < len);
+ varNumbers[resind] = attnum;
+
+ switch (variable->varno)
+ {
+ case INNER:
+ varSlotOffsets[resind] = offsetof(ExprContext,
+ ecxt_innertuple);
+ lastInnerVar = Max(lastInnerVar, attnum);
+ break;
+
+ case OUTER:
+ varSlotOffsets[resind] = offsetof(ExprContext,
+ ecxt_outertuple);
+ lastOuterVar = Max(lastOuterVar, attnum);
+ break;
+
+ default:
+ varSlotOffsets[resind] = offsetof(ExprContext,
+ ecxt_scantuple);
+ lastScanVar = Max(lastScanVar, attnum);
+ break;
+ }
+ }
+ projInfo->pi_lastInnerVar = lastInnerVar;
+ projInfo->pi_lastOuterVar = lastOuterVar;
+ projInfo->pi_lastScanVar = lastScanVar;
+ }
+ else
{
- projInfo->pi_tupValues = (Datum *) palloc(len * sizeof(Datum));
- projInfo->pi_tupNulls = (char *) palloc(len * sizeof(char));
- projInfo->pi_itemIsDone = (ExprDoneCond *) palloc(len * sizeof(ExprDoneCond));
+ projInfo->pi_itemIsDone = (ExprDoneCond *)
+ palloc(len * sizeof(ExprDoneCond));
+ projInfo->pi_varSlotOffsets = NULL;
+ projInfo->pi_varNumbers = NULL;
}
return projInfo;
@@ -582,7 +664,7 @@ ExecGetScanType(ScanState *scanstate)
{
TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;
- return slot->ttc_tupleDescriptor;
+ return slot->tts_tupleDescriptor;
}
/* ----------------
@@ -772,20 +854,16 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
EState *estate,
bool is_vacuum)
{
- HeapTuple heapTuple;
ResultRelInfo *resultRelInfo;
int i;
int numIndices;
RelationPtr relationDescs;
Relation heapRelation;
- TupleDesc heapDescriptor;
IndexInfo **indexInfoArray;
ExprContext *econtext;
Datum datum[INDEX_MAX_KEYS];
char nullv[INDEX_MAX_KEYS];
- heapTuple = slot->val;
-
/*
* Get information from the result relation info structure.
*/
@@ -794,7 +872,6 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
relationDescs = resultRelInfo->ri_IndexRelationDescs;
indexInfoArray = resultRelInfo->ri_IndexRelationInfo;
heapRelation = resultRelInfo->ri_RelationDesc;
- heapDescriptor = RelationGetDescr(heapRelation);
/*
* We will use the EState's per-tuple context for evaluating
@@ -844,12 +921,11 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
/*
* FormIndexDatum fills in its datum and null parameters with
- * attribute information taken from the given heap tuple. It also
+ * attribute information taken from the given tuple. It also
* computes any expressions needed.
*/
FormIndexDatum(indexInfo,
- heapTuple,
- heapDescriptor,
+ slot,
estate,
datum,
nullv);
@@ -860,9 +936,9 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
* need to move dead tuples that have the same keys as live ones.
*/
result = index_insert(relationDescs[i], /* index relation */
- datum, /* array of heaptuple Datums */
+ datum, /* array of index Datums */
nullv, /* info on nulls */
- &(heapTuple->t_self), /* tid of heap tuple */
+ tupleid, /* tid of heap tuple */
heapRelation,
relationDescs[i]->rd_index->indisunique && !is_vacuum);